bj751212
驱动牛犊
驱动牛犊
  • 注册日期2004-10-11
  • 最后登录2005-04-26
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1360回复:3

键盘过滤的问题

楼主#
更多 发布于:2004-12-07 17:35
为何我的程序可以挂接键盘,都正常,但动态卸载后,再按键盘系统就会崩溃呢?? wowocock也发过这样的贴子,解决了吗?请说说

//======================================================================
#include "SeaKbFilter.h"

extern "C"

//----------------------------------------------------------------------
// DriverEntry
//----------------------------------------------------------------------
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
    UNICODE_STRING target_device_name;   //目标设备名
    PDEVICE_OBJECT target_device_object = NULL;
    
PDEVICE_OBJECT fdo = NULL;

NTSTATUS  status;

    PDEVICE_EXTENSION  pdx;
    
    RtlInitUnicodeString(&target_device_name, TARGET_DEVICE_NAME);
    
    //-----------------得到目标设备-----------------------------
status = IoGetDeviceObjectPointer(&target_device_name,
                                      0,
                                      &target_file_object,
                                      &target_device_object
                                      );
    if(!NT_SUCCESS(status))
{
  target_file_object = NULL;
       target_device_object= NULL;
       return status;
}

    //------------------建立设备fido-------------------------
    status = IoCreateDevice(DriverObject,                  
                            sizeof(DEVICE_EXTENSION),
                            NULL,                    
                            FILE_DEVICE_UNKNOWN,  
                            0,                    
                            FALSE,                
                            &fido              
                            );

    if (!NT_SUCCESS(status))
{
ObDereferenceObject(target_file_object);
        target_file_object = NULL;
        target_device_object= NULL;
        return (status);
    }
  
    pdx = (PDEVICE_EXTENSION)fido->DeviceExtension;
    
//新设备对象放到堆栈上,返回下一层设备对象的地址
fdo = IoAttachDeviceToDeviceStack(fido,target_device_object);

    if(!fdo)
    {
        IoDeleteDevice(fido);
        fido = NULL;
        ObDereferenceObject(target_file_object);
        target_file_object = NULL;
        target_device_object = NULL;
        return(status);
    }

    pdx->NextStackDevice = fdo;

fido->Flags |= fdo->Flags & (DO_DIRECT_IO|DO_BUFFERED_IO);
    fido->Flags |= DO_POWER_PAGABLE;
    fido->DeviceType = fdo->DeviceType;
    fido->Characteristics = fdo->Characteristics;
    fido->Flags &= ~DO_DEVICE_INITIALIZING;

    ULONG i;

    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
        DriverObject->MajorFunction = Ctrl2capDispatchGeneral;
    }

    DriverObject->MajorFunction[IRP_MJ_READ] = Ctrl2capDispatchRead;
    DriverObject->MajorFunction [IRP_MJ_POWER]  = Ctrl2capPower;
    DriverObject->MajorFunction [IRP_MJ_PNP]  = Ctrl2capPnP;

    DriverObject->DriverUnload = Ctrl2capUnload;

    return STATUS_SUCCESS;
}

