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