diff --git a/reactos/drivers/storage/class/class2/class2.c b/reactos/drivers/storage/class/class2/class2.c index 2ff00dd8fbc..e4c95c15bbb 100644 --- a/reactos/drivers/storage/class/class2/class2.c +++ b/reactos/drivers/storage/class/class2/class2.c @@ -107,6 +107,13 @@ ClassIoCompletion( IN PVOID Context ); +NTSTATUS +STDCALL +ClassCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context); + + NTSTATUS STDCALL DriverEntry( @@ -1837,7 +1844,7 @@ Return Value: { PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; IO_STATUS_BLOCK ioStatus; - ULONG controlType; + ULONG controlType, mjFunction; PIRP irp; PIO_STACK_LOCATION irpStack; KEVENT event; @@ -1845,9 +1852,12 @@ Return Value: ULONG retryCount = MAXIMUM_RETRIES; NTSTATUS status; BOOLEAN retry; + LARGE_INTEGER dummy; PAGED_CODE(); + dummy.QuadPart = 0; + // // Write length to SRB. // @@ -1917,12 +1927,13 @@ retry: controlType = IOCTL_SCSI_EXECUTE_OUT; Srb->SrbFlags = SRB_FLAGS_DATA_OUT; + mjFunction = IRP_MJ_WRITE; } else { controlType = IOCTL_SCSI_EXECUTE_IN; Srb->SrbFlags = SRB_FLAGS_DATA_IN; - + mjFunction = IRP_MJ_READ; } } else { @@ -1930,21 +1941,19 @@ retry: BufferLength = 0; controlType = IOCTL_SCSI_EXECUTE_NONE; Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER; + mjFunction = IRP_MJ_FLUSH_BUFFERS; } // // Build device I/O control request with data transfer. // - - irp = IoBuildDeviceIoControlRequest(controlType, - deviceExtension->PortDeviceObject, - NULL, - 0, - BufferAddress, - BufferLength, - TRUE, - &event, - &ioStatus); + irp = IoBuildAsynchronousFsdRequest( + mjFunction, + deviceExtension->DeviceObject, + BufferAddress, + (BufferAddress) ? BufferLength : 0, + &dummy, + &ioStatus); if (irp == NULL) { ExFreePool(senseInfoBuffer); @@ -1952,6 +1961,9 @@ retry: return(STATUS_INSUFFICIENT_RESOURCES); } + // Set event field + irp->UserEvent = &event; + // // Disable synchronous transfer for these requests. // @@ -1971,12 +1983,24 @@ retry: Srb->ScsiStatus = Srb->SrbStatus = 0; Srb->NextSrb = 0; + // Set completion routine + IoSetCompletionRoutine( + irp, + ClassCompletionRoutine, + NULL, + TRUE, + TRUE, + TRUE); + // // Get next stack location. // irpStack = IoGetNextIrpStackLocation(irp); + irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + irpStack->Parameters.DeviceIoControl.IoControlCode = controlType; + // // Set up SRB for execute scsi request. Save SRB address in next stack // for the port driver. @@ -3551,11 +3575,12 @@ Return Value: NTSTATUS status; ULONG modifiedIoControlCode; - // Class can't handle RESET_DEVICE ioctl - if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_RESET_DEVICE) - { - status = Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + if (irpStack->Parameters.DeviceIoControl.IoControlCode == + IOCTL_STORAGE_RESET_DEVICE) { + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); + status = STATUS_UNSUCCESSFUL; goto SetStatusAndReturn; } @@ -4770,3 +4795,39 @@ Return Value: return STATUS_MORE_PROCESSING_REQUIRED; } + +NTSTATUS +STDCALL +ClassCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + PIO_STATUS_BLOCK IoStatusBlock = Irp->UserIosb; + PKEVENT Event = Irp->UserEvent; + PMDL Mdl; + + *IoStatusBlock = Irp->IoStatus; + Irp->UserIosb = NULL; + Irp->UserEvent = NULL; + + if(Irp->MdlAddress) + { + Mdl = Irp->MdlAddress; + + // if necessary - unlock pages + if ((Mdl->MdlFlags & MDL_PAGES_LOCKED) && + !(Mdl->MdlFlags & MDL_PARTIAL_HAS_BEEN_MAPPED)) + { + MmUnlockPages(Mdl); + } + + // free this mdl + IoFreeMdl(Mdl); + } + + // free irp and set event to unsignaled state + IoFreeIrp(Irp); + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; +}