- Update to r53061
[reactos.git] / dll / win32 / kernel32 / client / file / deviceio.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: kernel32/file/deviceio.c
5 * PURPOSE: Device I/O Base Client Functionality
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <k32.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS ******************************************************************/
16
17 /*
18 * @implemented
19 */
20 BOOL
21 WINAPI
22 Beep (DWORD dwFreq, DWORD dwDuration)
23 {
24 HANDLE hBeep;
25 UNICODE_STRING BeepDevice;
26 OBJECT_ATTRIBUTES ObjectAttributes;
27 IO_STATUS_BLOCK IoStatusBlock;
28 BEEP_SET_PARAMETERS BeepSetParameters;
29 NTSTATUS Status;
30
31 /* check the parameters */
32 if ((dwFreq >= 0x25 && dwFreq <= 0x7FFF) ||
33 (dwFreq == 0x0 && dwDuration == 0x0))
34 {
35 /* open the device */
36 RtlInitUnicodeString(&BeepDevice,
37 L"\\Device\\Beep");
38
39 InitializeObjectAttributes(&ObjectAttributes,
40 &BeepDevice,
41 0,
42 NULL,
43 NULL);
44
45 Status = NtCreateFile(&hBeep,
46 FILE_READ_DATA | FILE_WRITE_DATA,
47 &ObjectAttributes,
48 &IoStatusBlock,
49 NULL,
50 0,
51 FILE_SHARE_READ | FILE_SHARE_WRITE,
52 FILE_OPEN_IF,
53 0,
54 NULL,
55 0);
56 if (NT_SUCCESS(Status))
57 {
58 /* Set beep data */
59 BeepSetParameters.Frequency = dwFreq;
60 BeepSetParameters.Duration = dwDuration;
61
62 Status = NtDeviceIoControlFile(hBeep,
63 NULL,
64 NULL,
65 NULL,
66 &IoStatusBlock,
67 IOCTL_BEEP_SET,
68 &BeepSetParameters,
69 sizeof(BEEP_SET_PARAMETERS),
70 NULL,
71 0);
72
73 /* do an alertable wait if necessary */
74 if (NT_SUCCESS(Status) &&
75 (dwFreq != 0x0 || dwDuration != 0x0) && dwDuration != MAXDWORD)
76 {
77 SleepEx(dwDuration,
78 TRUE);
79 }
80
81 NtClose(hBeep);
82 }
83 }
84 else
85 Status = STATUS_INVALID_PARAMETER;
86
87 if (!NT_SUCCESS(Status))
88 {
89 BaseSetLastNTError (Status);
90 return FALSE;
91 }
92
93 return TRUE;
94 }
95
96 /*
97 * @implemented
98 */
99 BOOL
100 WINAPI
101 DeviceIoControl(IN HANDLE hDevice,
102 IN DWORD dwIoControlCode,
103 IN LPVOID lpInBuffer OPTIONAL,
104 IN DWORD nInBufferSize OPTIONAL,
105 OUT LPVOID lpOutBuffer OPTIONAL,
106 IN DWORD nOutBufferSize OPTIONAL,
107 OUT LPDWORD lpBytesReturned OPTIONAL,
108 IN LPOVERLAPPED lpOverlapped OPTIONAL)
109 {
110 BOOL FsIoCtl;
111 NTSTATUS Status;
112 PVOID ApcContext;
113 IO_STATUS_BLOCK Iosb;
114
115 /* Check what kind of IOCTL to send */
116 FsIoCtl = ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM);
117
118 /* CHeck for async */
119 if (lpOverlapped != NULL)
120 {
121 /* Set pending status */
122 lpOverlapped->Internal = STATUS_PENDING;
123
124
125 /* Check if there's an APC context */
126 ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
127
128
129 /* Send file system control? */
130 if (FsIoCtl)
131 {
132 /* Send it */
133 Status = NtFsControlFile(hDevice,
134 lpOverlapped->hEvent,
135 NULL,
136 ApcContext,
137 (PIO_STATUS_BLOCK)lpOverlapped,
138 dwIoControlCode,
139 lpInBuffer,
140 nInBufferSize,
141 lpOutBuffer,
142 nOutBufferSize);
143 }
144 else
145 {
146 /* Otherwise send a device control */
147 Status = NtDeviceIoControlFile(hDevice,
148 lpOverlapped->hEvent,
149 NULL,
150 ApcContext,
151 (PIO_STATUS_BLOCK)lpOverlapped,
152 dwIoControlCode,
153 lpInBuffer,
154 nInBufferSize,
155 lpOutBuffer,
156 nOutBufferSize);
157 }
158
159 /* Check for or information instead of failure */
160 if (!(NT_ERROR(Status)) && (lpBytesReturned))
161 {
162 /* Protect with SEH */
163 _SEH2_TRY
164 {
165 /* Return the bytes */
166 *lpBytesReturned = lpOverlapped->InternalHigh;
167 }
168 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
169 {
170 /* Return zero bytes */
171 *lpBytesReturned = 0;
172 }
173 _SEH2_END;
174 }
175
176 /* Now check for any kind of failure except pending*/
177 if (!(NT_SUCCESS(Status)) || (Status == STATUS_PENDING))
178 {
179 /* Fail */
180 BaseSetLastNTError(Status);
181 return FALSE;
182 }
183 }
184 else
185 {
186 /* Sync case -- send file system code? */
187 if (FsIoCtl)
188 {
189 /* Do it */
190 Status = NtFsControlFile(hDevice,
191 NULL,
192 NULL,
193 NULL,
194 &Iosb,
195 dwIoControlCode,
196 lpInBuffer,
197 nInBufferSize,
198 lpOutBuffer,
199 nOutBufferSize);
200 }
201 else
202 {
203 /* Send device code instead */
204 Status = NtDeviceIoControlFile(hDevice,
205 NULL,
206 NULL,
207 NULL,
208 &Iosb,
209 dwIoControlCode,
210 lpInBuffer,
211 nInBufferSize,
212 lpOutBuffer,
213 nOutBufferSize);
214 }
215
216 /* Now check if the operation isn't done yet */
217 if (Status == STATUS_PENDING)
218 {
219 /* Wait for it and get the final status */
220 Status = NtWaitForSingleObject(hDevice, FALSE, NULL);
221 if (NT_SUCCESS(Status)) Status = Iosb.Status;
222 }
223
224 /* Check for success */
225 if (NT_SUCCESS(Status))
226 {
227 /* Return the byte count */
228 *lpBytesReturned = Iosb.Information;
229 }
230 else
231 {
232 /* Check for informational or warning failure */
233 if (!NT_ERROR(Status)) *lpBytesReturned = Iosb.Information;
234
235 /* Return a failure */
236 BaseSetLastNTError(Status);
237 return FALSE;
238 }
239 }
240
241 /* Return success */
242 return TRUE;
243 }
244
245
246 /*
247 * @implemented
248 */
249 BOOL
250 WINAPI
251 GetOverlappedResult(IN HANDLE hFile,
252 IN LPOVERLAPPED lpOverlapped,
253 OUT LPDWORD lpNumberOfBytesTransferred,
254 IN BOOL bWait)
255 {
256 DWORD WaitStatus;
257 HANDLE hObject;
258
259
260 /* Check for pending operation */
261 if (lpOverlapped->Internal == STATUS_PENDING)
262 {
263 /* Check if the caller is okay with waiting */
264 if (!bWait)
265 {
266 /* Set timeout */
267 WaitStatus = WAIT_TIMEOUT;
268 }
269 else
270 {
271 /* Wait for the result */
272 hObject = lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile;
273 WaitStatus = WaitForSingleObject(hObject, INFINITE);
274 }
275
276
277 /* Check for timeout */
278 if (WaitStatus == WAIT_TIMEOUT)
279 {
280 /* We have to override the last error with INCOMPLETE instead */
281 SetLastError(ERROR_IO_INCOMPLETE);
282 return FALSE;
283 }
284
285
286 /* Fail if we had an error -- the last error is already set */
287 if (WaitStatus != 0) return FALSE;
288 }
289
290
291 /* Return bytes transferred */
292 *lpNumberOfBytesTransferred = lpOverlapped->InternalHigh;
293
294
295 /* Check for failure during I/O */
296 if (!NT_SUCCESS(lpOverlapped->Internal))
297 {
298 /* Set the error and fail */
299 BaseSetLastNTError(lpOverlapped->Internal);
300 return FALSE;
301 }
302
303
304 /* All done */
305 return TRUE;
306 }
307
308 /* EOF */
309