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