5ae6a725ffaf90bb8cadf5f501a0cc0ec2010b18
[reactos.git] / reactos / ntoskrnl / io / irp.c
1 /* $Id: irp.c,v 1.36 2001/04/09 02:45:04 dwelch 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 = IoGetCurrentIrpStackLocation(Irp);
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("IoCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
108
109 DriverObject = DeviceObject->DriverObject;
110 Param = IoGetNextIrpStackLocation(Irp);
111
112 Irp->Tail.Overlay.CurrentStackLocation--;
113 Irp->CurrentLocation--;
114
115 // DPRINT("MajorFunction %d\n", Param->MajorFunction);
116 // DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
117 // DriverObject->MajorFunction[Param->MajorFunction]);
118 Status = DriverObject->MajorFunction[Param->MajorFunction](DeviceObject,
119 Irp);
120 return Status;
121 }
122
123
124 NTSTATUS
125 STDCALL
126 IoCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
127 {
128 return IofCallDriver (
129 DeviceObject,
130 Irp
131 );
132 }
133
134
135 PIRP
136 STDCALL
137 IoAllocateIrp (CCHAR StackSize, BOOLEAN ChargeQuota)
138 /*
139 * FUNCTION: Allocates an IRP
140 * ARGUMENTS:
141 * StackSize = the size of the stack required for the irp
142 * ChargeQuota = Charge allocation to current threads quota
143 * RETURNS: Irp allocated
144 */
145 {
146 PIRP Irp;
147
148 #if 0
149 DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
150 StackSize,
151 ChargeQuota);
152 KeDumpStackFrames(0,8);
153 #endif
154
155 if (ChargeQuota)
156 {
157 // Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
158 Irp = ExAllocatePoolWithTag(NonPagedPool, IoSizeOfIrp(StackSize),
159 TAG_IRP);
160 }
161 else
162 {
163 Irp = ExAllocatePoolWithTag(NonPagedPool,IoSizeOfIrp(StackSize),
164 TAG_IRP);
165 }
166
167 if (Irp==NULL)
168 {
169 return(NULL);
170 }
171
172 IoInitializeIrp(Irp, IoSizeOfIrp(StackSize), StackSize);
173
174 // DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
175
176 return Irp;
177 }
178
179
180 VOID IopCompleteRequest(struct _KAPC* Apc,
181 PKNORMAL_ROUTINE* NormalRoutine,
182 PVOID* NormalContext,
183 PVOID* SystemArgument1,
184 PVOID* SystemArgument2)
185 {
186 DPRINT("IopCompleteRequest(Apc %x, SystemArgument1 %x, "
187 "(*SystemArgument1) %x\n", Apc, SystemArgument1,
188 *SystemArgument1);
189 IoSecondStageCompletion((PIRP)(*SystemArgument1),
190 (KPRIORITY)(*SystemArgument2));
191 }
192
193
194 VOID
195 FASTCALL
196 IofCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
197 /*
198 * FUNCTION: Indicates the caller has finished all processing for a given
199 * I/O request and is returning the given IRP to the I/O manager
200 * ARGUMENTS:
201 * Irp = Irp to be cancelled
202 * PriorityBoost = Increment by which to boost the priority of the
203 * thread making the request
204 */
205 {
206 unsigned int i;
207 NTSTATUS Status;
208
209 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
210 Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
211
212 for (i=0;i<Irp->StackCount;i++)
213 {
214 if (Irp->Stack[i].CompletionRoutine != NULL)
215 {
216 Status = Irp->Stack[i].CompletionRoutine(
217 Irp->Stack[i].DeviceObject,
218 Irp,
219 Irp->Stack[i].CompletionContext);
220 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
221 {
222 return;
223 }
224 }
225 if (Irp->Stack[i].Control & SL_PENDING_RETURNED)
226 {
227 Irp->PendingReturned = TRUE;
228 }
229 }
230 if (Irp->PendingReturned)
231 {
232 DPRINT("Dispatching APC\n");
233 KeInitializeApc(&Irp->Tail.Apc,
234 &Irp->Tail.Overlay.Thread->Tcb,
235 0,
236 IopCompleteRequest,
237 NULL,
238 (PKNORMAL_ROUTINE)
239 NULL,
240 KernelMode,
241 NULL);
242 KeInsertQueueApc(&Irp->Tail.Apc,
243 (PVOID)Irp,
244 (PVOID)(ULONG)PriorityBoost,
245 KernelMode);
246 DPRINT("Finished dispatching APC\n");
247 }
248 else
249 {
250 DPRINT("Calling completion routine directly\n");
251 IoSecondStageCompletion(Irp,PriorityBoost);
252 DPRINT("Finished completition routine\n");
253 }
254 }
255
256
257 VOID
258 STDCALL
259 IoCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
260 {
261 IofCompleteRequest (
262 Irp,
263 PriorityBoost
264 );
265 }
266
267
268 /**********************************************************************
269 * NAME EXPORTED
270 * IoIsOperationSynchronous@4
271 *
272 * DESCRIPTION
273 * Check if the I/O operation associated with the given IRP
274 * is synchronous.
275 *
276 * ARGUMENTS
277 * Irp Packet to check.
278 *
279 * RETURN VALUE
280 * TRUE if Irp's operation is synchronous; otherwise FALSE.
281 */
282 BOOLEAN
283 STDCALL
284 IoIsOperationSynchronous (
285 IN PIRP Irp
286 )
287 {
288 ULONG Flags = 0;
289 PFILE_OBJECT FileObject = NULL;
290
291 /*
292 * Check the associated FILE_OBJECT's
293 * flags first.
294 */
295 FileObject = Irp->Tail.Overlay.OriginalFileObject;
296 if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
297 {
298 /* Check IRP's flags. */
299 Flags = Irp->Flags;
300 if (!( (IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO)
301 & Flags
302 ))
303 {
304 return FALSE;
305 }
306 }
307 /*
308 * Check more IRP's flags.
309 */
310 Flags = Irp->Flags;
311 if ( !(IRP_MOUNT_COMPLETION & Flags)
312 || (IRP_SYNCHRONOUS_PAGING_IO & Flags)
313 )
314 {
315 return TRUE;
316 }
317 /*
318 * Otherwise, it is an
319 * asynchronous operation.
320 */
321 return FALSE;
322 }
323
324
325 VOID
326 STDCALL
327 IoEnqueueIrp (
328 PIRP Irp
329 )
330 {
331 UNIMPLEMENTED;
332 }
333
334
335 VOID
336 STDCALL
337 IoSetTopLevelIrp (
338 IN PIRP Irp
339 )
340 {
341 PETHREAD Thread;
342
343 Thread = PsGetCurrentThread ();
344 Thread->TopLevelIrp->TopLevelIrp = Irp;
345 }
346
347
348 PIRP
349 STDCALL
350 IoGetTopLevelIrp (
351 VOID
352 )
353 {
354 return (PsGetCurrentThread ()->TopLevelIrp->TopLevelIrp);
355 }
356
357
358 VOID
359 STDCALL
360 IoQueueThreadIrp (
361 PVOID Unknown0
362 )
363 {
364 UNIMPLEMENTED;
365 }
366
367 /* EOF */