Windows驱动
+ -

windows驱动协安装的配置及源安装路径获取

2021-07-01 113 0

在做windows驱动开发时,有时需要在驱动安装前,安装后,等事件发生时进行一系列的处理工作,当然如果在驱动内部配置相关的IRP回调函数,但有时多有不便。微软给我们提供了一种叫做协安装的方法,由系统调用,我们只需要生成DLL并导出函数即可。

以vm虚拟机的显卡驱动为例,inf文件配置如下:

[vmx_svga.ModeChange]
vmx_mode.dll

[vmx_svga.CoInstallers]
CopyFiles = vmx_svga.ModeChange
AddReg = vmx_svga_CoInstallers_AddReg

[vmx_svga_nt64.CoInstallers]
CopyFiles = vmx_svga.ModeChange
AddReg = vmx_svga_CoInstallers_AddReg

[vmx_svga_vista.CoInstallers]
CopyFiles = vmx_svga.ModeChange
AddReg = vmx_svga_CoInstallers_AddReg

[vmx_svga_vista64.CoInstallers]
CopyFiles = vmx_svga.ModeChange
AddReg = vmx_svga_CoInstallers_AddReg

[vmx_svga_CoInstallers_AddReg]
HKR, , CoInstallers32, 0x00010000, "vmx_mode.dll, VMX_ModeChange"

[VMwarePathInfo]
OriginalInfSourcePath = %1%

在各版本系统的CoIntallers节中,其中CopyFiles指向需要复制的文件节vmx_svga.ModeChange,其内容为复制vmx_mode.dll到系统目录下(system32),AddReg指定了vmx_mode.dll的导出函数VMX_ModeChange为协安装调用的导出函数。

一个空的协安装函数如下:

DWORD  CALLBACK CoInstaller(DI_FUNCTION DifCode,
    HDEVINFO devInfoset,
    PSP_DEVINFO_DATA devInfoData,
    PCOINSTALLER_CONTEXT_DATA Context)
{
    return NO_ERROR;
}

其中 DI_FUNCTION 为DIF,指定了系统调用此函数的事件类型,事件的类型如下:

//
// Class installer function codes
//
#define DIF_SELECTDEVICE                    0x00000001
#define DIF_INSTALLDEVICE                   0x00000002
#define DIF_ASSIGNRESOURCES                 0x00000003
#define DIF_PROPERTIES                      0x00000004
#define DIF_REMOVE                          0x00000005
#define DIF_FIRSTTIMESETUP                  0x00000006
#define DIF_FOUNDDEVICE                     0x00000007
#define DIF_SELECTCLASSDRIVERS              0x00000008
#define DIF_VALIDATECLASSDRIVERS            0x00000009
#define DIF_INSTALLCLASSDRIVERS             0x0000000A
#define DIF_CALCDISKSPACE                   0x0000000B
#define DIF_DESTROYPRIVATEDATA              0x0000000C
#define DIF_VALIDATEDRIVER                  0x0000000D
#define DIF_DETECT                          0x0000000F
#define DIF_INSTALLWIZARD                   0x00000010
#define DIF_DESTROYWIZARDDATA               0x00000011
#define DIF_PROPERTYCHANGE                  0x00000012
#define DIF_ENABLECLASS                     0x00000013
#define DIF_DETECTVERIFY                    0x00000014
#define DIF_INSTALLDEVICEFILES              0x00000015
#define DIF_UNREMOVE                        0x00000016
#define DIF_SELECTBESTCOMPATDRV             0x00000017
#define DIF_ALLOW_INSTALL                   0x00000018
#define DIF_REGISTERDEVICE                  0x00000019
#define DIF_NEWDEVICEWIZARD_PRESELECT       0x0000001A
#define DIF_NEWDEVICEWIZARD_SELECT          0x0000001B
#define DIF_NEWDEVICEWIZARD_PREANALYZE      0x0000001C
#define DIF_NEWDEVICEWIZARD_POSTANALYZE     0x0000001D
#define DIF_NEWDEVICEWIZARD_FINISHINSTALL   0x0000001E
#define DIF_UNUSED1                         0x0000001F
#define DIF_INSTALLINTERFACES               0x00000020
#define DIF_DETECTCANCEL                    0x00000021
#define DIF_REGISTER_COINSTALLERS           0x00000022
#define DIF_ADDPROPERTYPAGE_ADVANCED        0x00000023
#define DIF_ADDPROPERTYPAGE_BASIC           0x00000024
#define DIF_RESERVED1                       0x00000025
#define DIF_TROUBLESHOOTER                  0x00000026
#define DIF_POWERMESSAGEWAKE                0x00000027
#define DIF_ADDREMOTEPROPERTYPAGE_ADVANCED  0x00000028
#define DIF_UPDATEDRIVER_UI                 0x00000029
#define DIF_FINISHINSTALL_ACTION            0x0000002A
#define DIF_RESERVED2                       0x00000030

