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