WDK_DeviceQuery.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. #include "StdAfx.h"
  2. #include <winioctl.h>
  3. #include <strsafe.h>
  4. #include <setupapi.h>
  5. #include <ntddndis.h>
  6. #include <ntdddisk.h>
  7. #include <algorithm>
  8. #include "WDK_DeviceQuery.h"
  9. #ifdef __cplusplus
  10. extern "C"
  11. {
  12. #endif
  13. #include <hidsdi.h>
  14. #ifdef __cplusplus
  15. }
  16. #endif
  17. #pragma comment (lib, "Setupapi.lib")
  18. #pragma comment (lib, "hid.lib")
  19. const GUID GUID_QUERYSET[] = {
  20. // 人机交互设备VID-PID
  21. {0x4D1E55B2, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30},
  22. // 网卡原生MAC地址(包含USB网卡)
  23. {0xAD498944, 0x762F, 0x11D0, 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C},
  24. // 网卡原生MAC地址(剔除USB网卡)
  25. {0xAD498944, 0x762F, 0x11D0, 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C},
  26. // 硬盘序列号
  27. {0x53F56307, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B},
  28. };
  29. // 获取设备的VID-PID
  30. static BOOL WDK_GetVIDPID( TCHAR* DevicePath, TCHAR* szProperty, UINT uSize )
  31. {
  32. HANDLE hDeviceFile;
  33. BOOL isOK = FALSE;
  34. // 获取设备句柄
  35. hDeviceFile = CreateFile( DevicePath,
  36. 0,
  37. FILE_SHARE_READ | FILE_SHARE_WRITE,
  38. NULL,
  39. OPEN_EXISTING,
  40. 0,
  41. NULL);
  42. if( hDeviceFile != INVALID_HANDLE_VALUE )
  43. { // 获取设备属性
  44. HIDD_ATTRIBUTES Attributes;
  45. Attributes.Size = sizeof(HIDD_ATTRIBUTES);
  46. isOK = HidD_GetAttributes( hDeviceFile, &Attributes );
  47. if( isOK )
  48. {
  49. if( szProperty != NULL )
  50. {
  51. StringCchPrintf( szProperty, uSize, TEXT("%04X-%04X"), Attributes.VendorID, Attributes.ProductID );
  52. }
  53. }
  54. CloseHandle( hDeviceFile );
  55. }
  56. return isOK;
  57. }
  58. // 获取网卡原生MAC地址
  59. static BOOL WDK_GetMacAddress( TCHAR* DevicePath, TCHAR* szProperty, UINT uSize, BOOL isIncludeUSB )
  60. {
  61. HANDLE hDeviceFile;
  62. BOOL isOK = FALSE;
  63. // 剔除虚拟网卡
  64. if( _tcsnicmp( DevicePath + 4, TEXT("root"), 4 ) == 0 )
  65. {
  66. return FALSE;
  67. }
  68. if( !isIncludeUSB )
  69. { // 剔除USB网卡
  70. if( _tcsnicmp( DevicePath + 4, TEXT("usb"), 4 ) == 0 )
  71. {
  72. return FALSE;
  73. }
  74. }
  75. // 获取设备句柄
  76. hDeviceFile = CreateFile( DevicePath,
  77. 0,
  78. FILE_SHARE_READ | FILE_SHARE_WRITE,
  79. NULL,
  80. OPEN_EXISTING,
  81. 0,
  82. NULL);
  83. if( hDeviceFile != INVALID_HANDLE_VALUE )
  84. {
  85. ULONG dwID;
  86. BYTE ucData[8];
  87. DWORD dwByteRet;
  88. // 获取原生MAC地址
  89. dwID = OID_802_3_PERMANENT_ADDRESS;
  90. isOK = DeviceIoControl( hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL );
  91. if( isOK )
  92. {
  93. if( szProperty != NULL )
  94. { // 将字节数组转换成16进制字符串
  95. for( DWORD i = 0; i < dwByteRet; i++ )
  96. {
  97. StringCchPrintf( szProperty + (i << 1), uSize - (i << 1), TEXT("%02X"), ucData[i] );
  98. }
  99. }
  100. }
  101. CloseHandle( hDeviceFile );
  102. }
  103. return isOK;
  104. }
  105. // 获取硬盘序列号(需要系统管理员权限)
  106. static BOOL WDK_GetHarddiskSerialNumberWithAdminRights( TCHAR* DevicePath, TCHAR* szProperty, UINT uSize )
  107. {
  108. HANDLE hDeviceFile;
  109. BOOL isOK = FALSE;
  110. // 获取设备句柄
  111. hDeviceFile = CreateFile( DevicePath,
  112. GENERIC_READ | GENERIC_WRITE, // 注意:需要系统管理员权限才能执行读写操作
  113. FILE_SHARE_READ | FILE_SHARE_WRITE,
  114. NULL,
  115. OPEN_EXISTING,
  116. 0,
  117. NULL);
  118. if( hDeviceFile != INVALID_HANDLE_VALUE )
  119. {
  120. GETVERSIONINPARAMS VersionInParams;
  121. DWORD dwByteRet;
  122. // 获取硬盘属性
  123. isOK = DeviceIoControl( hDeviceFile, SMART_GET_VERSION, NULL, 0, &VersionInParams, sizeof(GETVERSIONINPARAMS), &dwByteRet, NULL );
  124. if( isOK )
  125. {
  126. isOK = FALSE;
  127. if( VersionInParams.fCapabilities & CAP_ATA_ID_CMD )
  128. {
  129. BYTE abSCIP[sizeof(SENDCMDINPARAMS) - 1] = {0};
  130. BYTE abSCOP[sizeof(SENDCMDOUTPARAMS) - 1 + 512] = {0};
  131. SENDCMDINPARAMS *scip = reinterpret_cast<SENDCMDINPARAMS*>(abSCIP);
  132. SENDCMDOUTPARAMS *scop = reinterpret_cast<SENDCMDOUTPARAMS*>(abSCOP);
  133. // 设置输入参数
  134. scip->irDriveRegs.bCommandReg = ID_CMD;
  135. // 设置输出参数
  136. scop->cBufferSize = 512;
  137. // 获取硬盘详细信息
  138. isOK = DeviceIoControl( hDeviceFile, SMART_RCV_DRIVE_DATA, scip, sizeof(abSCIP), scop, sizeof(abSCOP), &dwByteRet, NULL );
  139. if( isOK )
  140. {
  141. if( szProperty != NULL )
  142. { // 提取硬盘序列号
  143. for( UINT i = 0; i < 20; i += 2 )
  144. { // 颠倒高低位字节
  145. szProperty[i] = scop->bBuffer[i+21];
  146. szProperty[i + 1] = scop->bBuffer[i+20];
  147. }
  148. szProperty[20] = TEXT('\0');
  149. // 去掉空格
  150. std::remove( szProperty, szProperty + _tcslen(szProperty) + 1, L' ' );
  151. }
  152. }
  153. }
  154. }
  155. CloseHandle( hDeviceFile );
  156. }
  157. return isOK;
  158. }
  159. static BOOL WDK_GetProperty( TCHAR* DevicePath, INT iQueryType, TCHAR* szProperty, UINT uSize )
  160. {
  161. BOOL isOK = FALSE;
  162. switch( iQueryType )
  163. {
  164. case 0:
  165. // 获取设备的VID-PID
  166. isOK = WDK_GetVIDPID( DevicePath, szProperty, uSize );
  167. break;
  168. case 1: // 网卡原生MAC地址(包含USB网卡)
  169. isOK = WDK_GetMacAddress( DevicePath, szProperty, uSize, TRUE );
  170. break;
  171. case 2: // 网卡原生MAC地址(剔除USB网卡)
  172. isOK = WDK_GetMacAddress( DevicePath, szProperty, uSize, FALSE );
  173. break;
  174. case 3: // 硬盘序列号(需要系统管理员权限)
  175. isOK = WDK_GetHarddiskSerialNumberWithAdminRights( DevicePath, szProperty, uSize );
  176. break;
  177. default:
  178. break;
  179. }
  180. return isOK;
  181. }
  182. INT WDK_DeviceQuery_Property( INT iQueryType, T_DEVICE_PROPERTY *properties, INT iSize )
  183. {
  184. HDEVINFO hDevInfo;
  185. DWORD MemberIndex, RequiredSize;
  186. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  187. PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
  188. INT iTotal = 0;
  189. // 判断查询类型是否支持
  190. if( (iQueryType < 0) || (iQueryType >= sizeof(GUID_QUERYSET)/sizeof(GUID)) )
  191. {
  192. return -2; // 查询类型不支持
  193. }
  194. // 获取设备信息集
  195. hDevInfo = SetupDiGetClassDevs( GUID_QUERYSET + iQueryType, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );
  196. if( hDevInfo == INVALID_HANDLE_VALUE )
  197. {
  198. return -1;
  199. }
  200. // 枚举设备信息集中所有设备
  201. DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  202. for( MemberIndex = 0; ((properties == NULL) || (iTotal < iSize)); MemberIndex++ )
  203. { // 获取设备接口
  204. if( !SetupDiEnumDeviceInterfaces( hDevInfo, NULL, GUID_QUERYSET + iQueryType, MemberIndex, &DeviceInterfaceData ) )
  205. { // 设备枚举完毕
  206. break;
  207. }
  208. // 获取接收缓冲区大小,函数返回值为FALSE,GetLastError()=ERROR_INSUFFICIENT_BUFFER
  209. SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL );
  210. // 申请接收缓冲区
  211. DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc( RequiredSize );
  212. DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  213. // 获取设备细节信息
  214. if( SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL ) )
  215. {
  216. if( properties != NULL )
  217. {
  218. if( WDK_GetProperty( DeviceInterfaceDetailData->DevicePath, iQueryType, properties[iTotal].szProperty, PROPERTY_MAX_LEN ) )
  219. {
  220. if( iTotal > 0 )
  221. { // 剔除重复设备
  222. if( _tcscmp( properties[iTotal].szProperty, properties[iTotal - 1].szProperty ) != 0 )
  223. {
  224. iTotal++;
  225. }
  226. }
  227. else
  228. {
  229. iTotal++;
  230. }
  231. }
  232. }
  233. else
  234. {
  235. iTotal++;
  236. }
  237. }
  238. free( DeviceInterfaceDetailData );
  239. }
  240. SetupDiDestroyDeviceInfoList( hDevInfo );
  241. return iTotal;
  242. }
  243. INT WDK_DeviceQuery_VIDPID( const GUID* pGuid, HIDD_VIDPID* pVIDPID, INT iSize )
  244. {
  245. HDEVINFO hDevInfo;
  246. DWORD MemberIndex, RequiredSize;
  247. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  248. PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
  249. INT iTotal = 0;
  250. // 获取设备信息集
  251. hDevInfo = SetupDiGetClassDevs( pGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );
  252. if( hDevInfo == INVALID_HANDLE_VALUE )
  253. {
  254. return -1;
  255. }
  256. // 枚举设备信息集中所有设备
  257. DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  258. for( MemberIndex = 0; ((pVIDPID == NULL) || (iTotal < iSize)); MemberIndex++ )
  259. { // 获取设备接口
  260. if( !SetupDiEnumDeviceInterfaces( hDevInfo, NULL, pGuid, MemberIndex, &DeviceInterfaceData ) )
  261. { // 设备枚举完毕
  262. break;
  263. }
  264. // 获取接收缓冲区大小,函数返回值为FALSE,GetLastError()=ERROR_INSUFFICIENT_BUFFER
  265. SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL );
  266. // 申请接收缓冲区
  267. DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc( RequiredSize );
  268. DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  269. // 获取设备细节信息
  270. if( SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL ) )
  271. { // 获取设备句柄
  272. HANDLE hDeviceFile;
  273. hDeviceFile = CreateFile( DeviceInterfaceDetailData->DevicePath,
  274. 0,
  275. FILE_SHARE_READ | FILE_SHARE_WRITE,
  276. NULL,
  277. OPEN_EXISTING,
  278. 0,
  279. NULL);
  280. if( hDeviceFile != INVALID_HANDLE_VALUE )
  281. { // 获取设备属性
  282. HIDD_ATTRIBUTES Attributes;
  283. Attributes.Size = sizeof(HIDD_ATTRIBUTES);
  284. if( HidD_GetAttributes( hDeviceFile, &Attributes ) )
  285. {
  286. if( pVIDPID != NULL )
  287. {
  288. pVIDPID[iTotal].VendorID = Attributes.VendorID;
  289. pVIDPID[iTotal].ProductID = Attributes.ProductID;
  290. if( iTotal > 0 )
  291. { // 剔除重复设备
  292. if( (pVIDPID[iTotal].VendorID != pVIDPID[iTotal - 1].VendorID) || (pVIDPID[iTotal].ProductID != pVIDPID[iTotal - 1].ProductID) )
  293. {
  294. iTotal++;
  295. }
  296. }
  297. else
  298. {
  299. iTotal++;
  300. }
  301. }
  302. else
  303. {
  304. iTotal++;
  305. }
  306. }
  307. CloseHandle( hDeviceFile );
  308. }
  309. }
  310. free( DeviceInterfaceDetailData );
  311. }
  312. SetupDiDestroyDeviceInfoList( hDevInfo );
  313. return iTotal;
  314. }