后2个参数是与设备相关的参数信息,用于SetupAPI函数集使用。

说明:

VMwarePathInfo其实可以不要,但有进为了获取安装文件目录所在的位置,使用一个节来存储临时路径信息。OriginalInfSourcePath = %1%在安装时会存储安装文件的路径。这样当发生DIF_INSTALLDEVICE事件时,解析INF文件对应的节项即可获取源文件的路径。

DWORD  CoInstall(
    _In_     DI_FUNCTION               InstallFunction,
    _In_     HDEVINFO                  DeviceInfoSet,
    _In_     PSP_DEVINFO_DATA          DeviceInfoData   OPTIONAL,
    _Inout_ PCOINSTALLER_CONTEXT_DATA Context
)
{

    HINF hInf = INVALID_HANDLE_VALUE;
    SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
    LPWSTR FileNamePart;
    do
    {
        SP_DRVINFO_DATA DriverInfoData;
        DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
        if (!SetupDiGetSelectedDriver(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
        {
            Log(L"SetupDiGetSelectedDriver error 0x%x\n", GetLastError());
            break;
        }

        DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
        if (!SetupDiGetDriverInfoDetail(DeviceInfoSet,
            DeviceInfoData,
            &DriverInfoData,
            &DriverInfoDetailData,
            sizeof(SP_DRVINFO_DETAIL_DATA),
            NULL)
            && (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
        {
            Log(L"SetupDiGetDriverInfoDetail error 0x%x\n", GetLastError());
            break;
        }

        TCHAR InfPath[MAX_PATH] = {0};
        DWORD PathLength = GetFullPathName(DriverInfoDetailData.InfFileName,
            MAX_PATH,
            InfPath,
            &FileNamePart
        );

         hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
            NULL,
            INF_STYLE_WIN4,
            NULL
        );

        if (hInf == INVALID_HANDLE_VALUE)
        {
            Log(L"SetupOpenInfFile erro 0x%x\n",GetLastError());
            break;
        }

        INFCONTEXT InfContext;
        if (!SetupFindFirstLine(hInf, L"VMwarePathInfo", L"OriginalInfSourcePath", &InfContext))
        {
            Log(L"SetupFindFirstLine error 0x%x\n", GetLastError());
            break;
        }

        TCHAR InstallSourceDirectory[MAX_PATH] = { 0 };
        if (!SetupGetStringField(&InfContext, 1, InstallSourceDirectory, MAX_PATH, &PathLength))
        {
            Log(L"SetupGetStringField error 0x%x\n", GetLastError());
            break;
        }

        Log(L"SourceFilePath is %s\n", InstallSourceDirectory);

    } while (0);

    if (hInf != INVALID_HANDLE_VALUE)
    {
        SetupCloseInfFile(hInf);
    }

    return NO_ERROR;
}

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

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

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