2004-08-15 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / ntoskrnl / io / rw.c
1 /* $Id: rw.c,v 1.54 2004/08/15 16:39:03 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/rw.c
6 * PURPOSE: Implements read/write APIs
7 * PROGRAMMER: David Welch (welch@cwcom.net)
8 * UPDATE HISTORY:
9 * 30/05/98: Created
10 */
11
12 /* INCLUDES ****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* FUNCTIONS ***************************************************************/
19
20
21 /**********************************************************************
22 * NAME EXPORTED
23 * NtReadFile
24 *
25 * DESCRIPTION
26 *
27 * ARGUMENTS
28 *
29 * RETURN VALUE
30 *
31 * REVISIONS
32 *
33 * @implemented
34 */
35 NTSTATUS STDCALL
36 NtReadFile (IN HANDLE FileHandle,
37 IN HANDLE Event OPTIONAL,
38 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
39 IN PVOID ApcContext OPTIONAL,
40 OUT PIO_STATUS_BLOCK IoStatusBlock,
41 OUT PVOID Buffer,
42 IN ULONG Length,
43 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
44 IN PULONG Key OPTIONAL)
45 {
46 NTSTATUS Status;
47 PFILE_OBJECT FileObject;
48 PIRP Irp;
49 PIO_STACK_LOCATION StackPtr;
50 KPROCESSOR_MODE PreviousMode;
51 PKEVENT EventObject = NULL;
52
53 DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
54 "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
55 IoStatusBlock);
56
57 if (IoStatusBlock == NULL)
58 return STATUS_ACCESS_VIOLATION;
59
60 PreviousMode = ExGetPreviousMode();
61
62 Status = ObReferenceObjectByHandle(FileHandle,
63 FILE_READ_DATA,
64 IoFileObjectType,
65 PreviousMode,
66 (PVOID*)&FileObject,
67 NULL);
68 if (!NT_SUCCESS(Status))
69 {
70 return(Status);
71 }
72
73 if (ByteOffset == NULL)
74 {
75 /* a valid ByteOffset is required if asynch. op. */
76 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
77 {
78 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
79 ObDereferenceObject(FileObject);
80 return STATUS_INVALID_PARAMETER;
81 }
82
83 ByteOffset = &FileObject->CurrentByteOffset;
84 }
85
86 if (Event != NULL)
87 {
88 Status = ObReferenceObjectByHandle(Event,
89 SYNCHRONIZE,
90 ExEventObjectType,
91 PreviousMode,
92 (PVOID*)&EventObject,
93 NULL);
94 if (!NT_SUCCESS(Status))
95 {
96 ObDereferenceObject(FileObject);
97 return(Status);
98 }
99 KeClearEvent(EventObject);
100 }
101
102 KeClearEvent(&FileObject->Event);
103
104 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
105 FileObject->DeviceObject,
106 Buffer,
107 Length,
108 ByteOffset,
109 EventObject,
110 IoStatusBlock);
111
112 /* Trigger FileObject/Event dereferencing */
113 Irp->Tail.Overlay.OriginalFileObject = FileObject;
114
115 Irp->RequestorMode = PreviousMode;
116
117 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
118 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
119
120 StackPtr = IoGetNextIrpStackLocation(Irp);
121 StackPtr->FileObject = FileObject;
122 StackPtr->Parameters.Read.Key = Key ? *Key : 0;
123
124 Status = IoCallDriver(FileObject->DeviceObject, Irp);
125 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
126 {
127 Status = KeWaitForSingleObject (&FileObject->Event,
128 Executive,
129 PreviousMode,
130 FileObject->Flags & FO_ALERTABLE_IO,
131 NULL);
132
133 if (Status != STATUS_WAIT_0)
134 {
135 /* Wait failed. */
136 return(Status);
137 }
138
139 Status = IoStatusBlock->Status;
140 }
141
142 return Status;
143 }
144
145
146 /**********************************************************************
147 * NAME EXPORTED
148 * NtWriteFile
149 *
150 * DESCRIPTION
151 *
152 * ARGUMENTS
153 *
154 * RETURN VALUE
155 *
156 * REVISIONS
157 *
158 * @implemented
159 */
160 NTSTATUS STDCALL
161 NtWriteFile (IN HANDLE FileHandle,
162 IN HANDLE Event OPTIONAL,
163 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
164 IN PVOID ApcContext OPTIONAL,
165 OUT PIO_STATUS_BLOCK IoStatusBlock,
166 IN PVOID Buffer,
167 IN ULONG Length,
168 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
169 IN PULONG Key OPTIONAL)
170 {
171 NTSTATUS Status;
172 PFILE_OBJECT FileObject;
173 PIRP Irp;
174 PIO_STACK_LOCATION StackPtr;
175 KPROCESSOR_MODE PreviousMode;
176 PKEVENT EventObject = NULL;
177
178 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
179 "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
180 IoStatusBlock);
181
182 if (IoStatusBlock == NULL)
183 return STATUS_ACCESS_VIOLATION;
184
185 PreviousMode = ExGetPreviousMode();
186
187 Status = ObReferenceObjectByHandle(FileHandle,
188 FILE_WRITE_DATA,
189 IoFileObjectType,
190 PreviousMode,
191 (PVOID*)&FileObject,
192 NULL);
193 if (!NT_SUCCESS(Status))
194 {
195 return(Status);
196 }
197
198 if (ByteOffset == NULL)
199 {
200 /* a valid ByteOffset is required if asynch. op. */
201 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
202 {
203 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
204 ObDereferenceObject(FileObject);
205 return STATUS_INVALID_PARAMETER;
206 }
207
208 ByteOffset = &FileObject->CurrentByteOffset;
209 }
210
211 if (Event != NULL)
212 {
213 Status = ObReferenceObjectByHandle(Event,
214 SYNCHRONIZE,
215 ExEventObjectType,
216 PreviousMode,
217 (PVOID*)&EventObject,
218 NULL);
219
220 if (!NT_SUCCESS(Status))
221 {
222 ObDereferenceObject(FileObject);
223 return(Status);
224 }
225
226 KeClearEvent(EventObject);
227 }
228
229 KeClearEvent(&FileObject->Event);
230
231 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
232 FileObject->DeviceObject,
233 Buffer,
234 Length,
235 ByteOffset,
236 EventObject,
237 IoStatusBlock);
238
239 /* Trigger FileObject/Event dereferencing */
240 Irp->Tail.Overlay.OriginalFileObject = FileObject;
241
242 Irp->RequestorMode = PreviousMode;
243
244 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
245 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
246
247 StackPtr = IoGetNextIrpStackLocation(Irp);
248 StackPtr->FileObject = FileObject;
249 StackPtr->Parameters.Write.Key = Key ? *Key : 0;
250
251 Status = IoCallDriver(FileObject->DeviceObject, Irp);
252 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
253 {
254 Status = KeWaitForSingleObject (&FileObject->Event,
255 Executive,
256 PreviousMode,
257 FileObject->Flags & FO_ALERTABLE_IO,
258 NULL);
259 if (Status != STATUS_WAIT_0)
260 {
261 /* Wait failed. */
262 return(Status);
263 }
264
265 Status = IoStatusBlock->Status;
266 }
267
268 return Status;
269 }
270
271
272 /**********************************************************************
273 * NAME EXPORTED
274 * NtReadFileScatter
275 *
276 * DESCRIPTION
277 *
278 * ARGUMENTS
279 *
280 * RETURN VALUE
281 *
282 * REVISIONS
283 */
284 NTSTATUS
285 STDCALL
286 NtReadFileScatter (
287 IN HANDLE FileHandle,
288 IN HANDLE Event OPTIONAL,
289 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
290 IN PVOID UserApcContext OPTIONAL,
291 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
292 IN FILE_SEGMENT_ELEMENT BufferDescription [],
293 IN ULONG BufferLength,
294 IN PLARGE_INTEGER ByteOffset,
295 IN PULONG Key OPTIONAL
296 )
297 {
298 UNIMPLEMENTED;
299 return(STATUS_NOT_IMPLEMENTED);
300 }
301
302
303 /**********************************************************************
304 * NAME EXPORTED
305 * NtWriteFileGather
306 *
307 * DESCRIPTION
308 *
309 * ARGUMENTS
310 *
311 * RETURN VALUE
312 *
313 * REVISIONS
314 */
315 NTSTATUS
316 STDCALL
317 NtWriteFileGather (
318 IN HANDLE FileHandle,
319 IN HANDLE Event OPTIONAL,
320 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
321 IN PVOID ApcContext OPTIONAL,
322 OUT PIO_STATUS_BLOCK IoStatusBlock,
323 IN FILE_SEGMENT_ELEMENT BufferDescription [],
324 IN ULONG BufferLength,
325 IN PLARGE_INTEGER ByteOffset,
326 IN PULONG Key OPTIONAL
327 )
328 {
329 UNIMPLEMENTED;
330 return(STATUS_NOT_IMPLEMENTED);
331 }
332
333
334 /* EOF */