reactos/reactos/ntoskrnl/io/cleanup.c
Gunnar Dalsnes a988e5ab0e -corrected protoype
svn path=/trunk/; revision=4848
2003-06-05 23:38:37 +00:00

280 lines
7 KiB
C

/*
* 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 <ddk/ntddk.h>
#include <internal/io.h>
#include <internal/ob.h>
#include <internal/mm.h>
#include <internal/ps.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ***************************************************************/
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 STDCALL
IoSecondStageCompletion_KernelApcRoutine(
IN PKAPC Apc,
IN OUT PKNORMAL_ROUTINE *NormalRoutine,
IN OUT PVOID *NormalContext,
IN OUT PVOID *SystemArgument1,
IN OUT PVOID *SystemArgument2
)
{
IoFreeIrp((PIRP)(*SystemArgument1));
}
VOID STDCALL
IoSecondStageCompletion_RundownApcRoutine(
IN PKAPC Apc
)
{
PIRP Irp;
Irp = CONTAINING_RECORD(Apc, IRP, Tail.Apc);
IoFreeIrp(Irp);
}
/*
* FUNCTION: Performs the second stage of irp completion for read/write irps
*
* Called as a special kernel APC or directly from IofCompleteRequest()
*/
VOID STDCALL
IoSecondStageCompletion(
PKAPC Apc,
PKNORMAL_ROUTINE* NormalRoutine,
PVOID* NormalContext,
PVOID* SystemArgument1,
PVOID* SystemArgument2)
{
PIO_STACK_LOCATION IoStack;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT OriginalFileObject;
PIRP Irp;
CCHAR PriorityBoost;
OriginalFileObject = (PFILE_OBJECT)(*NormalContext);
Irp = (PIRP)(*SystemArgument1);
PriorityBoost = (CCHAR)(LONG)(*SystemArgument2);
IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
DeviceObject = IoStack->DeviceObject;
DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n", Irp, PriorityBoost);
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->UserIosb!=NULL)
{
*Irp->UserIosb=Irp->IoStatus;
}
if (Irp->UserEvent)
{
KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
}
//Windows NT File System Internals, page 169
if (OriginalFileObject)
{
if (Irp->UserEvent == NULL)
{
KeSetEvent(&OriginalFileObject->Event,PriorityBoost,FALSE);
}
else if (OriginalFileObject->Flags & FO_SYNCHRONOUS_IO && Irp->UserEvent != &OriginalFileObject->Event)
{
KeSetEvent(&OriginalFileObject->Event,PriorityBoost,FALSE);
}
}
//Windows NT File System Internals, page 154
if (!(Irp->Flags & IRP_PAGING_IO) && OriginalFileObject)
{
// if the event is not the one in the file object, it needs dereferenced
if (Irp->UserEvent && Irp->UserEvent != &OriginalFileObject->Event)
{
ObDereferenceObject(Irp->UserEvent);
}
if (IoStack->MajorFunction != IRP_MJ_CLOSE)
{
ObDereferenceObject(OriginalFileObject);
}
}
if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
{
PKNORMAL_ROUTINE UserApcRoutine;
PVOID UserApcContext;
DPRINT("Dispatching user APC\n");
UserApcRoutine = (PKNORMAL_ROUTINE)Irp->Overlay.AsynchronousParameters.UserApcRoutine;
UserApcContext = (PVOID)Irp->Overlay.AsynchronousParameters.UserApcContext;
KeInitializeApc( &Irp->Tail.Apc,
KeGetCurrentThread(),
OriginalApcEnvironment,
IoSecondStageCompletion_KernelApcRoutine,
IoSecondStageCompletion_RundownApcRoutine,
UserApcRoutine,
UserMode,
UserApcContext);
KeInsertQueueApc( &Irp->Tail.Apc,
Irp,
NULL,
PriorityBoost);
//NOTE: kernel (or rundown) routine frees the IRP
return;
}
IoFreeIrp(Irp);
}