阅读:3916回复:15
通过Setupapi族函数,如何得到U盘的vid和pid
高人指点一二
|
|
最新喜欢:![]() |
沙发#
发布于:2005-01-15 22:57
do you want to get the VID/PID when the device is enumerating OR it is already enumerated?
|
|
板凳#
发布于:2005-01-16 12:46
这个简单啊
|
|
|
地板#
发布于:2005-01-16 22:19
在网上搜,有源码。我搜到过的
|
|
地下室#
发布于:2005-01-17 14:12
各位,详细说说好吗?有源码最好。
我就是想枚举所有的U盘,向获得他们的VID,PID,以及Handle。 我在网上搜过,没有找着合适的。 |
|
5楼#
发布于:2005-01-17 14:35
你是说USB设备的VID和PID吗?简单.
用BUSHOUND看枚举过程,在返回的STANDARD DEVICE DESCRIPTOR里包 含了该设备的VID和PID.分别是以0为基数的第8,9字节(VID)和第10, 11字节(PID). 不知我说的对不对. |
|
|
6楼#
发布于:2005-01-17 14:53
呵呵,我是要在程序里面读取。
|
|
7楼#
发布于:2005-01-17 15:33
贴一个自己写的:
// GetDevice.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdlib.h> #include <WINDOWS.H> #include <initguid.h> #include <SetupApi.h> //Project>Setting...>Link>Library>Add "SetupAPI.lib" #include "DeviceInterfaceClassGUID.h" int main(int argc, char* argv[]) { //下面三行输出版本信息,可以不要 printf("GetUSBDevice V3.0(简化版) By 王辉(tsingkong)@CAU 2004-11-08\n"); printf("Press ENTER to continue...\n"); getchar(); //得到InterfaceGUID的设备信息集合 HDEVINFO hDeviceInfo; //设备信息集合的指针 GUID InterfaceGUID; //需要访问的设备的GUID //DiskClassGuid是硬盘和U盘的GUID,如果是手机,需要修改 //朗科的32M U盘属于FloppyClassGuid InterfaceGUID=FloppyClassGuid; //调用SetupDiGetClassDevs得到设备信息集合 hDeviceInfo=SetupDiGetClassDevs(&InterfaceGUID,NULL,NULL,DIGCF_DEVICEINTERFACE|DIGCF_PRESENT); //如果没有得到说明硬件没有连接好,退出程序 if (hDeviceInfo == INVALID_HANDLE_VALUE) { printf("系统中没有这种设备!\n"); return false; } //得到设备信息集合完毕! int i=0; //得到设备信息集合中的第i+1个Interface的信息 while(1) { BOOL bRet; //保存函数的返回值 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; //保存Interface信息 DeviceInterfaceData.cbSize =sizeof(SP_DEVICE_INTERFACE_DATA); bRet=SetupDiEnumDeviceInterfaces(hDeviceInfo,NULL,&InterfaceGUID,i++,&DeviceInterfaceData); //如果bRet等于0,说明没有成功,释放资源,退出程序 if(!bRet) break; //下面需要得到Interface的详细信息 //先得到详细信息需要的内存大小------------------------------ DWORD RequiredSize; SetupDiGetDeviceInterfaceDetail(hDeviceInfo,&DeviceInterfaceData,NULL,0,&RequiredSize,NULL); //然后,就可以为详细信息分配内存了 PSP_INTERFACE_DEVICE_DETAIL_DATA pDeviceDetailData=NULL; pDeviceDetailData=(PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(RequiredSize); if(pDeviceDetailData==NULL) break; //可以得到Interface的详细信息了 DWORD predictLength=RequiredSize;; pDeviceDetailData->cbSize =sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); bRet=SetupDiGetDeviceInterfaceDetail(hDeviceInfo,&DeviceInterfaceData,pDeviceDetailData,predictLength,&RequiredSize,NULL); if(!bRet) break; //pDeviceDetailData->DevicePath保存着设备的路径名 //我们通过它把非USB的设备过滤掉,如果是手机,需要修改 if((strstr(pDeviceDetailData->DevicePath,"USB")==NULL)&&(strstr(pDeviceDetailData->DevicePath,"usb")==NULL)) continue; //可以打开设备了 char DevicePath[256]; //存储设备的路径名 strcpy(DevicePath,pDeviceDetailData->DevicePath ); strcat(DevicePath,"\\PIPE1"); HANDLE hUSBFile=NULL; hUSBFile=CreateFile(DevicePath,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); if(hUSBFile) printf("成功打开设备!\n"); else{ printf("打开设备失败!\n"); break; } //打开设备成功了,就可以读写了 //可以使用ReadFile,WriteFile,DeviceIoControl //如果是手机,需要修改 char buffer[1024]; unsigned long RealLength; //SetFilePointer(hUSBPipe,512*n,FILE_BEGIN); HANDLE savef=NULL; savef=CreateFile("C:\\Save.DAT",GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if(NULL==savef) { printf("Can't Open Save File!"); CloseHandle(hUSBFile); break; } while(ReadFile(hUSBFile,buffer,512,&RealLength,NULL)) { bRet=WriteFile(savef,buffer,512,&RealLength,NULL); break; } CloseHandle(savef); // ZeroMemory(buffer,512); // bRet=SetFilePointer(hUSBFile,0,0,FILE_BEGIN); // bRet=WriteFile(hUSBFile,buffer,512,&RealLength,NULL); //最后别忘了关闭设备 if(CloseHandle(hUSBFile)) printf("成功关闭设备!\n"); else printf("关闭设备失败!\n"); } //退出喽 //释放资源 SetupDiDestroyDeviceInfoList(hDeviceInfo); //回车退出 printf("Press ENTER to Exit!"); getchar(); return 0; } |
|
|
8楼#
发布于:2005-01-17 15:34
头文件:
DeviceInterfaceClassGUID.h //keyBoard DEFINE_GUID(GUID_CLASS_KEYBOARD, 0x884b96c3, 0x56ef, 0x11d1, 0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd); //Mouse DEFINE_GUID(GUID_CLASS_MOUSE, 0x378de44c, 0x56ef, 0x11d1, 0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd ); //Parallel DEFINE_GUID(GUID_PARALLEL_DEVICE, 0x97F76EF0, 0xF883, 0x11D0, 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x5C); DEFINE_GUID(GUID_PARCLASS_DEVICE, 0x811FC6A5, 0xF728, 0x11D0, 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75, 0x3E, 0xD1); //PCMCIA DEFINE_GUID(GUID_PCMCIA_INTERFACE_STANDARD, 0xbed5dadfL, 0x38fb, 0x11d1, 0x94, 0x62, 0x00, 0xc0, 0x4f, 0xb9, 0x60, 0xee); //SCSI DEFINE_GUID(ScsiRawInterfaceGuid, 0x53f56309L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(WmiScsiAddressGuid, 0x53f5630fL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); //Serial DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73); DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR, 0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18); //Storage DEFINE_GUID(DiskClassGuid, 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(CdRomClassGuid, 0x53f56308L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(PartitionClassGuid, 0x53f5630aL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(TapeClassGuid, 0x53f5630bL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(WriteOnceDiskClassGuid, 0x53f5630cL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(VolumeClassGuid, 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(MediumChangerClassGuid, 0x53f56310L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(FloppyClassGuid, 0x53f56311L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(CdChangerClassGuid, 0x53f56312L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); DEFINE_GUID(StoragePortClassGuid, 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); |
|
|
9楼#
发布于:2005-01-17 16:06
Thanks a lot to tsingkong!
有几个疑问: 第一:if((strstr(pDeviceDetailData->DevicePath,"USB")==NULL)&&(strstr(pDeviceDetailData->DevicePath,"usb")==NULL)) 这个判断是否准确? 第二:CreateFile调用为什么要使用strcpy(DevicePath,pDeviceDetailData->DevicePath ); strcat(DevicePath,"\PIPE1");,直接pDeviceDetailData->DevicePath不可以吗? 第三:你的代码没有获得vid和pid吧? |
|
10楼#
发布于:2005-01-17 16:21
第一:在现有的情况下可以认为是准确的,再过10年就不知道了:)
第二:我是仿照周立功的书上写的,实际上,直接DevicePath也可以,我记得我试过的。 第三:看下面的这个吧:// GetDevice.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include<iostream.h> #include <WINDOWS.H> #include <SetupApi.h> //Project>Setting...>Link>Library>Add "SetupAPI.lib" #define DeviceRegDataSize 256 #define PropertyNum 32 char RegDataDescription[PropertyNum][128]; void PrintGUID(GUID * guid) { printf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",guid->Data1 ,\ guid->Data2 ,guid->Data3 ,guid->Data4 [0],guid->Data4 [1],guid->Data4 [2],\ guid->Data4 [3],guid->Data4 [4],guid->Data4 [5],guid->Data4 [6],guid->Data4 [7]); } int main(int argc, char* argv[]) { HDEVINFO hDeviceInfo; SP_DEVINFO_DATA spDevInfoData; BOOL bRet; long loop; DWORD RequiredSize; DWORD RegDataType; BYTE DeviceRegData[DeviceRegDataSize]; printf("GetUSBDevice V1.0 By 王辉(tsingkong)@CAU 2004-11-04\n"); printf("Press ENTER to continue...\n"); getchar(); for(loop=0;loop<PropertyNum;loop++) strcpy(RegDataDescription[loop],"unused"); strncpy(RegDataDescription[SPDRP_DEVICEDESC],"DeviceDesc (R/W)",127); strncpy(RegDataDescription[SPDRP_HARDWAREID],"HardwareID (R/W)",127); strncpy(RegDataDescription[SPDRP_COMPATIBLEIDS],"CompatibleIDs (R/W)",127); strncpy(RegDataDescription[SPDRP_UNUSED0],"unused",127); strncpy(RegDataDescription[SPDRP_SERVICE],"Service (R/W)",127); strncpy(RegDataDescription[SPDRP_UNUSED1],"unused",127); strncpy(RegDataDescription[SPDRP_UNUSED2],"unused",127); strncpy(RegDataDescription[SPDRP_CLASS],"Class (R--tied to ClassGUID)",127); strncpy(RegDataDescription[SPDRP_CLASSGUID],"ClassGUID (R/W)",127); strncpy(RegDataDescription[SPDRP_DRIVER],"Driver (R/W)",127); strncpy(RegDataDescription[SPDRP_CONFIGFLAGS],"ConfigFlags (R/W)",127); strncpy(RegDataDescription[SPDRP_MFG],"Mfg (R/W)",127); strncpy(RegDataDescription[SPDRP_FRIENDLYNAME],"FriendlyName (R/W)",127); strncpy(RegDataDescription[SPDRP_LOCATION_INFORMATION],"LocationInformation (R/W)",127); strncpy(RegDataDescription[SPDRP_PHYSICAL_DEVICE_OBJECT_NAME],"PhysicalDeviceObjectName (R)",127); strncpy(RegDataDescription[SPDRP_CAPABILITIES],"Capabilities (R)",127); strncpy(RegDataDescription[SPDRP_UI_NUMBER],"UiNumber (R)",127); strncpy(RegDataDescription[SPDRP_UPPERFILTERS],"UpperFilters (R/W)",127); strncpy(RegDataDescription[SPDRP_LOWERFILTERS],"LowerFilters (R/W)",127); strncpy(RegDataDescription[SPDRP_BUSTYPEGUID],"BusTypeGUID (R)",127); strncpy(RegDataDescription[SPDRP_LEGACYBUSTYPE],"LegacyBusType (R)",127); strncpy(RegDataDescription[SPDRP_BUSNUMBER],"BusNumber (R)",127); strncpy(RegDataDescription[SPDRP_ENUMERATOR_NAME],"Enumerator Name (R)",127); strncpy(RegDataDescription[SPDRP_SECURITY],"Security (R/W, binary form)",127); strncpy(RegDataDescription[SPDRP_SECURITY_SDS],"Security (W, SDS form)",127); strncpy(RegDataDescription[SPDRP_DEVTYPE],"Device Type (R/W)",127); strncpy(RegDataDescription[SPDRP_EXCLUSIVE],"Device is exclusive-access (R/W)",127); strncpy(RegDataDescription[SPDRP_CHARACTERISTICS],"Device Characteristics (R/W)",127); strncpy(RegDataDescription[SPDRP_ADDRESS],"Device Address (R)",127); strncpy(RegDataDescription[SPDRP_UI_NUMBER_DESC_FORMAT],"UiNumberDescFormat (R/W)",127); strncpy(RegDataDescription[SPDRP_MAXIMUM_PROPERTY],"Upper bound on ordinals",127); hDeviceInfo=SetupDiGetClassDevs(NULL,"USB",NULL,DIGCF_ALLCLASSES|DIGCF_PRESENT); if (hDeviceInfo == INVALID_HANDLE_VALUE) { printf("访问系统硬件出错!"); return false; } spDevInfoData.cbSize =sizeof(SP_DEVINFO_DATA); for(loop=0;SetupDiEnumDeviceInfo(hDeviceInfo,loop,&spDevInfoData);loop++) { printf("第%d个USB设备:\n",loop+1); for(int i=0;i<PropertyNum;i++) { if(strcmpi("unused",RegDataDescription)==0) continue; memset(DeviceRegData,0,DeviceRegDataSize); RequiredSize=0; SetupDiGetDeviceRegistryProperty(hDeviceInfo,&spDevInfoData,\ i,&RegDataType,(PBYTE)DeviceRegData,DeviceRegDataSize,&RequiredSize); if(RequiredSize<=0) continue; printf("\t%s:",RegDataDescription); if((RegDataType==REG_SZ)||(RegDataType==REG_MULTI_SZ)||(RegDataType==REG_EXPAND_SZ)) printf("%s",DeviceRegData); else if(RegDataType==REG_DWORD) { printf("0x%X(%d)",((DWORD *)DeviceRegData)[0],((DWORD *)DeviceRegData)[0]); } else if(strstr(RegDataDescription,"BusTypeGUID")) { PrintGUID((GUID*)DeviceRegData); } else{ for(unsigned int j=0;j<RequiredSize;j++) printf("%02X",((PBYTE)DeviceRegData)[j]); } printf("\n"); } } printf("Total:%d\n",loop); bRet=SetupDiDestroyDeviceInfoList(hDeviceInfo); printf("Press ENTER to Exit!"); getchar(); return 0; } |
|
|
11楼#
发布于:2005-01-17 16:25
貌似通过SetupDiGetDeviceRegistryProperty得到设备信息的。
PID和VID都在注册表里面呢。 时间长了,很多东西都忘了。 不妥之处请莫见怪。 |
|
|
12楼#
发布于:2005-01-17 21:35
严重感谢!
已经放了一半的分了(50哦)。 再请教一下,第一个程序里面获得的读写handle怎么和第二个程序里面获得的vid、pid对应上?也就是说,在可能有多个U盘的情况下,如何确保获得的handle和vid都指向同一个U盘。 结构SP_DEVINFO_DATA里面的 DevInst 是啥意思?和handle类似的意思? |
|
13楼#
发布于:2005-01-17 22:16
关于SP_DEVINFO_DATA,你那里没有MSDN吗:)
关于如何对上的问题,我也有疑问。 我上面贴的两段程序,根据U盘的两种属性分别对其访问。 如果同时插上两个牌子的U盘肯定可以分别将Handle和vid,pid对应上。 如果是同一个牌子的,那就不行了,handle肯定不同,但是vid,pid极有可能相同。 |
|
|
14楼#
发布于:2005-01-18 08:23
其实,我也写过这样的程序.如果是同一牌子的两个U盘,它们的VID是相同的,同一系列的产品PID也相同,不同系列的产品PID就不同了.如果要区分的话,可以依据它们的Serial Number(序列号)来区分,这个东西是唯一标识一个设备的.
|
|
15楼#
发布于:2005-01-18 09:07
关于SP_DEVINFO_DATA,你那里没有MSDN吗:) 呵呵,关于如何对应上的问题我琢磨很久了。不知道具体怎么做,在这里也搜了很久了。 |
|