Merge aicom-network-branch (without NDIS changes for now)
[reactos.git] / reactos / subsystems / win32 / win32k / eng / device.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Driver Device Functions
5 * FILE: subsys/win32k/eng/device.c
6 * PROGRAMER: Jason Filby
7 * Timo Kreuzer
8 */
9
10 #include <w32k.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 static
16 NTSTATUS
17 EngpFileIoRequest(
18 PFILE_OBJECT pFileObject,
19 ULONG ulMajorFunction,
20 LPVOID lpBuffer,
21 DWORD nBufferSize,
22 ULONGLONG ullStartOffset,
23 OUT LPDWORD lpInformation)
24 {
25 PDEVICE_OBJECT pDeviceObject;
26 KEVENT Event;
27 PIRP pIrp;
28 IO_STATUS_BLOCK Iosb;
29 NTSTATUS Status;
30 LARGE_INTEGER liStartOffset;
31
32 /* Get corresponding device object */
33 pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
34 if (!pDeviceObject)
35 {
36 return STATUS_INVALID_PARAMETER;
37 }
38
39 /* Initialize an event */
40 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
41
42 /* Build IPR */
43 liStartOffset.QuadPart = ullStartOffset;
44 pIrp = IoBuildSynchronousFsdRequest(ulMajorFunction,
45 pDeviceObject,
46 lpBuffer,
47 nBufferSize,
48 &liStartOffset,
49 &Event,
50 &Iosb);
51 if (!pIrp)
52 {
53 return STATUS_INSUFFICIENT_RESOURCES;
54 }
55
56 /* Call the driver */
57 Status = IoCallDriver(pDeviceObject, pIrp);
58
59 /* Wait if neccessary */
60 if (STATUS_PENDING == Status)
61 {
62 KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0);
63 Status = Iosb.Status;
64 }
65
66 /* Return information to the caller about the operation. */
67 *lpInformation = Iosb.Information;
68
69 /* Return NTSTATUS */
70 return Status;
71 }
72
73 VOID
74 APIENTRY
75 EngFileWrite(
76 IN PFILE_OBJECT pFileObject,
77 IN PVOID lpBuffer,
78 IN SIZE_T nLength,
79 IN PSIZE_T lpBytesWritten)
80 {
81 EngpFileIoRequest(pFileObject,
82 IRP_MJ_WRITE,
83 lpBuffer,
84 nLength,
85 0,
86 lpBytesWritten);
87 }
88
89 NTSTATUS
90 APIENTRY
91 EngFileIoControl(
92 IN PFILE_OBJECT pFileObject,
93 IN DWORD dwIoControlCode,
94 IN PVOID lpInBuffer,
95 IN SIZE_T nInBufferSize,
96 OUT PVOID lpOutBuffer,
97 IN SIZE_T nOutBufferSize,
98 OUT LPDWORD lpInformation)
99 {
100 PDEVICE_OBJECT pDeviceObject;
101 KEVENT Event;
102 PIRP pIrp;
103 IO_STATUS_BLOCK Iosb;
104 NTSTATUS Status;
105
106 /* Get corresponding device object */
107 pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
108 if (!pDeviceObject)
109 {
110 return STATUS_INVALID_PARAMETER;
111 }
112
113 /* Initialize an event */
114 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
115
116 /* Build IO control IPR */
117 pIrp = IoBuildDeviceIoControlRequest(dwIoControlCode,
118 pDeviceObject,
119 lpInBuffer,
120 nInBufferSize,
121 lpOutBuffer,
122 nOutBufferSize,
123 FALSE,
124 &Event,
125 &Iosb);
126 if (!pIrp)
127 {
128 return STATUS_INSUFFICIENT_RESOURCES;
129 }
130
131 /* Call the driver */
132 Status = IoCallDriver(pDeviceObject, pIrp);
133
134 /* Wait if neccessary */
135 if (Status == STATUS_PENDING)
136 {
137 KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0);
138 Status = Iosb.Status;
139 }
140
141 /* Return information to the caller about the operation. */
142 *lpInformation = Iosb.Information;
143
144 /* This function returns NTSTATUS */
145 return Status;
146 }
147
148 /*
149 * @implemented
150 */
151 DWORD APIENTRY
152 EngDeviceIoControl(
153 HANDLE hDevice,
154 DWORD dwIoControlCode,
155 LPVOID lpInBuffer,
156 DWORD nInBufferSize,
157 LPVOID lpOutBuffer,
158 DWORD nOutBufferSize,
159 DWORD *lpBytesReturned)
160 {
161 PIRP Irp;
162 NTSTATUS Status;
163 KEVENT Event;
164 IO_STATUS_BLOCK Iosb;
165 PDEVICE_OBJECT DeviceObject;
166
167 DPRINT("EngDeviceIoControl() called\n");
168
169 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
170
171 DeviceObject = (PDEVICE_OBJECT) hDevice;
172
173 Irp = IoBuildDeviceIoControlRequest(dwIoControlCode,
174 DeviceObject,
175 lpInBuffer,
176 nInBufferSize,
177 lpOutBuffer,
178 nOutBufferSize, FALSE, &Event, &Iosb);
179 if (!Irp) return ERROR_NOT_ENOUGH_MEMORY;
180
181 Status = IoCallDriver(DeviceObject, Irp);
182
183 if (Status == STATUS_PENDING)
184 {
185 (VOID)KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0);
186 Status = Iosb.Status;
187 }
188
189 DPRINT("EngDeviceIoControl(): Returning %X/%X\n", Iosb.Status,
190 Iosb.Information);
191
192 /* Return information to the caller about the operation. */
193 *lpBytesReturned = Iosb.Information;
194
195 /* Convert NT status values to win32 error codes. */
196 switch (Status)
197 {
198 case STATUS_INSUFFICIENT_RESOURCES:
199 return ERROR_NOT_ENOUGH_MEMORY;
200
201 case STATUS_BUFFER_OVERFLOW:
202 return ERROR_MORE_DATA;
203
204 case STATUS_NOT_IMPLEMENTED:
205 return ERROR_INVALID_FUNCTION;
206
207 case STATUS_INVALID_PARAMETER:
208 return ERROR_INVALID_PARAMETER;
209
210 case STATUS_BUFFER_TOO_SMALL:
211 return ERROR_INSUFFICIENT_BUFFER;
212
213 case STATUS_DEVICE_DOES_NOT_EXIST:
214 return ERROR_DEV_NOT_EXIST;
215
216 case STATUS_PENDING:
217 return ERROR_IO_PENDING;
218 }
219
220 return Status;
221 }
222
223 /* EOF */