//键盘输入可正常捕捉
问题在于没有键盘输入时,只需拖动窗口或滚动条就会捕捉到1d+3个2e 的扫描码。。
而我压根就没动过键盘呢,每次都这样只须发生上述行为(不动键盘)就会捕捉到1d+3个2e的扫描码?
请高手解释..完整代码如下:(代码有点长,已删除掉一些不太重要的)
#include <ntddk.h>
#include <ntddkbd.h>
//读请求次数
ULONG gC2pKeyCount = 0;
typedef struct _C2P_DEV_EXT 
{
 ...//设备扩展常用结构
 }C2P_DEV_EXT, *PC2P_DEV_EXT;//填充设备扩展结构
NTSTATUS c2pDevExtInit( 
       IN PC2P_DEV_EXT devExt, 
       IN PDEVICE_OBJECT pFilterDeviceObject, 
       IN PDEVICE_OBJECT pTargetDeviceObject, 
       IN PDEVICE_OBJECT pLowerDeviceObject ) 

    memset(devExt, 0, sizeof(C2P_DEV_EXT)); 
    devExt->NodeSize = sizeof(C2P_DEV_EXT); 
    devExt->pFilterDeviceObject = pFilterDeviceObject; 
    KeInitializeSpinLock(&(devExt->IoRequestsSpinLock)); 
    KeInitializeEvent(&(devExt->IoInProgressEvent), NotificationEvent, FALSE); 
    devExt->TargetDeviceObject = pTargetDeviceObject; 
    devExt->LowerDeviceObject = pLowerDeviceObject; 
    return( STATUS_SUCCESS ); 
}extern POBJECT_TYPE IoDriverObjectType;
#define  KBD_DRIVER_NAME L"\\Driver\\Kbdclass"NTSTATUS ObReferenceObjectByName(
 PUNICODE_STRING ObjectName,
 ULONG Attributes,
 PACCESS_STATE AccessState,
 ACCESS_MASK DesiredAccess,
 POBJECT_TYPE ObjectType,
 KPROCESSOR_MODE AccessMode,
 PVOID ParseContext,
 PVOID *Object
 );
