87c088751fe83e6c44b9dfb6046b4aa76991feab
[reactos.git] / reactos / ntoskrnl / io / irp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/irp.c
5 * PURPOSE: Handle IRPs
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * 24/05/98: Created
9 */
10
11 /* NOTES *******************************************************************
12 *
13 * Layout of an IRP
14 *
15 * ################
16 * # Headers #
17 * ################
18 * # #
19 * # Variable #
20 * # length list #
21 * # of io stack #
22 * # locations #
23 * # #
24 * ################
25 *
26 *
27 *
28 */
29
30 /* INCLUDES ****************************************************************/
31
32 #include <ddk/ntddk.h>
33 #include <string.h>
34 #include <internal/string.h>
35 #include <internal/io.h>
36
37 #define NDEBUG
38 #include <internal/debug.h>
39
40 /* FUNCTIONS ****************************************************************/
41
42 PDEVICE_OBJECT IoGetDeviceToVerify(PETHREAD Thread)
43 /*
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
46 */
47 {
48 UNIMPLEMENTED;
49 }
50
51 VOID IoFreeIrp(PIRP Irp)
52 /*
53 * FUNCTION: Releases a caller allocated irp
54 * ARGUMENTS:
55 * Irp = Irp to free
56 */
57 {
58 ExFreePool(Irp);
59 }
60
61 PIRP IoMakeAssociatedIrp(PIRP Irp, CCHAR StackSize)
62 /*
63 * FUNCTION: Allocates and initializes an irp to associated with a master irp
64 * ARGUMENTS:
65 * Irp = Master irp
66 * StackSize = Number of stack locations to be allocated in the irp
67 * RETURNS: The irp allocated
68 */
69 {
70 PIRP AssocIrp;
71
72 AssocIrp = IoAllocateIrp(StackSize,FALSE);
73 UNIMPLEMENTED;
74 }
75
76 VOID IoMarkIrpPending(PIRP Irp)
77 /*
78 * FUNCTION: Marks the specified irp, indicating further processing will
79 * be required by other driver routines
80 * ARGUMENTS:
81 * Irp = Irp to mark
82 */
83 {
84 // DPRINT("IoGetCurrentIrpStackLocation(Irp) %x\n",
85 // IoGetCurrentIrpStackLocation(Irp));
86 IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED;
87 }
88
89 USHORT IoSizeOfIrp(CCHAR StackSize)
90 /*
91 * FUNCTION: Determines the size of an IRP
92 * ARGUMENTS:
93 * StackSize = number of stack locations in the IRP
94 * RETURNS: The size of the IRP in bytes
95 */
96 {
97 return(sizeof(IRP)+((StackSize-1)*sizeof(IO_STACK_LOCATION)));
98 }
99
100 VOID IoInitializeIrp(PIRP Irp, USHORT PacketSize, CCHAR StackSize)
101 /*
102 * FUNCTION: Initalizes an irp allocated by the caller
103 * ARGUMENTS:
104 * Irp = IRP to initalize
105 * PacketSize = Size in bytes of the IRP
106 * StackSize = Number of stack locations in the IRP
107 */
108 {
109 assert(Irp != NULL);
110
111 memset(Irp, 0, PacketSize);
112 Irp->StackCount = StackSize;
113 Irp->CurrentLocation = StackSize;
114 Irp->Tail.Overlay.CurrentStackLocation = IoGetCurrentIrpStackLocation(Irp);
115 }
116
117 PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
118 /*
119 * FUNCTION: Gets a pointer to the callers location in the I/O stack in
120 * the given IRP
121 * ARGUMENTS:
122 * Irp = Points to the IRP
123 * RETURNS: A pointer to the stack location
124 */
125 {
126 // DPRINT("IoGetCurrentIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n",
127 // Irp,
128 // Irp->CurrentLocation,
129 // Irp->StackCount);
130
131 return(&Irp->Stack[(ULONG)Irp->CurrentLocation]);
132 }
133
134 VOID IoSetNextIrpStackLocation(PIRP Irp)
135 {
136 Irp->CurrentLocation--;
137 Irp->Tail.Overlay.CurrentStackLocation--;
138 }
139
140 PIO_STACK_LOCATION IoGetNextIrpStackLocation(PIRP Irp)
141 /*
142 * FUNCTION: Gives a higher level driver access to the next lower driver's
143 * I/O stack location
144 * ARGUMENTS:
145 * Irp = points to the irp
146 * RETURNS: A pointer to the stack location
147 */
148 {
149 // DPRINT("IoGetNextIrpStackLocation(Irp %x)\n",Irp);
150
151 assert(Irp!=NULL);
152 // DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation);
153 return(&Irp->Stack[Irp->CurrentLocation-1]);
154 }
155
156 NTSTATUS IoCallDriver(PDEVICE_OBJECT DeviceObject, PIRP Irp)
157 /*
158 * FUNCTION: Sends an IRP to the next lower driver
159 */
160 {
161 NTSTATUS Status;
162 PDRIVER_OBJECT DriverObject;
163 PIO_STACK_LOCATION Param;
164
165 // DPRINT("IoCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
166
167 DriverObject = DeviceObject->DriverObject;
168 Param = IoGetNextIrpStackLocation(Irp);
169
170 Irp->Tail.Overlay.CurrentStackLocation--;
171 Irp->CurrentLocation--;
172
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,
177 Irp);
178 return Status;
179 }
180
181 PIRP IoAllocateIrp(CCHAR StackSize, BOOLEAN ChargeQuota)
182 /*
183 * FUNCTION: Allocates an IRP
184 * ARGUMENTS:
185 * StackSize = the size of the stack required for the irp
186 * ChargeQuota = Charge allocation to current threads quota
187 * RETURNS: Irp allocated
188 */
189 {
190 PIRP Irp;
191
192 #if 0
193 DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
194 StackSize,
195 ChargeQuota);
196 KeDumpStackFrames(0,8);
197 #endif
198
199 if (ChargeQuota)
200 {
201 // Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
202 Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
203 }
204 else
205 {
206 Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
207 }
208
209 if (Irp==NULL)
210 {
211 return(NULL);
212 }
213
214 IoInitializeIrp(Irp, IoSizeOfIrp(StackSize), StackSize);
215
216 // DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
217
218 return Irp;
219 }
220
221 VOID IoSetCompletionRoutine(PIRP Irp,
222 PIO_COMPLETION_ROUTINE CompletionRoutine,
223 PVOID Context,
224 BOOLEAN InvokeOnSuccess,
225 BOOLEAN InvokeOnError,
226 BOOLEAN InvokeOnCancel)
227 {
228 IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(Irp);
229
230 param->CompletionRoutine=CompletionRoutine;
231 param->CompletionContext=Context;
232 if (InvokeOnSuccess)
233 {
234 param->Control = param->Control | SL_INVOKE_ON_SUCCESS;
235 }
236 if (InvokeOnError)
237 {
238 param->Control = param->Control | SL_INVOKE_ON_ERROR;
239 }
240 if (InvokeOnCancel)
241 {
242 param->Control = param->Control | SL_INVOKE_ON_CANCEL;
243 }
244 }
245
246 VOID IopCompleteRequest(struct _KAPC* Apc,
247 PKNORMAL_ROUTINE* NormalRoutine,
248 PVOID* NormalContext,
249 PVOID* SystemArgument1,
250 PVOID* SystemArgument2)
251 {
252 DPRINT("IopCompleteRequest(Apc %x, SystemArgument1 %x, "
253 "(*SystemArgument1) %x\n", Apc, SystemArgument1,
254 *SystemArgument1);
255 IoSecondStageCompletion((PIRP)(*SystemArgument1),
256 (KPRIORITY)(*SystemArgument2));
257 }
258
259 VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost)
260 /*
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
263 * ARGUMENTS:
264 * Irp = Irp to be cancelled
265 * PriorityBoost = Increment by which to boost the priority of the
266 * thread making the request
267 */
268 {
269 unsigned int i;
270 NTSTATUS Status;
271 PKTHREAD Thread;
272
273 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
274 Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
275
276 for (i=0;i<Irp->StackCount;i++)
277 {
278 if (Irp->Stack[i].CompletionRoutine != NULL)
279 {
280 Status = Irp->Stack[i].CompletionRoutine(
281 Irp->Stack[i].DeviceObject,
282 Irp,
283 Irp->Stack[i].CompletionContext);
284 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
285 {
286 return;
287 }
288 }
289 if (Irp->Stack[i].Control & SL_PENDING_RETURNED)
290 {
291 Irp->PendingReturned = TRUE;
292 }
293 }
294
295 if (Irp->PendingReturned)
296 {
297 DPRINT("Dispatching APC\n");
298 Thread = &Irp->Tail.Overlay.Thread->Tcb;
299 KeInitializeApc(&Irp->Tail.Apc,
300 Thread,
301 0,
302 IopCompleteRequest,
303 NULL,
304 (PKNORMAL_ROUTINE)
305 Irp->Overlay.AsynchronousParameters.UserApcRoutine,
306 UserMode,
307 (PVOID)
308 Irp->Overlay.AsynchronousParameters.UserApcContext);
309 KeInsertQueueApc(&Irp->Tail.Apc,
310 (PVOID)Irp,
311 (PVOID)(ULONG)PriorityBoost,
312 KernelMode);
313 DPRINT("Finished dispatching APC\n");
314 }
315 else
316 {
317 DPRINT("Calling completion routine directly\n");
318 IoSecondStageCompletion(Irp,PriorityBoost);
319 DPRINT("Finished completition routine\n");
320 }
321 }
322