SetupApi函数
+ -

DevCon DriverNodes命令代码实现

2022-01-28 50 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文件和驱动日期版本信息

0 篇笔记 写笔记

DevCon DriverNodes命令
DevCon DriverNodes命令列出与设备兼容的所有驱动程序包及其版本和驱动排名。DevCon DriverNodes 操作仅在本地计算机上运行。DevCon DriverNodes 操作对于排查驱动安装问题特别有用。 例如,可以使用它来确定设备Windows INF 文件或自定义的第三方 ......
DevCon DriverNodes命令代码实现
DevCon DriverNodes命令的代码实现几乎和Devcon hwids命令源代码实现几乎一致,惟一的不同就是回调要显示的参数不同和DriverNodes不支持在远程机器上运行却不支持/m命令。int cmdDriverNodes(_In_ LPCTSTR BaseName, _In_o......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!