woshiwo12345
驱动牛犊
驱动牛犊
  • 注册日期2005-11-17
  • 最后登录2010-05-07
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望45点
  • 贡献值0点
  • 好评度42点
  • 原创分0分
  • 专家分0分
阅读:4900回复:7

Scsi过滤驱动的问题&&如何降低IRQL

楼主#
更多 发布于:2008-04-22 19:16
想做实现U盘SCSI命令的过滤,一插U盘就重启,
现在初步确定应该是由于在高IRQL访问分页内存造成的,即KeGetCurrentIrql() > APC_LEVEL
怎样才能将将IRQL降低到APC_LEVEL。KeLowerIrql和KeRaiseIrql只能配对使用提升IRQL

相关代码

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    ULONG i;

    DebugPrintMsg(("Enter DriverEntry!\n"));    
    DebugPrintMsg(("RegistryPath->Buffer:%S, DriverObject:%p", RegistryPath->Buffer, DriverObject));

    // save the registry path in global variable
    g_Data.szRegPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
    g_Data.szRegPath.Buffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPool, g_Data.szRegPath.MaximumLength, POOL_TAG);
    if(!g_Data.szRegPath.Buffer)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }
    else
    {
        RtlCopyUnicodeString(&g_Data.szRegPath, RegistryPath);
        DebugPrintMsg(("RegistryPath->Buffer:%S, g_Data.szRegPath.Buffer:%S", RegistryPath->Buffer, g_Data.szRegPath.Buffer));
    }    
    
    // pass through routine/function
    for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction = USBCtrlPass;
    }

    // setup our dispatch function table in the driver object
    DriverObject->MajorFunction[IRP_MJ_POWER] = UsbCtrlDispatchPower;
    DriverObject->MajorFunction[IRP_MJ_PNP] = UsbCtrlDispatchPnp;
    DriverObject->MajorFunction[IRP_MJ_CREATE] = UsbCtrlDispatchCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = UsbCtrlDispatchClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = UsbCtrlDispatchDevCtrl;
    DriverObject->MajorFunction[IRP_MJ_SCSI] = UsbCtrlDispatchScsi;

    DriverObject->DriverExtension->AddDevice = USBCtrlAddDevice;
    DriverObject->DriverUnload = USBCtrlUnload;

    

    return status;
}




