2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/irp.c
6 * PROGRAMMER: David Welch (welch@mcmail.com)
11 /* NOTES *******************************************************************
30 /* INCLUDES ****************************************************************/
32 #include <ddk/ntddk.h>
34 #include <internal/string.h>
35 #include <internal/io.h>
38 #include <internal/debug.h>
40 /* FUNCTIONS ****************************************************************/
42 PDEVICE_OBJECT
IoGetDeviceToVerify(PETHREAD Thread
)
44 * FUNCTION: Returns a pointer to the device, representing a removable-media
45 * device, that is the target of the given thread's I/O request
51 VOID
IoFreeIrp(PIRP Irp
)
53 * FUNCTION: Releases a caller allocated irp
61 PIRP
IoMakeAssociatedIrp(PIRP Irp
, CCHAR StackSize
)
63 * FUNCTION: Allocates and initializes an irp to associated with a master irp
66 * StackSize = Number of stack locations to be allocated in the irp
67 * RETURNS: The irp allocated
72 AssocIrp
= IoAllocateIrp(StackSize
,FALSE
);
76 VOID
IoMarkIrpPending(PIRP Irp
)
78 * FUNCTION: Marks the specified irp, indicating further processing will
79 * be required by other driver routines
84 // DPRINT("IoGetCurrentIrpStackLocation(Irp) %x\n",
85 // IoGetCurrentIrpStackLocation(Irp));
86 IoGetCurrentIrpStackLocation(Irp
)->Control
|= SL_PENDING_RETURNED
;
89 USHORT
IoSizeOfIrp(CCHAR StackSize
)
91 * FUNCTION: Determines the size of an IRP
93 * StackSize = number of stack locations in the IRP
94 * RETURNS: The size of the IRP in bytes
97 return(sizeof(IRP
)+((StackSize
-1)*sizeof(IO_STACK_LOCATION
)));
100 VOID
IoInitializeIrp(PIRP Irp
, USHORT PacketSize
, CCHAR StackSize
)
102 * FUNCTION: Initalizes an irp allocated by the caller
104 * Irp = IRP to initalize
105 * PacketSize = Size in bytes of the IRP
106 * StackSize = Number of stack locations in the IRP
111 memset(Irp
, 0, PacketSize
);
112 Irp
->StackCount
= StackSize
;
113 Irp
->CurrentLocation
= StackSize
;
114 Irp
->Tail
.Overlay
.CurrentStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
117 PIO_STACK_LOCATION
IoGetCurrentIrpStackLocation(PIRP Irp
)
119 * FUNCTION: Gets a pointer to the callers location in the I/O stack in
122 * Irp = Points to the IRP
123 * RETURNS: A pointer to the stack location
126 // DPRINT("IoGetCurrentIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n",
128 // Irp->CurrentLocation,
131 return(&Irp
->Stack
[(ULONG
)Irp
->CurrentLocation
]);
134 VOID
IoSetNextIrpStackLocation(PIRP Irp
)
136 Irp
->CurrentLocation
--;
137 Irp
->Tail
.Overlay
.CurrentStackLocation
--;
140 PIO_STACK_LOCATION
IoGetNextIrpStackLocation(PIRP Irp
)
142 * FUNCTION: Gives a higher level driver access to the next lower driver's
145 * Irp = points to the irp
146 * RETURNS: A pointer to the stack location
149 // DPRINT("IoGetNextIrpStackLocation(Irp %x)\n",Irp);
152 // DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation);
153 return(&Irp
->Stack
[Irp
->CurrentLocation
-1]);
156 NTSTATUS
IoCallDriver(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
158 * FUNCTION: Sends an IRP to the next lower driver
162 PDRIVER_OBJECT DriverObject
;
163 PIO_STACK_LOCATION Param
;
165 // DPRINT("IoCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
167 DriverObject
= DeviceObject
->DriverObject
;
168 Param
= IoGetNextIrpStackLocation(Irp
);
170 Irp
->Tail
.Overlay
.CurrentStackLocation
--;
171 Irp
->CurrentLocation
--;
173 // DPRINT("MajorFunction %d\n", Param->MajorFunction);
174 // DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
175 // DriverObject->MajorFunction[Param->MajorFunction]);
176 Status
= DriverObject
->MajorFunction
[Param
->MajorFunction
](DeviceObject
,
181 PIRP
IoAllocateIrp(CCHAR StackSize
, BOOLEAN ChargeQuota
)
183 * FUNCTION: Allocates an IRP
185 * StackSize = the size of the stack required for the irp
186 * ChargeQuota = Charge allocation to current threads quota
187 * RETURNS: Irp allocated
193 DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
196 KeDumpStackFrames(0,8);
201 // Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
202 Irp
= ExAllocatePool(NonPagedPool
,IoSizeOfIrp(StackSize
));
206 Irp
= ExAllocatePool(NonPagedPool
,IoSizeOfIrp(StackSize
));
214 IoInitializeIrp(Irp
, IoSizeOfIrp(StackSize
), StackSize
);
216 // DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
221 VOID
IoSetCompletionRoutine(PIRP Irp
,
222 PIO_COMPLETION_ROUTINE CompletionRoutine
,
224 BOOLEAN InvokeOnSuccess
,
225 BOOLEAN InvokeOnError
,
226 BOOLEAN InvokeOnCancel
)
228 IO_STACK_LOCATION
* param
= IoGetNextIrpStackLocation(Irp
);
230 param
->CompletionRoutine
=CompletionRoutine
;
231 param
->CompletionContext
=Context
;
234 param
->Control
= param
->Control
| SL_INVOKE_ON_SUCCESS
;
238 param
->Control
= param
->Control
| SL_INVOKE_ON_ERROR
;
242 param
->Control
= param
->Control
| SL_INVOKE_ON_CANCEL
;
246 VOID
IopCompleteRequest(struct _KAPC
* Apc
,
247 PKNORMAL_ROUTINE
* NormalRoutine
,
248 PVOID
* NormalContext
,
249 PVOID
* SystemArgument1
,
250 PVOID
* SystemArgument2
)
252 DPRINT("IopCompleteRequest(Apc %x, SystemArgument1 %x, "
253 "(*SystemArgument1) %x\n", Apc
, SystemArgument1
,
255 IoSecondStageCompletion((PIRP
)(*SystemArgument1
),
256 (KPRIORITY
)(*SystemArgument2
));
259 VOID
IoCompleteRequest(PIRP Irp
, CCHAR PriorityBoost
)
261 * FUNCTION: Indicates the caller has finished all processing for a given
262 * I/O request and is returning the given IRP to the I/O manager
264 * Irp = Irp to be cancelled
265 * PriorityBoost = Increment by which to boost the priority of the
266 * thread making the request
273 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
274 Irp
,PriorityBoost
, Irp
->UserEvent
, PsGetCurrentThread());
276 for (i
=0;i
<Irp
->StackCount
;i
++)
278 if (Irp
->Stack
[i
].CompletionRoutine
!= NULL
)
280 Status
= Irp
->Stack
[i
].CompletionRoutine(
281 Irp
->Stack
[i
].DeviceObject
,
283 Irp
->Stack
[i
].CompletionContext
);
284 if (Status
== STATUS_MORE_PROCESSING_REQUIRED
)
289 if (Irp
->Stack
[i
].Control
& SL_PENDING_RETURNED
)
291 Irp
->PendingReturned
= TRUE
;
295 if (Irp
->PendingReturned
)
297 DPRINT("Dispatching APC\n");
298 Thread
= &Irp
->Tail
.Overlay
.Thread
->Tcb
;
299 KeInitializeApc(&Irp
->Tail
.Apc
,
305 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
,
308 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
);
309 KeInsertQueueApc(&Irp
->Tail
.Apc
,
311 (PVOID
)(ULONG
)PriorityBoost
,
313 DPRINT("Finished dispatching APC\n");
317 DPRINT("Calling completion routine directly\n");
318 IoSecondStageCompletion(Irp
,PriorityBoost
);
319 DPRINT("Finished completition routine\n");