键盘过滤驱动- 学习结束

[写得很乱,不想再写了,原来的意思是想用界面控制驱动,动态替换按键,[因为有些键盘坏了,有些键不能用,比如wsx这几个键,暂时没好键盘,按虚拟键又麻烦的情况下,更改上面的FX键换它。]

差不多完成。。。链表及替换未写,这个很快就可以实现了,链表初始化分配内存,并把应用层(应用层里已把char转成ushort数组存在缓冲区中。格式1E 10 ...)的扫描码保存到结构中,就OK了。不过这样通迅好麻烦。

具体过程:先在DriverEntry入口函数把MJ的数组指向是生成一个新的设备[不是过滤设备]的各种分发函数,有设备名,还有MJ里设置控制IO的API,然后在应用层把扫描码要替换扫描码这种格式填上,点OK就发送到设备中,然后在这个设备的CONTROL IRP里创建一个新的设备,这个设备就是用来过滤键盘的设备。并更改driver里的分发函数地址成为有过滤后的IRP。卸载的话要判断是否是过滤设备。从而分开删除。

键盘过滤暂时到此,,,下一步不知是先看进程方面还是文件驱动。。

驱动代码:
#include <ntddk.h>
#include <ntddkbd.h>
#include <windef.h>
#include "control.h"

typedef struct _MY_LIST
{
USHORT uyMakeCode;//原来的扫描码
USHORT uhMakeCode;//替换后的扫描码
LIST_ENTRY ListEntry; //
}MY_LIST,*PMY_LIST;

typedef struct _FILTER_DEVICE_EXTEN
{
BOOL FilterFlags;
PDEVICE_OBJECT pFilterDeviceObject;//过滤设备
PDEVICE_OBJECT pTagerDeviceObject;//要绑定的设备对象
PDEVICE_OBJECT pLowDeviceObject;//绑定之后的下一个设备,在过滤设备下面
// KSPIN_LOCK Lockspin;//调用时的保护锁
// KEVENT ProcessEvent;//进程间同步
UNICODE_STRING DeviceSymoblic;
LIST_ENTRY ListHead;//list table head
}FILTER_DEVICE_EXTEN,*PFILTER_DEVICE_EXTEN;

ULONG gC2pKeyCount = 0;

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING puServiceRegPath);
VOID FilterUnload(IN PDRIVER_OBJECT pDriverObject);
NTSTATUS AllIrpOther(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp);
NTSTATUS FilterPower(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp);//IRP_MJ_POWER要调用一个PoCallDriver与PoStartNextPowerIrp
NTSTATUS FilterPnp(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp);//IRP_MJ_PNP还要一个PNP(即插即用)分发函数
NTSTATUS AttachDeviceObject(PDRIVER_OBJECT pDriverObject,PDEVICE_OBJECT *pOutDeviceObject);
NTSTATUS FilterReadIrp(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp);//read irp
NTSTATUS FilterCompletionRoutine(IN PDEVICE_OBJECT pCRDeviceObject,IN PIRP pCRIrp,IN PVOID Context);
NTSTATUS DeviceControlIrp(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp);//control irp

NTSTATUS TestCreateDevice(IN PDRIVER_OBJECT pDriverObject);
VOID TestUnload(IN PDRIVER_OBJECT pDriverObject);
VOID OkTestUnload(IN PDRIVER_OBJECT pDriverObject);
NTSTATUS TestCreate(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp);

#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, FilterUnload)
#pragma alloc_text (PAGE, AllIrpOther)
#pragma alloc_text (PAGE, FilterPower)

#pragma alloc_text (PAGE, FilterPnp)
#pragma alloc_text (INIT, AttachDeviceObject)
#pragma alloc_text (PAGE, FilterReadIrp)
#pragma alloc_text (PAGE, FilterCompletionRoutine)
#pragma alloc_text (PAGE, DeviceControlIrp)

