WMIDeviceQuery.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include "stdafx.h"
  2. #include "WMIDeviceQuery.h"
  3. #include <WinIoCtl.h>
  4. #include <comutil.h>
  5. #include <Wbemidl.h>
  6. #include <tchar.h>
  7. #include <strsafe.h>
  8. #include <algorithm>
  9. #include <atlconv.h>
  10. #include <ntddndis.h>
  11. #pragma comment (lib, "comsuppw.lib")
  12. #pragma comment (lib, "wbemuuid.lib")
  13. static const char *GetWQLQueryString(WMI_DEVICE_TYPE eDevType)
  14. {
  15. switch (eDevType)
  16. {
  17. case Processor:
  18. return "SELECT * FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)";
  19. break;
  20. case BaseBoard:
  21. return "SELECT * FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)";
  22. break;
  23. case DiskDrive:
  24. return "SELECT * FROM Win32_DiskDrive WHERE (SerialNumber IS NOT NULL) AND (MediaType LIKE 'Fixed hard disk%')";
  25. break;
  26. case NetworkAdapter:
  27. return "SELECT * FROM Win32_NetworkAdapter WHERE (PHYSICALADAPTER=TRUE) AND (MACAddress IS NOT NULL)";
  28. break;
  29. case BIOS:
  30. return "SELECT * FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)";
  31. break;
  32. case PatchList:
  33. return "SELECT * FROM Win32_QuickFixEngineering WHERE (HotFixID IS NOT NULL)";
  34. break;
  35. default:
  36. return NULL;
  37. break;
  38. }
  39. }
  40. static bool CheckHardDiskSerialNum(TCHAR *SerialNumber, int nBufLen)
  41. {
  42. int nLen = _tcslen(SerialNumber);
  43. if (nLen == 40) // InterfaceType = "IDE"
  44. {
  45. // 需要将16进制编码串转换为字符串
  46. TCHAR szBuf[32] = {};
  47. bool bSuc = true;
  48. for (int i = 0; i < 20; i++)
  49. {
  50. // 将16进制字符转换为高4位
  51. BYTE b;
  52. TCHAR ch = SerialNumber[i * 2];
  53. if ((ch >= '0') && (ch <= '9'))
  54. {
  55. b = ch - '0';
  56. }
  57. else if ((ch >= 'A') && (ch <= 'F'))
  58. {
  59. b = ch - 'A' + 10;
  60. }
  61. else if ((ch >= 'a') && (ch <= 'f'))
  62. {
  63. b = ch - 'a' + 10;
  64. }
  65. else
  66. {
  67. // 非法字符
  68. bSuc = false;
  69. break;
  70. }
  71. b <<= 4;
  72. // 将16进制字符转换为低4位
  73. ch = SerialNumber[i * 2 + 1];
  74. if ((ch >= '0') && (ch <= '9'))
  75. {
  76. b += ch - '0';
  77. }
  78. else if ((ch >= 'A') && (ch <= 'F'))
  79. {
  80. b += ch - 'A' + 10;
  81. }
  82. else if ((ch >= 'a') && (ch <= 'f'))
  83. {
  84. b += ch - 'a' + 10;
  85. }
  86. else
  87. {
  88. // 非法字符
  89. bSuc = false;
  90. break;
  91. }
  92. szBuf[i] = b;
  93. }
  94. if (bSuc)
  95. {
  96. // 转换成功
  97. szBuf[20] = 0;
  98. StringCchCopy(SerialNumber, nBufLen, szBuf);
  99. nBufLen = _tcslen(SerialNumber);
  100. }
  101. }
  102. // 每2个字符互换位置
  103. for (int i = 0; i < nBufLen; i += 2)
  104. {
  105. std::swap(SerialNumber[i], SerialNumber[i + 1]);
  106. }
  107. // 去掉空格
  108. std::remove(SerialNumber, SerialNumber + _tcslen(SerialNumber) + 1, ' ');
  109. return true;
  110. }
  111. static bool CheckWMIPropVal(WMI_DEVICE_TYPE eDevType, const char *szPropName, char *szPropVal, int nValSize)
  112. {
  113. BOOL bOK = true;
  114. if (eDevType == DiskDrive && stricmp(szPropName, "SerialNumber") == 0)
  115. bOK = CheckHardDiskSerialNum(szPropVal, nValSize);
  116. // 去掉空格
  117. std::remove(szPropVal, szPropVal + _tcslen(szPropVal) + 1, ' ');
  118. return bOK;
  119. }
  120. // 基于Windows Management Instrumentation(Windows管理规范)
  121. bool QueryWMIDevice(WMI_DEVICE_TYPE eDevType, const char *szPropName, char *pValBuf, int *pBufLen)
  122. {
  123. int nTotal = 0;
  124. // 初始化
  125. //HRESULT hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  126. HRESULT hResult = CoInitialize(NULL);
  127. if (FAILED(hResult))
  128. return false;
  129. // 设置COM的安全认证级别
  130. hResult = CoInitializeSecurity(
  131. NULL,
  132. -1,
  133. NULL,
  134. NULL,
  135. RPC_C_AUTHN_LEVEL_DEFAULT,
  136. RPC_C_IMP_LEVEL_IMPERSONATE,
  137. NULL,
  138. EOAC_NONE,
  139. NULL
  140. );
  141. if (FAILED(hResult) && RPC_E_TOO_LATE != hResult)
  142. {
  143. CoUninitialize();
  144. return false;
  145. }
  146. // 获得WMI连接COM接口
  147. IWbemLocator *pLoc = NULL;
  148. hResult = CoCreateInstance(
  149. CLSID_WbemLocator,
  150. NULL,
  151. CLSCTX_INPROC_SERVER,
  152. IID_IWbemLocator,
  153. reinterpret_cast<LPVOID*>(&pLoc)
  154. );
  155. if (FAILED(hResult))
  156. {
  157. CoUninitialize();
  158. return false;
  159. }
  160. // 通过连接接口连接WMI的内核对象名"ROOT//CIMV2"
  161. IWbemServices *pSvc = NULL;
  162. hResult = pLoc->ConnectServer(
  163. _bstr_t(L"ROOT\\CIMV2"),
  164. NULL,
  165. NULL,
  166. NULL,
  167. 0,
  168. NULL,
  169. NULL,
  170. &pSvc
  171. );
  172. if (FAILED(hResult))
  173. {
  174. pLoc->Release();
  175. CoUninitialize();
  176. return false;
  177. }
  178. // 设置请求代理的安全级别
  179. hResult = CoSetProxyBlanket(
  180. pSvc,
  181. RPC_C_AUTHN_WINNT,
  182. RPC_C_AUTHZ_NONE,
  183. NULL,
  184. RPC_C_AUTHN_LEVEL_CALL,
  185. RPC_C_IMP_LEVEL_IMPERSONATE,
  186. NULL,
  187. EOAC_NONE
  188. );
  189. if (FAILED(hResult))
  190. {
  191. pSvc->Release();
  192. pLoc->Release();
  193. CoUninitialize();
  194. return false;
  195. }
  196. // 通过请求代理来向WMI发送请求
  197. IEnumWbemClassObject *pEnumerator = NULL;
  198. hResult = pSvc->ExecQuery(
  199. bstr_t("WQL"),
  200. bstr_t(GetWQLQueryString(eDevType)),
  201. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  202. NULL,
  203. &pEnumerator
  204. );
  205. if (FAILED(hResult))
  206. {
  207. pSvc->Release();
  208. pLoc->Release();
  209. CoUninitialize();
  210. return false;
  211. }
  212. // 循环枚举所有的结果对象
  213. int nRetLen = 0;
  214. while (pEnumerator)
  215. {
  216. IWbemClassObject *pclsObj = NULL;
  217. ULONG uReturn = 0;
  218. pEnumerator->Next(
  219. WBEM_INFINITE,
  220. 1,
  221. &pclsObj,
  222. &uReturn
  223. );
  224. if (uReturn == 0)
  225. break;
  226. // 获取属性值
  227. VARIANT vtProperty;
  228. VariantInit(&vtProperty);
  229. USES_CONVERSION;
  230. pclsObj->Get(A2W(szPropName), 0, &vtProperty, NULL, NULL);
  231. pclsObj->Release();
  232. if (vtProperty.vt == VT_EMPTY || vtProperty.vt == VT_NULL)
  233. continue;
  234. char szTmp[256] = {};
  235. StringCchCopyA(szTmp, sizeof(szTmp)-1, W2A(vtProperty.bstrVal));
  236. VariantClear(&vtProperty);
  237. // 对属性值做进一步的处理
  238. if (CheckWMIPropVal(eDevType, szPropName, szTmp, 256))
  239. {
  240. if (strlen(szTmp) + nRetLen +1 >= *pBufLen)
  241. break;
  242. nTotal++;
  243. if (nRetLen > 0)
  244. {
  245. nRetLen++;
  246. strcat(pValBuf, ";");
  247. }
  248. strcat(pValBuf, szTmp);
  249. nRetLen += strlen(szTmp);
  250. }
  251. }
  252. // 释放资源
  253. pEnumerator->Release();
  254. pSvc->Release();
  255. pLoc->Release();
  256. CoUninitialize();
  257. return nTotal >0;
  258. }