ssdt-hook实现鼠标2个键互换

最近对驱动比较感兴趣,所以打算做个windows下面的驱动,正好自己电脑的鼠标左键的单击有的时候会变双击,所有打算弄个鼠标的过滤驱动来解决这个问题。

网上找了一下,原来早就有人做了这个功能 http://download.csdn.net/detail/guijc1/5263421(不是故意给这个打广告的),所以我的代码基本都是仿照这里的源码。

这篇文章的重点是如何动手写一个过滤驱动,不是驱动的技术细节。还有就是驱动需要支持32和64系统的问题,安装驱动的问题。

以下很多都是从网络上面获取的资料。我会把链接都放到文章里面。

1.开发环境的搭建

 vs2008+GRMWDK_EN_7600_1.ISO,这些直接安装就行了 注意如果要64位版本需要安装vs2008的64编译环境,接下来就是环境的配置了。我参照的是

http://jacky-dai.iteye.com/blog/1536456  以及http://blog.csdn.net/huangxy10/article/details/15284881

(1)打开vs2008,选择“工具--选项--项目和解决方案”在右侧平台选择“win32”--“包含文件”,然后在下面添加自己的wdk中的inc相关路径 
D:WINDDK7600.16385.1incwdfkmdf1.9 
D:WINDDK7600.16385.1incapi 
D:WINDDK7600.16385.1inccrt 
D:WINDDK7600.16385.1incddk

注意:vc包含文件的D:WinDDK7600.16385.1incapi不一定是放最前面,编译不过去的时候可以放到$(VCInstallDir)include的后面。

然后选择“win32”--“库文件”添加自己的WDK中LIB路径 
D:WINDDK7600.16385.1libwdfkmdfi3861.9 
D:WINDDK7600.16385.1libwxpi386

如果是64位的需要添加的库文件是

D:WINDDK7600.16385.1libwdfkmdfamd641.9 
D:WINDDK7600.16385.1libwin7amd64

(2) 工程配置

新建一个win32的控制台工程,把里面带的文件都删除掉

右键工程,选择属性

     点击“c/c++”-- 

     选择“常规”,“调试信息”选:“C7 兼容(/Z7)”,“警告等级”--“3级(/w3)”,“将警告视为错误”--选“是” (这个需要看情况设置)

     选择“优化”,“优化”选“禁用(/0d)” 

     选择“预处理器”,“预处理器定义”输入“WIN32=100;_X86_=1;DBG=1”  如果是64的则把_X86_=1 替换为_AMD64_=1

     选择“高级”,“调用约定”选“__stdcall (/Gz)” 

     点击“连接器”-- 

     选择“常规”,“输出文件”输入“$(OutDir)$(ProjectName)32.sys”(64位的修改为"$(OutDir)$(ProjectName)64.sys"),“启用增量连接”,选“否(/INCREMENTAL:NO)”,“附加库目录”输入“D:WINDDK7600.16385.0libwxpi386”

如果是64的修改为"D:WinDDK7600.16385.1libwin7amd64”

     选择“输入”,“附加依赖项”输入“ntoskrnl.lib $(NOINHERIT)”,“忽略所有默认库”选“是(/NODEFAULTLIB)” 

     选择“清单文件”,“启用用户账户控制(UAC)”选“否” 

     选择“调试”,“生成调试信息”选择“是”,“生成程序数据库文件”输入“MyChecked_Driver$(ProjectName).pdb” 

     选择“系统”,“子系统”选“本机(/SUBSYSTEM:NATIVE)”,“堆栈保留大小”输入“40000”,“堆栈提交大小”输入“1000”,“驱动程序”选“驱动程序(/DRIVER)” 

     选择“高级”,“入口点”输入“DriverEntry”,“基址”输入“0x10000”,“随机基址”选“默认值”,“数据执行保护(DEP)”选“默认值”,“目标计算机”选“MachineX86 (/MACHINE:X86)”  如果是64的就选择"MachineX64 (/MACHINE:X64)"

2.下面是工程源码  解决鼠标单击变双击的问题
MouseLeftKeyFilter.h

#pragma once

#define DEVICE_NAME          L"\Device\MouseFilter"
#define DOS_DEVICE_NAME      L"\DosDevices\MouseFilter"

