首页
社区
课程
招聘
[求助]WDM驱动处理IRP_MN_REMOVE_DEVICE意外IRQL_NOT_LESS_OR_EQUAL
发表于: 2013-5-1 11:26 10070

[求助]WDM驱动处理IRP_MN_REMOVE_DEVICE意外IRQL_NOT_LESS_OR_EQUAL

2013-5-1 11:26
10070
如题,我写了一个WDM模型过滤驱动程序,注册表同时挂接在Mouclass和Kbdclass的LowerFilter上。系统启动的时候收到了一个IRP_MJ_PNP,IRP_MN_QUERY_REMOVE_DEVICE的IRP,然后我就删除创建的设备对象,但是这个过程中就直接BSOD了,原因IRQL_NOT_LESS_OR_EQUAL。我看了半天实在找不出来到底哪里升了IRQL,甚至我在每两行代码间都加入了if(KeGetCurrentIrql()>PASSIVE_LEVEL){__asm int 3},但是都断不下来。代码如下。

NTSTATUS 
WKC_PnP(
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp
    )
{
    DebugTracePrint(
        DEBUG_NORMAL_INFO,
        "WKC_PnP",
        ("Function entered."));
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
    PWKC_DEVICE_EXTENSION pExt = ((PWKC_DEVICE_EXTENSION)DeviceObject->DeviceExtension);
    NTSTATUS status;
 
    ASSERT(pExt);
 
    switch (irpSp->MinorFunction){
 
    case IRP_MN_START_DEVICE:
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
 
    case IRP_MN_QUERY_REMOVE_DEVICE:
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
 
    case IRP_MN_REMOVE_DEVICE:
 
        status = WKC_ForwardIrpSynchronous(DeviceObject, Irp);
 
        DetachDevice(DeviceObject);//此处出错
 
        Irp->IoStatus.Status = STATUS_SUCCESS;
 
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
 
    case IRP_MN_QUERY_PNP_DEVICE_STATE:
        status = WKC_ForwardIrpSynchronous(DeviceObject, Irp);
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }
 
    return WKC_DefaultHandler(DeviceObject, Irp);
}
 
NTSTATUS WKC_ForwardIrpSynchronous(
    IN PDEVICE_OBJECT pDeviceObject,
    IN PIRP pIrp
    )
{
    PWKC_DEVICE_EXTENSION   devExtension;
    KEVENT pEvent;
    NTSTATUS status;
 
    DebugTracePrint(
        DEBUG_NORMAL_INFO,
        "WKC_ForwardIrpSynchronous",
        ("Synchronizing IRP."));  
 
    KeInitializeEvent(&pEvent, NotificationEvent, FALSE);
 
    devExtension = (PWKC_DEVICE_EXTENSION) pDeviceObject->DeviceExtension;
 
    IoCopyCurrentIrpStackLocationToNext(pIrp);
 
    IoSetCompletionRoutine(pIrp, WKC_IrpCompletion, &pEvent, TRUE, TRUE, TRUE);
 
    status = IoCallDriver(devExtension->pTargetDeviceObject, pIrp);
 
    if (status == STATUS_PENDING) {
        KeWaitForSingleObject(&pEvent, Executive, KernelMode, FALSE, NULL);
        status = pIrp->IoStatus.Status;
    }
 
    DebugTracePrint(
        DEBUG_NORMAL_INFO,
        "WKC_ForwardIrpSynchronous",
        (" IRP Synchronize finished."));  
 
    return status;
}
 
VOID 
DetachDevice(
    IN PDEVICE_OBJECT pDeviceObject
    ) 
{ 
    PWKC_DEVICE_EXTENSION devExtension; 
 
    BOOLEAN NoRequestsOutstanding = FALSE;
 
    DebugTracePrint(
        DEBUG_NORMAL_INFO,
        "DetachDevice",
        ("Function enterd."));
 
    devExtension = (PWKC_DEVICE_EXTENSION)pDeviceObject->DeviceExtension; 
    __try { 
        __try { 
            IoDetachDevice(devExtension->pTargetDeviceObject);
 
            devExtension->pTargetDeviceObject = NULL; 
 
            IoDeleteDevice(pDeviceObject); 
 
            devExtension->pFilterDeviceObject = NULL; //此处出错
 
            DebugTracePrint(
                DEBUG_NORMAL_INFO,
                "DetachDevice",
                ("Detach Finished."));
        } 
        __except (EXCEPTION_EXECUTE_HANDLER){
            DebugTracePrint(
                DEBUG_ERROR,
                "DetachDevice",
                ("Something wrong occured when detach the device. SEH handled."));
        } 
    } 
    __finally{} 
    return; 
}


以下是Windbg分析

*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************
 
IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 00000000, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, bitfield :
    bit 0 : value 0 = read operation, 1 = write operation
    bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status)
Arg4: 80524f8c, address which referenced memory
 
Debugging Details:
------------------
 
*** No owner thread found for resource 80552f60
*** No owner thread found for resource 80552f60
*** No owner thread found for resource 80552f60
 
WRITE_ADDRESS:  00000000 
 
CURRENT_IRQL:  2
 
FAULTING_IP: 
nt!PoRegisterDeviceForIdleDetection+46
80524f8c 8901            mov     dword ptr [ecx],eax
 
DEFAULT_BUCKET_ID:  DRIVER_FAULT
 
BUGCHECK_STR:  0xA
 
PROCESS_NAME:  System
 
TRAP_FRAME:  f8af5a8c -- (.trap 0xfffffffff8af5a8c)
ErrCode = 00000002
eax=8208ef18 ebx=8055ac08 ecx=00000000 edx=00000000 esi=820822a4 edi=820822b4
eip=80524f8c esp=f8af5b00 ebp=f8af5b10 iopl=0         nv up ei pl nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010202
nt!PoRegisterDeviceForIdleDetection+0x46:
80524f8c 8901            mov     dword ptr [ecx],eax  ds:0023:00000000=????????
Resetting default scope
 
LOCK_ADDRESS:  80552fe0 -- (!locks 80552fe0)
 
Resource @ nt!IopDeviceTreeLock (0x80552fe0)    Shared 1 owning threads
     Threads: 821b7640-01<*> 
1 total locks, 1 locks currently held
 
PNP_TRIAGE: 
    Lock address  : 0x80552fe0
    Thread Count  : 1
    Thread address: 0x821b7640
    Thread wait   : 0x5da
 
LAST_CONTROL_TRANSFER:  from 804f8b9d to 80528bdc
 
STACK_TEXT:  
f8af5640 804f8b9d 00000003 f8af599c 00000000 nt!RtlpBreakWithStatusInstruction
f8af568c 804f978a 00000003 00000000 80524f8c nt!KiBugCheckDebugBreak+0x19
f8af5a6c 80541683 0000000a 00000000 00000002 nt!KeBugCheck2+0x574
f8af5a6c 80524f8c 0000000a 00000000 00000002 nt!KiTrap0E+0x233
f8af5b10 80649d0e 820821d8 00000000 00000000 nt!PoRegisterDeviceForIdleDetection+0x46
f8af5b34 804f1915 820821d8 8218a170 f8af5b7c nt!PoRunDownDeviceObject+0x1c
f8af5b44 f892b3d2 820821d8 81d40c64 8218a170 nt!IoDeleteDevice+0x4d
f8af5b7c f892bd6b 820821d8 00000002 00000001 Subci_WinKernelCaptor!DetachDevice+0x92 [d:\projects\bciseries\subci_winkernelcaptor\attachmanage.cpp @ 325]
f8af5b9c 804ef119 820821d8 81d40b40 f8af5c28 Subci_WinKernelCaptor!WKC_PnP+0xeb [d:\projects\bciseries\subci_winkernelcaptor\dispatchroutines.cpp @ 338]
f8af5bac 80588fc9 8208ef18 8208ef18 00000002 nt!IopfCallDriver+0x31
f8af5bd8 805890ed 820821d8 f8af5c04 00000000 nt!IopSynchronousCall+0xb7
f8af5c2c 804f6e86 8208ef18 00000002 00000000 nt!IopRemoveDevice+0x93
f8af5c54 8058ac06 e14ea8c8 0000001f e1691888 nt!IopRemoveLockedDeviceNode+0x160
f8af5c6c 8058ac6d 8208e3c0 00000002 e1691888 nt!IopDeleteLockedDeviceNode+0x34
f8af5ca0 805908dd 8208ef18 02691888 00000002 nt!IopDeleteLockedDeviceNodes+0x3f
f8af5d34 80590ba0 f8af5d70 806d3778 e16578b0 nt!PiProcessQueryRemoveAndEject+0x76b
f8af5d50 80590ce6 f8af5d70 82134200 8055c0fc nt!PiProcessTargetDeviceEvent+0x2a
f8af5d74 80535c02 82134200 00000000 821b7640 nt!PiWalkDeviceList+0xea
f8af5dac 805c7160 82134200 00000000 00000000 nt!ExpWorkerThread+0x100
f8af5ddc 80542dd2 80535b02 00000001 00000000 nt!PspSystemThreadStartup+0x34
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16
 
 
STACK_COMMAND:  kb
 
FOLLOWUP_IP: 
Subci_WinKernelCaptor!DetachDevice+92 [d:\projects\bciseries\subci_winkernelcaptor\attachmanage.cpp @ 325]
f892b3d2 8b4de0          mov     ecx,dword ptr [ebp-20h]
 
