zoukankan      html  css  js  c++  java
  • Windows驱动开发-键盘过滤

    抄来的代码

    大概思路:

    不是用的WDM驱动模型,是用的NT驱动模型

    找到键盘驱动,把自己的设备绑在键盘驱动设备上

    没处理PNP请求,不懂为什么可以不用处理。

    亲测能用,但是用工具stop的时候,蓝屏。。。

    头文件

    #include <ntddk.h>
    #include <ntddkbd.h>
    
    #define KBD_DRIVER_NAME L"\Driver\kbdclass"
    
    typedef struct _DEVICE_EXTENSION
    {
        PIRP proxyIrp;
        PDEVICE_OBJECT poldDevice;
        PDEVICE_OBJECT pDevice;
        PDEVICE_OBJECT pbindDevice;
    }DEVICE_EXTENSION,*PDEVICE_EXTENSION;
    
    extern POBJECT_TYPE* IoDriverObjectType;
    
    NTSTATUS ObReferenceObjectByName(
        PUNICODE_STRING ObjectName,
        ULONG Attributes,
        PACCESS_STATE AccessState,
        ACCESS_MASK DesiredAccess,
        POBJECT_TYPE ObjectType,
        KPROCESSOR_MODE AccessMode,
        PVOID ParseContest,
        PVOID* Object
    );
    
    NTSTATUS FilterDispatchRoutin(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp);
    
    BOOLEAN CancelIrp(PIRP pIrp);
    void FilterUnload(IN PDRIVER_OBJECT pDriverObject);
    NTSTATUS BindDevice(PDRIVER_OBJECT pDriverObject);
    NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject, IN PDEVICE_OBJECT oldDevObj);
    NTSTATUS CallBackKbdFilter(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
    头文件

    点西文件

    #include "FirstDriver.h"
    
    //驱动入口
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
    {
        NTSTATUS status = STATUS_SUCCESS;
        DbgPrint("registerPath ... %ws ...
    ",pRegistryPath->Buffer);
        DbgPrint("驱动加载开始.../n");
        pDriverObject->DriverUnload = FilterUnload;
    
        //设置读取派遣函数
        pDriverObject->MajorFunction[IRP_MJ_READ] = FilterDispatchRoutin;
    
        BindDevice(pDriverObject);
    
        DbgPrint("驱动加载结束.../n");
    
        return status;
    }
    
    BOOLEAN CancelIrp(PIRP pIrp)
    {
        if (pIrp == NULL)
        {
            DbgPrint("取消irp错误.../n");
            return FALSE;
        }
        if (pIrp->Cancel || pIrp->CancelRoutine == NULL)
        {
            DbgPrint("取消irp错误.../n");
            return FALSE;
        }
        if (FALSE == IoCancelIrp(pIrp))
        {
            DbgPrint("IoCancelIrp to irp错误.../n");
            return FALSE;
        }
    
        //取消后重设此例为空
        IoSetCancelRoutine(pIrp, NULL);
        return TRUE;
    }
    
    NTSTATUS CallBackKbdFilter(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
    {
        UNREFERENCED_PARAMETER(DeviceObject);
        UNREFERENCED_PARAMETER(Context);
        PIO_STACK_LOCATION currentIrp;
        PKEYBOARD_INPUT_DATA keyData;
    
        currentIrp = IoGetCurrentIrpStackLocation(Irp);
    
        if (NT_SUCCESS(Irp->IoStatus.Status))
        {
            keyData = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
    
            //DbgPrint("扫描码:%x",keyData->MakeCode);
            DbgPrint("键盘 :%s", keyData->Flags ? "UP" : "DOWN");
            //print_keystroke((UCHAR)keyData->MakeCode);
            if (keyData->MakeCode == 0x1f)
            {
                keyData->MakeCode = 0x20;
            }
        }
        if (Irp->PendingReturned)
        {
            IoMarkIrpPending(Irp);
        }
        return Irp->IoStatus.Status;
    }
    
    
    //派遣函数
    NTSTATUS FilterDispatchRoutin(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
    {
        PIO_STACK_LOCATION currentIrpStack;
        PDEVICE_EXTENSION pDevExt;
    
        //得到设备扩展
        pDevExt = pDevObj->DeviceExtension;
    
        //得到当前irp包
        currentIrpStack = IoGetCurrentIrpStackLocation(pIrp);
        //将当前irp复制到下层设备irp堆栈
        IoCopyCurrentIrpStackLocationToNext(pIrp);
    
        //保存原来的irp
        //pDevExt->tagIrp=pIrp;
    
        //代理irp
        pDevExt->proxyIrp = pIrp;
    
        //设置当irp完成时的回调例程
        IoSetCompletionRoutine(pDevExt->proxyIrp, CallBackKbdFilter, pDevObj, TRUE, TRUE, TRUE);
        DbgPrint("irp回调例程设置完毕.../n");
        return IoCallDriver(pDevExt->poldDevice, pDevExt->proxyIrp);
    }
    
    //创建设备
    NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject, IN PDEVICE_OBJECT oldDevObj)
    {
        NTSTATUS status;
        PDEVICE_OBJECT pDevObj;
        //谁被扩展
        PDEVICE_EXTENSION pDevExt;
    
        status = IoCreateDevice(pDriverObject,
            sizeof(PDEVICE_EXTENSION),
            NULL,
            oldDevObj->DeviceType,//设备类型需要和被附加的设备类型相等
            0,
            FALSE,//如果指定设备是独占的,大部分驱动程序设置这个值为FALSE,如果不是独占的话设置为TRUE.
            &pDevObj);
    
        if (!NT_SUCCESS(status))
        {
            DbgPrint("创建设备失败..../n");
            return status;
        }
        pDevExt = pDevObj->DeviceExtension;
        //存储设备对象
        pDevExt->pDevice = pDevObj;
        //绑定前原设备
        pDevExt->poldDevice = oldDevObj;
    
        //标志位
        pDevObj->Flags |= oldDevObj->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE);
    
        //该标识指示I/O管理器对所有发送到控制设备对象的Open请求进行安全检测
        pDevObj->Characteristics = oldDevObj->Characteristics;
    
    
        //绑定设备
        PDEVICE_OBJECT topDev = IoAttachDeviceToDeviceStack(pDevObj, oldDevObj);
        if (topDev == NULL)
        {
            //如果绑定失败,销毁设备
            IoDeleteDevice(pDevObj);
            status = STATUS_UNSUCCESSFUL;
            return status;
        }
    
        //将绑定的设备和原始设备放入设备扩展中
        pDevExt->poldDevice = oldDevObj;
        pDevExt->pbindDevice = topDev;
    
        pDevObj->Flags = pDevObj->Flags & ~DO_DEVICE_INITIALIZING;
        KdPrint(("绑定成功../n"));
        return STATUS_SUCCESS;
    }
    
    //绑定设备
    NTSTATUS BindDevice(PDRIVER_OBJECT pDriverObject)
    {
        NTSTATUS status;
        UNICODE_STRING uniNtNameString;
    
        //要打开的驱动对象
        PDRIVER_OBJECT KbdDriverObject = NULL;
        //驱动对象的设备
        PDEVICE_OBJECT kbdDeviceOjbect;
    
        //初始化一个字符串,就是kbdclass驱动的名子
        RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME);
    
        //根据名字打开驱动对象
        status = ObReferenceObjectByName(
            &uniNtNameString,
            OBJ_CASE_INSENSITIVE,
            NULL,
            0,
            *IoDriverObjectType,
            KernelMode,
            NULL,
            (PVOID*)&KbdDriverObject);
    
        //如果失败了就直接返回
        if (!NT_SUCCESS(status))
        {
            DbgPrint("打开设备失败.../n");
            return status;
        }
    
        //调用ObReferenceObjectByName会导致对驱动对象的引用计数增加
        //必须响应的调用解引用ObDereferenceObject
        ObDereferenceObject(pDriverObject);
        DbgPrint("打开成功,解除引用.../n");
    
    
        //键盘驱动的第一个设备
        kbdDeviceOjbect = KbdDriverObject->DeviceObject;
        while (kbdDeviceOjbect != NULL)
        {
            //创建并绑定过滤设备
            CreateDevice(pDriverObject, kbdDeviceOjbect);
            //下一个设备
            kbdDeviceOjbect = kbdDeviceOjbect->NextDevice;
        }
    
        return status;
    }
    
    //卸载例程
    void FilterUnload(IN PDRIVER_OBJECT pDriverObject)
    {
        //得到设备
        PDEVICE_OBJECT pDevObj = pDriverObject->DeviceObject;
        while (pDevObj != NULL)
        {
            //设备扩展
            PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
            //PDEVICE_OBJECT pTagObj = pDevExt->pbindDevice;
    
            //解除绑定
            if (pDevExt->pbindDevice != NULL)
            {
                IoDetachDevice(pDevExt->pbindDevice);
            }
    
            //删除设备
            if (pDevExt->pDevice != NULL)
            {
                IoDeleteDevice(pDevExt->pDevice);
            }
    
            if (pDevExt->proxyIrp != NULL)
            {
                if (CancelIrp(pDevExt->proxyIrp))
                {
                    DbgPrint("取消成功。。。/n");
                }
                else
                {
                    DbgPrint("取消失败。。。/n");
                }
            }
            //下一个设备
            pDevObj = pDevObj->NextDevice;
    
        }
    }
    点西文件

    备用代码

    // flags for keyboard status
    #define    S_SHIFT                1
    #define    S_CAPS                2
    #define    S_NUM                4
    static int kb_status = S_NUM;
    
    unsigned char asciiTbl[] = {
        0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09,    //normal
            0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x5B, 0x5D, 0x0D, 0x00, 0x61, 0x73,
            0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x7A, 0x78, 0x63, 0x76,
            0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
            0x32, 0x33, 0x30, 0x2E,
            0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09,    //caps
            0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x5B, 0x5D, 0x0D, 0x00, 0x41, 0x53,
            0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x5A, 0x58, 0x43, 0x56,
            0x42, 0x4E, 0x4D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
            0x32, 0x33, 0x30, 0x2E,
            0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09,    //shift
            0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x7B, 0x7D, 0x0D, 0x00, 0x41, 0x53,
            0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x5A, 0x58, 0x43, 0x56,
            0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
            0x32, 0x33, 0x30, 0x2E,
            0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09,    //caps + shift
            0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x7B, 0x7D, 0x0D, 0x00, 0x61, 0x73,
            0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x7A, 0x78, 0x63, 0x76,
            0x62, 0x6E, 0x6D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
            0x32, 0x33, 0x30, 0x2E
    };
    
    
    void __stdcall print_keystroke(UCHAR sch)
    {
        UCHAR    ch = 0;
        int        off = 0;
    
        if ((sch & 0x80) == 0)    //make
        {
            if ((sch < 0x47) || 
                ((sch >= 0x47 && sch < 0x54) && (kb_status & S_NUM))) // Num Lock
            {
                ch = asciiTbl[off+sch];
            }
    
            switch (sch)
            {
            case 0x3A:
                kb_status ^= S_CAPS;
                break;
    
            case 0x2A:
            case 0x36:
                kb_status |= S_SHIFT;
                break;
    
            case 0x45:
                kb_status ^= S_NUM;
            }
        }
        else        //break
        {
            if (sch == 0xAA || sch == 0xB6)
                kb_status &= ~S_SHIFT;
        }
    
        if (ch >= 0x20 && ch < 0x7F)
        {
            DbgPrint("%C /n",ch);
        }
    
    }
    备用代码
  • 相关阅读:
    50个提高PHP程序运行效率的方法
    虚拟主机FTP上传文件为什么要用二进制上传
    Status Bar 总结
    TableView 总结
    阿里Java开发手册(泰山版)个人记录
    下载excel模板
    微信公众号-发送模板消息
    ffmpeg获取视频时长
    微信公众号授权
    根据word模板生成word、转换成pdf、打成war包
  • 原文地址:https://www.cnblogs.com/a-s-m/p/12420835.html
Copyright © 2011-2022 走看看