IofCallDriver(): Non-handled 'IRP_MJ_FLUSH_BUFFERS' is silently ignored.
[reactos.git] / ntoskrnl / io / cleanup.c
1 /*
2  * COPYRIGHT:      See COPYING in the top level directory
3  * PROJECT:        ReactOS kernel
4  * FILE:           ntoskrnl/io/cleanup.c
5  * PURPOSE:        IRP cleanup
6  * PROGRAMMER:     David Welch (welch@mcmail.com)
7  * UPDATE HISTORY:
8  *                 30/05/98: Created
9  */
10
11 /* INCLUDES ****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <internal/io.h>
15 #include <internal/ob.h>
16 #include <internal/mm.h>
17 #include <internal/ps.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 /* FUNCTIONS ***************************************************************/
23
24 VOID STDCALL
25 IopCompleteRequest1(struct _KAPC* Apc,
26                     PKNORMAL_ROUTINE* NormalRoutine,
27                     PVOID* NormalContext,
28                     PVOID* SystemArgument1,
29                     PVOID* SystemArgument2)
30 {
31    PIRP Irp;
32    CCHAR PriorityBoost;
33    PIO_STACK_LOCATION IoStack;
34    PFILE_OBJECT FileObject;
35    
36    DPRINT("IopCompleteRequest1()\n");
37    
38    Irp = (PIRP)(*SystemArgument1);
39    PriorityBoost = (CCHAR)(LONG)(*SystemArgument2);
40    
41    IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
42    FileObject = IoStack->FileObject;
43    
44    (*SystemArgument1) = (PVOID)Irp->UserIosb;
45    (*SystemArgument2) = (PVOID)Irp->IoStatus.Information;
46    
47    if (Irp->UserIosb!=NULL)
48      {
49         *Irp->UserIosb=Irp->IoStatus;
50      }
51
52    if (Irp->UserEvent)
53    {
54       KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
55    }
56
57    if (!(Irp->Flags & IRP_PAGING_IO) && FileObject)
58    {
59       // if the event is not the one in the file object, it needs dereferenced
60       if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event)
61          ObDereferenceObject(Irp->UserEvent);
62
63       if (IoStack->MajorFunction != IRP_MJ_CLOSE)
64       {
65          ObDereferenceObject(FileObject);
66       }
67    }
68    
69    IoFreeIrp(Irp);
70
71 }
72
73 VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
74                                PIRP Irp,
75                                PIO_STACK_LOCATION IoStack)
76 {
77    ULONG IoControlCode;
78    
79    IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
80    
81    switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
82      {
83       case METHOD_BUFFERED:
84         DPRINT ("Using METHOD_BUFFERED!\n");
85         
86         /* copy output buffer back and free it */
87         if (Irp->AssociatedIrp.SystemBuffer)
88           {
89              if (IoStack->Parameters.DeviceIoControl.OutputBufferLength)
90                {
91                   RtlCopyMemory(Irp->UserBuffer,
92                                 Irp->AssociatedIrp.SystemBuffer,
93                                 IoStack->Parameters.DeviceIoControl.
94                                 OutputBufferLength);
95                }
96              ExFreePool (Irp->AssociatedIrp.SystemBuffer);
97           }
98         break;
99         
100       case METHOD_IN_DIRECT:
101         DPRINT ("Using METHOD_IN_DIRECT!\n");
102
103         /* copy output buffer back and free it */
104         if (Irp->AssociatedIrp.SystemBuffer)
105           {
106              if (IoStack->Parameters.DeviceIoControl.OutputBufferLength)
107                {
108                   RtlCopyMemory(Irp->UserBuffer,
109                                 Irp->AssociatedIrp.SystemBuffer,
110                                 IoStack->Parameters.DeviceIoControl.
111                                 OutputBufferLength);
112                }
113             ExFreePool (Irp->AssociatedIrp.SystemBuffer);
114           }
115         
116         /* free input buffer (data transfer buffer) */
117         if (Irp->MdlAddress)
118           IoFreeMdl (Irp->MdlAddress);
119         break;
120         
121       case METHOD_OUT_DIRECT:
122         DPRINT ("Using METHOD_OUT_DIRECT!\n");
123         
124         /* free input buffer (control buffer) */
125         if (Irp->AssociatedIrp.SystemBuffer)
126           ExFreePool (Irp->AssociatedIrp.SystemBuffer);
127         
128         /* free output buffer (data transfer buffer) */
129         if (Irp->MdlAddress)
130           IoFreeMdl (Irp->MdlAddress);
131         break;
132         
133       case METHOD_NEITHER:
134         DPRINT ("Using METHOD_NEITHER!\n");
135         /* nothing to do */
136         break;
137      }
138 }
139
140 VOID IoReadWriteCompletion(PDEVICE_OBJECT DeviceObject,
141                            PIRP Irp,
142                            PIO_STACK_LOCATION IoStack)
143 {   
144    PFILE_OBJECT FileObject;
145    
146    FileObject = IoStack->FileObject;
147    
148    if (DeviceObject->Flags & DO_BUFFERED_IO)     
149      {
150         if (IoStack->MajorFunction == IRP_MJ_READ)
151           {
152              DPRINT("Copying buffered io back to user\n");
153              memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer,
154                     IoStack->Parameters.Read.Length);
155           }
156         ExFreePool(Irp->AssociatedIrp.SystemBuffer);
157      }
158    if (DeviceObject->Flags & DO_DIRECT_IO)
159      {
160         /* FIXME: Is the MDL destroyed on a paging i/o, check all cases. */
161         DPRINT("Tearing down MDL\n");
162         if (Irp->MdlAddress->MappedSystemVa != NULL)
163           {          
164              MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa,
165                                 Irp->MdlAddress);
166           }
167         MmUnlockPages(Irp->MdlAddress);
168         ExFreePool(Irp->MdlAddress);
169      }
170 }
171
172 VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject,
173                                    PIRP Irp,
174                                    PIO_STACK_LOCATION IoStack)
175 {
176 }
177
178 VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
179 /*
180  * FUNCTION: Performs the second stage of irp completion for read/write irps
181  * ARGUMENTS:
182  *          Irp = Irp to completion
183  *          FromDevice = True if the operation transfered data from the device
184  */
185 {
186    PIO_STACK_LOCATION IoStack;
187    PDEVICE_OBJECT DeviceObject;
188    PFILE_OBJECT FileObject;
189    
190    DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n",
191           Irp, PriorityBoost);
192    
193    /* FIXME: Should we set 'Irp->UserIosb' only on MasterIrp finalization
194     * or we should set it for each subrequest?
195     */
196    if (Irp->UserIosb)
197       {
198          *Irp->UserIosb=Irp->IoStatus;
199       }
200    
201    /* Handling only subrequest of AssociatedIrp group from MasterIrp?
202     * Is it the last subrequest?
203     * FIXME: It appears to me as if 'Irp->AssociatedIrp.IrpCount' is +1 than expected. :-?
204     */
205    if (Irp->Flags & IRP_ASSOCIATED_IRP)
206       {
207          Irp=Irp->AssociatedIrp.MasterIrp;
208          if (!Irp)
209             KeBugCheck(0);
210          if (!Irp->AssociatedIrp.IrpCount)
211             KeBugCheck(0);      /* Completion of already completed MasterIrp? */
212          /* TODO:thread */
213          if (--Irp->AssociatedIrp.IrpCount)
214             return;     /* not yet fully completed MasterIrp */
215          if (Irp->UserIosb)
216             {
217                *Irp->UserIosb=Irp->IoStatus;
218             }
219       }
220    
221    IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
222    FileObject = IoStack->FileObject;
223    
224    DeviceObject = IoStack->DeviceObject;
225    
226    switch (IoStack->MajorFunction)
227      {
228       case IRP_MJ_CREATE:
229       case IRP_MJ_FLUSH_BUFFERS:
230           /* NOP */
231         break;
232         
233       case IRP_MJ_READ:
234       case IRP_MJ_WRITE:
235         IoReadWriteCompletion(DeviceObject,Irp,IoStack);
236         break;
237         
238       case IRP_MJ_DEVICE_CONTROL:
239       case IRP_MJ_INTERNAL_DEVICE_CONTROL:
240         IoDeviceControlCompletion(DeviceObject, Irp, IoStack);
241         break;
242         
243       case IRP_MJ_QUERY_VOLUME_INFORMATION:
244       case IRP_MJ_SET_VOLUME_INFORMATION:
245         IoVolumeInformationCompletion(DeviceObject, Irp, IoStack);
246         break;
247         
248       default:
249         break;
250      }
251    
252    if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
253      {
254 #ifndef LIBCAPTIVE
255         PKTHREAD Thread;
256         PKNORMAL_ROUTINE UserApcRoutine;
257         PVOID UserApcContext;
258 #endif /* LIBCAPTIVE */
259         
260         DPRINT("Dispatching APC\n");
261 #ifndef LIBCAPTIVE
262         Thread = &Irp->Tail.Overlay.Thread->Tcb;
263         UserApcRoutine = (PKNORMAL_ROUTINE)
264           Irp->Overlay.AsynchronousParameters.UserApcRoutine;
265         UserApcContext = (PVOID)
266           Irp->Overlay.AsynchronousParameters.UserApcContext;
267         KeInitializeApc(&Irp->Tail.Apc,
268                         Thread,
269                         0,
270                         IopCompleteRequest1,
271                         NULL,
272                         UserApcRoutine,
273                         UserMode,
274                         UserApcContext);
275         KeInsertQueueApc(&Irp->Tail.Apc,
276                          Irp,
277                          (PVOID)(LONG)PriorityBoost,
278                          KernelMode);
279 #else /* !LIBCAPTIVE */
280         KeBugCheck(0);
281 #endif /* !LIBCAPTIVE */
282         return;
283      }
284    
285    DPRINT("Irp->UserIosb %x &Irp->UserIosb %x\n", 
286            Irp->UserIosb,
287            &Irp->UserIosb);
288    if (Irp->UserIosb!=NULL)
289      {
290         *Irp->UserIosb=Irp->IoStatus;
291      }
292
293    if (Irp->UserEvent)
294    {
295       KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
296    }
297
298    if (!(Irp->Flags & IRP_PAGING_IO) && FileObject)
299    {
300       // if the event is not the one in the file object, it needs dereferenced
301       if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event)
302          ObDereferenceObject(Irp->UserEvent);
303
304       if (IoStack->MajorFunction != IRP_MJ_CLOSE)
305       {
306          ObDereferenceObject(FileObject);
307       }
308    }
309
310    IoFreeIrp(Irp);
311 }