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