#pragma alloc_text (INIT, TestCreateDevice)
#pragma alloc_text (PAGE, TestUnload)
#pragma alloc_text (PAGE, OkTestUnload)
#pragma alloc_text (PAGE, TestCreate)

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING puServiceRegPath)
{
// NTSTATUS status=STATUS_SUCCESS;
// int i;
// for (i=0;i<IRP_MJ_MAXIMUM_FUNCTION+1;i++)
// {
//   pDriverObject->MajorFunction[i]=AllIrpOther;
// }
// pDriverObject->DriverUnload=FilterUnload;//卸载函数
// pDriverObject->MajorFunction[IRP_MJ_POWER]=FilterPower;
// pDriverObject->MajorFunction[IRP_MJ_PNP]=FilterPnp;
// pDriverObject->MajorFunction[IRP_MJ_READ]=FilterReadIrp;
pDriverObject->MajorFunction[IRP_MJ_CREATE]=TestCreate;
pDriverObject->DriverUnload=TestUnload;//卸载函数
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=DeviceControlIrp;
// return AttachDeviceObject(pDriverObject);
return TestCreateDevice(pDriverObject);
}


/************************************************************************/
/* 其它直接用IoCallDriver把IRP传到下一层驱动中                         */
/************************************************************************/
NTSTATUS AllIrpOther(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
PFILTER_DEVICE_EXTEN pFilterExten;
    KdPrint(("Other IRP!\n"));
pFilterExten=(PFILTER_DEVICE_EXTEN)pDeviceObject->DeviceExtension;
    IoSkipCurrentIrpStackLocation(pIrp);
    return IoCallDriver(pFilterExten->pTagerDeviceObject,pIrp);
}

