28eab558ba1290abf00e5ae35839a37b49f99a4a
[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 VOID
18 WINAPI
19 NotifySoundSentry(VOID)
20 {
21 CSR_API_MESSAGE ApiMessage;
22
23 /* Get the video mode */
24 if (!GetConsoleDisplayMode(&ApiMessage.Data.SoundSentryRequest.VideoMode))
25 {
26 ApiMessage.Data.SoundSentryRequest.VideoMode = 0;
27 }
28
29 /* Make sure it's not fullscreen, and send the message if not */
30 if (ApiMessage.Data.SoundSentryRequest.VideoMode == 0)
31 {
32 CsrClientCallServer(&ApiMessage,
33 NULL,
34 CSR_CREATE_API_NUMBER(CSR_NATIVE, SOUND_SENTRY),
35 sizeof(CSR_API_MESSAGE));
36 }
37 }
38
39 /*
40 * @implemented
41 */
42 BOOL
43 WINAPI
44 Beep(IN DWORD dwFreq,
45 IN DWORD dwDuration)
46 {
47 HANDLE hBeep;
48 UNICODE_STRING BeepDevice;
49 OBJECT_ATTRIBUTES ObjectAttributes;
50 IO_STATUS_BLOCK IoStatusBlock;
51 BEEP_SET_PARAMETERS BeepSetParameters;
52 NTSTATUS Status;
53
54 //
55 // On TS systems, we need to Load Winsta.dll and call WinstationBeepOpen
56 // after doing a GetProcAddress for it
57 //
58
59 /* Open the device */
60 RtlInitUnicodeString(&BeepDevice, L"\\Device\\Beep");
61 InitializeObjectAttributes(&ObjectAttributes, &BeepDevice, 0, NULL, NULL);
62 Status = NtCreateFile(&hBeep,
63 FILE_READ_DATA | FILE_WRITE_DATA,
64 &ObjectAttributes,
65 &IoStatusBlock,
66 NULL,
67 0,
68 FILE_SHARE_READ | FILE_SHARE_WRITE,
69 FILE_OPEN_IF,
70 0,
71 NULL,
72 0);
73 if (!NT_SUCCESS(Status))
74 {
75 BaseSetLastNTError(Status);
76 return FALSE;
77 }
78
79 /* check the parameters */
80 if ((dwFreq >= 0x25 && dwFreq <= 0x7FFF) ||
81 (dwFreq == 0x0 && dwDuration == 0x0))
82 {
83 /* Set beep data */
84 BeepSetParameters.Frequency = dwFreq;
85 BeepSetParameters.Duration = dwDuration;
86
87 /* Send the beep */
88 Status = NtDeviceIoControlFile(hBeep,
89 NULL,
90 NULL,
91 NULL,
92 &IoStatusBlock,
93 IOCTL_BEEP_SET,
94 &BeepSetParameters,
95 sizeof(BeepSetParameters),
96 NULL,
97 0);
98 }
99 else
100 {
101 /* We'll fail the call, but still notify the sound sentry */
102 Status = STATUS_INVALID_PARAMETER;
103 }
104
105 /* Notify the sound sentry */
106 NotifySoundSentry();
107
108 /* Bail out if the hardware beep failed */
109 if (!NT_SUCCESS(Status))
110 {
111 NtClose(hBeep);
112 BaseSetLastNTError(Status);
113 return FALSE;
114 }
115
116 /* If an actual beep was emitted, wait for it */
117 if (((dwFreq != 0x0) || (dwDuration != 0x0)) && (dwDuration != MAXDWORD))
118 {
119 SleepEx(dwDuration, TRUE);
120 }
121
122 /* Close the handle and return success */
123 NtClose(hBeep);
124 return TRUE;
125 }
126
127 /*
128 * @implemented
129 */
130 BOOL
131 WINAPI
132 DeviceIoControl(IN HANDLE hDevice,
133 IN DWORD dwIoControlCode,
134 IN LPVOID lpInBuffer OPTIONAL,
135 IN DWORD nInBufferSize OPTIONAL,
136 OUT LPVOID lpOutBuffer OPTIONAL,
137 IN DWORD nOutBufferSize OPTIONAL,
138 OUT LPDWORD lpBytesReturned OPTIONAL,
139 IN LPOVERLAPPED lpOverlapped OPTIONAL)
140 {
141 BOOL FsIoCtl;
142 NTSTATUS Status;
143 PVOID ApcContext;
144 IO_STATUS_BLOCK Iosb;
145
146 //
147 // Note: on a TS Machine, we should call IsTSAppCompatEnabled and unless the
148 // IOCTLs are IOCTL_STORAGE_EJECT_MEDIA, IOCTL_DISK_EJECT_MEDIA, FSCTL_DISMOUNT_VOLUME
149 // we should call IsCallerAdminOrSystem and return STATUS_ACCESS_DENIED for
150 // any other IOCTLs.
151 //
152
153 /* Check what kind of IOCTL to send */
154 FsIoCtl = ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM);
155
156 /* CHeck for async */
157 if (lpOverlapped != NULL)
158 {
159 /* Set pending status */
160 lpOverlapped->Internal = STATUS_PENDING;
161
162 /* Check if there's an APC context */
163 ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
164
165 /* Send file system control? */
166 if (FsIoCtl)
167 {
168 /* Send it */
169 Status = NtFsControlFile(hDevice,
170 lpOverlapped->hEvent,
171 NULL,
172 ApcContext,
173 (PIO_STATUS_BLOCK)lpOverlapped,
174 dwIoControlCode,
175 lpInBuffer,
176 nInBufferSize,
177 lpOutBuffer,
178 nOutBufferSize);
179 }
180 else
181 {
182 /* Otherwise send a device control */
183 Status = NtDeviceIoControlFile(hDevice,
184 lpOverlapped->hEvent,
185 NULL,
186 ApcContext,
187 (PIO_STATUS_BLOCK)lpOverlapped,
188 dwIoControlCode,
189 lpInBuffer,
190 nInBufferSize,
191 lpOutBuffer,
192 nOutBufferSize);
193 }
194
195 /* Check for or information instead of failure */
196 if (!(NT_ERROR(Status)) && (lpBytesReturned))
197 {
198 /* Protect with SEH */
199 _SEH2_TRY
200 {
201 /* Return the bytes */
202 *lpBytesReturned = lpOverlapped->InternalHigh;
203 }
204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
205 {
206 /* Return zero bytes */
207 *lpBytesReturned = 0;
208 }
209 _SEH2_END;
210 }
211
212 /* Now check for any kind of failure except pending*/
213 if (!(NT_SUCCESS(Status)) || (Status == STATUS_PENDING))
214 {
215 /* Fail */
216 BaseSetLastNTError(Status);
217 return FALSE;
218 }
219 }
220 else
221 {
222 /* Sync case -- send file system code? */
223 if (FsIoCtl)
224 {
225 /* Do it */
226 Status = NtFsControlFile(hDevice,
227 NULL,
228 NULL,
229 NULL,
230 &Iosb,
231 dwIoControlCode,
232 lpInBuffer,
233 nInBufferSize,
234 lpOutBuffer,
235 nOutBufferSize);
236 }
237 else
238 {
239 /* Send device code instead */
240 Status = NtDeviceIoControlFile(hDevice,
241 NULL,
242 NULL,
243 NULL,
244 &Iosb,
245 dwIoControlCode,
246 lpInBuffer,
247 nInBufferSize,
248 lpOutBuffer,
249 nOutBufferSize);
250 }
251
252 /* Now check if the operation isn't done yet */
253 if (Status == STATUS_PENDING)
254 {
255 /* Wait for it and get the final status */
256 Status = NtWaitForSingleObject(hDevice, FALSE, NULL);
257 if (NT_SUCCESS(Status)) Status = Iosb.Status;
258 }
259
260 /* Check for success */
261 if (NT_SUCCESS(Status))
262 {
263 /* Return the byte count */
264 *lpBytesReturned = Iosb.Information;
265 }
266 else
267 {
268 /* Check for informational or warning failure */
269 if (!NT_ERROR(Status)) *lpBytesReturned = Iosb.Information;
270
271 /* Return a failure */
272 BaseSetLastNTError(Status);
273 return FALSE;
274 }
275 }
276
277 /* Return success */
278 return TRUE;
279 }
280
281 /*
282 * @implemented
283 */
284 BOOL
285 WINAPI
286 CancelIo(IN HANDLE hFile)
287 {
288 IO_STATUS_BLOCK IoStatusBlock;
289 NTSTATUS Status;
290
291 Status = NtCancelIoFile(hFile, &IoStatusBlock);
292 if (!NT_SUCCESS(Status))
293 {
294 BaseSetLastNTError(Status);
295 return FALSE;
296 }
297
298 return TRUE;
299 }
300
301 /* EOF */