|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
dump.cpp
Abstract:
Device Console dump information out about a particular device
@@BEGIN_DDKSPLIT Author:
Jamie Hunter (JamieHun) Nov-30-2000
Revision History:
@@END_DDKSPLIT --*/
#include "devcon.h"
BOOL DumpDeviceWithInfo(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo,LPCTSTR Info) /*++
Routine Description:
Write device instance & info to stdout
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
none
--*/ { TCHAR devID[MAX_DEVICE_ID_LEN]; LPTSTR desc; BOOL b = TRUE; SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
devInfoListDetail.cbSize = sizeof(devInfoListDetail); if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) || (CM_Get_Device_ID_Ex(DevInfo->DevInst,devID,MAX_DEVICE_ID_LEN,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) { lstrcpy(devID,TEXT("?")); b = FALSE; }
if(Info) { _tprintf(TEXT("%-60s: %s\n"),devID,Info); } else { _tprintf(TEXT("%s\n"),devID); } return b; }
BOOL DumpDevice(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++
Routine Description:
Write device instance & description to stdout
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
TRUE if success
--*/ { LPTSTR desc; BOOL b;
desc = GetDeviceDescription(Devs,DevInfo); b = DumpDeviceWithInfo(Devs,DevInfo,desc); if(desc) { delete [] desc; } return b; }
BOOL DumpDeviceDescr(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++
Routine Description:
Write device description to stdout
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
TRUE if success
--*/ { LPTSTR desc; BOOL b;
desc = GetDeviceDescription(Devs,DevInfo); if(!desc) { return FALSE; } Padding(1); FormatToStream(stdout,MSG_DUMP_DESCRIPTION,desc); delete [] desc; return TRUE; }
BOOL DumpDeviceClass(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++
Routine Description:
Write device class information to stdout
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
TRUE if success
--*/ { LPTSTR cls; LPTSTR guid;
Padding(1); cls = GetDeviceStringProperty(Devs,DevInfo,SPDRP_CLASS); guid = GetDeviceStringProperty(Devs,DevInfo,SPDRP_CLASSGUID); if(!cls && !guid) { FormatToStream(stdout, MSG_DUMP_NOSETUPCLASS ); } else { FormatToStream(stdout, MSG_DUMP_SETUPCLASS, guid ? guid : TEXT("{}"), cls ? cls : TEXT("(?)") ); }
if(cls) { delete [] cls; } if(guid) { delete [] guid; }
return TRUE; }
BOOL DumpDeviceStatus(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++
Routine Description:
Write device status to stdout
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
none
--*/ { SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; ULONG status = 0; ULONG problem = 0; BOOL hasInfo = FALSE;
devInfoListDetail.cbSize = sizeof(devInfoListDetail); if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) || (CM_Get_DevNode_Status_Ex(&status,&problem,DevInfo->DevInst,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) { return FALSE; } //
// handle off the status/problem codes
//
if((status & DN_HAS_PROBLEM) && problem == CM_PROB_DISABLED) { hasInfo = TRUE; Padding(1); FormatToStream(stdout,MSG_DUMP_DISABLED); return TRUE; } if(status & DN_HAS_PROBLEM) { hasInfo = TRUE; Padding(1); FormatToStream(stdout,MSG_DUMP_PROBLEM,problem); } if(status & DN_PRIVATE_PROBLEM) { hasInfo = TRUE; Padding(1); FormatToStream(stdout,MSG_DUMP_PRIVATE_PROBLEM); } if(status & DN_STARTED) { Padding(1); FormatToStream(stdout,MSG_DUMP_STARTED); } else if (!hasInfo) { Padding(1); FormatToStream(stdout,MSG_DUMP_NOTSTARTED); } return TRUE; }
BOOL DumpDeviceResourcesOfType(DEVINST DevInst,HMACHINE MachineHandle,LOG_CONF Config,RESOURCEID ReqResId) { RES_DES prevResDes = (RES_DES)Config; RES_DES resDes = 0; RESOURCEID resId = ReqResId; ULONG dataSize; PBYTE resDesData; while(CM_Get_Next_Res_Des_Ex(&resDes,prevResDes,ReqResId,&resId,0,MachineHandle)==CR_SUCCESS) { if(prevResDes != Config) { CM_Free_Res_Des_Handle(prevResDes); } prevResDes = resDes; if(CM_Get_Res_Des_Data_Size_Ex(&dataSize,resDes,0,MachineHandle)!=CR_SUCCESS) { continue; } resDesData = new BYTE[dataSize]; if(!resDesData) { continue; } if(CM_Get_Res_Des_Data_Ex(resDes,resDesData,dataSize,0,MachineHandle)!=CR_SUCCESS) { delete [] resDesData; continue; } switch(resId) { case ResType_Mem: {
PMEM_RESOURCE pMemData = (PMEM_RESOURCE)resDesData; if(pMemData->MEM_Header.MD_Alloc_End-pMemData->MEM_Header.MD_Alloc_Base+1) { Padding(2); _tprintf(TEXT("MEM : %08I64x-%08I64x\n"),pMemData->MEM_Header.MD_Alloc_Base,pMemData->MEM_Header.MD_Alloc_End); } break; }
case ResType_IO: {
PIO_RESOURCE pIoData = (PIO_RESOURCE)resDesData; if(pIoData->IO_Header.IOD_Alloc_End-pIoData->IO_Header.IOD_Alloc_Base+1) { Padding(2); _tprintf(TEXT("IO : %04I64x-%04I64x\n"),pIoData->IO_Header.IOD_Alloc_Base,pIoData->IO_Header.IOD_Alloc_End); } break; }
case ResType_DMA: {
PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)resDesData; Padding(2); _tprintf(TEXT("DMA : %u\n"),pDmaData->DMA_Header.DD_Alloc_Chan); break; }
case ResType_IRQ: {
PIRQ_RESOURCE pIrqData = (PIRQ_RESOURCE)resDesData;
Padding(2); _tprintf(TEXT("IRQ : %u\n"),pIrqData->IRQ_Header.IRQD_Alloc_Num); break; } } delete [] resDesData; } if(prevResDes != Config) { CM_Free_Res_Des_Handle(prevResDes); } return TRUE; }
BOOL DumpDeviceResources(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++
Routine Description:
Dump Resources to stdout
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
none
--*/ { SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; ULONG status = 0; ULONG problem = 0; LOG_CONF config = 0; BOOL haveConfig = FALSE;
//
// see what state the device is in
//
devInfoListDetail.cbSize = sizeof(devInfoListDetail); if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) || (CM_Get_DevNode_Status_Ex(&status,&problem,DevInfo->DevInst,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) { return FALSE; }
//
// see if the device is running and what resources it might be using
//
if(!(status & DN_HAS_PROBLEM)) { //
// If this device is running, does this devinst have a ALLOC log config?
//
if (CM_Get_First_Log_Conf_Ex(&config, DevInfo->DevInst, ALLOC_LOG_CONF, devInfoListDetail.RemoteMachineHandle) == CR_SUCCESS) { haveConfig = TRUE; } } if(!haveConfig) { //
// If no config so far, does it have a FORCED log config?
// (note that technically these resources might be used by another device
// but is useful info to show)
//
if (CM_Get_First_Log_Conf_Ex(&config, DevInfo->DevInst, FORCED_LOG_CONF, devInfoListDetail.RemoteMachineHandle) == CR_SUCCESS) { haveConfig = TRUE; } }
if(!haveConfig) { //
// if there's a hardware-disabled problem, boot-config isn't valid
// otherwise use this if we don't have anything else
//
if(!(status & DN_HAS_PROBLEM) || (problem != CM_PROB_HARDWARE_DISABLED)) { //
// Does it have a BOOT log config?
//
if (CM_Get_First_Log_Conf_Ex(&config, DevInfo->DevInst, BOOT_LOG_CONF, devInfoListDetail.RemoteMachineHandle) == CR_SUCCESS) { haveConfig = TRUE; } } }
if(!haveConfig) { //
// if we don't have any configuration, display an apropriate message
//
Padding(1); FormatToStream(stdout,(status & DN_STARTED) ? MSG_DUMP_NO_RESOURCES : MSG_DUMP_NO_RESERVED_RESOURCES ); return TRUE; } Padding(1); FormatToStream(stdout,(status & DN_STARTED) ? MSG_DUMP_RESOURCES : MSG_DUMP_RESERVED_RESOURCES );
//
// dump resources
//
DumpDeviceResourcesOfType(DevInfo->DevInst,devInfoListDetail.RemoteMachineHandle,config,ResType_Mem); DumpDeviceResourcesOfType(DevInfo->DevInst,devInfoListDetail.RemoteMachineHandle,config,ResType_IO); DumpDeviceResourcesOfType(DevInfo->DevInst,devInfoListDetail.RemoteMachineHandle,config,ResType_DMA); DumpDeviceResourcesOfType(DevInfo->DevInst,devInfoListDetail.RemoteMachineHandle,config,ResType_IRQ);
//
// release handle
//
CM_Free_Log_Conf_Handle(config);
return TRUE; }
UINT DumpDeviceDriversCallback(PVOID Context,UINT Notification,UINT_PTR Param1,UINT_PTR Param2) /*++
Routine Description:
if Context provided, Simply count otherwise dump files indented 2
Arguments:
Context - DWORD Count Notification - SPFILENOTIFY_QUEUESCAN Param1 - scan
Return Value:
none
--*/ { LPDWORD count = (LPDWORD)Context; LPTSTR file = (LPTSTR)Param1; if(count) { count[0]++; } else { Padding(2); _tprintf(TEXT("%s\n"),file); }
return NO_ERROR; }
BOOL FindCurrentDriver(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo,PSP_DRVINFO_DATA DriverInfoData) /*++
Routine Description:
Find the driver that is associated with the current device We can do this either the quick way (available in WinXP) or the long way that works in Win2k.
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
TRUE if we managed to determine and select current driver
--*/ { SP_DEVINSTALL_PARAMS deviceInstallParams; WCHAR SectionName[LINE_LEN]; WCHAR DrvDescription[LINE_LEN]; WCHAR MfgName[LINE_LEN]; WCHAR ProviderName[LINE_LEN]; HKEY hKey = NULL; DWORD RegDataLength; DWORD RegDataType; DWORD c; BOOL match = FALSE; long regerr;
ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams)); deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if(!SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { return FALSE; }
#ifdef DI_FLAGSEX_INSTALLEDDRIVER
//
// Set the flags that tell SetupDiBuildDriverInfoList to just put the
// currently installed driver node in the list, and that it should allow
// excluded drivers. This flag introduced in WinXP.
//
deviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
if(SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { //
// we were able to specify this flag, so proceed the easy way
// we should get a list of no more than 1 driver
//
if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) { return FALSE; } if (!SetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_CLASSDRIVER, 0, DriverInfoData)) { return FALSE; } //
// we've selected the current driver
//
return TRUE; } deviceInstallParams.FlagsEx &= ~(DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS); #endif
//
// The following method works in Win2k, but it's slow and painful.
//
// First, get driver key - if it doesn't exist, no driver
//
hKey = SetupDiOpenDevRegKey(Devs, DevInfo, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ );
if(hKey == INVALID_HANDLE_VALUE) { //
// no such value exists, so there can't be an associated driver
//
RegCloseKey(hKey); return FALSE; }
//
// obtain path of INF - we'll do a search on this specific INF
//
RegDataLength = sizeof(deviceInstallParams.DriverPath); // bytes!!!
regerr = RegQueryValueEx(hKey, REGSTR_VAL_INFPATH, NULL, &RegDataType, (PBYTE)deviceInstallParams.DriverPath, &RegDataLength );
if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) { //
// no such value exists, so no associated driver
//
RegCloseKey(hKey); return FALSE; }
//
// obtain name of Provider to fill into DriverInfoData
//
RegDataLength = sizeof(ProviderName); // bytes!!!
regerr = RegQueryValueEx(hKey, REGSTR_VAL_PROVIDER_NAME, NULL, &RegDataType, (PBYTE)ProviderName, &RegDataLength );
if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) { //
// no such value exists, so we don't have a valid associated driver
//
RegCloseKey(hKey); return FALSE; }
//
// obtain name of section - for final verification
//
RegDataLength = sizeof(SectionName); // bytes!!!
regerr = RegQueryValueEx(hKey, REGSTR_VAL_INFSECTION, NULL, &RegDataType, (PBYTE)SectionName, &RegDataLength );
if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) { //
// no such value exists, so we don't have a valid associated driver
//
RegCloseKey(hKey); return FALSE; }
//
// driver description (need not be same as device description)
// - for final verification
//
RegDataLength = sizeof(DrvDescription); // bytes!!!
regerr = RegQueryValueEx(hKey, REGSTR_VAL_DRVDESC, NULL, &RegDataType, (PBYTE)DrvDescription, &RegDataLength );
RegCloseKey(hKey);
if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) { //
// no such value exists, so we don't have a valid associated driver
//
return FALSE; }
//
// Manufacturer (via SPDRP_MFG, don't access registry directly!)
//
if(!SetupDiGetDeviceRegistryProperty(Devs, DevInfo, SPDRP_MFG, NULL, // datatype is guaranteed to always be REG_SZ.
(PBYTE)MfgName, sizeof(MfgName), // bytes!!!
NULL)) { //
// no such value exists, so we don't have a valid associated driver
//
return FALSE; }
//
// now search for drivers listed in the INF
//
//
deviceInstallParams.Flags |= DI_ENUMSINGLEINF; deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
if(!SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { return FALSE; } if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) { return FALSE; }
//
// find the entry in the INF that was used to install the driver for
// this device
//
for(c=0;SetupDiEnumDriverInfo(Devs,DevInfo,SPDIT_CLASSDRIVER,c,DriverInfoData);c++) { if((_tcscmp(DriverInfoData->MfgName,MfgName)==0) &&(_tcscmp(DriverInfoData->ProviderName,ProviderName)==0)) { //
// these two fields match, try more detailed info
// to ensure we have the exact driver entry used
//
SP_DRVINFO_DETAIL_DATA detail; detail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); if(!SetupDiGetDriverInfoDetail(Devs,DevInfo,DriverInfoData,&detail,sizeof(detail),NULL) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { continue; } if((_tcscmp(detail.SectionName,SectionName)==0) && (_tcscmp(detail.DrvDescription,DrvDescription)==0)) { match = TRUE; break; } } } if(!match) { SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_CLASSDRIVER); } return match; }
BOOL DumpDeviceDriverFiles(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++
Routine Description:
Dump information about what files were installed for driver package <tab>Installed using OEM123.INF section [abc.NT] <tab><tab>file...
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
none
--*/ { //
// do this by 'searching' for the current driver
// mimmicing a copy-only install to our own file queue
// and then parsing that file queue
//
SP_DEVINSTALL_PARAMS deviceInstallParams; SP_DRVINFO_DATA driverInfoData; SP_DRVINFO_DETAIL_DATA driverInfoDetail; HSPFILEQ queueHandle = INVALID_HANDLE_VALUE; DWORD count; DWORD scanResult; BOOL success = FALSE;
ZeroMemory(&driverInfoData,sizeof(driverInfoData)); driverInfoData.cbSize = sizeof(driverInfoData);
if(!FindCurrentDriver(Devs,DevInfo,&driverInfoData)) { Padding(1); FormatToStream(stdout, MSG_DUMP_NO_DRIVER); return FALSE; }
//
// get useful driver information
//
driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); if(!SetupDiGetDriverInfoDetail(Devs,DevInfo,&driverInfoData,&driverInfoDetail,sizeof(SP_DRVINFO_DETAIL_DATA),NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { //
// no information about driver or section
//
goto final; } if(!driverInfoDetail.InfFileName[0] || !driverInfoDetail.SectionName[0]) { goto final; }
//
// pretend to do the file-copy part of a driver install
// to determine what files are used
// the specified driver must be selected as the active driver
//
if(!SetupDiSetSelectedDriver(Devs, DevInfo, &driverInfoData)) { goto final; }
//
// create a file queue so we can look at this queue later
//
queueHandle = SetupOpenFileQueue();
if ( queueHandle == (HSPFILEQ)INVALID_HANDLE_VALUE ) { goto final; }
//
// modify flags to indicate we're providing our own queue
//
ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams)); deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if ( !SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams) ) { goto final; }
//
// we want to add the files to the file queue, not install them!
//
deviceInstallParams.FileQueue = queueHandle; deviceInstallParams.Flags |= DI_NOVCP;
if ( !SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams) ) { goto final; }
//
// now fill queue with files that are to be installed
// this involves all class/co-installers
//
if ( !SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, Devs, DevInfo) ) { goto final; }
//
// we now have a list of delete/rename/copy files
// iterate the copy queue twice - 1st time to get # of files
// 2nd time to get files
// (WinXP has API to get # of files, but we want this to work
// on Win2k too)
//
count = 0; scanResult = 0; //
// call once to count
//
SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,&count,&scanResult); Padding(1); FormatToStream(stdout, count ? MSG_DUMP_DRIVER_FILES : MSG_DUMP_NO_DRIVER_FILES, count, driverInfoDetail.InfFileName, driverInfoDetail.SectionName); //
// call again to dump the files
//
SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,NULL,&scanResult);
success = TRUE;
final:
SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_CLASSDRIVER);
if ( queueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE ) { SetupCloseFileQueue(queueHandle); }
if(!success) { Padding(1); FormatToStream(stdout, MSG_DUMP_NO_DRIVER); }
return success;
}
BOOL DumpArray(int pad,LPTSTR * Array) /*++
Routine Description:
Iterate array and dump entries to screen
Arguments:
pad - padding Array - array to dump
Return Value:
none
--*/ { if(!Array || !Array[0]) { return FALSE; } while(Array[0]) { Padding(pad); _tprintf(TEXT("%s\n"),Array[0]); Array++; } return TRUE; }
BOOL DumpDeviceHwIds(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++
Routine Description:
Write device instance & description to stdout <tab>Hardware ID's <tab><tab>ID ... <tab>Compatible ID's <tab><tab>ID ... or <tab>No Hardware ID's for device
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
none
--*/ { LPTSTR * hwIdArray = GetDevMultiSz(Devs,DevInfo,SPDRP_HARDWAREID); LPTSTR * compatIdArray = GetDevMultiSz(Devs,DevInfo,SPDRP_COMPATIBLEIDS); BOOL displayed = FALSE;
if(hwIdArray && hwIdArray[0]) { displayed = TRUE; Padding(1); FormatToStream(stdout, MSG_DUMP_HWIDS); DumpArray(2,hwIdArray); } if(compatIdArray && compatIdArray[0]) { displayed = TRUE; Padding(1); FormatToStream(stdout, MSG_DUMP_COMPATIDS); DumpArray(2,compatIdArray); } if(!displayed) { Padding(1); FormatToStream(stdout, MSG_DUMP_NO_HWIDS); }
DelMultiSz(hwIdArray); DelMultiSz(compatIdArray);
return TRUE; }
BOOL DumpDeviceDriverNodes(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++
Routine Description:
Write device instance & description to stdout <tab>Installed using OEM123.INF section [abc.NT] <tab><tab>file...
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
none
--*/ { BOOL success = FALSE; SP_DEVINSTALL_PARAMS deviceInstallParams; SP_DRVINFO_DATA driverInfoData; SP_DRVINFO_DETAIL_DATA driverInfoDetail; SP_DRVINSTALL_PARAMS driverInstallParams; DWORD index; SYSTEMTIME SystemTime; ULARGE_INTEGER Version; TCHAR Buffer[MAX_PATH];
ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams)); ZeroMemory(&driverInfoData, sizeof(driverInfoData));
driverInfoData.cbSize = sizeof(SP_DRVINFO_DATA); deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if(!SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { return FALSE; }
//
// Set the flags that tell SetupDiBuildDriverInfoList to allow excluded drivers.
//
deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
if(!SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { return FALSE; }
//
// Now build a class driver list.
//
if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_COMPATDRIVER)) { goto final2; }
//
// Enumerate all of the drivernodes.
//
index = 0; while(SetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_COMPATDRIVER, index, &driverInfoData)) {
success = TRUE;
FormatToStream(stdout,MSG_DUMP_DRIVERNODE_HEADER,index);
//
// get useful driver information
//
driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); if(SetupDiGetDriverInfoDetail(Devs,DevInfo,&driverInfoData,&driverInfoDetail,sizeof(SP_DRVINFO_DETAIL_DATA),NULL) || GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
Padding(1); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_INF,driverInfoDetail.InfFileName); Padding(1); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_SECTION,driverInfoDetail.SectionName); }
Padding(1); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_DESCRIPTION,driverInfoData.Description); Padding(1); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_MFGNAME,driverInfoData.MfgName); Padding(1); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_PROVIDERNAME,driverInfoData.ProviderName);
if (FileTimeToSystemTime(&driverInfoData.DriverDate, &SystemTime)) { if (GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &SystemTime, NULL, Buffer, sizeof(Buffer)/sizeof(TCHAR) ) != 0) { Padding(1); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_DRIVERDATE,Buffer); } }
Version.QuadPart = driverInfoData.DriverVersion; Padding(1); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_DRIVERVERSION, HIWORD(Version.HighPart), LOWORD(Version.HighPart), HIWORD(Version.LowPart), LOWORD(Version.LowPart) );
driverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS); if(SetupDiGetDriverInstallParams(Devs,DevInfo,&driverInfoData,&driverInstallParams)) { Padding(1); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_RANK,driverInstallParams.Rank); Padding(1); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS,driverInstallParams.Flags);
//
// Interesting flags to dump
//
if (driverInstallParams.Flags & DNF_OLD_INET_DRIVER) { Padding(2); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_OLD_INET_DRIVER); } if (driverInstallParams.Flags & DNF_BAD_DRIVER) { Padding(2); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_BAD_DRIVER); } #if defined(DNF_INF_IS_SIGNED)
//
// DNF_INF_IS_SIGNED is only available since WinXP
//
if (driverInstallParams.Flags & DNF_INF_IS_SIGNED) { Padding(2); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_INF_IS_SIGNED); } #endif
#if defined(DNF_OEM_F6_INF)
//
// DNF_OEM_F6_INF is only available since WinXP
//
if (driverInstallParams.Flags & DNF_OEM_F6_INF) { Padding(2); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_OEM_F6_INF); } #endif
#if defined(DNF_BASIC_DRIVER)
//
// DNF_BASIC_DRIVER is only available since WinXP
//
if (driverInstallParams.Flags & DNF_BASIC_DRIVER) { Padding(2); FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_BASIC_DRIVER); } #endif
}
index++; }
SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_COMPATDRIVER);
final2:
if(!success) { Padding(1); FormatToStream(stdout, MSG_DUMP_NO_DRIVERNODES); }
return success;
}
BOOL DumpDeviceStack(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++
Routine Description:
Write expected stack information to stdout
Arguments:
Devs )_ uniquely identify device DevInfo )
Return Value:
TRUE if success
--*/ { LPTSTR * filters; LPTSTR service; HKEY hClassKey = (HKEY)INVALID_HANDLE_VALUE; SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
//
// we need machine information
//
devInfoListDetail.cbSize = sizeof(devInfoListDetail); if(!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) { return FALSE; }
//
// we need device setup class, we can use the GUID in DevInfo
// note that this GUID is a snapshot, but works fine
// if DevInfo isn't old
//
//
// class upper/lower filters are in class registry
//
hClassKey = SetupDiOpenClassRegKeyEx(&DevInfo->ClassGuid, KEY_READ, DIOCR_INSTALLER, devInfoListDetail.RemoteMachineName[0] ? devInfoListDetail.RemoteMachineName : NULL, NULL);
if(hClassKey != INVALID_HANDLE_VALUE) { //
// dump upper class filters if available
//
filters = GetRegMultiSz(hClassKey,REGSTR_VAL_UPPERFILTERS); if(filters) { if(filters[0]) { Padding(1); FormatToStream(stdout,MSG_DUMP_DEVICESTACK_UPPERCLASSFILTERS); DumpArray(2,filters); } DelMultiSz(filters); } } filters = GetDevMultiSz(Devs,DevInfo,SPDRP_UPPERFILTERS); if(filters) { if(filters[0]) { //
// dump upper device filters
//
Padding(1); FormatToStream(stdout,MSG_DUMP_DEVICESTACK_UPPERFILTERS); DumpArray(2,filters); } DelMultiSz(filters); } service = GetDeviceStringProperty(Devs,DevInfo,SPDRP_SERVICE); Padding(1); FormatToStream(stdout,MSG_DUMP_DEVICESTACK_SERVICE); if(service && service[0]) { //
// dump service
//
Padding(2); _tprintf(TEXT("%s\n"),service); } else { //
// dump the fact that there's no service
//
Padding(2); FormatToStream(stdout,MSG_DUMP_DEVICESTACK_NOSERVICE); } if(service) { delete [] service; } if(hClassKey != INVALID_HANDLE_VALUE) { filters = GetRegMultiSz(hClassKey,REGSTR_VAL_LOWERFILTERS); if(filters) { if(filters[0]) { //
// lower class filters
//
Padding(1); FormatToStream(stdout,MSG_DUMP_DEVICESTACK_LOWERCLASSFILTERS); DumpArray(2,filters); } DelMultiSz(filters); } RegCloseKey(hClassKey); } filters = GetDevMultiSz(Devs,DevInfo,SPDRP_LOWERFILTERS); if(filters) { if(filters[0]) { //
// lower device filters
//
Padding(1); FormatToStream(stdout,MSG_DUMP_DEVICESTACK_LOWERFILTERS); DumpArray(2,filters); } DelMultiSz(filters); }
return TRUE; }
|