Added some modifications for asyncronous i/o requests (for vfatfs).
[reactos.git] / reactos / ntoskrnl / io / ioctrl.c
1 /* $Id: ioctrl.c,v 1.13 2001/11/02 22:22:33 hbirr Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/ioctrl.c
6 * PURPOSE: Device IO control
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * Eric Kohl (ekohl@abo.rhein-zeitung.de)
9 * UPDATE HISTORY:
10 * Created 22/05/98
11 * Filled in ZwDeviceIoControlFile 22/02/99
12 * Fixed IO method handling 08/03/99
13 * Added APC support 05/11/99
14 */
15
16 /* INCLUDES *****************************************************************/
17
18 #include <ddk/ntddk.h>
19 #include <internal/io.h>
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* FUNCTIONS *****************************************************************/
24
25 NTSTATUS STDCALL NtDeviceIoControlFile (IN HANDLE DeviceHandle,
26 IN HANDLE Event,
27 IN PIO_APC_ROUTINE UserApcRoutine,
28 IN PVOID UserApcContext,
29 OUT PIO_STATUS_BLOCK IoStatusBlock,
30 IN ULONG IoControlCode,
31 IN PVOID InputBuffer,
32 IN ULONG InputBufferSize,
33 OUT PVOID OutputBuffer,
34 IN ULONG OutputBufferSize)
35 {
36 NTSTATUS Status;
37 PFILE_OBJECT FileObject;
38 PDEVICE_OBJECT DeviceObject;
39 PIRP Irp;
40 PIO_STACK_LOCATION StackPtr;
41 KEVENT KEvent;
42 PKEVENT ptrEvent;
43 IO_STATUS_BLOCK IoSB;
44
45 DPRINT("NtDeviceIoControlFile(DeviceHandle %x Event %x UserApcRoutine %x "
46 "UserApcContext %x IoStatusBlock %x IoControlCode %x "
47 "InputBuffer %x InputBufferSize %x OutputBuffer %x "
48 "OutputBufferSize %x)\n",
49 DeviceHandle,Event,UserApcRoutine,UserApcContext,IoStatusBlock,
50 IoControlCode,InputBuffer,InputBufferSize,OutputBuffer,
51 OutputBufferSize);
52
53 Status = ObReferenceObjectByHandle(DeviceHandle,
54 FILE_READ_DATA | FILE_WRITE_DATA,
55 IoFileObjectType,
56 KernelMode,
57 (PVOID *) &FileObject,
58 NULL);
59
60 if (!NT_SUCCESS(Status))
61 {
62 return(Status);
63 }
64 if (Event != NULL)
65 {
66 Status = ObReferenceObjectByHandle (Event,
67 SYNCHRONIZE,
68 ExEventObjectType,
69 UserMode,
70 (PVOID*)&ptrEvent,
71 NULL);
72 if (!NT_SUCCESS(Status))
73 {
74 ObDereferenceObject(FileObject);
75 return Status;
76 }
77 }
78 else if (FileObject->Flags & FO_SYNCHRONOUS_IO)
79 {
80 ptrEvent = NULL;
81 }
82 else
83 {
84 KeInitializeEvent (&KEvent,
85 NotificationEvent,
86 FALSE);
87 ptrEvent = &KEvent;
88 }
89
90 DeviceObject = FileObject->DeviceObject;
91
92 KeInitializeEvent(&KEvent,NotificationEvent,TRUE);
93
94 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
95 DeviceObject,
96 InputBuffer,
97 InputBufferSize,
98 OutputBuffer,
99 OutputBufferSize,
100 FALSE,
101 ptrEvent,
102 Event ? IoStatusBlock : &IoSB);
103
104 Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine;
105 Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext;
106
107 StackPtr = IoGetNextIrpStackLocation(Irp);
108 StackPtr->FileObject = FileObject;
109 StackPtr->DeviceObject = DeviceObject;
110 StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferSize;
111 StackPtr->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferSize;
112
113 Status = IoCallDriver(DeviceObject,Irp);
114 if (Event == NULL && Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
115 {
116 KeWaitForSingleObject(&KEvent,Executive,KernelMode,FALSE,NULL);
117 Status = IoSB.Status;
118 }
119 if (IoStatusBlock)
120 {
121 *IoStatusBlock = IoSB;
122 }
123 return(Status);
124 }
125
126 /* EOF */