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