Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1226 lines
40 KiB

  1. #include "dfcm.h"
  2. #include <stdio.h>
  3. #include <winuser.h>
  4. #include <tchar.h>
  5. #include "cfgmgr32.h"
  6. #include "drvfull.h"
  7. #include "dfhlprs.h"
  8. #include "setupapi.h"
  9. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  10. // 100 interface max
  11. static GUID rgguidInterface[100];
  12. static DWORD cguidInterface = 0;
  13. static GUID g_guidVolume =
  14. {0x53f5630d, 0xb6bf, 0x11d0,
  15. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  16. static GUID g_guidUSB =
  17. {0x36fc9e60, 0xc465, 0x11cf,
  18. {0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
  19. static GUID g_guidDiskDrive =
  20. {0x4d36e967, 0xe325, 0x11ce,
  21. {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
  22. static GUID g_guidDiskDriveIntf =
  23. {0x53f56307L, 0xb6bf, 0x11d0,
  24. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  25. struct DevInterface
  26. {
  27. LPTSTR pszName;
  28. GUID guid;
  29. };
  30. // see HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses for more
  31. static DevInterface rgDevInterface[] =
  32. {
  33. TEXT("DiskClassGuid"), { 0x53f56307L, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  34. TEXT("CdRomClassGuid"), { 0x53f56308L, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  35. TEXT("PartitionClassGuid"), { 0x53f5630aL, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  36. TEXT("TapeClassGuid"), { 0x53f5630bL, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  37. TEXT("WriteOnceDiskClassGuid"), { 0x53f5630cL, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  38. TEXT("VolumeClassGuid"), { 0x53f5630dL, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  39. TEXT("MediumChangerClassGuid"), { 0x53f56310L, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  40. TEXT("FloppyClassGuid"), { 0x53f56311L, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  41. TEXT("CdChangerClassGuid"), { 0x53f56312L, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  42. TEXT("StoragePortClassGuid"), { 0x2accfe60L, 0xc130, 0x11d2, { 0xb0, 0x82, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b }},
  43. TEXT("GUID_CLASS_COMPORT"), { 0x86e0d1e0L, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73 }},
  44. TEXT("GUID_SERENUM_BUS_ENUMERATOR"), {0x4D36E978L, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 }},
  45. };
  46. static DWORD g_dwLevel = 0;
  47. BOOL _HexStringToDword(LPCWSTR* ppsz, DWORD* lpValue, int cDigits,
  48. WCHAR chDelim)
  49. {
  50. LPCWSTR psz = *ppsz;
  51. DWORD Value = 0;
  52. BOOL fRet = TRUE;
  53. for (int ich = 0; ich < cDigits; ich++)
  54. {
  55. WCHAR ch = psz[ich];
  56. if ((ch >= TEXT('0')) && (ch <= TEXT('9')))
  57. {
  58. Value = (Value << 4) + ch - TEXT('0');
  59. }
  60. else
  61. {
  62. if (((ch |= (TEXT('a')-TEXT('A'))) >= TEXT('a')) &&
  63. ((ch |= (TEXT('a')-TEXT('A'))) <= TEXT('f')))
  64. {
  65. Value = (Value << 4) + ch - TEXT('a') + 10;
  66. }
  67. else
  68. {
  69. return(FALSE);
  70. }
  71. }
  72. }
  73. if (chDelim)
  74. {
  75. fRet = (psz[ich++] == chDelim);
  76. }
  77. *lpValue = Value;
  78. *ppsz = psz+ich;
  79. return fRet;
  80. }
  81. BOOL StringToGUID(LPCWSTR psz, GUID *pguid)
  82. {
  83. DWORD dw;
  84. if (*psz++ != TEXT('{') /*}*/ )
  85. return FALSE;
  86. if (!_HexStringToDword(&psz, &pguid->Data1, sizeof(DWORD)*2, TEXT('-')))
  87. return FALSE;
  88. if (!_HexStringToDword(&psz, &dw, sizeof(WORD)*2, TEXT('-')))
  89. return FALSE;
  90. pguid->Data2 = (WORD)dw;
  91. if (!_HexStringToDword(&psz, &dw, sizeof(WORD)*2, TEXT('-')))
  92. return FALSE;
  93. pguid->Data3 = (WORD)dw;
  94. if (!_HexStringToDword(&psz, &dw, sizeof(BYTE)*2, 0))
  95. return FALSE;
  96. pguid->Data4[0] = (BYTE)dw;
  97. if (!_HexStringToDword(&psz, &dw, sizeof(BYTE)*2, TEXT('-')))
  98. return FALSE;
  99. pguid->Data4[1] = (BYTE)dw;
  100. if (!_HexStringToDword(&psz, &dw, sizeof(BYTE)*2, 0))
  101. return FALSE;
  102. pguid->Data4[2] = (BYTE)dw;
  103. if (!_HexStringToDword(&psz, &dw, sizeof(BYTE)*2, 0))
  104. return FALSE;
  105. pguid->Data4[3] = (BYTE)dw;
  106. if (!_HexStringToDword(&psz, &dw, sizeof(BYTE)*2, 0))
  107. return FALSE;
  108. pguid->Data4[4] = (BYTE)dw;
  109. if (!_HexStringToDword(&psz, &dw, sizeof(BYTE)*2, 0))
  110. return FALSE;
  111. pguid->Data4[5] = (BYTE)dw;
  112. if (!_HexStringToDword(&psz, &dw, sizeof(BYTE)*2, 0))
  113. return FALSE;
  114. pguid->Data4[6] = (BYTE)dw;
  115. if (!_HexStringToDword(&psz, &dw, sizeof(BYTE)*2, /*(*/ TEXT('}')))
  116. return FALSE;
  117. pguid->Data4[7] = (BYTE)dw;
  118. return TRUE;
  119. }
  120. _sFLAG_DESCR _DevCapFD[] =
  121. {
  122. FLAG_DESCR(CM_DEVCAP_LOCKSUPPORTED),
  123. FLAG_DESCR(CM_DEVCAP_EJECTSUPPORTED),
  124. FLAG_DESCR(CM_DEVCAP_REMOVABLE),
  125. FLAG_DESCR(CM_DEVCAP_DOCKDEVICE),
  126. FLAG_DESCR(CM_DEVCAP_UNIQUEID),
  127. FLAG_DESCR(CM_DEVCAP_SILENTINSTALL),
  128. FLAG_DESCR(CM_DEVCAP_RAWDEVICEOK),
  129. FLAG_DESCR(CM_DEVCAP_SURPRISEREMOVALOK),
  130. FLAG_DESCR(CM_DEVCAP_HARDWAREDISABLED),
  131. FLAG_DESCR(CM_DEVCAP_NONDYNAMIC),
  132. };
  133. int _PrintDeviceInfo(DEVINST devinst, HMACHINE hMachine, DWORD dwFlags[],
  134. DWORD cchIndent)
  135. {
  136. // MAX_DEVICE_ID_LEN -> CM_Get_Device_ID_Size_Ex
  137. TCHAR szDeviceID[MAX_DEVICE_ID_LEN];
  138. LPTSTR pszDevIntf;
  139. int i = 0;
  140. CONFIGRET cr = CM_Get_Device_ID_Ex(devinst, szDeviceID,
  141. ARRAYSIZE(szDeviceID), 0, NULL); // hMachine?
  142. if (CR_SUCCESS == cr)
  143. {
  144. TCHAR szText[1024];
  145. DWORD cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  146. GUID guid;
  147. DWORD cbguid = sizeof(guid);
  148. i += _PrintIndent(cchIndent);
  149. i += _tprintf(TEXT("+ (%d) '%s'\n"), g_dwLevel, szDeviceID);
  150. cr = CM_Get_DevNode_Registry_Property_Ex(devinst, CM_DRP_FRIENDLYNAME,
  151. NULL, szText, &cbText, 0, hMachine);
  152. if (CR_SUCCESS == cr)
  153. {
  154. i += _PrintIndent(cchIndent + 5);
  155. i += _tprintf(TEXT("('%s')\n"), szText);
  156. }
  157. cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  158. cr = CM_Get_DevNode_Registry_Property_Ex(devinst, CM_DRP_DEVICEDESC,
  159. NULL, szText, &cbText, 0, hMachine);
  160. if (CR_SUCCESS == cr)
  161. {
  162. i += _PrintIndent(cchIndent + 5);
  163. i += _tprintf(TEXT("<'%s'>\n"), szText);
  164. }
  165. if (_IsFlagSet(MOD_FULLREPORT3, dwFlags))
  166. {
  167. //
  168. //regkeys
  169. {
  170. /*
  171. CM_REGISTRY_HARDWARE (0x00000000)
  172. Open a key for storing driver-independent information
  173. relating to the device instance. On Windows NT, the
  174. full path to such a storage key is of the form:
  175. HKLM\System\CurrentControlSet\Enum\<enumerator>\
  176. <DeviceID>\<InstanceID>\Device Parameters
  177. CM_REGISTRY_SOFTWARE (0x00000001)
  178. Open a key for storing driver-specific information
  179. relating to the device instance. On Windows NT, the
  180. full path to such a storage key is of the form:
  181. HKLM\System\CurrentControlSet\Control\Class\
  182. <DevNodeClass>\<ClassInstanceOrdinal>
  183. CM_REGISTRY_USER (0x00000100)
  184. Open a key under HKEY_CURRENT_USER instead of
  185. HKEY_LOCAL_MACHINE. This flag may not be used with
  186. CM_REGISTRY_CONFIG. There is no analagous kernel-mode
  187. API on NT to get a per-user device configuration
  188. storage, since this concept does not apply to device
  189. drivers (no user may be logged on, etc). However,
  190. this flag is provided for consistency with Win95, and
  191. because it is foreseeable that it could be useful to
  192. Win32 services that interact with Plug-and-Play model.
  193. CM_REGISTRY_CONFIG (0x00000200)
  194. Open the key under a hardware profile branch instead
  195. of HKEY_LOCAL_MACHINE. If this flag is specified,
  196. then ulHardwareProfile supplies the handle of the
  197. hardware profile to be used. This flag may not be
  198. used with CM_REGISTRY_USER.
  199. */
  200. {
  201. HKEY hkeyDevInst;
  202. cr = CM_Open_DevNode_Key(devinst, MAXIMUM_ALLOWED,
  203. 0, RegDisposition_OpenExisting,
  204. &hkeyDevInst, CM_REGISTRY_SOFTWARE);
  205. if (CR_SUCCESS == cr)
  206. {
  207. DWORD dwEnum = 0;
  208. WCHAR szKeyName[256];
  209. DWORD cchKeyName = ARRAYSIZE(szKeyName);
  210. while (ERROR_SUCCESS == RegEnumKeyEx(
  211. hkeyDevInst, dwEnum, szKeyName,
  212. &cchKeyName, NULL, NULL,
  213. NULL, NULL))
  214. {
  215. cchKeyName = ARRAYSIZE(szKeyName);
  216. ++dwEnum;
  217. _tprintf(TEXT("Dev Inst Key[%02d]: %s\n"),
  218. dwEnum, szKeyName);
  219. }
  220. if (!dwEnum)
  221. {
  222. _tprintf(TEXT("Dev Inst: no subkey\n"));
  223. }
  224. RegCloseKey(hkeyDevInst);
  225. }
  226. else
  227. {
  228. _tprintf(TEXT("Failed to open Dev Inst key\n"));
  229. }
  230. }
  231. {
  232. }
  233. }
  234. //
  235. cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  236. cr = CM_Get_DevNode_Registry_Property_Ex(devinst, CM_DRP_HARDWAREID,
  237. NULL, szText, &cbText, 0, hMachine);
  238. if (CR_SUCCESS == cr)
  239. {
  240. for (LPTSTR psz = szText; *psz; psz += lstrlen(psz) + 1)
  241. {
  242. i += _PrintIndent(cchIndent + 5);
  243. i += _tprintf(TEXT("~'%s'~\n"), psz);
  244. }
  245. }
  246. cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  247. cr = CM_Get_DevNode_Registry_Property_Ex(devinst, CM_DRP_COMPATIBLEIDS,
  248. NULL, szText, &cbText, 0, hMachine);
  249. if (CR_SUCCESS == cr)
  250. {
  251. for (LPTSTR psz = szText; *psz; psz += lstrlen(psz) + 1)
  252. {
  253. i += _PrintIndent(cchIndent + 5);
  254. i += _tprintf(TEXT("::'%s'::\n"), psz);
  255. }
  256. }
  257. cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  258. cr = CM_Get_DevNode_Registry_Property_Ex(devinst,
  259. CM_DRP_LOCATION_INFORMATION,
  260. NULL, szText, &cbText, 0, hMachine);
  261. if (CR_SUCCESS == cr)
  262. {
  263. i += _PrintIndent(cchIndent + 5);
  264. i += _tprintf(TEXT(">'%s'<\n"), szText);
  265. }
  266. DWORD dwAddress;
  267. DWORD cbAddress = sizeof(dwAddress);
  268. cr = CM_Get_DevNode_Registry_Property_Ex(devinst,
  269. CM_DRP_ADDRESS,
  270. NULL, &dwAddress, &cbAddress, 0, hMachine);
  271. if (CR_SUCCESS == cr)
  272. {
  273. i += _PrintIndent(cchIndent + 5);
  274. i += _tprintf(TEXT("^'%d'^\n"), dwAddress);
  275. }
  276. DWORD dwCap;
  277. DWORD cbCap = sizeof(dwCap);
  278. cr = CM_Get_DevNode_Registry_Property_Ex(devinst,
  279. CM_DRP_CAPABILITIES,
  280. NULL, &dwCap, &cbCap, 0, hMachine);
  281. if (CR_SUCCESS == cr)
  282. {
  283. i += _PrintFlag(dwCap, _DevCapFD, ARRAYSIZE(_DevCapFD),
  284. cchIndent + 7, TRUE, TRUE, FALSE, TRUE);
  285. i+= _PrintCR();
  286. }
  287. cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  288. cr = CM_Get_DevNode_Registry_Property_Ex(devinst,
  289. CM_DRP_DRIVER, NULL, szText, &cbText, 0, hMachine);
  290. if (CR_SUCCESS == cr)
  291. {
  292. i += _PrintIndent(cchIndent + 5);
  293. i += _tprintf(TEXT(">>'%s'<<\n"), szText);
  294. }
  295. cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  296. cr = CM_Get_DevNode_Registry_Property_Ex(devinst,
  297. CM_DRP_ENUMERATOR_NAME, NULL, szText, &cbText, 0, hMachine);
  298. if (CR_SUCCESS == cr)
  299. {
  300. i += _PrintIndent(cchIndent + 5);
  301. i += _tprintf(TEXT("!'%s'!\n"), szText);
  302. }
  303. cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  304. cr = CM_Get_DevNode_Registry_Property_Ex(devinst,
  305. CM_DRP_UI_NUMBER,
  306. NULL, szText, &cbText, 0, hMachine);
  307. if (CR_SUCCESS == cr)
  308. {
  309. /* cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  310. cr = CM_Get_DevNode_Registry_Property_Ex(devinst,
  311. CM_DRP_UI_NUMBER_DESC_FORMAT,
  312. NULL, szText, &cbText, 0, hMachine);
  313. if (CR_SUCCESS == cr)
  314. {
  315. i += _PrintIndent(cchIndent + 5);
  316. i += _tprintf(TEXT("$'%s'$\n"), szText);
  317. }*/
  318. if ((TEXT('P') == szDeviceID[0]) && (TEXT('C') == szDeviceID[1]) &&
  319. (TEXT('I') == szDeviceID[2]) && (TEXT('\\') == szDeviceID[3]))
  320. {
  321. i += _PrintIndent(cchIndent + 5);
  322. i += _tprintf(TEXT("#PCI Slot: %d#\n"), (DWORD)*((DWORD*)szText));
  323. }
  324. }
  325. for (DWORD dwIntf = 0; dwIntf < ARRAYSIZE(rgDevInterface); ++dwIntf)
  326. {
  327. ULONG ulSize;
  328. cr = CM_Get_Device_Interface_List_Size(&ulSize,
  329. &(rgDevInterface[dwIntf].guid), szDeviceID, 0);
  330. if ((CR_SUCCESS == cr) && (ulSize > 1))
  331. {
  332. pszDevIntf = (LPTSTR)LocalAlloc(LPTR,
  333. ulSize * sizeof(TCHAR));
  334. if (pszDevIntf)
  335. {
  336. // *sizeof(TCHAR) ?
  337. cr = CM_Get_Device_Interface_List(&(rgDevInterface[dwIntf].guid),
  338. szDeviceID, pszDevIntf, ulSize, 0); //CM_GET_DEVICE_INTERFACE_LIST_PRESENT
  339. if (CR_SUCCESS == cr)
  340. {
  341. for (LPTSTR psz = pszDevIntf; *psz;
  342. psz += lstrlen(psz) + 1)
  343. {
  344. i += _PrintIndent(cchIndent + 5);
  345. i += _tprintf(TEXT("<>'%s'<> (%s)\n"), psz,
  346. rgDevInterface[dwIntf].pszName);
  347. }
  348. }
  349. LocalFree(pszDevIntf);
  350. }
  351. }
  352. }
  353. }
  354. cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  355. cr = CM_Get_DevNode_Registry_Property_Ex(devinst, CM_DRP_CLASSGUID,
  356. NULL, szText, &cbText, 0, hMachine);
  357. if (CR_SUCCESS == cr)
  358. {
  359. StringToGUID(szText, &guid);
  360. cbText = ARRAYSIZE(szText) * sizeof(TCHAR);
  361. cr = CM_Get_Class_Name_Ex(&guid, szText, &cbText, 0, hMachine);
  362. if (CR_SUCCESS == cr)
  363. {
  364. i += _PrintIndent(cchIndent + 5);
  365. i += _tprintf(TEXT("{'%s'}\n"), szText);
  366. }
  367. }
  368. {
  369. ULONG ulSize;
  370. cr = CM_Get_Device_Interface_List_Size(&ulSize, &g_guidVolume,
  371. szDeviceID, 0);
  372. if ((CR_SUCCESS == cr) && (ulSize > 1))
  373. {
  374. pszDevIntf = (LPTSTR)LocalAlloc(LPTR,
  375. ulSize * sizeof(TCHAR));
  376. if (pszDevIntf)
  377. {
  378. // *sizeof(TCHAR) ?
  379. cr = CM_Get_Device_Interface_List(&g_guidVolume,
  380. szDeviceID, pszDevIntf, ulSize, 0); //CM_GET_DEVICE_INTERFACE_LIST_PRESENT
  381. if (CR_SUCCESS == cr)
  382. {
  383. for (LPTSTR psz = pszDevIntf; *psz; psz += lstrlen(psz) + 1)
  384. {
  385. i += _PrintIndent(cchIndent + 5);
  386. i += _tprintf(TEXT("['%s']\n"), psz);
  387. }
  388. }
  389. }
  390. }
  391. }
  392. {
  393. ULONG ulSize;
  394. cr = CM_Get_Device_Interface_List_Size(&ulSize, &g_guidDiskDriveIntf,
  395. szDeviceID, 0);
  396. if ((CR_SUCCESS == cr) && (ulSize > 1))
  397. {
  398. pszDevIntf = (LPTSTR)LocalAlloc(LPTR,
  399. ulSize * sizeof(TCHAR));
  400. if (pszDevIntf)
  401. {
  402. // *sizeof(TCHAR) ?
  403. cr = CM_Get_Device_Interface_List(&g_guidDiskDriveIntf,
  404. szDeviceID, pszDevIntf, ulSize, 0); //CM_GET_DEVICE_INTERFACE_LIST_PRESENT
  405. if (CR_SUCCESS == cr)
  406. {
  407. for (LPTSTR psz = pszDevIntf; *psz; psz += lstrlen(psz) + 1)
  408. {
  409. i += _PrintIndent(cchIndent + 5);
  410. i += _tprintf(TEXT("[['%s']]\n"), psz);
  411. }
  412. }
  413. }
  414. }
  415. }
  416. }
  417. return i;
  418. }
  419. HRESULT _EnumChildRecurs(DEVINST devinst, HMACHINE hMachine, DWORD dwFlags[],
  420. DWORD cchIndent)
  421. {
  422. HRESULT hres;
  423. DEVINST devinstChild;
  424. CONFIGRET cr = CM_Get_Child_Ex(&devinstChild, devinst, 0, hMachine);
  425. g_dwLevel += 1;
  426. if (CR_SUCCESS == cr)
  427. {
  428. do
  429. {
  430. DEVINST devinstChildNext;
  431. _PrintDeviceInfo(devinstChild, hMachine, dwFlags, cchIndent);
  432. hres = _EnumChildRecurs(devinstChild, hMachine, dwFlags,
  433. cchIndent + 4);
  434. // check return value
  435. cr = CM_Get_Sibling_Ex(&devinstChildNext, devinstChild, 0,
  436. hMachine);
  437. if (CR_SUCCESS == cr)
  438. {
  439. devinstChild = devinstChildNext;
  440. }
  441. }
  442. while (CR_SUCCESS == cr);
  443. }
  444. g_dwLevel -= 1;
  445. return S_OK;
  446. }
  447. HRESULT _GetDeviceInstance(LPWSTR pszDeviceID, DEVINST* pdevinst)
  448. {
  449. HRESULT hres = E_FAIL;
  450. HDEVINFO hdevinfo = SetupDiCreateDeviceInfoList(NULL, NULL);
  451. *pdevinst = NULL;
  452. if (INVALID_HANDLE_VALUE != hdevinfo)
  453. {
  454. SP_DEVICE_INTERFACE_DATA sdid = {0};
  455. sdid.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  456. if (SetupDiOpenDeviceInterface(hdevinfo, pszDeviceID, 0, &sdid))
  457. {
  458. DWORD cbsdidd = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) +
  459. (MAX_DEVICE_ID_LEN * sizeof(WCHAR));
  460. SP_DEVINFO_DATA sdd = {0};
  461. SP_DEVICE_INTERFACE_DETAIL_DATA* psdidd =
  462. (SP_DEVICE_INTERFACE_DETAIL_DATA*)LocalAlloc(LPTR, cbsdidd);
  463. if (psdidd)
  464. {
  465. psdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  466. sdd.cbSize = sizeof(SP_DEVINFO_DATA);
  467. // Stupidity Alert!
  468. //
  469. // SetupDiGetDeviceInterfaceDetail (below) requires that the
  470. // cbSize member of SP_DEVICE_INTERFACE_DETAIL_DATA be set
  471. // to the size of the fixed part of the structure, and to pass
  472. // the size of the full thing as the 4th param.
  473. if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &sdid, psdidd,
  474. cbsdidd, NULL, &sdd))
  475. {
  476. *pdevinst = sdd.DevInst;
  477. hres = S_OK;
  478. }
  479. LocalFree((HLOCAL)psdidd);
  480. }
  481. }
  482. SetupDiDestroyDeviceInfoList(hdevinfo);
  483. }
  484. return hres;
  485. }
  486. HRESULT _DeviceInfo(DWORD dwFlags[], LPWSTR pszDeviceID, DWORD cchIndent)
  487. {
  488. DEVINST devinst;
  489. HRESULT hres = _GetDeviceInstance(pszDeviceID, &devinst);
  490. if (SUCCEEDED(hres))
  491. {
  492. _PrintDeviceInfo(devinst, NULL, dwFlags, cchIndent);
  493. }
  494. return hres;
  495. }
  496. HRESULT _DeviceInterface(DWORD dwFlags[], LPWSTR pszDeviceID, DWORD cchIndent)
  497. {
  498. int i = 0;
  499. {
  500. for (DWORD dwIntf = 0; dwIntf < ARRAYSIZE(rgDevInterface); ++dwIntf)
  501. {
  502. ULONG ulSize;
  503. CONFIGRET cr = CM_Get_Device_Interface_List_Size(&ulSize,
  504. &(rgDevInterface[dwIntf].guid), pszDeviceID, 0);
  505. if ((CR_SUCCESS == cr) && (ulSize > 1))
  506. {
  507. LPTSTR pszDevIntf = (LPTSTR)LocalAlloc(LPTR,
  508. ulSize * sizeof(TCHAR));
  509. if (pszDevIntf)
  510. {
  511. // *sizeof(TCHAR) ?
  512. cr = CM_Get_Device_Interface_List(&(rgDevInterface[dwIntf].guid),
  513. pszDeviceID, pszDevIntf, ulSize, 0); //CM_GET_DEVICE_INTERFACE_LIST_PRESENT
  514. if (CR_SUCCESS == cr)
  515. {
  516. for (LPTSTR psz = pszDevIntf; *psz;
  517. psz += lstrlen(psz) + 1)
  518. {
  519. i += _PrintIndent(cchIndent + 5);
  520. i += _tprintf(TEXT("<>'%s'<> (%s)\n"), psz,
  521. rgDevInterface[dwIntf].pszName);
  522. }
  523. }
  524. LocalFree(pszDevIntf);
  525. }
  526. }
  527. }
  528. }
  529. {
  530. ULONG ul = 0;
  531. cguidInterface = 0;
  532. CONFIGRET cr;
  533. do
  534. {
  535. GUID guid;
  536. HMACHINE hMachine = NULL;
  537. cr = CM_Enumerate_Classes_Ex(ul, &guid, 0, hMachine);
  538. if (CR_SUCCESS == cr)
  539. {
  540. TCHAR szText[1024];
  541. DWORD cchText = ARRAYSIZE(szText);
  542. if (ul < ARRAYSIZE(rgguidInterface))
  543. {
  544. rgguidInterface[ul] = guid;
  545. ++cguidInterface;
  546. }
  547. /* cr = CM_Get_Class_Name(&guid, szText, &cchText, 0);
  548. if (CR_SUCCESS == cr)
  549. {
  550. _tprintf(TEXT("'%s' ("), szText);
  551. _PrintGUID(&guid);
  552. _tprintf(TEXT(")\n"));
  553. }*/
  554. }
  555. ++ul;
  556. }
  557. while (CR_SUCCESS == cr);
  558. for (DWORD dwIntf = 0; dwIntf < cguidInterface; ++dwIntf)
  559. {
  560. ULONG ulSize;
  561. CONFIGRET cr = CM_Get_Device_Interface_List_Size(&ulSize,
  562. &(rgguidInterface[dwIntf]), pszDeviceID, 0);
  563. if ((CR_SUCCESS == cr) && (ulSize > 1))
  564. {
  565. LPTSTR pszDevIntf = (LPTSTR)LocalAlloc(LPTR,
  566. ulSize * sizeof(TCHAR));
  567. if (pszDevIntf)
  568. {
  569. // *sizeof(TCHAR) ?
  570. cr = CM_Get_Device_Interface_List(&(rgguidInterface[dwIntf]),
  571. pszDeviceID, pszDevIntf, ulSize, 0); //CM_GET_DEVICE_INTERFACE_LIST_PRESENT
  572. if (CR_SUCCESS == cr)
  573. {
  574. for (LPTSTR psz = pszDevIntf; *psz;
  575. psz += lstrlen(psz) + 1)
  576. {
  577. i += _PrintIndent(cchIndent + 5);
  578. i += _PrintGUID(&(rgguidInterface[dwIntf]));
  579. i += _tprintf(TEXT(")\n"));
  580. }
  581. }
  582. LocalFree(pszDevIntf);
  583. }
  584. }
  585. }
  586. }
  587. return S_OK;
  588. }
  589. HRESULT _DeviceIDList(DWORD dwFlags[], LPWSTR pszDeviceID, DWORD cchIndent)
  590. {
  591. ULONG ulSize;
  592. HMACHINE hMachine = NULL;
  593. int i = 0;
  594. ULONG uFlags = CM_GETIDLIST_FILTER_NONE;
  595. CONFIGRET cr = CM_Get_Device_ID_List_Size_Ex(&ulSize,
  596. NULL, uFlags, hMachine);
  597. if ((CR_SUCCESS == cr) && (ulSize > 1))
  598. {
  599. LPTSTR pszDevIDList = (LPTSTR)LocalAlloc(LPTR, ulSize * sizeof(TCHAR));
  600. if (pszDevIDList)
  601. {
  602. // *sizeof(TCHAR) ?
  603. cr = CM_Get_Device_ID_List_Ex(NULL, pszDevIDList, ulSize,
  604. uFlags, hMachine);
  605. if (CR_SUCCESS == cr)
  606. {
  607. for (LPTSTR psz = pszDevIDList; *psz;
  608. psz += lstrlen(psz) + 1)
  609. {
  610. i += _PrintIndent(cchIndent + 5);
  611. i += _tprintf(TEXT("'%s'\n"), psz);
  612. }
  613. }
  614. LocalFree(pszDevIDList);
  615. }
  616. }
  617. return S_OK;
  618. }
  619. HRESULT _EnumDevice(DWORD dwFlags[], LPWSTR pszArg, DWORD cchIndent)
  620. {
  621. ULONG ulSize;
  622. LPTSTR pszDevIntf;
  623. ULONG ulFlags = CM_GET_DEVICE_INTERFACE_LIST_PRESENT;
  624. HMACHINE hMachine = NULL;
  625. GUID guid;
  626. if (StringToGUID(pszArg, &guid))
  627. {
  628. CONFIGRET cr = CM_Get_Device_Interface_List_Size(&ulSize, &guid,
  629. NULL, ulFlags);
  630. if ((CR_SUCCESS == cr) && (ulSize > 1))
  631. {
  632. pszDevIntf = (LPTSTR)LocalAlloc(LPTR, ulSize * sizeof(TCHAR));
  633. if (pszDevIntf)
  634. {
  635. // *sizeof(TCHAR) ?
  636. cr = CM_Get_Device_Interface_List_Ex(&guid, NULL, pszDevIntf, ulSize,
  637. ulFlags, hMachine);
  638. if (CR_SUCCESS == cr)
  639. {
  640. for (LPTSTR psz = pszDevIntf; *psz; psz += lstrlen(psz) + 1)
  641. {
  642. _tprintf(TEXT("['%s']\n"), psz);
  643. DEVINST devinst;
  644. // for now
  645. cr = CM_Locate_DevNode_Ex(&devinst, psz, 0, hMachine);
  646. if (CR_SUCCESS == cr)
  647. {
  648. ULONG ulStatus;
  649. ULONG ulProblem;
  650. cr = CM_Get_DevNode_Status_Ex(&ulStatus, &ulProblem,
  651. devinst, 0, hMachine);
  652. if (CR_SUCCESS == cr)
  653. {
  654. _tprintf(TEXT(" Status: 0x%08X]\n Problem #: 0x%08X"),
  655. ulStatus, ulProblem);
  656. }
  657. }
  658. }
  659. _tprintf(TEXT("\n"));
  660. }
  661. }
  662. }
  663. }
  664. return S_OK;
  665. }
  666. HRESULT _FullTree(DWORD dwFlags[], DWORD cchIndent)
  667. {
  668. HRESULT hres = E_FAIL;
  669. DEVINST devinstRoot;
  670. HMACHINE hMachine = NULL;
  671. CONFIGRET cr;
  672. _tprintf(TEXT("==================================================\n"));
  673. {
  674. ULONG ul = 0;
  675. cguidInterface = 0;
  676. do
  677. {
  678. GUID guid;
  679. cr = CM_Enumerate_Classes_Ex(ul, &guid, 0, hMachine);
  680. if (CR_SUCCESS == cr)
  681. {
  682. TCHAR szText[1024];
  683. DWORD cchText = ARRAYSIZE(szText);
  684. if (_IsFlagSet(MOD_FULLREPORT3, dwFlags))
  685. {
  686. if (ul < ARRAYSIZE(rgguidInterface))
  687. {
  688. rgguidInterface[ul] = guid;
  689. ++cguidInterface;
  690. }
  691. }
  692. cr = CM_Get_Class_Name(&guid, szText, &cchText, 0);
  693. if (CR_SUCCESS == cr)
  694. {
  695. _tprintf(TEXT("'%s' ("), szText);
  696. _PrintGUID(&guid);
  697. _tprintf(TEXT(")\n"));
  698. }
  699. }
  700. ++ul;
  701. }
  702. while (CR_SUCCESS == cr);
  703. }
  704. // Get Root Device node
  705. cr = CM_Locate_DevNode_Ex(&devinstRoot, NULL,
  706. CM_LOCATE_DEVNODE_NORMAL, hMachine);
  707. if (CR_SUCCESS == cr)
  708. {
  709. _PrintDeviceInfo(devinstRoot, hMachine, dwFlags, cchIndent);
  710. hres = _EnumChildRecurs(devinstRoot, hMachine, dwFlags, cchIndent + 4);
  711. }
  712. _tprintf(TEXT("= Volumes ===========================================\n"));
  713. {
  714. ULONG ulSize;
  715. LPTSTR pszDevIntf;
  716. ULONG ulFlags = CM_GET_DEVICE_INTERFACE_LIST_PRESENT;
  717. // ULONG ulFlags = CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES;
  718. cr = CM_Get_Device_Interface_List_Size(&ulSize, &g_guidVolume,
  719. NULL, ulFlags);
  720. if ((CR_SUCCESS == cr) && (ulSize > 1))
  721. {
  722. pszDevIntf = (LPTSTR)LocalAlloc(LPTR, ulSize * sizeof(TCHAR));
  723. if (pszDevIntf)
  724. {
  725. // *sizeof(TCHAR) ?
  726. cr = CM_Get_Device_Interface_List_Ex(&g_guidVolume, NULL, pszDevIntf, ulSize,
  727. ulFlags, hMachine);
  728. if (CR_SUCCESS == cr)
  729. {
  730. for (LPTSTR psz = pszDevIntf; *psz; psz += lstrlen(psz) + 1)
  731. {
  732. _tprintf(TEXT("['%s']\n"), psz);
  733. DEVINST devinst;
  734. // for now
  735. cr = CM_Locate_DevNode_Ex(&devinst, psz, 0, hMachine);
  736. if (CR_SUCCESS == cr)
  737. {
  738. ULONG ulStatus;
  739. ULONG ulProblem;
  740. cr = CM_Get_DevNode_Status_Ex(&ulStatus, &ulProblem,
  741. devinst, 0, hMachine);
  742. if (CR_SUCCESS == cr)
  743. {
  744. _tprintf(TEXT(" Status: 0x%08X]\n Problem #: 0x%08X"),
  745. ulStatus, ulProblem);
  746. }
  747. }
  748. }
  749. _tprintf(TEXT("\n"));
  750. }
  751. }
  752. }
  753. else
  754. {
  755. _tprintf(TEXT("\n"));
  756. }
  757. }
  758. _tprintf(TEXT("= Drives ===========================================\n"));
  759. {
  760. ULONG ulSize;
  761. LPTSTR pszDevIntf;
  762. ULONG ulFlags = CM_GET_DEVICE_INTERFACE_LIST_PRESENT;
  763. // ULONG ulFlags = CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES;
  764. cr = CM_Get_Device_Interface_List_Size(&ulSize, &g_guidDiskDriveIntf,
  765. NULL, ulFlags);
  766. if ((CR_SUCCESS == cr) && (ulSize > 1))
  767. {
  768. pszDevIntf = (LPTSTR)LocalAlloc(LPTR, ulSize * sizeof(TCHAR));
  769. if (pszDevIntf)
  770. {
  771. // *sizeof(TCHAR) ?
  772. cr = CM_Get_Device_Interface_List_Ex(&g_guidDiskDriveIntf, NULL, pszDevIntf, ulSize,
  773. ulFlags, hMachine);
  774. if (CR_SUCCESS == cr)
  775. {
  776. for (LPTSTR psz = pszDevIntf; *psz; psz += lstrlen(psz) + 1)
  777. {
  778. _tprintf(TEXT("['%s']\n"), psz);
  779. }
  780. _tprintf(TEXT("\n"));
  781. }
  782. }
  783. }
  784. else
  785. {
  786. _tprintf(TEXT("\n"));
  787. }
  788. }
  789. _tprintf(TEXT("==================================================\n"));
  790. {
  791. ULONG ul = 0;
  792. do
  793. {
  794. TCHAR szEnum[4096];
  795. ULONG ulEnum = sizeof(szEnum);
  796. cr = CM_Enumerate_Enumerators_Ex(ul, szEnum, &ulEnum, 0, hMachine);
  797. if (CR_SUCCESS == cr)
  798. {
  799. _tprintf(TEXT("'%s'\n"), szEnum);
  800. }
  801. ++ul;
  802. }
  803. while (CR_SUCCESS == cr);
  804. }
  805. return hres;
  806. }
  807. /*CM_Connect_Machine
  808. CM_Get_Device_ID_List_Size_Ex
  809. CM_Get_Child_Ex
  810. CM_Get_Sibling_Ex
  811. CM_Get_Parent_Ex
  812. CM_Get_DevNode_Registry_Property_Ex
  813. CM_Get_Class_Name_Ex
  814. CM_Get_DevNode_Status_Ex
  815. CM_Get_Device_ID_Ex
  816. CM_Request_Device_Eject_Ex
  817. CM_Locate_DevNode_Ex*/
  818. /*
  819. InitDevTreeDlgProc
  820. DEVINST* DeviceInstance
  821. HMACHINE DeviceTree->hMachine
  822. DEVINST DeviceTree->DevInst
  823. GUID DeviceTreeNode->ClassGuid
  824. TCHAR DeviceID[MAX_DEVICE_ID_LEN]
  825. PTSTR DeviceInterface
  826. //
  827. // Get the root devnode.
  828. //
  829. ConfigRet = CM_Locate_DevNode_Ex(&DeviceTree->DevInst,
  830. NULL,
  831. CM_LOCATE_DEVNODE_NORMAL,
  832. DeviceTree->hMachine (NULL)
  833. );
  834. if (ConfigRet != CR_SUCCESS) {
  835. ConfigRet = CM_Get_Child_Ex(&DeviceInstance, (Out param)
  836. DeviceTree->DevInst, (prev call)
  837. 0,
  838. DeviceTree->hMachine (NULL)
  839. );
  840. if (ConfigRet == CR_SUCCESS) {
  841. // for info
  842. ConfigRet = CM_Get_DevNode_Registry_Property_Ex(DeviceInstance, (from above)
  843. CM_DRP_CLASSGUID,
  844. NULL,
  845. &Buffer,
  846. &Len,
  847. 0,
  848. DeviceTree->hMachine (NULL)
  849. );
  850. if (ConfigRet == CR_SUCCESS) {
  851. Out: // GUID_DEVCLASS_COMPUTER
  852. {0x4d36e966L, 0xe325, 0x11ce,
  853. {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}},
  854. if (ConfigRet == CR_SUCCESS) {
  855. ConfigRet = CM_Get_Class_Name_Ex(&DeviceTreeNode->ClassGuid,
  856. Buffer,
  857. &Len,
  858. 0,
  859. DeviceTree->hMachine
  860. );
  861. Out: Computer
  862. if (ConfigRet == CR_SUCCESS) {
  863. // trying to find drive letter
  864. x DevNodeToDriveLetter(x
  865. x
  866. x if (CM_Get_Device_ID_Ex(DevInst,
  867. x DeviceID,
  868. x sizeof(DeviceID)/sizeof(TCHAR),
  869. x 0,
  870. x NULL
  871. x ) == CR_SUCCESS) {
  872. x Out: 0x0006ee8c "ROOT\ACPI_HAL\0000"
  873. x
  874. x
  875. x if (CM_Get_Device_Interface_List_Size(&ulSize,
  876. x (LPGUID)&VolumeClassGuid,
  877. x DeviceID,
  878. x 0) == CR_SUCCESS) &&
  879. x
  880. x Out: FAILS
  881. x (ulSize > 1) &&
  882. x ((DeviceInterface = LocalAlloc(LPTR, ulSize*sizeof(TCHAR))) != NULL) &&
  883. x (CM_Get_Device_Interface_List((LPGUID)&VolumeClassGuid,
  884. x DeviceID,
  885. x DeviceInterface,
  886. x ulSize,
  887. x 0
  888. x ) == CR_SUCCESS) &&
  889. ConfigRet = CM_Get_DevNode_Registry_Property_Ex(DeviceInstance,
  890. CM_DRP_FRIENDLYNAME,
  891. NULL,
  892. Buffer,
  893. &Len,
  894. 0,
  895. DeviceTree->hMachine
  896. );
  897. then, CM_DRP_DEVICEDESC... out: "Advanced Configuration and Power Interface (ACPI) PC"
  898. ....
  899. BuildLocationInformation: Boring....
  900. // Get InstanceId
  901. ConfigRet = CM_Get_Device_ID_ExW(DeviceInstance,
  902. Buffer,
  903. Len/sizeof(TCHAR),
  904. 0,
  905. DeviceTree->hMachine
  906. );
  907. Out "ROOT\ACPI_HAL\0000"
  908. { // should skip
  909. BuildDeviceRelationsList
  910. ConfigRet = CM_Get_Device_ID_List_Size_Ex(&Len,
  911. DeviceId, ("ROOT\ACPI_HAL\0000")
  912. FilterFlag, (CM_GETIDLIST_FILTER_EJECTRELATIONS)
  913. hMachine (NULL)
  914. );
  915. BuildDeviceRelationsList
  916. ConfigRet = CM_Get_Device_ID_List_Size_Ex(&Len,
  917. DeviceId, ("ROOT\ACPI_HAL\0000")
  918. FilterFlag, (CM_GETIDLIST_FILTER_REMOVALRELATIONS)
  919. hMachine
  920. );
  921. // Both FAILED, if would have succeeded, would have trierd to enum drive letters
  922. }
  923. // If this devinst has children, then recurse to fill in its child sibling list.
  924. ConfigRet = CM_Get_Child_Ex(&ChildDeviceInstance, (out param)
  925. DeviceInstance, (same as above)
  926. 0,
  927. DeviceTree->hMachine (NULL)
  928. );
  929. //recurse to redo the same as above for child, then ...
  930. // Next sibling ...
  931. ConfigRet = CM_Get_Sibling_Ex(&DeviceInstance, (Ouch!)
  932. DeviceInstance,
  933. 0,
  934. DeviceTree->hMachine
  935. );
  936. ///////////////////////////////////////////////////////////////////////////////
  937. //
  938. // Device Instance status flags, returned by call to CM_Get_DevInst_Status
  939. //
  940. #define DN_ROOT_ENUMERATED (0x00000001) // Was enumerated by ROOT
  941. #define DN_DRIVER_LOADED (0x00000002) // Has Register_Device_Driver
  942. #define DN_ENUM_LOADED (0x00000004) // Has Register_Enumerator
  943. #define DN_STARTED (0x00000008) // Is currently configured
  944. #define DN_MANUAL (0x00000010) // Manually installed
  945. #define DN_NEED_TO_ENUM (0x00000020) // May need reenumeration
  946. #define DN_NOT_FIRST_TIME (0x00000040) // Has received a config
  947. #define DN_HARDWARE_ENUM (0x00000080) // Enum generates hardware ID
  948. #define DN_LIAR (0x00000100) // Lied about can reconfig once
  949. #define DN_HAS_MARK (0x00000200) // Not CM_Create_DevInst lately
  950. #define DN_HAS_PROBLEM (0x00000400) // Need device installer
  951. #define DN_FILTERED (0x00000800) // Is filtered
  952. #define DN_MOVED (0x00001000) // Has been moved
  953. #define DN_DISABLEABLE (0x00002000) // Can be rebalanced
  954. #define DN_REMOVABLE (0x00004000) // Can be removed
  955. #define DN_PRIVATE_PROBLEM (0x00008000) // Has a private problem
  956. #define DN_MF_PARENT (0x00010000) // Multi function parent
  957. #define DN_MF_CHILD (0x00020000) // Multi function child
  958. #define DN_WILL_BE_REMOVED (0x00040000) // DevInst is being removed
  959. // Flags for CM_Get_Device_ID_List, CM_Get_Device_ID_List_Size
  960. //
  961. #define CM_GETIDLIST_FILTER_NONE (0x00000000)
  962. #define CM_GETIDLIST_FILTER_ENUMERATOR (0x00000001)
  963. #define CM_GETIDLIST_FILTER_SERVICE (0x00000002)
  964. #define CM_GETIDLIST_FILTER_EJECTRELATIONS (0x00000004)
  965. #define CM_GETIDLIST_FILTER_REMOVALRELATIONS (0x00000008)
  966. #define CM_GETIDLIST_FILTER_POWERRELATIONS (0x00000010)
  967. #define CM_GETIDLIST_FILTER_BUSRELATIONS (0x00000020)
  968. #define CM_GETIDLIST_DONOTGENERATE (0x10000040)
  969. #define CM_GETIDLIST_FILTER_BITS (0x1000007F)
  970. //
  971. // Flags for CM_Get_Device_Interface_List, CM_Get_Device_Interface_List_Size
  972. //
  973. #define CM_GET_DEVICE_INTERFACE_LIST_PRESENT (0x00000000) // only currently 'live' device interfaces
  974. #define CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES (0x00000001) // all registered device interfaces, live or not
  975. #define CM_GET_DEVICE_INTERFACE_LIST_BITS (0x00000001)
  976. */