+SeDeassignSecurity()
[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   return NULL;
78 }
79
80 #endif /* LIBCAPTIVE */
81
82 VOID STDCALL
83 IoInitializeIrp(PIRP Irp,
84                 USHORT PacketSize,
85                 CCHAR StackSize)
86 /*
87  * FUNCTION: Initalizes an irp allocated by the caller
88  * ARGUMENTS:
89  *          Irp = IRP to initalize
90  *          PacketSize = Size in bytes of the IRP
91  *          StackSize = Number of stack locations in the IRP
92  */
93 {
94   assert(Irp != NULL);
95
96   memset(Irp, 0, PacketSize);
97   Irp->Type = IO_TYPE_IRP;
98   Irp->Size = PacketSize;
99   Irp->StackCount = StackSize;
100   Irp->CurrentLocation = StackSize;
101   Irp->Tail.Overlay.CurrentStackLocation = &Irp->Stack[(ULONG)StackSize];
102 }
103
104
105 NTSTATUS FASTCALL
106 IofCallDriver(PDEVICE_OBJECT DeviceObject,
107               PIRP Irp)
108 /*
109   * FUNCTION: Sends an IRP to the next lower driver
110  */
111 {
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   IoSetNextIrpStackLocation(Irp);
125   Param = IoGetCurrentIrpStackLocation(Irp);
126
127   DPRINT("IrpSp 0x%X\n", Param);
128   
129   Param->DeviceObject = DeviceObject;
130
131   DPRINT("MajorFunction %d\n", Param->MajorFunction);
132   DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
133     DriverObject->MajorFunction[Param->MajorFunction]);
134
135   if (!DriverObject->MajorFunction[Param->MajorFunction])
136     KeBugCheck(0);
137   return DriverObject->MajorFunction[Param->MajorFunction](DeviceObject, Irp);
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    ULONG             i;
230    NTSTATUS          Status;
231    PDEVICE_OBJECT    DeviceObject;
232
233    DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
234       Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
235
236    assert(Irp->CancelRoutine == NULL);
237    assert(Irp->IoStatus.Status != STATUS_PENDING);
238
239    if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
240    {
241       Irp->PendingReturned = TRUE;
242    }
243
244    for (i=Irp->CurrentLocation;i<(ULONG)Irp->StackCount;i++)
245    {
246       /*
247       Completion routines expect the current irp stack location to be the same as when
248       IoSetCompletionRoutine was called to set them. A side effect is that completion
249       routines set by highest level drivers without their own stack location will receive
250       an invalid current stack location (at least it should be considered as invalid).
251       Since the DeviceObject argument passed is taken from the current stack, this value
252       is also invalid (NULL).
253       */
254       if (Irp->CurrentLocation < Irp->StackCount - 1)
255       {
256          IoSetPreviousIrpStackLocation(Irp);
257          DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject;
258       }
259       else
260       {
261          DeviceObject = NULL;
262       }
263
264       if (Irp->Stack[i].CompletionRoutine != NULL &&
265          ((NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_SUCCESS)) ||
266          (!NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_ERROR)) ||
267          (Irp->Cancel && (Irp->Stack[i].Control & SL_INVOKE_ON_CANCEL))))
268       {
269          Status = Irp->Stack[i].CompletionRoutine(DeviceObject,
270                                                   Irp,
271                                                   Irp->Stack[i].CompletionContext);
272
273          if (Status == STATUS_MORE_PROCESSING_REQUIRED)
274          {
275             if (Irp->UserIosb)
276                {
277                   *Irp->UserIosb=Irp->IoStatus;
278                }
279             return;
280          }
281       }
282    
283       if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
284       {
285          Irp->PendingReturned = TRUE;
286       }
287    }
288
289    if (Irp->PendingReturned)
290      {
291 #ifdef LIBCAPTIVE
292         /* FIXME: Why the hell should we bother with some damned APCs?!?
293          * Call it directly below!
294          */
295         DPRINT("IofCompleteRequest() would like to dispatch APC: F*ck off!\n");
296 #else /* !LIBCAPTIVE */
297         DPRINT("Dispatching APC\n");
298         KeInitializeApc(&Irp->Tail.Apc,
299                         &Irp->Tail.Overlay.Thread->Tcb,
300                         0,
301                         IopCompleteRequest,
302                         NULL,
303                         (PKNORMAL_ROUTINE)
304                         NULL,
305                         KernelMode,
306                         NULL);
307         KeInsertQueueApc(&Irp->Tail.Apc,
308                          (PVOID)Irp,
309                          (PVOID)(ULONG)PriorityBoost,
310                          KernelMode);
311         DPRINT("Finished dispatching APC\n");
312 #endif /* !LIBCAPTIVE */
313      }
314 #ifndef LIBCAPTIVE
315    else
316 #endif /* LIBCAPTIVE */
317      {
318         DPRINT("Calling completion routine directly\n");
319         IoSecondStageCompletion(Irp,PriorityBoost);
320         DPRINT("Finished completition routine\n");
321      }
322 }
323
324
325 VOID STDCALL
326 IoCompleteRequest(PIRP Irp,
327                   CCHAR PriorityBoost)
328 {
329   IofCompleteRequest(Irp,
330                      PriorityBoost);
331 }
332
333
334 /**********************************************************************
335  * NAME                                                 EXPORTED
336  *      IoIsOperationSynchronous@4
337  *
338  * DESCRIPTION
339  *      Check if the I/O operation associated with the given IRP
340  *      is synchronous.
341  *
342  * ARGUMENTS
343  *      Irp     Packet to check.
344  *
345  * RETURN VALUE
346  *      TRUE if Irp's operation is synchronous; otherwise FALSE.
347  */
348 BOOLEAN STDCALL
349 IoIsOperationSynchronous(IN PIRP Irp)
350 {
351   PFILE_OBJECT FileObject = NULL;
352   ULONG Flags = 0;
353
354   /* Check the FILE_OBJECT's flags first. */
355   FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
356   if (FileObject == NULL)
357     KeBugCheck(0);
358   if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
359     {
360       /* Check IRP's flags. */
361       Flags = Irp->Flags;
362       if (!((IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO) & Flags))
363         {
364 #ifdef LIBCAPTIVE
365           /* libcaptive is fully single-thread/single-process synchronous model. */
366           return TRUE;
367 #endif /* LIBCAPTIVE */
368           return(FALSE);
369         }
370     }
371
372   /* Check more IRP's flags. */
373   Flags = Irp->Flags;
374   if (!(IRP_PAGING_IO & Flags)
375       || (IRP_SYNCHRONOUS_PAGING_IO & Flags))
376     {
377       return(TRUE);
378     }
379
380   /* Otherwise, it is an asynchronous operation. */
381 #ifdef LIBCAPTIVE
382   /* libcaptive is fully single-thread/single-process synchronous model. */
383   return TRUE;
384 #endif /* LIBCAPTIVE */
385   return(FALSE);
386 }
387
388 #ifndef LIBCAPTIVE
389
390 VOID STDCALL
391 IoEnqueueIrp(IN PIRP Irp)
392 {
393   UNIMPLEMENTED;
394 }
395
396 #endif /* LIBCAPTIVE */
397
398 VOID STDCALL
399 IoSetTopLevelIrp(IN PIRP Irp)
400 {
401   PETHREAD Thread;
402
403   Thread = PsGetCurrentThread();
404   Thread->TopLevelIrp->TopLevelIrp = Irp;
405 }
406
407
408 PIRP STDCALL
409 IoGetTopLevelIrp(VOID)
410 {
411   return(PsGetCurrentThread()->TopLevelIrp->TopLevelIrp);
412 }
413
414 #ifndef LIBCAPTIVE
415
416 VOID STDCALL
417 IoQueueThreadIrp(IN PIRP Irp)
418 {
419   UNIMPLEMENTED;
420 }
421
422 /*
423 NTSTATUS
424 STDCALL
425 IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
426 {
427   UNIMPLEMENTED;
428         return 0;
429 }
430
431 NTSTATUS
432 STDCALL
433 IoGetDeviceProperty(
434   IN PDEVICE_OBJECT DeviceObject,
435   IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
436   IN ULONG BufferLength,
437   OUT PVOID PropertyBuffer,
438   OUT PULONG ResultLength)
439 {
440   UNIMPLEMENTED;
441         return 0;
442 }
443
444 NTSTATUS
445 STDCALL
446 IoOpenDeviceRegistryKey(
447   IN PDEVICE_OBJECT DeviceObject,
448   IN ULONG DevInstKeyType,
449   IN ACCESS_MASK DesiredAccess,
450   OUT PHANDLE DevInstRegKey)
451 {
452   UNIMPLEMENTED;
453         return 0;
454 }
455  */
456
457 #endif /* LIBCAPTIVE */
458
459 /* EOF */