-/*\r
- * COPYRIGHT: See COPYING in the top level directory\r
- * PROJECT: ReactOS kernel\r
- * FILE: ntoskrnl/io/irp.c\r
- * PURPOSE: Handle IRPs\r
- * PROGRAMMER: David Welch (welch@mcmail.com)\r
- * UPDATE HISTORY: \r
- * 24/05/98: Created \r
- */\r
-\r
-/* NOTES *******************************************************************\r
- * \r
- * Layout of an IRP \r
- * \r
- * ################\r
- * # Headers #\r
- * ################\r
- * # #\r
- * # Variable #\r
- * # length list #\r
- * # of io stack #\r
- * # locations #\r
- * # #\r
- * ################\r
- * \r
- * \r
- * \r
- */\r
-\r
-/* INCLUDES ****************************************************************/\r
-\r
-#include <internal/string.h>\r
-#include <internal/io.h>\r
-#include <ddk/ntddk.h>\r
-\r
-//#define NDEBUG\r
-#include <internal/debug.h>\r
-\r
-/* FUNCTIONS ****************************************************************/\r
-\r
-PDEVICE_OBJECT IoGetDeviceToVerify(PETHREAD Thread)\r
-/*\r
- * FUNCTION: Returns a pointer to the device, representing a removable-media\r
- * device, that is the target of the given thread's I/O request\r
- */\r
-{\r
- UNIMPLEMENTED;\r
-}\r
-\r
-VOID IoFreeIrp(PIRP Irp)\r
-/*\r
- * FUNCTION: Releases a caller allocated irp\r
- * ARGUMENTS:\r
- * Irp = Irp to free\r
- */\r
-{\r
- ExFreePool(Irp);\r
-}\r
-\r
-PIRP IoMakeAssociatedIrp(PIRP Irp, CCHAR StackSize)\r
-/*\r
- * FUNCTION: Allocates and initializes an irp to associated with a master irp\r
- * ARGUMENTS:\r
- * Irp = Master irp\r
- * StackSize = Number of stack locations to be allocated in the irp\r
- * RETURNS: The irp allocated\r
- */\r
-{\r
- PIRP AssocIrp;\r
- \r
- AssocIrp = IoAllocateIrp(StackSize,FALSE);\r
- UNIMPLEMENTED;\r
-}\r
-\r
-VOID IoMarkIrpPending(PIRP Irp)\r
-/*\r
- * FUNCTION: Marks the specified irp, indicating further processing will\r
- * be required by other driver routines\r
- * ARGUMENTS:\r
- * Irp = Irp to mark\r
- */\r
-{\r
- DPRINT("IoGetCurrentIrpStackLocation(Irp) %x\n",\r
- IoGetCurrentIrpStackLocation(Irp));\r
- IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED;\r
- Irp->Tail.Overlay.Thread = KeGetCurrentThread();\r
- DPRINT("IoGetCurrentIrpStackLocation(Irp)->Control %x\n",\r
- IoGetCurrentIrpStackLocation(Irp)->Control);\r
- DPRINT("SL_PENDING_RETURNED %x\n",SL_PENDING_RETURNED);\r
-}\r
-\r
-USHORT IoSizeOfIrp(CCHAR StackSize)\r
-/*\r
- * FUNCTION: Determines the size of an IRP\r
- * ARGUMENTS: \r
- * StackSize = number of stack locations in the IRP\r
- * RETURNS: The size of the IRP in bytes \r
- */\r
-{\r
- return(sizeof(IRP)+((StackSize-1)*sizeof(IO_STACK_LOCATION)));\r
-}\r
-\r
-VOID IoInitializeIrp(PIRP Irp, USHORT PacketSize, CCHAR StackSize)\r
-/*\r
- * FUNCTION: Initalizes an irp allocated by the caller\r
- * ARGUMENTS:\r
- * Irp = IRP to initalize\r
- * PacketSize = Size in bytes of the IRP\r
- * StackSize = Number of stack locations in the IRP\r
- */\r
-{\r
- assert(Irp!=NULL);\r
- memset(Irp,0,PacketSize);\r
- Irp->StackCount=StackSize;\r
- Irp->CurrentLocation=StackSize;\r
- Irp->Tail.Overlay.CurrentStackLocation=IoGetCurrentIrpStackLocation(Irp);\r
-}\r
-\r
-PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)\r
-/*\r
- * FUNCTION: Gets a pointer to the callers location in the I/O stack in\r
- * the given IRP\r
- * ARGUMENTS:\r
- * Irp = Points to the IRP\r
- * RETURNS: A pointer to the stack location\r
- */\r
-{\r
- DPRINT("IoGetCurrentIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n", \r
- Irp,\r
- Irp->CurrentLocation,\r
- Irp->StackCount);\r
-\r
- return &Irp->Stack[Irp->CurrentLocation];\r
-}\r
-\r
-\r
-VOID IoSetNextIrpStackLocation(PIRP Irp)\r
-{\r
- Irp->CurrentLocation--;\r
- Irp->Tail.Overlay.CurrentStackLocation--;\r
-}\r
-\r
-PIO_STACK_LOCATION IoGetNextIrpStackLocation(PIRP Irp)\r
-/*\r
- * FUNCTION: Gives a higher level driver access to the next lower driver's \r
- * I/O stack location\r
- * ARGUMENTS: \r
- * Irp = points to the irp\r
- * RETURNS: A pointer to the stack location \r
- */\r
-{\r
- DPRINT("IoGetNextIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n", \r
- Irp,\r
- Irp->CurrentLocation,\r
- Irp->StackCount);\r
-\r
- assert(Irp!=NULL);\r
- DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation);\r
- return(&Irp->Stack[Irp->CurrentLocation-1]);\r
-}\r
-\r
-NTSTATUS IoCallDriver(PDEVICE_OBJECT DevObject, PIRP irp)\r
-/*\r
- * FUNCTION: Sends an IRP to the next lower driver\r
- */\r
-{\r
- NTSTATUS Status;\r
- PDRIVER_OBJECT drv = DevObject->DriverObject;\r
- IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(irp);\r
-\r
- DPRINT("Deviceobject %x\n",DevObject);\r
- DPRINT("Irp %x\n",irp);\r
-\r
- irp->Tail.Overlay.CurrentStackLocation--;\r
- irp->CurrentLocation--;\r
-\r
- DPRINT("Io stack address %x\n",param);\r
- DPRINT("Function %d Routine %x\n",param->MajorFunction,\r
- drv->MajorFunction[param->MajorFunction]);\r
-\r
- Status = drv->MajorFunction[param->MajorFunction](DevObject,irp);\r
- return Status;\r
-}\r
-\r
-PIRP IoAllocateIrp(CCHAR StackSize, BOOLEAN ChargeQuota)\r
-/*\r
- * FUNCTION: Allocates an IRP\r
- * ARGUMENTS:\r
- * StackSize = the size of the stack required for the irp\r
- * ChargeQuota = Charge allocation to current threads quota\r
- * RETURNS: Irp allocated\r
- */\r
-{\r
- PIRP Irp;\r
- \r
- DPRINT("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",StackSize,\r
- ChargeQuota);\r
- if (ChargeQuota)\r
- {\r
- Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));\r
- }\r
- else\r
- { \r
- Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));\r
- }\r
- \r
- if (Irp==NULL)\r
- {\r
- return(NULL);\r
- }\r
- \r
- Irp->StackCount=StackSize;\r
- Irp->CurrentLocation=StackSize;\r
-\r
- DPRINT("Irp %x Irp->StackPtr %d\n",Irp,Irp->CurrentLocation);\r
- return(Irp);\r
-}\r
-\r
-VOID IoSetCompletionRoutine(PIRP Irp,\r
- PIO_COMPLETION_ROUTINE CompletionRoutine,\r
- PVOID Context,\r
- BOOLEAN InvokeOnSuccess,\r
- BOOLEAN InvokeOnError,\r
- BOOLEAN InvokeOnCancel)\r
-{\r
- IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(Irp);\r
- \r
- param->CompletionRoutine=CompletionRoutine;\r
- param->CompletionContext=Context;\r
- if (InvokeOnSuccess)\r
- {\r
- param->Control = param->Control | SL_INVOKE_ON_SUCCESS;\r
- }\r
- if (InvokeOnError)\r
- {\r
- param->Control = param->Control | SL_INVOKE_ON_ERROR;\r
- }\r
- if (InvokeOnCancel)\r
- {\r
- param->Control = param->Control | SL_INVOKE_ON_CANCEL;\r
- }\r
-}\r
-\r
-VOID IopCompleteRequest(struct _KAPC* Apc,\r
- PKNORMAL_ROUTINE* NormalRoutine,\r
- PVOID* NormalContext,\r
- PVOID* SystemArgument1,\r
- PVOID* SystemArgument2)\r
-{\r
- IoSecondStageCompletion((PIRP)(*NormalContext),\r
- IO_NO_INCREMENT);\r
-}\r
-\r
-VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost)\r
-/*\r
- * FUNCTION: Indicates the caller has finished all processing for a given\r
- * I/O request and is returning the given IRP to the I/O manager\r
- * ARGUMENTS:\r
- * Irp = Irp to be cancelled\r
- * PriorityBoost = Increment by which to boost the priority of the\r
- * thread making the request\r
- */\r
-{\r
- unsigned int i;\r
- NTSTATUS Status;\r
- \r
- DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d)\n",\r
- Irp,PriorityBoost);\r
-\r
- for (i=0;i<Irp->StackCount;i++)\r
- {\r
- DPRINT("&Irp->Stack[i] %x\n",&Irp->Stack[i]);\r
- if (Irp->Stack[i].CompletionRoutine!=NULL)\r
- {\r
- Status = Irp->Stack[i].CompletionRoutine(\r
- Irp->Stack[i].DeviceObject,\r
- Irp,\r
- Irp->Stack[i].CompletionContext);\r
- if (Status == STATUS_MORE_PROCESSING_REQUIRED)\r
- {\r
- return;\r
- }\r
- }\r
- DPRINT("Irp->Stack[i].Control %x\n",Irp->Stack[i].Control);\r
- if (Irp->Stack[i].Control & SL_PENDING_RETURNED)\r
- {\r
- DPRINT("Setting PendingReturned flag\n");\r
- Irp->PendingReturned = TRUE;\r
- }\r
- }\r
-\r
- if (Irp->PendingReturned)\r
- {\r
- KeInitializeApc(&Irp->Tail.Apc,\r
- &Irp->Tail.Overlay.Thread->Tcb,\r
- 0,\r
- IopCompleteRequest,\r
- NULL,\r
- NULL,\r
- 0,\r
- Irp);\r
- KeInsertQueueApc(&Irp->Tail.Apc,NULL,NULL,0);\r
- }\r
- else\r
- {\r
- IoSecondStageCompletion(Irp,PriorityBoost);\r
- }\r
-}\r
->>>>>>> 1.7\r
+/* $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
+ * PURPOSE: Handle IRPs
+ * PROGRAMMER: David Welch (welch@mcmail.com)
+ * UPDATE HISTORY:
+ * 24/05/98: Created
+ */
+
+/* NOTES *******************************************************************
+ *
+ * Layout of an IRP
+ *
+ * ################
+ * # Headers #
+ * ################
+ * # #
+ * # Variable #
+ * # length list #
+ * # of io stack #
+ * # locations #
+ * # #
+ * ################
+ *
+ *
+ *
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <string.h>
+#include <internal/string.h>
+#include <internal/io.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+/* FUNCTIONS ****************************************************************/
+
+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
+STDCALL
+IoFreeIrp (PIRP Irp)
+/*
+ * FUNCTION: Releases a caller allocated irp
+ * ARGUMENTS:
+ * Irp = Irp to free
+ */
+{
+ ExFreePool(Irp);
+}
+
+
+PIRP
+STDCALL
+IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
+/*
+ * FUNCTION: Allocates and initializes an irp to associated with a master irp
+ * ARGUMENTS:
+ * Irp = Master irp
+ * StackSize = Number of stack locations to be allocated in the irp
+ * RETURNS: The irp allocated
+ */
+{
+ PIRP AssocIrp;
+
+ AssocIrp = IoAllocateIrp(StackSize,FALSE);
+ UNIMPLEMENTED;
+}
+
+
+/**********************************************************************
+ * NAME INTERNAL
+ * IoMarkIrpPending
+ */
+VOID
+IoMarkIrpPending (PIRP Irp)
+/*
+ * FUNCTION: Marks the specified irp, indicating further processing will
+ * be required by other driver routines
+ * ARGUMENTS:
+ * Irp = Irp to mark
+ */
+{
+// DPRINT("IoGetCurrentIrpStackLocation(Irp) %x\n",
+// IoGetCurrentIrpStackLocation(Irp));
+ IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED;
+}
+
+
+/**********************************************************************
+ * NAME INTERNAL
+ * IoSizeOfIrp
+ */
+USHORT
+IoSizeOfIrp (CCHAR StackSize)
+/*
+ * FUNCTION: Determines the size of an IRP
+ * ARGUMENTS:
+ * StackSize = number of stack locations in the IRP
+ * RETURNS: The size of the IRP in bytes
+ */
+{
+ return(sizeof(IRP)+((StackSize-1)*sizeof(IO_STACK_LOCATION)));
+}
+
+
+VOID
+STDCALL
+IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
+/*
+ * FUNCTION: Initalizes an irp allocated by the caller
+ * ARGUMENTS:
+ * Irp = IRP to initalize
+ * PacketSize = Size in bytes of the IRP
+ * StackSize = Number of stack locations in the IRP
+ */
+{
+ assert(Irp != NULL);
+
+ memset(Irp, 0, PacketSize);
+ Irp->Size = PacketSize;
+ Irp->StackCount = StackSize;
+ Irp->CurrentLocation = StackSize;
+ Irp->Tail.Overlay.CurrentStackLocation = IoGetCurrentIrpStackLocation(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
+ * ARGUMENTS:
+ * Irp = Points to the IRP
+ * RETURNS: A pointer to the stack location
+ */
+{
+// DPRINT("IoGetCurrentIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n",
+// Irp,
+// Irp->CurrentLocation,
+// Irp->StackCount);
+
+ return(&Irp->Stack[(ULONG)Irp->CurrentLocation]);
+}
+
+
+/**********************************************************************
+ * NAME INTERNAL
+ * IoSetNextIrpStackLocation
+ */
+VOID
+IoSetNextIrpStackLocation (PIRP Irp)
+{
+ Irp->CurrentLocation--;
+ Irp->Tail.Overlay.CurrentStackLocation--;
+}
+
+
+/**********************************************************************
+ * 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
+ * ARGUMENTS:
+ * Irp = points to the irp
+ * 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);
+ return(&Irp->Stack[Irp->CurrentLocation-1]);
+}
+
+
+NTSTATUS
+FASTCALL
+IofCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+/*
+ * FUNCTION: Sends an IRP to the next lower driver
+ */
+{
+ 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;
+}
+
+
+NTSTATUS
+STDCALL
+IoCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ return IofCallDriver (
+ DeviceObject,
+ Irp
+ );
+}
+
+
+PIRP
+STDCALL
+IoAllocateIrp (CCHAR StackSize, BOOLEAN ChargeQuota)
+/*
+ * FUNCTION: Allocates an IRP
+ * ARGUMENTS:
+ * StackSize = the size of the stack required for the irp
+ * ChargeQuota = Charge allocation to current threads quota
+ * RETURNS: Irp allocated
+ */
+{
+ PIRP Irp;
+
+#if 0
+ DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
+ StackSize,
+ ChargeQuota);
+ KeDumpStackFrames(0,8);
+#endif
+
+ if (ChargeQuota)
+ {
+// Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
+ Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
+ }
+ else
+ {
+ Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
+ }
+
+ if (Irp==NULL)
+ {
+ return(NULL);
+ }
+
+ IoInitializeIrp(Irp, IoSizeOfIrp(StackSize), StackSize);
+
+// DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
+
+ return Irp;
+}
+
+
+/**********************************************************************
+ * NAME INTERNAL
+ * IoSetCompletionRoutine
+ */
+VOID
+IoSetCompletionRoutine (PIRP Irp,
+ PIO_COMPLETION_ROUTINE CompletionRoutine,
+ PVOID Context,
+ BOOLEAN InvokeOnSuccess,
+ BOOLEAN InvokeOnError,
+ BOOLEAN InvokeOnCancel)
+{
+ IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(Irp);
+
+ param->CompletionRoutine=CompletionRoutine;
+ param->CompletionContext=Context;
+ if (InvokeOnSuccess)
+ {
+ param->Control = param->Control | SL_INVOKE_ON_SUCCESS;
+ }
+ if (InvokeOnError)
+ {
+ param->Control = param->Control | SL_INVOKE_ON_ERROR;
+ }
+ if (InvokeOnCancel)
+ {
+ param->Control = param->Control | SL_INVOKE_ON_CANCEL;
+ }
+}
+
+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
+ * ARGUMENTS:
+ * Irp = Irp to be cancelled
+ * PriorityBoost = Increment by which to boost the priority of the
+ * thread making the request
+ */
+{
+ unsigned int i;
+ NTSTATUS Status;
+ PKTHREAD Thread;
+
+ 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)
+ {
+ 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->PendingReturned)
+ {
+ 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");
+ }
+ else
+ {
+ DPRINT("Calling completion routine directly\n");
+ IoSecondStageCompletion(Irp,PriorityBoost);
+ DPRINT("Finished completition routine\n");
+ }
+}
+
+
+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 */