7230ffce44cda655a32540f91d901c2c43666123
[reactos.git] / reactos / ntoskrnl / io / irp.c
1 /* $Id: irp.c,v 1.39 2002/01/21 22:30:26 hbirr 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 <internal/io.h>
35 #include <internal/ps.h>
36 #include <internal/pool.h>
37
38 #define NDEBUG
39 #include <internal/debug.h>
40
41 /* GLOBALS *******************************************************************/
42
43 #define TAG_IRP TAG('I', 'R', 'P', ' ')
44
45 /* FUNCTIONS ****************************************************************/
46
47
48 VOID STDCALL
49 IoFreeIrp (PIRP Irp)
50 /*
51 * FUNCTION: Releases a caller allocated irp
52 * ARGUMENTS:
53 * Irp = Irp to free
54 */
55 {
56 ExFreePool(Irp);
57 }
58
59
60 PIRP STDCALL
61 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
77 VOID STDCALL
78 IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
79 /*
80 * FUNCTION: Initalizes an irp allocated by the caller
81 * ARGUMENTS:
82 * Irp = IRP to initalize
83 * PacketSize = Size in bytes of the IRP
84 * StackSize = Number of stack locations in the IRP
85 */
86 {
87 assert(Irp != NULL);
88
89 memset(Irp, 0, PacketSize);
90 Irp->Size = PacketSize;
91 Irp->StackCount = StackSize;
92 Irp->CurrentLocation = StackSize;
93 Irp->Tail.Overlay.CurrentStackLocation = &Irp->Stack[(ULONG)StackSize];
94 }
95
96
97 NTSTATUS FASTCALL
98 IofCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
99 /*
100 * FUNCTION: Sends an IRP to the next lower driver
101 */
102 {
103 NTSTATUS Status;
104 PDRIVER_OBJECT DriverObject;
105 PIO_STACK_LOCATION Param;
106
107 DPRINT("IofCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
108
109 assert(Irp);
110 assert(DeviceObject);
111
112 DriverObject = DeviceObject->DriverObject;
113
114 assert(DriverObject);
115
116 Param = IoGetNextIrpStackLocation(Irp);
117
118 DPRINT("IrpSp 0x%X\n", Param);
119
120 Irp->Tail.Overlay.CurrentStackLocation--;
121 Irp->CurrentLocation--;
122
123 DPRINT("MajorFunction %d\n", Param->MajorFunction);
124 DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
125 DriverObject->MajorFunction[Param->MajorFunction]);
126 Status = DriverObject->MajorFunction[Param->MajorFunction](DeviceObject,
127 Irp);
128 return Status;
129 }
130
131
132 NTSTATUS
133 STDCALL
134 IoCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
135 {
136 return IofCallDriver (
137 DeviceObject,
138 Irp
139 );
140 }
141
142
143 PIRP
144 STDCALL
145 IoAllocateIrp (CCHAR StackSize, BOOLEAN ChargeQuota)
146 /*
147 * FUNCTION: Allocates an IRP
148 * ARGUMENTS:
149 * StackSize = the size of the stack required for the irp
150 * ChargeQuota = Charge allocation to current threads quota
151 * RETURNS: Irp allocated
152 */
153 {
154 PIRP Irp;
155
156 #if 0
157 DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
158 StackSize,
159 ChargeQuota);
160 KeDumpStackFrames(0,8);
161 #endif
162
163 if (ChargeQuota)
164 {
165 // Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
166 Irp = ExAllocatePoolWithTag(NonPagedPool, IoSizeOfIrp(StackSize),
167 TAG_IRP);
168 }
169 else
170 {
171 Irp = ExAllocatePoolWithTag(NonPagedPool,IoSizeOfIrp(StackSize),
172 TAG_IRP);
173 }
174
175 if (Irp==NULL)
176 {
177 return(NULL);
178 }
179
180 IoInitializeIrp(Irp, IoSizeOfIrp(StackSize), StackSize);
181
182 // DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
183
184 return Irp;
185 }
186
187
188 VOID STDCALL
189 IopCompleteRequest(struct _KAPC* Apc,
190 PKNORMAL_ROUTINE* NormalRoutine,
191 PVOID* NormalContext,
192 PVOID* SystemArgument1,
193 PVOID* SystemArgument2)
194 {
195 DPRINT("IopCompleteRequest(Apc %x, SystemArgument1 %x, "
196 "(*SystemArgument1) %x\n", Apc, SystemArgument1,
197 *SystemArgument1);
198 IoSecondStageCompletion((PIRP)(*SystemArgument1),
199 (KPRIORITY)(*SystemArgument2));
200 }
201
202
203 VOID FASTCALL
204 IofCompleteRequest(PIRP Irp,
205 CCHAR PriorityBoost)
206 /*
207 * FUNCTION: Indicates the caller has finished all processing for a given
208 * I/O request and is returning the given IRP to the I/O manager
209 * ARGUMENTS:
210 * Irp = Irp to be cancelled
211 * PriorityBoost = Increment by which to boost the priority of the
212 * thread making the request
213 */
214 {
215 unsigned int i;
216 NTSTATUS Status;
217
218 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
219 Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
220
221 for (i=0;i<Irp->StackCount;i++)
222 {
223 if (Irp->Stack[i].CompletionRoutine != NULL)
224 {
225 Status = Irp->Stack[i].CompletionRoutine(
226 Irp->Stack[i].DeviceObject,
227 Irp,
228 Irp->Stack[i].CompletionContext);
229 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
230 {
231 return;
232 }
233 }
234 if (Irp->Stack[i].Control & SL_PENDING_RETURNED)
235 {
236 Irp->PendingReturned = TRUE;
237 }
238 }
239 if (Irp->PendingReturned)
240 {
241 DPRINT("Dispatching APC\n");
242 KeInitializeApc(&Irp->Tail.Apc,
243 &Irp->Tail.Overlay.Thread->Tcb,
244 0,
245 IopCompleteRequest,
246 NULL,
247 (PKNORMAL_ROUTINE)
248 NULL,
249 KernelMode,
250 NULL);
251 KeInsertQueueApc(&Irp->Tail.Apc,
252 (PVOID)Irp,
253 (PVOID)(ULONG)PriorityBoost,
254 KernelMode);
255 DPRINT("Finished dispatching APC\n");
256 }
257 else
258 {
259 DPRINT("Calling completion routine directly\n");
260 IoSecondStageCompletion(Irp,PriorityBoost);
261 DPRINT("Finished completition routine\n");
262 }
263 }
264
265
266 VOID
267 STDCALL
268 IoCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
269 {
270 IofCompleteRequest (
271 Irp,
272 PriorityBoost
273 );
274 }
275
276
277 /**********************************************************************
278 * NAME EXPORTED
279 * IoIsOperationSynchronous@4
280 *
281 * DESCRIPTION
282 * Check if the I/O operation associated with the given IRP
283 * is synchronous.
284 *
285 * ARGUMENTS
286 * Irp Packet to check.
287 *
288 * RETURN VALUE
289 * TRUE if Irp's operation is synchronous; otherwise FALSE.
290 */
291 BOOLEAN
292 STDCALL
293 IoIsOperationSynchronous (
294 IN PIRP Irp
295 )
296 {
297 ULONG Flags = 0;
298 PFILE_OBJECT FileObject = NULL;
299
300 /*
301 * Check the associated FILE_OBJECT's
302 * flags first.
303 */
304 FileObject = Irp->Tail.Overlay.OriginalFileObject;
305 if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
306 {
307 /* Check IRP's flags. */
308 Flags = Irp->Flags;
309 if (!( (IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO)
310 & Flags
311 ))
312 {
313 return FALSE;
314 }
315 }
316 /*
317 * Check more IRP's flags.
318 */
319 Flags = Irp->Flags;
320 if ( !(IRP_MOUNT_COMPLETION & Flags)
321 || (IRP_SYNCHRONOUS_PAGING_IO & Flags)
322 )
323 {
324 return TRUE;
325 }
326 /*
327 * Otherwise, it is an
328 * asynchronous operation.
329 */
330 return FALSE;
331 }
332
333
334 VOID
335 STDCALL
336 IoEnqueueIrp (
337 PIRP Irp
338 )
339 {
340 UNIMPLEMENTED;
341 }
342
343
344 VOID
345 STDCALL
346 IoSetTopLevelIrp (
347 IN PIRP Irp
348 )
349 {
350 PETHREAD Thread;
351
352 Thread = PsGetCurrentThread ();
353 Thread->TopLevelIrp->TopLevelIrp = Irp;
354 }
355
356
357 PIRP
358 STDCALL
359 IoGetTopLevelIrp (
360 VOID
361 )
362 {
363 return (PsGetCurrentThread ()->TopLevelIrp->TopLevelIrp);
364 }
365
366
367 VOID
368 STDCALL
369 IoQueueThreadIrp (
370 PVOID Unknown0
371 )
372 {
373 UNIMPLEMENTED;
374 }
375
376 /* EOF */