- Reference the file object in IopSecurityFile.
[reactos.git] / reactos / ntoskrnl / io / file.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/file.c
5 * PURPOSE: I/O File Object & NT File Handle Access/Managment of Files.
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 #define TAG_SYSB TAG('S', 'Y', 'S', 'B')
20 #define TAG_LOCK TAG('F','l','c','k')
21 #define TAG_FILE_NAME TAG('F', 'N', 'A', 'M')
22
23 extern GENERIC_MAPPING IopFileMapping;
24
25 NTSTATUS
26 STDCALL
27 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
28 PSECURITY_DESCRIPTOR SecurityDescriptor,
29 PULONG BufferLength);
30
31 /* INTERNAL FUNCTIONS ********************************************************/
32
33 /*
34 * NAME INTERNAL
35 * IopCreateFile
36 *
37 * DESCRIPTION
38 *
39 * ARGUMENTS
40 *
41 * RETURN VALUE
42 *
43 * REVISIONS
44 */
45 NTSTATUS
46 STDCALL
47 IopCreateFile(PVOID ObjectBody,
48 PVOID Parent,
49 PWSTR RemainingPath,
50 POBJECT_ATTRIBUTES ObjectAttributes)
51 {
52 PDEVICE_OBJECT DeviceObject;
53 PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody;
54 POBJECT_TYPE ParentObjectType;
55 NTSTATUS Status;
56
57 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
58 ObjectBody,
59 Parent,
60 RemainingPath);
61
62 if (NULL == Parent)
63 {
64 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
65 for the cache manager, so return STATUS_SUCCESS */
66 DPRINT("Parent object was NULL\n");
67 return(STATUS_SUCCESS);
68 }
69
70 ParentObjectType = BODY_TO_HEADER(Parent)->ObjectType;
71
72 if (ParentObjectType != IoDeviceObjectType &&
73 ParentObjectType != IoFileObjectType)
74 {
75 DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n",
76 &BODY_TO_HEADER(Parent)->Name,
77 BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer,
78 RemainingPath);
79 return(STATUS_UNSUCCESSFUL);
80 }
81
82 Status = ObReferenceObjectByPointer(Parent,
83 STANDARD_RIGHTS_REQUIRED,
84 ParentObjectType,
85 UserMode);
86 if (!NT_SUCCESS(Status))
87 {
88 CPRINT("Failed to reference parent object %x\n", Parent);
89 return(Status);
90 }
91
92 if (ParentObjectType == IoDeviceObjectType)
93 {
94 /* Parent is a devce object */
95 DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)Parent);
96 DPRINT("DeviceObject %x\n", DeviceObject);
97
98 if (RemainingPath == NULL)
99 {
100 FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
101 FileObject->FileName.Buffer = 0;
102 FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0;
103 }
104 else
105 {
106 if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
107 && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
108 && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
109 && (DeviceObject->DeviceType != FILE_DEVICE_TAPE)
110 && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
111 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
112 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
113 {
114 CPRINT("Device was wrong type\n");
115 return(STATUS_UNSUCCESSFUL);
116 }
117
118 if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
119 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
120 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
121 {
122 if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
123 {
124 DPRINT("Mount the logical volume\n");
125 Status = IoMountVolume(DeviceObject, FALSE);
126 DPRINT("Status %x\n", Status);
127 if (!NT_SUCCESS(Status))
128 {
129 CPRINT("Failed to mount logical volume (Status %x)\n",
130 Status);
131 return(Status);
132 }
133 }
134 DeviceObject = DeviceObject->Vpb->DeviceObject;
135 DPRINT("FsDeviceObject %lx\n", DeviceObject);
136 }
137 RtlpCreateUnicodeString(&(FileObject->FileName),
138 RemainingPath, NonPagedPool);
139 }
140 }
141 else
142 {
143 /* Parent is a file object */
144 if (RemainingPath == NULL)
145 {
146 CPRINT("Device is unnamed\n");
147 return STATUS_UNSUCCESSFUL;
148 }
149
150 DeviceObject = ((PFILE_OBJECT)Parent)->DeviceObject;
151 DPRINT("DeviceObject %x\n", DeviceObject);
152
153 FileObject->RelatedFileObject = (PFILE_OBJECT)Parent;
154
155 RtlpCreateUnicodeString(&(FileObject->FileName),
156 RemainingPath, NonPagedPool);
157 }
158
159 DPRINT("FileObject->FileName %wZ\n",
160 &FileObject->FileName);
161 FileObject->DeviceObject = DeviceObject;
162 DPRINT("FileObject %x DeviceObject %x\n",
163 FileObject,
164 DeviceObject);
165 FileObject->Vpb = DeviceObject->Vpb;
166 FileObject->Type = IO_TYPE_FILE;
167
168 return(STATUS_SUCCESS);
169 }
170
171 VOID
172 STDCALL
173 IopDeleteFile(PVOID ObjectBody)
174 {
175 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
176 PIRP Irp;
177 PIO_STACK_LOCATION StackPtr;
178 NTSTATUS Status;
179 KEVENT Event;
180 PDEVICE_OBJECT DeviceObject;
181
182 DPRINT("IopDeleteFile()\n");
183
184 if (FileObject->DeviceObject)
185 {
186 /* Check if this is a direct open or not */
187 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
188 {
189 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
190 }
191 else
192 {
193 DeviceObject = IoGetRelatedDeviceObject(FileObject);
194 }
195
196 /* Clear and set up Events */
197 KeClearEvent(&FileObject->Event);
198 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
199
200 /* Allocate an IRP */
201 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
202
203 /* Set it up */
204 Irp->UserEvent = &Event;
205 Irp->UserIosb = &Irp->IoStatus;
206 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
207 Irp->Tail.Overlay.OriginalFileObject = FileObject;
208 Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
209
210 /* Set up Stack Pointer Data */
211 StackPtr = IoGetNextIrpStackLocation(Irp);
212 StackPtr->MajorFunction = IRP_MJ_CLOSE;
213 StackPtr->DeviceObject = DeviceObject;
214 StackPtr->FileObject = FileObject;
215
216 /* Call the FS Driver */
217 Status = IoCallDriver(DeviceObject, Irp);
218
219 /* Wait for completion */
220 if (Status == STATUS_PENDING)
221 {
222 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
223 }
224 IoFreeIrp(Irp);
225
226 }
227
228 /* Clear the file name */
229 if (FileObject->FileName.Buffer)
230 {
231 ExFreePool(FileObject->FileName.Buffer);
232 FileObject->FileName.Buffer = NULL;
233 }
234
235 /* Free the completion context */
236 if (FileObject->CompletionContext)
237 {
238 ObDereferenceObject(FileObject->CompletionContext->Port);
239 ExFreePool(FileObject->CompletionContext);
240 }
241 }
242
243 NTSTATUS
244 STDCALL
245 IopSecurityFile(PVOID ObjectBody,
246 SECURITY_OPERATION_CODE OperationCode,
247 SECURITY_INFORMATION SecurityInformation,
248 PSECURITY_DESCRIPTOR SecurityDescriptor,
249 PULONG BufferLength)
250 {
251 IO_STATUS_BLOCK IoStatusBlock;
252 PIO_STACK_LOCATION StackPtr;
253 PFILE_OBJECT FileObject;
254 PDEVICE_OBJECT DeviceObject;
255 ULONG MajorFunction;
256 PIRP Irp;
257 BOOLEAN LocalEvent = FALSE;
258 KEVENT Event;
259 NTSTATUS Status = STATUS_SUCCESS;
260
261 DPRINT("IopSecurityFile() called\n");
262
263 FileObject = (PFILE_OBJECT)ObjectBody;
264
265 if (OperationCode == QuerySecurityDescriptor)
266 {
267 MajorFunction = IRP_MJ_QUERY_SECURITY;
268 DPRINT("Query security descriptor\n");
269 }
270 else if (OperationCode == DeleteSecurityDescriptor)
271 {
272 DPRINT("Delete\n");
273 return STATUS_SUCCESS;
274 }
275 else if (OperationCode == AssignSecurityDescriptor)
276 {
277 /* If this is a direct open, we can assign it */
278 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
279 {
280 /* Get the Device Object */
281 DPRINT1("here\n");
282 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
283
284 /* Assign the Security Descriptor */
285 DeviceObject->SecurityDescriptor = SecurityDescriptor;
286 }
287 return STATUS_SUCCESS;
288 }
289 else
290 {
291 MajorFunction = IRP_MJ_SET_SECURITY;
292 DPRINT("Set security descriptor\n");
293
294 /* If this is a direct open, we can set it */
295 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
296 {
297 DPRINT1("Set SD unimplemented for Devices\n");
298 return STATUS_SUCCESS;
299 }
300 }
301
302 /* Get the Device Object */
303 DPRINT1("FileObject: %p\n", FileObject);
304 DeviceObject = IoGetRelatedDeviceObject(FileObject);
305
306 /* Check if we should use Sync IO or not */
307 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
308 {
309 /* Use File Object event */
310 KeClearEvent(&FileObject->Event);
311 }
312 else
313 {
314 /* Use local event */
315 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
316 LocalEvent = TRUE;
317 }
318
319 /* Allocate the IRP */
320 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
321
322 /* Set the IRP */
323 Irp->Tail.Overlay.OriginalFileObject = FileObject;
324 Irp->RequestorMode = ExGetPreviousMode();
325 Irp->UserIosb = &IoStatusBlock;
326 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
327 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
328 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
329
330 /* Set Stack Parameters */
331 StackPtr = IoGetNextIrpStackLocation(Irp);
332 StackPtr->FileObject = FileObject;
333
334 /* Set Parameters */
335 if (OperationCode == QuerySecurityDescriptor)
336 {
337 StackPtr->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
338 StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
339 Irp->UserBuffer = SecurityDescriptor;
340 }
341 else
342 {
343 StackPtr->Parameters.SetSecurity.SecurityInformation = SecurityInformation;
344 StackPtr->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;
345 }
346
347 ObReferenceObject(FileObject);
348
349 /* Call the Driver */
350 Status = IoCallDriver(FileObject->DeviceObject, Irp);
351
352 if (Status == STATUS_PENDING)
353 {
354 if (LocalEvent)
355 {
356 KeWaitForSingleObject(&Event,
357 Executive,
358 KernelMode,
359 FileObject->Flags & FO_ALERTABLE_IO,
360 NULL);
361 Status = IoStatusBlock.Status;
362 }
363 else
364 {
365 KeWaitForSingleObject(&FileObject->Event,
366 Executive,
367 KernelMode,
368 FileObject->Flags & FO_ALERTABLE_IO,
369 NULL);
370 Status = FileObject->FinalStatus;
371 }
372 }
373
374 /* This Driver doesn't implement Security, so try to give it a default */
375 if (Status == STATUS_INVALID_DEVICE_REQUEST)
376 {
377 if (OperationCode == QuerySecurityDescriptor)
378 {
379 /* Set a World Security Descriptor */
380 Status = SeSetWorldSecurityDescriptor(SecurityInformation,
381 SecurityDescriptor,
382 BufferLength);
383 }
384 else
385 {
386 /* It wasn't a query, so just fake success */
387 Status = STATUS_SUCCESS;
388 }
389 }
390 else if (OperationCode == QuerySecurityDescriptor)
391 {
392 /* Return length */
393 *BufferLength = IoStatusBlock.Information;
394 }
395
396 /* Return Status */
397 return Status;
398 }
399
400 NTSTATUS
401 STDCALL
402 IopQueryNameFile(PVOID ObjectBody,
403 POBJECT_NAME_INFORMATION ObjectNameInfo,
404 ULONG Length,
405 PULONG ReturnLength)
406 {
407 PVOID LocalInfo;
408 PFILE_OBJECT FileObject;
409 ULONG LocalReturnLength;
410 NTSTATUS Status;
411
412 DPRINT1("IopQueryNameFile() called\n");
413
414 FileObject = (PFILE_OBJECT)ObjectBody;
415
416 /* Allocate Buffer */
417 LocalInfo = ExAllocatePool(PagedPool,
418 sizeof(OBJECT_NAME_INFORMATION) +
419 MAX_PATH * sizeof(WCHAR));
420 if (LocalInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES;
421
422 /* Query the name */
423 Status = ObQueryNameString(FileObject->DeviceObject,
424 LocalInfo,
425 MAX_PATH * sizeof(WCHAR),
426 &LocalReturnLength);
427 if (!NT_SUCCESS (Status))
428 {
429 ExFreePool (LocalInfo);
430 return Status;
431 }
432 DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
433
434 /* Write Device Path */
435 Status = RtlAppendUnicodeStringToString(&ObjectNameInfo->Name,
436 &((POBJECT_NAME_INFORMATION)LocalInfo)->Name);
437
438 /* Query the File name */
439 Status = IoQueryFileInformation(FileObject,
440 FileNameInformation,
441 LocalReturnLength,
442 LocalInfo,
443 NULL);
444 if (Status != STATUS_SUCCESS)
445 {
446 ExFreePool(LocalInfo);
447 return Status;
448 }
449
450 /* Write the Name */
451 Status = RtlAppendUnicodeToString(&ObjectNameInfo->Name,
452 ((PFILE_NAME_INFORMATION)LocalInfo)->FileName);
453 DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
454
455 /* Free buffer and return */
456 ExFreePool(LocalInfo);
457 return Status;
458 }
459
460 VOID
461 STDCALL
462 IopCloseFile(PVOID ObjectBody,
463 ULONG HandleCount)
464 {
465 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
466 KEVENT Event;
467 PIRP Irp;
468 PIO_STACK_LOCATION StackPtr;
469 NTSTATUS Status;
470 PDEVICE_OBJECT DeviceObject;
471
472 DPRINT("IopCloseFile()\n");
473
474 if (HandleCount > 1 || FileObject->DeviceObject == NULL) return;
475
476 /* Check if this is a direct open or not */
477 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
478 {
479 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
480 }
481 else
482 {
483 DeviceObject = IoGetRelatedDeviceObject(FileObject);
484 }
485
486 /* Clear and set up Events */
487 KeClearEvent(&FileObject->Event);
488 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
489
490 /* Allocate an IRP */
491 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
492
493 /* Set it up */
494 Irp->UserEvent = &Event;
495 Irp->UserIosb = &Irp->IoStatus;
496 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
497 Irp->Tail.Overlay.OriginalFileObject = FileObject;
498 Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
499
500 /* Set up Stack Pointer Data */
501 StackPtr = IoGetNextIrpStackLocation(Irp);
502 StackPtr->MajorFunction = IRP_MJ_CLEANUP;
503 StackPtr->FileObject = FileObject;
504
505 /* Call the FS Driver */
506 Status = IoCallDriver(DeviceObject, Irp);
507
508 /* Wait for completion */
509 if (Status == STATUS_PENDING)
510 {
511 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
512 }
513 IoFreeIrp(Irp);
514 }
515
516 /* FUNCTIONS *****************************************************************/
517
518 /*
519 * @unimplemented
520 */
521 NTSTATUS
522 STDCALL
523 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,
524 IN ULONG Length,
525 IN BOOLEAN SetOperation)
526 {
527 UNIMPLEMENTED;
528 return STATUS_NOT_IMPLEMENTED;
529 }
530
531 /*
532 * @unimplemented
533 */
534 NTSTATUS
535 STDCALL
536 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
537 IN ULONG QuotaLength,
538 OUT PULONG ErrorOffset)
539 {
540 UNIMPLEMENTED;
541 return STATUS_NOT_IMPLEMENTED;
542 }
543
544 /*
545 * NAME EXPORTED
546 * IoCreateFile@56
547 *
548 * DESCRIPTION
549 * Either causes a new file or directory to be created, or it
550 * opens an existing file, device, directory or volume, giving
551 * the caller a handle for the file object. This handle can be
552 * used by subsequent calls to manipulate data within the file
553 * or the file object's state of attributes.
554 *
555 * ARGUMENTS
556 * FileHandle (OUT)
557 * Points to a variable which receives the file handle
558 * on return;
559 *
560 * DesiredAccess
561 * Desired access to the file;
562 *
563 * ObjectAttributes
564 * Structure describing the file;
565 *
566 * IoStatusBlock (OUT)
567 * Receives information about the operation on return;
568 *
569 * AllocationSize [OPTIONAL]
570 * Initial size of the file in bytes;
571 *
572 * FileAttributes
573 * Attributes to create the file with;
574 *
575 * ShareAccess
576 * Type of shared access the caller would like to the
577 * file;
578 *
579 * CreateDisposition
580 * Specifies what to do, depending on whether the
581 * file already exists;
582 *
583 * CreateOptions
584 * Options for creating a new file;
585 *
586 * EaBuffer [OPTIONAL]
587 * Undocumented;
588 *
589 * EaLength
590 * Undocumented;
591 *
592 * CreateFileType
593 * Type of file (normal, named pipe, mailslot) to create;
594 *
595 * ExtraCreateParameters [OPTIONAL]
596 * Additional creation data for named pipe and mailsots;
597 *
598 * Options
599 * Undocumented.
600 *
601 * RETURN VALUE
602 * Status
603 *
604 * NOTE
605 * Prototype taken from Bo Branten's ntifs.h v15.
606 * Description taken from old NtCreateFile's which is
607 * now a wrapper of this call.
608 *
609 * REVISIONS
610 *
611 * @implemented
612 */
613 NTSTATUS
614 STDCALL
615 IoCreateFile(OUT PHANDLE FileHandle,
616 IN ACCESS_MASK DesiredAccess,
617 IN POBJECT_ATTRIBUTES ObjectAttributes,
618 OUT PIO_STATUS_BLOCK IoStatusBlock,
619 IN PLARGE_INTEGER AllocationSize OPTIONAL,
620 IN ULONG FileAttributes,
621 IN ULONG ShareAccess,
622 IN ULONG CreateDisposition,
623 IN ULONG CreateOptions,
624 IN PVOID EaBuffer OPTIONAL,
625 IN ULONG EaLength,
626 IN CREATE_FILE_TYPE CreateFileType,
627 IN PVOID ExtraCreateParameters OPTIONAL,
628 IN ULONG Options)
629 {
630 PFILE_OBJECT FileObject = NULL;
631 PDEVICE_OBJECT DeviceObject;
632 PIRP Irp;
633 PIO_STACK_LOCATION StackLoc;
634 IO_SECURITY_CONTEXT SecurityContext;
635 KPROCESSOR_MODE AccessMode;
636 HANDLE LocalHandle;
637 IO_STATUS_BLOCK LocalIoStatusBlock;
638 LARGE_INTEGER SafeAllocationSize;
639 PVOID SystemEaBuffer = NULL;
640 NTSTATUS Status = STATUS_SUCCESS;
641
642 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
643 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
644 FileHandle,DesiredAccess,ObjectAttributes,
645 ObjectAttributes->ObjectName->Buffer);
646
647 ASSERT_IRQL(PASSIVE_LEVEL);
648
649 if (IoStatusBlock == NULL || FileHandle == NULL)
650 return STATUS_ACCESS_VIOLATION;
651
652 LocalHandle = 0;
653
654 if(Options & IO_NO_PARAMETER_CHECKING)
655 AccessMode = KernelMode;
656 else
657 AccessMode = ExGetPreviousMode();
658
659 if(AccessMode != KernelMode)
660 {
661 _SEH_TRY
662 {
663 ProbeForWrite(FileHandle,
664 sizeof(HANDLE),
665 sizeof(ULONG));
666 ProbeForWrite(IoStatusBlock,
667 sizeof(IO_STATUS_BLOCK),
668 sizeof(ULONG));
669 if(AllocationSize != NULL)
670 {
671 ProbeForRead(AllocationSize,
672 sizeof(LARGE_INTEGER),
673 sizeof(ULONG));
674 SafeAllocationSize = *AllocationSize;
675 }
676 else
677 SafeAllocationSize.QuadPart = 0;
678
679 if(EaBuffer != NULL && EaLength > 0)
680 {
681 ProbeForRead(EaBuffer,
682 EaLength,
683 sizeof(ULONG));
684
685 /* marshal EaBuffer */
686 SystemEaBuffer = ExAllocatePool(NonPagedPool,
687 EaLength);
688 if(SystemEaBuffer == NULL)
689 {
690 Status = STATUS_INSUFFICIENT_RESOURCES;
691 _SEH_LEAVE;
692 }
693
694 RtlCopyMemory(SystemEaBuffer,
695 EaBuffer,
696 EaLength);
697 }
698 }
699 _SEH_HANDLE
700 {
701 Status = _SEH_GetExceptionCode();
702 }
703 _SEH_END;
704
705 if(!NT_SUCCESS(Status))
706 {
707 return Status;
708 }
709 }
710 else
711 {
712 if(AllocationSize != NULL)
713 SafeAllocationSize = *AllocationSize;
714 else
715 SafeAllocationSize.QuadPart = 0;
716
717 if(EaBuffer != NULL && EaLength > 0)
718 {
719 SystemEaBuffer = EaBuffer;
720 }
721 }
722
723 if(Options & IO_CHECK_CREATE_PARAMETERS)
724 {
725 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
726 }
727
728 if (CreateDisposition == FILE_OPEN ||
729 CreateDisposition == FILE_OPEN_IF)
730 {
731 Status = ObOpenObjectByName(ObjectAttributes,
732 NULL,
733 NULL,
734 AccessMode,
735 DesiredAccess,
736 NULL,
737 &LocalHandle);
738 if (NT_SUCCESS(Status))
739 {
740 Status = ObReferenceObjectByHandle(LocalHandle,
741 DesiredAccess,
742 NULL,
743 AccessMode,
744 (PVOID*)&DeviceObject,
745 NULL);
746 ZwClose(LocalHandle);
747 if (!NT_SUCCESS(Status))
748 {
749 return Status;
750 }
751 if (BODY_TO_HEADER(DeviceObject)->ObjectType != IoDeviceObjectType)
752 {
753 ObDereferenceObject (DeviceObject);
754 return STATUS_OBJECT_NAME_COLLISION;
755 }
756 /* FIXME: wt... */
757 FileObject = IoCreateStreamFileObject(NULL, DeviceObject);
758 ObDereferenceObject (DeviceObject);
759 }
760 }
761
762
763 if (FileObject == NULL)
764 {
765 Status = ObCreateObject(AccessMode,
766 IoFileObjectType,
767 ObjectAttributes,
768 AccessMode,
769 NULL,
770 sizeof(FILE_OBJECT),
771 0,
772 0,
773 (PVOID*)&FileObject);
774 if (!NT_SUCCESS(Status))
775 {
776 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
777 return Status;
778 }
779 }
780 RtlMapGenericMask(&DesiredAccess,
781 &BODY_TO_HEADER(FileObject)->ObjectType->TypeInfo.GenericMapping);
782
783 Status = ObInsertObject ((PVOID)FileObject,
784 NULL,
785 DesiredAccess,
786 0,
787 NULL,
788 &LocalHandle);
789 if (!NT_SUCCESS(Status))
790 {
791 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status);
792 ObDereferenceObject (FileObject);
793 return Status;
794 }
795
796 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
797 {
798 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
799 }
800 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
801 {
802 FileObject->Flags |= FO_SYNCHRONOUS_IO;
803 }
804
805 if (CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
806 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
807
808 SecurityContext.SecurityQos = NULL; /* ?? */
809 SecurityContext.AccessState = NULL; /* ?? */
810 SecurityContext.DesiredAccess = DesiredAccess;
811 SecurityContext.FullCreateOptions = 0; /* ?? */
812
813 KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, TRUE);
814 KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
815
816 DPRINT("FileObject %x\n", FileObject);
817 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
818 /*
819 * Create a new IRP to hand to
820 * the FS driver: this may fail
821 * due to resource shortage.
822 */
823 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
824 if (Irp == NULL)
825 {
826 ZwClose(LocalHandle);
827 return STATUS_UNSUCCESSFUL;
828 }
829
830 //trigger FileObject/Event dereferencing
831 Irp->Tail.Overlay.OriginalFileObject = FileObject;
832 Irp->RequestorMode = AccessMode;
833 Irp->UserIosb = &LocalIoStatusBlock;
834 Irp->AssociatedIrp.SystemBuffer = SystemEaBuffer;
835 Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
836 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
837 Irp->UserEvent = &FileObject->Event;
838 Irp->Overlay.AllocationSize = SafeAllocationSize;
839
840 /*
841 * Get the stack location for the new
842 * IRP and prepare it.
843 */
844 StackLoc = IoGetNextIrpStackLocation(Irp);
845 StackLoc->MinorFunction = 0;
846 StackLoc->Flags = (UCHAR)Options;
847 StackLoc->Control = 0;
848 StackLoc->DeviceObject = FileObject->DeviceObject;
849 StackLoc->FileObject = FileObject;
850
851 switch (CreateFileType)
852 {
853 default:
854 case CreateFileTypeNone:
855 StackLoc->MajorFunction = IRP_MJ_CREATE;
856 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
857 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
858 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
859 StackLoc->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
860 StackLoc->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
861 StackLoc->Parameters.Create.EaLength = SystemEaBuffer != NULL ? EaLength : 0;
862 break;
863
864 case CreateFileTypeNamedPipe:
865 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
866 StackLoc->Parameters.CreatePipe.SecurityContext = &SecurityContext;
867 StackLoc->Parameters.CreatePipe.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
868 StackLoc->Parameters.CreatePipe.Options |= (CreateDisposition << 24);
869 StackLoc->Parameters.CreatePipe.ShareAccess = (USHORT)ShareAccess;
870 StackLoc->Parameters.CreatePipe.Parameters = ExtraCreateParameters;
871 break;
872
873 case CreateFileTypeMailslot:
874 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
875 StackLoc->Parameters.CreateMailslot.SecurityContext = &SecurityContext;
876 StackLoc->Parameters.CreateMailslot.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
877 StackLoc->Parameters.CreateMailslot.Options |= (CreateDisposition << 24);
878 StackLoc->Parameters.CreateMailslot.ShareAccess = (USHORT)ShareAccess;
879 StackLoc->Parameters.CreateMailslot.Parameters = ExtraCreateParameters;
880 break;
881 }
882
883 /*
884 * Now call the driver and
885 * possibly wait if it can
886 * not complete the request
887 * immediately.
888 */
889 Status = IofCallDriver(FileObject->DeviceObject, Irp );
890 DPRINT("Status :%x\n", Status);
891
892 if (Status == STATUS_PENDING)
893 {
894 KeWaitForSingleObject(&FileObject->Event,
895 Executive,
896 AccessMode,
897 FALSE,
898 NULL);
899 Status = LocalIoStatusBlock.Status;
900 }
901 if (!NT_SUCCESS(Status))
902 {
903 DPRINT("Failing create request with status %x\n", Status);
904 FileObject->DeviceObject = NULL;
905 FileObject->Vpb = NULL;
906
907 ZwClose(LocalHandle);
908 }
909 else
910 {
911 _SEH_TRY
912 {
913 *FileHandle = LocalHandle;
914 *IoStatusBlock = LocalIoStatusBlock;
915 }
916 _SEH_HANDLE
917 {
918 Status = _SEH_GetExceptionCode();
919 }
920 _SEH_END;
921 }
922
923 /* cleanup EABuffer if captured */
924 if(AccessMode != KernelMode && SystemEaBuffer != NULL)
925 {
926 ExFreePool(SystemEaBuffer);
927 }
928
929 ASSERT_IRQL(PASSIVE_LEVEL);
930
931 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
932
933 return Status;
934 }
935
936 /*
937 * @unimplemented
938 */
939 NTSTATUS
940 STDCALL
941 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle,
942 IN ACCESS_MASK DesiredAccess,
943 IN POBJECT_ATTRIBUTES ObjectAttributes,
944 OUT PIO_STATUS_BLOCK IoStatusBlock,
945 IN PLARGE_INTEGER AllocationSize OPTIONAL,
946 IN ULONG FileAttributes,
947 IN ULONG ShareAccess,
948 IN ULONG Disposition,
949 IN ULONG CreateOptions,
950 IN PVOID EaBuffer OPTIONAL,
951 IN ULONG EaLength,
952 IN CREATE_FILE_TYPE CreateFileType,
953 IN PVOID ExtraCreateParameters OPTIONAL,
954 IN ULONG Options,
955 IN PVOID DeviceObject)
956 {
957 UNIMPLEMENTED;
958 return STATUS_NOT_IMPLEMENTED;
959 }
960
961 /*
962 * NAME EXPORTED
963 * IoCreateStreamFileObject@8
964 *
965 * DESCRIPTION
966 *
967 * ARGUMENTS
968 * FileObject
969 * ?
970 *
971 * DeviceObject
972 * ?
973 *
974 * RETURN VALUE
975 *
976 * NOTE
977 *
978 * REVISIONS
979 *
980 * @implemented
981 */
982 PFILE_OBJECT
983 STDCALL
984 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
985 PDEVICE_OBJECT DeviceObject)
986 {
987 PFILE_OBJECT CreatedFileObject;
988 NTSTATUS Status;
989
990 /* FIXME: This function should call ObInsertObject. The "Lite" version
991 doesnt. This function is also called from IoCreateFile for some
992 reason. These hacks need to be removed.
993 */
994
995 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
996 FileObject, DeviceObject);
997 PAGED_CODE();
998
999 /* Create the File Object */
1000 Status = ObCreateObject(KernelMode,
1001 IoFileObjectType,
1002 NULL,
1003 KernelMode,
1004 NULL,
1005 sizeof(FILE_OBJECT),
1006 0,
1007 0,
1008 (PVOID*)&CreatedFileObject);
1009 if (!NT_SUCCESS(Status))
1010 {
1011 DPRINT1("Could not create FileObject\n");
1012 return (NULL);
1013 }
1014
1015 /* Choose Device Object */
1016 if (FileObject) DeviceObject = FileObject->DeviceObject;
1017 DPRINT("DeviceObject %x\n", DeviceObject);
1018
1019 /* HACK */
1020 DeviceObject = IoGetAttachedDevice(DeviceObject);
1021
1022 /* Set File Object Data */
1023 CreatedFileObject->DeviceObject = DeviceObject;
1024 CreatedFileObject->Vpb = DeviceObject->Vpb;
1025 CreatedFileObject->Type = IO_TYPE_FILE;
1026 /* HACK */
1027 //CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
1028 CreatedFileObject->Flags |= FO_STREAM_FILE;
1029
1030 /* Initialize Lock and Event */
1031 KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
1032 KeInitializeEvent(&CreatedFileObject->Lock, SynchronizationEvent, TRUE);
1033
1034 /* Return file */
1035 return CreatedFileObject;
1036 }
1037
1038 /*
1039 * @unimplemented
1040 */
1041 PFILE_OBJECT
1042 STDCALL
1043 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL,
1044 IN PDEVICE_OBJECT DeviceObject OPTIONAL,
1045 OUT PHANDLE FileObjectHandle OPTIONAL)
1046 {
1047 UNIMPLEMENTED;
1048 return 0;
1049 }
1050
1051 /*
1052 * @unimplemented
1053 */
1054 PFILE_OBJECT
1055 STDCALL
1056 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL,
1057 IN PDEVICE_OBJECT DeviceObject OPTIONAL)
1058 {
1059 UNIMPLEMENTED;
1060 return 0;
1061 }
1062
1063 /*
1064 * @implemented
1065 */
1066 PGENERIC_MAPPING
1067 STDCALL
1068 IoGetFileObjectGenericMapping(VOID)
1069 {
1070 return &IopFileMapping;
1071 }
1072
1073 /*
1074 * @implemented
1075 */
1076 BOOLEAN
1077 STDCALL
1078 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject)
1079 {
1080 /* Return the flag status */
1081 return (FileObject->Flags & FO_REMOTE_ORIGIN);
1082 }
1083
1084 /*
1085 * @unimplemented
1086 */
1087 NTSTATUS
1088 STDCALL
1089 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject,
1090 OUT POBJECT_NAME_INFORMATION *ObjectNameInformation)
1091 {
1092 UNIMPLEMENTED;
1093 return STATUS_NOT_IMPLEMENTED;
1094 }
1095
1096 /*
1097 * @implemented
1098 */
1099 NTSTATUS
1100 STDCALL
1101 IoQueryFileInformation(IN PFILE_OBJECT FileObject,
1102 IN FILE_INFORMATION_CLASS FileInformationClass,
1103 IN ULONG Length,
1104 OUT PVOID FileInformation,
1105 OUT PULONG ReturnedLength)
1106 {
1107 IO_STATUS_BLOCK IoStatusBlock;
1108 PIRP Irp;
1109 PDEVICE_OBJECT DeviceObject;
1110 PIO_STACK_LOCATION StackPtr;
1111 BOOLEAN LocalEvent = FALSE;
1112 KEVENT Event;
1113 NTSTATUS Status;
1114
1115 ASSERT(FileInformation != NULL);
1116
1117 Status = ObReferenceObjectByPointer(FileObject,
1118 FILE_READ_ATTRIBUTES,
1119 IoFileObjectType,
1120 KernelMode);
1121 if (!NT_SUCCESS(Status)) return(Status);
1122
1123 DPRINT("FileObject %x\n", FileObject);
1124
1125 /* Get the Device Object */
1126 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1127
1128 /* Check if we should use Sync IO or not */
1129 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1130 {
1131 /* Use File Object event */
1132 KeClearEvent(&FileObject->Event);
1133 }
1134 else
1135 {
1136 /* Use local event */
1137 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
1138 LocalEvent = TRUE;
1139 }
1140
1141 /* Allocate the IRP */
1142 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1143
1144 /* Set the IRP */
1145 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1146 Irp->RequestorMode = KernelMode;
1147 Irp->AssociatedIrp.SystemBuffer = FileInformation;
1148 Irp->UserIosb = &IoStatusBlock;
1149 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
1150 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1151 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1152
1153 /* Set the Stack Data */
1154 StackPtr = IoGetNextIrpStackLocation(Irp);
1155 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
1156 StackPtr->FileObject = FileObject;
1157
1158 /* Set Parameters */
1159 StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
1160 StackPtr->Parameters.QueryFile.Length = Length;
1161
1162 /* Call the Driver */
1163 Status = IoCallDriver(FileObject->DeviceObject, Irp);
1164
1165 if (Status == STATUS_PENDING)
1166 {
1167 if (LocalEvent)
1168 {
1169 KeWaitForSingleObject(&Event,
1170 Executive,
1171 KernelMode,
1172 FileObject->Flags & FO_ALERTABLE_IO,
1173 NULL);
1174 Status = IoStatusBlock.Status;
1175 }
1176 else
1177 {
1178 KeWaitForSingleObject(&FileObject->Event,
1179 Executive,
1180 KernelMode,
1181 FileObject->Flags & FO_ALERTABLE_IO,
1182 NULL);
1183 Status = FileObject->FinalStatus;
1184 }
1185 }
1186
1187
1188 /* Return the Length and Status. ReturnedLength is NOT optional */
1189 *ReturnedLength = IoStatusBlock.Information;
1190 return Status;
1191 }
1192
1193 /*
1194 * @unimplemented
1195 */
1196 NTSTATUS
1197 STDCALL
1198 IoSetFileOrigin(IN PFILE_OBJECT FileObject,
1199 IN BOOLEAN Remote)
1200 {
1201 UNIMPLEMENTED;
1202 return STATUS_NOT_IMPLEMENTED;
1203 }
1204
1205 /**
1206 * @name NtCancelIoFile
1207 *
1208 * Cancel all pending I/O operations in the current thread for specified
1209 * file object.
1210 *
1211 * @param FileHandle
1212 * Handle to file object to cancel requests for. No specific
1213 * access rights are needed.
1214 * @param IoStatusBlock
1215 * Pointer to status block which is filled with final completition
1216 * status on successful return.
1217 *
1218 * @return Status.
1219 *
1220 * @implemented
1221 */
1222 NTSTATUS
1223 STDCALL
1224 NtCancelIoFile(IN HANDLE FileHandle,
1225 OUT PIO_STATUS_BLOCK IoStatusBlock)
1226 {
1227 NTSTATUS Status;
1228 PFILE_OBJECT FileObject;
1229 PETHREAD Thread;
1230 PLIST_ENTRY IrpEntry;
1231 PIRP Irp;
1232 KIRQL OldIrql;
1233 BOOLEAN OurIrpsInList = FALSE;
1234 LARGE_INTEGER Interval;
1235
1236 if ((ULONG_PTR)IoStatusBlock >= MmUserProbeAddress &&
1237 KeGetPreviousMode() == UserMode)
1238 return STATUS_ACCESS_VIOLATION;
1239
1240 Status = ObReferenceObjectByHandle(FileHandle, 0, IoFileObjectType,
1241 KeGetPreviousMode(), (PVOID*)&FileObject,
1242 NULL);
1243 if (!NT_SUCCESS(Status))
1244 return Status;
1245
1246 /* IRP cancellations are synchronized at APC_LEVEL. */
1247 OldIrql = KfRaiseIrql(APC_LEVEL);
1248
1249 /*
1250 * Walk the list of active IRPs and cancel the ones that belong to
1251 * our file object.
1252 */
1253
1254 Thread = PsGetCurrentThread();
1255 for (IrpEntry = Thread->IrpList.Flink;
1256 IrpEntry != &Thread->IrpList;
1257 IrpEntry = IrpEntry->Flink)
1258 {
1259 Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
1260 if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
1261 {
1262 IoCancelIrp(Irp);
1263 /* Don't break here, we want to cancel all IRPs for the file object. */
1264 OurIrpsInList = TRUE;
1265 }
1266 }
1267
1268 KfLowerIrql(OldIrql);
1269
1270 while (OurIrpsInList)
1271 {
1272 OurIrpsInList = FALSE;
1273
1274 /* Wait a short while and then look if all our IRPs were completed. */
1275 Interval.QuadPart = -1000000; /* 100 milliseconds */
1276 KeDelayExecutionThread(KernelMode, FALSE, &Interval);
1277
1278 OldIrql = KfRaiseIrql(APC_LEVEL);
1279
1280 /*
1281 * Look in the list if all IRPs for the specified file object
1282 * are completed (or cancelled). If someone sends a new IRP
1283 * for our file object while we're here we can happily loop
1284 * forever.
1285 */
1286
1287 for (IrpEntry = Thread->IrpList.Flink;
1288 IrpEntry != &Thread->IrpList;
1289 IrpEntry = IrpEntry->Flink)
1290 {
1291 Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
1292 if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
1293 {
1294 OurIrpsInList = TRUE;
1295 break;
1296 }
1297 }
1298
1299 KfLowerIrql(OldIrql);
1300 }
1301
1302 _SEH_TRY
1303 {
1304 IoStatusBlock->Status = STATUS_SUCCESS;
1305 IoStatusBlock->Information = 0;
1306 Status = STATUS_SUCCESS;
1307 }
1308 _SEH_HANDLE
1309 {
1310 Status = STATUS_UNSUCCESSFUL;
1311 }
1312 _SEH_END;
1313
1314 ObDereferenceObject(FileObject);
1315
1316 return Status;
1317 }
1318
1319 /*
1320 * NAME EXPORTED
1321 * NtCreateFile@44
1322 *
1323 * DESCRIPTION
1324 * Entry point to call IoCreateFile with
1325 * default parameters.
1326 *
1327 * ARGUMENTS
1328 * See IoCreateFile.
1329 *
1330 * RETURN VALUE
1331 * See IoCreateFile.
1332 *
1333 * REVISIONS
1334 * 2000-03-25 (ea)
1335 * Code originally in NtCreateFile moved in IoCreateFile.
1336 *
1337 * @implemented
1338 */
1339 NTSTATUS
1340 STDCALL
1341 NtCreateFile(PHANDLE FileHandle,
1342 ACCESS_MASK DesiredAccess,
1343 POBJECT_ATTRIBUTES ObjectAttributes,
1344 PIO_STATUS_BLOCK IoStatusBlock,
1345 PLARGE_INTEGER AllocateSize,
1346 ULONG FileAttributes,
1347 ULONG ShareAccess,
1348 ULONG CreateDisposition,
1349 ULONG CreateOptions,
1350 PVOID EaBuffer,
1351 ULONG EaLength)
1352 {
1353 /* Call the I/O Function */
1354 return IoCreateFile(FileHandle,
1355 DesiredAccess,
1356 ObjectAttributes,
1357 IoStatusBlock,
1358 AllocateSize,
1359 FileAttributes,
1360 ShareAccess,
1361 CreateDisposition,
1362 CreateOptions,
1363 EaBuffer,
1364 EaLength,
1365 CreateFileTypeNone,
1366 NULL,
1367 0);
1368 }
1369
1370 NTSTATUS
1371 STDCALL
1372 NtCreateMailslotFile(OUT PHANDLE FileHandle,
1373 IN ACCESS_MASK DesiredAccess,
1374 IN POBJECT_ATTRIBUTES ObjectAttributes,
1375 OUT PIO_STATUS_BLOCK IoStatusBlock,
1376 IN ULONG CreateOptions,
1377 IN ULONG MailslotQuota,
1378 IN ULONG MaxMessageSize,
1379 IN PLARGE_INTEGER TimeOut)
1380 {
1381 MAILSLOT_CREATE_PARAMETERS Buffer;
1382
1383 DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
1384 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1385 FileHandle,DesiredAccess,ObjectAttributes,
1386 ObjectAttributes->ObjectName->Buffer);
1387 PAGED_CODE();
1388
1389 /* Check for Timeout */
1390 if (TimeOut)
1391 {
1392 /* Enable it */
1393 Buffer.TimeoutSpecified = TRUE;
1394
1395 /* FIXME: Add SEH */
1396 Buffer.ReadTimeout = *TimeOut;
1397 }
1398 else
1399 {
1400 /* No timeout */
1401 Buffer.TimeoutSpecified = FALSE;
1402 }
1403
1404 /* Set Settings */
1405 Buffer.MailslotQuota = MailslotQuota;
1406 Buffer.MaximumMessageSize = MaxMessageSize;
1407
1408 /* Call I/O */
1409 return IoCreateFile(FileHandle,
1410 DesiredAccess,
1411 ObjectAttributes,
1412 IoStatusBlock,
1413 NULL,
1414 FILE_ATTRIBUTE_NORMAL,
1415 FILE_SHARE_READ | FILE_SHARE_WRITE,
1416 FILE_CREATE,
1417 CreateOptions,
1418 NULL,
1419 0,
1420 CreateFileTypeMailslot,
1421 (PVOID)&Buffer,
1422 0);
1423 }
1424
1425 NTSTATUS
1426 STDCALL
1427 NtCreateNamedPipeFile(PHANDLE FileHandle,
1428 ACCESS_MASK DesiredAccess,
1429 POBJECT_ATTRIBUTES ObjectAttributes,
1430 PIO_STATUS_BLOCK IoStatusBlock,
1431 ULONG ShareAccess,
1432 ULONG CreateDisposition,
1433 ULONG CreateOptions,
1434 ULONG NamedPipeType,
1435 ULONG ReadMode,
1436 ULONG CompletionMode,
1437 ULONG MaximumInstances,
1438 ULONG InboundQuota,
1439 ULONG OutboundQuota,
1440 PLARGE_INTEGER DefaultTimeout)
1441 {
1442 NAMED_PIPE_CREATE_PARAMETERS Buffer;
1443
1444 DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
1445 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1446 FileHandle,DesiredAccess,ObjectAttributes,
1447 ObjectAttributes->ObjectName->Buffer);
1448 PAGED_CODE();
1449
1450 /* Check for Timeout */
1451 if (DefaultTimeout)
1452 {
1453 /* Enable it */
1454 Buffer.TimeoutSpecified = TRUE;
1455
1456 /* FIXME: Add SEH */
1457 Buffer.DefaultTimeout = *DefaultTimeout;
1458 }
1459 else
1460 {
1461 /* No timeout */
1462 Buffer.TimeoutSpecified = FALSE;
1463 }
1464
1465 /* Set Settings */
1466 Buffer.NamedPipeType = NamedPipeType;
1467 Buffer.ReadMode = ReadMode;
1468 Buffer.CompletionMode = CompletionMode;
1469 Buffer.MaximumInstances = MaximumInstances;
1470 Buffer.InboundQuota = InboundQuota;
1471 Buffer.OutboundQuota = OutboundQuota;
1472
1473 /* Call I/O */
1474 return IoCreateFile(FileHandle,
1475 DesiredAccess,
1476 ObjectAttributes,
1477 IoStatusBlock,
1478 NULL,
1479 FILE_ATTRIBUTE_NORMAL,
1480 ShareAccess,
1481 CreateDisposition,
1482 CreateOptions,
1483 NULL,
1484 0,
1485 CreateFileTypeNamedPipe,
1486 (PVOID)&Buffer,
1487 0);
1488 }
1489
1490 /*
1491 * NAME EXPORTED
1492 * NtDeleteFile@4
1493 *
1494 * DESCRIPTION
1495 *
1496 * ARGUMENTS
1497 * ObjectAttributes
1498 * ?
1499 *
1500 * RETURN VALUE
1501 *
1502 * REVISIONS
1503 *
1504 * @unimplemented
1505 */
1506 NTSTATUS
1507 STDCALL
1508 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
1509 {
1510 UNIMPLEMENTED;
1511 return(STATUS_NOT_IMPLEMENTED);
1512 }
1513
1514 NTSTATUS
1515 STDCALL
1516 NtFlushWriteBuffer(VOID)
1517 {
1518 KeFlushWriteBuffer();
1519 return STATUS_SUCCESS;
1520 }
1521
1522 /*
1523 * FUNCTION: Flushes cached file data to disk
1524 * ARGUMENTS:
1525 * FileHandle = Points to the file
1526 * IoStatusBlock = Caller must supply storage to receive the result of
1527 * the flush buffers operation. The information field is
1528 * set to number of bytes flushed to disk.
1529 * RETURNS: Status
1530 * REMARKS: This function maps to the win32 FlushFileBuffers
1531 */
1532 NTSTATUS
1533 STDCALL
1534 NtFlushBuffersFile(IN HANDLE FileHandle,
1535 OUT PIO_STATUS_BLOCK IoStatusBlock)
1536 {
1537 PFILE_OBJECT FileObject = NULL;
1538 PIRP Irp;
1539 PIO_STACK_LOCATION StackPtr;
1540 NTSTATUS Status;
1541 PDEVICE_OBJECT DeviceObject;
1542 KEVENT Event;
1543 BOOLEAN LocalEvent = FALSE;
1544 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
1545
1546 /* Get the File Object */
1547 Status = ObReferenceObjectByHandle(FileHandle,
1548 FILE_WRITE_DATA,
1549 NULL,
1550 PreviousMode,
1551 (PVOID*)&FileObject,
1552 NULL);
1553 if (Status != STATUS_SUCCESS) return(Status);
1554
1555 /* Check if this is a direct open or not */
1556 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
1557 {
1558 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
1559 }
1560 else
1561 {
1562 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1563 }
1564
1565 /* Check if we should use Sync IO or not */
1566 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1567 {
1568 /* Use File Object event */
1569 KeClearEvent(&FileObject->Event);
1570 }
1571 else
1572 {
1573 /* Use local event */
1574 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
1575 LocalEvent = TRUE;
1576 }
1577
1578 /* Allocate the IRP */
1579 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
1580 {
1581 ObDereferenceObject(FileObject);
1582 return STATUS_INSUFFICIENT_RESOURCES;
1583 }
1584
1585 /* Set up the IRP */
1586 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1587 Irp->RequestorMode = PreviousMode;
1588 Irp->UserIosb = IoStatusBlock;
1589 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
1590 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1591 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1592
1593 /* Set up Stack Data */
1594 StackPtr = IoGetNextIrpStackLocation(Irp);
1595 StackPtr->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
1596 StackPtr->FileObject = FileObject;
1597
1598 /* Call the Driver */
1599 Status = IoCallDriver(DeviceObject, Irp);
1600 if (Status == STATUS_PENDING)
1601 {
1602 if (LocalEvent)
1603 {
1604 KeWaitForSingleObject(&Event,
1605 Executive,
1606 PreviousMode,
1607 FileObject->Flags & FO_ALERTABLE_IO,
1608 NULL);
1609 Status = IoStatusBlock->Status;
1610 }
1611 else
1612 {
1613 KeWaitForSingleObject(&FileObject->Event,
1614 Executive,
1615 PreviousMode,
1616 FileObject->Flags & FO_ALERTABLE_IO,
1617 NULL);
1618 Status = FileObject->FinalStatus;
1619 }
1620 }
1621
1622 /* Return the Status */
1623 return Status;
1624 }
1625
1626 /*
1627 * @implemented
1628 */
1629 NTSTATUS
1630 STDCALL
1631 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
1632 IN HANDLE Event OPTIONAL,
1633 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
1634 IN PVOID ApcContext OPTIONAL,
1635 OUT PIO_STATUS_BLOCK IoStatusBlock,
1636 OUT PVOID Buffer,
1637 IN ULONG BufferSize,
1638 IN ULONG CompletionFilter,
1639 IN BOOLEAN WatchTree)
1640 {
1641 PIRP Irp;
1642 PDEVICE_OBJECT DeviceObject;
1643 PFILE_OBJECT FileObject;
1644 PIO_STACK_LOCATION IoStack;
1645 KPROCESSOR_MODE PreviousMode;
1646 NTSTATUS Status = STATUS_SUCCESS;
1647
1648 DPRINT("NtNotifyChangeDirectoryFile()\n");
1649
1650 PAGED_CODE();
1651
1652 PreviousMode = ExGetPreviousMode();
1653
1654 if(PreviousMode != KernelMode)
1655 {
1656 _SEH_TRY
1657 {
1658 ProbeForWrite(IoStatusBlock,
1659 sizeof(IO_STATUS_BLOCK),
1660 sizeof(ULONG));
1661 if(BufferSize != 0)
1662 {
1663 ProbeForWrite(Buffer,
1664 BufferSize,
1665 sizeof(ULONG));
1666 }
1667 }
1668 _SEH_HANDLE
1669 {
1670 Status = _SEH_GetExceptionCode();
1671 }
1672 _SEH_END;
1673
1674 if(!NT_SUCCESS(Status))
1675 {
1676 return Status;
1677 }
1678 }
1679
1680 Status = ObReferenceObjectByHandle(FileHandle,
1681 FILE_LIST_DIRECTORY,
1682 IoFileObjectType,
1683 PreviousMode,
1684 (PVOID *)&FileObject,
1685 NULL);
1686 if (Status != STATUS_SUCCESS) return(Status);
1687
1688
1689 DeviceObject = FileObject->DeviceObject;
1690
1691
1692 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1693 if (Irp==NULL)
1694 {
1695 ObDereferenceObject(FileObject);
1696 return STATUS_UNSUCCESSFUL;
1697 }
1698
1699 if (Event == NULL)
1700 {
1701 Event = &FileObject->Event;
1702 }
1703
1704 /* Trigger FileObject/Event dereferencing */
1705 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1706 Irp->RequestorMode = PreviousMode;
1707 Irp->UserIosb = IoStatusBlock;
1708 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1709 Irp->UserEvent = Event;
1710 KeResetEvent( Event );
1711 Irp->UserBuffer = Buffer;
1712 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
1713 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
1714
1715 IoStack = IoGetNextIrpStackLocation(Irp);
1716
1717 IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
1718 IoStack->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
1719 IoStack->Flags = 0;
1720 IoStack->Control = 0;
1721 IoStack->DeviceObject = DeviceObject;
1722 IoStack->FileObject = FileObject;
1723
1724 if (WatchTree)
1725 {
1726 IoStack->Flags = SL_WATCH_TREE;
1727 }
1728
1729 IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
1730 IoStack->Parameters.NotifyDirectory.Length = BufferSize;
1731
1732 Status = IoCallDriver(FileObject->DeviceObject,Irp);
1733
1734 /* FIXME: Should we wait here or not for synchronously opened files? */
1735
1736 return Status;
1737 }
1738
1739 /*
1740 * @unimplemented
1741 */
1742 NTSTATUS
1743 STDCALL
1744 NtLockFile(IN HANDLE FileHandle,
1745 IN HANDLE EventHandle OPTIONAL,
1746 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
1747 IN PVOID ApcContext OPTIONAL,
1748 OUT PIO_STATUS_BLOCK IoStatusBlock,
1749 IN PLARGE_INTEGER ByteOffset,
1750 IN PLARGE_INTEGER Length,
1751 IN PULONG Key,
1752 IN BOOLEAN FailImmediately,
1753 IN BOOLEAN ExclusiveLock)
1754 {
1755 PFILE_OBJECT FileObject = NULL;
1756 PLARGE_INTEGER LocalLength = NULL;
1757 PIRP Irp = NULL;
1758 PIO_STACK_LOCATION StackPtr;
1759 PDEVICE_OBJECT DeviceObject;
1760 PKEVENT Event = NULL;
1761 BOOLEAN LocalEvent = FALSE;
1762 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
1763 NTSTATUS Status = STATUS_SUCCESS;
1764 OBJECT_HANDLE_INFORMATION HandleInformation;
1765
1766 /* FIXME: instead of this, use SEH */
1767 if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
1768
1769 /* Get File Object */
1770 Status = ObReferenceObjectByHandle(FileHandle,
1771 0,
1772 IoFileObjectType,
1773 PreviousMode,
1774 (PVOID*)&FileObject,
1775 &HandleInformation);
1776 if (!NT_SUCCESS(Status)) return Status;
1777
1778 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
1779 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
1780 {
1781 DPRINT1("Invalid access rights\n");
1782 ObDereferenceObject(FileObject);
1783 return STATUS_ACCESS_DENIED;
1784 }
1785
1786 /* Get Event Object */
1787 if (EventHandle)
1788 {
1789 Status = ObReferenceObjectByHandle(EventHandle,
1790 EVENT_MODIFY_STATE,
1791 ExEventObjectType,
1792 PreviousMode,
1793 (PVOID *)&Event,
1794 NULL);
1795 if (Status != STATUS_SUCCESS) return(Status);
1796 KeClearEvent(Event);
1797 }
1798
1799 /* Check if this is a direct open or not */
1800 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
1801 {
1802 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
1803 }
1804 else
1805 {
1806 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1807 }
1808
1809 /* Check if we should use Sync IO or not */
1810 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1811 {
1812 /* Use File Object event */
1813 KeClearEvent(&FileObject->Event);
1814 }
1815 else
1816 {
1817 LocalEvent = TRUE;
1818 }
1819
1820 /* Allocate the IRP */
1821 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
1822 {
1823 ObDereferenceObject(FileObject);
1824 return STATUS_INSUFFICIENT_RESOURCES;
1825 }
1826
1827 /* Allocate local buffer */
1828 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
1829 sizeof(LARGE_INTEGER),
1830 TAG_LOCK);
1831 if (!LocalLength)
1832 {
1833 IoFreeIrp(Irp);
1834 ObDereferenceObject(FileObject);
1835 return STATUS_INSUFFICIENT_RESOURCES;
1836 }
1837 *LocalLength = *Length;
1838
1839 /* Set up the IRP */
1840 Irp->RequestorMode = PreviousMode;
1841 Irp->UserIosb = IoStatusBlock;
1842 Irp->UserEvent = Event;
1843 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1844 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1845
1846 /* Set up Stack Data */
1847 StackPtr = IoGetNextIrpStackLocation(Irp);
1848 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
1849 StackPtr->MinorFunction = IRP_MN_LOCK;
1850 StackPtr->FileObject = FileObject;
1851
1852 /* Set Parameters */
1853 StackPtr->Parameters.LockControl.Length = LocalLength;
1854 StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
1855 StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
1856
1857 /* Set Flags */
1858 if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
1859 if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
1860
1861 /* Call the Driver */
1862 FileObject->LockOperation = TRUE;
1863 Status = IoCallDriver(DeviceObject, Irp);
1864 if (Status == STATUS_PENDING)
1865 {
1866 if (!LocalEvent)
1867 {
1868 KeWaitForSingleObject(&FileObject->Event,
1869 Executive,
1870 PreviousMode,
1871 FileObject->Flags & FO_ALERTABLE_IO,
1872 NULL);
1873 Status = FileObject->FinalStatus;
1874 }
1875 }
1876
1877 /* Return the Status */
1878 return Status;
1879 }
1880
1881 /*
1882 * NAME EXPORTED
1883 * NtOpenFile@24
1884 *
1885 * DESCRIPTION
1886 * Opens an existing file (simpler than NtCreateFile).
1887 *
1888 * ARGUMENTS
1889 * FileHandle (OUT)
1890 * Variable that receives the file handle on return;
1891 *
1892 * DesiredAccess
1893 * Access desired by the caller to the file;
1894 *
1895 * ObjectAttributes
1896 * Structue describing the file to be opened;
1897 *
1898 * IoStatusBlock (OUT)
1899 * Receives details about the result of the
1900 * operation;
1901 *
1902 * ShareAccess
1903 * Type of shared access the caller requires;
1904 *
1905 * OpenOptions
1906 * Options for the file open.
1907 *
1908 * RETURN VALUE
1909 * Status.
1910 *
1911 * NOTE
1912 * Undocumented.
1913 *
1914 * @implemented
1915 */
1916 NTSTATUS
1917 STDCALL
1918 NtOpenFile(PHANDLE FileHandle,
1919 ACCESS_MASK DesiredAccess,
1920 POBJECT_ATTRIBUTES ObjectAttributes,
1921 PIO_STATUS_BLOCK IoStatusBlock,
1922 ULONG ShareAccess,
1923 ULONG OpenOptions)
1924 {
1925 /* Call the I/O Function */
1926 return IoCreateFile(FileHandle,
1927 DesiredAccess,
1928 ObjectAttributes,
1929 IoStatusBlock,
1930 NULL,
1931 0,
1932 ShareAccess,
1933 FILE_OPEN,
1934 OpenOptions,
1935 NULL,
1936 0,
1937 CreateFileTypeNone,
1938 NULL,
1939 0);
1940 }
1941
1942 NTSTATUS
1943 STDCALL
1944 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
1945 OUT PFILE_BASIC_INFORMATION FileInformation)
1946 {
1947 IO_STATUS_BLOCK IoStatusBlock;
1948 HANDLE FileHandle;
1949 NTSTATUS Status;
1950
1951 /* Open the file */
1952 Status = ZwOpenFile(&FileHandle,
1953 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
1954 ObjectAttributes,
1955 &IoStatusBlock,
1956 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1957 FILE_SYNCHRONOUS_IO_NONALERT);
1958 if (!NT_SUCCESS (Status))
1959 {
1960 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
1961 return Status;
1962 }
1963
1964 /* Get file attributes */
1965 Status = ZwQueryInformationFile(FileHandle,
1966 &IoStatusBlock,
1967 FileInformation,
1968 sizeof(FILE_BASIC_INFORMATION),
1969 FileBasicInformation);
1970 if (!NT_SUCCESS (Status))
1971 {
1972 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
1973 }
1974
1975 ZwClose(FileHandle);
1976 return Status;
1977 }
1978
1979 /*
1980 * @implemented
1981 *
1982 * FUNCTION: Queries a directory file.
1983 * ARGUMENTS:
1984 * FileHandle = Handle to a directory file
1985 * EventHandle = Handle to the event signaled on completion
1986 * ApcRoutine = Asynchroneous procedure callback, called on completion
1987 * ApcContext = Argument to the apc.
1988 * IoStatusBlock = Caller supplies storage for extended status information.
1989 * FileInformation = Caller supplies storage for the resulting information.
1990 *
1991 * FileNameInformation FILE_NAMES_INFORMATION
1992 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
1993 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
1994 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
1995 *
1996 * Length = Size of the storage supplied
1997 * FileInformationClass = Indicates the type of information requested.
1998 * ReturnSingleEntry = Specify true if caller only requests the first
1999 * directory found.
2000 * FileName = Initial directory name to query, that may contain wild
2001 * cards.
2002 * RestartScan = Number of times the action should be repeated
2003 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2004 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2005 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2006 */
2007 NTSTATUS
2008 STDCALL
2009 NtQueryDirectoryFile(IN HANDLE FileHandle,
2010 IN HANDLE PEvent OPTIONAL,
2011 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2012 IN PVOID ApcContext OPTIONAL,
2013 OUT PIO_STATUS_BLOCK IoStatusBlock,
2014 OUT PVOID FileInformation,
2015 IN ULONG Length,
2016 IN FILE_INFORMATION_CLASS FileInformationClass,
2017 IN BOOLEAN ReturnSingleEntry,
2018 IN PUNICODE_STRING FileName OPTIONAL,
2019 IN BOOLEAN RestartScan)
2020 {
2021 PIRP Irp;
2022 PDEVICE_OBJECT DeviceObject;
2023 PFILE_OBJECT FileObject;
2024 PIO_STACK_LOCATION StackPtr;
2025 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2026 NTSTATUS Status = STATUS_SUCCESS;
2027 BOOLEAN LocalEvent = FALSE;
2028 PKEVENT Event = NULL;
2029
2030 DPRINT("NtQueryDirectoryFile()\n");
2031 PAGED_CODE();
2032
2033 /* Validate User-Mode Buffers */
2034 if(PreviousMode != KernelMode)
2035 {
2036 _SEH_TRY
2037 {
2038 ProbeForWrite(IoStatusBlock,
2039 sizeof(IO_STATUS_BLOCK),
2040 sizeof(ULONG));
2041 ProbeForWrite(FileInformation,
2042 Length,
2043 sizeof(ULONG));
2044 }
2045 _SEH_HANDLE
2046 {
2047 Status = _SEH_GetExceptionCode();
2048 }
2049 _SEH_END;
2050
2051 if(!NT_SUCCESS(Status)) return Status;
2052 }
2053
2054 /* Get File Object */
2055 Status = ObReferenceObjectByHandle(FileHandle,
2056 FILE_LIST_DIRECTORY,
2057 IoFileObjectType,
2058 PreviousMode,
2059 (PVOID *)&FileObject,
2060 NULL);
2061 if (Status != STATUS_SUCCESS) return(Status);
2062
2063 /* Get Event Object */
2064 if (PEvent)
2065 {
2066 Status = ObReferenceObjectByHandle(PEvent,
2067 EVENT_MODIFY_STATE,
2068 ExEventObjectType,
2069 PreviousMode,
2070 (PVOID *)&Event,
2071 NULL);
2072 if (Status != STATUS_SUCCESS) return(Status);
2073 KeClearEvent(Event);
2074 }
2075
2076 /* Check if this is a direct open or not */
2077 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2078 {
2079 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2080 }
2081 else
2082 {
2083 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2084 }
2085
2086 /* Check if we should use Sync IO or not */
2087 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2088 {
2089 /* Use File Object event */
2090 KeClearEvent(&FileObject->Event);
2091 }
2092 else
2093 {
2094 LocalEvent = TRUE;
2095 }
2096
2097 /* Allocate the IRP */
2098 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2099 {
2100 ObDereferenceObject(FileObject);
2101 return STATUS_INSUFFICIENT_RESOURCES;
2102 }
2103
2104 /* Set up the IRP */
2105 Irp->RequestorMode = PreviousMode;
2106 Irp->UserIosb = IoStatusBlock;
2107 Irp->UserEvent = Event;
2108 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2109 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2110 Irp->UserBuffer = FileInformation;
2111 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2112 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2113
2114 /* Set up Stack Data */
2115 StackPtr = IoGetNextIrpStackLocation(Irp);
2116 StackPtr->FileObject = FileObject;
2117 StackPtr->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
2118 StackPtr->MinorFunction = IRP_MN_QUERY_DIRECTORY;
2119
2120 /* Set Parameters */
2121 StackPtr->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;
2122 StackPtr->Parameters.QueryDirectory.FileName = FileName;
2123 StackPtr->Parameters.QueryDirectory.FileIndex = 0;
2124 StackPtr->Parameters.QueryDirectory.Length = Length;
2125 StackPtr->Flags = 0;
2126 if (RestartScan) StackPtr->Flags = SL_RESTART_SCAN;
2127 if (ReturnSingleEntry) StackPtr->Flags |= SL_RETURN_SINGLE_ENTRY;
2128
2129 /* Call the Driver */
2130 Status = IoCallDriver(DeviceObject, Irp);
2131 if (Status == STATUS_PENDING)
2132 {
2133 if (!LocalEvent)
2134 {
2135 KeWaitForSingleObject(&FileObject->Event,
2136 Executive,
2137 PreviousMode,
2138 FileObject->Flags & FO_ALERTABLE_IO,
2139 NULL);
2140 Status = FileObject->FinalStatus;
2141 }
2142 }
2143
2144 /* Return the Status */
2145 return Status;
2146 }
2147
2148 /*
2149 * @unimplemented
2150 */
2151 NTSTATUS STDCALL
2152 NtQueryEaFile(IN HANDLE FileHandle,
2153 OUT PIO_STATUS_BLOCK IoStatusBlock,
2154 OUT PVOID Buffer,
2155 IN ULONG Length,
2156 IN BOOLEAN ReturnSingleEntry,
2157 IN PVOID EaList OPTIONAL,
2158 IN ULONG EaListLength,
2159 IN PULONG EaIndex OPTIONAL,
2160 IN BOOLEAN RestartScan)
2161 {
2162 UNIMPLEMENTED;
2163 return STATUS_NOT_IMPLEMENTED;
2164 }
2165
2166 NTSTATUS
2167 STDCALL
2168 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
2169 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
2170 {
2171 IO_STATUS_BLOCK IoStatusBlock;
2172 HANDLE FileHandle;
2173 NTSTATUS Status;
2174
2175 /* Open the file */
2176 Status = ZwOpenFile(&FileHandle,
2177 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
2178 ObjectAttributes,
2179 &IoStatusBlock,
2180 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2181 FILE_SYNCHRONOUS_IO_NONALERT);
2182 if (!NT_SUCCESS (Status))
2183 {
2184 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
2185 return Status;
2186 }
2187
2188 /* Get file attributes */
2189 Status = ZwQueryInformationFile(FileHandle,
2190 &IoStatusBlock,
2191 FileInformation,
2192 sizeof(FILE_NETWORK_OPEN_INFORMATION),
2193 FileNetworkOpenInformation);
2194 if (!NT_SUCCESS (Status))
2195 {
2196 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
2197 }
2198
2199 ZwClose (FileHandle);
2200 return Status;
2201 }
2202
2203 /*
2204 * @implemented
2205 */
2206 NTSTATUS STDCALL
2207 NtQueryInformationFile(HANDLE FileHandle,
2208 PIO_STATUS_BLOCK IoStatusBlock,
2209 PVOID FileInformation,
2210 ULONG Length,
2211 FILE_INFORMATION_CLASS FileInformationClass)
2212 {
2213 OBJECT_HANDLE_INFORMATION HandleInformation;
2214 PFILE_OBJECT FileObject;
2215 NTSTATUS Status;
2216 PIRP Irp;
2217 PDEVICE_OBJECT DeviceObject;
2218 PIO_STACK_LOCATION StackPtr;
2219 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2220 KEVENT Event;
2221 BOOLEAN LocalEvent = FALSE;
2222 BOOLEAN Failed = FALSE;
2223
2224 ASSERT(IoStatusBlock != NULL);
2225 ASSERT(FileInformation != NULL);
2226
2227 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2228 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
2229 Length, FileInformationClass);
2230
2231 /* Reference the Handle */
2232 Status = ObReferenceObjectByHandle(FileHandle,
2233 0,
2234 IoFileObjectType,
2235 PreviousMode,
2236 (PVOID *)&FileObject,
2237 &HandleInformation);
2238 if (!NT_SUCCESS(Status)) return Status;
2239
2240 /* Check information class specific access rights */
2241 switch (FileInformationClass)
2242 {
2243 case FileBasicInformation:
2244 if (!(HandleInformation.GrantedAccess & FILE_READ_ATTRIBUTES))
2245 Failed = TRUE;
2246 break;
2247
2248 case FilePositionInformation:
2249 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
2250 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
2251 Failed = TRUE;
2252 break;
2253
2254 case FileAlignmentInformation:
2255 if (!(FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING))
2256 Failed = TRUE;
2257 break;
2258
2259 default:
2260 break;
2261 }
2262
2263 if (Failed)
2264 {
2265 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2266 ObDereferenceObject(FileObject);
2267 return STATUS_ACCESS_DENIED;
2268 }
2269
2270 DPRINT("FileObject %x\n", FileObject);
2271
2272 /* Check if this is a direct open or not */
2273 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2274 {
2275 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2276 }
2277 else
2278 {
2279 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2280 }
2281
2282 /* Check if we should use Sync IO or not */
2283 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2284 {
2285 /* Use File Object event */
2286 KeClearEvent(&FileObject->Event);
2287 }
2288 else
2289 {
2290 /* Use local event */
2291 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
2292 LocalEvent = TRUE;
2293 }
2294
2295 /* Allocate the IRP */
2296 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2297 {
2298 ObDereferenceObject(FileObject);
2299 return STATUS_INSUFFICIENT_RESOURCES;
2300 }
2301
2302 /* Allocate the System Buffer */
2303 if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2304 Length,
2305 TAG_SYSB)))
2306 {
2307 IoFreeIrp(Irp);
2308 ObDereferenceObject(FileObject);
2309 return STATUS_INSUFFICIENT_RESOURCES;
2310 }
2311
2312 /* Set up the IRP */
2313 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2314 Irp->RequestorMode = PreviousMode;
2315 Irp->UserIosb = IoStatusBlock;
2316 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
2317 Irp->UserBuffer = FileInformation;
2318 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2319 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION;
2320 Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
2321
2322 /* Set up Stack Data */
2323 StackPtr = IoGetNextIrpStackLocation(Irp);
2324 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
2325 StackPtr->FileObject = FileObject;
2326
2327 /* Set the Parameters */
2328 StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
2329 StackPtr->Parameters.QueryFile.Length = Length;
2330
2331 /* Call the Driver */
2332 Status = IoCallDriver(DeviceObject, Irp);
2333 if (Status == STATUS_PENDING)
2334 {
2335 if (LocalEvent)
2336 {
2337 KeWaitForSingleObject(&Event,
2338 Executive,
2339 PreviousMode,
2340 FileObject->Flags & FO_ALERTABLE_IO,
2341 NULL);
2342 Status = IoStatusBlock->Status;
2343 }
2344 else
2345 {
2346 KeWaitForSingleObject(&FileObject->Event,
2347 Executive,
2348 PreviousMode,
2349 FileObject->Flags & FO_ALERTABLE_IO,
2350 NULL);
2351 Status = FileObject->FinalStatus;
2352 }
2353 }
2354
2355 /* Return the Status */
2356 return Status;
2357 }
2358
2359 /*
2360 * @unimplemented
2361 */
2362 NTSTATUS
2363 STDCALL
2364 NtQueryQuotaInformationFile(IN HANDLE FileHandle,
2365 OUT PIO_STATUS_BLOCK IoStatusBlock,
2366 OUT PVOID Buffer,
2367 IN ULONG Length,
2368 IN BOOLEAN ReturnSingleEntry,
2369 IN PVOID SidList OPTIONAL,
2370 IN ULONG SidListLength,
2371 IN PSID StartSid OPTIONAL,
2372 IN BOOLEAN RestartScan)
2373 {
2374 UNIMPLEMENTED;
2375 return STATUS_NOT_IMPLEMENTED;
2376 }
2377
2378 /*
2379 * NAME EXPORTED
2380 * NtReadFile
2381 *
2382 * DESCRIPTION
2383 *
2384 * ARGUMENTS
2385 *
2386 * RETURN VALUE
2387 *
2388 * REVISIONS
2389 *
2390 * @implemented
2391 */
2392 NTSTATUS
2393 STDCALL
2394 NtReadFile(IN HANDLE FileHandle,
2395 IN HANDLE Event OPTIONAL,
2396 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2397 IN PVOID ApcContext OPTIONAL,
2398 OUT PIO_STATUS_BLOCK IoStatusBlock,
2399 OUT PVOID Buffer,
2400 IN ULONG Length,
2401 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
2402 IN PULONG Key OPTIONAL)
2403 {
2404 NTSTATUS Status = STATUS_SUCCESS;
2405 PFILE_OBJECT FileObject;
2406 PIRP Irp = NULL;
2407 PDEVICE_OBJECT DeviceObject;
2408 PIO_STACK_LOCATION StackPtr;
2409 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2410 BOOLEAN LocalEvent = FALSE;
2411 PKEVENT EventObject = NULL;
2412
2413 DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2414 "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
2415 IoStatusBlock);
2416 PAGED_CODE();
2417
2418 /* Validate User-Mode Buffers */
2419 if(PreviousMode != KernelMode)
2420 {
2421 _SEH_TRY
2422 {
2423 ProbeForWrite(IoStatusBlock,
2424 sizeof(IO_STATUS_BLOCK),
2425 sizeof(ULONG));
2426 #if 0
2427 ProbeForWrite(Buffer,
2428 Length,
2429 sizeof(ULONG));
2430 #endif
2431 }
2432 _SEH_HANDLE
2433 {
2434 Status = _SEH_GetExceptionCode();
2435 }
2436 _SEH_END;
2437
2438 if(!NT_SUCCESS(Status)) return Status;
2439 }
2440
2441 /* Get File Object */
2442 Status = ObReferenceObjectByHandle(FileHandle,
2443 FILE_READ_DATA,
2444 IoFileObjectType,
2445 PreviousMode,
2446 (PVOID*)&FileObject,
2447 NULL);
2448 if (!NT_SUCCESS(Status)) return Status;
2449
2450 /* Check the Byte Offset */
2451 if (!ByteOffset ||
2452 (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
2453 ByteOffset->u.HighPart == 0xffffffff))
2454 {
2455 /* a valid ByteOffset is required if asynch. op. */
2456 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
2457 {
2458 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2459 ObDereferenceObject(FileObject);
2460 return STATUS_INVALID_PARAMETER;
2461 }
2462
2463 /* Use the Current Byte OFfset */
2464 ByteOffset = &FileObject->CurrentByteOffset;
2465 }
2466
2467 /* Check for event */
2468 if (Event)
2469 {
2470 /* Reference it */
2471 Status = ObReferenceObjectByHandle(Event,
2472 EVENT_MODIFY_STATE,
2473 ExEventObjectType,
2474 PreviousMode,
2475 (PVOID*)&EventObject,
2476 NULL);
2477 if (!NT_SUCCESS(Status))
2478 {
2479 ObDereferenceObject(FileObject);
2480 return Status;
2481 }
2482 KeClearEvent(EventObject);
2483 }
2484
2485 /* Check if this is a direct open or not */
2486 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2487 {
2488 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2489 }
2490 else
2491 {
2492 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2493 }
2494
2495 /* Check if we should use Sync IO or not */
2496 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2497 {
2498 /* Use File Object event */
2499 KeClearEvent(&FileObject->Event);
2500 }
2501 else
2502 {
2503 LocalEvent = TRUE;
2504 }
2505
2506 /* Create the IRP */
2507 _SEH_TRY
2508 {
2509 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
2510 DeviceObject,
2511 Buffer,
2512 Length,
2513 ByteOffset,
2514 EventObject,
2515 IoStatusBlock);
2516 if (Irp == NULL)
2517 {
2518 Status = STATUS_INSUFFICIENT_RESOURCES;
2519 }
2520 }
2521 _SEH_HANDLE
2522 {
2523 Status = _SEH_GetExceptionCode();
2524 }
2525 _SEH_END;
2526
2527 /* Cleanup if IRP Allocation Failed */
2528 if (!NT_SUCCESS(Status))
2529 {
2530 if (Event) ObDereferenceObject(EventObject);
2531 ObDereferenceObject(FileObject);
2532 return Status;
2533 }
2534
2535 /* Set up IRP Data */
2536 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2537 Irp->RequestorMode = PreviousMode;
2538 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2539 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2540 Irp->Flags |= IRP_READ_OPERATION;
2541 #if 0
2542 /* FIXME:
2543 * Vfat doesn't handle non cached files correctly.
2544 */
2545 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
2546 #endif
2547
2548 /* Setup Stack Data */
2549 StackPtr = IoGetNextIrpStackLocation(Irp);
2550 StackPtr->FileObject = FileObject;
2551 StackPtr->Parameters.Read.Key = Key ? *Key : 0;
2552
2553 /* Call the Driver */
2554 Status = IoCallDriver(DeviceObject, Irp);
2555 if (Status == STATUS_PENDING)
2556 {
2557 if (!LocalEvent)
2558 {
2559 KeWaitForSingleObject(&FileObject->Event,
2560 Executive,
2561 PreviousMode,
2562 FileObject->Flags & FO_ALERTABLE_IO,
2563 NULL);
2564 Status = FileObject->FinalStatus;
2565 }
2566 }
2567
2568 /* Return the Status */
2569 return Status;
2570 }
2571
2572 /*
2573 * NAME EXPORTED
2574 * NtReadFileScatter
2575 *
2576 * DESCRIPTION
2577 *
2578 * ARGUMENTS
2579 *
2580 * RETURN VALUE
2581 *
2582 * REVISIONS
2583 */
2584 NTSTATUS
2585 STDCALL
2586 NtReadFileScatter(IN HANDLE FileHandle,
2587 IN HANDLE Event OPTIONAL,
2588 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
2589 IN PVOID UserApcContext OPTIONAL,
2590 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
2591 IN FILE_SEGMENT_ELEMENT BufferDescription [],
2592 IN ULONG BufferLength,
2593 IN PLARGE_INTEGER ByteOffset,
2594 IN PULONG Key OPTIONAL)
2595 {
2596 UNIMPLEMENTED;
2597 return(STATUS_NOT_IMPLEMENTED);
2598 }
2599
2600 /*
2601 * @unimplemented
2602 */
2603 NTSTATUS
2604 STDCALL
2605 NtSetEaFile(IN HANDLE FileHandle,
2606 IN PIO_STATUS_BLOCK IoStatusBlock,
2607 IN PVOID EaBuffer,
2608 IN ULONG EaBufferSize)
2609 {
2610 UNIMPLEMENTED;
2611 return STATUS_NOT_IMPLEMENTED;
2612 }
2613
2614 /*
2615 * @implemented
2616 */
2617 NTSTATUS STDCALL
2618 NtSetInformationFile(HANDLE FileHandle,
2619 PIO_STATUS_BLOCK IoStatusBlock,
2620 PVOID FileInformation,
2621 ULONG Length,
2622 FILE_INFORMATION_CLASS FileInformationClass)
2623 {
2624 OBJECT_HANDLE_INFORMATION HandleInformation;
2625 PIO_STACK_LOCATION StackPtr;
2626 PFILE_OBJECT FileObject;
2627 PDEVICE_OBJECT DeviceObject;
2628 PIRP Irp;
2629 KEVENT Event;
2630 BOOLEAN LocalEvent = FALSE;
2631 NTSTATUS Status = STATUS_SUCCESS;
2632 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2633 BOOLEAN Failed = FALSE;
2634
2635 ASSERT(IoStatusBlock != NULL);
2636 ASSERT(FileInformation != NULL);
2637
2638 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2639 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
2640 Length, FileInformationClass);
2641
2642 /* Get the file object from the file handle */
2643 Status = ObReferenceObjectByHandle(FileHandle,
2644 0,
2645 IoFileObjectType,
2646 PreviousMode,
2647 (PVOID *)&FileObject,
2648 &HandleInformation);
2649 if (!NT_SUCCESS(Status)) return Status;
2650
2651 /* Check information class specific access rights */
2652 switch (FileInformationClass)
2653 {
2654 case FileBasicInformation:
2655 if (!(HandleInformation.GrantedAccess & FILE_WRITE_ATTRIBUTES))
2656 Failed = TRUE;
2657 break;
2658
2659 case FileDispositionInformation:
2660 if (!(HandleInformation.GrantedAccess & DELETE))
2661 Failed = TRUE;
2662 break;
2663
2664 case FilePositionInformation:
2665 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
2666 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
2667 Failed = TRUE;
2668 break;
2669
2670 case FileEndOfFileInformation:
2671 if (!(HandleInformation.GrantedAccess & FILE_WRITE_DATA))
2672 Failed = TRUE;
2673 break;
2674
2675 default:
2676 break;
2677 }
2678
2679 if (Failed)
2680 {
2681 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2682 ObDereferenceObject(FileObject);
2683 return STATUS_ACCESS_DENIED;
2684 }
2685
2686 DPRINT("FileObject %x\n", FileObject);
2687
2688 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2689 /* Handle IO Completion Port quickly */
2690 if (FileInformationClass == FileCompletionInformation)
2691 {
2692 PVOID Queue;
2693 PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation;
2694 PIO_COMPLETION_CONTEXT Context;
2695
2696 if (Length < sizeof(FILE_COMPLETION_INFORMATION))
2697 {
2698 Status = STATUS_INFO_LENGTH_MISMATCH;
2699 }
2700 else
2701 {
2702 /* Reference the Port */
2703 Status = ObReferenceObjectByHandle(CompletionInfo->IoCompletionHandle,
2704 IO_COMPLETION_MODIFY_STATE,
2705 IoCompletionType,
2706 PreviousMode,
2707 (PVOID*)&Queue,
2708 NULL);
2709 if (NT_SUCCESS(Status))
2710 {
2711 /* Allocate the Context */
2712 Context = ExAllocatePoolWithTag(PagedPool,
2713 sizeof(IO_COMPLETION_CONTEXT),
2714 TAG('I', 'o', 'C', 'p'));
2715
2716 /* Set the Data */
2717 Context->Key = CompletionInfo->CompletionKey;
2718 Context->Port = Queue;
2719 FileObject->CompletionContext = Context;
2720
2721 /* Dereference the Port now */
2722 ObDereferenceObject(Queue);
2723 }
2724 }
2725
2726 /* Complete the I/O */
2727 ObDereferenceObject(FileObject);
2728 return Status;
2729 }
2730
2731 /* Check if this is a direct open or not */
2732 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2733 {
2734 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2735 }
2736 else
2737 {
2738 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2739 }
2740
2741 /* Check if we should use Sync IO or not */
2742 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2743 {
2744 /* Use File Object event */
2745 KeClearEvent(&FileObject->Event);
2746 }
2747 else
2748 {
2749 /* Use local event */
2750 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
2751 LocalEvent = TRUE;
2752 }
2753
2754 /* Allocate the IRP */
2755 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2756 {
2757 ObDereferenceObject(FileObject);
2758 return STATUS_INSUFFICIENT_RESOURCES;
2759 }
2760
2761 /* Allocate the System Buffer */
2762 if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2763 Length,
2764 TAG_SYSB)))
2765 {
2766 IoFreeIrp(Irp);
2767 ObDereferenceObject(FileObject);
2768 return STATUS_INSUFFICIENT_RESOURCES;
2769 }
2770
2771 /* Copy the data inside */
2772 MmSafeCopyFromUser(Irp->AssociatedIrp.SystemBuffer, FileInformation, Length);
2773
2774 /* Set up the IRP */
2775 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2776 Irp->RequestorMode = PreviousMode;
2777 Irp->UserIosb = IoStatusBlock;
2778 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
2779 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2780 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
2781 Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
2782
2783 /* Set up Stack Data */
2784 StackPtr = IoGetNextIrpStackLocation(Irp);
2785 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
2786 StackPtr->FileObject = FileObject;
2787
2788 /* Set the Parameters */
2789 StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass;
2790 StackPtr->Parameters.SetFile.Length = Length;
2791
2792 /* Call the Driver */
2793 Status = IoCallDriver(DeviceObject, Irp);
2794 if (Status == STATUS_PENDING)
2795 {
2796 if (LocalEvent)
2797 {
2798 KeWaitForSingleObject(&Event,
2799 Executive,
2800 PreviousMode,
2801 FileObject->Flags & FO_ALERTABLE_IO,
2802 NULL);
2803 Status = IoStatusBlock->Status;
2804 }
2805 else
2806 {
2807 KeWaitForSingleObject(&FileObject->Event,
2808 Executive,
2809 PreviousMode,
2810 FileObject->Flags & FO_ALERTABLE_IO,
2811 NULL);
2812 Status = FileObject->FinalStatus;
2813 }
2814 }
2815
2816 /* Return the Status */
2817 return Status;
2818 }
2819
2820 /*
2821 * @unimplemented
2822 */
2823 NTSTATUS
2824 STDCALL
2825 NtSetQuotaInformationFile(HANDLE FileHandle,
2826 PIO_STATUS_BLOCK IoStatusBlock,
2827 PFILE_USER_QUOTA_INFORMATION Buffer,
2828 ULONG BufferLength)
2829 {
2830 UNIMPLEMENTED;
2831 return STATUS_NOT_IMPLEMENTED;
2832 }
2833
2834 /*
2835 * @unimplemented
2836 */
2837 NTSTATUS
2838 STDCALL
2839 NtUnlockFile(IN HANDLE FileHandle,
2840 OUT PIO_STATUS_BLOCK IoStatusBlock,
2841 IN PLARGE_INTEGER ByteOffset,
2842 IN PLARGE_INTEGER Length,
2843 OUT PULONG Key OPTIONAL)
2844 {
2845 PFILE_OBJECT FileObject = NULL;
2846 PLARGE_INTEGER LocalLength = NULL;
2847 PIRP Irp = NULL;
2848 PIO_STACK_LOCATION StackPtr;
2849 PDEVICE_OBJECT DeviceObject;
2850 KEVENT Event;
2851 BOOLEAN LocalEvent = FALSE;
2852 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2853 NTSTATUS Status = STATUS_SUCCESS;
2854 OBJECT_HANDLE_INFORMATION HandleInformation;
2855
2856 /* FIXME: instead of this, use SEH */
2857 if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
2858
2859 /* Get File Object */
2860 Status = ObReferenceObjectByHandle(FileHandle,
2861 0,
2862 IoFileObjectType,
2863 PreviousMode,
2864 (PVOID*)&FileObject,
2865 &HandleInformation);
2866 if (!NT_SUCCESS(Status)) return Status;
2867
2868 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
2869 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
2870 {
2871 DPRINT1("Invalid access rights\n");
2872 ObDereferenceObject(FileObject);
2873 return STATUS_ACCESS_DENIED;
2874 }
2875
2876 /* Check if this is a direct open or not */
2877 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2878 {
2879 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2880 }
2881 else
2882 {
2883 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2884 }
2885
2886 /* Check if we should use Sync IO or not */
2887 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2888 {
2889 /* Use File Object event */
2890 KeClearEvent(&FileObject->Event);
2891 }
2892 else
2893 {
2894 /* Use local event */
2895 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
2896 LocalEvent = TRUE;
2897 }
2898
2899 /* Allocate the IRP */
2900 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2901 {
2902 ObDereferenceObject(FileObject);
2903 return STATUS_INSUFFICIENT_RESOURCES;
2904 }
2905
2906 /* Allocate local buffer */
2907 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
2908 sizeof(LARGE_INTEGER),
2909 TAG_LOCK);
2910 if (!LocalLength)
2911 {
2912 IoFreeIrp(Irp);
2913 ObDereferenceObject(FileObject);
2914 return STATUS_INSUFFICIENT_RESOURCES;
2915 }
2916 *LocalLength = *Length;
2917
2918 /* Set up the IRP */
2919 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
2920 Irp->RequestorMode = PreviousMode;
2921 Irp->UserIosb = IoStatusBlock;
2922 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
2923 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2924 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2925
2926 /* Set up Stack Data */
2927 StackPtr = IoGetNextIrpStackLocation(Irp);
2928 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
2929 StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
2930 StackPtr->FileObject = FileObject;
2931
2932 /* Set Parameters */
2933 StackPtr->Parameters.LockControl.Length = LocalLength;
2934 StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
2935 StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
2936
2937 /* Call the Driver */
2938 Status = IoCallDriver(DeviceObject, Irp);
2939 if (Status == STATUS_PENDING)
2940 {
2941 if (LocalEvent)
2942 {
2943 KeWaitForSingleObject(&Event,
2944 Executive,
2945 PreviousMode,
2946 FileObject->Flags & FO_ALERTABLE_IO,
2947 NULL);
2948 Status = IoStatusBlock->Status;
2949 }
2950 else
2951 {
2952 KeWaitForSingleObject(&FileObject->Event,
2953 Executive,
2954 PreviousMode,
2955 FileObject->Flags & FO_ALERTABLE_IO,
2956 NULL);
2957 Status = FileObject->FinalStatus;
2958 }
2959 }
2960
2961 /* Return the Status */
2962 return Status;
2963 }
2964
2965 /*
2966 * NAME EXPORTED
2967 * NtWriteFile
2968 *
2969 * DESCRIPTION
2970 *
2971 * ARGUMENTS
2972 *
2973 * RETURN VALUE
2974 *
2975 * REVISIONS
2976 *
2977 * @implemented
2978 */
2979 NTSTATUS
2980 STDCALL
2981 NtWriteFile (IN HANDLE FileHandle,
2982 IN HANDLE Event OPTIONAL,
2983 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2984 IN PVOID ApcContext OPTIONAL,
2985 OUT PIO_STATUS_BLOCK IoStatusBlock,
2986 IN PVOID Buffer,
2987 IN ULONG Length,
2988 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
2989 IN PULONG Key OPTIONAL)
2990 {
2991 OBJECT_HANDLE_INFORMATION HandleInformation;
2992 NTSTATUS Status = STATUS_SUCCESS;
2993 PFILE_OBJECT FileObject;
2994 PIRP Irp = NULL;
2995 PDEVICE_OBJECT DeviceObject;
2996 PIO_STACK_LOCATION StackPtr;
2997 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2998 BOOLEAN LocalEvent = FALSE;
2999 PKEVENT EventObject = NULL;
3000
3001 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
3002 "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
3003 IoStatusBlock);
3004
3005 /* Validate User-Mode Buffers */
3006 if(PreviousMode != KernelMode)
3007 {
3008 _SEH_TRY
3009 {
3010 #if 0
3011 ProbeForWrite(IoStatusBlock,
3012 sizeof(IO_STATUS_BLOCK),
3013 sizeof(ULONG));
3014
3015 ProbeForRead(Buffer,
3016 Length,
3017 sizeof(ULONG));
3018 #endif
3019 }
3020 _SEH_HANDLE
3021 {
3022 Status = _SEH_GetExceptionCode();
3023 }
3024 _SEH_END;
3025
3026 if(!NT_SUCCESS(Status)) return Status;
3027 }
3028
3029 /* Get File Object */
3030 Status = ObReferenceObjectByHandle(FileHandle,
3031 0,
3032 IoFileObjectType,
3033 PreviousMode,
3034 (PVOID*)&FileObject,
3035 &HandleInformation);
3036 if (!NT_SUCCESS(Status)) return Status;
3037
3038 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3039 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
3040 {
3041 DPRINT1("Invalid access rights\n");
3042 ObDereferenceObject(FileObject);
3043 return STATUS_ACCESS_DENIED;
3044 }
3045
3046 /* Check if we got write Access */
3047 if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
3048 {
3049 /* Check the Byte Offset */
3050 if (!ByteOffset ||
3051 (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
3052 ByteOffset->u.HighPart == 0xffffffff))
3053 {
3054 /* a valid ByteOffset is required if asynch. op. */
3055 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3056 {
3057 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3058 ObDereferenceObject(FileObject);
3059 return STATUS_INVALID_PARAMETER;
3060 }
3061
3062 /* Use the Current Byte OFfset */
3063 ByteOffset = &FileObject->CurrentByteOffset;
3064 }
3065 }
3066 else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
3067 {
3068 /* a valid ByteOffset is required if asynch. op. */
3069 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3070 {
3071 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3072 ObDereferenceObject(FileObject);
3073 return STATUS_INVALID_PARAMETER;
3074 }
3075
3076 /* Give the drivers somethign to understand */
3077 ByteOffset->u.LowPart = FILE_WRITE_TO_END_OF_FILE;
3078 ByteOffset->u.HighPart = 0xffffffff;
3079 }
3080
3081 /* Check if we got an event */
3082 if (Event)
3083 {
3084 /* Reference it */
3085 Status = ObReferenceObjectByHandle(Event,
3086 EVENT_MODIFY_STATE,
3087 ExEventObjectType,
3088 PreviousMode,
3089 (PVOID*)&EventObject,
3090 NULL);
3091 if (!NT_SUCCESS(Status))
3092 {
3093 ObDereferenceObject(FileObject);
3094 return Status;
3095 }
3096 KeClearEvent(EventObject);
3097 }
3098
3099 /* Check if this is a direct open or not */
3100 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3101 {
3102 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
3103 }
3104 else
3105 {
3106 DeviceObject = IoGetRelatedDeviceObject(FileObject);
3107 }
3108
3109 /* Check if we should use Sync IO or not */
3110 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3111 {
3112 /* Use File Object event */
3113 KeClearEvent(&FileObject->Event);
3114 }
3115 else
3116 {
3117 LocalEvent = TRUE;
3118 }
3119
3120 /* Build the IRP */
3121 _SEH_TRY
3122 {
3123 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
3124 DeviceObject,
3125 Buffer,
3126 Length,
3127 ByteOffset,
3128 EventObject,
3129 IoStatusBlock);
3130 if (Irp == NULL)
3131 {
3132 Status = STATUS_INSUFFICIENT_RESOURCES;
3133 }
3134 }
3135 _SEH_HANDLE
3136 {
3137 Status = _SEH_GetExceptionCode();
3138 }
3139 _SEH_END;
3140
3141 /* Cleanup on failure */
3142 if (!NT_SUCCESS(Status))
3143 {
3144 if (Event)
3145 {
3146 ObDereferenceObject(&EventObject);
3147 }
3148 ObDereferenceObject(FileObject);
3149 return Status;
3150 }
3151
3152 /* Set up IRP Data */
3153 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3154 Irp->RequestorMode = PreviousMode;
3155 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
3156 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
3157 Irp->Flags |= IRP_WRITE_OPERATION;
3158 #if 0
3159 /* FIXME:
3160 * Vfat doesn't handle non cached files correctly.
3161 */
3162 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
3163 #endif
3164
3165 /* Setup Stack Data */
3166 StackPtr = IoGetNextIrpStackLocation(Irp);
3167 StackPtr->FileObject = FileObject;
3168 StackPtr->Parameters.Write.Key = Key ? *Key : 0;
3169 if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
3170
3171 /* Call the Driver */
3172 Status = IoCallDriver(DeviceObject, Irp);
3173 if (Status == STATUS_PENDING)
3174 {
3175 if (!LocalEvent)
3176 {
3177 KeWaitForSingleObject(&FileObject->Event,
3178 Executive,
3179 PreviousMode,
3180 FileObject->Flags & FO_ALERTABLE_IO,
3181 NULL);
3182 Status = FileObject->FinalStatus;
3183 }
3184 }
3185
3186 /* Return the Status */
3187 return Status;
3188 }
3189
3190 /*
3191 * NAME EXPORTED
3192 * NtWriteFileGather
3193 *
3194 * DESCRIPTION
3195 *
3196 * ARGUMENTS
3197 *
3198 * RETURN VALUE
3199 *
3200 * REVISIONS
3201 */
3202 NTSTATUS
3203 STDCALL
3204 NtWriteFileGather(IN HANDLE FileHandle,
3205 IN HANDLE Event OPTIONAL,
3206 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
3207 IN PVOID UserApcContext OPTIONAL,
3208 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
3209 IN FILE_SEGMENT_ELEMENT BufferDescription [],
3210 IN ULONG BufferLength,
3211 IN PLARGE_INTEGER ByteOffset,
3212 IN PULONG Key OPTIONAL)
3213 {
3214 UNIMPLEMENTED;
3215 return(STATUS_NOT_IMPLEMENTED);
3216 }
3217 /* EOF */