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.

482 lines
15 KiB

  1. #include "dfstpdi.h"
  2. #include <stdio.h>
  3. #include <winuser.h>
  4. #include <tchar.h>
  5. #include "cfgmgr32.h"
  6. #include "setupapi.h"
  7. #include "dbt.h"
  8. #include "drvfull.h"
  9. #include "dfhlprs.h"
  10. #include "shellapi.h"
  11. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  12. static GUID g_guidIntfClass =
  13. {0x53f5630d, 0xb6bf, 0x11d0,
  14. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  15. static HDEVINFO g_hdevinfo = NULL;
  16. _sFLAG_DESCR _SPDID_FD[] =
  17. {
  18. FLAG_DESCR(SPINT_ACTIVE),
  19. FLAG_DESCR(SPINT_DEFAULT),
  20. FLAG_DESCR(SPINT_REMOVED),
  21. };
  22. _sFLAG_DESCR _regpropFD[] =
  23. {
  24. FLAG_DESCR_COMMENT(SPDRP_DEVICEDESC, TEXT("DeviceDesc (R/W)")),
  25. FLAG_DESCR_COMMENT(SPDRP_HARDWAREID, TEXT("HardwareID (R/W)")),
  26. FLAG_DESCR_COMMENT(SPDRP_COMPATIBLEIDS, TEXT("CompatibleIDs (R/W)")),
  27. FLAG_DESCR_COMMENT(SPDRP_SERVICE, TEXT("Service (R/W)")),
  28. FLAG_DESCR_COMMENT(SPDRP_CLASS, TEXT("Class (R--tied to ClassGUID)")),
  29. FLAG_DESCR_COMMENT(SPDRP_CLASSGUID, TEXT("ClassGUID (R/W)")),
  30. FLAG_DESCR_COMMENT(SPDRP_DRIVER, TEXT("Driver (R/W)")),
  31. FLAG_DESCR_COMMENT(SPDRP_CONFIGFLAGS, TEXT("ConfigFlags (R/W)")),
  32. FLAG_DESCR_COMMENT(SPDRP_MFG, TEXT("Mfg (R/W)")),
  33. FLAG_DESCR_COMMENT(SPDRP_FRIENDLYNAME, TEXT("FriendlyName (R/W)")),
  34. FLAG_DESCR_COMMENT(SPDRP_LOCATION_INFORMATION, TEXT("LocationInformation (R/W)")),
  35. FLAG_DESCR_COMMENT(SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, TEXT("PhysicalDeviceObjectName (R)")),
  36. FLAG_DESCR_COMMENT(SPDRP_CAPABILITIES, TEXT("Capabilities (R)")),
  37. FLAG_DESCR_COMMENT(SPDRP_UI_NUMBER, TEXT("UiNumber (R)")),
  38. FLAG_DESCR_COMMENT(SPDRP_UPPERFILTERS, TEXT("UpperFilters (R/W)")),
  39. FLAG_DESCR_COMMENT(SPDRP_LOWERFILTERS, TEXT("LowerFilters (R/W)")),
  40. FLAG_DESCR_COMMENT(SPDRP_BUSTYPEGUID, TEXT("BusTypeGUID (R)")),
  41. FLAG_DESCR_COMMENT(SPDRP_LEGACYBUSTYPE, TEXT("LegacyBusType (R)")),
  42. FLAG_DESCR_COMMENT(SPDRP_BUSNUMBER, TEXT("BusNumber (R)")),
  43. FLAG_DESCR_COMMENT(SPDRP_ENUMERATOR_NAME, TEXT("Enumerator Name (R)")),
  44. FLAG_DESCR_COMMENT(SPDRP_SECURITY, TEXT("Security (R/W, binary form)")),
  45. FLAG_DESCR_COMMENT(SPDRP_SECURITY_SDS, TEXT("Security (W, SDS form)")),
  46. FLAG_DESCR_COMMENT(SPDRP_DEVTYPE, TEXT("Device Type (R/W)")),
  47. FLAG_DESCR_COMMENT(SPDRP_EXCLUSIVE, TEXT("Device is exclusive-access (R/W)")),
  48. FLAG_DESCR_COMMENT(SPDRP_CHARACTERISTICS, TEXT("Device Characteristics (R/W)")),
  49. FLAG_DESCR_COMMENT(SPDRP_ADDRESS, TEXT("Device Address (R)")),
  50. FLAG_DESCR_COMMENT(SPDRP_UI_NUMBER_DESC_FORMAT, TEXT("UiNumberDescFormat (R/W)")),
  51. FLAG_DESCR_COMMENT(SPDRP_MAXIMUM_PROPERTY, TEXT("Upper bound on ordinals")),
  52. };
  53. HRESULT _PrintDetailed(DWORD dwFlags[], DWORD cchIndent, HDEVINFO hdevinfo,
  54. SP_DEVINFO_DATA* pdevinfo, SP_DEVICE_INTERFACE_DATA* pspdid,
  55. SP_DEVICE_INTERFACE_DETAIL_DATA* pspdidd)
  56. {
  57. HRESULT hres = S_OK;
  58. if (_IsFlagSet(MOD_FULLREPORT1, dwFlags))
  59. {
  60. _PrintIndent(cchIndent + 2);
  61. _tprintf(TEXT("Registry properties (SetupDiGetDeviceRegistryProperty):\n"));
  62. _PrintIndent(cchIndent + 2);
  63. _tprintf(TEXT("{\n"));
  64. TCHAR szTest[1024];
  65. if (SetupDiGetDeviceRegistryProperty(hdevinfo, pdevinfo,
  66. SPDRP_FRIENDLYNAME, NULL, (PBYTE)szTest,
  67. ARRAYSIZE(szTest) * sizeof(TCHAR), NULL))
  68. {
  69. _PrintIndent(cchIndent + 4);
  70. _tprintf(TEXT("%s ("), szTest);
  71. _PrintFlag(SPDRP_FRIENDLYNAME, _regpropFD, ARRAYSIZE(_regpropFD), 0,
  72. FALSE, FALSE, TRUE, FALSE);
  73. _tprintf(TEXT(")\n"));
  74. }
  75. if (SetupDiGetDeviceRegistryProperty(hdevinfo, pdevinfo,
  76. SPDRP_DEVICEDESC, NULL, (PBYTE)szTest,
  77. ARRAYSIZE(szTest) * sizeof(TCHAR), NULL))
  78. {
  79. _PrintIndent(cchIndent + 4);
  80. _tprintf(TEXT("%s ("), szTest);
  81. _PrintFlag(SPDRP_DEVICEDESC, _regpropFD, ARRAYSIZE(_regpropFD), 0,
  82. FALSE, FALSE, TRUE, FALSE);
  83. _tprintf(TEXT(")\n"));
  84. }
  85. _PrintIndent(cchIndent + 2);
  86. _tprintf(TEXT("}\n"));
  87. }
  88. if (_IsFlagSet(MOD_FULLREPORT2, dwFlags))
  89. {
  90. _PrintCR();
  91. _PrintIndent(cchIndent + 2);
  92. _tprintf(TEXT("SP_DEVICE_INTERFACE_DATA\n"));
  93. _PrintIndent(cchIndent + 2);
  94. _tprintf(TEXT("{\n"));
  95. _PrintIndent(cchIndent + 4);
  96. _PrintGUID(&(pspdid->InterfaceClassGuid));
  97. _tprintf(TEXT(" (GUID InterfaceClassGuid)\n"));
  98. _PrintFlag(pspdid->Flags, _SPDID_FD, ARRAYSIZE(_SPDID_FD), cchIndent + 4,
  99. TRUE, TRUE, FALSE, FALSE);
  100. _tprintf(TEXT(" (DWORD Flags)\n"));
  101. _PrintIndent(cchIndent + 2);
  102. _tprintf(TEXT("}\n"));
  103. _PrintIndent(cchIndent + 2);
  104. _tprintf(TEXT("SP_DEVINFO_DATA\n"));
  105. _PrintIndent(cchIndent + 2);
  106. _tprintf(TEXT("{\n"));
  107. _PrintIndent(cchIndent + 4);
  108. _PrintGUID(&(pdevinfo->ClassGuid));
  109. _tprintf(TEXT(" (GUID ClassGuid)\n"));
  110. _PrintIndent(cchIndent + 4);
  111. _tprintf(TEXT("%u (DWORD DevInst)\n"), pdevinfo->DevInst);
  112. _PrintIndent(cchIndent + 2);
  113. _tprintf(TEXT("}\n"));
  114. _PrintIndent(cchIndent + 2);
  115. _tprintf(TEXT("SP_DEVICE_INTERFACE_DETAIL_DATA\n"));
  116. _PrintIndent(cchIndent + 2);
  117. _tprintf(TEXT("{\n"));
  118. DWORD cch = lstrlen(pspdidd->DevicePath);
  119. for (DWORD dw = 0; dw < cch; dw += 80)
  120. {
  121. TCHAR sz[81];
  122. if (dw && (dw < cch))
  123. {
  124. _tprintf(TEXT("...\n"));
  125. }
  126. lstrcpyn(sz, pspdidd->DevicePath + dw, ARRAYSIZE(sz));
  127. _PrintIndent(cchIndent + 4);
  128. _tprintf(sz);
  129. }
  130. _PrintIndent(cchIndent + 4);
  131. _tprintf(TEXT(" (TCHAR DevicePath)\n"));
  132. _PrintIndent(cchIndent + 2);
  133. _tprintf(TEXT("}\n"));
  134. }
  135. return hres;
  136. }
  137. extern int g_argc;
  138. extern wchar_t** g_argv;
  139. // drvfull -pnpcs <deviceID> <Property>
  140. HRESULT _CustomProperty(DWORD dwFlags[], LPWSTR , DWORD cchIndent)
  141. {
  142. HRESULT hr;
  143. HDEVINFO hdevinfo = SetupDiCreateDeviceInfoList(NULL, NULL);
  144. if (INVALID_HANDLE_VALUE != hdevinfo)
  145. {
  146. SP_DEVINFO_DATA sdd = {0};
  147. sdd.cbSize = sizeof(sdd);
  148. if ((TEXT('\\') == g_argv[2][0]) && (TEXT('\\') == g_argv[2][1]) &&
  149. (TEXT('?') == g_argv[2][2]) && (TEXT('\\') == g_argv[2][3]))
  150. {
  151. SP_DEVICE_INTERFACE_DATA sdid = {0};
  152. sdid.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  153. if (SetupDiOpenDeviceInterface(hdevinfo, (LPCWSTR)g_argv[2], 0, &sdid))
  154. {
  155. DWORD cbsdidd = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) +
  156. (MAX_DEVICE_ID_LEN * sizeof(WCHAR));
  157. SP_DEVICE_INTERFACE_DETAIL_DATA* psdidd =
  158. (SP_DEVICE_INTERFACE_DETAIL_DATA*)LocalAlloc(LPTR, cbsdidd);
  159. if (psdidd)
  160. {
  161. psdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  162. // SetupDiGetDeviceInterfaceDetail (below) requires that the
  163. // cbSize member of SP_DEVICE_INTERFACE_DETAIL_DATA be set
  164. // to the size of the fixed part of the structure, and to pass
  165. // the size of the full thing as the 4th param.
  166. if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &sdid, psdidd,
  167. cbsdidd, NULL, &sdd))
  168. {
  169. hr = S_OK;
  170. }
  171. LocalFree((HLOCAL)psdidd);
  172. }
  173. }
  174. }
  175. else
  176. {
  177. if (SetupDiOpenDeviceInfo(hdevinfo, (LPCWSTR)g_argv[2], NULL, 0, &sdd))
  178. {
  179. hr = S_OK;
  180. }
  181. }
  182. if (SUCCEEDED(hr))
  183. {
  184. WCHAR szTestProp[512];
  185. if (SetupDiGetCustomDeviceProperty(hdevinfo, &sdd,
  186. (LPCWSTR)g_argv[3], 0, NULL, (PBYTE)szTestProp,
  187. ARRAYSIZE(szTestProp), NULL))
  188. {
  189. _PrintIndent(cchIndent + 4);
  190. _tprintf(TEXT("%s = %s"), (LPCWSTR)g_argv[3], szTestProp);
  191. }
  192. }
  193. SetupDiDestroyDeviceInfoList(hdevinfo);
  194. }
  195. return hr;
  196. }
  197. HRESULT _EnumDevices(DWORD dwFlags[], HDEVINFO hdevinfo,
  198. SP_DEVINFO_DATA* pdevinfoConstraint, CONST GUID *pguidIntfClass,
  199. DWORD cchIndent)
  200. {
  201. HRESULT hres = E_FAIL;
  202. SP_DEVICE_INTERFACE_DATA spdid = {0};
  203. SP_DEVICE_INTERFACE_DETAIL_DATA* pspdidd = NULL;
  204. SP_DEVINFO_DATA devinfo = {0};
  205. DWORD cbspdidd = 0;
  206. devinfo.cbSize = sizeof(devinfo);
  207. spdid.cbSize = sizeof(spdid);
  208. for (DWORD dw = 0; SetupDiEnumDeviceInterfaces(hdevinfo, pdevinfoConstraint,
  209. pguidIntfClass, dw, &spdid); ++dw)
  210. {
  211. DWORD dwReqSize;
  212. hres = S_OK;
  213. // To retrieve the device interface name (e.g., that you can call
  214. // CreateFile() on...
  215. while (SUCCEEDED(hres) && !SetupDiGetDeviceInterfaceDetail(hdevinfo,
  216. &spdid, pspdidd, cbspdidd, &dwReqSize, &devinfo))
  217. {
  218. // We failed to get the device interface detail data--was it because
  219. // our buffer was too small? (Hopefully so!)
  220. DWORD dwErr = GetLastError();
  221. if (pspdidd)
  222. {
  223. free(pspdidd);
  224. pspdidd = NULL;
  225. }
  226. if (ERROR_INSUFFICIENT_BUFFER == dwErr)
  227. {
  228. // We failed due to insufficient buffer. Allocate one that's
  229. // sufficiently large and try again.
  230. pspdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA*)malloc(dwReqSize);
  231. if (pspdidd)
  232. {
  233. cbspdidd = dwReqSize;
  234. pspdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  235. }
  236. else
  237. {
  238. // Failure!
  239. cbspdidd = 0;
  240. _PrintIndent(cchIndent);
  241. _tprintf(TEXT("Not enough memory\n"));
  242. hres = E_OUTOFMEMORY;
  243. break;
  244. }
  245. }
  246. else
  247. {
  248. // Failure!
  249. _PrintIndent(cchIndent);
  250. _tprintf(TEXT("SetupDiGetDeviceInterfaceDetail failed\n"));
  251. _PrintGetLastError(cchIndent);
  252. hres = E_FAIL;
  253. break;
  254. }
  255. }
  256. if (SUCCEEDED(hres))
  257. {
  258. if (!pdevinfoConstraint)
  259. {
  260. BOOL bResult;
  261. TCHAR szDeviceName[MAX_PATH];
  262. TCHAR szVolumeName[MAX_PATH * 2];
  263. lstrcpy(szDeviceName, pspdidd->DevicePath);
  264. lstrcat(szDeviceName, TEXT("\\"));
  265. bResult = GetVolumeNameForVolumeMountPoint(szDeviceName,
  266. szVolumeName, MAX_PATH);
  267. if (bResult)
  268. {
  269. _PrintCR();
  270. _PrintIndent(cchIndent + 2);
  271. _tprintf(TEXT("--------------------------------------------")\
  272. TEXT("--------------------------\n"));
  273. _PrintIndent(cchIndent + 2);
  274. _tprintf(TEXT("-- Volume name: '%s'\n"), szVolumeName);
  275. }
  276. }
  277. if (_IsFlagSet(MOD_FULLREPORTFULL, dwFlags))
  278. {
  279. hres = _PrintDetailed(dwFlags, cchIndent, hdevinfo,
  280. &devinfo, &spdid, pspdidd);
  281. }
  282. /* if (!pdevinfoConstraint)
  283. {
  284. GUID guidUSB = {0x36fc9e60, 0xc465, 0x11cf,
  285. {0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
  286. hres = _EnumDevices(dwFlags, hdevinfo, &devinfo, &guidUSB,
  287. cchIndent + 2);
  288. }*/
  289. }
  290. }
  291. if (pspdidd)
  292. {
  293. free(pspdidd);
  294. }
  295. return hres;
  296. }
  297. HRESULT _InitNotifSetupDI(DWORD dwFlags[], DWORD cchIndent)
  298. {
  299. HRESULT hres = S_OK;
  300. // Create a device information set that will be the container for our
  301. // device interfaces.
  302. g_hdevinfo = SetupDiCreateDeviceInfoList(NULL, NULL);
  303. if (INVALID_HANDLE_VALUE != g_hdevinfo)
  304. {
  305. // OK, now we can retrieve the existing list of active device
  306. // interfaces into the device information set we created above.
  307. HDEVINFO hdevinfo = SetupDiGetClassDevsEx(&g_guidIntfClass, NULL,
  308. NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE, g_hdevinfo, NULL,
  309. NULL);
  310. if (INVALID_HANDLE_VALUE != hdevinfo)
  311. {
  312. // If SetupDiGetClassDevsEx succeeds and it was passed in an
  313. // existing device information set to be used, then the HDEVINFO
  314. // it returns is the same as the one it was passed in. Thus, we
  315. // can just use the original DeviceInfoSet handle from here on.
  316. // Now fill in our listbox with the current device interface list.
  317. hres = _EnumDevices(dwFlags, g_hdevinfo, NULL, &g_guidIntfClass,
  318. cchIndent);
  319. if (FAILED(hres))
  320. {
  321. _PrintGetLastError(cchIndent);
  322. }
  323. }
  324. else
  325. {
  326. _PrintIndent(cchIndent);
  327. _tprintf(TEXT("SetupDiGetClassDevsEx failed\n"));
  328. _PrintGetLastError(cchIndent);
  329. hres = E_FAIL;
  330. }
  331. }
  332. else
  333. {
  334. _PrintIndent(cchIndent);
  335. _tprintf(TEXT("SetupDiCreateDeviceInfoList failed\n"));
  336. _PrintGetLastError(cchIndent);
  337. hres = E_FAIL;
  338. }
  339. return hres;
  340. }
  341. HRESULT _CleanupSetupDI()
  342. {
  343. if (g_hdevinfo)
  344. {
  345. SetupDiDestroyDeviceInfoList(g_hdevinfo);
  346. }
  347. return S_OK;
  348. }
  349. HRESULT _HandleNotifSetupDI(DWORD dwFlags[], DWORD cchIndent, WPARAM wParam,
  350. LPARAM lParam)
  351. {
  352. HRESULT hres = E_FAIL;
  353. SP_DEVICE_INTERFACE_DATA spdid = {0};
  354. DEV_BROADCAST_DEVICEINTERFACE* pdbdi;
  355. if (DBT_DEVTYP_DEVICEINTERFACE ==
  356. ((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype)
  357. {
  358. pdbdi = (DEV_BROADCAST_DEVICEINTERFACE*)lParam;
  359. if (DBT_DEVICEARRIVAL == wParam)
  360. {
  361. // Open this new device interface into our device information set.
  362. if (!SetupDiOpenDeviceInterface(g_hdevinfo,
  363. pdbdi->dbcc_name, 0, NULL))
  364. {
  365. _PrintIndent(cchIndent + 2);
  366. _tprintf(TEXT("SetupDiOpenDeviceInterface failed\n"));
  367. _PrintGetLastError(cchIndent + 2);
  368. _PrintCR();
  369. }
  370. }
  371. else
  372. {
  373. // First, locate this device interface in our device information set.
  374. spdid.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  375. if (SetupDiOpenDeviceInterface(g_hdevinfo,
  376. pdbdi->dbcc_name, DIODI_NO_ADD, &spdid))
  377. {
  378. if (!SetupDiDeleteDeviceInterfaceData(g_hdevinfo,
  379. &spdid))
  380. {
  381. _PrintIndent(cchIndent + 2);
  382. _tprintf(TEXT("SetupDiDeletespdid failed\n"));
  383. _PrintGetLastError(cchIndent + 2);
  384. _PrintCR();
  385. }
  386. }
  387. else
  388. {
  389. _PrintIndent(cchIndent + 2);
  390. _tprintf(TEXT("SetupDiOpenDeviceInterface failed\n"));
  391. _PrintGetLastError(cchIndent + 2);
  392. _PrintCR();
  393. }
  394. }
  395. }
  396. hres = _EnumDevices(dwFlags, g_hdevinfo, NULL, &g_guidIntfClass, cchIndent);
  397. return hres;
  398. }