Util_GetSystemSpecs.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /************************************************************************************
  2. Filename : Util_GetSystemSpecs.cpp
  3. Content : This code needs to be shared by applications, but can't be in LibOVR.
  4. Define GET_SYSTEM_SPECS and include directly in a cpp file.
  5. Created : Feb 27, 2015
  6. Authors : Kevin Jenkins (moved from RiftConfigUtil)
  7. Copyright : Copyright 2015 Oculus, Inc. All Rights reserved.
  8. Use of this software is subject to the terms of the Oculus Inc license
  9. agreement provided at the time of installation or download, or which
  10. otherwise accompanies this software in either electronic or hard copy form.
  11. *************************************************************************************/
  12. #if defined(GET_SYSTEM_SPECS)
  13. #ifndef WCHAR_TO_OVR_STRING
  14. //Qt redefines wchar_t , but our String has an explicit constructor. Use this hack for desired behavior
  15. #define WCHAR_TO_OVR_STRING(wchar_array) String() + wchar_array
  16. #endif
  17. #include <QtCore/QMap>
  18. #include <QtCore/QStringList>
  19. #include "Util/Util_SystemInfo.h"
  20. #if defined(OVR_OS_WIN32)
  21. #define _WIN32_DCOM
  22. #include <comdef.h>
  23. #include <Wbemidl.h>
  24. # pragma comment(lib, "wbemuuid.lib")
  25. #include "DXGI.h"
  26. JSON* GetSystemSpecs()
  27. {
  28. JSON* specs = JSON::CreateObject();
  29. HRESULT hres;
  30. IWbemLocator *pLoc = NULL;
  31. hres = CoCreateInstance(
  32. CLSID_WbemLocator,
  33. 0,
  34. CLSCTX_INPROC_SERVER,
  35. IID_IWbemLocator, (LPVOID *)&pLoc);
  36. if (FAILED(hres))
  37. {
  38. return specs; // Program has failed.
  39. }
  40. IWbemServices *pSvc = NULL;
  41. // Connect to the root\cimv2 namespace with
  42. // the current user and obtain pointer pSvc
  43. // to make IWbemServices calls.
  44. hres = pLoc->ConnectServer(
  45. _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
  46. NULL, // User name. NULL = current user
  47. NULL, // User password. NULL = current
  48. 0, // Locale. NULL indicates current
  49. NULL, // Security flags.
  50. 0, // Authority (for example, Kerberos)
  51. 0, // Context object
  52. &pSvc // pointer to IWbemServices proxy
  53. );
  54. if (FAILED(hres))
  55. {
  56. pLoc->Release();
  57. return specs; // Program has failed.
  58. }
  59. hres = CoSetProxyBlanket(
  60. pSvc, // Indicates the proxy to set
  61. RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
  62. RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
  63. NULL, // Server principal name
  64. RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
  65. RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
  66. NULL, // client identity
  67. EOAC_NONE // proxy capabilities
  68. );
  69. if (FAILED(hres))
  70. {
  71. pSvc->Release();
  72. pLoc->Release();
  73. return specs; // Program has failed.
  74. }
  75. IEnumWbemClassObject* pEnumerator = NULL;
  76. hres = pSvc->ExecQuery(
  77. bstr_t("WQL"),
  78. bstr_t("SELECT Caption FROM Win32_OperatingSystem"),
  79. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  80. NULL,
  81. &pEnumerator);
  82. if (FAILED(hres))
  83. {
  84. pSvc->Release();
  85. pLoc->Release();
  86. return specs; // Program has failed.
  87. }
  88. IWbemClassObject *pclsObj;
  89. ULONG uReturn = 0;
  90. while (pEnumerator)
  91. {
  92. HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
  93. &pclsObj, &uReturn);
  94. if (0 == uReturn)
  95. {
  96. break;
  97. }
  98. VARIANT vtProp;
  99. // Get the value of the Name property
  100. hr = pclsObj->Get(L"Caption", 0, &vtProp, 0, 0);
  101. specs->AddStringItem("Operating System", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  102. VariantClear(&vtProp);
  103. pclsObj->Release();
  104. }
  105. pEnumerator = NULL;
  106. hres = pSvc->ExecQuery(
  107. bstr_t("WQL"),
  108. bstr_t("SELECT Name FROM Win32_processor"),
  109. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  110. NULL,
  111. &pEnumerator);
  112. if (FAILED(hres))
  113. {
  114. pSvc->Release();
  115. pLoc->Release();
  116. return specs; // Program has failed.
  117. }
  118. uReturn = 0;
  119. while (pEnumerator)
  120. {
  121. HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
  122. &pclsObj, &uReturn);
  123. if (0 == uReturn)
  124. {
  125. break;
  126. }
  127. VARIANT vtProp;
  128. // Get the value of the Name property
  129. hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
  130. specs->AddStringItem("Processor", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  131. VariantClear(&vtProp);
  132. pclsObj->Release();
  133. }
  134. pEnumerator = NULL;
  135. hres = pSvc->ExecQuery(
  136. bstr_t("WQL"),
  137. bstr_t("SELECT Name , AdapterRam, DriverVersion, VideoModeDescription FROM Win32_VideoController"),
  138. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  139. NULL,
  140. &pEnumerator);
  141. if (FAILED(hres))
  142. {
  143. pSvc->Release();
  144. pLoc->Release();
  145. return specs; // Program has failed.
  146. }
  147. JSON* graphicsadapters = JSON::CreateArray();
  148. uReturn = 0;
  149. while (pEnumerator)
  150. {
  151. JSON* graphicscard = JSON::CreateObject();
  152. HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
  153. &pclsObj, &uReturn);
  154. if (0 == uReturn)
  155. {
  156. break;
  157. }
  158. VARIANT vtProp;
  159. // Get the value of the Name property
  160. hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
  161. graphicscard->AddStringItem("Name", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  162. VariantClear(&vtProp);
  163. // Get the value of the Name property
  164. hr = pclsObj->Get(L"AdapterRam", 0, &vtProp, 0, 0);
  165. uint32_t capacity = vtProp.uintVal;
  166. graphicscard->AddNumberItem("Video Controller RAM (MB)", capacity / 1048576);
  167. VariantClear(&vtProp);
  168. //get driver version
  169. hr = pclsObj->Get(L"DriverVersion", 0, &vtProp, 0, 0);
  170. graphicscard->AddStringItem("Driver Version", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  171. //get resolution
  172. hr = pclsObj->Get(L"VideoModeDescription", 0, &vtProp, 0, 0);
  173. graphicscard->AddStringItem("Video Mode", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  174. VariantClear(&vtProp);
  175. pclsObj->Release();
  176. graphicsadapters->AddArrayElement(graphicscard);
  177. }
  178. specs->AddItem("Graphics Adapters", graphicsadapters);
  179. pEnumerator = NULL;
  180. hres = pSvc->ExecQuery(
  181. bstr_t("WQL"),
  182. bstr_t("SELECT Capacity FROM Win32_PhysicalMemory"),
  183. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  184. NULL,
  185. &pEnumerator);
  186. if (FAILED(hres))
  187. {
  188. pSvc->Release();
  189. pLoc->Release();
  190. return specs; // Program has failed.
  191. }
  192. uint64_t totalram = 0;
  193. uReturn = 0;
  194. while (pEnumerator)
  195. {
  196. HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
  197. &pclsObj, &uReturn);
  198. if (0 == uReturn)
  199. {
  200. break;
  201. }
  202. VARIANT vtProp;
  203. // Get the value of the Name property
  204. hr = pclsObj->Get(L"Capacity", 0, &vtProp, 0, 0);
  205. uint64_t capacity = QString::fromWCharArray(vtProp.bstrVal).toLongLong();
  206. totalram += capacity;
  207. VariantClear(&vtProp);
  208. pclsObj->Release();
  209. }
  210. specs->AddNumberItem("Total RAM (GB)", totalram / 1073741824.0);
  211. JSON* usbtree = JSON::CreateArray();
  212. QMap<QString, QStringList> antecedents;
  213. pEnumerator = NULL;
  214. hres = pSvc->ExecQuery(
  215. bstr_t("WQL"),
  216. bstr_t("SELECT Antecedent,Dependent FROM Win32_USBControllerDevice"),
  217. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  218. NULL,
  219. &pEnumerator);
  220. if (FAILED(hres))
  221. {
  222. pSvc->Release();
  223. pLoc->Release();
  224. return specs; // Program has failed.
  225. }
  226. VARIANT vtProp;
  227. while (pEnumerator)
  228. {
  229. HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
  230. &pclsObj, &uReturn);
  231. if (0 == uReturn)
  232. {
  233. break;
  234. }
  235. // Get the reference value of the Antecedent property. There is not a function to dereference the value.
  236. hr = pclsObj->Get(L"Antecedent", 0, &vtProp, 0, 0);
  237. BSTR name = vtProp.bstrVal;
  238. //sanitize the string input to just the output
  239. QString antecedent = QString::fromWCharArray(name).split("=")[1].replace("\"", "");
  240. VariantClear(&vtProp);
  241. // Get the reference value of the Dependent property. There is not a function to dereference the value.
  242. hr = pclsObj->Get(L"Dependent", 0, &vtProp, 0, 0);
  243. name = vtProp.bstrVal;
  244. //sanitize the string input to just the output
  245. QString dependent = QString::fromWCharArray(name).split("=")[1].replace("\"", "");
  246. antecedents[antecedent].append(dependent);
  247. VariantClear(&vtProp);
  248. }
  249. for (int ant = 0; ant < antecedents.size(); ant++)
  250. {
  251. QString antecedent_name = antecedents.keys()[ant];
  252. //get antecedent object in a new enumerator
  253. IEnumWbemClassObject* pEnumerator2 = NULL;
  254. IWbemClassObject *pclsObj2;
  255. hres = pSvc->ExecQuery(
  256. bstr_t("WQL"),
  257. bstr_t("SELECT Manufacturer, Name, DeviceID, Caption FROM WIN32_USBController where deviceid = '") + bstr_t(antecedent_name.toUtf8()) + bstr_t("'"),
  258. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  259. NULL,
  260. &pEnumerator2);
  261. if (FAILED(hres))
  262. {
  263. pSvc->Release();
  264. pLoc->Release();
  265. return specs; // Program has failed.
  266. }
  267. JSON* USBAntecedent = JSON::CreateObject();
  268. while (pEnumerator2)
  269. {
  270. HRESULT hr = pEnumerator2->Next(WBEM_INFINITE, 1,
  271. &pclsObj2, &uReturn);
  272. if (0 == uReturn)
  273. {
  274. break;
  275. }
  276. VARIANT vtProp;
  277. // Get the value of the Name property
  278. hr = pclsObj2->Get(L"Name", 0, &vtProp, 0, 0);
  279. USBAntecedent->AddStringItem("name", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  280. VariantClear(&vtProp);
  281. // Get the value of the DeviceID property
  282. hr = pclsObj2->Get(L"DeviceID", 0, &vtProp, 0, 0);
  283. USBAntecedent->AddStringItem("deviceid", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  284. VariantClear(&vtProp);
  285. // Get the value of the caption property
  286. hr = pclsObj2->Get(L"Caption", 0, &vtProp, 0, 0);
  287. USBAntecedent->AddStringItem("caption", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  288. VariantClear(&vtProp);
  289. // Get the value of the manufacturer property
  290. hr = pclsObj2->Get(L"Manufacturer", 0, &vtProp, 0, 0);
  291. USBAntecedent->AddStringItem("manufacturer", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  292. VariantClear(&vtProp);
  293. pclsObj2->Release();
  294. }
  295. JSON* devices = JSON::CreateArray();
  296. for (int dev = 0; dev < antecedents[antecedent_name].size(); ++dev)
  297. {
  298. //get antecedent object in a new enumerator
  299. pEnumerator2 = NULL;
  300. if (!pclsObj2) pclsObj2->Release();
  301. hres = pSvc->ExecQuery(
  302. bstr_t("WQL"),
  303. bstr_t("SELECT Manufacturer,Name FROM Win32_PnPEntity where DeviceID = '") + bstr_t(antecedents[antecedent_name][dev].toUtf8()) + bstr_t("'"),
  304. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  305. NULL,
  306. &pEnumerator2);
  307. if (FAILED(hres))
  308. {
  309. pSvc->Release();
  310. pLoc->Release();
  311. return specs; // Program has failed.
  312. }
  313. while (pEnumerator2)
  314. {
  315. HRESULT hr = pEnumerator2->Next(WBEM_INFINITE, 1,
  316. &pclsObj2, &uReturn);
  317. if (0 == uReturn)
  318. {
  319. break;
  320. }
  321. VARIANT vtProp;
  322. JSON* properties = JSON::CreateObject();
  323. // Get the value of the Manufacturer property
  324. hr = pclsObj2->Get(L"Manufacturer", 0, &vtProp, 0, 0);
  325. properties->AddStringItem("manufacturer", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  326. VariantClear(&vtProp);
  327. // Get the value of the Manufacturer property
  328. hr = pclsObj2->Get(L"Name", 0, &vtProp, 0, 0);
  329. properties->AddStringItem("name", WCHAR_TO_OVR_STRING(vtProp.bstrVal));
  330. VariantClear(&vtProp);
  331. pclsObj2->Release();
  332. devices->AddArrayElement(properties);
  333. }
  334. }
  335. USBAntecedent->AddItem("Devices", devices);
  336. usbtree->AddArrayElement(USBAntecedent);
  337. }
  338. specs->AddItem("USB Tree", usbtree);
  339. // Cleanup
  340. // ========
  341. pSvc->Release();
  342. pLoc->Release();
  343. pEnumerator->Release();
  344. if (!pclsObj) pclsObj->Release();
  345. return specs;
  346. }
  347. #endif
  348. #ifdef OVR_OS_MAC
  349. JSON* GetSystemSpecs()
  350. {
  351. return nullptr;
  352. }
  353. #endif
  354. #ifdef OVR_OS_LINUX
  355. JSON* GetSystemSpecs()
  356. {
  357. return nullptr;
  358. }
  359. #endif
  360. #endif // GET_SYSTEM_SPECS