DevCon DriverNodes命令代码实现
2022-01-28
54
0
DevCon DriverNodes命令的代码实现几乎和Devcon hwids命令源代码实现几乎一致,惟一的不同就是回调要显示的参数不同和DriverNodes不支持在远程机器上运行却不支持/m命令。
int cmdDriverNodes(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[])
/*++
Routine Description:
STATUS <id> ...
use EnumerateDevices to do hardwareID matching
for each match, dump drivernodes to stdout
note that we only enumerate present devices
Arguments:
BaseName - name of executable
Machine - if non-NULL, remote machine
argc/argv - remaining parameters - passed into EnumerateDevices
Return Value:
EXIT_xxxx
--*/
{
GenericContext context;
int failcode;
UNREFERENCED_PARAMETER(Flags);
if(!argc) {
return EXIT_USAGE;
}
if(Machine) {
//
// must be local machine as we need to involve class/co installers (FIND_DRIVERNODES)
//
return EXIT_USAGE;
}
context.count = 0;
context.control = FIND_DEVICE | FIND_DRIVERNODES;
failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context);
if(failcode == EXIT_OK) {
if(!context.count) {
FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine);
} else {
FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine);
}
}
return failcode;
}
int cmdHwIds(_In_ LPCTSTR BaseName,
可以看到,也使用的是FindCallback回调函数,并且需要显示的是FIND_DRIVERNODES。
if (pFindContext->control&FIND_DRIVERNODES) {
DumpDeviceDriverNodes(Devs,DevInfo);
}
通过DumpDeviceDriverNodes函数显示设备下所有的兼容驱动程序。
BOOL DumpDeviceDriverNodes(_In_ HDEVINFO Devs, _In_ 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;
}
可以看到,这里使用SetupDiEnumDriverInfo枚举设备所有驱动程序,不过在调用该函数之前需要做一些“设置配置”,这些设置配置是通过SetupDiGetDeviceInstallParams获取,并通过SetupDiSetDeviceInstallParams修改实现的,最后通过SetupDiBuildDriverInfoList创建驱动表表信息,这样就可以通过SetupDiEnumDriverInfo枚举驱动列表中的所有设备驱动程序包信息了。
DI_FLAGSEX_ALLOWEXCLUDEDDRVS 要为PnP设备生成驱动程序文件列表,SetupDiBuildDriverFolist的调用者必须设置此标志。
以上其实获取的是设备的驱动列表,如果只有一个,当然就是这个设备正在使用的驱动,但如有的时候我们需要知道当前正在使用的驱动信息。这时可以通过注册表来获取。具体详见:SetupAPI根据硬件ID获取驱动INF文件和驱动日期版本信息