6fd0302943ecbb7697a5da2d4b2655c458565eb1
[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         /* free input buffer (control buffer) */
104         if (Irp->AssociatedIrp.SystemBuffer)
105           ExFreePool (Irp->AssociatedIrp.SystemBuffer);
106         
107         /* free output buffer (data transfer buffer) */
108         if (Irp->MdlAddress)
109           IoFreeMdl (Irp->MdlAddress);
110         break;
111         
112       case METHOD_OUT_DIRECT:
113         DPRINT ("Using METHOD_OUT_DIRECT!\n");
114         
115         /* free input buffer (control buffer) */
116         if (Irp->AssociatedIrp.SystemBuffer)
117           ExFreePool (Irp->AssociatedIrp.SystemBuffer);
118         
119         /* free output buffer (data transfer buffer) */
120         if (Irp->MdlAddress)
121           IoFreeMdl (Irp->MdlAddress);
122         break;
123         
124       case METHOD_NEITHER:
125         DPRINT ("Using METHOD_NEITHER!\n");
126         /* nothing to do */
127         break;
128      }
129 }
130
131 VOID IoReadWriteCompletion(PDEVICE_OBJECT DeviceObject,
132                            PIRP Irp,
133                            PIO_STACK_LOCATION IoStack)
134 {   
135    PFILE_OBJECT FileObject;
136    
137    FileObject = IoStack->FileObject;
138    
139    if (DeviceObject->Flags & DO_BUFFERED_IO)     
140      {
141         if (IoStack->MajorFunction == IRP_MJ_READ)
142           {
143              DPRINT("Copying buffered io back to user\n");
144              memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer,
145                     IoStack->Parameters.Read.Length);
146           }
147         ExFreePool(Irp->AssociatedIrp.SystemBuffer);
148      }
149    if (DeviceObject->Flags & DO_DIRECT_IO)
150      {
151         /* FIXME: Is the MDL destroyed on a paging i/o, check all cases. */
152         DPRINT("Tearing down MDL\n");
153         if (Irp->MdlAddress->MappedSystemVa != NULL)
154           {          
155              MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa,
156                                 Irp->MdlAddress);
157           }
158         MmUnlockPages(Irp->MdlAddress);
159         ExFreePool(Irp->MdlAddress);
160      }
161 }
162
163 VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject,
164                                    PIRP Irp,
165                                    PIO_STACK_LOCATION IoStack)
166 {
167 }
168
169 VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
170 /*
171  * FUNCTION: Performs the second stage of irp completion for read/write irps
172  * ARGUMENTS:
173  *          Irp = Irp to completion
174  *          FromDevice = True if the operation transfered data from the device
175  */
176 {
177    PIO_STACK_LOCATION IoStack;
178    PDEVICE_OBJECT DeviceObject;
179    PFILE_OBJECT FileObject;
180    
181    DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n",
182           Irp, PriorityBoost);
183    
184    IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
185    FileObject = IoStack->FileObject;
186    
187    DeviceObject = IoStack->DeviceObject;
188    
189    switch (IoStack->MajorFunction)
190      {
191       case IRP_MJ_CREATE:
192       case IRP_MJ_FLUSH_BUFFERS:
193           /* NOP */
194         break;
195         
196       case IRP_MJ_READ:
197       case IRP_MJ_WRITE:
198         IoReadWriteCompletion(DeviceObject,Irp,IoStack);
199         break;
200         
201       case IRP_MJ_DEVICE_CONTROL:
202       case IRP_MJ_INTERNAL_DEVICE_CONTROL:
203         IoDeviceControlCompletion(DeviceObject, Irp, IoStack);
204         break;
205         
206       case IRP_MJ_QUERY_VOLUME_INFORMATION:
207       case IRP_MJ_SET_VOLUME_INFORMATION:
208         IoVolumeInformationCompletion(DeviceObject, Irp, IoStack);
209         break;
210         
211       default:
212         break;
213      }
214    
215    if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
216      {
217 #ifndef LIBCAPTIVE
218         PKTHREAD Thread;
219         PKNORMAL_ROUTINE UserApcRoutine;
220         PVOID UserApcContext;
221 #endif /* LIBCAPTIVE */
222         
223         DPRINT("Dispatching APC\n");
224 #ifndef LIBCAPTIVE
225         Thread = &Irp->Tail.Overlay.Thread->Tcb;
226         UserApcRoutine = (PKNORMAL_ROUTINE)
227           Irp->Overlay.AsynchronousParameters.UserApcRoutine;
228         UserApcContext = (PVOID)
229           Irp->Overlay.AsynchronousParameters.UserApcContext;
230         KeInitializeApc(&Irp->Tail.Apc,
231                         Thread,
232                         0,
233                         IopCompleteRequest1,
234                         NULL,
235                         UserApcRoutine,
236                         UserMode,
237                         UserApcContext);
238         KeInsertQueueApc(&Irp->Tail.Apc,
239                          Irp,
240                          (PVOID)(LONG)PriorityBoost,
241                          KernelMode);
242 #else /* !LIBCAPTIVE */
243         KeBugCheck(0);
244 #endif /* !LIBCAPTIVE */
245         return;
246      }
247    
248    DPRINT("Irp->UserIosb %x &Irp->UserIosb %x\n", 
249            Irp->UserIosb,
250            &Irp->UserIosb);
251    if (Irp->UserIosb!=NULL)
252      {
253         *Irp->UserIosb=Irp->IoStatus;
254      }
255
256    if (Irp->UserEvent)
257    {
258       KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
259    }
260
261    if (!(Irp->Flags & IRP_PAGING_IO) && FileObject)
262    {
263       // if the event is not the one in the file object, it needs dereferenced
264       if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event)
265          ObDereferenceObject(Irp->UserEvent);
266
267       if (IoStack->MajorFunction != IRP_MJ_CLOSE)
268       {
269          ObDereferenceObject(FileObject);
270       }
271    }
272
273    IoFreeIrp(Irp);
274 }