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 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 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 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 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