NTSTATUS
UsbCtrlDispatchScsi(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    int opCode;
    PSCSI_REQUEST_BLOCK CurSrb;
    PCDB cdb;
    PMODE_PARAMETER_HEADER modeData;        //mode sence
    PIO_STACK_LOCATION IrpStack;
    KEVENT event;
    NTSTATUS status = STATUS_SUCCESS;
    PUSB_CTRL_DEVICE_EXTENSION dx;

    ASSERT(Irp != NULL);
    
    // init
    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
    IrpStack = IoGetCurrentIrpStackLocation(Irp);
    

    DebugPrintMsg(("Enter SCSI: DeviceType = %x", dx->DeviceType));

    if( !UsbCtrlAcquireRemoveLock(dx))
    {
        status = STATUS_DELETE_PENDING;

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

//把下面这段注释掉,则不会重启
    //if (USBSTOR_DISK == dx->DeviceType )
    {
        // Handle opCode of SCSI,
        // Get current SCSI SRB, analysis SCSI command here
        CurSrb = IrpStack->Parameters.Scsi.Srb;
        cdb = (PCDB)CurSrb->Cdb;
        opCode = cdb->CDB6READWRITE.OperationCode;
        
        if (SCSIOP_MODE_SENSE == opCode)
        {
            DebugPrintMsg(("Enter SCSIOP_MODE_SENSE"));
            IoCopyCurrentIrpStackLocationToNext(Irp);
            IoSetCompletionRoutine(Irp,
                                (PIO_COMPLETION_ROUTINE) UsbCtrlFilterModeSenseCompletionRoutine,
                                &event,
                                TRUE,
                                TRUE,
                                TRUE);
            status = IoCallDriver(dx->LowerDeviceObject, Irp);
            UsbCtrlReleaseRemoveLock(dx);
            return status;
        }

        if (SCSIOP_TEST_UNIT_READY == opCode)
        {
            DebugPrintMsg(("Enter SCSIOP_TEST_UNIT"));
            IoCopyCurrentIrpStackLocationToNext(Irp);
            IoSetCompletionRoutine(Irp,
                                (PIO_COMPLETION_ROUTINE) UsbCtrlFilterModeSenseCompletionRoutine,
                                &event,
                                TRUE,
                                TRUE,
                                TRUE);
            status = IoCallDriver(dx->LowerDeviceObject, Irp);
            UsbCtrlReleaseRemoveLock(dx);
            return status;
        }
    }
   
    UsbCtrlReleaseRemoveLock(dx);
    return USBCtrlPass(DeviceObject, Irp);
}

请指点
woshiwo12345
驱动牛犊
驱动牛犊
  • 注册日期2005-11-17
  • 最后登录2010-05-07
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望45点
  • 贡献值0点
  • 好评度42点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-04-22 19:17
这是inf文件
; ScsiFilter.inf
;
; Installation inf for the Disk Performance Monitor Filter driver [ DDK Sample ]
;
; Copyright (c) Microsoft Corporation
;

[Version]
Signature="$CHICAGO$"
Class=USB
ClassGUID={36FC9E60-C465-11CF-8056-444553540000}
Provider  = %msft%
DriverVer = 04/14/2008,5.1.2600.0


;
; General installation section
;

[DefaultInstall]
CopyFiles = @ScsiFilter.sys
Addreg    = ScsiFilter.AddReg

[DestinationDirs]
DefaultDestDir = 12

[ScsiFilter.AddReg]
HKLM, System\CurrentControlSet\Control\Class\{36FC9E60-C465-11CF-8056-444553540000}, LowerFilters, 0x00010008, ScsiFilter


;
; Service installation section
;
[DefaultInstall.Services]
AddService = ScsiFilter, , ScsiFilter.Service.Install

[ScsiFilter.Service.Install]
DisplayName    = %service_desc%
ServiceType    = 1
StartType      = 3
ErrorControl   = 1
ServiceBinary  = %12%\ScsiFilter.sys
LoadOrderGroup = "PnP Filter"

[DefaultUninstall]
DelFiles   = @ScsiFilter.sys
DelReg     = ScsiFilter.DelReg

[DefaultUninstall.Services]
DelService = Sfilter,0x200        ; Flags note to stop service first

[ScsiFilter.DelReg]
HKLM, System\CurrentControlSet\Control\Class\{36FC9E60-C465-11CF-8056-444553540000}, LowerFilters, 0x00010000, ScsiFilter


;
; Localizable Strings
;

[Strings]

msft         = "Microsoft Corporation"
service_desc = "Disk Performance Scsi Monitor Filter Driver"
AlexSho
驱动牛犊
驱动牛犊
  • 注册日期2008-01-10
  • 最后登录2017-12-01
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望164点
  • 贡献值0点
  • 好评度45点
  • 原创分0分
  • 专家分0分
  • 社区居民
板凳#
发布于:2008-04-23 12:14
你的completion routine呢?
另外还有和楼主问题无关的一个小问题:设置了完成例程,UsbCtrlReleaseRemoveLock应该在completion routine里调用才能更好地和remove pnp协作吧。
woshiwo12345
驱动牛犊
驱动牛犊
  • 注册日期2005-11-17
  • 最后登录2010-05-07
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望45点
  • 贡献值0点
  • 好评度42点
  • 原创分0分
  • 专家分0分
地板#
发布于:2008-04-23 14:36
做了点改动,全部代码如下:
/****************************************************************** **************
** File name: USBCtrl.c
********************************************************************************/

#include "ScsiCtrl.h"

GLOBAL_DATA g_Data;

// for debug 06.8.30
static MJ_FUN_NAME MjFunArr[] =
{
    // 0
    {IRP_MJ_CREATE,                             "IRP_MJ_CREATE"},
    {IRP_MJ_CREATE_NAMED_PIPE,                 "IRP_MJ_CREATE_NAMED_PIPE"},
    {IRP_MJ_CLOSE,                             "IRP_MJ_CLOSE"},
    {IRP_MJ_READ,                             "IRP_MJ_READ"},
    {IRP_MJ_WRITE,                             "IRP_MJ_WRITE"},
    {IRP_MJ_QUERY_INFORMATION,                 "IRP_MJ_QUERY_INFORMATION"},
    {IRP_MJ_SET_INFORMATION,                 "IRP_MJ_SET_INFORMATION"},
    {IRP_MJ_QUERY_EA,                         "IRP_MJ_QUERY_EA"},
    {IRP_MJ_SET_EA,                             "IRP_MJ_SET_EA"},
    {IRP_MJ_FLUSH_BUFFERS,                     "IRP_MJ_FLUSH_BUFFERS"},

    // 10 = 0xa
    {IRP_MJ_QUERY_VOLUME_INFORMATION,         "IRP_MJ_QUERY_VOLUME_INFORMATION"},
    {IRP_MJ_SET_VOLUME_INFORMATION,         "IRP_MJ_SET_VOLUME_INFORMATION"},
    {IRP_MJ_DIRECTORY_CONTROL,                 "IRP_MJ_DIRECTORY_CONTROL"},
    {IRP_MJ_FILE_SYSTEM_CONTROL,             "IRP_MJ_FILE_SYSTEM_CONTROL"},
    {IRP_MJ_DEVICE_CONTROL,                 "IRP_MJ_DEVICE_CONTROL"},
    {IRP_MJ_INTERNAL_DEVICE_CONTROL,         "IRP_MJ_INTERNAL_DEVICE_CONTROL"},
    {IRP_MJ_SHUTDOWN,                         "IRP_MJ_SHUTDOWN"},
    {IRP_MJ_LOCK_CONTROL,                     "IRP_MJ_LOCK_CONTROL"},
    {IRP_MJ_CLEANUP,                         "IRP_MJ_CLEANUP"},
    {IRP_MJ_CREATE_MAILSLOT,                 "IRP_MJ_CREATE_MAILSLOT"},

    // 20 = 0x14
    {IRP_MJ_QUERY_SECURITY,                 "IRP_MJ_QUERY_SECURITY"},
    {IRP_MJ_SET_SECURITY,                     "IRP_MJ_SET_SECURITY"},
    {IRP_MJ_POWER,                             "IRP_MJ_POWER"},
    {IRP_MJ_SYSTEM_CONTROL,                 "IRP_MJ_SYSTEM_CONTROL"},
    {IRP_MJ_DEVICE_CHANGE,                     "IRP_MJ_DEVICE_CHANGE"},
    {IRP_MJ_QUERY_QUOTA,                     "IRP_MJ_QUERY_QUOTA"},
    {IRP_MJ_SET_QUOTA,                         "IRP_MJ_SET_QUOTA"},
    {IRP_MJ_PNP,                             "IRP_MJ_PNP"},
    // {IRP_MJ_PNP_POWER, "IRP_MJ_PNP_POWER"}, #define IRP_MJ_PNP_POWER                IRP_MJ_PNP      // Obsolete....
};


KSPIN_LOCK gControlDeviceStateLock;

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    Installable driver initialization entry point.
    This entry point is called directly by the I/O system.

Arguments:

    DriverObject - pointer to the driver object

    RegistryPath - pointer to a unicode string representing the path,
                   to driver-specific key in the registry.

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise.

--*/
{
    NTSTATUS status = STATUS_SUCCESS;
    ULONG i;

    DebugPrintMsg(("Enter DriverEntry!\n"));    
    DebugPrintMsg(("RegistryPath->Buffer:%S, DriverObject:%p", RegistryPath->Buffer, DriverObject));

    // save the registry path in global variable
    g_Data.szRegPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
    g_Data.szRegPath.Buffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPool, g_Data.szRegPath.MaximumLength, POOL_TAG);
    if(!g_Data.szRegPath.Buffer)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }
    else
    {
        RtlCopyUnicodeString(&g_Data.szRegPath, RegistryPath);
        DebugPrintMsg(("RegistryPath->Buffer:%S, g_Data.szRegPath.Buffer:%S", RegistryPath->Buffer, g_Data.szRegPath.Buffer));
    }    
    
    // pass through routine/function
    for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction = USBCtrlPass;
    }

    // setup our dispatch function table in the driver object
    DriverObject->MajorFunction[IRP_MJ_POWER] = UsbCtrlDispatchPower;
    DriverObject->MajorFunction[IRP_MJ_PNP] = UsbCtrlDispatchPnp;
    DriverObject->MajorFunction[IRP_MJ_CREATE] = UsbCtrlDispatchCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = UsbCtrlDispatchClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = UsbCtrlDispatchDevCtrl;
    DriverObject->MajorFunction[IRP_MJ_SCSI] = UsbCtrlDispatchScsi;

    DriverObject->DriverExtension->AddDevice = USBCtrlAddDevice;
    DriverObject->DriverUnload = USBCtrlUnload;

    KeInitializeSpinLock( &gControlDeviceStateLock );

    return status;
}

