windows驱动协安装的配置及源安装路径获取
2021-07-01
129
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;
}