#define POOL_TAG             'tsiL'

#ifdef __cplusplus   
extern "C"  
{   
#endif
    //一类是不支持即插即用功能的NT式的驱动程序
    //NT式的驱动程序要导入的头文件时NTDDK.H,而WDM式的驱动要导入的头文件为WDM.H.
    #include <ntddk.h> 

    typedef NTSTATUS (*READ_DISPATCH)(__in PDEVICE_OBJECT pDeviceObject, __in PIRP Irp);

    typedef struct _DEVICE_EXTENSION {
        PDEVICE_OBJECT  pDeviceObject;  
    } DEVICE_EXTENSION, *PDEVICE_EXTENSION;

    typedef struct _MOUSE_FILTER_DATA{
        PDRIVER_OBJECT  pMouseDriverObject; // "\Driver\Mouclass" 的指针
        READ_DISPATCH OldRead; // 原来的IRP_MJ_READ 派遣例程
        ULONG LeftDownTime; // 上次鼠标左键按下的时刻 
        KMUTEX ReadMutex; // Read互斥体
        SINGLE_LIST_ENTRY ListHead;// 保存Pending IRP的链表
        SINGLE_LIST_ENTRY CancelHead;// 用来对上面链表的进行复制
    }MOUSE_FILTER_DATA, *PMOUSE_FILTER_DATA;

    typedef struct _PENDING_IRP_LIST{
        SINGLE_LIST_ENTRY SingleListEntry;    
        PIRP PendingIrp;
    }PENDING_IRP_LIST, *PPENDING_IRP_LIST;

    extern POBJECT_TYPE *IoDriverObjectType;

    extern NTSTATUS ObReferenceObjectByName(
        PUNICODE_STRING ObjectName,
        ULONG Attributes,
        PACCESS_STATE AccessState,
        ACCESS_MASK DesiredAccess,
        POBJECT_TYPE ObjectType,
        KPROCESSOR_MODE AccessMode,
        PVOID ParseContext,
        PVOID *Object
        );

    NTSTATUS DriverEntry (IN  PDRIVER_OBJECT  pDeviceObject,
        IN  PUNICODE_STRING RegistryPath
        );
    VOID DriverUnload(IN PDRIVER_OBJECT pDeviceObject);

    NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT pDeviceObject,
        IN PIRP Irp
        );
    NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT pDeviceObject,
        IN PIRP Irp
        );
    NTSTATUS MyDispatchRead(IN PDEVICE_OBJECT pDeviceObject,
        IN PIRP Irp
        );
    NTSTATUS MyDispatchReadComplete(IN PDEVICE_OBJECT pDeviceObject,
        IN PIRP Irp, 
        IN PVOID Context ) ;

    VOID CleanUP(IN PDEVICE_OBJECT pDeviceObject);
    VOID CancelPendingIrp();
    BOOLEAN IsFakeDoubleClick ();
    
#ifdef __cplusplus   
};   
#endif 

//#ifdef ALLOC_PRAGMA   
//#pragma alloc_text(INIT, DriverEntry)   
//#pragma alloc_text(PAGE, testDriverUnload)   
//#endif

下面是MouseLeftKeyFilter.cpp

#include "MouseLeftKeyFilter.h"
#include <ntddmou.h>

MOUSE_FILTER_DATA gFilterData = {0};


