WMIDeviceQuery.cpp 5.5 KB

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