NTSTATUS c2pAttachDevices(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    NTSTATUS status = 0;
    UNICODE_STRING uniNtNameString;
    PC2P_DEV_EXT devExt;
    PDEVICE_OBJECT pFilterDeviceObject = NULL;
    PDEVICE_OBJECT pTargerDeviceObject = NULL;
    PDEVICE_OBJECT pLowerDeviceObject = NULL;
    PDRIVER_OBJECT kbdDriverObject = NULL;    KdPrint(("开始绑定KbdClass下的所有设备\n"));    RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME);
       status = ObReferenceObjectByName(
&uniNtNameString, 
OBJ_CASE_INSENSITIVE, 
NULL, 
0, 
IoDriverObjectType,
KernelMode, 
NULL, 
&kbdDriverObject
);    if (!NT_SUCCESS(status))
    {
KdPrint(("打开驱动对象KbdClass失败!\n"));
return status;
    }
    else
    {
ObDereferenceObject(driver);
    }    //这是设备链中的第一个设备
    pTargerDeviceObject = kbdDriverObject->DeviceObject;
    //现在开始遍历这个设备链
    while(pTargerDeviceObject)
    {
//生成一个过滤设备
status = IoCreateDevice(
    driver, 
    sizeof(C2P_DEV_EXT), 
    NULL, 
    pTargerDeviceObject->DeviceType, 
    pTargerDeviceObject ->Characteristics,
    FALSE, 
    &pFilterDeviceObject
    );
if (!NT_SUCCESS(status))
{
    KdPrint(("生成过滤设备失败\n"));
    return status;
} //绑定
pLowerDeviceObject = IoAttachDeviceToDeviceStack(
    pFilterDeviceObject, 
    pTargerDeviceObject
    );
//如果绑定失败了,放弃之前操作,退出
if (pLowerDeviceObject == NULL)
{
    KdPrint(("绑定设备失败!\n"));
    IoDeleteDevice(pFilterDeviceObject);
    pFilterDeviceObject = NULL;
    return status;
} //设备扩展
devExt = (PC2P_DEV_EXT)(pFilterDeviceObject->DeviceExtension);
c2pDevExtInit(
    devExt, 
    pFilterDeviceObject, 
    pTargerDeviceObject, 
    pLowerDeviceObject
    );
//复制关键标志位
          //...
//移动到下一个设备,继续遍历
pTargerDeviceObject = pTargerDeviceObject->NextDevice;
    }
    return status;
}//其它请求分发函数
NTSTATUS c2pDispatchGeneral( PDEVICE_OBJECT device, PIRP Irp) 

    // 其他的分发函数,直接skip然后用IoCallDriver把IRP发送到真实设备的设备对象。 
    KdPrint(("其它请求分发函数!\n")); 
    IoSkipCurrentIrpStackLocation(Irp); 
    return IoCallDriver(((PC2P_DEV_EXT)device->DeviceExtension)->LowerDeviceObject, Irp); 
} //几种关键按键之下字符
unsigned char asciiTbl[]={...};//略
//键盘标志状态
#define  S_SHIFT 1
#define  S_CAPS 2
#define  S_NUM 4
//这是一个标记,用来保存当前键盘的状态。其中有3个位,分别表示
//Caps Lock键、Num Lock键和Shift键是否按下了
static int kb_status = S_NUM;
void _stdcall print_keystroke(UCHAR sch)
{
    UCHAR ch = 0;
    ULONG off = 0;    if ((sch & 0x80) == 0)  //如果是按下(扫描码的最高位判断按下或抬起)
    {
//如果按下了字母或数字等可见字符
if ((sch < 0x47) || ((sch >= 0x47 && sch < 0x54) && (kb_status & S_NUM)))
{
         ch = asciiTbl[off + sch];
} switch (sch)
{

case 0x3A: kb_status = kb_status ^ S_CAPS; break;
case 0x45: kb_status = kb_status ^ S_NUM; break;
case 0x2a:
case 0x36:
    kb_status = kb_status | S_SHIFT; break;
}
    }
    else
    {
if (sch == 0xAA || sch == 0xB6)
{
    kb_status = kb_status & ~S_SHIFT;
}
    }    if (ch >= 0x20 && ch < 0x7F)
    {
DbgPrint("4.实际字符:%c\n", ch);
    }
}#define LCONTROL ((USHORT)0x1D) 
#define CAPS_LOCK ((USHORT)0x3A) 
//这是一个IRP完成回调函数的原型
NTSTATUS c2pReadComplete(PDEVICE_OBJECT device, PIRP Irp, PVOID Context)
{
    PIO_STACK_LOCATION IrpSp =  IoGetCurrentIrpStackLocation(Irp);
    ULONG i, numKeys, buff_len = 0;
    PUCHAR buff = NULL;
    PKEYBOARD_INPUT_DATA KeyData;    //假设这个请求是成功的。很显然,如果请求失败了,这么获取进一步信息是没有意义的
    if (NT_SUCCESS(Irp->IoStatus.Status))
    {
//获得读请求完成后的缓冲区
buff = Irp->AssociatedIrp.SystemBuffer;
KeyData = (PKEYBOARD_INPUT_DATA)buff;
buff_len = Irp->IoStatus.Information;
numKeys = buff_len / sizeof(KEYBOARD_INPUT_DATA);
//To do something
//....
for (i = 0; i<numKeys; i++)
{
    DbgPrint("1.KID结构数目:%d\n", numKeys);
    DbgPrint("2.扫描码:%x\n", KeyData->MakeCode);
    DbgPrint("3.%s\n", KeyData->Flags ? "抬起" : "按下");
    print_keystroke((UCHAR)KeyData->MakeCode);
         }
    }    gC2pKeyCount--;    if (Irp->PendingReturned)
    {
IoMarkIrpPending(Irp);
    }
    return Irp->IoStatus.Status;
}
//读请求
NTSTATUS c2pDispatchRead(IN PDEVICE_OBJECT device, PIRP Irp)
{
    NTSTATUS status = STATUS_SUCCESS;
    PC2P_DEV_EXT devExt;
    PIO_STACK_LOCATION currentIrpStack;
    KEVENT waitEvent;
    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);    if (Irp->CurrentLocation == 1) //IRP当前栈空间
    {
ULONG ReturnedInformation = 0;
KdPrint(("Dispatch encountered bogus current location\n"));
status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = ReturnedInformation;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
    }    //全局变量键计数器+1
    gC2pKeyCount++;    //得到设备扩展,目的是为了获得下一个设备指针
    devExt = (PC2P_DEV_EXT)device->DeviceExtension;
    currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, c2pReadComplete, device, TRUE, TRUE, TRUE);
    return IoCallDriver(devExt->LowerDeviceObject, Irp);
}
//电源相关请求
NTSTATUS c2pPower(IN PDEVICE_OBJECT device, IN PIRP Irp)
{
    PC2P_DEV_EXT devExt;
    devExt = (PC2P_DEV_EXT)device->DeviceExtension;
    PoStartNextPowerIrp(Irp);
    IoSkipCurrentIrpStackLocation(Irp);
    return PoCallDriver(devExt->LowerDeviceObject, Irp);
}//PNP处理
NTSTATUS c2pPnP(IN PDEVICE_OBJECT device, PIRP Irp)
{
    PC2P_DEV_EXT devExt;
    PIO_STACK_LOCATION irpStack;
    NTSTATUS status = STATUS_SUCCESS;
    KIRQL oldIrql;
    KEVENT event;    //获得真实设备
    devExt = (PC2P_DEV_EXT)(device->DeviceExtension);
    irpStack = IoGetCurrentIrpStackLocation(Irp);    switch (irpStack->MinorFunction)
    {
    case IRP_MN_REMOVE_DEVICE:
KdPrint(("IRP_MN_REMOVE_DEVICE\n")); IoSkipCurrentIrpStackLocation(Irp);
IoCallDriver(devExt->LowerDeviceObject, Irp);
IoDetachDevice(devExt->LowerDeviceObject);
IoDeleteDevice(device);
status = STATUS_SUCCESS;
break;    default:
//对于其它类型的IRP,全部都直接下发即可
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(devExt->LowerDeviceObject, Irp);
    }
    return status;
}//解除绑定,并删除本驱动生成的过滤设备
VOID c2pDetach(IN PDEVICE_OBJECT pDeviceObject) 

    PC2P_DEV_EXT devExt; 
    BOOLEAN NoRequestsOutstanding = FALSE; 
    devExt = (PC2P_DEV_EXT)pDeviceObject->DeviceExtension; 
         IoDetachDevice(devExt->TargetDeviceObject);  //解除绑定用目标设备//以绑定COM不同
    devExt->TargetDeviceObject = NULL; 
    IoDeleteDevice(pDeviceObject);     //删除本驱动生成的过滤设备
    devExt->pFilterDeviceObject = NULL; 
    DbgPrint(("解除绑定并删除本驱动生成的过滤设备成功\n")); 
    return; 
}
#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND * 1000)
#define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND * 1000)
VOID c2pUnload(IN PDRIVER_OBJECT driver)
{
    PDEVICE_OBJECT DeviceObject;
    PDEVICE_OBJECT OldDeviceObject;
    PC2P_DEV_EXT devExt;
    LARGE_INTEGER lDelay;
    PRKTHREAD CurrentThread;
    //延迟些时间
    lDelay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND);
    CurrentThread = KeGetCurrentThread();
        KeSetPriorityThread(CurrentThread, LOW_REALTIME_PRIORITY);    UNREFERENCED_PARAMETER(driver);
   
      DeviceObject = driver->DeviceObject;
    while (DeviceObject)
    {
c2pDetach(DeviceObject);
DeviceObject = DeviceObject->NextDevice;
    }
   
    while (gC2pKeyCount)
    {
KeDelayExecutionThread(KernelMode, FALSE, &lDelay);
    }
    KdPrint(("驱动卸载成功!\n"));
}NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    ULONG i;
    NTSTATUS status;
    KdPrint(("驱动入口!\n"));    //填写所有分发函数的指针
    for (i = 0; i<IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
driver->MajorFunction[i] = c2pDispatchGeneral;
    }     driver->MajorFunction[IRP_MJ_READ] = c2pDispatchRead; 
    driver->MajorFunction [IRP_MJ_POWER] = c2pPower;         driver->MajorFunction [IRP_MJ_PNP] = c2pPnP;     // 卸载函数。
    driver->DriverUnload = c2pUnload; 
    // gDriverObject = DriverObject;    // 绑定所有键盘设备
    status =c2pAttachDevices(driver, reg_path);    return status;
}