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