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