阅读:4900回复:7
Scsi过滤驱动的问题&&如何降低IRQL
想做实现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); } 请指点 |
|
沙发#
发布于: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" |
|
板凳#
发布于:2008-04-23 12:14
你的completion routine呢?
另外还有和楼主问题无关的一个小问题:设置了完成例程,UsbCtrlReleaseRemoveLock应该在completion routine里调用才能更好地和remove pnp协作吧。 |
|
地板#
发布于: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; } |
|
地下室#
发布于: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 郁闷 |
|
5楼#
发布于:2008-04-24 09:29
现在初步确定应该是由于在高IRQL访问分页内存造成的,即KeGetCurrentIrql() > APC_LEVEL
怎样才能将将IRQL降低到APC_LEVEL。KeLowerIrql和KeRaiseIrql只能配对使用提升IRQL |
|
6楼#
发布于:2008-06-16 21:41
UsbCtrlScsiCompletionRoutine做为底层驱动的回调函数,其运行级别由低层驱动决定。我觉得你还是将SCSI Command结果分析放在UsbCtrlDispatchScsi()函数内部,当IoCallDriver()返回再去处理其结果是比较通用的作法。没必要一定在UsbCtrlScsiCompletionRoutine()里面降低IRQL。
|
|
7楼#
发布于:2008-09-07 15:16
Re:Scsi过滤驱动的问题&&如何降低IRQL
可以考虑另开一个线程,具体做法请自己琢磨 |
|