63f80fa072b8783436bc74871b7ad8a0aeb568cb
[reactos.git] / reactos / 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
43 (*SystemArgument1) = (PVOID)Irp->UserIosb;
44 (*SystemArgument2) = (PVOID)Irp->IoStatus.Information;
45
46 if (Irp->UserIosb!=NULL)
47 {
48 *Irp->UserIosb=Irp->IoStatus;
49 }
50 if (Irp->UserEvent!=NULL)
51 {
52 KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
53 ObDereferenceObject( Irp->UserEvent );
54 }
55
56 FileObject = IoStack->FileObject;
57
58 if (FileObject != NULL && IoStack->MajorFunction != IRP_MJ_CLOSE)
59 {
60 ObDereferenceObject(FileObject);
61 }
62
63 IoFreeIrp(Irp);
64
65 }
66
67 VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
68 PIRP Irp,
69 PIO_STACK_LOCATION IoStack)
70 {
71 ULONG IoControlCode;
72
73 IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
74
75 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
76 {
77 case METHOD_BUFFERED:
78 DPRINT ("Using METHOD_BUFFERED!\n");
79
80 /* copy output buffer back and free it */
81 if (Irp->AssociatedIrp.SystemBuffer)
82 {
83 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength)
84 {
85 RtlCopyMemory(Irp->UserBuffer,
86 Irp->AssociatedIrp.SystemBuffer,
87 IoStack->Parameters.DeviceIoControl.
88 OutputBufferLength);
89 }
90 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
91 }
92 break;
93
94 case METHOD_IN_DIRECT:
95 DPRINT ("Using METHOD_IN_DIRECT!\n");
96
97 /* free input buffer (control buffer) */
98 if (Irp->AssociatedIrp.SystemBuffer)
99 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
100
101 /* free output buffer (data transfer buffer) */
102 if (Irp->MdlAddress)
103 IoFreeMdl (Irp->MdlAddress);
104 break;
105
106 case METHOD_OUT_DIRECT:
107 DPRINT ("Using METHOD_OUT_DIRECT!\n");
108
109 /* free input buffer (control buffer) */
110 if (Irp->AssociatedIrp.SystemBuffer)
111 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
112
113 /* free output buffer (data transfer buffer) */
114 if (Irp->MdlAddress)
115 IoFreeMdl (Irp->MdlAddress);
116 break;
117
118 case METHOD_NEITHER:
119 DPRINT ("Using METHOD_NEITHER!\n");
120 /* nothing to do */
121 break;
122 }
123 }
124
125 VOID IoReadWriteCompletion(PDEVICE_OBJECT DeviceObject,
126 PIRP Irp,
127 PIO_STACK_LOCATION IoStack)
128 {
129 PFILE_OBJECT FileObject;
130
131 FileObject = IoStack->FileObject;
132
133 if (DeviceObject->Flags & DO_BUFFERED_IO)
134 {
135 if (IoStack->MajorFunction == IRP_MJ_READ)
136 {
137 DPRINT("Copying buffered io back to user\n");
138 memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer,
139 IoStack->Parameters.Read.Length);
140 }
141 ExFreePool(Irp->AssociatedIrp.SystemBuffer);
142 }
143 if (DeviceObject->Flags & DO_DIRECT_IO)
144 {
145 /* FIXME: Is the MDL destroyed on a paging i/o, check all cases. */
146 DPRINT("Tearing down MDL\n");
147 if (Irp->MdlAddress->MappedSystemVa != NULL)
148 {
149 MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa,
150 Irp->MdlAddress);
151 }
152 MmUnlockPages(Irp->MdlAddress);
153 ExFreePool(Irp->MdlAddress);
154 }
155 }
156
157 VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject,
158 PIRP Irp,
159 PIO_STACK_LOCATION IoStack)
160 {
161 }
162
163 VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
164 /*
165 * FUNCTION: Performs the second stage of irp completion for read/write irps
166 * ARGUMENTS:
167 * Irp = Irp to completion
168 * FromDevice = True if the operation transfered data from the device
169 */
170 {
171 PIO_STACK_LOCATION IoStack;
172 PDEVICE_OBJECT DeviceObject;
173 PFILE_OBJECT FileObject;
174
175 DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n",
176 Irp, PriorityBoost);
177
178 IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
179 FileObject = IoStack->FileObject;
180
181 DeviceObject = IoStack->DeviceObject;
182
183 switch (IoStack->MajorFunction)
184 {
185 case IRP_MJ_CREATE:
186 case IRP_MJ_FLUSH_BUFFERS:
187 /* NOP */
188 break;
189
190 case IRP_MJ_READ:
191 case IRP_MJ_WRITE:
192 IoReadWriteCompletion(DeviceObject,Irp,IoStack);
193 break;
194
195 case IRP_MJ_DEVICE_CONTROL:
196 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
197 IoDeviceControlCompletion(DeviceObject, Irp, IoStack);
198 break;
199
200 case IRP_MJ_QUERY_VOLUME_INFORMATION:
201 case IRP_MJ_SET_VOLUME_INFORMATION:
202 IoVolumeInformationCompletion(DeviceObject, Irp, IoStack);
203 break;
204
205 default:
206 break;
207 }
208
209 if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
210 {
211 PKTHREAD Thread;
212 PKNORMAL_ROUTINE UserApcRoutine;
213 PVOID UserApcContext;
214
215 DPRINT("Dispatching APC\n");
216 Thread = &Irp->Tail.Overlay.Thread->Tcb;
217 UserApcRoutine = (PKNORMAL_ROUTINE)
218 Irp->Overlay.AsynchronousParameters.UserApcRoutine;
219 UserApcContext = (PVOID)
220 Irp->Overlay.AsynchronousParameters.UserApcContext;
221 KeInitializeApc(&Irp->Tail.Apc,
222 Thread,
223 0,
224 IopCompleteRequest1,
225 NULL,
226 UserApcRoutine,
227 UserMode,
228 UserApcContext);
229 KeInsertQueueApc(&Irp->Tail.Apc,
230 Irp,
231 (PVOID)(LONG)PriorityBoost,
232 KernelMode);
233 return;
234 }
235
236 DPRINT("Irp->UserIosb %x &Irp->UserIosb %x\n",
237 Irp->UserIosb,
238 &Irp->UserIosb);
239 if (Irp->UserIosb!=NULL)
240 {
241 *Irp->UserIosb=Irp->IoStatus;
242 }
243 if (Irp->UserEvent!=NULL)
244 {
245 KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
246 // if the event is not the one in the file object, it needs dereferenced
247 if( FileObject && Irp->UserEvent != &FileObject->Event )
248 ObDereferenceObject( Irp->UserEvent );
249 }
250
251 if (FileObject != NULL && IoStack->MajorFunction != IRP_MJ_CLOSE)
252 {
253 //ObDereferenceObject(FileObject);
254 }
255 if (FileObject != NULL && (IoStack->MajorFunction == IRP_MJ_READ || IoStack->MajorFunction == IRP_MJ_WRITE || IoStack->MajorFunction ==IRP_MJ_CLEANUP || IoStack->MajorFunction ==IRP_MJ_CREATE || IoStack->MajorFunction==IRP_MJ_DIRECTORY_CONTROL))
256 {
257 ObDereferenceObject(FileObject);
258 }
259
260 IoFreeIrp(Irp);
261 }