[KERNEL32]
[reactos.git] / reactos / dll / win32 / kernel32 / client / file / rw.c
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 OPTIONAL,
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 */