ff02e89087ef98e84313c71ba2fb09ae9f3a7c7c
[reactos.git] / reactos / ntoskrnl / io / irp.c
1 /* $Id: irp.c,v 1.26 2000/03/06 01:02:30 ea Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/irp.c
6 * PURPOSE: Handle IRPs
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * 24/05/98: Created
10 */
11
12 /* NOTES *******************************************************************
13 *
14 * Layout of an IRP
15 *
16 * ################
17 * # Headers #
18 * ################
19 * # #
20 * # Variable #
21 * # length list #
22 * # of io stack #
23 * # locations #
24 * # #
25 * ################
26 *
27 *
28 *
29 */
30
31 /* INCLUDES ****************************************************************/
32
33 #include <ddk/ntddk.h>
34 #include <string.h>
35 #include <internal/string.h>
36 #include <internal/io.h>
37
38 #define NDEBUG
39 #include <internal/debug.h>
40
41 /* FUNCTIONS ****************************************************************/
42
43 PDEVICE_OBJECT
44 STDCALL
45 IoGetDeviceToVerify (PETHREAD Thread)
46 /*
47 * FUNCTION: Returns a pointer to the device, representing a removable-media
48 * device, that is the target of the given thread's I/O request
49 */
50 {
51 UNIMPLEMENTED;
52 }
53
54
55 VOID
56 STDCALL
57 IoFreeIrp (PIRP Irp)
58 /*
59 * FUNCTION: Releases a caller allocated irp
60 * ARGUMENTS:
61 * Irp = Irp to free
62 */
63 {
64 ExFreePool(Irp);
65 }
66
67
68 PIRP
69 STDCALL
70 IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
71 /*
72 * FUNCTION: Allocates and initializes an irp to associated with a master irp
73 * ARGUMENTS:
74 * Irp = Master irp
75 * StackSize = Number of stack locations to be allocated in the irp
76 * RETURNS: The irp allocated
77 */
78 {
79 PIRP AssocIrp;
80
81 AssocIrp = IoAllocateIrp(StackSize,FALSE);
82 UNIMPLEMENTED;
83 }
84
85
86 /**********************************************************************
87 * NAME INTERNAL
88 * IoMarkIrpPending
89 */
90 VOID
91 IoMarkIrpPending (PIRP Irp)
92 /*
93 * FUNCTION: Marks the specified irp, indicating further processing will
94 * be required by other driver routines
95 * ARGUMENTS:
96 * Irp = Irp to mark
97 */
98 {
99 // DPRINT("IoGetCurrentIrpStackLocation(Irp) %x\n",
100 // IoGetCurrentIrpStackLocation(Irp));
101 IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED;
102 }
103
104
105 /**********************************************************************
106 * NAME INTERNAL
107 * IoSizeOfIrp
108 */
109 USHORT
110 IoSizeOfIrp (CCHAR StackSize)
111 /*
112 * FUNCTION: Determines the size of an IRP
113 * ARGUMENTS:
114 * StackSize = number of stack locations in the IRP
115 * RETURNS: The size of the IRP in bytes
116 */
117 {
118 return(sizeof(IRP)+((StackSize-1)*sizeof(IO_STACK_LOCATION)));
119 }
120
121
122 VOID
123 STDCALL
124 IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
125 /*
126 * FUNCTION: Initalizes an irp allocated by the caller
127 * ARGUMENTS:
128 * Irp = IRP to initalize
129 * PacketSize = Size in bytes of the IRP
130 * StackSize = Number of stack locations in the IRP
131 */
132 {
133 assert(Irp != NULL);
134
135 memset(Irp, 0, PacketSize);
136 Irp->Size = PacketSize;
137 Irp->StackCount = StackSize;
138 Irp->CurrentLocation = StackSize;
139 Irp->Tail.Overlay.CurrentStackLocation = IoGetCurrentIrpStackLocation(Irp);
140 }
141
142
143 /**********************************************************************
144 * NAME INTERNAL
145 * IoGetCurrentIrpStackLocation
146 */
147 PIO_STACK_LOCATION
148 IoGetCurrentIrpStackLocation (PIRP Irp)
149 /*
150 * FUNCTION: Gets a pointer to the callers location in the I/O stack in
151 * the given IRP
152 * ARGUMENTS:
153 * Irp = Points to the IRP
154 * RETURNS: A pointer to the stack location
155 */
156 {
157 // DPRINT("IoGetCurrentIrpStackLocation: Irp %08lx CurLoc %d StkCnt %d\n",
158 // Irp,
159 // Irp->CurrentLocation,
160 // Irp->StackCount);
161
162 return(&Irp->Stack[(ULONG)Irp->CurrentLocation]);
163 }
164
165
166 /**********************************************************************
167 * NAME INTERNAL
168 * IoSetNextIrpStackLocation
169 */
170 VOID
171 IoSetNextIrpStackLocation (PIRP Irp)
172 {
173 Irp->CurrentLocation--;
174 Irp->Tail.Overlay.CurrentStackLocation--;
175 }
176
177
178 /**********************************************************************
179 * NAME INTERNAL
180 * IoGetNextIrpStackLocation
181 */
182 PIO_STACK_LOCATION
183 IoGetNextIrpStackLocation (PIRP Irp)
184 /*
185 * FUNCTION: Gives a higher level driver access to the next lower driver's
186 * I/O stack location
187 * ARGUMENTS:
188 * Irp = points to the irp
189 * RETURNS: A pointer to the stack location
190 */
191 {
192 // DPRINT("IoGetNextIrpStackLocation(Irp %x)\n",Irp);
193
194 assert(Irp!=NULL);
195 // DPRINT("Irp %x Irp->StackPtr %x\n",Irp,Irp->CurrentLocation);
196 return(&Irp->Stack[Irp->CurrentLocation-1]);
197 }
198
199
200 NTSTATUS
201 FASTCALL
202 IofCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
203 /*
204 * FUNCTION: Sends an IRP to the next lower driver
205 */
206 {
207 NTSTATUS Status;
208 PDRIVER_OBJECT DriverObject;
209 PIO_STACK_LOCATION Param;
210
211 // DPRINT("IoCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
212
213 DriverObject = DeviceObject->DriverObject;
214 Param = IoGetNextIrpStackLocation(Irp);
215
216 Irp->Tail.Overlay.CurrentStackLocation--;
217 Irp->CurrentLocation--;
218
219 // DPRINT("MajorFunction %d\n", Param->MajorFunction);
220 // DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
221 // DriverObject->MajorFunction[Param->MajorFunction]);
222 Status = DriverObject->MajorFunction[Param->MajorFunction](DeviceObject,
223 Irp);
224 return Status;
225 }
226
227
228 NTSTATUS
229 STDCALL
230 IoCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
231 {
232 return IofCallDriver (
233 DeviceObject,
234 Irp
235 );
236 }
237
238
239 PIRP
240 STDCALL
241 IoAllocateIrp (CCHAR StackSize, BOOLEAN ChargeQuota)
242 /*
243 * FUNCTION: Allocates an IRP
244 * ARGUMENTS:
245 * StackSize = the size of the stack required for the irp
246 * ChargeQuota = Charge allocation to current threads quota
247 * RETURNS: Irp allocated
248 */
249 {
250 PIRP Irp;
251
252 #if 0
253 DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
254 StackSize,
255 ChargeQuota);
256 KeDumpStackFrames(0,8);
257 #endif
258
259 if (ChargeQuota)
260 {
261 // Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
262 Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
263 }
264 else
265 {
266 Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
267 }
268
269 if (Irp==NULL)
270 {
271 return(NULL);
272 }
273
274 IoInitializeIrp(Irp, IoSizeOfIrp(StackSize), StackSize);
275
276 // DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
277
278 return Irp;
279 }
280
281
282 /**********************************************************************
283 * NAME INTERNAL
284 * IoSetCompletionRoutine
285 */
286 VOID
287 IoSetCompletionRoutine (PIRP Irp,
288 PIO_COMPLETION_ROUTINE CompletionRoutine,
289 PVOID Context,
290 BOOLEAN InvokeOnSuccess,
291 BOOLEAN InvokeOnError,
292 BOOLEAN InvokeOnCancel)
293 {
294 IO_STACK_LOCATION* param = IoGetNextIrpStackLocation(Irp);
295
296 param->CompletionRoutine=CompletionRoutine;
297 param->CompletionContext=Context;
298 if (InvokeOnSuccess)
299 {
300 param->Control = param->Control | SL_INVOKE_ON_SUCCESS;
301 }
302 if (InvokeOnError)
303 {
304 param->Control = param->Control | SL_INVOKE_ON_ERROR;
305 }
306 if (InvokeOnCancel)
307 {
308 param->Control = param->Control | SL_INVOKE_ON_CANCEL;
309 }
310 }
311
312 VOID IopCompleteRequest(struct _KAPC* Apc,
313 PKNORMAL_ROUTINE* NormalRoutine,
314 PVOID* NormalContext,
315 PVOID* SystemArgument1,
316 PVOID* SystemArgument2)
317 {
318 DPRINT("IopCompleteRequest(Apc %x, SystemArgument1 %x, "
319 "(*SystemArgument1) %x\n", Apc, SystemArgument1,
320 *SystemArgument1);
321 IoSecondStageCompletion((PIRP)(*SystemArgument1),
322 (KPRIORITY)(*SystemArgument2));
323 }
324
325
326 VOID
327 FASTCALL
328 IofCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
329 /*
330 * FUNCTION: Indicates the caller has finished all processing for a given
331 * I/O request and is returning the given IRP to the I/O manager
332 * ARGUMENTS:
333 * Irp = Irp to be cancelled
334 * PriorityBoost = Increment by which to boost the priority of the
335 * thread making the request
336 */
337 {
338 unsigned int i;
339 NTSTATUS Status;
340 PKTHREAD Thread;
341
342 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
343 Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
344
345 for (i=0;i<Irp->StackCount;i++)
346 {
347 if (Irp->Stack[i].CompletionRoutine != NULL)
348 {
349 Status = Irp->Stack[i].CompletionRoutine(
350 Irp->Stack[i].DeviceObject,
351 Irp,
352 Irp->Stack[i].CompletionContext);
353 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
354 {
355 return;
356 }
357 }
358 if (Irp->Stack[i].Control & SL_PENDING_RETURNED)
359 {
360 Irp->PendingReturned = TRUE;
361 }
362 }
363
364 if (Irp->PendingReturned)
365 {
366 DPRINT("Dispatching APC\n");
367 Thread = &Irp->Tail.Overlay.Thread->Tcb;
368 KeInitializeApc(&Irp->Tail.Apc,
369 Thread,
370 0,
371 IopCompleteRequest,
372 NULL,
373 (PKNORMAL_ROUTINE)
374 Irp->Overlay.AsynchronousParameters.UserApcRoutine,
375 UserMode,
376 (PVOID)
377 Irp->Overlay.AsynchronousParameters.UserApcContext);
378 KeInsertQueueApc(&Irp->Tail.Apc,
379 (PVOID)Irp,
380 (PVOID)(ULONG)PriorityBoost,
381 KernelMode);
382 DPRINT("Finished dispatching APC\n");
383 }
384 else
385 {
386 DPRINT("Calling completion routine directly\n");
387 IoSecondStageCompletion(Irp,PriorityBoost);
388 DPRINT("Finished completition routine\n");
389 }
390 }
391
392
393 VOID
394 STDCALL
395 IoCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
396 {
397 IofCompleteRequest (
398 Irp,
399 PriorityBoost
400 );
401 }
402
403
404 /**********************************************************************
405 * NAME EXPORTED
406 * IoIsOperationSynchronous@4
407 *
408 * DESCRIPTION
409 * Check if the I/O operation associated with the given IRP
410 * is synchronous.
411 *
412 * ARGUMENTS
413 * Irp Packet to check.
414 *
415 * RETURN VALUE
416 * TRUE if Irp's operation is synchronous; otherwise FALSE.
417 */
418 BOOLEAN
419 STDCALL
420 IoIsOperationSynchronous (
421 IN PIRP Irp
422 )
423 {
424 ULONG Flags = 0;
425 PFILE_OBJECT FileObject = NULL;
426
427 /*
428 * Check the associated FILE_OBJECT's
429 * flags first.
430 */
431 FileObject = Irp->Tail.Overlay.OriginalFileObject;
432 if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
433 {
434 /* Check IRP's flags. */
435 Flags = Irp->Flags;
436 if (!( (IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO)
437 & Flags
438 ))
439 {
440 return FALSE;
441 }
442 }
443 /*
444 * Check more IRP's flags.
445 */
446 Flags = Irp->Flags;
447 if ( !(IRP_MOUNT_COMPLETION & Flags)
448 || (IRP_SYNCHRONOUS_PAGING_IO & Flags)
449 )
450 {
451 return TRUE;
452 }
453 /*
454 * Otherwise, it is an
455 * asynchronous operation.
456 */
457 return FALSE;
458 }
459
460
461 /* EOF */