//----------------------------------------------------------------------
// Ctrl2capPnP
//----------------------------------------------------------------------
NTSTATUS Ctrl2capPnP(IN PDEVICE_OBJECT DeviceObject,
                     IN PIRP Irp)
{
    PDEVICE_EXTENSION           devExt;
    PIO_STACK_LOCATION          irpStack;
    NTSTATUS                    status = STATUS_SUCCESS;
    KIRQL                       oldIrql;
    KEVENT                      event;        

    devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    switch (irpStack->MinorFunction)
{
        case IRP_MN_REMOVE_DEVICE:
           // Detach from the target device after passing the IRP down
  // the devnode stack.

           IoSkipCurrentIrpStackLocation(Irp);
           IoCallDriver(devExt->NextStackDevice,Irp);

           IoDetachDevice(devExt->NextStackDevice);
           IoDeleteDevice(DeviceObject);

           status = STATUS_SUCCESS;
           break;

        case IRP_MN_SURPRISE_REMOVAL:
           // Same as a remove device, but don't call IoDetach or IoDeleteDevice.
           IoSkipCurrentIrpStackLocation(Irp);
           status = IoCallDriver(devExt->NextStackDevice, Irp);
           break;

        case IRP_MN_START_DEVICE:
        case IRP_MN_QUERY_REMOVE_DEVICE:
        case IRP_MN_QUERY_STOP_DEVICE:
        case IRP_MN_CANCEL_REMOVE_DEVICE:
        case IRP_MN_CANCEL_STOP_DEVICE:
        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
        case IRP_MN_STOP_DEVICE:
        case IRP_MN_QUERY_DEVICE_RELATIONS:
        case IRP_MN_QUERY_INTERFACE:
        case IRP_MN_QUERY_CAPABILITIES:
        case IRP_MN_QUERY_DEVICE_TEXT:
        case IRP_MN_QUERY_RESOURCES:
        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
        case IRP_MN_READ_CONFIG:
        case IRP_MN_WRITE_CONFIG:
        case IRP_MN_EJECT:
        case IRP_MN_SET_LOCK:
        case IRP_MN_QUERY_ID:
        case IRP_MN_QUERY_PNP_DEVICE_STATE:

        default:
            IoSkipCurrentIrpStackLocation(Irp);
            status = IoCallDriver(devExt->NextStackDevice, Irp);
            break;
    }

    return status;
}


//----------------------------------------------------------------------
// Ctrl2capPower
//----------------------------------------------------------------------
NTSTATUS Ctrl2capPower(IN PDEVICE_OBJECT DeviceObject,
                       IN PIRP Irp)
{
    PDEVICE_EXTENSION devExt;
    
    devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    // Let the next power IRP out of the gate
    PoStartNextPowerIrp(Irp);
    
    // Pass this power IRP to the keyboard class driver
    IoSkipCurrentIrpStackLocation(Irp);
    
    return PoCallDriver(devExt->NextStackDevice, Irp);
}


//----------------------------------------------------------------------
// Ctrl2capUnload
//----------------------------------------------------------------------
VOID Ctrl2capUnload(IN PDRIVER_OBJECT Driver)
{
    UNREFERENCED_PARAMETER(Driver);

    PDEVICE_EXTENSION pdx;

if(target_file_object)
{
       ObDereferenceObject(target_file_object);
       target_file_object = NULL;
}

if(fido)
{
       pdx=(PDEVICE_EXTENSION)fido->DeviceExtension;
  if(pdx->NextStackDevice)
  {
          IoDetachDevice(pdx->NextStackDevice);  //把fido从设备栈中脱开:
  }
       IoDeleteDevice(fido);
       fido=NULL;
}

}

//----------------------------------------------------------------------
// Ctrl2capDispatchRead
//----------------------------------------------------------------------
NTSTATUS Ctrl2capDispatchRead(IN PDEVICE_OBJECT DeviceObject,
                              IN PIRP Irp)
{
    PDEVICE_EXTENSION   devExt;
    PIO_STACK_LOCATION  currentIrpStack;
    PIO_STACK_LOCATION  nextIrpStack;

    //
    // Gather our variables.
    //
    devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    nextIrpStack = IoGetNextIrpStackLocation(Irp);    

    // Push params down for keyboard class driver.

    *nextIrpStack = *currentIrpStack;

    // Set the completion callback, so we can "frob" the keyboard data.

    IoSetCompletionRoutine(Irp,
                  Ctrl2capReadComplete,
                           DeviceObject,
  TRUE,
  TRUE,
  TRUE);

    // Return the results of the call to the keyboard class driver.
    return IoCallDriver(devExt->NextStackDevice,Irp);
}

