update for HEAD-2003050101
[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    IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
194    FileObject = IoStack->FileObject;
195    
196    DeviceObject = IoStack->DeviceObject;
197    
198    switch (IoStack->MajorFunction)
199      {
200       case IRP_MJ_CREATE:
201       case IRP_MJ_FLUSH_BUFFERS:
202           /* NOP */
203         break;
204         
205       case IRP_MJ_READ:
206       case IRP_MJ_WRITE:
207         IoReadWriteCompletion(DeviceObject,Irp,IoStack);
208         break;
209         
210       case IRP_MJ_DEVICE_CONTROL:
211       case IRP_MJ_INTERNAL_DEVICE_CONTROL:
212         IoDeviceControlCompletion(DeviceObject, Irp, IoStack);
213         break;
214         
215       case IRP_MJ_QUERY_VOLUME_INFORMATION:
216       case IRP_MJ_SET_VOLUME_INFORMATION:
217         IoVolumeInformationCompletion(DeviceObject, Irp, IoStack);
218         break;
219         
220       default:
221         break;
222      }
223    
224    if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
225      {
226         PKTHREAD Thread;
227         PKNORMAL_ROUTINE UserApcRoutine;
228         PVOID UserApcContext;
229         
230         DPRINT("Dispatching APC\n");
231         Thread = &Irp->Tail.Overlay.Thread->Tcb;
232         UserApcRoutine = (PKNORMAL_ROUTINE)
233           Irp->Overlay.AsynchronousParameters.UserApcRoutine;
234         UserApcContext = (PVOID)
235           Irp->Overlay.AsynchronousParameters.UserApcContext;
236         KeInitializeApc(&Irp->Tail.Apc,
237                         Thread,
238                         0,
239                         IopCompleteRequest1,
240                         NULL,
241                         UserApcRoutine,
242                         UserMode,
243                         UserApcContext);
244         KeInsertQueueApc(&Irp->Tail.Apc,
245                          Irp,
246                          (PVOID)(LONG)PriorityBoost,
247                          KernelMode);
248         return;
249      }
250    
251    DPRINT("Irp->UserIosb %x &Irp->UserIosb %x\n", 
252            Irp->UserIosb,
253            &Irp->UserIosb);
254    if (Irp->UserIosb!=NULL)
255      {
256         *Irp->UserIosb=Irp->IoStatus;
257      }
258
259    if (Irp->UserEvent)
260    {
261       KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
262    }
263
264    if (!(Irp->Flags & IRP_PAGING_IO) && FileObject)
265    {
266       // if the event is not the one in the file object, it needs dereferenced
267       if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event)
268          ObDereferenceObject(Irp->UserEvent);
269
270       if (IoStack->MajorFunction != IRP_MJ_CLOSE)
271       {
272          ObDereferenceObject(FileObject);
273       }
274    }
275
276    IoFreeIrp(Irp);
277 }