NTSTATUS
USBCtrlAddDevice(
    IN PDRIVER_OBJECT  DriverObject,
    IN PDEVICE_OBJECT  PhysicalDeviceObject
    )
 /*++

Routine Description:

    The Plug & Play subsystem is handing us a brand new PDO, for which we
    (by means of INF registration) have been asked to provide a driver.

    We need to determine if we need to be in the driver stack for the device.
    Create a function device object to attach to the stack
    Initialize that device object
    Return status success.

    Remember: We can NOT actually send ANY non pnp IRPS to the given driver
    stack, UNTIL we have received an IRP_MN_START_DEVICE.

Arguments:

    DeviceObject - pointer to a device object.

    PhysicalDeviceObject -  pointer to a device object created by the
                            underlying bus driver.

Return Value:

    NT status code.

--*/
{
    NTSTATUS status;
    PDEVICE_OBJECT DeviceObject;
    PUSB_CTRL_DEVICE_EXTENSION dx;
    ULONG deviceType;

    DebugPrintMsg(("PhysicalDeviceObject: %p", PhysicalDeviceObject));

    if( ! IoIsWdmVersionAvailable(1, 0x20))    // Windows XP, refer to DDK
    {
            // on Win2k for storage stack we need to copy
            // DeviceType from the top of the stack device object,
            // otherwise OS will bugcheck
            DeviceObject = IoGetAttachedDeviceReference(PhysicalDeviceObject);
        deviceType = DeviceObject->DeviceType;
        ObDereferenceObject(DeviceObject);
    }
    else
    {
        deviceType = FILE_DEVICE_UNKNOWN;
    }

    // create our own device object
    status = IoCreateDevice(DriverObject,
                        sizeof(USB_CTRL_DEVICE_EXTENSION),
                        NULL,    // no device name
                        deviceType,
                        FILE_DEVICE_SECURE_OPEN,
                        FALSE,
                        &DeviceObject);
    if(!NT_SUCCESS(status))
    {
        DebugPrintMsg(("IoCreateDevice in AddDevice failed!status is %x", status));
        return status;
    }

    DebugPrintMsg(("Our FiDO is %p", DeviceObject));

    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    // zero memory
    RtlZeroMemory(dx, sizeof(USB_CTRL_DEVICE_EXTENSION));

    // save the physical device object PDO and our own device object
    dx->PhysicalDeviceObject = PhysicalDeviceObject;
    dx->DeviceObject = DeviceObject;

    // set RemoveCount to 1. Transition to zero
    // means IRP_MN_REMOVE_DEVICE was received
    dx->RemoveCount = 1;

    // init remove event
    KeInitializeEvent(&dx->RemoveEvent, NotificationEvent, FALSE);

    dx->PnpState = PnpStateNotStarted;
    dx->PreviousPnpState = PnpStateNotStarted;

    // register device interface
    if( 0 == dx->ifSymLinkName.Length)    // check whether created.
    {
        // the spaces for dx->ifSymLinkName 's buffer is allocated by
        // IO manager, and it is our responsibility to free these spaces
        // refer to DDK for more detail. we freed it in IRP_MN_REMOVE_DEVICE
        // when the device is removed.
        status = IoRegisterDeviceInterface(PhysicalDeviceObject,
                                        &GUID_DEVINTERFACE_USB_CTRL,
                                        NULL,
                                        &dx->ifSymLinkName);
        if( !NT_SUCCESS(status))
        {
            // lml write:
            IoDeleteDevice(DeviceObject);    
            // ??? oringinal is:
            // IoDeleteDevice(PhysicalDeviceObject);
            DebugPrintMsg(("IoRegisterDeviceInterface in AddDevice failed!status is %x", status));
            return status;
        }
    }
    IoSetDeviceInterfaceState(&dx->ifSymLinkName, TRUE);

    // attach our device to the device stack and get the device object
    // to which we should send down IRPs to
    dx->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
    if( NULL == dx->LowerDeviceObject )
    {
        DebugPrintMsg(("IoAttachDeviceToDeviceStack get no lower driver object"));
        IoDeleteDevice(DeviceObject);
        return STATUS_DEVICE_REMOVED;
    }

    // init the device object flags
    DeviceObject->Flags =
         dx->LowerDeviceObject->Flags & ( DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE);

    DeviceObject->DeviceType = dx->LowerDeviceObject->DeviceType;
    DeviceObject->Characteristics = dx->LowerDeviceObject->Characteristics;

    if(PhysicalDeviceObject->DeviceType == FILE_DEVICE_CD_ROM)
        dx->bCdRom = TRUE;
    else
        dx->bCdRom = FALSE;
    
    if(RtlCompareMemory(dx->ifSymLinkName.Buffer,IDE_DISK_STRING,sizeof(IDE_DISK_STRING)-sizeof(WCHAR)) == sizeof(IDE_DISK_STRING)-sizeof(WCHAR))
    {
        dx->DeviceType = IDE_DISK;
    }
    
    if(RtlCompareMemory(dx->ifSymLinkName.Buffer,USBSTOR_DISK_STRING,sizeof(USBSTOR_DISK_STRING)-sizeof(WCHAR)) == sizeof(USBSTOR_DISK_STRING)-sizeof(WCHAR))
    {
        dx->DeviceType = USBSTOR_DISK;
    }
    
    if(RtlCompareMemory(dx->ifSymLinkName.Buffer,SCSI_CdRom_STRING,sizeof(SCSI_CdRom_STRING)-sizeof(WCHAR)) == sizeof(SCSI_CdRom_STRING)-sizeof(WCHAR))
    {
        dx->DeviceType = SCSI_CdRom;
    }
    if(RtlCompareMemory(dx->ifSymLinkName.Buffer,IDE_CdRom_STRING,sizeof(IDE_CdRom_STRING)-sizeof(WCHAR)) == sizeof(IDE_CdRom_STRING)-sizeof(WCHAR))
    {
        dx->DeviceType = IDE_CdRom;
    }

    // the original set this statement before the above one. any problem???
    // and now I removed it from the bottom. 06.8.25
    status = STATUS_SUCCESS;
    
    // we are all done, so we need to clear the DO_DEVICE_INITIALIZING flag.
    // This must be the last action in AddDevice
    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    
    return status;

}

