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 ***************************************************************/
24 VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
26 PIO_STACK_LOCATION IoStack)
29 ULONG OutputBufferLength;
31 if (IoStack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)
34 ((PEXTENDED_IO_STACK_LOCATION)IoStack)->Parameters.FileSystemControl.FsControlCode;
36 ((PEXTENDED_IO_STACK_LOCATION)IoStack)->Parameters.FileSystemControl.OutputBufferLength;
40 IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
41 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
44 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
47 DPRINT ("Using METHOD_BUFFERED!\n");
49 /* copy output buffer back and free it */
50 if (Irp->AssociatedIrp.SystemBuffer)
52 if (OutputBufferLength)
54 RtlCopyMemory(Irp->UserBuffer,
55 Irp->AssociatedIrp.SystemBuffer,
58 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
62 case METHOD_IN_DIRECT:
63 DPRINT ("Using METHOD_IN_DIRECT!\n");
65 /* copy output buffer back and free it */
66 if (Irp->AssociatedIrp.SystemBuffer)
68 if (OutputBufferLength)
70 RtlCopyMemory(Irp->UserBuffer,
71 Irp->AssociatedIrp.SystemBuffer,
74 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
77 /* free input buffer (data transfer buffer) */
79 IoFreeMdl (Irp->MdlAddress);
82 case METHOD_OUT_DIRECT:
83 DPRINT ("Using METHOD_OUT_DIRECT!\n");
85 /* free input buffer (control buffer) */
86 if (Irp->AssociatedIrp.SystemBuffer)
87 ExFreePool (Irp->AssociatedIrp.SystemBuffer);
89 /* free output buffer (data transfer buffer) */
91 IoFreeMdl (Irp->MdlAddress);
95 DPRINT ("Using METHOD_NEITHER!\n");
101 VOID IoReadWriteCompletion(PDEVICE_OBJECT DeviceObject,
103 PIO_STACK_LOCATION IoStack)
105 PFILE_OBJECT FileObject;
107 FileObject = IoStack->FileObject;
109 if (DeviceObject->Flags & DO_BUFFERED_IO)
111 if (IoStack->MajorFunction == IRP_MJ_READ)
113 DPRINT("Copying buffered io back to user\n");
114 memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer,
115 IoStack->Parameters.Read.Length);
117 ExFreePool(Irp->AssociatedIrp.SystemBuffer);
119 if (DeviceObject->Flags & DO_DIRECT_IO)
121 /* FIXME: Is the MDL destroyed on a paging i/o, check all cases. */
122 DPRINT("Tearing down MDL\n");
123 if (Irp->MdlAddress->MappedSystemVa != NULL)
125 MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa,
128 MmUnlockPages(Irp->MdlAddress);
129 ExFreePool(Irp->MdlAddress);
133 VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject,
135 PIO_STACK_LOCATION IoStack)
141 IoSecondStageCompletion_KernelApcRoutine(
143 IN OUT PKNORMAL_ROUTINE *NormalRoutine,
144 IN OUT PVOID *NormalContext,
145 IN OUT PVOID *SystemArgument1,
146 IN OUT PVOID *SystemArgument2
149 IoFreeIrp((PIRP)(*SystemArgument1));
154 IoSecondStageCompletion_RundownApcRoutine(
160 Irp = CONTAINING_RECORD(Apc, IRP, Tail.Apc);
166 * FUNCTION: Performs the second stage of irp completion for read/write irps
168 * Called as a special kernel APC or directly from IofCompleteRequest()
171 IoSecondStageCompletion(
173 PKNORMAL_ROUTINE* NormalRoutine,
174 PVOID* NormalContext,
175 PVOID* SystemArgument1,
176 PVOID* SystemArgument2)
179 PIO_STACK_LOCATION IoStack;
180 PDEVICE_OBJECT DeviceObject;
181 PFILE_OBJECT OriginalFileObject;
185 OriginalFileObject = (PFILE_OBJECT)(*NormalContext);
186 Irp = (PIRP)(*SystemArgument1);
187 PriorityBoost = (CCHAR)(LONG)(*SystemArgument2);
189 IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
190 DeviceObject = IoStack->DeviceObject;
192 DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n", Irp, PriorityBoost);
194 switch (IoStack->MajorFunction)
197 case IRP_MJ_FLUSH_BUFFERS:
203 IoReadWriteCompletion(DeviceObject,Irp,IoStack);
206 case IRP_MJ_DEVICE_CONTROL:
207 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
208 case IRP_MJ_FILE_SYSTEM_CONTROL:
209 IoDeviceControlCompletion(DeviceObject, Irp, IoStack);
212 case IRP_MJ_QUERY_VOLUME_INFORMATION:
213 case IRP_MJ_SET_VOLUME_INFORMATION:
214 IoVolumeInformationCompletion(DeviceObject, Irp, IoStack);
221 if (Irp->UserIosb!=NULL)
223 *Irp->UserIosb=Irp->IoStatus;
228 KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
231 //Windows NT File System Internals, page 169
232 if (OriginalFileObject)
234 if (Irp->UserEvent == NULL)
236 KeSetEvent(&OriginalFileObject->Event,PriorityBoost,FALSE);
238 else if (OriginalFileObject->Flags & FO_SYNCHRONOUS_IO && Irp->UserEvent != &OriginalFileObject->Event)
240 KeSetEvent(&OriginalFileObject->Event,PriorityBoost,FALSE);
244 //Windows NT File System Internals, page 154
245 if (!(Irp->Flags & IRP_PAGING_IO) && OriginalFileObject)
247 // if the event is not the one in the file object, it needs dereferenced
248 if (Irp->UserEvent && Irp->UserEvent != &OriginalFileObject->Event)
250 ObDereferenceObject(Irp->UserEvent);
253 if (IoStack->MajorFunction != IRP_MJ_CLOSE)
255 ObDereferenceObject(OriginalFileObject);
259 if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
261 PKNORMAL_ROUTINE UserApcRoutine;
262 PVOID UserApcContext;
264 DPRINT("Dispatching user APC\n");
266 UserApcRoutine = (PKNORMAL_ROUTINE)Irp->Overlay.AsynchronousParameters.UserApcRoutine;
267 UserApcContext = (PVOID)Irp->Overlay.AsynchronousParameters.UserApcContext;
269 KeInitializeApc( &Irp->Tail.Apc,
270 KeGetCurrentThread(),
271 OriginalApcEnvironment,
272 IoSecondStageCompletion_KernelApcRoutine,
273 IoSecondStageCompletion_RundownApcRoutine,
278 KeInsertQueueApc( &Irp->Tail.Apc,
283 //NOTE: kernel (or rundown) routine frees the IRP