3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/irp.c
7 * PROGRAMMER: David Welch (welch@mcmail.com)
12 /* NOTES *******************************************************************
31 /* INCLUDES ****************************************************************/
33 #include <ddk/ntddk.h>
34 #include <internal/io.h>
35 #include <internal/ps.h>
36 #include <internal/pool.h>
39 #include <internal/debug.h>
41 /* GLOBALS *******************************************************************/
43 #define TAG_IRP TAG('I', 'R', 'P', ' ')
46 /* FUNCTIONS ****************************************************************/
55 * FUNCTION: Releases a caller allocated irp
69 IoMakeAssociatedIrp(PIRP Irp,
72 * FUNCTION: Allocates and initializes an irp to associated with a master irp
75 * StackSize = Number of stack locations to be allocated in the irp
76 * RETURNS: The irp allocated
81 AssocIrp = IoAllocateIrp(StackSize,FALSE);
86 #endif /* LIBCAPTIVE */
92 IoInitializeIrp(PIRP Irp,
96 * FUNCTION: Initalizes an irp allocated by the caller
98 * Irp = IRP to initalize
99 * PacketSize = Size in bytes of the IRP
100 * StackSize = Number of stack locations in the IRP
105 memset(Irp, 0, PacketSize);
106 Irp->Type = IO_TYPE_IRP;
107 Irp->Size = PacketSize;
108 Irp->StackCount = StackSize;
109 Irp->CurrentLocation = StackSize;
110 Irp->Tail.Overlay.CurrentStackLocation = &Irp->Stack[(ULONG)StackSize];
118 IofCallDriver(PDEVICE_OBJECT DeviceObject,
121 * FUNCTION: Sends an IRP to the next lower driver
124 PDRIVER_OBJECT DriverObject;
125 PIO_STACK_LOCATION Param;
127 DPRINT("IofCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
130 assert(DeviceObject);
132 DriverObject = DeviceObject->DriverObject;
134 assert(DriverObject);
136 IoSetNextIrpStackLocation(Irp);
137 Param = IoGetCurrentIrpStackLocation(Irp);
139 DPRINT("IrpSp 0x%X\n", Param);
141 Param->DeviceObject = DeviceObject;
143 DPRINT("MajorFunction %d\n", Param->MajorFunction);
144 DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
145 DriverObject->MajorFunction[Param->MajorFunction]);
147 if (!DriverObject->MajorFunction[Param->MajorFunction])
149 if (Param->MajorFunction==IRP_MJ_FLUSH_BUFFERS)
151 ObDereferenceObject(Param->FileObject);
152 return STATUS_SUCCESS;
158 return DriverObject->MajorFunction[Param->MajorFunction](DeviceObject, Irp);
159 #else /* !LIBCAPTIVE */
160 return (NTSTATUS)captive_stdcall_call_8(
161 (CaptiveStdCallFunc8)DriverObject->MajorFunction[Param->MajorFunction],
164 #endif /* LIBCAPTIVE */
173 IoCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
175 return(IofCallDriver(DeviceObject,
184 IoAllocateIrp(CCHAR StackSize,
187 * FUNCTION: Allocates an IRP
189 * StackSize = the size of the stack required for the irp
190 * ChargeQuota = Charge allocation to current threads quota
191 * RETURNS: Irp allocated
197 DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
200 KeDumpStackFrames(0,8);
205 // Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
206 Irp = ExAllocatePoolWithTag(NonPagedPool,
207 IoSizeOfIrp(StackSize),
212 Irp = ExAllocatePoolWithTag(NonPagedPool,
213 IoSizeOfIrp(StackSize),
223 IoSizeOfIrp(StackSize),
226 // DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
233 /* file-scope of libcaptive/io/irp.c: */
234 extern void IofCompleteRequest_register_APC(PFILE_OBJECT OriginalFileObject,PIRP Irp,CCHAR PriorityBoost);
235 #endif /* LIBCAPTIVE */
241 IofCompleteRequest(PIRP Irp,
244 * FUNCTION: Indicates the caller has finished all processing for a given
245 * I/O request and is returning the given IRP to the I/O manager
247 * Irp = Irp to be cancelled
248 * PriorityBoost = Increment by which to boost the priority of the
249 * thread making the request
254 PDEVICE_OBJECT DeviceObject;
255 PFILE_OBJECT OriginalFileObject;
257 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
258 Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
260 assert(Irp->CancelRoutine == NULL);
261 assert(Irp->IoStatus.Status != STATUS_PENDING);
263 if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
265 Irp->PendingReturned = TRUE;
268 for (i=Irp->CurrentLocation;i<(ULONG)Irp->StackCount;i++)
271 Completion routines expect the current irp stack location to be the same as when
272 IoSetCompletionRoutine was called to set them. A side effect is that completion
273 routines set by highest level drivers without their own stack location will receive
274 an invalid current stack location (at least it should be considered as invalid).
275 Since the DeviceObject argument passed is taken from the current stack, this value
276 is also invalid (NULL).
278 if (Irp->CurrentLocation < Irp->StackCount - 1)
280 IoSetPreviousIrpStackLocation(Irp);
281 DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject;
288 if (Irp->Stack[i].CompletionRoutine != NULL &&
289 ((NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_SUCCESS)) ||
290 (!NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_ERROR)) ||
291 (Irp->Cancel && (Irp->Stack[i].Control & SL_INVOKE_ON_CANCEL))))
293 Status = Irp->Stack[i].CompletionRoutine(DeviceObject,
295 Irp->Stack[i].Context);
297 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
301 *Irp->UserIosb=Irp->IoStatus;
307 if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
309 Irp->PendingReturned = TRUE;
313 //Windows NT File System Internals, page 154
314 OriginalFileObject = Irp->Tail.Overlay.OriginalFileObject;
316 if (Irp->PendingReturned)
320 #endif /* LIBCAPTIVE */
323 /* FIXME: Why the hell should we bother with some damned APCs?!?
324 * Call it directly below!
326 DPRINT("IofCompleteRequest() dispatching APC: using g_idle_add_full()\n");
327 IofCompleteRequest_register_APC(OriginalFileObject,Irp,PriorityBoost);
328 #else /* !LIBCAPTIVE */
329 DPRINT("Dispatching APC\n");
330 KeInitializeApc( &Irp->Tail.Apc,
331 &Irp->Tail.Overlay.Thread->Tcb,
332 OriginalApcEnvironment,
333 IoSecondStageCompletion,
335 (PKNORMAL_ROUTINE) NULL,
339 bStatus = KeInsertQueueApc(&Irp->Tail.Apc,
341 (PVOID)(ULONG)PriorityBoost,
344 if (bStatus == FALSE)
346 DPRINT1("Error queueing APC for thread. Thread has probably exited.\n");
348 #endif /* !LIBCAPTIVE */
350 DPRINT("Finished dispatching APC\n");
354 DPRINT("Calling IoSecondStageCompletion routine directly\n");
355 IoSecondStageCompletion(NULL,NULL,(PVOID)&OriginalFileObject,(PVOID) &Irp,(PVOID) &PriorityBoost);
356 DPRINT("Finished completition routine\n");
366 IoCompleteRequest(PIRP Irp,
369 IofCompleteRequest(Irp,
374 /**********************************************************************
376 * IoIsOperationSynchronous@4
379 * Check if the I/O operation associated with the given IRP
383 * Irp Packet to check.
386 * TRUE if Irp's operation is synchronous; otherwise FALSE.
391 IoIsOperationSynchronous(IN PIRP Irp)
393 PFILE_OBJECT FileObject = NULL;
396 /* Check the FILE_OBJECT's flags first. */
397 FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
398 if (FileObject == NULL)
400 if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
402 /* Check IRP's flags. */
404 if (!((IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO) & Flags))
407 /* libcaptive is fully single-thread/single-process synchronous model. */
409 #endif /* LIBCAPTIVE */
414 if (Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO)
419 if (Irp->Flags & IRP_PAGING_IO)
422 /* libcaptive is fully single-thread/single-process synchronous model. */
424 #endif /* LIBCAPTIVE */
428 //NOTE: Windows 2000 crash if IoStack->FileObject == NULL, so I guess we should too;-)
429 if (Irp->Flags & IRP_SYNCHRONOUS_API || FileObject->Flags & FO_SYNCHRONOUS_IO)
434 /* Otherwise, it is an asynchronous operation. */
436 /* libcaptive is fully single-thread/single-process synchronous model. */
438 #endif /* LIBCAPTIVE */
448 IoEnqueueIrp(IN PIRP Irp)
453 #endif /* LIBCAPTIVE */
459 IoSetTopLevelIrp(IN PIRP Irp)
463 Thread = PsGetCurrentThread();
464 Thread->TopLevelIrp->TopLevelIrp = Irp;
472 IoGetTopLevelIrp(VOID)
474 return(PsGetCurrentThread()->TopLevelIrp->TopLevelIrp);
483 IoQueueThreadIrp(IN PIRP Irp)
488 #endif /* LIBCAPTIVE */