我有一个同时具有x86和x64位驱动程序的驱动程序。安装程序会检查Is64BitOS && Is64BitProcess
。如果它是真的那么它会抓住我的x64驱动程序并对我做一些有点奇怪的事情。它将禁用DisableWow64FSRedirection
,将x64驱动程序复制到c:\ windows \ system32 \ drivers,然后RevertWow64FSRedirection
这对我来说似乎不对。哦,在完成复制所述文件后,它会创建一个内核服务。我不确定为什么安装程序会这样做,或者即使应该这样做。当我在HKLM\System\CurrentControlSet\Services\driver64
查看我的注册表(出于好奇心,我在我的x64机器上安装了它们)时,图像路径为\??\C:\Windows\System32\drivers\driver64.sys
但是当我查看HKLM\System\CurrentControlSet\Services\driver86
时,ImagePath只是driver86
而不是sys扩展......虽然我确实看到了另一个没有的WOW64标志..有趣的。
长话短说。我不喜欢那样。如果Microsoft决定进行重定向,那么我也确定当我为所述驱动程序创建一个SafeFileHandle时它会重定向到正确的驱动程序。我疯了吗?
我在C#中安装了安装程序。以下是代码的安装位
private static void InstallDriver()
{
string name = GetCorrectDriverName();
byte[] driver = is64Bit ? Properties.Resources.inpoutx64 : Properties.Resources.inpout32;
string path = Kernel32.CopyDriverToSystem32(is64Bit, name, driver);
ServiceInstaller.InstallAndStart(name, name, path);
}
Kernel32.cs
/// <summary>
/// Copies a driver with a specific name to the System32\Driver folder
/// </summary>
/// <param name="is64Bit">Value to determine if system is 32 or 64 bit. SYSTEM not program</param>
/// <param name="driverName">the name of the driver. file extension and path will be added to this, so just the name</param>
/// <param name="driver">the driver itself. In this case it is an embedded resource.</param>
/// <returns>the full path name of the driver that was intalled.</returns>
public static string CopyDriverToSystem32(bool is64Bit, string driverName, byte[] driver)
{
bool oldValue = false;
if (is64Bit) DisableWow64FSRedirection(out oldValue);
string path = Path.Combine(Environment.SystemDirectory, "drivers");
path = Path.Combine(path, driverName + ".sys");
File.WriteAllBytes(path, driver);
if (is64Bit) RevertWow64FSRedirection(oldValue);
return path;
}
ServiceInstaller.cs
public static void InstallAndStart(string serviceName, string displayName, string fileName)
{
IntPtr scm = OpenSCManager(ScmAccessRights.AllAccess);
try
{
IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.AllAccess);
if (service == IntPtr.Zero)
{
service = CreateService(scm, serviceName, displayName, ServiceAccessRights.AllAccess, SERVICE_KERNEL_DRIVER, ServiceBootFlag.AutoStart, ServiceError.Normal, fileName, null, IntPtr.Zero, null, null, null);
}
if (service == IntPtr.Zero)
throw new ApplicationException("Failed to install service.");
try
{
StartService(service);
}
finally
{
CloseServiceHandle(service);
}
}
finally
{
CloseServiceHandle(scm);
}
}
private static IntPtr OpenSCManager(ScmAccessRights rights)
{
IntPtr scm = OpenSCManager(null, null, rights);
if (scm == IntPtr.Zero)
throw new ApplicationException("Could not connect to service control manager.");
return scm;
}
完成安装后使用它非常简单,这就是我希望保留的内容。
string driverName = GetCorrectDriverName();
try
{
var driverHandle = Kernel32.CreateExclusiveRWFile(driverName);
}
catch (System.IO.FileNotFoundException)
{
InstallDriver();
}