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.

1182 lines
31 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. dump.cpp
  5. Abstract:
  6. Device Console
  7. dump information out about a particular device
  8. @@BEGIN_DDKSPLIT
  9. Author:
  10. Jamie Hunter (JamieHun) Nov-30-2000
  11. Revision History:
  12. @@END_DDKSPLIT
  13. --*/
  14. #include "devcon.h"
  15. BOOL DumpDeviceWithInfo(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo,LPCTSTR Info)
  16. /*++
  17. Routine Description:
  18. Write device instance & info to stdout
  19. Arguments:
  20. Devs )_ uniquely identify device
  21. DevInfo )
  22. Return Value:
  23. none
  24. --*/
  25. {
  26. TCHAR devID[MAX_DEVICE_ID_LEN];
  27. LPTSTR desc;
  28. BOOL b = TRUE;
  29. SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
  30. devInfoListDetail.cbSize = sizeof(devInfoListDetail);
  31. if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) ||
  32. (CM_Get_Device_ID_Ex(DevInfo->DevInst,devID,MAX_DEVICE_ID_LEN,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) {
  33. lstrcpy(devID,TEXT("?"));
  34. b = FALSE;
  35. }
  36. if(Info) {
  37. _tprintf(TEXT("%-60s: %s\n"),devID,Info);
  38. } else {
  39. _tprintf(TEXT("%s\n"),devID);
  40. }
  41. return b;
  42. }
  43. BOOL DumpDevice(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo)
  44. /*++
  45. Routine Description:
  46. Write device instance & description to stdout
  47. Arguments:
  48. Devs )_ uniquely identify device
  49. DevInfo )
  50. Return Value:
  51. TRUE if success
  52. --*/
  53. {
  54. LPTSTR desc;
  55. BOOL b;
  56. desc = GetDeviceDescription(Devs,DevInfo);
  57. b = DumpDeviceWithInfo(Devs,DevInfo,desc);
  58. if(desc) {
  59. delete [] desc;
  60. }
  61. return b;
  62. }
  63. BOOL DumpDeviceDescr(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo)
  64. /*++
  65. Routine Description:
  66. Write device description to stdout
  67. Arguments:
  68. Devs )_ uniquely identify device
  69. DevInfo )
  70. Return Value:
  71. TRUE if success
  72. --*/
  73. {
  74. LPTSTR desc;
  75. BOOL b;
  76. desc = GetDeviceDescription(Devs,DevInfo);
  77. if(!desc) {
  78. return FALSE;
  79. }
  80. Padding(1);
  81. FormatToStream(stdout,MSG_DUMP_DESCRIPTION,desc);
  82. delete [] desc;
  83. return TRUE;
  84. }
  85. BOOL DumpDeviceClass(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo)
  86. /*++
  87. Routine Description:
  88. Write device class information to stdout
  89. Arguments:
  90. Devs )_ uniquely identify device
  91. DevInfo )
  92. Return Value:
  93. TRUE if success
  94. --*/
  95. {
  96. LPTSTR cls;
  97. LPTSTR guid;
  98. Padding(1);
  99. cls = GetDeviceStringProperty(Devs,DevInfo,SPDRP_CLASS);
  100. guid = GetDeviceStringProperty(Devs,DevInfo,SPDRP_CLASSGUID);
  101. if(!cls && !guid) {
  102. FormatToStream(stdout,
  103. MSG_DUMP_NOSETUPCLASS
  104. );
  105. } else {
  106. FormatToStream(stdout,
  107. MSG_DUMP_SETUPCLASS,
  108. guid ? guid : TEXT("{}"),
  109. cls ? cls : TEXT("(?)")
  110. );
  111. }
  112. if(cls) {
  113. delete [] cls;
  114. }
  115. if(guid) {
  116. delete [] guid;
  117. }
  118. return TRUE;
  119. }
  120. BOOL DumpDeviceStatus(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo)
  121. /*++
  122. Routine Description:
  123. Write device status to stdout
  124. Arguments:
  125. Devs )_ uniquely identify device
  126. DevInfo )
  127. Return Value:
  128. none
  129. --*/
  130. {
  131. SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
  132. ULONG status = 0;
  133. ULONG problem = 0;
  134. BOOL hasInfo = FALSE;
  135. devInfoListDetail.cbSize = sizeof(devInfoListDetail);
  136. if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) ||
  137. (CM_Get_DevNode_Status_Ex(&status,&problem,DevInfo->DevInst,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) {
  138. return FALSE;
  139. }
  140. //
  141. // handle off the status/problem codes
  142. //
  143. if((status & DN_HAS_PROBLEM) && problem == CM_PROB_DISABLED) {
  144. hasInfo = TRUE;
  145. Padding(1);
  146. FormatToStream(stdout,MSG_DUMP_DISABLED);
  147. return TRUE;
  148. }
  149. if(status & DN_HAS_PROBLEM) {
  150. hasInfo = TRUE;
  151. Padding(1);
  152. FormatToStream(stdout,MSG_DUMP_PROBLEM,problem);
  153. }
  154. if(status & DN_PRIVATE_PROBLEM) {
  155. hasInfo = TRUE;
  156. Padding(1);
  157. FormatToStream(stdout,MSG_DUMP_PRIVATE_PROBLEM);
  158. }
  159. if(status & DN_STARTED) {
  160. Padding(1);
  161. FormatToStream(stdout,MSG_DUMP_STARTED);
  162. } else if (!hasInfo) {
  163. Padding(1);
  164. FormatToStream(stdout,MSG_DUMP_NOTSTARTED);
  165. }
  166. return TRUE;
  167. }
  168. BOOL DumpDeviceResourcesOfType(DEVINST DevInst,HMACHINE MachineHandle,LOG_CONF Config,RESOURCEID ReqResId)
  169. {
  170. RES_DES prevResDes = (RES_DES)Config;
  171. RES_DES resDes = 0;
  172. RESOURCEID resId = ReqResId;
  173. ULONG dataSize;
  174. PBYTE resDesData;
  175. while(CM_Get_Next_Res_Des_Ex(&resDes,prevResDes,ReqResId,&resId,0,MachineHandle)==CR_SUCCESS) {
  176. if(prevResDes != Config) {
  177. CM_Free_Res_Des_Handle(prevResDes);
  178. }
  179. prevResDes = resDes;
  180. if(CM_Get_Res_Des_Data_Size_Ex(&dataSize,resDes,0,MachineHandle)!=CR_SUCCESS) {
  181. continue;
  182. }
  183. resDesData = new BYTE[dataSize];
  184. if(!resDesData) {
  185. continue;
  186. }
  187. if(CM_Get_Res_Des_Data_Ex(resDes,resDesData,dataSize,0,MachineHandle)!=CR_SUCCESS) {
  188. delete [] resDesData;
  189. continue;
  190. }
  191. switch(resId) {
  192. case ResType_Mem: {
  193. PMEM_RESOURCE pMemData = (PMEM_RESOURCE)resDesData;
  194. if(pMemData->MEM_Header.MD_Alloc_End-pMemData->MEM_Header.MD_Alloc_Base+1) {
  195. Padding(2);
  196. _tprintf(TEXT("MEM : %08I64x-%08I64x\n"),pMemData->MEM_Header.MD_Alloc_Base,pMemData->MEM_Header.MD_Alloc_End);
  197. }
  198. break;
  199. }
  200. case ResType_IO: {
  201. PIO_RESOURCE pIoData = (PIO_RESOURCE)resDesData;
  202. if(pIoData->IO_Header.IOD_Alloc_End-pIoData->IO_Header.IOD_Alloc_Base+1) {
  203. Padding(2);
  204. _tprintf(TEXT("IO : %04I64x-%04I64x\n"),pIoData->IO_Header.IOD_Alloc_Base,pIoData->IO_Header.IOD_Alloc_End);
  205. }
  206. break;
  207. }
  208. case ResType_DMA: {
  209. PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)resDesData;
  210. Padding(2);
  211. _tprintf(TEXT("DMA : %u\n"),pDmaData->DMA_Header.DD_Alloc_Chan);
  212. break;
  213. }
  214. case ResType_IRQ: {
  215. PIRQ_RESOURCE pIrqData = (PIRQ_RESOURCE)resDesData;
  216. Padding(2);
  217. _tprintf(TEXT("IRQ : %u\n"),pIrqData->IRQ_Header.IRQD_Alloc_Num);
  218. break;
  219. }
  220. }
  221. delete [] resDesData;
  222. }
  223. if(prevResDes != Config) {
  224. CM_Free_Res_Des_Handle(prevResDes);
  225. }
  226. return TRUE;
  227. }
  228. BOOL DumpDeviceResources(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo)
  229. /*++
  230. Routine Description:
  231. Dump Resources to stdout
  232. Arguments:
  233. Devs )_ uniquely identify device
  234. DevInfo )
  235. Return Value:
  236. none
  237. --*/
  238. {
  239. SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
  240. ULONG status = 0;
  241. ULONG problem = 0;
  242. LOG_CONF config = 0;
  243. BOOL haveConfig = FALSE;
  244. //
  245. // see what state the device is in
  246. //
  247. devInfoListDetail.cbSize = sizeof(devInfoListDetail);
  248. if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) ||
  249. (CM_Get_DevNode_Status_Ex(&status,&problem,DevInfo->DevInst,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) {
  250. return FALSE;
  251. }
  252. //
  253. // see if the device is running and what resources it might be using
  254. //
  255. if(!(status & DN_HAS_PROBLEM)) {
  256. //
  257. // If this device is running, does this devinst have a ALLOC log config?
  258. //
  259. if (CM_Get_First_Log_Conf_Ex(&config,
  260. DevInfo->DevInst,
  261. ALLOC_LOG_CONF,
  262. devInfoListDetail.RemoteMachineHandle) == CR_SUCCESS) {
  263. haveConfig = TRUE;
  264. }
  265. }
  266. if(!haveConfig) {
  267. //
  268. // If no config so far, does it have a FORCED log config?
  269. // (note that technically these resources might be used by another device
  270. // but is useful info to show)
  271. //
  272. if (CM_Get_First_Log_Conf_Ex(&config,
  273. DevInfo->DevInst,
  274. FORCED_LOG_CONF,
  275. devInfoListDetail.RemoteMachineHandle) == CR_SUCCESS) {
  276. haveConfig = TRUE;
  277. }
  278. }
  279. if(!haveConfig) {
  280. //
  281. // if there's a hardware-disabled problem, boot-config isn't valid
  282. // otherwise use this if we don't have anything else
  283. //
  284. if(!(status & DN_HAS_PROBLEM) || (problem != CM_PROB_HARDWARE_DISABLED)) {
  285. //
  286. // Does it have a BOOT log config?
  287. //
  288. if (CM_Get_First_Log_Conf_Ex(&config,
  289. DevInfo->DevInst,
  290. BOOT_LOG_CONF,
  291. devInfoListDetail.RemoteMachineHandle) == CR_SUCCESS) {
  292. haveConfig = TRUE;
  293. }
  294. }
  295. }
  296. if(!haveConfig) {
  297. //
  298. // if we don't have any configuration, display an apropriate message
  299. //
  300. Padding(1);
  301. FormatToStream(stdout,(status & DN_STARTED) ? MSG_DUMP_NO_RESOURCES : MSG_DUMP_NO_RESERVED_RESOURCES );
  302. return TRUE;
  303. }
  304. Padding(1);
  305. FormatToStream(stdout,(status & DN_STARTED) ? MSG_DUMP_RESOURCES : MSG_DUMP_RESERVED_RESOURCES );
  306. //
  307. // dump resources
  308. //
  309. DumpDeviceResourcesOfType(DevInfo->DevInst,devInfoListDetail.RemoteMachineHandle,config,ResType_Mem);
  310. DumpDeviceResourcesOfType(DevInfo->DevInst,devInfoListDetail.RemoteMachineHandle,config,ResType_IO);
  311. DumpDeviceResourcesOfType(DevInfo->DevInst,devInfoListDetail.RemoteMachineHandle,config,ResType_DMA);
  312. DumpDeviceResourcesOfType(DevInfo->DevInst,devInfoListDetail.RemoteMachineHandle,config,ResType_IRQ);
  313. //
  314. // release handle
  315. //
  316. CM_Free_Log_Conf_Handle(config);
  317. return TRUE;
  318. }
  319. UINT DumpDeviceDriversCallback(PVOID Context,UINT Notification,UINT_PTR Param1,UINT_PTR Param2)
  320. /*++
  321. Routine Description:
  322. if Context provided, Simply count
  323. otherwise dump files indented 2
  324. Arguments:
  325. Context - DWORD Count
  326. Notification - SPFILENOTIFY_QUEUESCAN
  327. Param1 - scan
  328. Return Value:
  329. none
  330. --*/
  331. {
  332. LPDWORD count = (LPDWORD)Context;
  333. LPTSTR file = (LPTSTR)Param1;
  334. if(count) {
  335. count[0]++;
  336. } else {
  337. Padding(2);
  338. _tprintf(TEXT("%s\n"),file);
  339. }
  340. return NO_ERROR;
  341. }
  342. BOOL FindCurrentDriver(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo,PSP_DRVINFO_DATA DriverInfoData)
  343. /*++
  344. Routine Description:
  345. Find the driver that is associated with the current device
  346. We can do this either the quick way (available in WinXP)
  347. or the long way that works in Win2k.
  348. Arguments:
  349. Devs )_ uniquely identify device
  350. DevInfo )
  351. Return Value:
  352. TRUE if we managed to determine and select current driver
  353. --*/
  354. {
  355. SP_DEVINSTALL_PARAMS deviceInstallParams;
  356. WCHAR SectionName[LINE_LEN];
  357. WCHAR DrvDescription[LINE_LEN];
  358. WCHAR MfgName[LINE_LEN];
  359. WCHAR ProviderName[LINE_LEN];
  360. HKEY hKey = NULL;
  361. DWORD RegDataLength;
  362. DWORD RegDataType;
  363. DWORD c;
  364. BOOL match = FALSE;
  365. long regerr;
  366. ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams));
  367. deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  368. if(!SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) {
  369. return FALSE;
  370. }
  371. #ifdef DI_FLAGSEX_INSTALLEDDRIVER
  372. //
  373. // Set the flags that tell SetupDiBuildDriverInfoList to just put the
  374. // currently installed driver node in the list, and that it should allow
  375. // excluded drivers. This flag introduced in WinXP.
  376. //
  377. deviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
  378. if(SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) {
  379. //
  380. // we were able to specify this flag, so proceed the easy way
  381. // we should get a list of no more than 1 driver
  382. //
  383. if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) {
  384. return FALSE;
  385. }
  386. if (!SetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_CLASSDRIVER,
  387. 0, DriverInfoData)) {
  388. return FALSE;
  389. }
  390. //
  391. // we've selected the current driver
  392. //
  393. return TRUE;
  394. }
  395. deviceInstallParams.FlagsEx &= ~(DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
  396. #endif
  397. //
  398. // The following method works in Win2k, but it's slow and painful.
  399. //
  400. // First, get driver key - if it doesn't exist, no driver
  401. //
  402. hKey = SetupDiOpenDevRegKey(Devs,
  403. DevInfo,
  404. DICS_FLAG_GLOBAL,
  405. 0,
  406. DIREG_DRV,
  407. KEY_READ
  408. );
  409. if(hKey == INVALID_HANDLE_VALUE) {
  410. //
  411. // no such value exists, so there can't be an associated driver
  412. //
  413. RegCloseKey(hKey);
  414. return FALSE;
  415. }
  416. //
  417. // obtain path of INF - we'll do a search on this specific INF
  418. //
  419. RegDataLength = sizeof(deviceInstallParams.DriverPath); // bytes!!!
  420. regerr = RegQueryValueEx(hKey,
  421. REGSTR_VAL_INFPATH,
  422. NULL,
  423. &RegDataType,
  424. (PBYTE)deviceInstallParams.DriverPath,
  425. &RegDataLength
  426. );
  427. if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) {
  428. //
  429. // no such value exists, so no associated driver
  430. //
  431. RegCloseKey(hKey);
  432. return FALSE;
  433. }
  434. //
  435. // obtain name of Provider to fill into DriverInfoData
  436. //
  437. RegDataLength = sizeof(ProviderName); // bytes!!!
  438. regerr = RegQueryValueEx(hKey,
  439. REGSTR_VAL_PROVIDER_NAME,
  440. NULL,
  441. &RegDataType,
  442. (PBYTE)ProviderName,
  443. &RegDataLength
  444. );
  445. if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) {
  446. //
  447. // no such value exists, so we don't have a valid associated driver
  448. //
  449. RegCloseKey(hKey);
  450. return FALSE;
  451. }
  452. //
  453. // obtain name of section - for final verification
  454. //
  455. RegDataLength = sizeof(SectionName); // bytes!!!
  456. regerr = RegQueryValueEx(hKey,
  457. REGSTR_VAL_INFSECTION,
  458. NULL,
  459. &RegDataType,
  460. (PBYTE)SectionName,
  461. &RegDataLength
  462. );
  463. if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) {
  464. //
  465. // no such value exists, so we don't have a valid associated driver
  466. //
  467. RegCloseKey(hKey);
  468. return FALSE;
  469. }
  470. //
  471. // driver description (need not be same as device description)
  472. // - for final verification
  473. //
  474. RegDataLength = sizeof(DrvDescription); // bytes!!!
  475. regerr = RegQueryValueEx(hKey,
  476. REGSTR_VAL_DRVDESC,
  477. NULL,
  478. &RegDataType,
  479. (PBYTE)DrvDescription,
  480. &RegDataLength
  481. );
  482. RegCloseKey(hKey);
  483. if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) {
  484. //
  485. // no such value exists, so we don't have a valid associated driver
  486. //
  487. return FALSE;
  488. }
  489. //
  490. // Manufacturer (via SPDRP_MFG, don't access registry directly!)
  491. //
  492. if(!SetupDiGetDeviceRegistryProperty(Devs,
  493. DevInfo,
  494. SPDRP_MFG,
  495. NULL, // datatype is guaranteed to always be REG_SZ.
  496. (PBYTE)MfgName,
  497. sizeof(MfgName), // bytes!!!
  498. NULL)) {
  499. //
  500. // no such value exists, so we don't have a valid associated driver
  501. //
  502. return FALSE;
  503. }
  504. //
  505. // now search for drivers listed in the INF
  506. //
  507. //
  508. deviceInstallParams.Flags |= DI_ENUMSINGLEINF;
  509. deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
  510. if(!SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) {
  511. return FALSE;
  512. }
  513. if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) {
  514. return FALSE;
  515. }
  516. //
  517. // find the entry in the INF that was used to install the driver for
  518. // this device
  519. //
  520. for(c=0;SetupDiEnumDriverInfo(Devs,DevInfo,SPDIT_CLASSDRIVER,c,DriverInfoData);c++) {
  521. if((lstrcmp(DriverInfoData->MfgName,MfgName)==0)
  522. &&(lstrcmp(DriverInfoData->ProviderName,ProviderName)==0)) {
  523. //
  524. // these two fields match, try more detailed info
  525. // to ensure we have the exact driver entry used
  526. //
  527. SP_DRVINFO_DETAIL_DATA detail;
  528. detail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  529. if(!SetupDiGetDriverInfoDetail(Devs,DevInfo,DriverInfoData,&detail,sizeof(detail),NULL)
  530. && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
  531. continue;
  532. }
  533. if((lstrcmp(detail.SectionName,SectionName)==0) &&
  534. (lstrcmp(detail.DrvDescription,DrvDescription)==0)) {
  535. match = TRUE;
  536. break;
  537. }
  538. }
  539. }
  540. if(!match) {
  541. SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_CLASSDRIVER);
  542. }
  543. return match;
  544. }
  545. BOOL DumpDeviceDriverFiles(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo)
  546. /*++
  547. Routine Description:
  548. Dump information about what files were installed for driver package
  549. <tab>Installed using OEM123.INF section [abc.NT]
  550. <tab><tab>file...
  551. Arguments:
  552. Devs )_ uniquely identify device
  553. DevInfo )
  554. Return Value:
  555. none
  556. --*/
  557. {
  558. //
  559. // do this by 'searching' for the current driver
  560. // mimmicing a copy-only install to our own file queue
  561. // and then parsing that file queue
  562. //
  563. SP_DEVINSTALL_PARAMS deviceInstallParams;
  564. SP_DRVINFO_DATA driverInfoData;
  565. SP_DRVINFO_DETAIL_DATA driverInfoDetail;
  566. HSPFILEQ queueHandle = INVALID_HANDLE_VALUE;
  567. DWORD count;
  568. DWORD scanResult;
  569. BOOL success = FALSE;
  570. ZeroMemory(&driverInfoData,sizeof(driverInfoData));
  571. driverInfoData.cbSize = sizeof(driverInfoData);
  572. if(!FindCurrentDriver(Devs,DevInfo,&driverInfoData)) {
  573. Padding(1);
  574. FormatToStream(stdout, MSG_DUMP_NO_DRIVER);
  575. return FALSE;
  576. }
  577. //
  578. // get useful driver information
  579. //
  580. driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  581. if(!SetupDiGetDriverInfoDetail(Devs,DevInfo,&driverInfoData,&driverInfoDetail,sizeof(SP_DRVINFO_DETAIL_DATA),NULL) &&
  582. GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  583. //
  584. // no information about driver or section
  585. //
  586. goto final;
  587. }
  588. if(!driverInfoDetail.InfFileName[0] || !driverInfoDetail.SectionName[0]) {
  589. goto final;
  590. }
  591. //
  592. // pretend to do the file-copy part of a driver install
  593. // to determine what files are used
  594. // the specified driver must be selected as the active driver
  595. //
  596. if(!SetupDiSetSelectedDriver(Devs, DevInfo, &driverInfoData)) {
  597. goto final;
  598. }
  599. //
  600. // create a file queue so we can look at this queue later
  601. //
  602. queueHandle = SetupOpenFileQueue();
  603. if ( queueHandle == (HSPFILEQ)INVALID_HANDLE_VALUE ) {
  604. goto final;
  605. }
  606. //
  607. // modify flags to indicate we're providing our own queue
  608. //
  609. ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams));
  610. deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  611. if ( !SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams) ) {
  612. goto final;
  613. }
  614. //
  615. // we want to add the files to the file queue, not install them!
  616. //
  617. deviceInstallParams.FileQueue = queueHandle;
  618. deviceInstallParams.Flags |= DI_NOVCP;
  619. if ( !SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams) ) {
  620. goto final;
  621. }
  622. //
  623. // now fill queue with files that are to be installed
  624. // this involves all class/co-installers
  625. //
  626. if ( !SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, Devs, DevInfo) ) {
  627. goto final;
  628. }
  629. //
  630. // we now have a list of delete/rename/copy files
  631. // iterate the copy queue twice - 1st time to get # of files
  632. // 2nd time to get files
  633. // (WinXP has API to get # of files, but we want this to work
  634. // on Win2k too)
  635. //
  636. count = 0;
  637. scanResult = 0;
  638. //
  639. // call once to count
  640. //
  641. SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,&count,&scanResult);
  642. Padding(1);
  643. FormatToStream(stdout, count ? MSG_DUMP_DRIVER_FILES : MSG_DUMP_NO_DRIVER_FILES, count, driverInfoDetail.InfFileName, driverInfoDetail.SectionName);
  644. //
  645. // call again to dump the files
  646. //
  647. SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,NULL,&scanResult);
  648. success = TRUE;
  649. final:
  650. SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_CLASSDRIVER);
  651. if ( queueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE ) {
  652. SetupCloseFileQueue(queueHandle);
  653. }
  654. if(!success) {
  655. Padding(1);
  656. FormatToStream(stdout, MSG_DUMP_NO_DRIVER);
  657. }
  658. return success;
  659. }
  660. BOOL DumpArray(int pad,LPTSTR * IDs)
  661. /*++
  662. Routine Description:
  663. Iterate array and dump entries to screen
  664. Arguments:
  665. Devs )_ uniquely identify device
  666. DevInfo )
  667. Return Value:
  668. none
  669. --*/
  670. {
  671. if(!IDs || !IDs[0]) {
  672. return FALSE;
  673. }
  674. while(IDs[0]) {
  675. Padding(pad);
  676. _tprintf(TEXT("%s\n"),IDs[0]);
  677. IDs++;
  678. }
  679. return TRUE;
  680. }
  681. BOOL DumpDeviceHwIds(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo)
  682. /*++
  683. Routine Description:
  684. Write device instance & description to stdout
  685. <tab>Hardware ID's
  686. <tab><tab>ID
  687. ...
  688. <tab>Compatible ID's
  689. <tab><tab>ID
  690. ...
  691. or
  692. <tab>No Hardware ID's for device
  693. Arguments:
  694. Devs )_ uniquely identify device
  695. DevInfo )
  696. Return Value:
  697. none
  698. --*/
  699. {
  700. LPTSTR * hwIdArray = GetDevMultiSz(Devs,DevInfo,SPDRP_HARDWAREID);
  701. LPTSTR * compatIdArray = GetDevMultiSz(Devs,DevInfo,SPDRP_COMPATIBLEIDS);
  702. BOOL displayed = FALSE;
  703. if(hwIdArray && hwIdArray[0]) {
  704. displayed = TRUE;
  705. Padding(1);
  706. FormatToStream(stdout, MSG_DUMP_HWIDS);
  707. DumpArray(2,hwIdArray);
  708. }
  709. if(compatIdArray && compatIdArray[0]) {
  710. displayed = TRUE;
  711. Padding(1);
  712. FormatToStream(stdout, MSG_DUMP_COMPATIDS);
  713. DumpArray(2,compatIdArray);
  714. }
  715. if(!displayed) {
  716. Padding(1);
  717. FormatToStream(stdout, MSG_DUMP_NO_HWIDS);
  718. }
  719. DelMultiSz(hwIdArray);
  720. DelMultiSz(compatIdArray);
  721. return TRUE;
  722. }
  723. BOOL DumpDeviceDriverNodes(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo)
  724. /*++
  725. Routine Description:
  726. Write device instance & description to stdout
  727. <tab>Installed using OEM123.INF section [abc.NT]
  728. <tab><tab>file...
  729. Arguments:
  730. Devs )_ uniquely identify device
  731. DevInfo )
  732. Return Value:
  733. none
  734. --*/
  735. {
  736. BOOL success = FALSE;
  737. SP_DEVINSTALL_PARAMS deviceInstallParams;
  738. SP_DRVINFO_DATA driverInfoData;
  739. SP_DRVINFO_DETAIL_DATA driverInfoDetail;
  740. SP_DRVINSTALL_PARAMS driverInstallParams;
  741. DWORD index;
  742. SYSTEMTIME SystemTime;
  743. ULARGE_INTEGER Version;
  744. TCHAR Buffer[MAX_PATH];
  745. ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams));
  746. ZeroMemory(&driverInfoData, sizeof(driverInfoData));
  747. driverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  748. deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  749. if(!SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) {
  750. return FALSE;
  751. }
  752. //
  753. // Set the flags that tell SetupDiBuildDriverInfoList to allow excluded drivers.
  754. //
  755. deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
  756. if(!SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) {
  757. return FALSE;
  758. }
  759. //
  760. // Now build a class driver list.
  761. //
  762. if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_COMPATDRIVER)) {
  763. goto final2;
  764. }
  765. //
  766. // Enumerate all of the drivernodes.
  767. //
  768. index = 0;
  769. while(SetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_COMPATDRIVER,
  770. index, &driverInfoData)) {
  771. success = TRUE;
  772. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_HEADER,index);
  773. //
  774. // get useful driver information
  775. //
  776. driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  777. if(SetupDiGetDriverInfoDetail(Devs,DevInfo,&driverInfoData,&driverInfoDetail,sizeof(SP_DRVINFO_DETAIL_DATA),NULL) ||
  778. GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  779. Padding(1);
  780. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_INF,driverInfoDetail.InfFileName);
  781. Padding(1);
  782. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_SECTION,driverInfoDetail.SectionName);
  783. }
  784. Padding(1);
  785. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_DESCRIPTION,driverInfoData.Description);
  786. Padding(1);
  787. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_MFGNAME,driverInfoData.MfgName);
  788. Padding(1);
  789. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_PROVIDERNAME,driverInfoData.ProviderName);
  790. if (FileTimeToSystemTime(&driverInfoData.DriverDate, &SystemTime)) {
  791. if (GetDateFormat(LOCALE_USER_DEFAULT,
  792. DATE_SHORTDATE,
  793. &SystemTime,
  794. NULL,
  795. Buffer,
  796. sizeof(Buffer)/sizeof(TCHAR)
  797. ) != 0) {
  798. Padding(1);
  799. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_DRIVERDATE,Buffer);
  800. }
  801. }
  802. Version.QuadPart = driverInfoData.DriverVersion;
  803. Padding(1);
  804. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_DRIVERVERSION,
  805. HIWORD(Version.HighPart),
  806. LOWORD(Version.HighPart),
  807. HIWORD(Version.LowPart),
  808. LOWORD(Version.LowPart)
  809. );
  810. driverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
  811. if(SetupDiGetDriverInstallParams(Devs,DevInfo,&driverInfoData,&driverInstallParams)) {
  812. Padding(1);
  813. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_RANK,driverInstallParams.Rank);
  814. Padding(1);
  815. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS,driverInstallParams.Flags);
  816. //
  817. // Interesting flags to dump
  818. //
  819. if (driverInstallParams.Flags & DNF_OLD_INET_DRIVER) {
  820. Padding(2);
  821. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_OLD_INET_DRIVER);
  822. }
  823. if (driverInstallParams.Flags & DNF_BAD_DRIVER) {
  824. Padding(2);
  825. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_BAD_DRIVER);
  826. }
  827. #if defined(DNF_INF_IS_SIGNED)
  828. //
  829. // DNF_INF_IS_SIGNED is only available since WinXP
  830. //
  831. if (driverInstallParams.Flags & DNF_INF_IS_SIGNED) {
  832. Padding(2);
  833. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_INF_IS_SIGNED);
  834. }
  835. #endif
  836. #if defined(DNF_OEM_F6_INF)
  837. //
  838. // DNF_OEM_F6_INF is only available since WinXP
  839. //
  840. if (driverInstallParams.Flags & DNF_OEM_F6_INF) {
  841. Padding(2);
  842. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_OEM_F6_INF);
  843. }
  844. #endif
  845. #if defined(DNF_BASIC_DRIVER)
  846. //
  847. // DNF_BASIC_DRIVER is only available since WinXP
  848. //
  849. if (driverInstallParams.Flags & DNF_BASIC_DRIVER) {
  850. Padding(2);
  851. FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_BASIC_DRIVER);
  852. }
  853. #endif
  854. }
  855. index++;
  856. }
  857. SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_COMPATDRIVER);
  858. final2:
  859. if(!success) {
  860. Padding(1);
  861. FormatToStream(stdout, MSG_DUMP_NO_DRIVERNODES);
  862. }
  863. return success;
  864. }
  865. BOOL DumpDeviceStack(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo)
  866. /*++
  867. Routine Description:
  868. Write expected stack information to stdout
  869. Arguments:
  870. Devs )_ uniquely identify device
  871. DevInfo )
  872. Return Value:
  873. TRUE if success
  874. --*/
  875. {
  876. LPTSTR * filters;
  877. LPTSTR service;
  878. HKEY hClassKey = (HKEY)INVALID_HANDLE_VALUE;
  879. SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
  880. //
  881. // we need machine information
  882. //
  883. devInfoListDetail.cbSize = sizeof(devInfoListDetail);
  884. if(!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) {
  885. return FALSE;
  886. }
  887. //
  888. // we need device setup class, we can use the GUID in DevInfo
  889. // note that this GUID is a snapshot, but works fine
  890. // if DevInfo isn't old
  891. //
  892. //
  893. // class upper/lower filters are in class registry
  894. //
  895. hClassKey = SetupDiOpenClassRegKeyEx(&DevInfo->ClassGuid,
  896. KEY_READ,
  897. DIOCR_INSTALLER,
  898. devInfoListDetail.RemoteMachineName[0] ? devInfoListDetail.RemoteMachineName : NULL,
  899. NULL);
  900. if(hClassKey != INVALID_HANDLE_VALUE) {
  901. //
  902. // dump upper class filters if available
  903. //
  904. filters = GetRegMultiSz(hClassKey,REGSTR_VAL_UPPERFILTERS);
  905. if(filters) {
  906. if(filters[0]) {
  907. Padding(1);
  908. FormatToStream(stdout,MSG_DUMP_DEVICESTACK_UPPERCLASSFILTERS);
  909. DumpArray(2,filters);
  910. }
  911. DelMultiSz(filters);
  912. }
  913. }
  914. filters = GetDevMultiSz(Devs,DevInfo,SPDRP_UPPERFILTERS);
  915. if(filters) {
  916. if(filters[0]) {
  917. //
  918. // dump upper device filters
  919. //
  920. Padding(1);
  921. FormatToStream(stdout,MSG_DUMP_DEVICESTACK_UPPERFILTERS);
  922. DumpArray(2,filters);
  923. }
  924. DelMultiSz(filters);
  925. }
  926. service = GetDeviceStringProperty(Devs,DevInfo,SPDRP_SERVICE);
  927. Padding(1);
  928. FormatToStream(stdout,MSG_DUMP_DEVICESTACK_SERVICE);
  929. if(service && service[0]) {
  930. //
  931. // dump service
  932. //
  933. Padding(2);
  934. _tprintf(TEXT("%s\n"),service);
  935. } else {
  936. //
  937. // dump the fact that there's no service
  938. //
  939. Padding(2);
  940. FormatToStream(stdout,MSG_DUMP_DEVICESTACK_NOSERVICE);
  941. }
  942. if(service) {
  943. delete [] service;
  944. }
  945. if(hClassKey != INVALID_HANDLE_VALUE) {
  946. filters = GetRegMultiSz(hClassKey,REGSTR_VAL_LOWERFILTERS);
  947. if(filters) {
  948. if(filters[0]) {
  949. //
  950. // lower class filters
  951. //
  952. Padding(1);
  953. FormatToStream(stdout,MSG_DUMP_DEVICESTACK_LOWERCLASSFILTERS);
  954. DumpArray(2,filters);
  955. }
  956. DelMultiSz(filters);
  957. }
  958. RegCloseKey(hClassKey);
  959. }
  960. filters = GetDevMultiSz(Devs,DevInfo,SPDRP_LOWERFILTERS);
  961. if(filters) {
  962. if(filters[0]) {
  963. //
  964. // lower device filters
  965. //
  966. Padding(1);
  967. FormatToStream(stdout,MSG_DUMP_DEVICESTACK_LOWERFILTERS);
  968. DumpArray(2,filters);
  969. }
  970. DelMultiSz(filters);
  971. }
  972. return TRUE;
  973. }