1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: dll/win32/kernel32/client/file/rw.c 5 * PURPOSE: Read/write functions 6 * PROGRAMMER: Ariadne (ariadne@xs4all.nl) 7 * UPDATE HISTORY: 8 * Created 01/11/98 9 */ 10 11 /* INCLUDES ****************************************************************/ 12 13 #include <k32.h> 14 #define NDEBUG 15 #include <debug.h> 16 DEBUG_CHANNEL(kernel32file); 17 18 /* FUNCTIONS ****************************************************************/ 19 20 /* 21 * @implemented 22 */ 23 BOOL WINAPI 24 WriteFile(IN HANDLE hFile, 25 IN LPCVOID lpBuffer, 26 IN DWORD nNumberOfBytesToWrite OPTIONAL, 27 OUT LPDWORD lpNumberOfBytesWritten, 28 IN LPOVERLAPPED lpOverlapped OPTIONAL) 29 { 30 NTSTATUS Status; 31 32 TRACE("WriteFile(hFile %p)\n", hFile); 33 34 if (lpNumberOfBytesWritten != NULL) *lpNumberOfBytesWritten = 0; 35 36 hFile = TranslateStdHandle(hFile); 37 38 if (IsConsoleHandle(hFile)) 39 { 40 return WriteConsoleA(hFile, 41 lpBuffer, 42 nNumberOfBytesToWrite, 43 lpNumberOfBytesWritten, 44 lpOverlapped); 45 } 46 47 if (lpOverlapped != NULL) 48 { 49 LARGE_INTEGER Offset; 50 PVOID ApcContext; 51 52 Offset.u.LowPart = lpOverlapped->Offset; 53 Offset.u.HighPart = lpOverlapped->OffsetHigh; 54 lpOverlapped->Internal = STATUS_PENDING; 55 ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); 56 57 Status = NtWriteFile(hFile, 58 lpOverlapped->hEvent, 59 NULL, 60 ApcContext, 61 (PIO_STATUS_BLOCK)lpOverlapped, 62 (PVOID)lpBuffer, 63 nNumberOfBytesToWrite, 64 &Offset, 65 NULL); 66 67 /* return FALSE in case of failure and pending operations! */ 68 if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) 69 { 70 BaseSetLastNTError(Status); 71 return FALSE; 72 } 73 74 if (lpNumberOfBytesWritten != NULL) 75 *lpNumberOfBytesWritten = lpOverlapped->InternalHigh; 76 } 77 else 78 { 79 IO_STATUS_BLOCK Iosb; 80 81 Status = NtWriteFile(hFile, 82 NULL, 83 NULL, 84 NULL, 85 &Iosb, 86 (PVOID)lpBuffer, 87 nNumberOfBytesToWrite, 88 NULL, 89 NULL); 90 91 /* Wait in case operation is pending */ 92 if (Status == STATUS_PENDING) 93 { 94 Status = NtWaitForSingleObject(hFile, FALSE, NULL); 95 if (NT_SUCCESS(Status)) Status = Iosb.Status; 96 } 97 98 if (NT_SUCCESS(Status)) 99 { 100 /* 101 * lpNumberOfBytesWritten must not be NULL here, in fact Win doesn't 102 * check that case either and crashes (only after the operation 103 * completed). 104 */ 105 *lpNumberOfBytesWritten = Iosb.Information; 106 } 107 else 108 { 109 BaseSetLastNTError(Status); 110 return FALSE; 111 } 112 } 113 114 TRACE("WriteFile() succeeded\n"); 115 return TRUE; 116 } 117 118 119 /* 120 * @implemented 121 */ 122 BOOL WINAPI 123 ReadFile(IN HANDLE hFile, 124 IN LPVOID lpBuffer, 125 IN DWORD nNumberOfBytesToRead, 126 OUT LPDWORD lpNumberOfBytesRead OPTIONAL, 127 IN LPOVERLAPPED lpOverlapped OPTIONAL) 128 { 129 NTSTATUS Status; 130 131 TRACE("ReadFile(hFile %p)\n", hFile); 132 133 if (lpNumberOfBytesRead != NULL) *lpNumberOfBytesRead = 0; 134 135 hFile = TranslateStdHandle(hFile); 136 137 if (IsConsoleHandle(hFile)) 138 { 139 if (ReadConsoleA(hFile, 140 lpBuffer, 141 nNumberOfBytesToRead, 142 lpNumberOfBytesRead, 143 NULL)) 144 { 145 DWORD dwMode; 146 GetConsoleMode(hFile, &dwMode); 147 if ((dwMode & ENABLE_PROCESSED_INPUT) && *(PCHAR)lpBuffer == 0x1a) 148 { 149 /* EOF character entered; simulate end-of-file */ 150 *lpNumberOfBytesRead = 0; 151 } 152 return TRUE; 153 } 154 return FALSE; 155 } 156 157 if (lpOverlapped != NULL) 158 { 159 LARGE_INTEGER Offset; 160 PVOID ApcContext; 161 162 Offset.u.LowPart = lpOverlapped->Offset; 163 Offset.u.HighPart = lpOverlapped->OffsetHigh; 164 lpOverlapped->Internal = STATUS_PENDING; 165 ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); 166 167 Status = NtReadFile(hFile, 168 lpOverlapped->hEvent, 169 NULL, 170 ApcContext, 171 (PIO_STATUS_BLOCK)lpOverlapped, 172 lpBuffer, 173 nNumberOfBytesToRead, 174 &Offset, 175 NULL); 176 177 /* return FALSE in case of failure and pending operations! */ 178 if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) 179 { 180 if (Status == STATUS_END_OF_FILE && lpNumberOfBytesRead != NULL) 181 *lpNumberOfBytesRead = 0; 182 183 BaseSetLastNTError(Status); 184 return FALSE; 185 } 186 187 if (lpNumberOfBytesRead != NULL) 188 *lpNumberOfBytesRead = lpOverlapped->InternalHigh; 189 } 190 else 191 { 192 IO_STATUS_BLOCK Iosb; 193 194 Status = NtReadFile(hFile, 195 NULL, 196 NULL, 197 NULL, 198 &Iosb, 199 lpBuffer, 200 nNumberOfBytesToRead, 201 NULL, 202 NULL); 203 204 /* Wait in case operation is pending */ 205 if (Status == STATUS_PENDING) 206 { 207 Status = NtWaitForSingleObject(hFile, FALSE, NULL); 208 if (NT_SUCCESS(Status)) Status = Iosb.Status; 209 } 210 211 if (Status == STATUS_END_OF_FILE) 212 { 213 /* 214 * lpNumberOfBytesRead must not be NULL here, in fact Win doesn't 215 * check that case either and crashes (only after the operation 216 * completed). 217 */ 218 *lpNumberOfBytesRead = 0; 219 return TRUE; 220 } 221 222 if (NT_SUCCESS(Status)) 223 { 224 /* 225 * lpNumberOfBytesRead must not be NULL here, in fact Win doesn't 226 * check that case either and crashes (only after the operation 227 * completed). 228 */ 229 *lpNumberOfBytesRead = Iosb.Information; 230 } 231 else 232 { 233 BaseSetLastNTError(Status); 234 return FALSE; 235 } 236 } 237 238 TRACE("ReadFile() succeeded\n"); 239 return TRUE; 240 } 241 242 VOID WINAPI 243 ApcRoutine(PVOID ApcContext, 244 PIO_STATUS_BLOCK IoStatusBlock, 245 ULONG Reserved) 246 { 247 DWORD dwErrorCode; 248 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine = 249 (LPOVERLAPPED_COMPLETION_ROUTINE)ApcContext; 250 251 dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status); 252 lpCompletionRoutine(dwErrorCode, 253 IoStatusBlock->Information, 254 (LPOVERLAPPED)IoStatusBlock); 255 } 256 257 258 /* 259 * @implemented 260 */ 261 BOOL WINAPI 262 WriteFileEx(IN HANDLE hFile, 263 IN LPCVOID lpBuffer, 264 IN DWORD nNumberOfBytesToWrite OPTIONAL, 265 IN LPOVERLAPPED lpOverlapped, 266 IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 267 { 268 LARGE_INTEGER Offset; 269 NTSTATUS Status; 270 271 Offset.u.LowPart = lpOverlapped->Offset; 272 Offset.u.HighPart = lpOverlapped->OffsetHigh; 273 lpOverlapped->Internal = STATUS_PENDING; 274 275 Status = NtWriteFile(hFile, 276 NULL, 277 ApcRoutine, 278 lpCompletionRoutine, 279 (PIO_STATUS_BLOCK)lpOverlapped, 280 (PVOID)lpBuffer, 281 nNumberOfBytesToWrite, 282 &Offset, 283 NULL); 284 285 if (!NT_SUCCESS(Status)) 286 { 287 BaseSetLastNTError(Status); 288 return FALSE; 289 } 290 291 return TRUE; 292 } 293 294 295 /* 296 * @implemented 297 */ 298 BOOL WINAPI 299 ReadFileEx(IN HANDLE hFile, 300 IN LPVOID lpBuffer, 301 IN DWORD nNumberOfBytesToRead OPTIONAL, 302 IN LPOVERLAPPED lpOverlapped, 303 IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 304 { 305 LARGE_INTEGER Offset; 306 NTSTATUS Status; 307 308 Offset.u.LowPart = lpOverlapped->Offset; 309 Offset.u.HighPart = lpOverlapped->OffsetHigh; 310 lpOverlapped->Internal = STATUS_PENDING; 311 312 Status = NtReadFile(hFile, 313 NULL, 314 ApcRoutine, 315 lpCompletionRoutine, 316 (PIO_STATUS_BLOCK)lpOverlapped, 317 lpBuffer, 318 nNumberOfBytesToRead, 319 &Offset, 320 NULL); 321 322 if (!NT_SUCCESS(Status)) 323 { 324 BaseSetLastNTError(Status); 325 return FALSE; 326 } 327 328 return TRUE; 329 } 330 331 332 /* 333 * @implemented 334 */ 335 BOOL 336 WINAPI 337 ReadFileScatter(HANDLE hFile, 338 FILE_SEGMENT_ELEMENT aSegmentArray[], 339 DWORD nNumberOfBytesToRead, 340 LPDWORD lpReserved, 341 LPOVERLAPPED lpOverlapped) 342 { 343 PIO_STATUS_BLOCK pIOStatus; 344 LARGE_INTEGER Offset; 345 NTSTATUS Status; 346 347 DPRINT("(%p %p %u %p)\n", hFile, aSegmentArray, nNumberOfBytesToRead, lpOverlapped); 348 349 Offset.LowPart = lpOverlapped->Offset; 350 Offset.HighPart = lpOverlapped->OffsetHigh; 351 pIOStatus = (PIO_STATUS_BLOCK) lpOverlapped; 352 pIOStatus->Status = STATUS_PENDING; 353 pIOStatus->Information = 0; 354 355 Status = NtReadFileScatter(hFile, 356 NULL, 357 NULL, 358 NULL, 359 pIOStatus, 360 aSegmentArray, 361 nNumberOfBytesToRead, 362 &Offset, 363 NULL); 364 365 if (!NT_SUCCESS(Status)) 366 { 367 SetLastError(RtlNtStatusToDosError(Status)); 368 return FALSE; 369 } 370 371 return TRUE; 372 } 373 374 /* 375 * @implemented 376 */ 377 BOOL 378 WINAPI 379 WriteFileGather(HANDLE hFile, 380 FILE_SEGMENT_ELEMENT aSegmentArray[], 381 DWORD nNumberOfBytesToWrite, 382 LPDWORD lpReserved, 383 LPOVERLAPPED lpOverlapped) 384 { 385 PIO_STATUS_BLOCK IOStatus; 386 LARGE_INTEGER Offset; 387 NTSTATUS Status; 388 389 DPRINT("%p %p %u %p\n", hFile, aSegmentArray, nNumberOfBytesToWrite, lpOverlapped); 390 391 Offset.LowPart = lpOverlapped->Offset; 392 Offset.HighPart = lpOverlapped->OffsetHigh; 393 IOStatus = (PIO_STATUS_BLOCK) lpOverlapped; 394 IOStatus->Status = STATUS_PENDING; 395 IOStatus->Information = 0; 396 397 Status = NtWriteFileGather(hFile, 398 NULL, 399 NULL, 400 NULL, 401 IOStatus, 402 aSegmentArray, 403 nNumberOfBytesToWrite, 404 &Offset, 405 NULL); 406 407 if (!NT_SUCCESS(Status)) 408 { 409 SetLastError(RtlNtStatusToDosError(Status)); 410 return FALSE; 411 } 412 413 return TRUE; 414 } 415 416 /* EOF */ 417