-/*
+/* $Id: irp.c,v 1.26 2000/03/06 01:02:30 ea Exp $
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/irp.c
/* INCLUDES ****************************************************************/
-#include <internal/string.h>
-#include <internal/kernel.h>
#include <ddk/ntddk.h>
+#include <string.h>
+#include <internal/string.h>
+#include <internal/io.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ****************************************************************/
-PDEVICE_OBJECT IoGetDeviceToVerify(PETHREAD Thread)
+PDEVICE_OBJECT
+STDCALL
+IoGetDeviceToVerify (PETHREAD Thread)
/*
* FUNCTION: Returns a pointer to the device, representing a removable-media
* device, that is the target of the given thread's I/O request
UNIMPLEMENTED;
}
-VOID IoFreeIrp(PIRP Irp)
+
+VOID
+STDCALL
+IoFreeIrp (PIRP Irp)
/*
* FUNCTION: Releases a caller allocated irp
* ARGUMENTS:
ExFreePool(Irp);
}
-PIRP IoMakeAssociatedIrp(PIRP Irp, CCHAR StackSize)
+
+PIRP
+STDCALL
+IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
/*
* FUNCTION: Allocates and initializes an irp to associated with a master irp
* ARGUMENTS:
UNIMPLEMENTED;
}
-VOID IoMarkIrpPending(PIRP Irp)
+
+/**********************************************************************
+ * NAME INTERNAL
+ * IoMarkIrpPending
+ */
+VOID
+IoMarkIrpPending (PIRP Irp)
/*
* FUNCTION: Marks the specified irp, indicating further processing will
* be required by other driver routines
* Irp = Irp to mark
*/
{
+// DPRINT("IoGetCurrentIrpStackLocation(Irp) %x\n",
+// IoGetCurrentIrpStackLocation(Irp));
IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED;
}
-PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction,
- PDEVICE_OBJECT DeviceObject,
- PVOID Buffer,
- ULONG Length,
- PLARGE_INTEGER StartingOffset,
- PIO_STATUS_BLOCK IoStatusBlock)
-/*
- * FUNCTION: Allocates and sets up an IRP to be sent to lower level drivers
- * ARGUMENTS:
- * MajorFunction = One of IRP_MJ_READ, IRP_MJ_WRITE,
- * IRP_MJ_FLUSH_BUFFERS or IRP_MJ_SHUTDOWN
- * DeviceObject = Device object to send the irp to
- * Buffer = Buffer into which data will be read or written
- * Length = Length in bytes of the irp to be allocated
- * StartingOffset = Starting offset on the device
- * IoStatusBlock (OUT) = Storage for the result of the operation
- * RETURNS: The IRP allocated on success, or
- * NULL on failure
- */
-{
- PIRP Irp;
- PIO_STACK_LOCATION StackPtr;
-
- Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
- if (Irp==NULL)
- {
- return(NULL);
- }
-
- Irp->UserBuffer = (LPVOID)Buffer;
- if (DeviceObject->Flags&DO_BUFFERED_IO)
- {
- DPRINT("Doing buffer i/o\n",0);
- Irp->AssociatedIrp.SystemBuffer = (PVOID)
- ExAllocatePool(NonPagedPool,Length);
- if (Irp->AssociatedIrp.SystemBuffer==NULL)
- {
- return(NULL);
- }
- Irp->UserBuffer = NULL;
- }
- if (DeviceObject->Flags&DO_DIRECT_IO)
- {
- DPRINT("Doing direct i/o\n",0);
-
- Irp->MdlAddress = MmCreateMdl(NULL,Buffer,Length);
- MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess);
- Irp->UserBuffer = NULL;
- Irp->AssociatedIrp.SystemBuffer = NULL;
- }
- Irp->UserIosb = IoStatusBlock;
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = MajorFunction;
- StackPtr->MinorFunction = 0;
- StackPtr->Flags = 0;
- StackPtr->Control = 0;
- StackPtr->DeviceObject = DeviceObject;
- StackPtr->FileObject = NULL;
- StackPtr->Parameters.Write.Length = Length;
- if (StartingOffset!=NULL)
- {
- StackPtr->Parameters.Write.ByteOffset.LowPart =
- StartingOffset->LowPart;
- StackPtr->Parameters.Write.ByteOffset.HighPart =
- StartingOffset->HighPart;
- }
- else
- {
- StackPtr->Parameters.Write.ByteOffset.LowPart = 0;
- StackPtr->Parameters.Write.ByteOffset.HighPart = 0;
- }
-
- return(Irp);
-}
-
-PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode,
- PDEVICE_OBJECT DeviceObject,
- PVOID InputBuffer,
- ULONG InputBufferLength,
- PVOID OutputBuffer,
- ULONG OutputBufferLength,
- BOOLEAN InternalDeviceIoControl,
- PKEVENT Event,
- PIO_STATUS_BLOCK IoStatusBlock)
-{
- UNIMPLEMENTED;
-}
-
-PIRP IoBuildSynchronousFsdRequest(ULONG MajorFunction,
- PDEVICE_OBJECT DeviceObject,
- PVOID Buffer,
- ULONG Length,
- PLARGE_INTEGER StartingOffset,
- PKEVENT Event,
- PIO_STATUS_BLOCK IoStatusBlock)
-/*
- * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower
- * level driver(s)
- * ARGUMENTS:
- * MajorFunction = Major function code, one of IRP_MJ_READ,
- * IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_SHUTDOWN
- * DeviceObject = Target device object
- * Buffer = Buffer containing data for a read or write
- * Length = Length in bytes of the information to be transferred
- * StartingOffset = Offset to begin the read/write from
- * Event (OUT) = Will be set when the operation is complete
- * IoStatusBlock (OUT) = Set to the status of the operation
- * RETURNS: The IRP allocated on success, or
- * NULL on failure
+/**********************************************************************
+ * NAME INTERNAL
+ * IoSizeOfIrp
*/
-{
- PIRP Irp;
- PIO_STACK_LOCATION StackPtr;
-
- Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
- if (Irp==NULL)
- {
- return(NULL);
- }
-
- Irp->UserBuffer = (LPVOID)Buffer;
- if (DeviceObject->Flags&DO_BUFFERED_IO)
- {
- DPRINT("Doing buffer i/o\n",0);
- Irp->AssociatedIrp.SystemBuffer = (PVOID)
- ExAllocatePool(NonPagedPool,Length);
- if (Irp->AssociatedIrp.SystemBuffer==NULL)
- {
- return(NULL);
- }
- Irp->UserBuffer = NULL;
- }
- if (DeviceObject->Flags&DO_DIRECT_IO)
- {
- DPRINT("Doing direct i/o\n",0);
-
- Irp->MdlAddress = MmCreateMdl(NULL,Buffer,Length);
- MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess);
- Irp->UserBuffer = NULL;
- Irp->AssociatedIrp.SystemBuffer = NULL;
- }
-
- Irp->UserIosb = IoStatusBlock;
- Irp->UserEvent = Event;
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->MajorFunction = MajorFunction;
- StackPtr->MinorFunction = 0;
- StackPtr->Flags = 0;
- StackPtr->Control = 0;
- StackPtr->DeviceObject = DeviceObject;
- StackPtr->FileObject = NULL;
- StackPtr->Parameters.Write.Length = Length;
- if (StartingOffset!=NULL)
- {
- StackPtr->Parameters.Write.ByteOffset.LowPart =
- StartingOffset->LowPart;
- StackPtr->Parameters.Write.ByteOffset.HighPart =
- StartingOffset->HighPart;
- }
- else
- {
- StackPtr->Parameters.Write.ByteOffset.LowPart = 0;
- StackPtr->Parameters.Write.ByteOffset.HighPart = 0;
- }
-
- return(Irp);
-}
-
-USHORT IoSizeOfIrp(CCHAR StackSize)
+USHORT
+IoSizeOfIrp (CCHAR StackSize)
/*
* FUNCTION: Determines the size of an IRP
* ARGUMENTS:
return(sizeof(IRP)+((StackSize-1)*sizeof(IO_STACK_LOCATION)));
}
-VOID IoInitializeIrp(PIRP Irp, USHORT PacketSize, CCHAR StackSize)
+
+VOID
+STDCALL
+IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
/*
* FUNCTION: Initalizes an irp allocated by the caller
* ARGUMENTS:
* StackSize = Number of stack locations in the IRP
*/
{
- assert(Irp!=NULL);
- memset(Irp,0,PacketSize);
- Irp->CurrentLocation=StackSize;
- Irp->Tail.Overlay.CurrentStackLocation=IoGetCurrentIrpStackLocation(Irp);
+ assert(Irp != NULL);
+
+ memset(Irp, 0, PacketSize);
+ Irp->Size = PacketSize;
+ Irp->StackCount = StackSize;
+ Irp->CurrentLocation = StackSize;
+ Irp->Tail.Overlay.CurrentStackLocation = IoGetCurrentIrpStackLocation(Irp);
}
-PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
+
+/**********************************************************************
+ * NAME INTERNAL
+ * IoGetCurrentIrpStackLocation
+ */
+PIO_STACK_LOCATION
+IoGetCurrentIrpStackLocation (PIRP Irp)
/*
* FUNCTION: Gets a pointer to the callers location in the I/O stack in
* the given IRP
* RETURNS: A pointer to the stack location
*/
{
- return(&Irp->Stack[Irp->CurrentLocation]);
+// DPRINT("IoGetCurrentIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n",
+// Irp,
+// Irp->CurrentLocation,
+// Irp->StackCount);
+
+ return(&Irp->Stack[(ULONG)Irp->CurrentLocation]);
}
-VOID IoSetNextIrpStackLocation(PIRP Irp)
+/**********************************************************************
+ * NAME INTERNAL
+ * IoSetNextIrpStackLocation
+ */
+VOID
+IoSetNextIrpStackLocation (PIRP Irp)
{
Irp->CurrentLocation--;
Irp->Tail.Overlay.CurrentStackLocation--;
}
-PIO_STACK_LOCATION IoGetNextIrpStackLocation(PIRP Irp)
+
+/**********************************************************************
+ * NAME INTERNAL
+ * IoGetNextIrpStackLocation
+ */
+PIO_STACK_LOCATION
+IoGetNextIrpStackLocation (PIRP Irp)
/*
* FUNCTION: Gives a higher level driver access to the next lower driver's
* I/O stack location
* RETURNS: A pointer to the stack location
*/
{
+// DPRINT("IoGetNextIrpStackLocation(Irp %x)\n",Irp);
+
assert(Irp!=NULL);
- DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation);
+// DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation);
return(&Irp->Stack[Irp->CurrentLocation-1]);
}
-NTSTATUS IoCallDriver(PDEVICE_OBJECT DevObject, PIRP irp)
+
+NTSTATUS
+FASTCALL
+IofCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
- * FUNCTION: Sends an IRP to the next lower driver
+ * FUNCTION: Sends an IRP to the next lower driver
*/
{
- PDRIVER_OBJECT drv = DevObject->DriverObject;
- IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(irp);
- DPRINT("Deviceobject %x\n",DevObject);
- DPRINT("Irp %x\n",irp);
- irp->Tail.Overlay.CurrentStackLocation--;
- irp->CurrentLocation--;
- DPRINT("Io stack address %x\n",param);
- DPRINT("Function %d Routine %x\n",param->MajorFunction,
- drv->MajorFunction[param->MajorFunction]);
- DPRINT("IRP_MJ_CREATE %d\n",IRP_MJ_CREATE);
-
- return(drv->MajorFunction[param->MajorFunction](DevObject,irp));
+ NTSTATUS Status;
+ PDRIVER_OBJECT DriverObject;
+ PIO_STACK_LOCATION Param;
+
+// DPRINT("IoCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
+
+ DriverObject = DeviceObject->DriverObject;
+ Param = IoGetNextIrpStackLocation(Irp);
+
+ Irp->Tail.Overlay.CurrentStackLocation--;
+ Irp->CurrentLocation--;
+
+// DPRINT("MajorFunction %d\n", Param->MajorFunction);
+// DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
+// DriverObject->MajorFunction[Param->MajorFunction]);
+ Status = DriverObject->MajorFunction[Param->MajorFunction](DeviceObject,
+ Irp);
+ return Status;
}
-PIRP IoAllocateIrp(CCHAR StackSize, BOOLEAN ChargeQuota)
+
+NTSTATUS
+STDCALL
+IoCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ return IofCallDriver (
+ DeviceObject,
+ Irp
+ );
+}
+
+
+PIRP
+STDCALL
+IoAllocateIrp (CCHAR StackSize, BOOLEAN ChargeQuota)
/*
* FUNCTION: Allocates an IRP
* ARGUMENTS:
*/
{
PIRP Irp;
-
- DPRINT("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",StackSize,
+
+#if 0
+ DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
+ StackSize,
ChargeQuota);
+ KeDumpStackFrames(0,8);
+#endif
+
if (ChargeQuota)
{
- Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
+// Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
+ Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
}
else
{
return(NULL);
}
- Irp->CurrentLocation=StackSize;
+ IoInitializeIrp(Irp, IoSizeOfIrp(StackSize), StackSize);
+
+// DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
- DPRINT("Irp %x Irp->StackPtr %d\n",Irp,Irp->CurrentLocation);
- return(Irp);
+ return Irp;
}
-VOID IoSetCompletionRoutine(PIRP Irp,
+
+/**********************************************************************
+ * NAME INTERNAL
+ * IoSetCompletionRoutine
+ */
+VOID
+IoSetCompletionRoutine (PIRP Irp,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID Context,
BOOLEAN InvokeOnSuccess,
param->CompletionContext=Context;
if (InvokeOnSuccess)
{
- param->Control = SL_INVOKE_ON_SUCCESS;
+ param->Control = param->Control | SL_INVOKE_ON_SUCCESS;
}
if (InvokeOnError)
{
}
}
-VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost)
+VOID IopCompleteRequest(struct _KAPC* Apc,
+ PKNORMAL_ROUTINE* NormalRoutine,
+ PVOID* NormalContext,
+ PVOID* SystemArgument1,
+ PVOID* SystemArgument2)
+{
+ DPRINT("IopCompleteRequest(Apc %x, SystemArgument1 %x, "
+ "(*SystemArgument1) %x\n", Apc, SystemArgument1,
+ *SystemArgument1);
+ IoSecondStageCompletion((PIRP)(*SystemArgument1),
+ (KPRIORITY)(*SystemArgument2));
+}
+
+
+VOID
+FASTCALL
+IofCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
/*
* FUNCTION: Indicates the caller has finished all processing for a given
* I/O request and is returning the given IRP to the I/O manager
* thread making the request
*/
{
- unsigned int i=0;
- unsigned int stack_size;
+ unsigned int i;
+ NTSTATUS Status;
+ PKTHREAD Thread;
- DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d)\n",
- Irp,PriorityBoost);
- DPRINT("Irp->Stack[i].DeviceObject->StackSize %x\n",
- Irp->Stack[i].DeviceObject->StackSize);
- stack_size = Irp->Stack[i].DeviceObject->StackSize;
- for (i=0;i<stack_size;i++)
+ DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
+ Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
+
+ for (i=0;i<Irp->StackCount;i++)
{
- if (Irp->Stack[i].CompletionRoutine!=NULL)
+ if (Irp->Stack[i].CompletionRoutine != NULL)
{
- Irp->Stack[i].CompletionRoutine(Irp->Stack[i].DeviceObject,Irp,
+ Status = Irp->Stack[i].CompletionRoutine(
+ Irp->Stack[i].DeviceObject,
+ Irp,
Irp->Stack[i].CompletionContext);
+ if (Status == STATUS_MORE_PROCESSING_REQUIRED)
+ {
+ return;
+ }
+ }
+ if (Irp->Stack[i].Control & SL_PENDING_RETURNED)
+ {
+ Irp->PendingReturned = TRUE;
}
}
-
- if (Irp->UserEvent!=NULL)
+
+ if (Irp->PendingReturned)
{
- KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
+ DPRINT("Dispatching APC\n");
+ Thread = &Irp->Tail.Overlay.Thread->Tcb;
+ KeInitializeApc(&Irp->Tail.Apc,
+ Thread,
+ 0,
+ IopCompleteRequest,
+ NULL,
+ (PKNORMAL_ROUTINE)
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine,
+ UserMode,
+ (PVOID)
+ Irp->Overlay.AsynchronousParameters.UserApcContext);
+ KeInsertQueueApc(&Irp->Tail.Apc,
+ (PVOID)Irp,
+ (PVOID)(ULONG)PriorityBoost,
+ KernelMode);
+ DPRINT("Finished dispatching APC\n");
}
- if (Irp->UserIosb!=NULL)
+ else
{
- *Irp->UserIosb=Irp->IoStatus;
+ DPRINT("Calling completion routine directly\n");
+ IoSecondStageCompletion(Irp,PriorityBoost);
+ DPRINT("Finished completition routine\n");
}
-
- /*
- * If the
- */
}
+
+
+VOID
+STDCALL
+IoCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
+{
+ IofCompleteRequest (
+ Irp,
+ PriorityBoost
+ );
+}
+
+
+/**********************************************************************
+ * NAME EXPORTED
+ * IoIsOperationSynchronous@4
+ *
+ * DESCRIPTION
+ * Check if the I/O operation associated with the given IRP
+ * is synchronous.
+ *
+ * ARGUMENTS
+ * Irp Packet to check.
+ *
+ * RETURN VALUE
+ * TRUE if Irp's operation is synchronous; otherwise FALSE.
+ */
+BOOLEAN
+STDCALL
+IoIsOperationSynchronous (
+ IN PIRP Irp
+ )
+{
+ ULONG Flags = 0;
+ PFILE_OBJECT FileObject = NULL;
+
+ /*
+ * Check the associated FILE_OBJECT's
+ * flags first.
+ */
+ FileObject = Irp->Tail.Overlay.OriginalFileObject;
+ if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
+ {
+ /* Check IRP's flags. */
+ Flags = Irp->Flags;
+ if (!( (IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO)
+ & Flags
+ ))
+ {
+ return FALSE;
+ }
+ }
+ /*
+ * Check more IRP's flags.
+ */
+ Flags = Irp->Flags;
+ if ( !(IRP_MOUNT_COMPLETION & Flags)
+ || (IRP_SYNCHRONOUS_PAGING_IO & Flags)
+ )
+ {
+ return TRUE;
+ }
+ /*
+ * Otherwise, it is an
+ * asynchronous operation.
+ */
+ return FALSE;
+}
+
+
+/* EOF */