Merge 13159:13510 from trunk
[reactos.git] / reactos / ntoskrnl / io / file.c
1 /* $Id$
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 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17
18 /* GLOBALS *******************************************************************/
19
20 #define TAG_SYSB TAG('S', 'Y', 'S', 'B')
21
22
23 /* FUNCTIONS *****************************************************************/
24
25 /*
26 * @implemented
27 */
28 NTSTATUS STDCALL
29 NtQueryInformationFile(HANDLE FileHandle,
30 PIO_STATUS_BLOCK IoStatusBlock,
31 PVOID FileInformation,
32 ULONG Length,
33 FILE_INFORMATION_CLASS FileInformationClass)
34 {
35 PFILE_OBJECT FileObject;
36 NTSTATUS Status;
37 PIRP Irp;
38 PDEVICE_OBJECT DeviceObject;
39 PIO_STACK_LOCATION StackPtr;
40 PVOID SystemBuffer;
41 KPROCESSOR_MODE PreviousMode;
42
43 ASSERT(IoStatusBlock != NULL);
44 ASSERT(FileInformation != NULL);
45
46 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
47 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
48 Length, FileInformationClass);
49
50 PreviousMode = ExGetPreviousMode();
51
52 Status = ObReferenceObjectByHandle(FileHandle,
53 FILE_READ_ATTRIBUTES,
54 IoFileObjectType,
55 PreviousMode,
56 (PVOID *)&FileObject,
57 NULL);
58 if (!NT_SUCCESS(Status))
59 {
60 return(Status);
61 }
62 DPRINT("FileObject %x\n", FileObject);
63
64 DeviceObject = FileObject->DeviceObject;
65
66 Irp = IoAllocateIrp(DeviceObject->StackSize,
67 TRUE);
68 if (Irp == NULL)
69 {
70 ObDereferenceObject(FileObject);
71 return STATUS_INSUFFICIENT_RESOURCES;
72 }
73
74 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
75 Length,
76 TAG_SYSB);
77 if (SystemBuffer == NULL)
78 {
79 IoFreeIrp(Irp);
80 ObDereferenceObject(FileObject);
81 return(STATUS_INSUFFICIENT_RESOURCES);
82 }
83
84 /* Trigger FileObject/Event dereferencing */
85 Irp->Tail.Overlay.OriginalFileObject = FileObject;
86 Irp->RequestorMode = PreviousMode;
87 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
88 Irp->UserIosb = IoStatusBlock;
89 Irp->UserEvent = &FileObject->Event;
90 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
91 KeResetEvent( &FileObject->Event );
92
93 StackPtr = IoGetNextIrpStackLocation(Irp);
94 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
95 StackPtr->MinorFunction = 0;
96 StackPtr->Flags = 0;
97 StackPtr->Control = 0;
98 StackPtr->DeviceObject = DeviceObject;
99 StackPtr->FileObject = FileObject;
100
101 StackPtr->Parameters.QueryFile.FileInformationClass =
102 FileInformationClass;
103 StackPtr->Parameters.QueryFile.Length = Length;
104
105 Status = IoCallDriver(FileObject->DeviceObject,
106 Irp);
107 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
108 {
109 KeWaitForSingleObject(&FileObject->Event,
110 Executive,
111 PreviousMode,
112 FileObject->Flags & FO_ALERTABLE_IO,
113 NULL);
114 Status = IoStatusBlock->Status;
115 }
116
117 if (NT_SUCCESS(Status))
118 {
119 DPRINT("Information %lu\n", IoStatusBlock->Information);
120 MmSafeCopyToUser(FileInformation,
121 SystemBuffer,
122 IoStatusBlock->Information);
123 }
124
125 ExFreePool(SystemBuffer);
126
127 return Status;
128 }
129
130 /*
131 * @unimplemented
132 */
133 NTSTATUS
134 STDCALL
135 NtQueryQuotaInformationFile(
136 IN HANDLE FileHandle,
137 OUT PIO_STATUS_BLOCK IoStatusBlock,
138 OUT PVOID Buffer,
139 IN ULONG Length,
140 IN BOOLEAN ReturnSingleEntry,
141 IN PVOID SidList OPTIONAL,
142 IN ULONG SidListLength,
143 IN PSID StartSid OPTIONAL,
144 IN BOOLEAN RestartScan
145 )
146 {
147 UNIMPLEMENTED;
148 return STATUS_NOT_IMPLEMENTED;
149 }
150
151 /*
152 * @unimplemented
153 */
154 NTSTATUS
155 STDCALL
156 NtSetQuotaInformationFile(
157 HANDLE FileHandle,
158 PIO_STATUS_BLOCK IoStatusBlock,
159 PFILE_USER_QUOTA_INFORMATION Buffer,
160 ULONG BufferLength)
161 {
162 UNIMPLEMENTED;
163 return STATUS_NOT_IMPLEMENTED;
164 }
165
166
167 /*
168 * @unimplemented
169 */
170 NTSTATUS
171 STDCALL
172 IoCheckQuerySetFileInformation(
173 IN FILE_INFORMATION_CLASS FileInformationClass,
174 IN ULONG Length,
175 IN BOOLEAN SetOperation
176 )
177 {
178 UNIMPLEMENTED;
179 return STATUS_NOT_IMPLEMENTED;
180 }
181
182 /*
183 * @unimplemented
184 */
185 NTSTATUS
186 STDCALL
187 IoCheckQuerySetVolumeInformation(
188 IN FS_INFORMATION_CLASS FsInformationClass,
189 IN ULONG Length,
190 IN BOOLEAN SetOperation
191 )
192 {
193 UNIMPLEMENTED;
194 return STATUS_NOT_IMPLEMENTED;
195 }
196
197 /*
198 * @unimplemented
199 */
200 NTSTATUS
201 STDCALL
202 IoCheckQuotaBufferValidity(
203 IN PFILE_QUOTA_INFORMATION QuotaBuffer,
204 IN ULONG QuotaLength,
205 OUT PULONG ErrorOffset
206 )
207 {
208 UNIMPLEMENTED;
209 return STATUS_NOT_IMPLEMENTED;
210 }
211
212 /*
213 * @unimplemented
214 */
215 NTSTATUS
216 STDCALL
217 IoCreateFileSpecifyDeviceObjectHint(
218 OUT PHANDLE FileHandle,
219 IN ACCESS_MASK DesiredAccess,
220 IN POBJECT_ATTRIBUTES ObjectAttributes,
221 OUT PIO_STATUS_BLOCK IoStatusBlock,
222 IN PLARGE_INTEGER AllocationSize OPTIONAL,
223 IN ULONG FileAttributes,
224 IN ULONG ShareAccess,
225 IN ULONG Disposition,
226 IN ULONG CreateOptions,
227 IN PVOID EaBuffer OPTIONAL,
228 IN ULONG EaLength,
229 IN CREATE_FILE_TYPE CreateFileType,
230 IN PVOID ExtraCreateParameters OPTIONAL,
231 IN ULONG Options,
232 IN PVOID DeviceObject
233 )
234 {
235 UNIMPLEMENTED;
236 return STATUS_NOT_IMPLEMENTED;
237 }
238
239 /*
240 * @unimplemented
241 */
242 PFILE_OBJECT
243 STDCALL
244 IoCreateStreamFileObjectEx(
245 IN PFILE_OBJECT FileObject OPTIONAL,
246 IN PDEVICE_OBJECT DeviceObject OPTIONAL,
247 OUT PHANDLE FileObjectHandle OPTIONAL
248 )
249 {
250 UNIMPLEMENTED;
251 return 0;
252 }
253 /*
254 * @unimplemented
255 */
256 PFILE_OBJECT
257 STDCALL
258 IoCreateStreamFileObjectLite(
259 IN PFILE_OBJECT FileObject OPTIONAL,
260 IN PDEVICE_OBJECT DeviceObject OPTIONAL
261 )
262 {
263 UNIMPLEMENTED;
264 return 0;
265 }
266
267 /*
268 * @unimplemented
269 */
270 BOOLEAN
271 STDCALL
272 IoIsFileOriginRemote(
273 IN PFILE_OBJECT FileObject
274 )
275 {
276 UNIMPLEMENTED;
277 return FALSE;
278 }
279
280 /*
281 * @unimplemented
282 */
283 NTSTATUS
284 STDCALL
285 IoQueryFileDosDeviceName(
286 IN PFILE_OBJECT FileObject,
287 OUT POBJECT_NAME_INFORMATION *ObjectNameInformation
288 )
289 {
290 UNIMPLEMENTED;
291 return STATUS_NOT_IMPLEMENTED;
292 }
293
294 /*
295 * @implemented
296 */
297 NTSTATUS STDCALL
298 IoQueryFileInformation(IN PFILE_OBJECT FileObject,
299 IN FILE_INFORMATION_CLASS FileInformationClass,
300 IN ULONG Length,
301 OUT PVOID FileInformation,
302 OUT PULONG ReturnedLength)
303 {
304 IO_STATUS_BLOCK IoStatusBlock;
305 PIRP Irp;
306 PDEVICE_OBJECT DeviceObject;
307 PIO_STACK_LOCATION StackPtr;
308 NTSTATUS Status;
309
310 ASSERT(FileInformation != NULL);
311
312 Status = ObReferenceObjectByPointer(FileObject,
313 FILE_READ_ATTRIBUTES,
314 IoFileObjectType,
315 KernelMode);
316 if (!NT_SUCCESS(Status))
317 {
318 return(Status);
319 }
320
321 DPRINT("FileObject %x\n", FileObject);
322
323 DeviceObject = FileObject->DeviceObject;
324
325 Irp = IoAllocateIrp(DeviceObject->StackSize,
326 TRUE);
327 if (Irp == NULL)
328 {
329 ObDereferenceObject(FileObject);
330 return STATUS_INSUFFICIENT_RESOURCES;
331 }
332
333 /* Trigger FileObject/Event dereferencing */
334 Irp->Tail.Overlay.OriginalFileObject = FileObject;
335 Irp->RequestorMode = KernelMode;
336 Irp->AssociatedIrp.SystemBuffer = FileInformation;
337 Irp->UserIosb = &IoStatusBlock;
338 Irp->UserEvent = &FileObject->Event;
339 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
340 KeResetEvent( &FileObject->Event );
341
342 StackPtr = IoGetNextIrpStackLocation(Irp);
343 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
344 StackPtr->MinorFunction = 0;
345 StackPtr->Flags = 0;
346 StackPtr->Control = 0;
347 StackPtr->DeviceObject = DeviceObject;
348 StackPtr->FileObject = FileObject;
349
350 StackPtr->Parameters.QueryFile.FileInformationClass =
351 FileInformationClass;
352 StackPtr->Parameters.QueryFile.Length = Length;
353
354 Status = IoCallDriver(FileObject->DeviceObject,
355 Irp);
356 if (Status==STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
357 {
358 KeWaitForSingleObject(&FileObject->Event,
359 Executive,
360 KernelMode,
361 FileObject->Flags & FO_ALERTABLE_IO,
362 NULL);
363 Status = IoStatusBlock.Status;
364 }
365
366 if (ReturnedLength != NULL)
367 {
368 *ReturnedLength = IoStatusBlock.Information;
369 }
370
371
372 return Status;
373 }
374
375
376 /*
377 * @implemented
378 */
379 NTSTATUS STDCALL
380 NtSetInformationFile(HANDLE FileHandle,
381 PIO_STATUS_BLOCK IoStatusBlock,
382 PVOID FileInformation,
383 ULONG Length,
384 FILE_INFORMATION_CLASS FileInformationClass)
385 {
386 PIO_STACK_LOCATION StackPtr;
387 PFILE_OBJECT FileObject;
388 PDEVICE_OBJECT DeviceObject;
389 PIRP Irp;
390 NTSTATUS Status;
391 PVOID SystemBuffer;
392 KPROCESSOR_MODE PreviousMode;
393
394 ASSERT(IoStatusBlock != NULL);
395 ASSERT(FileInformation != NULL);
396
397 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
398 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
399 Length, FileInformationClass);
400
401 PreviousMode = ExGetPreviousMode();
402
403 /* Get the file object from the file handle */
404 Status = ObReferenceObjectByHandle(FileHandle,
405 FILE_WRITE_ATTRIBUTES,
406 IoFileObjectType,
407 PreviousMode,
408 (PVOID *)&FileObject,
409 NULL);
410 if (!NT_SUCCESS(Status))
411 {
412 return Status;
413 }
414
415 DPRINT("FileObject %x\n", FileObject);
416
417 /* io completion port? */
418 if (FileInformationClass == FileCompletionInformation)
419 {
420 PKQUEUE Queue;
421
422 if (Length < sizeof(FILE_COMPLETION_INFORMATION))
423 {
424 Status = STATUS_INFO_LENGTH_MISMATCH;
425 }
426 else
427 {
428 Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
429 IO_COMPLETION_MODIFY_STATE,//???
430 ExIoCompletionType,
431 PreviousMode,
432 (PVOID*)&Queue,
433 NULL);
434 if (NT_SUCCESS(Status))
435 {
436 /* FIXME: maybe use lookaside list */
437 FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
438 FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
439 FileObject->CompletionContext->Port = Queue;
440
441 ObDereferenceObject(Queue);
442 }
443 }
444
445 ObDereferenceObject(FileObject);
446 return Status;
447 }
448
449 DeviceObject = FileObject->DeviceObject;
450
451 Irp = IoAllocateIrp(DeviceObject->StackSize,
452 TRUE);
453 if (Irp == NULL)
454 {
455 ObDereferenceObject(FileObject);
456 return STATUS_INSUFFICIENT_RESOURCES;
457 }
458
459 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
460 Length,
461 TAG_SYSB);
462 if (SystemBuffer == NULL)
463 {
464 IoFreeIrp(Irp);
465 ObDereferenceObject(FileObject);
466 return(STATUS_INSUFFICIENT_RESOURCES);
467 }
468
469 MmSafeCopyFromUser(SystemBuffer,
470 FileInformation,
471 Length);
472
473 /* Trigger FileObject/Event dereferencing */
474 Irp->Tail.Overlay.OriginalFileObject = FileObject;
475 Irp->RequestorMode = PreviousMode;
476 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
477 Irp->UserIosb = IoStatusBlock;
478 Irp->UserEvent = &FileObject->Event;
479 KeResetEvent( &FileObject->Event );
480 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
481
482 StackPtr = IoGetNextIrpStackLocation(Irp);
483 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
484 StackPtr->MinorFunction = 0;
485 StackPtr->Flags = 0;
486 StackPtr->Control = 0;
487 StackPtr->DeviceObject = DeviceObject;
488 StackPtr->FileObject = FileObject;
489
490 StackPtr->Parameters.SetFile.FileInformationClass =
491 FileInformationClass;
492 StackPtr->Parameters.SetFile.Length = Length;
493
494 /*
495 * Pass the IRP to the FSD (and wait for
496 * it if required)
497 */
498 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
499 Status = IoCallDriver(FileObject->DeviceObject,
500 Irp);
501 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
502 {
503 KeWaitForSingleObject(&FileObject->Event,
504 Executive,
505 PreviousMode,
506 FileObject->Flags & FO_ALERTABLE_IO,
507 NULL);
508 Status = IoStatusBlock->Status;
509 }
510
511 ExFreePool(SystemBuffer);
512
513 return Status;
514 }
515
516
517 /*
518 * @unimplemented
519 */
520 NTSTATUS
521 STDCALL
522 IoSetFileOrigin(
523 IN PFILE_OBJECT FileObject,
524 IN BOOLEAN Remote
525 )
526 {
527 UNIMPLEMENTED;
528 return STATUS_NOT_IMPLEMENTED;
529 }
530
531 NTSTATUS STDCALL
532 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
533 OUT PFILE_BASIC_INFORMATION FileInformation)
534 {
535 IO_STATUS_BLOCK IoStatusBlock;
536 HANDLE FileHandle;
537 NTSTATUS Status;
538
539 /* Open the file */
540 Status = ZwOpenFile (&FileHandle,
541 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
542 ObjectAttributes,
543 &IoStatusBlock,
544 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
545 FILE_SYNCHRONOUS_IO_NONALERT);
546 if (!NT_SUCCESS (Status))
547 {
548 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
549 return Status;
550 }
551
552 /* Get file attributes */
553 Status = ZwQueryInformationFile (FileHandle,
554 &IoStatusBlock,
555 FileInformation,
556 sizeof(FILE_BASIC_INFORMATION),
557 FileBasicInformation);
558 ZwClose (FileHandle);
559 if (!NT_SUCCESS (Status))
560 {
561 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
562 }
563
564 return Status;
565 }
566
567
568 NTSTATUS STDCALL
569 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
570 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
571 {
572 IO_STATUS_BLOCK IoStatusBlock;
573 HANDLE FileHandle;
574 NTSTATUS Status;
575
576 /* Open the file */
577 Status = ZwOpenFile (&FileHandle,
578 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
579 ObjectAttributes,
580 &IoStatusBlock,
581 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
582 FILE_SYNCHRONOUS_IO_NONALERT);
583 if (!NT_SUCCESS (Status))
584 {
585 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
586 return Status;
587 }
588
589 /* Get file attributes */
590 Status = ZwQueryInformationFile (FileHandle,
591 &IoStatusBlock,
592 FileInformation,
593 sizeof(FILE_NETWORK_OPEN_INFORMATION),
594 FileNetworkOpenInformation);
595 ZwClose (FileHandle);
596 if (!NT_SUCCESS (Status))
597 {
598 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
599 }
600
601 return Status;
602 }
603
604
605 /*
606 * @unimplemented
607 */
608 NTSTATUS STDCALL
609 NtQueryEaFile(IN HANDLE FileHandle,
610 OUT PIO_STATUS_BLOCK IoStatusBlock,
611 OUT PVOID Buffer,
612 IN ULONG Length,
613 IN BOOLEAN ReturnSingleEntry,
614 IN PVOID EaList OPTIONAL,
615 IN ULONG EaListLength,
616 IN PULONG EaIndex OPTIONAL,
617 IN BOOLEAN RestartScan)
618 {
619 UNIMPLEMENTED;
620 return STATUS_NOT_IMPLEMENTED;
621 }
622
623
624 /*
625 * @unimplemented
626 */
627 NTSTATUS STDCALL
628 NtSetEaFile(IN HANDLE FileHandle,
629 IN PIO_STATUS_BLOCK IoStatusBlock,
630 IN PVOID EaBuffer,
631 IN ULONG EaBufferSize)
632 {
633 UNIMPLEMENTED;
634 return STATUS_NOT_IMPLEMENTED;
635 }
636
637 /* EOF */