VOID
USBCtrlUnload(IN PDRIVER_OBJECT  DriverObject)
/*++

Routine Description:

    Free all the allocated resources in DriverEntry, etc.

Arguments:

    DriverObject - pointer to a driver object.

Return Value:

    VOID.

--*/
{
    PAGED_CODE ();


    // free the unicode string allocated in DriverEntry
    RtlFreeUnicodeString(&g_Data.szRegPath);

    //
    // The device object(s) should be NULL now
    // (since we unload, all the devices objects associated with this
    // driver must be deleted.
    //
    ASSERT(DriverObject->DeviceObject == NULL);

    //
    // We should not be unloaded until all the devices we control
    // have been removed from our queue.
    //
    DebugPrintMsg (("Unload\n"));

    return;

}

NTSTATUS
USBCtrlPass(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    NTSTATUS status;
    PUSB_CTRL_DEVICE_EXTENSION dx;
    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    if( !UsbCtrlAcquireRemoveLock(dx))
    {
        status = STATUS_DELETE_PENDING;

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    IoSkipCurrentIrpStackLocation(Irp);
    status = IoCallDriver(dx->LowerDeviceObject, Irp);

    UsbCtrlReleaseRemoveLock(dx);

    return status;    
}


///////////////////////////////////////////////////////////////////////////////////////////////////
//  UsbCtrlAcquireRemoveLock
//      Acquires remove lock.
//
//  Arguments:
//      IN  DeviceExtension
//              our device extension
//
//  Return Value:
//      FALSE if remove device pending, TRUE otherwise.
//

BOOLEAN
UsbCtrlAcquireRemoveLock
    (IN PUSB_CTRL_DEVICE_EXTENSION dx)
{
    InterlockedIncrement(&dx->RemoveCount);
    if( PnpStateRemoved == dx->PnpState )
    {
        UsbCtrlReleaseRemoveLock(dx);

        return FALSE;
    }

    return TRUE;
}


///////////////////////////////////////////////////////////////////////////////////////////////////
//  UsbCtrlReleaseRemoveLock
//      Releases remove lock.
//
//  Arguments:
//      IN  DeviceExtension
//              our device extension
//
//  Return Value:
//      None.
//
VOID
UsbCtrlReleaseRemoveLock(
    IN  PUSB_CTRL_DEVICE_EXTENSION    dx
    )
{
    if (InterlockedDecrement(&dx->RemoveCount) == 0)
    {
        KeSetEvent(&dx->RemoveEvent, IO_NO_INCREMENT, FALSE);
    }
}

VOID
UsbCtrlWaitForSafeRemove(
    IN  PUSB_CTRL_DEVICE_EXTENSION    dx
    )
{
    dx->PnpState = PnpStateRemoved;
    UsbCtrlReleaseRemoveLock(dx);

    KeWaitForSingleObject(&dx->RemoveEvent, Executive, KernelMode, FALSE, NULL);
}

NTSTATUS
UsbCtrlDispatchPnp(
    IN PDEVICE_OBJECT DeviceObject,
    IN 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

--*/
{
    PUSB_CTRL_DEVICE_EXTENSION dx;
    NTSTATUS status;
    PIO_STACK_LOCATION IrpStack;

    DebugPrintMsg(("UsbCtrlDispatchPnp ++ Irp: %p", Irp));

    // get our current Irp stack
    IrpStack = IoGetCurrentIrpStackLocation(Irp);

    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    if( !UsbCtrlAcquireRemoveLock(dx) )
    {
        status = STATUS_DELETE_PENDING;

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        DebugPrintMsg(("UsbCtrlDispatchPnp --Irp1: %p", Irp));
        
        return status;
    }

    switch( IrpStack->MinorFunction )
    {
    case IRP_MN_START_DEVICE:
        // The device stack must be started from the bottom up, so, we send
        // the IRP down the stack and wait so that all devices below our's have
        // started before we process this IRP and start ourselves.
        status = UsbCtrlSubmitIrpSync(dx->LowerDeviceObject, Irp);
        if( !NT_SUCCESS(status) )
        {
            // someone below us failed to start, so we just complete with error.
            break;
        }

        // lower drivers have started their operation, so now we can process.

        // update our pnp state
        dx->PnpState = PnpStateStarted;
        if(dx->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
        {
            DeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
        }
        
        break;
    case IRP_MN_QUERY_STOP_DEVICE:
        // update our pnp state
        dx->PreviousPnpState = dx->PnpState;
        dx->PnpState = PnpStateStopPending;

        // we must set Irp->IoStatus.Status to STATUS_SUCCESS before passing it down.
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(dx->LowerDeviceObject, Irp);

        UsbCtrlReleaseRemoveLock(dx);

        DebugPrintMsg(("UsbCtrlDispatchPnp --Irp2: %p", Irp));

        return status;
        
        break;
    case IRP_MN_CANCEL_STOP_DEVICE:
        // send this Irp down and wait for it come back

        // first check to see whether we received a query before this cancel.
        // This could happen if someone above us failed a query and passed down
        // the subsequent cancel
        if( PnpStateStopPending == dx->PnpState )
        {
            status = UsbCtrlSubmitIrpSync(dx->LowerDeviceObject, Irp);
            if(NT_SUCCESS(status))
            {
                // restore previous pnp state
                dx->PnpState = dx->PreviousPnpState;                
            }
            else
            {
                // somebody below us failed the cancel, this is the fatal error.
                ASSERTMSG("Cancel stop failed ", FALSE);
            }
        }
        else
        {
            // spurious cancel so we just forward the request
            Irp->IoStatus.Status = STATUS_SUCCESS;
            IoSkipCurrentIrpStackLocation(Irp);

            status = IoCallDriver(dx->LowerDeviceObject, Irp);

            UsbCtrlReleaseRemoveLock(dx);

            DebugPrintMsg(("UsbCtrlDispatchPnp --Irp3: %p", Irp));

            return status;
        }
        break;
    case IRP_MN_STOP_DEVICE:
        // mark the device as stopped
        dx->PnpState = PnpStateStopped;

        // send the request down, and we are done.
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(Irp);

        status = IoCallDriver(dx->LowerDeviceObject, Irp);

        UsbCtrlReleaseRemoveLock(dx);

        DebugPrintMsg(("UsbCtrlDispatchPnp --Irp4: %p", Irp));

        return status;
        
        break;
    case IRP_MN_QUERY_REMOVE_DEVICE:
        // update the pnp state
        dx->PreviousPnpState = dx->PnpState;
        dx->PnpState = PnpStateRemovePending;

        // now just send the Irp down and we are done.
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(Irp);

        status = IoCallDriver(dx->LowerDeviceObject, Irp);

        UsbCtrlReleaseRemoveLock(dx);

        DebugPrintMsg(("UsbCtrlDispatchPnp --Irp5: %p", Irp));

        return status;
                
        break;
    case IRP_MN_CANCEL_REMOVE_DEVICE:
        // First check to see whether we have received a query remove request.
        // It could be happen if someone above us failed a query remove request and
        // send the subsequent cancel request.
        if(PnpStateRemovePending == dx->PnpState)
        {
            status = UsbCtrlSubmitIrpSync(dx->LowerDeviceObject, Irp);
            if(NT_SUCCESS(status))
            {
                // restore the pnp state, since remove was canceled
                dx->PnpState = dx->PreviousPnpState;                
            }
            else
            {
                // Nobody can fail this Irp, This is a fatal error
                ASSERTMSG("Cancel remove failed. Fatal error!", FALSE);
                DebugPrintMsg(("UsbCtrlDispatchPnp --Irp6: %p", Irp));
            }
        }
        else
        {
            // spurious cancel remove request so we just forward it
            Irp->IoStatus.Status = STATUS_SUCCESS;
            IoSkipCurrentIrpStackLocation(Irp);

            status = IoCallDriver(dx->LowerDeviceObject, Irp);

            UsbCtrlReleaseRemoveLock(dx);

            DebugPrintMsg(("UsbCtrlDispatchPnp --Irp7: %p", Irp));

            return status;            
        }
        break;
    case IRP_MN_SURPRISE_REMOVAL:
        // the device has been unexpectedly removed from the machine and is
        // no longer available for I/O
        dx->PnpState = PnpStateRemoved;

        // we must set the Irp->IoStatus.Status to STATUS_SUCCESS
        // before passing it down
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(Irp);

        status = IoCallDriver(dx->LowerDeviceObject, Irp);

        // Adjust the active I/O count
        UsbCtrlReleaseRemoveLock(dx);

        DebugPrintMsg(("UsbCtrlDispatchPnp --Irp: %p8", Irp));

        return status;            
        
        break;
    case IRP_MN_REMOVE_DEVICE:

        IoSetDeviceInterfaceState(&dx->ifSymLinkName, FALSE);
        RtlFreeUnicodeString(&(dx->ifSymLinkName));

        // the Plug & Play system has dictated the removal of this device. we have no choice
        // but to detach and delete the device object
        dx->PnpState = PnpStateRemoved;
        UsbCtrlReleaseRemoveLock(dx);
        UsbCtrlWaitForSafeRemove(dx);

        // send the remove Irp down the stack
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(dx->LowerDeviceObject, Irp);

        // detach our device object from the device stack
        IoDetachDevice(dx->LowerDeviceObject);

        // attempt to delete our device object
        IoDeleteDevice(dx->DeviceObject);
        
        DebugPrintMsg(("UsbCtrlDispatchPnp --Irp9: %p", Irp));

        return status;
        
        break;
    case IRP_MN_DEVICE_USAGE_NOTIFICATION:
        if( (NULL == DeviceObject->AttachedDevice)  ||
             (DeviceObject->AttachedDevice->Flags & DO_POWER_PAGABLE) )
        {
            DeviceObject->Flags |= DO_POWER_PAGABLE;
        }

        status = UsbCtrlSubmitIrpSync(dx->LowerDeviceObject, Irp);
        if( !(dx->LowerDeviceObject->Flags & DO_POWER_PAGABLE) )
        {
            DeviceObject->Flags &= ~ DO_POWER_PAGABLE;
        }
        break;
    default:
        // Pass down any unknown requests
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(dx->LowerDeviceObject, Irp);

        // adjust our active I/O count
        UsbCtrlReleaseRemoveLock(dx);
        
        DebugPrintMsg(("UsbCtrlDispatchPnp --Irp: %p10", Irp));
        return status;
        break;
    }

    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    // adjust our active I/O count
    UsbCtrlReleaseRemoveLock(dx);
    
    DebugPrintMsg(("UsbCtrlDispatchPnp --Irp11: %p", Irp));
    return status;
}

NTSTATUS
UsbCtrlSubmitIrpSync(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:
    send a given IRP down the stack to the next lower driver  and
    waits in a synchronous fashion for the IRP to complete

Arguments:
    DeviceObject-pointer to a device object

    Irp-pointer to a IRP
    
Return Value:

      NT status code
      
--*/
{
    KEVENT event;
    NTSTATUS status;

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    IoCopyCurrentIrpStackLocationToNext(Irp);

    IoSetCompletionRoutine(Irp,
                        UsbCtrlSubmitIrpSyncComplete,
                        &event,
                        TRUE,
                        TRUE,
                        TRUE);

    status = IoCallDriver(DeviceObject, Irp);

    // wait for the lower drivers to be done with this IRP. Important thing to note here
    // is when you allocate memory for an event in the stack you must do a kernal-mode
    // wait instead of UserMode wait to prevent the stack from getting paged out.
    if( STATUS_PENDING == status)
    {
        KeWaitForSingleObject(&event,
                            Executive,
                            KernelMode,
                            FALSE,
                            NULL);
        status = Irp->IoStatus.Status;
    }

    return status;    
}


NTSTATUS  
UsbCtrlSubmitIrpSyncComplete(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp,
    IN  PVOID         Context
    )
{
    NTSTATUS status;
    PKEVENT pEvent = (PKEVENT)Context;

    // if the lower driver didn't return STATUS_PENDING, we don't need to set
    // the event because we won't be waiting on  it.
    if(Irp->PendingReturned)
        KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);

    return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
UsbCtrlDispatchPower(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

    This routine is the dispatch routine for power irps.

Arguments:

    DeviceObject - Pointer to the device object.

    Irp - Pointer to the request packet.

Return Value:

    NT Status code
--*/
{
    NTSTATUS status;
    PUSB_CTRL_DEVICE_EXTENSION dx;

    DebugPrintMsg(("UsbCtrlDispatchPower ++Irp: %p", Irp));

    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    if( !(UsbCtrlAcquireRemoveLock(dx)))
    {
        status = STATUS_DELETE_PENDING;

        PoStartNextPowerIrp(Irp);

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        DebugPrintMsg(("UsbCtrlDispatchPower --Irp1: %p, status:0x%x", Irp, status));

        return status;        
    }

    PoStartNextPowerIrp(Irp);
    IoSkipCurrentIrpStackLocation(Irp);
    status = PoCallDriver(dx->LowerDeviceObject, Irp);

    UsbCtrlReleaseRemoveLock(dx);

    DebugPrintMsg(("UsbCtrlDispatchPower --Irp2: %p", Irp));

    return status;
}


NTSTATUS
UsbCtrlDispatchCreate(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++
Routine Description:
    This routine is the dispatch routine for IRP_MJ_CREATE.
--*/
{
    NTSTATUS status;
    PUSB_CTRL_DEVICE_EXTENSION dx;

    DebugPrintMsg(("UsbCtrlDispatchCreate ++Irp: %p", Irp));

    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    // make sure we can accept IRPs
    if( !(UsbCtrlAcquireRemoveLock(dx)) )
    {
        status = STATUS_DELETE_PENDING;

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        DebugPrintMsg(("UsbCtrlDispatchCreate --Irp1: %p", Irp));

        return status;
    }

    IoSkipCurrentIrpStackLocation(Irp);
    status = IoCallDriver(dx->LowerDeviceObject, Irp);

    UsbCtrlReleaseRemoveLock(dx);

    DebugPrintMsg(("UsbCtrlDispatchCreate --Irp2: %p", Irp));
    return status;
}

NTSTATUS
UsbCtrlDispatchClose(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    NTSTATUS status;
    PUSB_CTRL_DEVICE_EXTENSION dx;

    DebugPrintMsg(("UsbCtrlDispatchClose ++Irp: %p", Irp));

    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    // make sure we can accept IRPs
    if( !(UsbCtrlAcquireRemoveLock(dx)) )
    {
        status = STATUS_DELETE_PENDING;

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        DebugPrintMsg(("UsbCtrlDispatchClose --Irp1: %p", Irp));

        return status;
    }

    IoSkipCurrentIrpStackLocation(Irp);
    status = IoCallDriver(dx->LowerDeviceObject, Irp);

    UsbCtrlReleaseRemoveLock(dx);

    DebugPrintMsg(("UsbCtrlDispatchClose --Irp2: %p", Irp));
    return status;    
}


// Dispatch routine to handle IRP_MJ_DEVICE_CONTROL
NTSTATUS
UsbCtrlDispatchDevCtrl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PUSB_CTRL_DEVICE_EXTENSION dx;
    PIO_STACK_LOCATION IrpStack;
    int * pCtrlCode = NULL;
    BOOLEAN bIsDefinedCtrlCode = TRUE;

    DebugPrintMsg(("UsbCtrlDispatchDevCtrl ++Irp: %p", Irp));

    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    DebugPrintMsg(("UsbCtrlDispatchDevCtrl IO Code: %i", g_Data.nCtrlCode));

    IrpStack = IoGetCurrentIrpStackLocation(Irp);

    // make sure we can accept IRPs
    if( !(UsbCtrlAcquireRemoveLock(dx)) )
    {
        status = STATUS_DELETE_PENDING;

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        DebugPrintMsg(("UsbCtrlDispatchDevCtrl --Irp1: %p", Irp));

        return status;
    }

    switch(IrpStack->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_800_SET_READONLY:
        g_Data.nCtrlCode = READ_ONLY;
        DebugPrintMsg(("Set flag to READ_ONLY\n"));
        break;
    case IOCTL_801_DISABLE_RW:
        g_Data.nCtrlCode = LOCK_ALL;
        DebugPrintMsg(("Set flag to LOCK_ALL\n"));
        break;
    case IOCTL_802_SET_FREE:
        g_Data.nCtrlCode = FREE;
        DebugPrintMsg(("Set flag to FREE\n"));
        break;
    case IOCTL_803_QUERY_STATUS:
        pCtrlCode = (int *)Irp->AssociatedIrp.SystemBuffer;
        *pCtrlCode = (int)g_Data.nCtrlCode;
        Irp->IoStatus.Information = sizeof(int);
        DebugPrintMsg(("IOCTL_803_QUERY_STATUS, flag is %d\n", g_Data.nCtrlCode));    
        break;
    case IOCTL_804_DEBUG:
        break;        
    case IOCTL_805_NODEBUG:
        break;
    default:
        DebugPrintMsg(("Invalid IO_CTRL_CODE: 0x%x\n", IrpStack->Parameters.DeviceIoControl.IoControlCode));
        bIsDefinedCtrlCode = FALSE;
        status = Irp->IoStatus.Status;
         break;
    }

    if(!bIsDefinedCtrlCode)
    {
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(dx->LowerDeviceObject, Irp);        
    }
    else
    {
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        DebugPrintMsg(("Set flag operation is completed!\n"));    
    }

    UsbCtrlReleaseRemoveLock(dx);

    DebugPrintMsg(("UsbCtrlDispatchDevCtrl --Irp2:%p", Irp));
    
    return status;
}

NTSTATUS
UsbCtrlDispatchScsi(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    PSCSI_REQUEST_BLOCK CurSrb;
    KEVENT event;
    NTSTATUS status;
    PUSB_CTRL_DEVICE_EXTENSION dx;
    
    // init
    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    if( !UsbCtrlAcquireRemoveLock(dx))
    {
        status = STATUS_DELETE_PENDING;

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    // Handle opCode of SCSI,
    // Get current SCSI SRB, analysis SCSI command here
    IoCopyCurrentIrpStackLocationToNext(Irp);
    KeInitializeEvent( &event, NotificationEvent, FALSE );
    IoSetCompletionRoutine(Irp,
                            (PIO_COMPLETION_ROUTINE) UsbCtrlScsiCompletionRoutine,
                            &event,
                            TRUE,
                            TRUE,
                            TRUE);
    status = IoCallDriver(dx->LowerDeviceObject, Irp);
    /*if (status == STATUS_PENDING) {
        KeWaitForSingleObject( &event,
                               Executive,
                               KernelMode,
                               FALSE,
                               NULL );
        status = Irp->IoStatus.Status;
    }*/
    return status;
}

BOOLEAN
IsInternalBusType(
    const GUID *pGuid
    )
{
    //wdmguid.h
    //
    // Bus type GUIDs
    //
    //DEFINE_GUID( GUID_BUS_TYPE_INTERNAL,               0x1530ea73L, 0x086b, 0x11d1, 0xa0, 0x9f, 0x00, 0xc0, 0x4f, 0xc3, 0x40, 0xb1 );
    //DEFINE_GUID( GUID_BUS_TYPE_USB,                    0x9d7debbcL, 0xc85d, 0x11d1, 0x9e, 0xb4, 0x00, 0x60, 0x08, 0xc3, 0xa1, 0x9a );
    // {9D7DEBBC-C85D-11d1-9EB4-006008C3A19A}
    //{1530EA73-86B-11D1-A0-9F-0-C0-4F-C3-40-B1}
    if((pGuid->Data1==0x1530ea73L) &&
        (pGuid->Data2==0x086b) &&
        (pGuid->Data3==0x11d1) &&
        (pGuid->Data4[0]==0xa0) &&
        (pGuid->Data4[1]==0x9f) &&
        (pGuid->Data4[2]==0x00) &&
        (pGuid->Data4[3]==0xc0) &&
        (pGuid->Data4[4]==0x4f) &&
        (pGuid->Data4[5]==0xc3) &&
        (pGuid->Data4[6]==0x40) &&
        (pGuid->Data4[7]==0xb1))
    {
        return TRUE;
    }
    return FALSE;

}

NTSTATUS
UsbCtrlScsiCompletionRoutine(
      IN PDEVICE_OBJECT   DeviceObject,
      IN PIRP         Irp,
      IN PVOID         Context
      )
{
    PIO_STACK_LOCATION IrpStack;
    PSCSI_REQUEST_BLOCK CurSrb;
    int opCode;
    PUSB_CTRL_DEVICE_EXTENSION dx;
    
    // init
    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
        
    IrpStack = IoGetCurrentIrpStackLocation(Irp);

    //Get Current Scsi SRB, Analysis SCSI Command here!
    CurSrb = IrpStack->Parameters.Scsi.Srb;

    opCode = CurSrb->Cdb[0];
    /*if (opCode == SCSIOP_TEST_UNIT_READY)
    {
    }*/
    UsbCtrlReleaseRemoveLock(dx);
    return STATUS_SUCCESS;

}
woshiwo12345
驱动牛犊
驱动牛犊
  • 注册日期2005-11-17
  • 最后登录2010-05-07
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望45点
  • 贡献值0点
  • 好评度42点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-04-23 14:40
NTSTATUS
UsbCtrlScsiCompletionRoutine(
      IN PDEVICE_OBJECT   DeviceObject,
      IN PIRP         Irp,
      IN PVOID         Context
      )
{
    PIO_STACK_LOCATION IrpStack;
    PSCSI_REQUEST_BLOCK CurSrb;
    int opCode;
    PUSB_CTRL_DEVICE_EXTENSION dx;
    
    // init
    dx = (PUSB_CTRL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
        
    IrpStack = IoGetCurrentIrpStackLocation(Irp);

    //Get Current Scsi SRB, Analysis SCSI Command here!
    CurSrb = IrpStack->Parameters.Scsi.Srb;

    opCode = CurSrb->Cdb[0];
    /*if (opCode == SCSIOP_TEST_UNIT_READY)
    {
    }*/
    UsbCtrlReleaseRemoveLock(dx);
    return STATUS_SUCCESS;
}

把上面代码中opCode = CurSrb->Cdb[0];这句去掉就不会重启,用SoftICE运行到这里时提示
Break due to page fault
郁闷
woshiwo12345
驱动牛犊
驱动牛犊
  • 注册日期2005-11-17
  • 最后登录2010-05-07
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望45点
  • 贡献值0点
  • 好评度42点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2008-04-24 09:29
现在初步确定应该是由于在高IRQL访问分页内存造成的,即KeGetCurrentIrql() > APC_LEVEL
怎样才能将将IRQL降低到APC_LEVEL。KeLowerIrql和KeRaiseIrql只能配对使用提升IRQL
uohnep
驱动牛犊
驱动牛犊
  • 注册日期2006-06-12
  • 最后登录2009-10-13
  • 粉丝1
  • 关注0
  • 积分4分
  • 威望22点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2008-06-16 21:41
UsbCtrlScsiCompletionRoutine做为底层驱动的回调函数,其运行级别由低层驱动决定。我觉得你还是将SCSI Command结果分析放在UsbCtrlDispatchScsi()函数内部,当IoCallDriver()返回再去处理其结果是比较通用的作法。没必要一定在UsbCtrlScsiCompletionRoutine()里面降低IRQL。
zhangguangkai
驱动牛犊
驱动牛犊
  • 注册日期2008-09-06
  • 最后登录2010-10-30
  • 粉丝0
  • 关注0
  • 积分39分
  • 威望336点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2008-09-07 15:16
Re:Scsi过滤驱动的问题&amp;&amp;如何降低IRQL
可以考虑另开一个线程,具体做法请自己琢磨
游客

返回顶部