Sync with trunk r43000
[reactos.git] / reactos / 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 #include <wine/debug.h>
16
17 WINE_DEFAULT_DEBUG_CHANNEL(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((ULONG_PTR)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 hFile = TranslateStdHandle(hFile);
148
149 if (IsConsoleHandle(hFile))
150 {
151 if (ReadConsoleA(hFile,
152 lpBuffer,
153 nNumberOfBytesToRead,
154 lpNumberOfBytesRead,
155 NULL))
156 {
157 DWORD dwMode;
158 GetConsoleMode(hFile, &dwMode);
159 if ((dwMode & ENABLE_PROCESSED_INPUT) && *(char *)lpBuffer == 0x1a)
160 {
161 /* EOF character entered; simulate end-of-file */
162 *lpNumberOfBytesRead = 0;
163 }
164 return TRUE;
165 }
166 return FALSE;
167 }
168
169 if (lpOverlapped != NULL)
170 {
171 LARGE_INTEGER Offset;
172 PVOID ApcContext;
173
174 Offset.u.LowPart = lpOverlapped->Offset;
175 Offset.u.HighPart = lpOverlapped->OffsetHigh;
176 lpOverlapped->Internal = STATUS_PENDING;
177 ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
178
179 Status = NtReadFile(hFile,
180 lpOverlapped->hEvent,
181 NULL,
182 ApcContext,
183 (PIO_STATUS_BLOCK)lpOverlapped,
184 lpBuffer,
185 nNumberOfBytesToRead,
186 &Offset,
187 NULL);
188
189 /* return FALSE in case of failure and pending operations! */
190 if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
191 {
192 if (Status == STATUS_END_OF_FILE &&
193 lpNumberOfBytesRead != NULL)
194 {
195 *lpNumberOfBytesRead = 0;
196 }
197
198 SetLastErrorByStatus(Status);
199 return FALSE;
200 }
201
202 if (lpNumberOfBytesRead != NULL)
203 {
204 *lpNumberOfBytesRead = lpOverlapped->InternalHigh;
205 }
206 }
207 else
208 {
209 IO_STATUS_BLOCK Iosb;
210
211 Status = NtReadFile(hFile,
212 NULL,
213 NULL,
214 NULL,
215 &Iosb,
216 lpBuffer,
217 nNumberOfBytesToRead,
218 NULL,
219 NULL);
220
221 /* wait in case operation is pending */
222 if (Status == STATUS_PENDING)
223 {
224 Status = NtWaitForSingleObject(hFile,
225 FALSE,
226 NULL);
227 if (NT_SUCCESS(Status))
228 {
229 Status = Iosb.Status;
230 }
231 }
232
233 if (Status == STATUS_END_OF_FILE)
234 {
235 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
236 check that case either and crashes (only after the operation
237 completed) */
238 *lpNumberOfBytesRead = 0;
239 return TRUE;
240 }
241
242 if (NT_SUCCESS(Status))
243 {
244 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
245 check that case either and crashes (only after the operation
246 completed) */
247 *lpNumberOfBytesRead = Iosb.Information;
248 }
249 else
250 {
251 SetLastErrorByStatus(Status);
252 return FALSE;
253 }
254 }
255
256 TRACE("ReadFile() succeeded\n");
257 return TRUE;
258 }
259
260 VOID WINAPI
261 ApcRoutine(PVOID ApcContext,
262 struct _IO_STATUS_BLOCK* IoStatusBlock,
263 ULONG Reserved)
264 {
265 DWORD dwErrorCode;
266 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine =
267 (LPOVERLAPPED_COMPLETION_ROUTINE)ApcContext;
268
269 dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status);
270 lpCompletionRoutine(dwErrorCode,
271 IoStatusBlock->Information,
272 (LPOVERLAPPED)IoStatusBlock);
273 }
274
275
276 /*
277 * @implemented
278 */
279 BOOL WINAPI
280 WriteFileEx(IN HANDLE hFile,
281 IN LPCVOID lpBuffer,
282 IN DWORD nNumberOfBytesToWrite OPTIONAL,
283 IN LPOVERLAPPED lpOverlapped,
284 IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
285 {
286 LARGE_INTEGER Offset;
287 NTSTATUS Status;
288
289 Offset.u.LowPart = lpOverlapped->Offset;
290 Offset.u.HighPart = lpOverlapped->OffsetHigh;
291 lpOverlapped->Internal = STATUS_PENDING;
292
293 Status = NtWriteFile(hFile,
294 NULL,
295 ApcRoutine,
296 lpCompletionRoutine,
297 (PIO_STATUS_BLOCK)lpOverlapped,
298 (PVOID)lpBuffer,
299 nNumberOfBytesToWrite,
300 &Offset,
301 NULL);
302
303 if (!NT_SUCCESS(Status))
304 {
305 SetLastErrorByStatus(Status);
306 return FALSE;
307 }
308
309 return TRUE;
310 }
311
312
313 /*
314 * @implemented
315 */
316 BOOL WINAPI
317 ReadFileEx(IN HANDLE hFile,
318 IN LPVOID lpBuffer,
319 IN DWORD nNumberOfBytesToRead OPTIONAL,
320 IN LPOVERLAPPED lpOverlapped,
321 IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
322 {
323 LARGE_INTEGER Offset;
324 NTSTATUS Status;
325
326 Offset.u.LowPart = lpOverlapped->Offset;
327 Offset.u.HighPart = lpOverlapped->OffsetHigh;
328 lpOverlapped->Internal = STATUS_PENDING;
329
330 Status = NtReadFile(hFile,
331 NULL,
332 ApcRoutine,
333 lpCompletionRoutine,
334 (PIO_STATUS_BLOCK)lpOverlapped,
335 lpBuffer,
336 nNumberOfBytesToRead,
337 &Offset,
338 NULL);
339
340 if (!NT_SUCCESS(Status))
341 {
342 SetLastErrorByStatus(Status);
343 return FALSE;
344 }
345
346 return TRUE;
347 }
348
349 /* EOF */