/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/cleanup.c * PURPOSE: IRP cleanup * PROGRAMMER: David Welch (welch@mcmail.com) * UPDATE HISTORY: * 30/05/98: Created */ /* INCLUDES ****************************************************************/ #include #include #include #include #include #define NDEBUG #include /* FUNCTIONS ***************************************************************/ VOID STDCALL IopCompleteRequest1(struct _KAPC* Apc, PKNORMAL_ROUTINE* NormalRoutine, PVOID* NormalContext, PVOID* SystemArgument1, PVOID* SystemArgument2) { PIRP Irp; CCHAR PriorityBoost; PIO_STACK_LOCATION IoStack; PFILE_OBJECT FileObject; DPRINT("IopCompleteRequest1()\n"); Irp = (PIRP)(*SystemArgument1); PriorityBoost = (CCHAR)(LONG)(*SystemArgument2); IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation]; FileObject = IoStack->FileObject; (*SystemArgument1) = (PVOID)Irp->UserIosb; (*SystemArgument2) = (PVOID)Irp->IoStatus.Information; if (Irp->UserIosb!=NULL) { *Irp->UserIosb=Irp->IoStatus; } if (Irp->UserEvent) { KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE); } if (!(Irp->Flags & IRP_PAGING_IO) && FileObject) { // if the event is not the one in the file object, it needs dereferenced if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event) ObDereferenceObject(Irp->UserEvent); if (IoStack->MajorFunction != IRP_MJ_CLOSE) { ObDereferenceObject(FileObject); } } IoFreeIrp(Irp); } VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IoStack) { ULONG IoControlCode; IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode; switch (IO_METHOD_FROM_CTL_CODE(IoControlCode)) { case METHOD_BUFFERED: DPRINT ("Using METHOD_BUFFERED!\n"); /* copy output buffer back and free it */ if (Irp->AssociatedIrp.SystemBuffer) { if (IoStack->Parameters.DeviceIoControl.OutputBufferLength) { RtlCopyMemory(Irp->UserBuffer, Irp->AssociatedIrp.SystemBuffer, IoStack->Parameters.DeviceIoControl. OutputBufferLength); } ExFreePool (Irp->AssociatedIrp.SystemBuffer); } break; case METHOD_IN_DIRECT: DPRINT ("Using METHOD_IN_DIRECT!\n"); /* copy output buffer back and free it */ if (Irp->AssociatedIrp.SystemBuffer) { if (IoStack->Parameters.DeviceIoControl.OutputBufferLength) { RtlCopyMemory(Irp->UserBuffer, Irp->AssociatedIrp.SystemBuffer, IoStack->Parameters.DeviceIoControl. OutputBufferLength); } ExFreePool (Irp->AssociatedIrp.SystemBuffer); } /* free input buffer (data transfer buffer) */ if (Irp->MdlAddress) IoFreeMdl (Irp->MdlAddress); break; case METHOD_OUT_DIRECT: DPRINT ("Using METHOD_OUT_DIRECT!\n"); /* free input buffer (control buffer) */ if (Irp->AssociatedIrp.SystemBuffer) ExFreePool (Irp->AssociatedIrp.SystemBuffer); /* free output buffer (data transfer buffer) */ if (Irp->MdlAddress) IoFreeMdl (Irp->MdlAddress); break; case METHOD_NEITHER: DPRINT ("Using METHOD_NEITHER!\n"); /* nothing to do */ break; } } VOID IoReadWriteCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IoStack) { PFILE_OBJECT FileObject; FileObject = IoStack->FileObject; if (DeviceObject->Flags & DO_BUFFERED_IO) { if (IoStack->MajorFunction == IRP_MJ_READ) { DPRINT("Copying buffered io back to user\n"); memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer, IoStack->Parameters.Read.Length); } ExFreePool(Irp->AssociatedIrp.SystemBuffer); } if (DeviceObject->Flags & DO_DIRECT_IO) { /* FIXME: Is the MDL destroyed on a paging i/o, check all cases. */ DPRINT("Tearing down MDL\n"); if (Irp->MdlAddress->MappedSystemVa != NULL) { MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa, Irp->MdlAddress); } MmUnlockPages(Irp->MdlAddress); ExFreePool(Irp->MdlAddress); } } VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IoStack) { } VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost) /* * FUNCTION: Performs the second stage of irp completion for read/write irps * ARGUMENTS: * Irp = Irp to completion * FromDevice = True if the operation transfered data from the device */ { PIO_STACK_LOCATION IoStack; PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject; DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n", Irp, PriorityBoost); /* FIXME: Should we set 'Irp->UserIosb' only on MasterIrp finalization * or we should set it for each subrequest? */ if (Irp->UserIosb) { *Irp->UserIosb=Irp->IoStatus; } /* Handling only subrequest of AssociatedIrp group from MasterIrp? * Is it the last subrequest? * FIXME: It appears to me as if 'Irp->AssociatedIrp.IrpCount' is +1 than expected. :-? */ if (Irp->Flags & IRP_ASSOCIATED_IRP) { Irp=Irp->AssociatedIrp.MasterIrp; if (!Irp) KeBugCheck(0); if (!Irp->AssociatedIrp.IrpCount) KeBugCheck(0); /* Completion of already completed MasterIrp? */ /* TODO:thread */ if (--Irp->AssociatedIrp.IrpCount) return; /* not yet fully completed MasterIrp */ if (Irp->UserIosb) { *Irp->UserIosb=Irp->IoStatus; } } IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation]; FileObject = IoStack->FileObject; DeviceObject = IoStack->DeviceObject; switch (IoStack->MajorFunction) { case IRP_MJ_CREATE: case IRP_MJ_FLUSH_BUFFERS: /* NOP */ break; case IRP_MJ_READ: case IRP_MJ_WRITE: IoReadWriteCompletion(DeviceObject,Irp,IoStack); break; case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_INTERNAL_DEVICE_CONTROL: IoDeviceControlCompletion(DeviceObject, Irp, IoStack); break; case IRP_MJ_QUERY_VOLUME_INFORMATION: case IRP_MJ_SET_VOLUME_INFORMATION: IoVolumeInformationCompletion(DeviceObject, Irp, IoStack); break; default: break; } if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL) { #ifndef LIBCAPTIVE PKTHREAD Thread; PKNORMAL_ROUTINE UserApcRoutine; PVOID UserApcContext; #endif /* LIBCAPTIVE */ DPRINT("Dispatching APC\n"); #ifndef LIBCAPTIVE Thread = &Irp->Tail.Overlay.Thread->Tcb; UserApcRoutine = (PKNORMAL_ROUTINE) Irp->Overlay.AsynchronousParameters.UserApcRoutine; UserApcContext = (PVOID) Irp->Overlay.AsynchronousParameters.UserApcContext; KeInitializeApc(&Irp->Tail.Apc, Thread, 0, IopCompleteRequest1, NULL, UserApcRoutine, UserMode, UserApcContext); KeInsertQueueApc(&Irp->Tail.Apc, Irp, (PVOID)(LONG)PriorityBoost, KernelMode); #else /* !LIBCAPTIVE */ KeBugCheck(0); #endif /* !LIBCAPTIVE */ return; } DPRINT("Irp->UserIosb %x &Irp->UserIosb %x\n", Irp->UserIosb, &Irp->UserIosb); if (Irp->UserIosb!=NULL) { *Irp->UserIosb=Irp->IoStatus; } if (Irp->UserEvent) { KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE); } if (!(Irp->Flags & IRP_PAGING_IO) && FileObject) { // if the event is not the one in the file object, it needs dereferenced if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event) ObDereferenceObject(Irp->UserEvent); if (IoStack->MajorFunction != IRP_MJ_CLOSE) { ObDereferenceObject(FileObject); } } IoFreeIrp(Irp); }