/*++ 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((lstrcmp(DriverInfoData->MfgName,MfgName)==0) &&(lstrcmp(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((lstrcmp(detail.SectionName,SectionName)==0) && (lstrcmp(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 Installed using OEM123.INF section [abc.NT] 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 * IDs) /*++ Routine Description: Iterate array and dump entries to screen Arguments: Devs )_ uniquely identify device DevInfo ) Return Value: none --*/ { if(!IDs || !IDs[0]) { return FALSE; } while(IDs[0]) { Padding(pad); _tprintf(TEXT("%s\n"),IDs[0]); IDs++; } return TRUE; } BOOL DumpDeviceHwIds(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo) /*++ Routine Description: Write device instance & description to stdout Hardware ID's ID ... Compatible ID's ID ... or 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 Installed using OEM123.INF section [abc.NT] 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; }