/************************************************************************/
/*生成过滤设备并绑定键盘设备及保存各种设备地址在扩展设备中              */
/************************************************************************/
NTSTATUS AttachDeviceObject(PDRIVER_OBJECT pDriverObject,PDEVICE_OBJECT *pOutDeviceObject)
{
NTSTATUS status;
UNICODE_STRING uKbdKeyName,DeviceName,DeviceSysmbolic;
PFILTER_DEVICE_EXTEN pFilterExten;
PDEVICE_OBJECT pFilterDevice;
PDEVICE_OBJECT pTargetDevice;
PDEVICE_OBJECT pLowDevice;
PFILE_OBJECT pFileOb;
RtlInitUnicodeString(&DeviceName,L"
");
RtlInitUnicodeString(&DeviceSysmbolic,L"
");
RtlInitUnicodeString(&uKbdKeyName, L"
");
status=IoGetDeviceObjectPointer(&uKbdKeyName,FILE_ALL_ACCESS,&pFileOb,&pTargetDevice);
if (!NT_SUCCESS(status))
{
   KdPrint(("Get Keyboard Error !\n"));
   return status;
} else
{
   ObDereferenceObject(pFileOb);//成功 根据设备名得到设备对象指针及文件对象指针
//   IoDeleteDevice(pTargetDevice);
}
//pFileOb->DeviceObject 这个才是真正想要的设备对象地址

status=IoCreateDevice(pDriverObject,
     sizeof(FILTER_DEVICE_EXTEN),
     &DeviceName,
     pTargetDevice->Type,
     pTargetDevice->Characteristics,
     TRUE,
     &pFilterDevice);
if (!NT_SUCCESS(status))
{
   KdPrint(("Create Error\n"));
//   ObDereferenceObject(pFileOb);
   IoDeleteDevice(pTargetDevice);
   return status;
}

status=IoCreateSymbolicLink(&DeviceSysmbolic,&DeviceName);
if (!NT_SUCCESS(status))
{
   KdPrint(("Create Symbolic Error\n"));
   IoDeleteDevice(pFilterDevice);
//   ObDereferenceObject(pFileOb);
   IoDeleteDevice(pTargetDevice);
   return status;
}

pLowDevice=IoAttachDeviceToDeviceStack(pFilterDevice,pTargetDevice);
if (!pLowDevice)
{
   KdPrint(("Create Attach Error\n"));
   IoDeleteSymbolicLink(&DeviceSysmbolic);
   IoDeleteDevice(pFilterDevice);
//   ObDereferenceObject(pFileOb);
   IoDeleteDevice(pTargetDevice);
   return STATUS_UNSUCCESSFUL;
}
pFilterExten=(PFILTER_DEVICE_EXTEN)pFilterDevice->DeviceExtension;
RtlZeroMemory(pFilterExten,sizeof(FILTER_DEVICE_EXTEN));//zero memory

    pFilterExten->pFilterDeviceObject=pFilterDevice;
    pFilterExten->pTagerDeviceObject=pTargetDevice;
    pFilterExten->DeviceSymoblic=DeviceSysmbolic;
    pFilterExten->pLowDeviceObject=pLowDevice;
    pFilterExten->FilterFlags=TRUE;//TRUE表示是过滤设备 FALSE表示控制设备
    pFilterDevice->DeviceType=pLowDevice->DeviceType;
    pFilterDevice->Characteristics=pLowDevice->Characteristics;
    pFilterDevice->StackSize=pLowDevice->StackSize+1;
    pFilterDevice->Flags |= pLowDevice->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE) ;
*pOutDeviceObject=pFilterDevice;//把生成的设备对象指针保存
   return STATUS_SUCCESS;
}

/************************************************************************/
/* IRP_MJ_POWER                                                        */
/************************************************************************/
NTSTATUS FilterPower(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
PFILTER_DEVICE_EXTEN pFilterExten;
    pFilterExten =(PFILTER_DEVICE_EXTEN)pDeviceObject->DeviceExtension;
    PoStartNextPowerIrp( pIrp );
    IoSkipCurrentIrpStackLocation( pIrp );
    return PoCallDriver(pFilterExten->pLowDeviceObject, pIrp );
}

/************************************************************************/
/* IRP_MJ_PNP                                                          */
/************************************************************************/
NTSTATUS FilterPnp(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
    PFILTER_DEVICE_EXTEN pFilterExten;
    PIO_STACK_LOCATION irpStack;
    NTSTATUS status = STATUS_SUCCESS;


    // 获得真实设备。
    pFilterExten = (PFILTER_DEVICE_EXTEN)(pDeviceObject->DeviceExtension);
    irpStack = IoGetCurrentIrpStackLocation(pIrp);
    switch (irpStack->MinorFunction)
    {
    case IRP_MN_REMOVE_DEVICE:
        KdPrint(("IRP_MN_REMOVE_DEVICE\n"));
  
        // 首先把请求发下去
        IoSkipCurrentIrpStackLocation(pIrp);
        IoCallDriver(pFilterExten->pLowDeviceObject, pIrp);
        // 然后解除绑定。
        IoDetachDevice(pFilterExten->pLowDeviceObject);
        // 删除我们自己生成的虚拟设备。
        IoDeleteDevice(pDeviceObject);
        status = STATUS_SUCCESS;
        break;
  
    default:
        // 对于其他类型的IRP,全部都直接下发即可。
        IoSkipCurrentIrpStackLocation(pIrp);
        status = IoCallDriver(pFilterExten->pLowDeviceObject, pIrp);
    }
    return status;
}


/************************************************************************/
/* UnLoad                                                              */
/************************************************************************/
VOID FilterUnload(IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pDeviceObject;
    PDEVICE_OBJECT OldDeviceObject;
    PFILTER_DEVICE_EXTEN pFilterExten;
    LARGE_INTEGER lDelay;
    PKTHREAD CurrentThread;
    //delay some time
    lDelay = RtlConvertLongToLargeInteger(-1000000);
    CurrentThread = KeGetCurrentThread();
    // 把当前线程设置为低实时模式,以便让它的运行尽量少影响其他程序。
    KeSetPriorityThread(CurrentThread, LOW_REALTIME_PRIORITY);
    UNREFERENCED_PARAMETER(pDriverObject);
    KdPrint(("DriverEntry unLoading...\n"));
    pDeviceObject = pDriverObject->DeviceObject;//从驱动对象得到{dy}个设备对象
while (pDeviceObject)//pDeviceObject is not NULL
{
   pFilterExten=(PFILTER_DEVICE_EXTEN)pDeviceObject->DeviceExtension;
   if (pFilterExten->FilterFlags)//filter device object
   {
    IoDeleteSymbolicLink(&pFilterExten->DeviceSymoblic);
    IoDetachDevice(pFilterExten->pLowDeviceObject); //过滤驱动要删除绑定
    pDeviceObject=pDeviceObject->NextDevice;
    IoDeleteDevice(pFilterExten->pFilterDeviceObject);
   } else
   {
    IoDeleteSymbolicLink(&pFilterExten->DeviceSymoblic);
    pDeviceObject=pDeviceObject->NextDevice;
    IoDeleteDevice(pFilterExten->pFilterDeviceObject);
   }

}


    while (gC2pKeyCount)
    {
        KeDelayExecutionThread(KernelMode, FALSE, &lDelay);
    }
    KdPrint(("DriverEntry unLoad OK!\n"));
    return;
}

/************************************************************************/
/* read irp                                                            */
/************************************************************************/
NTSTATUS FilterReadIrp(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
    NTSTATUS status;
    PFILTER_DEVICE_EXTEN pFilterExten;
    //PIO_STACK_LOCATION currentIrpStack;
//    KEVENT waitEvent;
status= STATUS_SUCCESS;
//    KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
if (pIrp->CurrentLocation == 1)
{
   KdPrint(("Dispatch encountered bogus current location\n"));
   status = STATUS_INVALID_DEVICE_REQUEST;
   pIrp->IoStatus.Status = status;
   pIrp->IoStatus.Information = 0;
   IoCompleteRequest(pIrp, IO_NO_INCREMENT);
   return(status);
}

    // 全局变量键计数器加1
    gC2pKeyCount++;

    // 得到设备扩展。目的是之后为了获得下一个设备的指针。
    pFilterExten=(PFILTER_DEVICE_EXTEN)pDeviceObject->DeviceExtension;

    // 设置回调函数并把IRP传递下去。 之后读的处理也就结束了。
    // 剩下的任务是要等待读请求完成。
    //currentIrpStack = IoGetCurrentIrpStackLocation(pIrp);
    IoCopyCurrentIrpStackLocationToNext(pIrp);
    IoSetCompletionRoutine( pIrp, FilterCompletionRoutine,
        pDeviceObject, TRUE, TRUE, TRUE );
    return IoCallDriver( pFilterExten->pLowDeviceObject, pIrp );
}

NTSTATUS FilterCompletionRoutine(IN PDEVICE_OBJECT pCRDeviceObject,IN PIRP pCRIrp,IN PVOID Context)
{
PIO_STACK_LOCATION IrpSp;
ULONG buf_len;
PUCHAR buf;
size_t i,numKeys;
PKEYBOARD_INPUT_DATA KeyData;
buf = NULL;
buf_len = 0;
IrpSp = IoGetCurrentIrpStackLocation( pCRIrp );

// 如果这个请求是成功的。很显然,如果请求失败了,这么获取
//   进一步的信息是没意义的。
if( NT_SUCCESS( pCRIrp->IoStatus.Status ) )
{
        // 获得读请求完成后输出的缓冲区
        buf = pCRIrp->AssociatedIrp.SystemBuffer;
   KeyData = (PKEYBOARD_INPUT_DATA)buf;
        // 获得这个缓冲区的长度。一般的说返回值有多长都保存在
        // Information中。
        buf_len = pCRIrp->IoStatus.Information;
        numKeys = buf_len / sizeof(KEYBOARD_INPUT_DATA);
        //… 这里可以做进一步的处理。我这里很简单的打印出所有的扫
        // 描码。
        //for(i=0;i<buf_len;++i)
   for(i=0;i<numKeys;++i)
        {
    if (KeyData[i].Flags)
    {
     DbgPrint("ScanCode: %x ", KeyData[i].MakeCode );
    }
    if (KeyData[i].MakeCode==0x43)
    {
     KeyData[i].MakeCode=0x10;
    }

        }
    }
    gC2pKeyCount--;

if( pCRIrp->PendingReturned )
{
   IoMarkIrpPending( pCRIrp );
}
    return pCRIrp->IoStatus.Status;
}


NTSTATUS DeviceControlIrp(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
NTSTATUS status;
PIO_STACK_LOCATION pIoStackLocation;
ULONG uControlCode,uInBufferLength;
PCHAR pInBufferChar;
PUSHORT pUshort;
PDRIVER_OBJECT pDriverObject;
PDEVICE_OBJECT pOutFilterObject;
int i;

status=STATUS_SUCCESS;
pIoStackLocation=IoGetCurrentIrpStackLocation(pIrp);//get IO_STACK_LOCATION
uControlCode=pIoStackLocation->Parameters.DeviceIoControl.IoControlCode;//get controlcode
uInBufferLength=pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength;//get in buffer length
switch(uControlCode)
{
case CTIO_EXE_SYS:
   {
    pUshort=(PUSHORT)pIrp->AssociatedIrp.SystemBuffer;
   // pDeviceObject->DriverObject->DriverUnload=OkTestUnload;//更改驱动的卸载函数
   // pDeviceObject->DriverObject->MajorFunction[IRP_MJ_CLOSE]=TestCreate;
    while (*pUshort)
    {
     KdPrint(("%x\n",*pUshort));
     pUshort++;
    }
    pDriverObject=pDeviceObject->DriverObject; //driver object
    status=AttachDeviceObject(pDriverObject,&pOutFilterObject);
    if (!NT_SUCCESS(status))
    {
     KdPrint(("Device Io Control AttachDevice Error !\n"));
     break;//exit switch
    }
/////////////////////////////////////////////////////////////////////////////
    // for (i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
    // {
    //   pDeviceObject->DriverObject->MajorFunction[i]=AllIrpOther;
    // }
     pDeviceObject->DriverObject->DriverUnload=FilterUnload;//卸载函数
     pDeviceObject->DriverObject->MajorFunction[IRP_MJ_POWER]=FilterPower;
     pDeviceObject->DriverObject->MajorFunction[IRP_MJ_PNP]=FilterPnp;
     pDeviceObject->DriverObject->MajorFunction[IRP_MJ_READ]=FilterReadIrp;
/////////////////////////////////////////////////////////////////////////////    
     break;//exit switch
   }
default:
   status = STATUS_INVALID_VARIANT;
}
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return status;
}


VOID TestUnload(IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pUnloadDevice;
PFILTER_DEVICE_EXTEN pUnloadExten;
KdPrint(("Unload \n"));
pUnloadDevice=pDriverObject->DeviceObject;
while (pUnloadDevice)
{
   pUnloadExten=(PFILTER_DEVICE_EXTEN)pUnloadDevice->DeviceExtension;
   IoDeleteSymbolicLink(&pUnloadExten->DeviceSymoblic);
   pUnloadDevice=pUnloadDevice->NextDevice;
   IoDeleteDevice(pUnloadExten->pFilterDeviceObject);
}
}


VOID OkTestUnload(IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pUnloadDevice;
PFILTER_DEVICE_EXTEN pUnloadExten;
KdPrint(("ok test Unload \n"));
pUnloadDevice=pDriverObject->DeviceObject;
while (pUnloadDevice)
{
   pUnloadExten=(PFILTER_DEVICE_EXTEN)pUnloadDevice->DeviceExtension;
   IoDeleteSymbolicLink(&pUnloadExten->DeviceSymoblic);
   pUnloadDevice=pUnloadDevice->NextDevice;
   IoDeleteDevice(pUnloadExten->pFilterDeviceObject);
}
}

NTSTATUS TestCreateDevice(IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pcDeviceObject;
PFILTER_DEVICE_EXTEN pDeviceExten;
UNICODE_STRING ucDeviceName,usDeviceSymbolic;
RtlInitUnicodeString(&ucDeviceName,L"
");
RtlInitUnicodeString(&usDeviceSymbolic,L"
");
status=IoCreateDevice(pDriverObject,sizeof(FILTER_DEVICE_EXTEN),&ucDeviceName,
   FILE_DEVICE_UNKNOWN,0,FALSE,&pcDeviceObject);
if (!NT_SUCCESS(status))
{
   KdPrint(("create error\n"));
   return status;
}
status=IoCreateSymbolicLink(&usDeviceSymbolic,&ucDeviceName);
if (!NT_SUCCESS(status))
{
   KdPrint(("create symbolic error\n"));
   IoDeleteDevice(pcDeviceObject);
   return status;
}
pDeviceExten=(PFILTER_DEVICE_EXTEN)pcDeviceObject->DeviceExtension;
RtlZeroMemory(pDeviceExten,sizeof(FILTER_DEVICE_EXTEN));
pDeviceExten->DeviceSymoblic=usDeviceSymbolic;
pDeviceExten->pFilterDeviceObject=pcDeviceObject;
pDeviceExten->FilterFlags=FALSE;
pcDeviceObject->Flags |= DO_BUFFERED_IO;
return status;
}

NTSTATUS TestCreate(IN PDEVICE_OBJECT pDeviceObject,IN PIRP pIrp)
{
KdPrint(("Create\n"));
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return pIrp->IoStatus.Status;
}

应用层代码:

按钮button
void CAppppDlg::OnButton1()
{
// TODO: Add your control notification handler code here
   CString str;
GetDlgItemText(IDC_EDIT1,str);
char *pBuffer = (LPTSTR)(LPCTSTR)str;
int i=strlen(pBuffer);
int ilen=sizeof(USHORT)*(i+2);
PUSHORT pMenp=(PUSHORT)malloc(ilen);
memset(pMenp,0,i+2);
_asm
{
   xor eax,eax
    mov edx,0
    mov ebx,1//标志
    mov esi,[pBuffer] //字符串地址
    mov edi,[pMenp] //要写入的目的地址
    mov ecx,0
   
comstart:
   mov al,BYTE PTR [esi]
    cmp al,41h
    jge completesm
    cmp al,39h
    jle completenum
   
completesm:
   cmp al,46h
    jle comsmok
   
   
completenum:
   cmp al,30h
    jge comnumok
   
comnumok:
   sub al,30h
    cmp ebx,1
    jz editnumok
    or al,dl //高位与低位相或结果放在al中
    mov BYTE PTR [edi],al
    add edi,2
    inc esi
    inc ebx
    inc ecx
    cmp ecx,i
    jz exitloop
    jmp comstart
comsmok:
  
   sub al,41h
    add al,10 //这里转为十六进制
    cmp ebx,1
    jz editsmok
    or al,dl //高位与低位相或结果放在al中
    mov BYTE PTR [edi],al
    add edi,2
    inc esi
    inc ebx
    inc ecx
    cmp ecx,i
    jz exitloop
    jmp comstart
   
editnumok:
  
   mov dl,al
    shl dl,4
    inc esi
    dec ebx
    inc ecx
    cmp ecx,i
    jz exitloop
    jmp comstart
   
editsmok:
  
   mov dl,al
    shl dl,4
    inc esi
    dec ebx
    inc ecx
    cmp ecx,i
    jz exitloop
    jmp comstart
   
   
exitloop:
  
}
HANDLE hFile=CreateFile("
",
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
          NULL );

if (hFile == INVALID_HANDLE_VALUE)
{
   char *outformat="%d";
    char outnum[4];
   wsprintfA(outnum,outformat,GetLastError());
   ::MessageBox(NULL,outnum,outnum,0);
   return;
   }

DWORD dwOutput;
DeviceIoControl(hFile,
      CTIO_EXE_SYS,
      pMenp,
      ilen,
      NULL,
      0,
      &dwOutput,
      NULL);
CloseHandle(hFile);
free(pMenp);
}



郑重声明:资讯 【键盘过滤驱动- 学习结束】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——