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 */
219 /* file-scope of libcaptive/io/irp.c: */
220 extern void IofCompleteRequest_register_APC(PIRP Irp,CCHAR PriorityBoost);
221 #endif /* LIBCAPTIVE */
224 IofCompleteRequest(PIRP Irp,
227 * FUNCTION: Indicates the caller has finished all processing for a given
228 * I/O request and is returning the given IRP to the I/O manager
230 * Irp = Irp to be cancelled
231 * PriorityBoost = Increment by which to boost the priority of the
232 * thread making the request
237 PDEVICE_OBJECT DeviceObject;
239 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
240 Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
242 assert(Irp->CancelRoutine == NULL);
243 assert(Irp->IoStatus.Status != STATUS_PENDING);
245 if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
247 Irp->PendingReturned = TRUE;
250 for (i=Irp->CurrentLocation;i<(ULONG)Irp->StackCount;i++)
253 Completion routines expect the current irp stack location to be the same as when
254 IoSetCompletionRoutine was called to set them. A side effect is that completion
255 routines set by highest level drivers without their own stack location will receive
256 an invalid current stack location (at least it should be considered as invalid).
257 Since the DeviceObject argument passed is taken from the current stack, this value
258 is also invalid (NULL).
260 if (Irp->CurrentLocation < Irp->StackCount - 1)
262 IoSetPreviousIrpStackLocation(Irp);
263 DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject;
270 if (Irp->Stack[i].CompletionRoutine != NULL &&
271 ((NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_SUCCESS)) ||
272 (!NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_ERROR)) ||
273 (Irp->Cancel && (Irp->Stack[i].Control & SL_INVOKE_ON_CANCEL))))
275 Status = Irp->Stack[i].CompletionRoutine(DeviceObject,
277 Irp->Stack[i].CompletionContext);
279 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
283 *Irp->UserIosb=Irp->IoStatus;
289 if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
291 Irp->PendingReturned = TRUE;
295 if (Irp->PendingReturned)
298 /* FIXME: Why the hell should we bother with some damned APCs?!?
299 * Call it directly below!
301 DPRINT("IofCompleteRequest() dispatching APC: using g_idle_add_full()\n");
302 IofCompleteRequest_register_APC(Irp,PriorityBoost);
303 #else /* !LIBCAPTIVE */
304 DPRINT("Dispatching APC\n");
305 KeInitializeApc(&Irp->Tail.Apc,
306 &Irp->Tail.Overlay.Thread->Tcb,
314 KeInsertQueueApc(&Irp->Tail.Apc,
316 (PVOID)(ULONG)PriorityBoost,
318 #endif /* !LIBCAPTIVE */
319 DPRINT("Finished dispatching APC\n");
323 DPRINT("Calling completion routine directly\n");
324 IoSecondStageCompletion(Irp,PriorityBoost);
325 DPRINT("Finished completition routine\n");
331 IoCompleteRequest(PIRP Irp,
334 IofCompleteRequest(Irp,
339 /**********************************************************************
341 * IoIsOperationSynchronous@4
344 * Check if the I/O operation associated with the given IRP
348 * Irp Packet to check.
351 * TRUE if Irp's operation is synchronous; otherwise FALSE.
354 IoIsOperationSynchronous(IN PIRP Irp)
356 PFILE_OBJECT FileObject = NULL;
359 /* Check the FILE_OBJECT's flags first. */
360 FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
361 if (FileObject == NULL)
363 if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
365 /* Check IRP's flags. */
367 if (!((IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO) & Flags))
370 /* libcaptive is fully single-thread/single-process synchronous model. */
372 #endif /* LIBCAPTIVE */
377 /* Check more IRP's flags. */
379 if (!(IRP_PAGING_IO & Flags)
380 || (IRP_SYNCHRONOUS_PAGING_IO & Flags))
385 /* Otherwise, it is an asynchronous operation. */
387 /* libcaptive is fully single-thread/single-process synchronous model. */
389 #endif /* LIBCAPTIVE */
396 IoEnqueueIrp(IN PIRP Irp)
401 #endif /* LIBCAPTIVE */
404 IoSetTopLevelIrp(IN PIRP Irp)
408 Thread = PsGetCurrentThread();
409 Thread->TopLevelIrp->TopLevelIrp = Irp;
414 IoGetTopLevelIrp(VOID)
416 return(PsGetCurrentThread()->TopLevelIrp->TopLevelIrp);
422 IoQueueThreadIrp(IN PIRP Irp)
430 IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
439 IN PDEVICE_OBJECT DeviceObject,
440 IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
441 IN ULONG BufferLength,
442 OUT PVOID PropertyBuffer,
443 OUT PULONG ResultLength)
451 IoOpenDeviceRegistryKey(
452 IN PDEVICE_OBJECT DeviceObject,
453 IN ULONG DevInstKeyType,
454 IN ACCESS_MASK DesiredAccess,
455 OUT PHANDLE DevInstRegKey)
462 #endif /* LIBCAPTIVE */