NTSTATUS DriverEntry (IN  PDRIVER_OBJECT  pDeviceObject,
             IN  PUNICODE_STRING RegistryPath
             )
{
    NTSTATUS  status = STATUS_SUCCESS;
    UNICODE_STRING  DeviceName;
    UNICODE_STRING  SymbolicLinkName;
    UNICODE_STRING  MouseDriver;
    PDEVICE_OBJECT  DeviceObject = NULL;
    PDEVICE_EXTENSION   deviceExtension = NULL;

    //告诉编译器,已经使用了该变量,不必检测警告
    UNREFERENCED_PARAMETER (RegistryPath);

    KdPrint(("Entered DriverEntry =================== 
"));

    KeInitializeMutex(&gFilterData.ReadMutex, 0);
    gFilterData.ListHead.Next = NULL;
    gFilterData.CancelHead.Next = NULL;

    pDeviceObject->MajorFunction [IRP_MJ_CREATE] =
    pDeviceObject->MajorFunction [IRP_MJ_CLOSE] =  DispatchCreateClose;
    pDeviceObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;    
    pDeviceObject->DriverUnload = DriverUnload;

    //创建设备对象
    RtlInitUnicodeString(&DeviceName, DEVICE_NAME);    
    status = IoCreateDevice( 
        pDeviceObject,
        sizeof(DEVICE_EXTENSION),
        &DeviceName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &DeviceObject
        );
    if (!NT_SUCCESS(status))
    {
        KdPrint(("IoCreateDevice failed, 0x%0x!
", status));
        return status;
    }   

    //创建符号链接
    RtlInitUnicodeString(&SymbolicLinkName, DOS_DEVICE_NAME);
    status = IoCreateSymbolicLink(&SymbolicLinkName, &SymbolicLinkName);
    if(!NT_SUCCESS(status))
    {
        KdPrint(("IoCreateSymbolicLink failed, 0x%0x!
", status));
        CleanUP(DeviceObject);
        return status;
    }

    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));

    deviceExtension->pDeviceObject = DeviceObject;

    //DeviceObject->Flags |= DO_BUFFERED_IO;
    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;


    //取得鼠标驱动对象
    RtlInitUnicodeString(&MouseDriver, L"\Driver\Mouclass");
    status = ObReferenceObjectByName (
        &MouseDriver,
        OBJ_CASE_INSENSITIVE,
        NULL,
        0,
        *IoDriverObjectType,
        KernelMode,
        NULL,
        (PVOID *)&gFilterData.pMouseDriverObject
        );

    if(!NT_SUCCESS(status))
    {
        KdPrint(("Get mouse object failed, 0x%0x
", status));
        CleanUP(DeviceObject);
        return status;
    }


    //保存原来的IRP_MJ_READ 派遣例程
    gFilterData.OldRead = gFilterData.pMouseDriverObject->MajorFunction[IRP_MJ_READ];

    if(gFilterData.OldRead) // IRP HOOK
    {
        InterlockedExchange(
            (PLONG)&gFilterData.pMouseDriverObject->MajorFunction[IRP_MJ_READ],
            (LONG)MyDispatchRead
            );
    }
    else
    {
        CleanUP(DeviceObject);
        return STATUS_UNSUCCESSFUL;
    }    

    return status;
}

//IRP_MJ_READ 完成函数
NTSTATUS MyDispatchReadComplete(IN PDEVICE_OBJECT pDeviceObject,
                        IN PIRP Irp, 
                        IN PVOID Context ) 
{
    ULONG_PTR i,num;
    PMOUSE_INPUT_DATA data;
    PSINGLE_LIST_ENTRY pSingleListEntry = &gFilterData.ListHead;
    PPENDING_IRP_LIST PendingList = NULL;

    if( NT_SUCCESS( Irp->IoStatus.Status ) ) 
    {
        data = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
        num = Irp->IoStatus.Information / sizeof(MOUSE_INPUT_DATA);

        for( i = 0; i < num; i++ ) 
        {
            ////去除假的鼠标左键双击事件
            //if(data[i].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN )
            //{ 
            //    // 鼠标左键按下
            //    if(IsFakeDoubleClick() )
            //    {   //假双击
            //        KdPrint(("Got a Fake Double CLick!! ================= 
"));
            //        data[i].ButtonFlags = 0; //忽略掉
            //    }
            //    else
            //    {
            //        //KdPrint(("Left Button Down"));
            //    }
            //}

            //下面是实现左右互换的功能
            if(data[i].ButtonFlags &MOUSE_LEFT_BUTTON_DOWN )
            {
                data[i].ButtonFlags = data[i].ButtonFlags&0xfff0;
                data[i].ButtonFlags = data[i].ButtonFlags|MOUSE_RIGHT_BUTTON_DOWN;
            }
            else if (data[i].ButtonFlags &MOUSE_LEFT_BUTTON_UP)
            {
                data[i].ButtonFlags = data[i].ButtonFlags&0xfff0;
                data[i].ButtonFlags = data[i].ButtonFlags|MOUSE_RIGHT_BUTTON_UP;
            }
            else if (data[i].ButtonFlags &MOUSE_RIGHT_BUTTON_DOWN)
            {
                data[i].ButtonFlags = data[i].ButtonFlags&0xfff0;
                data[i].ButtonFlags = data[i].ButtonFlags|MOUSE_LEFT_BUTTON_DOWN;
            }
            else if (data[i].ButtonFlags &MOUSE_RIGHT_BUTTON_UP)
            {
                data[i].ButtonFlags = data[i].ButtonFlags&0xfff0;
                data[i].ButtonFlags = data[i].ButtonFlags|MOUSE_LEFT_BUTTON_UP;
            }
        }
    }

    KeWaitForMutexObject(&gFilterData.ReadMutex, Executive, KernelMode, FALSE, NULL);

    for(; pSingleListEntry->Next; pSingleListEntry = pSingleListEntry->Next)        
    {
        PendingList = CONTAINING_RECORD(pSingleListEntry->Next, PENDING_IRP_LIST, SingleListEntry);

        if(PendingList->PendingIrp == Irp)
        {// 从链表中移除
            pSingleListEntry->Next = pSingleListEntry->Next->Next;
            ExFreePoolWithTag(PendingList, POOL_TAG); 
            break;
        }
    }

    KeReleaseMutex(&gFilterData.ReadMutex, FALSE);       

    //KdPrint(("MyReadComplete ============ Irp= 0x%X, 0x%X", Irp,  Irp->IoStatus.Status));    

    //调用原来的完成函数
    if ((Irp->StackCount > 1) && (Context != NULL))
    {
        return ((PIO_COMPLETION_ROUTINE)Context)(pDeviceObject, Irp, NULL);
    }
    else
    {
        return Irp->IoStatus.Status;
    }
}


NTSTATUS MyDispatchRead(IN PDEVICE_OBJECT pDeviceObject,
       IN PIRP Irp
       )
{
    PPENDING_IRP_LIST PendingList = NULL;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);

    //KdPrint(("MyDispatchRead ================ Irp= 0x%p ", Irp)); 

    PendingList = (PPENDING_IRP_LIST)ExAllocatePoolWithTag(NonPagedPool, sizeof(PENDING_IRP_LIST), POOL_TAG);    

    if(PendingList)
    {
        PendingList->PendingIrp = Irp;

        KeWaitForMutexObject( &gFilterData.ReadMutex, Executive, KernelMode, FALSE, NULL);                
        PushEntryList(&gFilterData.ListHead, &PendingList->SingleListEntry);
        KeReleaseMutex(&gFilterData.ReadMutex, FALSE); 

        // 按理说,应该调用IoSetCompletionRoutine来设置完成例程的
        // 但是,那样会导致完成例程根本不会被执行,Why?
        irpSp->Control = SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR|SL_INVOKE_ON_CANCEL;

        //保留原来的完成函数
        irpSp->Context = irpSp->CompletionRoutine;
        irpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)MyDispatchReadComplete;
    }

    return  gFilterData.OldRead(pDeviceObject, Irp); 
}

NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT pDeviceObject,
            IN PIRP Irp
            )
{
    //IoGetCurrentIrpStackLocation 需要在项目设置里面添加 hal.lib
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);

    UNREFERENCED_PARAMETER(pDeviceObject);

    PAGED_CODE();

    KdPrint(("Entered ================ IRP_MJ_%s
", (irpStack->MajorFunction == IRP_MJ_CREATE) ? "CREATE" : "CLOSE" ));

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return Irp->IoStatus.Status;
}

NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT pDeviceObject,
              IN PIRP Irp
              )
{
    PAGED_CODE();

    Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest (Irp,IO_NO_INCREMENT);

    return Irp->IoStatus.Status;
}

VOID DriverUnload(IN PDRIVER_OBJECT pDeviceObject)
{
    PAGED_CODE ();

    KdPrint(("Entered ================== Unload
"));

    CleanUP(pDeviceObject->DeviceObject);

    CancelPendingIrp();

    //等待所有的IRP 完成    
    while (gFilterData.ListHead.Next) 
    {
        LARGE_INTEGER lDelay;
        lDelay.QuadPart = -10 * 1000 * 1000; // 1秒
        KeDelayExecutionThread(KernelMode, FALSE, &lDelay);
    }       
}

VOID CleanUP(IN PDEVICE_OBJECT pDeviceObject)
{
    UNICODE_STRING  SymbolicLinkName;

    if(!pDeviceObject)
        return;

    // 删除符号链接和设备对象
    RtlInitUnicodeString(&SymbolicLinkName, DOS_DEVICE_NAME);
    IoDeleteSymbolicLink(&SymbolicLinkName);       
    IoDeleteDevice(pDeviceObject);

    //恢复IRP  hook
    if(gFilterData.OldRead)
    {
        InterlockedExchange(
            (PLONG)&gFilterData.pMouseDriverObject->MajorFunction[IRP_MJ_READ], 
            (LONG)gFilterData.OldRead
            );         
    }  

    if(gFilterData.pMouseDriverObject)
    {
        ObDereferenceObject(gFilterData.pMouseDriverObject);  
    }
}

// 取消等待的IRP
VOID CancelPendingIrp()
{
    PPENDING_IRP_LIST PendingList = NULL, CancelList = NULL;
    PSINGLE_LIST_ENTRY pSingleListEntry = NULL;

    // 获取互斥体,保护链表gFilterData.ListHead
    KeWaitForMutexObject(&gFilterData.ReadMutex, Executive, KernelMode, FALSE, NULL);

    pSingleListEntry = gFilterData.ListHead.Next;
    while(pSingleListEntry)
    {       
        PendingList = CONTAINING_RECORD(pSingleListEntry, PENDING_IRP_LIST, SingleListEntry);
        KdPrint(("Copy ================= Single List = 0x%x", PendingList));

        // 复制链表,然后将取消IRP的操作放到新的链表中处理
        CancelList = (PPENDING_IRP_LIST)ExAllocatePoolWithTag(NonPagedPool, sizeof(PENDING_IRP_LIST), POOL_TAG);
        if(CancelList)
        {
            RtlCopyMemory(CancelList, PendingList, sizeof(PENDING_IRP_LIST));
            PushEntryList(&gFilterData.CancelHead, &CancelList->SingleListEntry);
        }           

        pSingleListEntry = pSingleListEntry->Next;
    }   
    // 释放互斥体
    KeReleaseMutex(&gFilterData.ReadMutex, FALSE);


    // 之所以要复制一个新的链表来取消IRP (通过调用IoCancelIrp),
    // 是因为IoCancelIrp 会调用MyDispatchReadComplete 这个完成例程回调,
    // 而MyDispatchReadComplete里面又对链表进行操作,这样会破坏链表的结构
    pSingleListEntry = PopEntryList(&gFilterData.CancelHead);
    while(pSingleListEntry)
    {
        CancelList = CONTAINING_RECORD(pSingleListEntry, PENDING_IRP_LIST, SingleListEntry);
        if(CancelList)
        {
            KdPrint(("CancelPendingIrp = 0x%x", CancelList->PendingIrp));

            if(!CancelList->PendingIrp->Cancel)
            {// 在这里,取出复制链表中的IRP,然后进行取消
                IoCancelIrp(CancelList->PendingIrp);
            }
            ExFreePoolWithTag(CancelList, POOL_TAG);        
            pSingleListEntry = PopEntryList(&gFilterData.CancelHead);
        }
    }
}

//判断是否是假双击,根据时间间隔判断
BOOLEAN IsFakeDoubleClick ()
{
    LARGE_INTEGER CurrentTime;
    BOOLEAN Flag = FALSE;

    KeQueryTickCount(&CurrentTime);

    CurrentTime.QuadPart *= KeQueryTimeIncrement();  
    CurrentTime.QuadPart /=  10000;

    //两次点击时间间隔小于100ms,视为假双击
    if( CurrentTime.LowPart - gFilterData.LeftDownTime < 100)
    {
        Flag = TRUE;
    }

    InterlockedExchange((volatile LONG *)&gFilterData.LeftDownTime, CurrentTime.LowPart);
    return Flag;
}

上面就是全部的代码。如果编译没有错误就会生成对应的sys文件。

3.安装驱动

安装过滤驱动有两种方式,一种是写服务来安装,这个网上也有源码,还有就是inf文件  在cmd里面执行rundll32 SETUPAPI.DLL,InstallHinfSection DefaultInstall 132 +inf路径

这里贴出来一个完整的inf 鼠标过滤驱动的文件

; HHD Software USB Monitoring Filter Driver
; Part of Device Monitoring Studio
;
; Copyright HHD Software Ltd.
[Version]
signature = "$Windows NT$"
DriverPackageType=ClassFilter
Class=Mouse
ClassGUID={59D5B0A2-8479-4333-BCFE-3EB1F6BD506D}
Provider=%ClasFilt.Provider%
DriverVer=12/03/2010,5.25.0.3036

;
[SourceDisksNames]
1 = %ClasFilt.MediaDesc%

[SourceDisksFiles]
MyMouseDrive32.sys = 1
MyMouseDrive64.sys = 1

[DestinationDirs]
DefaultDestDir = 12    ; DIRID_DRIVERS

[DefaultInstall.ntx86]
CopyFiles = @MyMouseDrive32.sys
AddReg = ClassFilter_AddReg.ntx86
 
[DefaultInstall.ntamd64]
CopyFiles = @MyMouseDrive64.sys
AddReg = ClassFilter_AddReg.ntamd64
 
; 指定过滤驱动对应的注册表项
[ClassFilter_AddReg.ntx86]
HKLM, SystemCurrentControlSetControlClass{4D36E96F-E325-11CE-BFC1-08002BE10318}, UpperFilters, 0x00010008, MyMouseDrive32

      
[ClassFilter_AddReg.ntamd64]
HKLM, SystemCurrentControlSetControlClass{4D36E96F-E325-11CE-BFC1-08002BE10318}, UpperFilters, 0x00010008, MyMouseDrive64


[DefaultInstall.ntx86.Services]
AddService = MyMouseDrive32, , clasfilt_Service_Inst.ntx86, clasfilt_EventLog_Inst.ntx86

[DefaultInstall.ntamd64.Services]
AddService = MyMouseDrive64, , clasfilt_Service_Inst.ntamd64, clasfilt_EventLog_Inst.ntamd64

[clasfilt_Service_Inst.ntx86]
DisplayName    = %ClasFilt.SvcDesc%
ServiceType    = %SERVICE_KERNEL_DRIVER%
StartType      = %SERVICE_DEMAND_START%
ErrorControl   = %SERVICE_ERROR_IGNORE%
ServiceBinary  = %12%MyMouseDrive32.sys

[clasfilt_Service_Inst.ntamd64]
DisplayName    = %ClasFilt.SvcDesc%
ServiceType    = %SERVICE_KERNEL_DRIVER%
StartType      = %SERVICE_DEMAND_START%
ErrorControl   = %SERVICE_ERROR_IGNORE%
ServiceBinary  = %12%MyMouseDrive64.sys

[clasfilt_EventLog_Inst.ntx86]
AddReg = clasfilt_EventLog_AddReg.ntx86

[clasfilt_EventLog_Inst.ntamd64]
AddReg = clasfilt_EventLog_AddReg.ntamd64

[clasfilt_EventLog_AddReg.ntx86]
HKR,,EventMessageFile, %REG_EXPAND_SZ%,"%%SystemRoot%%System32IoLogMsg.dll;%%SystemRoot%%System32driversMyMouseDrive32.sys"
HKR,,TypesSupported, %REG_DWORD%, 7

[clasfilt_EventLog_AddReg.ntamd64]
HKR,,EventMessageFile, %REG_EXPAND_SZ%,"%%SystemRoot%%System32IoLogMsg.dll;%%SystemRoot%%System32driversMyMouseDrive64.sys"
HKR,,TypesSupported, %REG_DWORD%, 7

[Strings]
; 不同的过滤驱动下面的信息要修改
;Note: the following must be modified, if it is other filter drivers 
ClasFilt.SvcDesc="MyMouse Filter Driver"
ClasFilt.MediaDesc="MyMouse Filter Package"
ClasFilt.Provider="MyMouse Software Ltd."

;下面这个信息不需要修改
; Useful constants
SERVICE_KERNEL_DRIVER = 1
SERVICE_DEMAND_START  = 3
SERVICE_ERROR_IGNORE  = 0
REG_EXPAND_SZ         = 0x00020000
REG_DWORD             = 0x00010001
    
原文地址:https://www.cnblogs.com/mayingkun/p/7758472.html