Reworked quite a bit of IO manager code to fix several bugs:
[reactos.git] / reactos / ntoskrnl / io / file.c
1 /* $Id: file.c,v 1.16 2002/04/07 18:36:13 phreak Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/file.c
6 * PURPOSE: Graceful system shutdown if a bug is detected
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/io.h>
16 #include <internal/mm.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21
22 /* GLOBALS *******************************************************************/
23
24 #define TAG_SYSB TAG('S', 'Y', 'S', 'B')
25
26
27 /* FUNCTIONS *****************************************************************/
28
29 NTSTATUS STDCALL
30 NtQueryInformationFile(HANDLE FileHandle,
31 PIO_STATUS_BLOCK IoStatusBlock,
32 PVOID FileInformation,
33 ULONG Length,
34 FILE_INFORMATION_CLASS FileInformationClass)
35 {
36 PFILE_OBJECT FileObject;
37 NTSTATUS Status;
38 PIRP Irp;
39 PDEVICE_OBJECT DeviceObject;
40 PIO_STACK_LOCATION StackPtr;
41 PVOID SystemBuffer;
42 IO_STATUS_BLOCK IoSB;
43
44 assert(IoStatusBlock != NULL);
45 assert(FileInformation != NULL);
46
47 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d Class %d)\n",
48 FileHandle,
49 IoStatusBlock,
50 FileInformation,
51 Length,
52 FileInformationClass);
53
54 Status = ObReferenceObjectByHandle(FileHandle,
55 FILE_READ_ATTRIBUTES,
56 IoFileObjectType,
57 UserMode,
58 (PVOID *)&FileObject,
59 NULL);
60 if (!NT_SUCCESS(Status))
61 {
62 return(Status);
63 }
64 DPRINT("FileObject %x\n", FileObject);
65
66 DeviceObject = FileObject->DeviceObject;
67
68 Irp = IoAllocateIrp(DeviceObject->StackSize,
69 TRUE);
70 if (Irp == NULL)
71 {
72 ObDereferenceObject(FileObject);
73 return STATUS_INSUFFICIENT_RESOURCES;
74 }
75
76 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
77 Length,
78 TAG_SYSB);
79 if (SystemBuffer == NULL)
80 {
81 IoFreeIrp(Irp);
82 ObDereferenceObject(FileObject);
83 return(STATUS_INSUFFICIENT_RESOURCES);
84 }
85
86 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
87 Irp->UserIosb = &IoSB;
88 Irp->UserEvent = &FileObject->Event;
89 KeResetEvent( &FileObject->Event );
90
91 StackPtr = IoGetNextIrpStackLocation(Irp);
92 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
93 StackPtr->MinorFunction = 0;
94 StackPtr->Flags = 0;
95 StackPtr->Control = 0;
96 StackPtr->DeviceObject = DeviceObject;
97 StackPtr->FileObject = FileObject;
98
99 StackPtr->Parameters.QueryFile.FileInformationClass =
100 FileInformationClass;
101 StackPtr->Parameters.QueryFile.Length = Length;
102
103 Status = IoCallDriver(FileObject->DeviceObject,
104 Irp);
105 if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
106 {
107 KeWaitForSingleObject(&FileObject->Event,
108 Executive,
109 KernelMode,
110 FALSE,
111 NULL);
112 Status = IoSB.Status;
113 }
114 if (IoStatusBlock)
115 {
116 *IoStatusBlock = IoSB;
117 }
118
119 if (NT_SUCCESS(Status))
120 {
121 DPRINT("Information %lu\n", IoStatusBlock->Information);
122 MmSafeCopyToUser(FileInformation,
123 SystemBuffer,
124 IoStatusBlock->Information);
125 }
126
127 ExFreePool(SystemBuffer);
128 ObDereferenceObject(FileObject);
129
130 return(Status);
131 }
132
133
134 NTSTATUS STDCALL
135 IoQueryFileInformation(IN PFILE_OBJECT FileObject,
136 IN FILE_INFORMATION_CLASS FileInformationClass,
137 IN ULONG Length,
138 OUT PVOID FileInformation,
139 OUT PULONG ReturnedLength)
140 {
141 IO_STATUS_BLOCK IoStatusBlock;
142 PIRP Irp;
143 PDEVICE_OBJECT DeviceObject;
144 PIO_STACK_LOCATION StackPtr;
145 NTSTATUS Status;
146
147 assert(FileInformation != NULL)
148
149 Status = ObReferenceObjectByPointer(FileObject,
150 FILE_READ_ATTRIBUTES,
151 IoFileObjectType,
152 KernelMode);
153 if (!NT_SUCCESS(Status))
154 {
155 return(Status);
156 }
157
158 DPRINT("FileObject %x\n", FileObject);
159
160 DeviceObject = FileObject->DeviceObject;
161
162 Irp = IoAllocateIrp(DeviceObject->StackSize,
163 TRUE);
164 if (Irp == NULL)
165 {
166 ObDereferenceObject(FileObject);
167 return STATUS_INSUFFICIENT_RESOURCES;
168 }
169
170 Irp->AssociatedIrp.SystemBuffer = FileInformation;
171 Irp->UserIosb = &IoStatusBlock;
172 Irp->UserEvent = &FileObject->Event;
173 KeResetEvent( &FileObject->Event );
174
175 StackPtr = IoGetNextIrpStackLocation(Irp);
176 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
177 StackPtr->MinorFunction = 0;
178 StackPtr->Flags = 0;
179 StackPtr->Control = 0;
180 StackPtr->DeviceObject = DeviceObject;
181 StackPtr->FileObject = FileObject;
182
183 StackPtr->Parameters.QueryFile.FileInformationClass =
184 FileInformationClass;
185 StackPtr->Parameters.QueryFile.Length = Length;
186
187 Status = IoCallDriver(FileObject->DeviceObject,
188 Irp);
189 if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
190 {
191 KeWaitForSingleObject(&FileObject->Event,
192 Executive,
193 KernelMode,
194 FALSE,
195 NULL);
196 Status = IoStatusBlock.Status;
197 }
198
199 if (ReturnedLength != NULL)
200 {
201 *ReturnedLength = IoStatusBlock.Information;
202 }
203
204 ObDereferenceObject(FileObject);
205
206 return Status;
207 }
208
209
210 NTSTATUS STDCALL
211 NtSetInformationFile(HANDLE FileHandle,
212 PIO_STATUS_BLOCK IoStatusBlock,
213 PVOID FileInformation,
214 ULONG Length,
215 FILE_INFORMATION_CLASS FileInformationClass)
216 {
217 PIO_STACK_LOCATION StackPtr;
218 PFILE_OBJECT FileObject;
219 PDEVICE_OBJECT DeviceObject;
220 PIRP Irp;
221 NTSTATUS Status;
222 PVOID SystemBuffer;
223 IO_STATUS_BLOCK IoSB;
224
225 assert(IoStatusBlock != NULL)
226 assert(FileInformation != NULL)
227
228 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d Class %d)\n",
229 FileHandle,
230 IoStatusBlock,
231 FileInformation,
232 Length,
233 FileInformationClass);
234
235 /* Get the file object from the file handle */
236 Status = ObReferenceObjectByHandle(FileHandle,
237 FILE_WRITE_ATTRIBUTES,
238 IoFileObjectType,
239 UserMode,
240 (PVOID *)&FileObject,
241 NULL);
242 if (!NT_SUCCESS(Status))
243 {
244 return Status;
245 }
246
247 DPRINT("FileObject %x\n", FileObject);
248
249 DeviceObject = FileObject->DeviceObject;
250
251 Irp = IoAllocateIrp(DeviceObject->StackSize,
252 TRUE);
253 if (Irp == NULL)
254 {
255 ObDereferenceObject(FileObject);
256 return STATUS_INSUFFICIENT_RESOURCES;
257 }
258
259 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
260 Length,
261 TAG_SYSB);
262 if (SystemBuffer == NULL)
263 {
264 IoFreeIrp(Irp);
265 ObDereferenceObject(FileObject);
266 return(STATUS_INSUFFICIENT_RESOURCES);
267 }
268
269 MmSafeCopyFromUser(SystemBuffer,
270 FileInformation,
271 Length);
272
273 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
274 Irp->UserIosb = &IoSB;
275 Irp->UserEvent = &FileObject->Event;
276 KeResetEvent( &FileObject->Event );
277
278 StackPtr = IoGetNextIrpStackLocation(Irp);
279 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
280 StackPtr->MinorFunction = 0;
281 StackPtr->Flags = 0;
282 StackPtr->Control = 0;
283 StackPtr->DeviceObject = DeviceObject;
284 StackPtr->FileObject = FileObject;
285
286 StackPtr->Parameters.SetFile.FileInformationClass =
287 FileInformationClass;
288 StackPtr->Parameters.SetFile.Length = Length;
289
290 /*
291 * Pass the IRP to the FSD (and wait for
292 * it if required)
293 */
294 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
295 Status = IoCallDriver(FileObject->DeviceObject,
296 Irp);
297 if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
298 {
299 KeWaitForSingleObject(&FileObject->Event,
300 Executive,
301 KernelMode,
302 FALSE,
303 NULL);
304 Status = IoSB.Status;
305 }
306 if (IoStatusBlock)
307 {
308 *IoStatusBlock = IoSB;
309 }
310 ExFreePool(SystemBuffer);
311 ObDereferenceObject(FileObject);
312
313 return Status;
314 }
315
316
317 NTSTATUS STDCALL
318 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
319 IN PVOID Buffer)
320 {
321 UNIMPLEMENTED;
322 return STATUS_NOT_IMPLEMENTED;
323 }
324
325
326 NTSTATUS STDCALL
327 NtQueryFullAttributesFile(IN HANDLE FileHandle,
328 IN PVOID Attributes)
329 {
330 UNIMPLEMENTED;
331 return STATUS_NOT_IMPLEMENTED;
332 }
333
334
335 NTSTATUS STDCALL
336 NtQueryEaFile(IN HANDLE FileHandle,
337 OUT PIO_STATUS_BLOCK IoStatusBlock,
338 OUT PVOID Buffer,
339 IN ULONG Length,
340 IN BOOLEAN ReturnSingleEntry,
341 IN PVOID EaList OPTIONAL,
342 IN ULONG EaListLength,
343 IN PULONG EaIndex OPTIONAL,
344 IN BOOLEAN RestartScan)
345 {
346 UNIMPLEMENTED;
347 return STATUS_NOT_IMPLEMENTED;
348 }
349
350
351 NTSTATUS STDCALL
352 NtSetEaFile(IN HANDLE FileHandle,
353 IN PIO_STATUS_BLOCK IoStatusBlock,
354 IN PVOID EaBuffer,
355 IN ULONG EaBufferSize)
356 {
357 UNIMPLEMENTED;
358 return STATUS_NOT_IMPLEMENTED;
359 }
360
361 /* EOF */