//----------------------------------------------------------------------
// Ctrl2capReadComplete
//----------------------------------------------------------------------
NTSTATUS Ctrl2capReadComplete(IN PDEVICE_OBJECT DeviceObject,
                              IN PIRP Irp,
 IN PVOID Context)
{
    PIO_STACK_LOCATION        IrpSp;
    PKEYBOARD_INPUT_DATA      KeyData;
    int                       numKeys, i;

    // Request completed - look at the result.
    IrpSp = IoGetCurrentIrpStackLocation(Irp);

    if(NT_SUCCESS(Irp->IoStatus.Status))
{
        KeyData = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
        numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);

        for( i = 0; i < numKeys; i++ )
{
            if(KeyData.MakeCode==LCONTROL)
{
               KeyData.MakeCode = SPACE;
            }

            if(KeyData.MakeCode==RCONTROL)
{
  KeyData.MakeCode = SPACE;
            }
        }
    }

    // Mark the Irp pending if required
    if( Irp->PendingReturned )
{
        IoMarkIrpPending(Irp);
    }
    return Irp->IoStatus.Status;
}

//----------------------------------------------------------------------
// Ctrl2capDispatchGeneral
//----------------------------------------------------------------------
NTSTATUS Ctrl2capDispatchGeneral(IN PDEVICE_OBJECT DeviceObject,
                                 IN PIRP Irp)
{
    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->NextStackDevice,Irp);
}


[编辑 -  12/7/04 by  bj751212]
bj751212
驱动牛犊
驱动牛犊
  • 注册日期2004-10-11
  • 最后登录2005-04-26
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-12-07 17:36
头文件

#ifdef __cplusplus

extern "C"
{
#endif

#include <ntddk.h>
#include <ntddkbd.h>
#include "stdarg.h"
#include "stdio.h"
#include "ntddkbd.h"

#ifdef __cplusplus
}
#endif

#define KEY_UP         1
#define KEY_DOWN       0

#define LCONTROL       ((USHORT)0x1D)
#define RCONTROL       ((USHORT)0xE01D)
#define SPACE          ((USHORT)0x39)


typedef struct _DEVICE_EXTENSION
{
   PDEVICE_OBJECT NextStackDevice;
  
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

PFILE_OBJECT target_file_object = NULL;
PDEVICE_OBJECT fido;

#define TARGET_DEVICE_NAME L"\\Device\\KeyboardClass0"

NTSTATUS Ctrl2capPnP(IN PDEVICE_OBJECT DeviceObject,
                     IN PIRP Irp);

NTSTATUS Ctrl2capPower(IN PDEVICE_OBJECT DeviceObject,
                       IN PIRP Irp);

VOID Ctrl2capUnload(IN PDRIVER_OBJECT Driver);

NTSTATUS Ctrl2capDispatchRead(IN PDEVICE_OBJECT DeviceObject,
 IN PIRP Irp);

NTSTATUS Ctrl2capDispatchGeneral(IN PDEVICE_OBJECT DeviceObject,
                                 IN PIRP Irp);

NTSTATUS Ctrl2capReadComplete(IN PDEVICE_OBJECT DeviceObject,
 IN PIRP Irp,
 IN PVOID Context);
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
板凳#
发布于:2004-12-08 09:42
呵呵,ctrl2cap本身作为一个WDM是不允许动态卸载的,因为你每次操作的时候,系统都会发IRP下来,然后在你的完成例程里完成,你卸载后还有未完成的IRP,导致完成例程执行时地址非法,你可以在IRP MJ READ里设置一个PENDING标志,每次经过加1,而在READ COMPLETITION里每次处理好后减1,在UNLOAD里判断PENGING是否为0,只有为0才可以退出,不然就KEDELAYEXECUTIONTHREAD等待吧.
其实作为过滤驱动而言,最好不要动态卸载,这也是MS的建议......
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
xiaopengyp
驱动牛犊
驱动牛犊
  • 注册日期2005-08-30
  • 最后登录2008-03-10
  • 粉丝0
  • 关注0
  • 积分520分
  • 威望53点
  • 贡献值0点
  • 好评度52点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-02-04 21:59
好文章
游客

返回顶部