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))))
294 Status = Irp->Stack[i].CompletionRoutine(DeviceObject,
296 Irp->Stack[i].Context);
297 #else /* !LIBCAPTIVE */
298 Status = (NTSTATUS)captive_stdcall_call_12((CaptiveStdCallFunc12)Irp->Stack[i].CompletionRoutine,
301 Irp->Stack[i].Context);
302 #endif /* LIBCAPTIVE */
304 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
308 *Irp->UserIosb=Irp->IoStatus;
314 if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
316 Irp->PendingReturned = TRUE;
320 //Windows NT File System Internals, page 154
321 OriginalFileObject = Irp->Tail.Overlay.OriginalFileObject;
323 if (Irp->PendingReturned)
327 #endif /* LIBCAPTIVE */
330 /* FIXME: Why the hell should we bother with some damned APCs?!?
331 * Call it directly below!
333 DPRINT("IofCompleteRequest() dispatching APC: using g_idle_add_full()\n");
334 IofCompleteRequest_register_APC(OriginalFileObject,Irp,PriorityBoost);
335 #else /* !LIBCAPTIVE */
336 DPRINT("Dispatching APC\n");
337 KeInitializeApc( &Irp->Tail.Apc,
338 &Irp->Tail.Overlay.Thread->Tcb,
339 OriginalApcEnvironment,
340 IoSecondStageCompletion,
342 (PKNORMAL_ROUTINE) NULL,
346 bStatus = KeInsertQueueApc(&Irp->Tail.Apc,
348 (PVOID)(ULONG)PriorityBoost,
351 if (bStatus == FALSE)
353 DPRINT1("Error queueing APC for thread. Thread has probably exited.\n");
355 #endif /* !LIBCAPTIVE */
357 DPRINT("Finished dispatching APC\n");
361 DPRINT("Calling IoSecondStageCompletion routine directly\n");
362 IoSecondStageCompletion(NULL,NULL,(PVOID)&OriginalFileObject,(PVOID) &Irp,(PVOID) &PriorityBoost);
363 DPRINT("Finished completition routine\n");
373 IoCompleteRequest(PIRP Irp,
376 IofCompleteRequest(Irp,
381 /**********************************************************************
383 * IoIsOperationSynchronous@4
386 * Check if the I/O operation associated with the given IRP
390 * Irp Packet to check.
393 * TRUE if Irp's operation is synchronous; otherwise FALSE.
398 IoIsOperationSynchronous(IN PIRP Irp)
400 PFILE_OBJECT FileObject = NULL;
403 /* Check the FILE_OBJECT's flags first. */
404 FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
405 if (FileObject == NULL)
407 if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
409 /* Check IRP's flags. */
411 if (!((IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO) & Flags))
414 /* libcaptive is fully single-thread/single-process synchronous model. */
416 #endif /* LIBCAPTIVE */
421 if (Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO)
426 if (Irp->Flags & IRP_PAGING_IO)
429 /* libcaptive is fully single-thread/single-process synchronous model. */
431 #endif /* LIBCAPTIVE */
435 //NOTE: Windows 2000 crash if IoStack->FileObject == NULL, so I guess we should too;-)
436 if (Irp->Flags & IRP_SYNCHRONOUS_API || FileObject->Flags & FO_SYNCHRONOUS_IO)
441 /* Otherwise, it is an asynchronous operation. */
443 /* libcaptive is fully single-thread/single-process synchronous model. */
445 #endif /* LIBCAPTIVE */
455 IoEnqueueIrp(IN PIRP Irp)
460 #endif /* LIBCAPTIVE */
466 IoSetTopLevelIrp(IN PIRP Irp)
470 Thread = PsGetCurrentThread();
471 Thread->TopLevelIrp->TopLevelIrp = Irp;
479 IoGetTopLevelIrp(VOID)
481 return(PsGetCurrentThread()->TopLevelIrp->TopLevelIrp);
490 IoQueueThreadIrp(IN PIRP Irp)
495 #endif /* LIBCAPTIVE */