FAULTING_SOURCE_CODE:  
   321:             devExtension->pTargetDeviceObject = NULL; 
   322: 
   323:             IoDeleteDevice(pDeviceObject); 
   324: 
>  325:             devExtension->pFilterDeviceObject = NULL; 
   326: 
   327:             DebugTracePrint(
   328:                 DEBUG_NORMAL_INFO,
   329:                 "DetachDevice",
   330:                 ("Detach Finished."));
 
 
SYMBOL_STACK_INDEX:  7
 
SYMBOL_NAME:  Subci_WinKernelCaptor!DetachDevice+92
 
FOLLOWUP_NAME:  MachineOwner
 
MODULE_NAME: Subci_WinKernelCaptor
 
IMAGE_NAME:  Subci_WinKernelCaptor.sys
 
DEBUG_FLR_IMAGE_TIMESTAMP:  517fcac7
 
FAILURE_BUCKET_ID:  0xA_Subci_WinKernelCaptor!DetachDevice+92
 
BUCKET_ID:  0xA_Subci_WinKernelCaptor!DetachDevice+92
 
Followup: MachineOwner
---------


LOCK_ADDRESS:  80552fe0 -- (!locks 80552fe0)
Resource @ nt!IopDeviceTreeLock (0x80552fe0)    Shared 1 owning threads
实在是看不出这个锁是哪里来的。IRP_MJ_PNP的派遣函数和WKC_ForwardIrpSynchronous基本上是VisualDDK生成的,完全郁闷了,不知道怎么办。是不是鼠标或者键盘的IRP_MN_QUERY_REMOVE_DEVICE要特殊处理,还是什么别的情况?另外我不是已经用了__try了,SEH为什么不能捕捉到这个BSOD?

还请各位大牛帮我一把……快把一个五一假期郁闷完了……

另外囊中羞涩,拿不出太多悬赏……实在抱歉……

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

收藏
免费 0
支持
分享
最新回复 (11)
雪    币: 65
活跃值: (112)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
基本常识要有吧?

空指针访问这种简单问题都看不出么???
2013-5-1 11:50
0
雪    币: 73
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
肯定不是空指针了……如果是空指针的话怎么可能纠结那么长时间呢……

kd> DT devExtension 
Local var @ 0xf8af5b5c Type _WKC_DEVICE_EXTENTION*
0x820ab368 
   +0x000 ulSize           : 0x28
   +0x004 pFilterDeviceObject : 0x820ab2b0 _DEVICE_OBJECT
   +0x008 IoRequestsSpinLock : 0
   +0x00c IoInProgressEvent : _KEVENT
   +0x01c DeviceType       : 0x32
   +0x020 pTargetDeviceObject : 0x824f53d8 _DEVICE_OBJECT
   +0x024 pLowerDeviceObject : 0x824f53d8 _DEVICE_OBJECT


devExtension是没有问题的
2013-5-1 17:39
0
雪    币: 73
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
另外重新跟踪了一下,应该是            
IoDeleteDevice(pDeviceObject); 这一句出错,Windbg识别错位了一行……
2013-5-1 17:43
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
windbg没错。。。。windbg报告的是返回地址。。。。
2013-5-2 08:48
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
IRP没发出去,你就删除设备对象了?????
2013-5-2 08:49
0
雪    币: 73
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
 status = WKC_ForwardIrpSynchronous(DeviceObject, Irp);


这是用来下发IRP然后等待返回的……应该是发出去了
2013-5-2 19:08
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
 status = WKC_ForwardIrpSynchronous(DeviceObject, Irp);
        DetachDevice(DeviceObject);//此处出错

        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);<-------------------
        return STATUS_SUCCESS;
2013-5-2 20:12
0
雪    币: 73
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
哦 晕死了 多谢指出问题
2013-5-2 20:32
0
雪    币: 10
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
新人求激活码一枚~~
2013-5-6 22:26
0
雪    币: 194
活跃值: (281)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
irp,需要同步,如下面代码

