2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/cleanup.c
6 * PROGRAMMER: David Welch (welch@mcmail.com)
11 /* INCLUDES ****************************************************************/
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>
20 #include <internal/debug.h>
22 /* FUNCTIONS ***************************************************************/
25 IopCompleteRequest1(struct _KAPC* Apc,
26 PKNORMAL_ROUTINE* NormalRoutine,
28 PVOID* SystemArgument1,
29 PVOID* SystemArgument2)
33 PIO_STACK_LOCATION IoStack;
34 PFILE_OBJECT FileObject;
36 DPRINT("IopCompleteRequest1()\n");
38 Irp = (PIRP)(*SystemArgument1);
39 PriorityBoost = (CCHAR)(LONG)(*SystemArgument2);
41 IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
42 FileObject = IoStack->FileObject;
44 (*SystemArgument1) = (PVOID)Irp->UserIosb;
45 (*SystemArgument2) = (PVOID)Irp->IoStatus.Information;
47 if (Irp->UserIosb!=NULL)
49 *Irp->UserIosb=Irp->IoStatus;
54 KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
57 if (!(Irp->Flags & IRP_PAGING_IO) && FileObject)
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);
63 if (IoStack->MajorFunction != IRP_MJ_CLOSE)
65 ObDereferenceObject(FileObject);
73 VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
75 PIO_STACK_LOCATION IoStack)
79 IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
81 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
84 DPRINT ("Using METHOD_BUFFERED!\n");
86 /* copy output buffer back and free it */
87 if (Irp->AssociatedIrp.SystemBuffer)
89 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength)
91 RtlCopyMemory(Irp->UserBuffer,
92 Irp->AssociatedIrp.SystemBuffer,
93 IoStack->Parameters.DeviceIoControl.
96 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
100 case METHOD_IN_DIRECT:
101 DPRINT ("Using METHOD_IN_DIRECT!\n");
103 /* copy output buffer back and free it */
104 if (Irp->AssociatedIrp.SystemBuffer)
106 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength)
108 RtlCopyMemory(Irp->UserBuffer,
109 Irp->AssociatedIrp.SystemBuffer,
110 IoStack->Parameters.DeviceIoControl.
113 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
116 /* free input buffer (data transfer buffer) */
118 IoFreeMdl (Irp->MdlAddress);
121 case METHOD_OUT_DIRECT:
122 DPRINT ("Using METHOD_OUT_DIRECT!\n");
124 /* free input buffer (control buffer) */
125 if (Irp->AssociatedIrp.SystemBuffer)
126 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
128 /* free output buffer (data transfer buffer) */
130 IoFreeMdl (Irp->MdlAddress);
134 DPRINT ("Using METHOD_NEITHER!\n");
140 VOID IoReadWriteCompletion(PDEVICE_OBJECT DeviceObject,
142 PIO_STACK_LOCATION IoStack)
144 PFILE_OBJECT FileObject;
146 FileObject = IoStack->FileObject;
148 if (DeviceObject->Flags & DO_BUFFERED_IO)
150 if (IoStack->MajorFunction == IRP_MJ_READ)
152 DPRINT("Copying buffered io back to user\n");
153 memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer,
154 IoStack->Parameters.Read.Length);
156 ExFreePool(Irp->AssociatedIrp.SystemBuffer);
158 if (DeviceObject->Flags & DO_DIRECT_IO)
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)
164 MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa,
167 MmUnlockPages(Irp->MdlAddress);
168 ExFreePool(Irp->MdlAddress);
172 VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject,
174 PIO_STACK_LOCATION IoStack)
178 VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
180 * FUNCTION: Performs the second stage of irp completion for read/write irps
182 * Irp = Irp to completion
183 * FromDevice = True if the operation transfered data from the device
186 PIO_STACK_LOCATION IoStack;
187 PDEVICE_OBJECT DeviceObject;
188 PFILE_OBJECT FileObject;
190 DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n",
193 /* FIXME: Should we set 'Irp->UserIosb' only on MasterIrp finalization
194 * or we should set it for each subrequest?
198 *Irp->UserIosb=Irp->IoStatus;
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. :-?
205 if (Irp->Flags & IRP_ASSOCIATED_IRP)
207 Irp=Irp->AssociatedIrp.MasterIrp;
210 if (!Irp->AssociatedIrp.IrpCount)
211 KeBugCheck(0); /* Completion of already completed MasterIrp? */
213 if (--Irp->AssociatedIrp.IrpCount)
214 return; /* not yet fully completed MasterIrp */
217 *Irp->UserIosb=Irp->IoStatus;
221 IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
222 FileObject = IoStack->FileObject;
224 DeviceObject = IoStack->DeviceObject;
226 switch (IoStack->MajorFunction)
229 case IRP_MJ_FLUSH_BUFFERS:
235 IoReadWriteCompletion(DeviceObject,Irp,IoStack);
238 case IRP_MJ_DEVICE_CONTROL:
239 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
240 IoDeviceControlCompletion(DeviceObject, Irp, IoStack);
243 case IRP_MJ_QUERY_VOLUME_INFORMATION:
244 case IRP_MJ_SET_VOLUME_INFORMATION:
245 IoVolumeInformationCompletion(DeviceObject, Irp, IoStack);
252 if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
256 PKNORMAL_ROUTINE UserApcRoutine;
257 PVOID UserApcContext;
258 #endif /* LIBCAPTIVE */
260 DPRINT("Dispatching APC\n");
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,
275 KeInsertQueueApc(&Irp->Tail.Apc,
277 (PVOID)(LONG)PriorityBoost,
279 #else /* !LIBCAPTIVE */
281 #endif /* !LIBCAPTIVE */
285 DPRINT("Irp->UserIosb %x &Irp->UserIosb %x\n",
288 if (Irp->UserIosb!=NULL)
290 *Irp->UserIosb=Irp->IoStatus;
295 KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
298 if (!(Irp->Flags & IRP_PAGING_IO) && FileObject)
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);
304 if (IoStack->MajorFunction != IRP_MJ_CLOSE)
306 ObDereferenceObject(FileObject);