阅读:1361回复:3
键盘过滤的问题
为何我的程序可以挂接键盘,都正常,但动态卸载后,再按键盘系统就会崩溃呢?? 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] |
|
沙发#
发布于:2007-02-04 21:59
好文章
|
|
板凳#
发布于:2004-12-08 09:42
呵呵,ctrl2cap本身作为一个WDM是不允许动态卸载的,因为你每次操作的时候,系统都会发IRP下来,然后在你的完成例程里完成,你卸载后还有未完成的IRP,导致完成例程执行时地址非法,你可以在IRP MJ READ里设置一个PENDING标志,每次经过加1,而在READ COMPLETITION里每次处理好后减1,在UNLOAD里判断PENGING是否为0,只有为0才可以退出,不然就KEDELAYEXECUTIONTHREAD等待吧.
其实作为过滤驱动而言,最好不要动态卸载,这也是MS的建议...... |
|
|
地板#
发布于: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); |
|