如何根据驱动程序及其安装文件来访问该设备呢(Visual C++ or C++ Builder均可以)
2003-07-22 08:00
751 查看
First of all,我要讲一下Windows对每检测到一个新设备的处理过程:
1.首先Windows将各种设备分成不同的设备类,比如说USB Storage存储类设备,而这些类设备都有一个GUID,它们位于注册表中HKEY_LOCAL_MACHINE/ControlSet001/Control/Class下,在这个键下你看到的以128位长度结点名称为结点都是设备类。
2.当检测到一个新设备时,Windows OS就会到KEY_LOCAL_MACHINE/ControlSet001下去搜索,如果此类设备已经注册,那么就此子键下增加一个子键,这个子键的名称是顺序递增的,如果当前该类设备中最大子键名称为0005,那么新设备的就是0006,0000,0001等就是设备的序列号。如果发现这个设备没有注册,那么OS就会以该设备对应的驱动程序安装文件.inf中的ClassGuid为名称来创建一个键,并将此被检测到的设备的序列号为0,在该键下创建一个子键,并且命名为0000来存储该设备的相关信息,之所以命名为0000,因为该设备是该类设备的第一个。
3.有些设备,如我们常用的COM1,COM2,当我们要访问它时可以用CreateFile("COM1"。。。)就可以打开串口,这里的COM1,COM2是符号名,有些设备也用到了符号名,比如说有些USB设备虚拟成一个COM口,如COM3,COM4,COM5等,在程序中我们只需要对COM3,COM4,COM5进行访问,就相当对该设备进行访问。
在没有符号名的情况下,我们如何根据设备驱动程序以及设备安装文件.inf来对设备进行访问呢?我们可以这样:
1.首先,我们在这个设备的符号名中找到设备类的ClassGuid,这是一定可以找到的。
2.然后我们到HKEY_LOCAL_MACHINE/ControlSet001/Control/Class下去找这个设备类,在找到后,我们再找它的子键,找到该设备对应的序列号,如它到底是0000还是0001,在得到这两个数据即ClassGuid和设备序列号后,就好办了。
下面我写一段代码,用来访问我机器上的一USB设备,并在listbox中列出当前机器上此设备类下的所有设备。
extern "C"
{
#include "setupapi.h"
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
//First of all,I will enumurate all the devices under the specified deviceclass
HKEY m_hKey,m_hSubKey;
long m_lResult=0;//using for return value
int m_nKeyIndex=0,m_nValueIndex=0;
char cKeyName[255],cValue[255];
unsigned char pbData[255];
BOOL bOutter=TRUE,bInter=TRUE;
char *cRoot="SYSTEM//ControlSet001//Control//Class//{4D36E96D-E325-11CE-BFC1-08002BE10318}";
AnsiString m_sAttached("");
m_lResult=::RegOpenKeyEx(HKEY_LOCAL_MACHINE,cRoot,0,KEY_ALL_ACCESS,&m_hKey);
if(m_lResult!=ERROR_SUCCESS) return FALSE;
//Enum Keys
while(bOutter){
m_lResult=::RegEnumKey(m_hKey,m_nKeyIndex,cKeyName,255);
bInter=TRUE;
if(m_lResult!=ERROR_SUCCESS) bOutter=FALSE;
else{
m_lResult=::RegOpenKeyEx(m_hKey,cKeyName,0,KEY_ALL_ACCESS,&m_hSubKey);
if(m_lResult!=ERROR_SUCCESS){
::RegCloseKey(m_hKey);
return FALSE;}
while(bInter){
unsigned long m_nDataSize=255;
unsigned long m_nValueNameSize=255;
unsigned long m_nType;
m_lResult=::RegEnumValue(m_hSubKey,m_nValueIndex,cValue,&m_nValueNameSize,0,&m_nType,pbData,&m_nDataSize);
if(m_lResult!=ERROR_SUCCESS) bInter=FALSE;
else{
if(!strcmp(cValue,"AttachedTo")){
m_sAttached=(AnsiString)(char*)pbData;
}
if(!strcmp(cValue,"DriverDesc")){
m_lstDevice->Items->Add((AnsiString)(char*)pbData+" "+m_sAttached);
}
m_nValueIndex++;
}
}
m_nValueIndex=0;
m_nKeyIndex++;
}
}
::RegCloseKey(m_hKey);
::RegCloseKey(m_hSubKey);
file://Next Step,I will access one of the device.I know its device serialno:0001
DWORD ReqLength;
DWORD Flags=DIGCF_PRESENT|DIGCF_DEVICEINTERFACE;
GUID CardGuid={4D36E96D-E325-11CE-BFC1-08002BE10318};
HANDLE hCard=0;
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceDetailData;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
DeviceInterfaceData.cbSize=sizeof(SP_DEVICE_INTERFACE_DATA);
hCard=SetupDiGetClassDevs(&CardGuid,NULL,NULL,Flags);
if(hCard==INVALID_HANDLE_VALUE){
::MessageBox(0,"Invalid Parameters!","Error",MB_OK|MB_ICONERROR);
return;}
BOOL status=SetupDiEnumDeviceInterfaces(hCard,NULL,&CardGuid,Index,&DeviceInterfaceData,&ReqLength,
NULL);//Index即设备的序号,这里的Index为1.
if(!status){
::MessageBox(0,"Failed to enumurate the specified
device!","Error",MB_OK+MB_ICONERROR);
::CloseHandle(hCard);
return;}
SetupDiGetInterfaceDeviceDetail(hCard,&DeviceInterfaceData,NULL,0,&ReqLength,NULL);
DeviceDetailData=(PSP_INTERFACE_DEVICE_DETAIL_DATA)new char[ReqLength];
if(DeviceDetailData){
::MessageBox("ERROR NOT ENOUGH MEMORY!","Error",MB_OK+MB_ICONERROR);
::CloseHandle(hCard);
return;}
status=SetupDiGetInterfaceDeviceDetail(hCard,&DeviceInterfaceData,DeviceDetailData,ReqLength,&ReqLength,NULL);
if(!status){
::MessageBox(0,"Failed to get interface detailed data","Error",MB_OK+MB_ICONERROR);
delete DeviceDetailData;
DeviceDetailData=NULL;
return;}
ShowMessage(DeviceDetailData->DevicePath());//在这里得到DevicePath就像得到符号名一样,那么接着下来,你你就可以象对串口操作一样来写程序,即是说:
HANDLE hUSB=::CreateFile(DeviceDetailData.DevicePath(),..............);
file://ReadFile,WriteFile and so on.....
}
所有以file:为前缀的地方都是注释部分,特此声明,以免误解,这是CSDN文档编辑器自动加的。
因最近一直在忙于学习驱动开发,现正在用DriverStudio进行开发一个USB Modem的驱动程序,有一点学习心得,特此交流一下。
1.首先Windows将各种设备分成不同的设备类,比如说USB Storage存储类设备,而这些类设备都有一个GUID,它们位于注册表中HKEY_LOCAL_MACHINE/ControlSet001/Control/Class下,在这个键下你看到的以128位长度结点名称为结点都是设备类。
2.当检测到一个新设备时,Windows OS就会到KEY_LOCAL_MACHINE/ControlSet001下去搜索,如果此类设备已经注册,那么就此子键下增加一个子键,这个子键的名称是顺序递增的,如果当前该类设备中最大子键名称为0005,那么新设备的就是0006,0000,0001等就是设备的序列号。如果发现这个设备没有注册,那么OS就会以该设备对应的驱动程序安装文件.inf中的ClassGuid为名称来创建一个键,并将此被检测到的设备的序列号为0,在该键下创建一个子键,并且命名为0000来存储该设备的相关信息,之所以命名为0000,因为该设备是该类设备的第一个。
3.有些设备,如我们常用的COM1,COM2,当我们要访问它时可以用CreateFile("COM1"。。。)就可以打开串口,这里的COM1,COM2是符号名,有些设备也用到了符号名,比如说有些USB设备虚拟成一个COM口,如COM3,COM4,COM5等,在程序中我们只需要对COM3,COM4,COM5进行访问,就相当对该设备进行访问。
在没有符号名的情况下,我们如何根据设备驱动程序以及设备安装文件.inf来对设备进行访问呢?我们可以这样:
1.首先,我们在这个设备的符号名中找到设备类的ClassGuid,这是一定可以找到的。
2.然后我们到HKEY_LOCAL_MACHINE/ControlSet001/Control/Class下去找这个设备类,在找到后,我们再找它的子键,找到该设备对应的序列号,如它到底是0000还是0001,在得到这两个数据即ClassGuid和设备序列号后,就好办了。
下面我写一段代码,用来访问我机器上的一USB设备,并在listbox中列出当前机器上此设备类下的所有设备。
extern "C"
{
#include "setupapi.h"
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
//First of all,I will enumurate all the devices under the specified deviceclass
HKEY m_hKey,m_hSubKey;
long m_lResult=0;//using for return value
int m_nKeyIndex=0,m_nValueIndex=0;
char cKeyName[255],cValue[255];
unsigned char pbData[255];
BOOL bOutter=TRUE,bInter=TRUE;
char *cRoot="SYSTEM//ControlSet001//Control//Class//{4D36E96D-E325-11CE-BFC1-08002BE10318}";
AnsiString m_sAttached("");
m_lResult=::RegOpenKeyEx(HKEY_LOCAL_MACHINE,cRoot,0,KEY_ALL_ACCESS,&m_hKey);
if(m_lResult!=ERROR_SUCCESS) return FALSE;
//Enum Keys
while(bOutter){
m_lResult=::RegEnumKey(m_hKey,m_nKeyIndex,cKeyName,255);
bInter=TRUE;
if(m_lResult!=ERROR_SUCCESS) bOutter=FALSE;
else{
m_lResult=::RegOpenKeyEx(m_hKey,cKeyName,0,KEY_ALL_ACCESS,&m_hSubKey);
if(m_lResult!=ERROR_SUCCESS){
::RegCloseKey(m_hKey);
return FALSE;}
while(bInter){
unsigned long m_nDataSize=255;
unsigned long m_nValueNameSize=255;
unsigned long m_nType;
m_lResult=::RegEnumValue(m_hSubKey,m_nValueIndex,cValue,&m_nValueNameSize,0,&m_nType,pbData,&m_nDataSize);
if(m_lResult!=ERROR_SUCCESS) bInter=FALSE;
else{
if(!strcmp(cValue,"AttachedTo")){
m_sAttached=(AnsiString)(char*)pbData;
}
if(!strcmp(cValue,"DriverDesc")){
m_lstDevice->Items->Add((AnsiString)(char*)pbData+" "+m_sAttached);
}
m_nValueIndex++;
}
}
m_nValueIndex=0;
m_nKeyIndex++;
}
}
::RegCloseKey(m_hKey);
::RegCloseKey(m_hSubKey);
file://Next Step,I will access one of the device.I know its device serialno:0001
DWORD ReqLength;
DWORD Flags=DIGCF_PRESENT|DIGCF_DEVICEINTERFACE;
GUID CardGuid={4D36E96D-E325-11CE-BFC1-08002BE10318};
HANDLE hCard=0;
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceDetailData;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
DeviceInterfaceData.cbSize=sizeof(SP_DEVICE_INTERFACE_DATA);
hCard=SetupDiGetClassDevs(&CardGuid,NULL,NULL,Flags);
if(hCard==INVALID_HANDLE_VALUE){
::MessageBox(0,"Invalid Parameters!","Error",MB_OK|MB_ICONERROR);
return;}
BOOL status=SetupDiEnumDeviceInterfaces(hCard,NULL,&CardGuid,Index,&DeviceInterfaceData,&ReqLength,
NULL);//Index即设备的序号,这里的Index为1.
if(!status){
::MessageBox(0,"Failed to enumurate the specified
device!","Error",MB_OK+MB_ICONERROR);
::CloseHandle(hCard);
return;}
SetupDiGetInterfaceDeviceDetail(hCard,&DeviceInterfaceData,NULL,0,&ReqLength,NULL);
DeviceDetailData=(PSP_INTERFACE_DEVICE_DETAIL_DATA)new char[ReqLength];
if(DeviceDetailData){
::MessageBox("ERROR NOT ENOUGH MEMORY!","Error",MB_OK+MB_ICONERROR);
::CloseHandle(hCard);
return;}
status=SetupDiGetInterfaceDeviceDetail(hCard,&DeviceInterfaceData,DeviceDetailData,ReqLength,&ReqLength,NULL);
if(!status){
::MessageBox(0,"Failed to get interface detailed data","Error",MB_OK+MB_ICONERROR);
delete DeviceDetailData;
DeviceDetailData=NULL;
return;}
ShowMessage(DeviceDetailData->DevicePath());//在这里得到DevicePath就像得到符号名一样,那么接着下来,你你就可以象对串口操作一样来写程序,即是说:
HANDLE hUSB=::CreateFile(DeviceDetailData.DevicePath(),..............);
file://ReadFile,WriteFile and so on.....
}
所有以file:为前缀的地方都是注释部分,特此声明,以免误解,这是CSDN文档编辑器自动加的。
因最近一直在忙于学习驱动开发,现正在用DriverStudio进行开发一个USB Modem的驱动程序,有一点学习心得,特此交流一下。
相关文章推荐
- 如何根据驱动程序及其安装文件来访问该设备呢(Visual C++ or C++ Builder均可以) 选择自 kingcaiyao 的 Blog
- 如何根据驱动程序及其安装文件来访问该设备[转]
- 已经越狱的 iPhone、iPad 设备,当通过其自带的 safari 浏览器访问 ipa 应用下载网站时,利用 itms-services 协议,可以一键安装 ipa 文件的 iOS 应用
- 如何安装一个设备驱动程序[转]
- 安装VMware 提示windows无法访问指定设备、路径或文件
- 【Linux设备驱动程序(第三版)】----设备文件的访问控制:独享设备
- 如何从内核模式设备驱动程序中打开文件以及如何读取或写入文件
- 如何从内核模式设备驱动程序中打开一个文件以及如何读取或写入文件(来自微软官网)
- 如何在vmware虚拟机中安装Linux系统后安装各种设备驱动程序呢?
- win8中如何在设备管理器中卸载某一设备及其驱动程序
- Linux设备驱动程序学习(6)-高级字符驱动程序操作[(3)设备文件的访问控制]
- Visual Studio Installer打包后生成的安装文件每次执行都需要重新安装C++ 2010运行库(x86)的解决方案
- Android开发实践经验谈:如何让各式手机浏览器可以直接下载apk安装文件且实现自动安装APP
- FB Flash Builder 安装错误 ERROR: DW050: - Microsoft Visual C++ 2010 Redistributable Package (x86): Install failed
- 如何配置nginx,从而可以访问网站根目录的文件
- 安装VS2005 SP1出现这样问题“windows 无法访问指定设备、路径或文件。您可能没有合适的权限访问这个项目。”
- Linux设备驱动程序学习(6) -高级字符驱动程序操作[(3)设备文件的访问控制]
- 设备驱动程序安装的重要文件
- linux系统,如何查看进程访问的设备和文件
- 【转帖】如何从内核模式设备驱动程序中打开一个文件以及如何读取或写入文件