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)
9 /* INCLUDES *******************************************************************/
18 /* FUNCTIONS ******************************************************************/
22 NotifySoundSentry(VOID
)
24 BASE_API_MESSAGE ApiMessage
;
25 PBASE_SOUND_SENTRY SoundSentryRequest
= &ApiMessage
.Data
.SoundSentryRequest
;
27 /* Get the video mode */
28 if (!GetConsoleDisplayMode(&SoundSentryRequest
->VideoMode
))
30 SoundSentryRequest
->VideoMode
= 0;
33 /* Make sure it's not fullscreen, and send the message if not */
34 if (SoundSentryRequest
->VideoMode
== 0)
36 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
38 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepSoundSentryNotification
),
39 sizeof(BASE_SOUND_SENTRY
));
52 UNICODE_STRING BeepDevice
;
53 OBJECT_ATTRIBUTES ObjectAttributes
;
54 IO_STATUS_BLOCK IoStatusBlock
;
55 BEEP_SET_PARAMETERS BeepSetParameters
;
59 // On TS systems, we need to Load Winsta.dll and call WinstationBeepOpen
60 // after doing a GetProcAddress for it
64 RtlInitUnicodeString(&BeepDevice
, L
"\\Device\\Beep");
65 InitializeObjectAttributes(&ObjectAttributes
, &BeepDevice
, 0, NULL
, NULL
);
66 Status
= NtCreateFile(&hBeep
,
67 FILE_READ_DATA
| FILE_WRITE_DATA
,
72 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
77 if (!NT_SUCCESS(Status
))
79 BaseSetLastNTError(Status
);
83 /* check the parameters */
84 if ((dwFreq
>= 0x25 && dwFreq
<= 0x7FFF) ||
85 (dwFreq
== 0x0 && dwDuration
== 0x0))
88 BeepSetParameters
.Frequency
= dwFreq
;
89 BeepSetParameters
.Duration
= dwDuration
;
92 Status
= NtDeviceIoControlFile(hBeep
,
99 sizeof(BeepSetParameters
),
105 /* We'll fail the call, but still notify the sound sentry */
106 Status
= STATUS_INVALID_PARAMETER
;
109 /* Notify the sound sentry */
112 /* Bail out if the hardware beep failed */
113 if (!NT_SUCCESS(Status
))
116 BaseSetLastNTError(Status
);
120 /* If an actual beep was emitted, wait for it */
121 if (((dwFreq
!= 0x0) || (dwDuration
!= 0x0)) && (dwDuration
!= MAXDWORD
))
123 SleepEx(dwDuration
, TRUE
);
126 /* Close the handle and return success */
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
)
148 IO_STATUS_BLOCK Iosb
;
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
157 /* Check what kind of IOCTL to send */
158 FsIoCtl
= ((dwIoControlCode
>> 16) == FILE_DEVICE_FILE_SYSTEM
);
160 /* CHeck for async */
161 if (lpOverlapped
!= NULL
)
163 /* Set pending status */
164 lpOverlapped
->Internal
= STATUS_PENDING
;
166 /* Check if there's an APC context */
167 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
169 /* Send file system control? */
173 Status
= NtFsControlFile(hDevice
,
174 lpOverlapped
->hEvent
,
177 (PIO_STATUS_BLOCK
)lpOverlapped
,
186 /* Otherwise send a device control */
187 Status
= NtDeviceIoControlFile(hDevice
,
188 lpOverlapped
->hEvent
,
191 (PIO_STATUS_BLOCK
)lpOverlapped
,
199 /* Check for or information instead of failure */
200 if (!(NT_ERROR(Status
)) && (lpBytesReturned
))
202 /* Protect with SEH */
205 /* Return the bytes */
206 *lpBytesReturned
= lpOverlapped
->InternalHigh
;
208 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
210 /* Return zero bytes */
211 *lpBytesReturned
= 0;
216 /* Now check for any kind of failure except pending*/
217 if (!(NT_SUCCESS(Status
)) || (Status
== STATUS_PENDING
))
220 BaseSetLastNTError(Status
);
226 /* Sync case -- send file system code? */
230 Status
= NtFsControlFile(hDevice
,
243 /* Send device code instead */
244 Status
= NtDeviceIoControlFile(hDevice
,
256 /* Now check if the operation isn't done yet */
257 if (Status
== STATUS_PENDING
)
259 /* Wait for it and get the final status */
260 Status
= NtWaitForSingleObject(hDevice
, FALSE
, NULL
);
261 if (NT_SUCCESS(Status
)) Status
= Iosb
.Status
;
264 /* Check for success */
265 if (NT_SUCCESS(Status
))
267 /* Return the byte count */
268 *lpBytesReturned
= Iosb
.Information
;
272 /* Check for informational or warning failure */
273 if (!NT_ERROR(Status
)) *lpBytesReturned
= Iosb
.Information
;
275 /* Return a failure */
276 BaseSetLastNTError(Status
);
290 CancelIo(IN HANDLE hFile
)
292 IO_STATUS_BLOCK IoStatusBlock
;
295 Status
= NtCancelIoFile(hFile
, &IoStatusBlock
);
296 if (!NT_SUCCESS(Status
))
298 BaseSetLastNTError(Status
);