Some fixes.
[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 <string.h>
16 #include <internal/string.h>
17 #include <internal/ob.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 /* FUNCTIONS ***************************************************************/
23
24 VOID IopCompleteRequest1(struct _KAPC* Apc,
25 PKNORMAL_ROUTINE* NormalRoutine,
26 PVOID* NormalContext,
27 PVOID* SystemArgument1,
28 PVOID* SystemArgument2)
29 {
30 PIRP Irp;
31
32 DPRINT("IopCompleteRequest1()\n");
33
34 Irp = (PIRP)(*SystemArgument1);
35 (*SystemArgument1) = (PVOID)Irp->UserIosb;
36 (*SystemArgument2) = (PVOID)Irp->IoStatus.Information;
37 IoFreeIrp((PIRP)(*SystemArgument1));
38 }
39
40 VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
41 PIRP Irp,
42 PIO_STACK_LOCATION IoStack)
43 {
44 ULONG IoControlCode;
45
46 IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
47
48 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
49 {
50 case METHOD_BUFFERED:
51 DPRINT ("Using METHOD_BUFFERED!\n");
52
53 /* copy output buffer back and free it */
54 if (Irp->AssociatedIrp.SystemBuffer)
55 {
56 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength)
57 {
58 RtlCopyMemory(Irp->UserBuffer,
59 Irp->AssociatedIrp.SystemBuffer,
60 IoStack->Parameters.DeviceIoControl.
61 OutputBufferLength);
62 }
63 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
64 }
65 break;
66
67 case METHOD_IN_DIRECT:
68 DPRINT ("Using METHOD_IN_DIRECT!\n");
69
70 /* free input buffer (control buffer) */
71 if (Irp->AssociatedIrp.SystemBuffer)
72 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
73
74 /* free output buffer (data transfer buffer) */
75 if (Irp->MdlAddress)
76 IoFreeMdl (Irp->MdlAddress);
77 break;
78
79 case METHOD_OUT_DIRECT:
80 DPRINT ("Using METHOD_OUT_DIRECT!\n");
81
82 /* free input buffer (control buffer) */
83 if (Irp->AssociatedIrp.SystemBuffer)
84 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
85
86 /* free output buffer (data transfer buffer) */
87 if (Irp->MdlAddress)
88 IoFreeMdl (Irp->MdlAddress);
89 break;
90
91 case METHOD_NEITHER:
92 DPRINT ("Using METHOD_NEITHER!\n");
93 /* nothing to do */
94 break;
95 }
96 }
97
98 VOID IoReadWriteCompletion(PDEVICE_OBJECT DeviceObject,
99 PIRP Irp,
100 PIO_STACK_LOCATION IoStack)
101 {
102 PFILE_OBJECT FileObject;
103
104 FileObject = IoStack->FileObject;
105
106 if (DeviceObject->Flags & DO_BUFFERED_IO)
107 {
108 if (IoStack->MajorFunction == IRP_MJ_READ)
109 {
110 DPRINT("Copying buffered io back to user\n");
111 memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer,
112 IoStack->Parameters.Read.Length);
113 }
114 ExFreePool(Irp->AssociatedIrp.SystemBuffer);
115 }
116 if (DeviceObject->Flags & DO_DIRECT_IO)
117 {
118 DPRINT("Tearing down MDL\n");
119 if (Irp->MdlAddress->MappedSystemVa!=NULL)
120 {
121 MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa,
122 Irp->MdlAddress);
123 }
124 MmUnlockPages(Irp->MdlAddress);
125 ExFreePool(Irp->MdlAddress);
126 }
127 if (FileObject != NULL)
128 {
129 FileObject->CurrentByteOffset.u.LowPart =
130 FileObject->CurrentByteOffset.u.LowPart +
131 Irp->IoStatus.Information;
132 }
133 }
134
135 VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject,
136 PIRP Irp,
137 PIO_STACK_LOCATION IoStack)
138 {
139 }
140
141 VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
142 /*
143 * FUNCTION: Performs the second stage of irp completion for read/write irps
144 * ARGUMENTS:
145 * Irp = Irp to completion
146 * FromDevice = True if the operation transfered data from the device
147 */
148 {
149 PIO_STACK_LOCATION IoStack;
150 PDEVICE_OBJECT DeviceObject;
151 PFILE_OBJECT FileObject;
152
153 DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n",
154 Irp, PriorityBoost);
155
156 IoStack = IoGetCurrentIrpStackLocation(Irp);
157
158 DeviceObject = IoStack->DeviceObject;
159
160 switch (IoStack->MajorFunction)
161 {
162 case IRP_MJ_CREATE:
163 case IRP_MJ_FLUSH_BUFFERS:
164 /* NOP */
165 break;
166
167 case IRP_MJ_READ:
168 case IRP_MJ_WRITE:
169 IoReadWriteCompletion(DeviceObject,Irp,IoStack);
170 break;
171
172 case IRP_MJ_DEVICE_CONTROL:
173 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
174 IoDeviceControlCompletion(DeviceObject, Irp, IoStack);
175 break;
176
177 case IRP_MJ_QUERY_VOLUME_INFORMATION:
178 case IRP_MJ_SET_VOLUME_INFORMATION:
179 IoVolumeInformationCompletion(DeviceObject, Irp, IoStack);
180 break;
181
182 default:
183 }
184
185 if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
186 {
187 PKTHREAD Thread;
188 PKNORMAL_ROUTINE UserApcRoutine;
189 PVOID UserApcContext;
190
191 DPRINT("Dispatching APC\n");
192 Thread = &Irp->Tail.Overlay.Thread->Tcb;
193 UserApcRoutine = (PKNORMAL_ROUTINE)
194 Irp->Overlay.AsynchronousParameters.UserApcRoutine;
195 UserApcContext = (PVOID)
196 Irp->Overlay.AsynchronousParameters.UserApcRoutine;
197 KeInitializeApc(&Irp->Tail.Apc,
198 Thread,
199 0,
200 IopCompleteRequest1,
201 NULL,
202 UserApcRoutine,
203 UserMode,
204 UserApcContext);
205 KeInsertQueueApc(&Irp->Tail.Apc,
206 Irp,
207 NULL,
208 KernelMode);
209 return;
210 }
211
212 DPRINT("Irp->UserIosb %x &Irp->UserIosb %x\n",
213 Irp->UserIosb,
214 &Irp->UserIosb);
215 if (Irp->UserIosb!=NULL)
216 {
217 *Irp->UserIosb=Irp->IoStatus;
218 }
219 if (Irp->UserEvent!=NULL)
220 {
221 KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
222 }
223
224 FileObject = IoStack->FileObject;
225
226 if (FileObject != NULL && IoStack->MajorFunction != IRP_MJ_CLOSE)
227 {
228 ObDereferenceObject(FileObject);
229 }
230
231 IoFreeIrp(Irp);
232 }