wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
阅读:1698回复:5

键盘过滤驱动

楼主#
更多 发布于:2003-09-22 17:18
为何我的程序可以挂接键盘,都正常,但退出以后,再按键盘系统就会崩溃呢??
//======================================================================
//======================================================================
//
// Ctrl2cap
//
// Copyright (C) 1996-1999 Mark Russinovich
//
// Hook onto the keyboard I/O path and massage the input stream
// converting caps-locks into controls. This example works on
// NT 4 and Win2K and the Win2K version is very losely based on the
// i8042 port filter driver sample, kbfiltr, from the Win2K DDK.
//
// For every function I list whether the function gets called
// under NT 4, WIN2K, or both.
//
// File: ctrl2cap.c
//
//======================================================================
#include \"ntddk.h\"
#include <ntddkbd.h>
#include \"stdarg.h\"
#include \"stdio.h\"
#include \"ctrl2cap.h\"
#include \"ntddkbd.h\"
//----------------------------------------------------------------------
//
// DriverEntry
//
// Installable driver initialization. Here we just set ourselves up.
//
// Called: NT4, WIN2K
//
//----------------------------------------------------------------------
NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
    ULONG                  i;
    NTSTATUS status;
    DbgPrint ((\"Ctrl2cap.SYS: entering DriverEntry\\n\"));

    //
    // Fill in all the dispatch entry points with the pass through function
    // and the explicitly fill in the functions we are going to intercept
    //
    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{

        DriverObject->MajorFunction = Ctrl2capDispatchGeneral;
    }

    //
    // Our read function is where we do our real work.
    //
    DriverObject->MajorFunction[IRP_MJ_READ] = Ctrl2capDispatchRead;

    //
    // Power IRPs are the only ones we have to handle specially under
    // Win2k since they require the special PoCallDriver and
    // PoStartNextPowerIrp function calls.
    //
    DriverObject->MajorFunction [IRP_MJ_POWER]  = Ctrl2capPower;

    //
    // The only reason we need to handle PnP IRPs is to know when
    // a device we\'ve attached to disappears (is removed).
    //
    DriverObject->MajorFunction [IRP_MJ_PNP]  = Ctrl2capPnP;

    //
    // Under Win2K we get told about the presence of keyboard
    // devices through our AddDevice entry point.
    //
    DriverObject->DriverUnload = Ctrl2capUnload;
    status =Ctrl2capAddDevice(DriverObject, RegistryPath);;

    return status;;
}

//----------------------------------------------------------------------
//
// Ctrl2capAddDevice
//
// The PnP Manager calls us for each keyboard present on the system.
// We attach to each one so that we can flip caps lock to controls.
//
// Called: WIN2K
//
//----------------------------------------------------------------------
NTSTATUS
Ctrl2capAddDevice(
    IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
    )
{
    NTSTATUS    status = 0;
UNICODE_STRING uniNtNameString, linkString;
PMyFilter_DeviceExtension pMyFilter_DeviceExtension;
PDEVICE_OBJECT pFilterDeviceObject = NULL;
PDEVICE_OBJECT pTargetDeviceObject = NULL;
PFILE_OBJECT pTargetFileObject = NULL;
PDEVICE_OBJECT pLowerDeviceObject = NULL;

    DbgPrint((\"MyAttach.\\n\"));

    RtlInitUnicodeString(&uniNtNameString, MYTEST_DEVICE_NAME);

status = IoGetDeviceObjectPointer(
               IN &uniNtNameString,
               IN FILE_READ_ATTRIBUTES,
               OUT &pTargetFileObject,  
               OUT &pTargetDeviceObject
               );
if(!NT_SUCCESS(status))
{
DbgPrint((\"MyAttach: Couldn\'t get the MyTest Device Object\\n\"));
pTargetFileObject = NULL;
pTargetDeviceObject = NULL;
return( status );
}

//
    // Create a filter device and attach it to the device stack.
    //
    RtlInitUnicodeString(&uniNtNameString, MYFILTER__DEVICE_NAME);

status = IoCreateDevice(
               IN DriverObject,
               IN sizeof(MyFilter_DeviceExtension),
               IN &uniNtNameString,
               IN pTargetDeviceObject->DeviceType,
               IN pTargetDeviceObject->Characteristics,
               IN FALSE,                
               OUT &pFilterDeviceObject
               );
    if (!NT_SUCCESS(status))
{

DbgPrint((\"MyAttach: Couldn\'t create the MyFilter Filter Device Object\\n\"));
ObDereferenceObject(pTargetFileObject);
pTargetFileObject = NULL;
pTargetDeviceObject = NULL;
        return (status);
        }

    pLowerDeviceObject = IoAttachDeviceToDeviceStack(pFilterDeviceObject, pTargetDeviceObject);
if(!pLowerDeviceObject)
{
DbgPrint((\"MyAttach: Couldn\'t attach to MyTest Device Object\\n\"));
IoDeleteDevice(pFilterDeviceObject);
pFilterDeviceObject = NULL;
ObDereferenceObject(pTargetFileObject);
pTargetFileObject = NULL;
pTargetDeviceObject = NULL;
return( status );
}

pMyFilter_DeviceExtension = (PMyFilter_DeviceExtension)(pFilterDeviceObject->DeviceExtension);
MyFilter_InitDeviceExtension(
IN pMyFilter_DeviceExtension,
IN pFilterDeviceObject,
IN pTargetDeviceObject,
IN pTargetFileObject,
IN pLowerDeviceObject
);

pFilterDeviceObject->DeviceType=pLowerDeviceObject->DeviceType;
    pFilterDeviceObject->Characteristics=pLowerDeviceObject->Characteristics;
pFilterDeviceObject->StackSize=pLowerDeviceObject->StackSize+1;
pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO \\
                                                     | DO_POWER_PAGABLE) ;

return status;
}

NTSTATUS
MyFilter_InitDeviceExtension(
IN PMyFilter_DeviceExtension pMyFilter_DeviceExtension,
IN PDEVICE_OBJECT pFilterDeviceObject,
IN PDEVICE_OBJECT pTargetDeviceObject,
IN PFILE_OBJECT pTargetFileObject,
IN PDEVICE_OBJECT pLowerDeviceObject
)
{
memset(pMyFilter_DeviceExtension, 0, sizeof(MyFilter_DeviceExtension));
pMyFilter_DeviceExtension->NodeSize = sizeof(MyFilter_DeviceExtension);
pMyFilter_DeviceExtension->pFilterDeviceObject = pFilterDeviceObject;
KeInitializeSpinLock(&(pMyFilter_DeviceExtension->IoRequestsSpinLock));
KeInitializeEvent(&(pMyFilter_DeviceExtension->IoInProgressEvent), NotificationEvent, FALSE);
pMyFilter_DeviceExtension->TargetDeviceObject = pTargetDeviceObject;
pMyFilter_DeviceExtension->TargetFileObject = pTargetFileObject;
pMyFilter_DeviceExtension->LowerDeviceObject = pLowerDeviceObject;

return( STATUS_SUCCESS );
}
//----------------------------------------------------------------------
//
// Ctrl2capPnP
//
// We have to handle PnP IRPs so that we detach from target
// devices when appropriate.
//
// Called: WIN2K
//
//----------------------------------------------------------------------
NTSTATUS Ctrl2capPnP(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
{
    PMyFilter_DeviceExtension pMyFilter_DeviceExtension;
    PIO_STACK_LOCATION          irpStack;
    NTSTATUS                    status = STATUS_SUCCESS;
    KIRQL                       oldIrql;
    KEVENT                      event;        

    pMyFilter_DeviceExtension = (PMyFilter_DeviceExtension)(DeviceObject->DeviceExtension);
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    switch (irpStack->MinorFunction) {
    case IRP_MN_REMOVE_DEVICE:
        DbgPrint((\"IRP_MN_REMOVE_DEVICE\\n\"));
        //
        // Detach from the target device after passing the IRP
        // down the devnode stack.
        //
        IoSkipCurrentIrpStackLocation(Irp);
        IoCallDriver(pMyFilter_DeviceExtension->LowerDeviceObject, Irp);

        IoDetachDevice(pMyFilter_DeviceExtension->LowerDeviceObject);
        IoDeleteDevice(DeviceObject);

        status = STATUS_SUCCESS;
        break;

    case IRP_MN_SURPRISE_REMOVAL:
         DbgPrint((\"IRP_MN_SURPRISE_REMOVAL\\n\"));
        //
        // Same as a remove device, but don\'t call IoDetach or IoDeleteDevice.
        //
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(pMyFilter_DeviceExtension->LowerDeviceObject, 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:
        DbgPrint((\"OTHER_IRP\\n\"));
//
        // Pass these through untouched
        //
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(pMyFilter_DeviceExtension->LowerDeviceObject, Irp);
        break;
    }

    return status;
}


//----------------------------------------------------------------------
//
// Ctrl2capPower
//
// We have to handle Power IRPs specially.
//
// Called: WIN2K
//
//----------------------------------------------------------------------
NTSTATUS Ctrl2capPower(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
{
    PMyFilter_DeviceExtension pMyFilter_DeviceExtension;
    
    pMyFilter_DeviceExtension = (PMyFilter_DeviceExtension)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(pMyFilter_DeviceExtension->LowerDeviceObject, Irp );
}

 // WIN2K


//----------------------------------------------------------------------
//
// Ctrl2capReadComplete
//
// Gets control after a read operation has completed.
//
// Called: WIN2K, NT4
//
//----------------------------------------------------------------------
NTSTATUS Ctrl2capReadComplete(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )
{
    PIO_STACK_LOCATION        IrpSp;
    PKEYBOARD_INPUT_DATA      KeyData;
    int                       numKeys, i;

    //
    IrpSp = IoGetCurrentIrpStackLocation( Irp );
    if( NT_SUCCESS( Irp->IoStatus.Status ) ) {

        //
        // Do caps-lock down and caps-lock up. Note that
        // just frobbing the MakeCode handles both the up-key
        // and down-key cases since the up/down information is specified
        // seperately in the Flags field of the keyboard input data
        // (0 means key-down, 1 means key-up).
        //
        KeyData = Irp->AssociatedIrp.SystemBuffer;
        numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);

        for( i = 0; i < numKeys; i++ ) {

            DbgPrint((\"ScanCode: %x \", KeyData.MakeCode ));
            DbgPrint((\"%s\\n\", KeyData.Flags ? \"Up\" : \"Down\" ));

            if( KeyData.MakeCode == CAPS_LOCK) {

                KeyData.MakeCode = LCONTROL;
            }
        }
    }

    //
    // Mark the Irp pending if required
    //
    if( Irp->PendingReturned ) {

        IoMarkIrpPending( Irp );
    }
return Irp->IoStatus.Status;
}


//----------------------------------------------------------------------
//
// Ctrl2capDispatchRead
//
// Sets up to look at the read request completion so that we can
// massage the input queue on IO completion.
//
// Called: WIN2K, NT4
//
//----------------------------------------------------------------------
NTSTATUS Ctrl2capDispatchRead(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp )
{
    NTSTATUS RC = STATUS_SUCCESS;
PMyFilter_DeviceExtension pMyFilter_DeviceExtension;
    PIO_STACK_LOCATION  currentIrpStack;
    PIO_STACK_LOCATION  nextIrpStack;

    //
    // Gather our variables.
    //
    if (Irp->CurrentLocation == 1)
{
ULONG ReturnedInformation = 0;

DbgPrint((\"Dispatch encountered bogus current location\\n\"));

RC = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Status = RC;
Irp->IoStatus.Information = ReturnedInformation;
IoCompleteRequest(Irp, IO_NO_INCREMENT);

return(RC);
}

pMyFilter_DeviceExtension = (PMyFilter_DeviceExtension)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( pMyFilter_DeviceExtension->LowerDeviceObject, Irp );
}


//----------------------------------------------------------------------
//
// Ctrl2capDispatchGeneral
//
// This handles several functions we are not interested in
// along to the keyboard class driver.
//
// Called: WIN2K, NT4
//
//----------------------------------------------------------------------
NTSTATUS Ctrl2capDispatchGeneral(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
{
    //
    // Pass the IRP to the target without touching the IRP
    //

    DbgPrint((\"Other Diapatch!\"));
    IoSkipCurrentIrpStackLocation(Irp);
#ifdef WINNT4  // WIN2K
    //
    // This is the equivalent of the IoSkipCurrentIrpStackLocation macro,
    // which doesn\'t exist in the NT 4 DDK.
    //
    Irp->CurrentLocation++;
    Irp->Tail.Overlay.CurrentStackLocation++;
#endif // WIN2K
    return IoCallDriver(((PMyFilter_DeviceExtension) DeviceObject->DeviceExtension)->LowerDeviceObject, Irp);
}

//----------------------------------------------------------------------
//
// Ctrl2capUnload
//
// Our Win2K PnP unload function. We don\'t need to do anything.
//
// Called: WIN2K
//
//----------------------------------------------------------------------

VOID
Ctrl2capUnload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT OldDeviceObject;
PMyFilter_DeviceExtension pMyFilter_DeviceExtension;
    
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint((\"DriverEntry unLoading...\\n\"));

DeviceObject = DriverObject->DeviceObject;
MyDetach(DeviceObject);
ASSERT(NULL == DriverObject->DeviceObject);
return;
}




VOID
MyDetach(IN PDEVICE_OBJECT pDeviceObject)
{
PMyFilter_DeviceExtension pMyFilter_DeviceExtension;
BOOLEAN NoRequestsOutstanding = FALSE;

pMyFilter_DeviceExtension = (PMyFilter_DeviceExtension)pDeviceObject->DeviceExtension;

try
{
try
{
IoDetachDevice(pMyFilter_DeviceExtension->TargetDeviceObject);//LowerDeviceObject,TargetDeviceObject);

if(pMyFilter_DeviceExtension->TargetFileObject)
ObDereferenceObject(pMyFilter_DeviceExtension->TargetFileObject);
pMyFilter_DeviceExtension->TargetFileObject = NULL;
   pMyFilter_DeviceExtension->TargetDeviceObject = NULL;
IoDeleteDevice(pDeviceObject);
            pMyFilter_DeviceExtension->pFilterDeviceObject = NULL;
DbgPrint((\"Detach Finished\\n\"));
}
except (EXCEPTION_EXECUTE_HANDLER){}
}
finally{}
return;
}

[编辑 -  9/22/03 by  wowocock]

最新喜欢:

hartonoharton...
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
AllenZh
驱动老牛
驱动老牛
  • 注册日期2001-08-19
  • 最后登录2015-11-27
  • 粉丝19
  • 关注10
  • 积分1316分
  • 威望2387点
  • 贡献值7点
  • 好评度321点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-09-30 14:31
是不是模块已经释放了但还有IRP没有处理完呀
1,承接Windows下驱动/应用开发 2,本人原创虚拟鼠标/键盘,触摸屏,虚拟显卡,Mirror驱动,XP无盘的SCSI虚拟磁盘驱动等 3,windows下有尝技术服务(包括BUG调试,员工培训等) 欢迎深圳和海外企业联系.msn:mfczmh@sina.com
arthurtu
驱动巨牛
驱动巨牛
  • 注册日期2001-11-08
  • 最后登录2020-12-19
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望161点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
  • 社区居民
板凳#
发布于:2003-09-30 18:46
呵呵
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
地板#
发布于:2003-10-09 13:19
对,该如何解决呢??难道就不能卸载不成????
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
punk
驱动小牛
驱动小牛
  • 注册日期2001-04-07
  • 最后登录2018-06-01
  • 粉丝0
  • 关注0
  • 积分621分
  • 威望164点
  • 贡献值0点
  • 好评度60点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-07-09 12:35
对,该如何解决呢??难道就不能卸载不成????

可以用一个计数器,只有计数器为0的时候才释放它
不停学习
punk
驱动小牛
驱动小牛
  • 注册日期2001-04-07
  • 最后登录2018-06-01
  • 粉丝0
  • 关注0
  • 积分621分
  • 威望164点
  • 贡献值0点
  • 好评度60点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-07-13 14:31
[quote]对,该如何解决呢??难道就不能卸载不成????

可以用一个计数器,只有计数器为0的时候才释放它 [/quote]
或者在unload里对没完成的irp调用iocancelirp,这样就可以迅
速unload了。
当然可能需要一个 list记录为完成的irp,不过根据经验只有一个没有完成的irp
不停学习
游客

返回顶部