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