NTSTATUS
FilterDispatchPnp (
                                   PDEVICE_OBJECT DeviceObject,
                                   PIRP Irp
                                   )
                                   /*++

                                   Routine Description:

                                   The plug and play dispatch routines.

                                   Most of these the driver will completely ignore.
                                   In all cases it must pass on the IRP to the lower driver.

                                   Arguments:

                                   DeviceObject - pointer to a device object.

                                   Irp - pointer to an I/O Request Packet.

                                   Return Value:

                                   NT status code

                                   --*/
{
        PDEVICE_EXTENSION           deviceExtension;
        PIO_STACK_LOCATION         irpStack;
        NTSTATUS                            status;
        KEVENT                               event;

        PAGED_CODE();

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

        status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp);
        if (!NT_SUCCESS (status)) {
                Irp->IoStatus.Status = status;
                IoCompleteRequest (Irp, IO_NO_INCREMENT);
                return status;
        }

        switch (irpStack->MinorFunction) {
        case IRP_MN_START_DEVICE:

        //省略部分代码

        case IRP_MN_REMOVE_DEVICE:

                //
                // Wait for all outstanding requests to complete
                //
                SecDebugPrint(("Usb存储设备拔出!\n"));
                IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp);

                IoSkipCurrentIrpStackLocation(Irp);

                status = IoCallDriver(deviceExtension->NextLowerDriver, Irp);

                SET_NEW_PNP_STATE(deviceExtension, Deleted);
               
                //释放用于保存设备相关的认证,mbr,dbr等信息,
                if (deviceExtension->pAuthBuff != NULL)
                {
                        ExFreePool(deviceExtension->pAuthBuff);
                }
                if (deviceExtension->pRealMbrBuff != NULL)
                {
                        ExFreePool(deviceExtension->pRealMbrBuff);
                }
                if (deviceExtension->pDbrOffset != NULL)
                {
                        ExFreePool(deviceExtension->pDbrOffset);
                }

                IoDetachDevice(deviceExtension->NextLowerDriver);
                IoDeleteDevice(DeviceObject);
                return status;

        case IRP_MN_QUERY_STOP_DEVICE:
                SET_NEW_PNP_STATE(deviceExtension, StopPending);
                status = STATUS_SUCCESS;
                break;

        case IRP_MN_CANCEL_STOP_DEVICE:

                //
                // Check to see whether you have received cancel-stop
                // without first receiving a query-stop. This could happen if someone
                // above us fails a query-stop and passes down the subsequent
                // cancel-stop.
                //
                if (StopPending == deviceExtension->DevicePnPState)
                {
                        //
                        // We did receive a query-stop, so restore.
                        //
                        RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
                }
                status = STATUS_SUCCESS; // We must not fail this IRP.
                break;

        case IRP_MN_STOP_DEVICE:
                SET_NEW_PNP_STATE(deviceExtension, Stopped);
                status = STATUS_SUCCESS;
                break;

        case IRP_MN_QUERY_REMOVE_DEVICE:

                SET_NEW_PNP_STATE(deviceExtension, RemovePending);
                status = STATUS_SUCCESS;
                break;

        case IRP_MN_SURPRISE_REMOVAL:

                SET_NEW_PNP_STATE(deviceExtension, SurpriseRemovePending);
                status = STATUS_SUCCESS;
                break;

        case IRP_MN_CANCEL_REMOVE_DEVICE:

                //
                // Check to see whether you have received cancel-remove
                // without first receiving a query-remove. This could happen if
                // someone above us fails a query-remove and passes down the
                // subsequent cancel-remove.
                //
                if (RemovePending == deviceExtension->DevicePnPState)
                {
                        //
                        // We did receive a query-remove, so restore.
                        //
                        RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
                }

                status = STATUS_SUCCESS; // We must not fail this IRP.
                break;

        case IRP_MN_DEVICE_USAGE_NOTIFICATION:

                //
                // On the way down, pagable might become set. Mimic the driver
                // above us. If no one is above us, just set pagable.
                //
#pragma prefast(suppress:__WARNING_INACCESSIBLE_MEMBER)
                if ((DeviceObject->AttachedDevice == NULL) ||
                        (DeviceObject->AttachedDevice->Flags & DO_POWER_PAGABLE)) {

                                DeviceObject->Flags |= DO_POWER_PAGABLE;
                }

                IoCopyCurrentIrpStackLocationToNext(Irp);

                IoSetCompletionRoutine(
                        Irp,
                        FilterDeviceUsageNotificationCompletionRoutine,
                        NULL,
                        TRUE,
                        TRUE,
                        TRUE
                        );

                return IoCallDriver(deviceExtension->NextLowerDriver, Irp);

        default:
                //
                // If you don't handle any IRP you must leave the
                // status as is.
                //
                status = Irp->IoStatus.Status;

                break;
        }

        //
        // Pass the IRP down and forget it.
        //
        Irp->IoStatus.Status = status;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (deviceExtension->NextLowerDriver, Irp);
        IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
        return status;
}
2013-5-26 10:51
0
雪    币: 73
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
谢谢大家,最后发现是下层驱动对象弄错了……应该IoCallDriver下层驱动而不是目标驱动(我想要过滤的驱动)……
2013-5-26 21:03
0
游客
登录 | 注册 方可回帖
返回
//