1

这个问题很难解释,我写了两个驱动程序,一个磁盘过滤驱动程序和一个音量过滤驱动程序,当我不打开verfier.exe来验证我的驱动程序的特殊池时。一切都很好。但是当我打开它时,窗口无法关闭,变成灰屏。仅适用于磁盘驱动程序,不适用于音量驱动程序。

我用windbg调试它,我发现当系统向我的驱动程序发送一个Irp(IRP_MN_DEVICE_USAGE_NOTIFICATION)时,我分析它,如果这个irp的Parameters.UsageNotification.Type不是DeviceUsageTypePaging,我通过它,但它没有返回,它是阻塞;IRP_MN_DEVICE_USAGE_NOTIFICATION 很有趣:

case IRP_MN_DEVICE_USAGE_NOTIFICATION:
    {
        BOOLEAN setPagable;

        if (pIrpStack->Parameters.UsageNotification.Type != DeviceUsageTypePaging) 
        {
            status = pOSNDf->PassThroughIrp(pOSNDiskDevice->GetTargetDeviceObject(), 
                pIrp);
            COSNDf::MyReleaseRemoveLock(pOSNDiskDevice->GetRemoveLock(),pIrp);

            return status;
        }

        //
        // wait on the paging path event
        //

        status = KeWaitForSingleObject(&pOSNDiskDevice->PagingPathCountEvent,
            Executive, 
            KernelMode,
            FALSE, 
            NULL);

        //
        // if removing last paging device, need to set DO_POWER_PAGABLE
        // bit here, and possible re-set it below on failure.
        //

        setPagable = FALSE;
        if (!pIrpStack->Parameters.UsageNotification.InPath &&
            pOSNDiskDevice->PagingPathCount == 1 ) 
        {
            //
            // removing the last paging file
            // must have DO_POWER_PAGABLE bits set
            //

            if (pDeviceObject->Flags & DO_POWER_INRUSH) {
            } else {
                pDeviceObject->Flags |= DO_POWER_PAGABLE;
                setPagable = TRUE;
            }
        }

        //
        // send the irp synchronously
        //

        status = pOSNDf->SynchorousSendPnPIrpDown(pOSNDiskDevice->GetTargetDeviceObject(), pIrp);

        //
        // now deal with the failure and success cases.
        // note that we are not allowed to fail the irp
        // once it is sent to the lower drivers.
        //

        if (NT_SUCCESS(status)) 
        {
            IoAdjustPagingPathCount(
                &pOSNDiskDevice->PagingPathCount,
                pIrpStack->Parameters.UsageNotification.InPath);

            if (pIrpStack->Parameters.UsageNotification.InPath)
            {
                if (pOSNDiskDevice->PagingPathCount == 1) 
                {
                    pDeviceObject->Flags &= ~DO_POWER_PAGABLE;
                }
            }

        } 
        else 
        {
            //
            // cleanup the changes done above
            //

            if (setPagable == TRUE) 
            {
                pDeviceObject->Flags &= ~DO_POWER_PAGABLE;
                setPagable = FALSE;
            }
        }

        //
        // set the event so the next one can occur.
        //

        KeSetEvent(&pOSNDiskDevice->PagingPathCountEvent,
            IO_NO_INCREMENT, FALSE);

        //
        // and complete the irp
        //

        IoCompleteRequest(pIrp, IO_NO_INCREMENT);

        COSNDf::MyReleaseRemoveLock(pOSNDiskDevice->GetRemoveLock(),pIrp);

        return status;


    }

PassThroughIrp fun code;
NTSTATUS COSNDf::PassThroughIrp(PDEVICE_OBJECT  pDeviceObject,PIRP pIrp)
{
    IoSkipCurrentIrpStackLocation(pIrp);
    return IoCallDriver(pDeviceObject, pIrp);
}

我调试了一下,pIrpStack->Parameters.UsageNotification.Type是DeviceUsageTypeDumpFile;当调用 iocalldriver 这个 irp 时,阻塞系统函数是 nt!ExpInterlockedPopEntrySListResume,它总是循环;有人能帮帮我吗?谢谢!

4

0 回答 0