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