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 ****************************************************************/
52 * FUNCTION: Releases a caller allocated irp
63 IoMakeAssociatedIrp(PIRP Irp,
66 * FUNCTION: Allocates and initializes an irp to associated with a master irp
69 * StackSize = Number of stack locations to be allocated in the irp
70 * RETURNS: The irp allocated
75 AssocIrp = IoAllocateIrp(StackSize,FALSE);
80 #endif /* LIBCAPTIVE */
83 IoInitializeIrp(PIRP Irp,
87 * FUNCTION: Initalizes an irp allocated by the caller
89 * Irp = IRP to initalize
90 * PacketSize = Size in bytes of the IRP
91 * StackSize = Number of stack locations in the IRP
96 memset(Irp, 0, PacketSize);
97 Irp->Type = IO_TYPE_IRP;
98 Irp->Size = PacketSize;
99 Irp->StackCount = StackSize;
100 Irp->CurrentLocation = StackSize;
101 Irp->Tail.Overlay.CurrentStackLocation = &Irp->Stack[(ULONG)StackSize];
106 IofCallDriver(PDEVICE_OBJECT DeviceObject,
109 * FUNCTION: Sends an IRP to the next lower driver
112 PDRIVER_OBJECT DriverObject;
113 PIO_STACK_LOCATION Param;
115 DPRINT("IofCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
118 assert(DeviceObject);
120 DriverObject = DeviceObject->DriverObject;
122 assert(DriverObject);
124 IoSetNextIrpStackLocation(Irp);
125 Param = IoGetCurrentIrpStackLocation(Irp);
127 DPRINT("IrpSp 0x%X\n", Param);
129 Param->DeviceObject = DeviceObject;
131 DPRINT("MajorFunction %d\n", Param->MajorFunction);
132 DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
133 DriverObject->MajorFunction[Param->MajorFunction]);
135 if (!DriverObject->MajorFunction[Param->MajorFunction])
137 return DriverObject->MajorFunction[Param->MajorFunction](DeviceObject, Irp);
143 IoCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
145 return(IofCallDriver(DeviceObject,
151 IoAllocateIrp(CCHAR StackSize,
154 * FUNCTION: Allocates an IRP
156 * StackSize = the size of the stack required for the irp
157 * ChargeQuota = Charge allocation to current threads quota
158 * RETURNS: Irp allocated
164 DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
167 KeDumpStackFrames(0,8);
172 // Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
173 Irp = ExAllocatePoolWithTag(NonPagedPool,
174 IoSizeOfIrp(StackSize),
179 Irp = ExAllocatePoolWithTag(NonPagedPool,
180 IoSizeOfIrp(StackSize),
190 IoSizeOfIrp(StackSize),
193 // DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
201 IopCompleteRequest(struct _KAPC* Apc,
202 PKNORMAL_ROUTINE* NormalRoutine,
203 PVOID* NormalContext,
204 PVOID* SystemArgument1,
205 PVOID* SystemArgument2)
207 DPRINT("IopCompleteRequest(Apc %x, SystemArgument1 %x, (*SystemArgument1) %x\n",
211 IoSecondStageCompletion((PIRP)(*SystemArgument1),
212 (KPRIORITY)(*SystemArgument2));
215 #endif /* LIBCAPTIVE */
218 IofCompleteRequest(PIRP Irp,
221 * FUNCTION: Indicates the caller has finished all processing for a given
222 * I/O request and is returning the given IRP to the I/O manager
224 * Irp = Irp to be cancelled
225 * PriorityBoost = Increment by which to boost the priority of the
226 * thread making the request
231 PDEVICE_OBJECT DeviceObject;
233 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
234 Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
236 assert(Irp->CancelRoutine == NULL);
237 assert(Irp->IoStatus.Status != STATUS_PENDING);
239 if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
241 Irp->PendingReturned = TRUE;
244 for (i=Irp->CurrentLocation;i<(ULONG)Irp->StackCount;i++)
247 Completion routines expect the current irp stack location to be the same as when
248 IoSetCompletionRoutine was called to set them. A side effect is that completion
249 routines set by highest level drivers without their own stack location will receive
250 an invalid current stack location (at least it should be considered as invalid).
251 Since the DeviceObject argument passed is taken from the current stack, this value
252 is also invalid (NULL).
254 if (Irp->CurrentLocation < Irp->StackCount - 1)
256 IoSetPreviousIrpStackLocation(Irp);
257 DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject;
264 if (Irp->Stack[i].CompletionRoutine != NULL &&
265 ((NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_SUCCESS)) ||
266 (!NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_ERROR)) ||
267 (Irp->Cancel && (Irp->Stack[i].Control & SL_INVOKE_ON_CANCEL))))
269 Status = Irp->Stack[i].CompletionRoutine(DeviceObject,
271 Irp->Stack[i].CompletionContext);
273 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
277 *Irp->UserIosb=Irp->IoStatus;
283 if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
285 Irp->PendingReturned = TRUE;
289 if (Irp->PendingReturned)
292 /* FIXME: Why the hell should we bother with some damned APCs?!?
293 * Call it directly below!
295 DPRINT("IofCompleteRequest() would like to dispatch APC: F*ck off!\n");
296 #else /* !LIBCAPTIVE */
297 DPRINT("Dispatching APC\n");
298 KeInitializeApc(&Irp->Tail.Apc,
299 &Irp->Tail.Overlay.Thread->Tcb,
307 KeInsertQueueApc(&Irp->Tail.Apc,
309 (PVOID)(ULONG)PriorityBoost,
311 DPRINT("Finished dispatching APC\n");
312 #endif /* !LIBCAPTIVE */
316 #endif /* LIBCAPTIVE */
318 DPRINT("Calling completion routine directly\n");
319 IoSecondStageCompletion(Irp,PriorityBoost);
320 DPRINT("Finished completition routine\n");
326 IoCompleteRequest(PIRP Irp,
329 IofCompleteRequest(Irp,
334 /**********************************************************************
336 * IoIsOperationSynchronous@4
339 * Check if the I/O operation associated with the given IRP
343 * Irp Packet to check.
346 * TRUE if Irp's operation is synchronous; otherwise FALSE.
349 IoIsOperationSynchronous(IN PIRP Irp)
351 PFILE_OBJECT FileObject = NULL;
354 /* Check the FILE_OBJECT's flags first. */
355 FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
356 if (FileObject == NULL)
358 if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
360 /* Check IRP's flags. */
362 if (!((IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO) & Flags))
365 /* libcaptive is fully single-thread/single-process synchronous model. */
367 #endif /* LIBCAPTIVE */
372 /* Check more IRP's flags. */
374 if (!(IRP_PAGING_IO & Flags)
375 || (IRP_SYNCHRONOUS_PAGING_IO & Flags))
380 /* Otherwise, it is an asynchronous operation. */
382 /* libcaptive is fully single-thread/single-process synchronous model. */
384 #endif /* LIBCAPTIVE */
391 IoEnqueueIrp(IN PIRP Irp)
396 #endif /* LIBCAPTIVE */
399 IoSetTopLevelIrp(IN PIRP Irp)
403 Thread = PsGetCurrentThread();
404 Thread->TopLevelIrp->TopLevelIrp = Irp;
409 IoGetTopLevelIrp(VOID)
411 return(PsGetCurrentThread()->TopLevelIrp->TopLevelIrp);
417 IoQueueThreadIrp(IN PIRP Irp)
425 IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
434 IN PDEVICE_OBJECT DeviceObject,
435 IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
436 IN ULONG BufferLength,
437 OUT PVOID PropertyBuffer,
438 OUT PULONG ResultLength)
446 IoOpenDeviceRegistryKey(
447 IN PDEVICE_OBJECT DeviceObject,
448 IN ULONG DevInstKeyType,
449 IN ACCESS_MASK DesiredAccess,
450 OUT PHANDLE DevInstRegKey)
457 #endif /* LIBCAPTIVE */