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.
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS *******************************************************************/
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')
23 extern GENERIC_MAPPING IopFileMapping
;
27 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation
,
28 PSECURITY_DESCRIPTOR SecurityDescriptor
,
31 /* INTERNAL FUNCTIONS ********************************************************/
47 IopCreateFile(PVOID ObjectBody
,
50 POBJECT_ATTRIBUTES ObjectAttributes
)
52 PDEVICE_OBJECT DeviceObject
;
53 PFILE_OBJECT FileObject
= (PFILE_OBJECT
) ObjectBody
;
54 POBJECT_TYPE ParentObjectType
;
57 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
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
);
70 ParentObjectType
= BODY_TO_HEADER(Parent
)->ObjectType
;
72 if (ParentObjectType
!= IoDeviceObjectType
&&
73 ParentObjectType
!= IoFileObjectType
)
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
,
79 return(STATUS_UNSUCCESSFUL
);
82 Status
= ObReferenceObjectByPointer(Parent
,
83 STANDARD_RIGHTS_REQUIRED
,
86 if (!NT_SUCCESS(Status
))
88 CPRINT("Failed to reference parent object %x\n", Parent
);
92 if (ParentObjectType
== IoDeviceObjectType
)
94 /* Parent is a devce object */
95 DeviceObject
= IoGetAttachedDevice((PDEVICE_OBJECT
)Parent
);
96 DPRINT("DeviceObject %x\n", DeviceObject
);
98 if (RemainingPath
== NULL
)
100 FileObject
->Flags
= FileObject
->Flags
| FO_DIRECT_DEVICE_OPEN
;
101 FileObject
->FileName
.Buffer
= 0;
102 FileObject
->FileName
.Length
= FileObject
->FileName
.MaximumLength
= 0;
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
))
114 CPRINT("Device was wrong type\n");
115 return(STATUS_UNSUCCESSFUL
);
118 if (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
119 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
120 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
122 if (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
124 DPRINT("Mount the logical volume\n");
125 Status
= IoMountVolume(DeviceObject
, FALSE
);
126 DPRINT("Status %x\n", Status
);
127 if (!NT_SUCCESS(Status
))
129 CPRINT("Failed to mount logical volume (Status %x)\n",
134 DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
135 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
137 RtlpCreateUnicodeString(&(FileObject
->FileName
),
138 RemainingPath
, NonPagedPool
);
143 /* Parent is a file object */
144 if (RemainingPath
== NULL
)
146 CPRINT("Device is unnamed\n");
147 return STATUS_UNSUCCESSFUL
;
150 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
151 DPRINT("DeviceObject %x\n", DeviceObject
);
153 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
155 RtlpCreateUnicodeString(&(FileObject
->FileName
),
156 RemainingPath
, NonPagedPool
);
159 DPRINT("FileObject->FileName %wZ\n",
160 &FileObject
->FileName
);
161 FileObject
->DeviceObject
= DeviceObject
;
162 DPRINT("FileObject %x DeviceObject %x\n",
165 FileObject
->Vpb
= DeviceObject
->Vpb
;
166 FileObject
->Type
= IO_TYPE_FILE
;
168 return(STATUS_SUCCESS
);
173 IopDeleteFile(PVOID ObjectBody
)
175 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
177 PIO_STACK_LOCATION StackPtr
;
180 PDEVICE_OBJECT DeviceObject
;
182 DPRINT("IopDeleteFile()\n");
184 if (FileObject
->DeviceObject
)
186 /* Check if this is a direct open or not */
187 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
189 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
193 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
196 /* Clear and set up Events */
197 KeClearEvent(&FileObject
->Event
);
198 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
200 /* Allocate an IRP */
201 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
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
;
210 /* Set up Stack Pointer Data */
211 StackPtr
= IoGetNextIrpStackLocation(Irp
);
212 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
213 StackPtr
->DeviceObject
= DeviceObject
;
214 StackPtr
->FileObject
= FileObject
;
216 /* Call the FS Driver */
217 Status
= IoCallDriver(DeviceObject
, Irp
);
219 /* Wait for completion */
220 if (Status
== STATUS_PENDING
)
222 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
228 /* Clear the file name */
229 if (FileObject
->FileName
.Buffer
)
231 ExFreePool(FileObject
->FileName
.Buffer
);
232 FileObject
->FileName
.Buffer
= NULL
;
235 /* Free the completion context */
236 if (FileObject
->CompletionContext
)
238 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
239 ExFreePool(FileObject
->CompletionContext
);
245 IopSecurityFile(PVOID ObjectBody
,
246 SECURITY_OPERATION_CODE OperationCode
,
247 SECURITY_INFORMATION SecurityInformation
,
248 PSECURITY_DESCRIPTOR SecurityDescriptor
,
251 IO_STATUS_BLOCK IoStatusBlock
;
252 PIO_STACK_LOCATION StackPtr
;
253 PFILE_OBJECT FileObject
;
254 PDEVICE_OBJECT DeviceObject
;
257 BOOLEAN LocalEvent
= FALSE
;
259 NTSTATUS Status
= STATUS_SUCCESS
;
261 DPRINT("IopSecurityFile() called\n");
263 FileObject
= (PFILE_OBJECT
)ObjectBody
;
265 if (OperationCode
== QuerySecurityDescriptor
)
267 MajorFunction
= IRP_MJ_QUERY_SECURITY
;
268 DPRINT("Query security descriptor\n");
270 else if (OperationCode
== DeleteSecurityDescriptor
)
273 return STATUS_SUCCESS
;
275 else if (OperationCode
== AssignSecurityDescriptor
)
277 /* If this is a direct open, we can assign it */
278 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
280 /* Get the Device Object */
282 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
284 /* Assign the Security Descriptor */
285 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
287 return STATUS_SUCCESS
;
291 MajorFunction
= IRP_MJ_SET_SECURITY
;
292 DPRINT("Set security descriptor\n");
294 /* If this is a direct open, we can set it */
295 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
297 DPRINT1("Set SD unimplemented for Devices\n");
298 return STATUS_SUCCESS
;
302 /* Get the Device Object */
303 DPRINT1("FileObject: %p\n", FileObject
);
304 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
306 /* Check if we should use Sync IO or not */
307 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
309 /* Use File Object event */
310 KeClearEvent(&FileObject
->Event
);
314 /* Use local event */
315 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
319 /* Allocate the IRP */
320 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
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();
330 /* Set Stack Parameters */
331 StackPtr
= IoGetNextIrpStackLocation(Irp
);
332 StackPtr
->FileObject
= FileObject
;
335 if (OperationCode
== QuerySecurityDescriptor
)
337 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
= SecurityInformation
;
338 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
339 Irp
->UserBuffer
= SecurityDescriptor
;
343 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
= SecurityInformation
;
344 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
= SecurityDescriptor
;
347 ObReferenceObject(FileObject
);
349 /* Call the Driver */
350 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
352 if (Status
== STATUS_PENDING
)
356 KeWaitForSingleObject(&Event
,
359 FileObject
->Flags
& FO_ALERTABLE_IO
,
361 Status
= IoStatusBlock
.Status
;
365 KeWaitForSingleObject(&FileObject
->Event
,
368 FileObject
->Flags
& FO_ALERTABLE_IO
,
370 Status
= FileObject
->FinalStatus
;
374 /* This Driver doesn't implement Security, so try to give it a default */
375 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
377 if (OperationCode
== QuerySecurityDescriptor
)
379 /* Set a World Security Descriptor */
380 Status
= SeSetWorldSecurityDescriptor(SecurityInformation
,
386 /* It wasn't a query, so just fake success */
387 Status
= STATUS_SUCCESS
;
390 else if (OperationCode
== QuerySecurityDescriptor
)
393 *BufferLength
= IoStatusBlock
.Information
;
402 IopQueryNameFile(PVOID ObjectBody
,
403 POBJECT_NAME_INFORMATION ObjectNameInfo
,
408 PFILE_OBJECT FileObject
;
409 ULONG LocalReturnLength
;
412 DPRINT1("IopQueryNameFile() called\n");
414 FileObject
= (PFILE_OBJECT
)ObjectBody
;
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
;
423 Status
= ObQueryNameString(FileObject
->DeviceObject
,
425 MAX_PATH
* sizeof(WCHAR
),
427 if (!NT_SUCCESS (Status
))
429 ExFreePool (LocalInfo
);
432 DPRINT ("Device path: %wZ\n", &LocalInfo
->Name
);
434 /* Write Device Path */
435 Status
= RtlAppendUnicodeStringToString(&ObjectNameInfo
->Name
,
436 &((POBJECT_NAME_INFORMATION
)LocalInfo
)->Name
);
438 /* Query the File name */
439 Status
= IoQueryFileInformation(FileObject
,
444 if (Status
!= STATUS_SUCCESS
)
446 ExFreePool(LocalInfo
);
451 Status
= RtlAppendUnicodeToString(&ObjectNameInfo
->Name
,
452 ((PFILE_NAME_INFORMATION
)LocalInfo
)->FileName
);
453 DPRINT ("Total path: %wZ\n", &ObjectNameInfo
->Name
);
455 /* Free buffer and return */
456 ExFreePool(LocalInfo
);
462 IopCloseFile(PVOID ObjectBody
,
465 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
468 PIO_STACK_LOCATION StackPtr
;
470 PDEVICE_OBJECT DeviceObject
;
472 DPRINT("IopCloseFile()\n");
474 if (HandleCount
> 1 || FileObject
->DeviceObject
== NULL
) return;
476 /* Check if this is a direct open or not */
477 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
479 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
483 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
486 /* Clear and set up Events */
487 KeClearEvent(&FileObject
->Event
);
488 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
490 /* Allocate an IRP */
491 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
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
;
500 /* Set up Stack Pointer Data */
501 StackPtr
= IoGetNextIrpStackLocation(Irp
);
502 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
503 StackPtr
->FileObject
= FileObject
;
505 /* Call the FS Driver */
506 Status
= IoCallDriver(DeviceObject
, Irp
);
508 /* Wait for completion */
509 if (Status
== STATUS_PENDING
)
511 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
516 /* FUNCTIONS *****************************************************************/
523 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
525 IN BOOLEAN SetOperation
)
528 return STATUS_NOT_IMPLEMENTED
;
536 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
537 IN ULONG QuotaLength
,
538 OUT PULONG ErrorOffset
)
541 return STATUS_NOT_IMPLEMENTED
;
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.
557 * Points to a variable which receives the file handle
561 * Desired access to the file;
564 * Structure describing the file;
566 * IoStatusBlock (OUT)
567 * Receives information about the operation on return;
569 * AllocationSize [OPTIONAL]
570 * Initial size of the file in bytes;
573 * Attributes to create the file with;
576 * Type of shared access the caller would like to the
580 * Specifies what to do, depending on whether the
581 * file already exists;
584 * Options for creating a new file;
586 * EaBuffer [OPTIONAL]
593 * Type of file (normal, named pipe, mailslot) to create;
595 * ExtraCreateParameters [OPTIONAL]
596 * Additional creation data for named pipe and mailsots;
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.
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
,
626 IN CREATE_FILE_TYPE CreateFileType
,
627 IN PVOID ExtraCreateParameters OPTIONAL
,
630 PFILE_OBJECT FileObject
= NULL
;
631 PDEVICE_OBJECT DeviceObject
;
633 PIO_STACK_LOCATION StackLoc
;
634 IO_SECURITY_CONTEXT SecurityContext
;
635 KPROCESSOR_MODE AccessMode
;
637 IO_STATUS_BLOCK LocalIoStatusBlock
;
638 LARGE_INTEGER SafeAllocationSize
;
639 PVOID SystemEaBuffer
= NULL
;
640 NTSTATUS Status
= STATUS_SUCCESS
;
642 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
643 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
644 FileHandle
,DesiredAccess
,ObjectAttributes
,
645 ObjectAttributes
->ObjectName
->Buffer
);
647 ASSERT_IRQL(PASSIVE_LEVEL
);
649 if (IoStatusBlock
== NULL
|| FileHandle
== NULL
)
650 return STATUS_ACCESS_VIOLATION
;
654 if(Options
& IO_NO_PARAMETER_CHECKING
)
655 AccessMode
= KernelMode
;
657 AccessMode
= ExGetPreviousMode();
659 if(AccessMode
!= KernelMode
)
663 ProbeForWrite(FileHandle
,
666 ProbeForWrite(IoStatusBlock
,
667 sizeof(IO_STATUS_BLOCK
),
669 if(AllocationSize
!= NULL
)
671 ProbeForRead(AllocationSize
,
672 sizeof(LARGE_INTEGER
),
674 SafeAllocationSize
= *AllocationSize
;
677 SafeAllocationSize
.QuadPart
= 0;
679 if(EaBuffer
!= NULL
&& EaLength
> 0)
681 ProbeForRead(EaBuffer
,
685 /* marshal EaBuffer */
686 SystemEaBuffer
= ExAllocatePool(NonPagedPool
,
688 if(SystemEaBuffer
== NULL
)
690 Status
= STATUS_INSUFFICIENT_RESOURCES
;
694 RtlCopyMemory(SystemEaBuffer
,
701 Status
= _SEH_GetExceptionCode();
705 if(!NT_SUCCESS(Status
))
712 if(AllocationSize
!= NULL
)
713 SafeAllocationSize
= *AllocationSize
;
715 SafeAllocationSize
.QuadPart
= 0;
717 if(EaBuffer
!= NULL
&& EaLength
> 0)
719 SystemEaBuffer
= EaBuffer
;
723 if(Options
& IO_CHECK_CREATE_PARAMETERS
)
725 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
728 if (CreateDisposition
== FILE_OPEN
||
729 CreateDisposition
== FILE_OPEN_IF
)
731 Status
= ObOpenObjectByName(ObjectAttributes
,
738 if (NT_SUCCESS(Status
))
740 Status
= ObReferenceObjectByHandle(LocalHandle
,
744 (PVOID
*)&DeviceObject
,
746 ZwClose(LocalHandle
);
747 if (!NT_SUCCESS(Status
))
751 if (BODY_TO_HEADER(DeviceObject
)->ObjectType
!= IoDeviceObjectType
)
753 ObDereferenceObject (DeviceObject
);
754 return STATUS_OBJECT_NAME_COLLISION
;
757 FileObject
= IoCreateStreamFileObject(NULL
, DeviceObject
);
758 ObDereferenceObject (DeviceObject
);
763 if (FileObject
== NULL
)
765 Status
= ObCreateObject(AccessMode
,
773 (PVOID
*)&FileObject
);
774 if (!NT_SUCCESS(Status
))
776 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
780 RtlMapGenericMask(&DesiredAccess
,
781 &BODY_TO_HEADER(FileObject
)->ObjectType
->TypeInfo
.GenericMapping
);
783 Status
= ObInsertObject ((PVOID
)FileObject
,
789 if (!NT_SUCCESS(Status
))
791 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
792 ObDereferenceObject (FileObject
);
796 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
798 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
800 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
802 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
805 if (CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
806 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
808 SecurityContext
.SecurityQos
= NULL
; /* ?? */
809 SecurityContext
.AccessState
= NULL
; /* ?? */
810 SecurityContext
.DesiredAccess
= DesiredAccess
;
811 SecurityContext
.FullCreateOptions
= 0; /* ?? */
813 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
814 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
816 DPRINT("FileObject %x\n", FileObject
);
817 DPRINT("FileObject->DeviceObject %x\n", FileObject
->DeviceObject
);
819 * Create a new IRP to hand to
820 * the FS driver: this may fail
821 * due to resource shortage.
823 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
826 ZwClose(LocalHandle
);
827 return STATUS_UNSUCCESSFUL
;
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
;
841 * Get the stack location for the new
842 * IRP and prepare it.
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
;
851 switch (CreateFileType
)
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;
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
;
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
;
884 * Now call the driver and
885 * possibly wait if it can
886 * not complete the request
889 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
890 DPRINT("Status :%x\n", Status
);
892 if (Status
== STATUS_PENDING
)
894 KeWaitForSingleObject(&FileObject
->Event
,
899 Status
= LocalIoStatusBlock
.Status
;
901 if (!NT_SUCCESS(Status
))
903 DPRINT("Failing create request with status %x\n", Status
);
904 FileObject
->DeviceObject
= NULL
;
905 FileObject
->Vpb
= NULL
;
907 ZwClose(LocalHandle
);
913 *FileHandle
= LocalHandle
;
914 *IoStatusBlock
= LocalIoStatusBlock
;
918 Status
= _SEH_GetExceptionCode();
923 /* cleanup EABuffer if captured */
924 if(AccessMode
!= KernelMode
&& SystemEaBuffer
!= NULL
)
926 ExFreePool(SystemEaBuffer
);
929 ASSERT_IRQL(PASSIVE_LEVEL
);
931 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle
));
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
,
952 IN CREATE_FILE_TYPE CreateFileType
,
953 IN PVOID ExtraCreateParameters OPTIONAL
,
955 IN PVOID DeviceObject
)
958 return STATUS_NOT_IMPLEMENTED
;
963 * IoCreateStreamFileObject@8
984 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
985 PDEVICE_OBJECT DeviceObject
)
987 PFILE_OBJECT CreatedFileObject
;
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.
995 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
996 FileObject
, DeviceObject
);
999 /* Create the File Object */
1000 Status
= ObCreateObject(KernelMode
,
1005 sizeof(FILE_OBJECT
),
1008 (PVOID
*)&CreatedFileObject
);
1009 if (!NT_SUCCESS(Status
))
1011 DPRINT1("Could not create FileObject\n");
1015 /* Choose Device Object */
1016 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1017 DPRINT("DeviceObject %x\n", DeviceObject
);
1020 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1022 /* Set File Object Data */
1023 CreatedFileObject
->DeviceObject
= DeviceObject
;
1024 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
1025 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1027 //CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
1028 CreatedFileObject
->Flags
|= FO_STREAM_FILE
;
1030 /* Initialize Lock and Event */
1031 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
1032 KeInitializeEvent(&CreatedFileObject
->Lock
, SynchronizationEvent
, TRUE
);
1035 return CreatedFileObject
;
1043 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1044 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1045 OUT PHANDLE FileObjectHandle OPTIONAL
)
1056 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1057 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1068 IoGetFileObjectGenericMapping(VOID
)
1070 return &IopFileMapping
;
1078 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
1080 /* Return the flag status */
1081 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
1089 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
1090 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
1093 return STATUS_NOT_IMPLEMENTED
;
1101 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1102 IN FILE_INFORMATION_CLASS FileInformationClass
,
1104 OUT PVOID FileInformation
,
1105 OUT PULONG ReturnedLength
)
1107 IO_STATUS_BLOCK IoStatusBlock
;
1109 PDEVICE_OBJECT DeviceObject
;
1110 PIO_STACK_LOCATION StackPtr
;
1111 BOOLEAN LocalEvent
= FALSE
;
1115 ASSERT(FileInformation
!= NULL
);
1117 Status
= ObReferenceObjectByPointer(FileObject
,
1118 FILE_READ_ATTRIBUTES
,
1121 if (!NT_SUCCESS(Status
)) return(Status
);
1123 DPRINT("FileObject %x\n", FileObject
);
1125 /* Get the Device Object */
1126 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1128 /* Check if we should use Sync IO or not */
1129 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1131 /* Use File Object event */
1132 KeClearEvent(&FileObject
->Event
);
1136 /* Use local event */
1137 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1141 /* Allocate the IRP */
1142 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
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();
1153 /* Set the Stack Data */
1154 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1155 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1156 StackPtr
->FileObject
= FileObject
;
1158 /* Set Parameters */
1159 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1160 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1162 /* Call the Driver */
1163 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
1165 if (Status
== STATUS_PENDING
)
1169 KeWaitForSingleObject(&Event
,
1172 FileObject
->Flags
& FO_ALERTABLE_IO
,
1174 Status
= IoStatusBlock
.Status
;
1178 KeWaitForSingleObject(&FileObject
->Event
,
1181 FileObject
->Flags
& FO_ALERTABLE_IO
,
1183 Status
= FileObject
->FinalStatus
;
1188 /* Return the Length and Status. ReturnedLength is NOT optional */
1189 *ReturnedLength
= IoStatusBlock
.Information
;
1198 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
1202 return STATUS_NOT_IMPLEMENTED
;
1206 * @name NtCancelIoFile
1208 * Cancel all pending I/O operations in the current thread for specified
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.
1224 NtCancelIoFile(IN HANDLE FileHandle
,
1225 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1228 PFILE_OBJECT FileObject
;
1230 PLIST_ENTRY IrpEntry
;
1233 BOOLEAN OurIrpsInList
= FALSE
;
1234 LARGE_INTEGER Interval
;
1236 if ((ULONG_PTR
)IoStatusBlock
>= MmUserProbeAddress
&&
1237 KeGetPreviousMode() == UserMode
)
1238 return STATUS_ACCESS_VIOLATION
;
1240 Status
= ObReferenceObjectByHandle(FileHandle
, 0, IoFileObjectType
,
1241 KeGetPreviousMode(), (PVOID
*)&FileObject
,
1243 if (!NT_SUCCESS(Status
))
1246 /* IRP cancellations are synchronized at APC_LEVEL. */
1247 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1250 * Walk the list of active IRPs and cancel the ones that belong to
1254 Thread
= PsGetCurrentThread();
1255 for (IrpEntry
= Thread
->IrpList
.Flink
;
1256 IrpEntry
!= &Thread
->IrpList
;
1257 IrpEntry
= IrpEntry
->Flink
)
1259 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1260 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1263 /* Don't break here, we want to cancel all IRPs for the file object. */
1264 OurIrpsInList
= TRUE
;
1268 KfLowerIrql(OldIrql
);
1270 while (OurIrpsInList
)
1272 OurIrpsInList
= FALSE
;
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
);
1278 OldIrql
= KfRaiseIrql(APC_LEVEL
);
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
1287 for (IrpEntry
= Thread
->IrpList
.Flink
;
1288 IrpEntry
!= &Thread
->IrpList
;
1289 IrpEntry
= IrpEntry
->Flink
)
1291 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1292 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1294 OurIrpsInList
= TRUE
;
1299 KfLowerIrql(OldIrql
);
1304 IoStatusBlock
->Status
= STATUS_SUCCESS
;
1305 IoStatusBlock
->Information
= 0;
1306 Status
= STATUS_SUCCESS
;
1310 Status
= STATUS_UNSUCCESSFUL
;
1314 ObDereferenceObject(FileObject
);
1324 * Entry point to call IoCreateFile with
1325 * default parameters.
1335 * Code originally in NtCreateFile moved in IoCreateFile.
1341 NtCreateFile(PHANDLE FileHandle
,
1342 ACCESS_MASK DesiredAccess
,
1343 POBJECT_ATTRIBUTES ObjectAttributes
,
1344 PIO_STATUS_BLOCK IoStatusBlock
,
1345 PLARGE_INTEGER AllocateSize
,
1346 ULONG FileAttributes
,
1348 ULONG CreateDisposition
,
1349 ULONG CreateOptions
,
1353 /* Call the I/O Function */
1354 return IoCreateFile(FileHandle
,
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
)
1381 MAILSLOT_CREATE_PARAMETERS Buffer
;
1383 DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
1384 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1385 FileHandle
,DesiredAccess
,ObjectAttributes
,
1386 ObjectAttributes
->ObjectName
->Buffer
);
1389 /* Check for Timeout */
1393 Buffer
.TimeoutSpecified
= TRUE
;
1395 /* FIXME: Add SEH */
1396 Buffer
.ReadTimeout
= *TimeOut
;
1401 Buffer
.TimeoutSpecified
= FALSE
;
1405 Buffer
.MailslotQuota
= MailslotQuota
;
1406 Buffer
.MaximumMessageSize
= MaxMessageSize
;
1409 return IoCreateFile(FileHandle
,
1414 FILE_ATTRIBUTE_NORMAL
,
1415 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1420 CreateFileTypeMailslot
,
1427 NtCreateNamedPipeFile(PHANDLE FileHandle
,
1428 ACCESS_MASK DesiredAccess
,
1429 POBJECT_ATTRIBUTES ObjectAttributes
,
1430 PIO_STATUS_BLOCK IoStatusBlock
,
1432 ULONG CreateDisposition
,
1433 ULONG CreateOptions
,
1434 ULONG NamedPipeType
,
1436 ULONG CompletionMode
,
1437 ULONG MaximumInstances
,
1439 ULONG OutboundQuota
,
1440 PLARGE_INTEGER DefaultTimeout
)
1442 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
1444 DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
1445 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1446 FileHandle
,DesiredAccess
,ObjectAttributes
,
1447 ObjectAttributes
->ObjectName
->Buffer
);
1450 /* Check for Timeout */
1454 Buffer
.TimeoutSpecified
= TRUE
;
1456 /* FIXME: Add SEH */
1457 Buffer
.DefaultTimeout
= *DefaultTimeout
;
1462 Buffer
.TimeoutSpecified
= FALSE
;
1466 Buffer
.NamedPipeType
= NamedPipeType
;
1467 Buffer
.ReadMode
= ReadMode
;
1468 Buffer
.CompletionMode
= CompletionMode
;
1469 Buffer
.MaximumInstances
= MaximumInstances
;
1470 Buffer
.InboundQuota
= InboundQuota
;
1471 Buffer
.OutboundQuota
= OutboundQuota
;
1474 return IoCreateFile(FileHandle
,
1479 FILE_ATTRIBUTE_NORMAL
,
1485 CreateFileTypeNamedPipe
,
1508 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
1511 return(STATUS_NOT_IMPLEMENTED
);
1516 NtFlushWriteBuffer(VOID
)
1518 KeFlushWriteBuffer();
1519 return STATUS_SUCCESS
;
1523 * FUNCTION: Flushes cached file data to disk
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.
1530 * REMARKS: This function maps to the win32 FlushFileBuffers
1534 NtFlushBuffersFile(IN HANDLE FileHandle
,
1535 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1537 PFILE_OBJECT FileObject
= NULL
;
1539 PIO_STACK_LOCATION StackPtr
;
1541 PDEVICE_OBJECT DeviceObject
;
1543 BOOLEAN LocalEvent
= FALSE
;
1544 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1546 /* Get the File Object */
1547 Status
= ObReferenceObjectByHandle(FileHandle
,
1551 (PVOID
*)&FileObject
,
1553 if (Status
!= STATUS_SUCCESS
) return(Status
);
1555 /* Check if this is a direct open or not */
1556 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1558 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1562 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1565 /* Check if we should use Sync IO or not */
1566 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1568 /* Use File Object event */
1569 KeClearEvent(&FileObject
->Event
);
1573 /* Use local event */
1574 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1578 /* Allocate the IRP */
1579 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
1581 ObDereferenceObject(FileObject
);
1582 return STATUS_INSUFFICIENT_RESOURCES
;
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
;
1593 /* Set up Stack Data */
1594 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1595 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1596 StackPtr
->FileObject
= FileObject
;
1598 /* Call the Driver */
1599 Status
= IoCallDriver(DeviceObject
, Irp
);
1600 if (Status
== STATUS_PENDING
)
1604 KeWaitForSingleObject(&Event
,
1607 FileObject
->Flags
& FO_ALERTABLE_IO
,
1609 Status
= IoStatusBlock
->Status
;
1613 KeWaitForSingleObject(&FileObject
->Event
,
1616 FileObject
->Flags
& FO_ALERTABLE_IO
,
1618 Status
= FileObject
->FinalStatus
;
1622 /* Return the Status */
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
,
1637 IN ULONG BufferSize
,
1638 IN ULONG CompletionFilter
,
1639 IN BOOLEAN WatchTree
)
1642 PDEVICE_OBJECT DeviceObject
;
1643 PFILE_OBJECT FileObject
;
1644 PIO_STACK_LOCATION IoStack
;
1645 KPROCESSOR_MODE PreviousMode
;
1646 NTSTATUS Status
= STATUS_SUCCESS
;
1648 DPRINT("NtNotifyChangeDirectoryFile()\n");
1652 PreviousMode
= ExGetPreviousMode();
1654 if(PreviousMode
!= KernelMode
)
1658 ProbeForWrite(IoStatusBlock
,
1659 sizeof(IO_STATUS_BLOCK
),
1663 ProbeForWrite(Buffer
,
1670 Status
= _SEH_GetExceptionCode();
1674 if(!NT_SUCCESS(Status
))
1680 Status
= ObReferenceObjectByHandle(FileHandle
,
1681 FILE_LIST_DIRECTORY
,
1684 (PVOID
*)&FileObject
,
1686 if (Status
!= STATUS_SUCCESS
) return(Status
);
1689 DeviceObject
= FileObject
->DeviceObject
;
1692 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1695 ObDereferenceObject(FileObject
);
1696 return STATUS_UNSUCCESSFUL
;
1701 Event
= &FileObject
->Event
;
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
;
1715 IoStack
= IoGetNextIrpStackLocation(Irp
);
1717 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1718 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1720 IoStack
->Control
= 0;
1721 IoStack
->DeviceObject
= DeviceObject
;
1722 IoStack
->FileObject
= FileObject
;
1726 IoStack
->Flags
= SL_WATCH_TREE
;
1729 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1730 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1732 Status
= IoCallDriver(FileObject
->DeviceObject
,Irp
);
1734 /* FIXME: Should we wait here or not for synchronously opened files? */
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
,
1752 IN BOOLEAN FailImmediately
,
1753 IN BOOLEAN ExclusiveLock
)
1755 PFILE_OBJECT FileObject
= NULL
;
1756 PLARGE_INTEGER LocalLength
= 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
;
1766 /* FIXME: instead of this, use SEH */
1767 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
1769 /* Get File Object */
1770 Status
= ObReferenceObjectByHandle(FileHandle
,
1774 (PVOID
*)&FileObject
,
1775 &HandleInformation
);
1776 if (!NT_SUCCESS(Status
)) return Status
;
1778 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
1779 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1781 DPRINT1("Invalid access rights\n");
1782 ObDereferenceObject(FileObject
);
1783 return STATUS_ACCESS_DENIED
;
1786 /* Get Event Object */
1789 Status
= ObReferenceObjectByHandle(EventHandle
,
1795 if (Status
!= STATUS_SUCCESS
) return(Status
);
1796 KeClearEvent(Event
);
1799 /* Check if this is a direct open or not */
1800 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1802 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1806 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1809 /* Check if we should use Sync IO or not */
1810 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1812 /* Use File Object event */
1813 KeClearEvent(&FileObject
->Event
);
1820 /* Allocate the IRP */
1821 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
1823 ObDereferenceObject(FileObject
);
1824 return STATUS_INSUFFICIENT_RESOURCES
;
1827 /* Allocate local buffer */
1828 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1829 sizeof(LARGE_INTEGER
),
1834 ObDereferenceObject(FileObject
);
1835 return STATUS_INSUFFICIENT_RESOURCES
;
1837 *LocalLength
= *Length
;
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
;
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
;
1852 /* Set Parameters */
1853 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1854 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
1855 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
1858 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1859 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1861 /* Call the Driver */
1862 FileObject
->LockOperation
= TRUE
;
1863 Status
= IoCallDriver(DeviceObject
, Irp
);
1864 if (Status
== STATUS_PENDING
)
1868 KeWaitForSingleObject(&FileObject
->Event
,
1871 FileObject
->Flags
& FO_ALERTABLE_IO
,
1873 Status
= FileObject
->FinalStatus
;
1877 /* Return the Status */
1886 * Opens an existing file (simpler than NtCreateFile).
1890 * Variable that receives the file handle on return;
1893 * Access desired by the caller to the file;
1896 * Structue describing the file to be opened;
1898 * IoStatusBlock (OUT)
1899 * Receives details about the result of the
1903 * Type of shared access the caller requires;
1906 * Options for the file open.
1918 NtOpenFile(PHANDLE FileHandle
,
1919 ACCESS_MASK DesiredAccess
,
1920 POBJECT_ATTRIBUTES ObjectAttributes
,
1921 PIO_STATUS_BLOCK IoStatusBlock
,
1925 /* Call the I/O Function */
1926 return IoCreateFile(FileHandle
,
1944 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1945 OUT PFILE_BASIC_INFORMATION FileInformation
)
1947 IO_STATUS_BLOCK IoStatusBlock
;
1952 Status
= ZwOpenFile(&FileHandle
,
1953 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
1956 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1957 FILE_SYNCHRONOUS_IO_NONALERT
);
1958 if (!NT_SUCCESS (Status
))
1960 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
1964 /* Get file attributes */
1965 Status
= ZwQueryInformationFile(FileHandle
,
1968 sizeof(FILE_BASIC_INFORMATION
),
1969 FileBasicInformation
);
1970 if (!NT_SUCCESS (Status
))
1972 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
1975 ZwClose(FileHandle
);
1982 * FUNCTION: Queries a directory file.
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.
1991 * FileNameInformation FILE_NAMES_INFORMATION
1992 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
1993 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
1994 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
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
2000 * FileName = Initial directory name to query, that may contain wild
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 ]
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
,
2016 IN FILE_INFORMATION_CLASS FileInformationClass
,
2017 IN BOOLEAN ReturnSingleEntry
,
2018 IN PUNICODE_STRING FileName OPTIONAL
,
2019 IN BOOLEAN RestartScan
)
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
;
2030 DPRINT("NtQueryDirectoryFile()\n");
2033 /* Validate User-Mode Buffers */
2034 if(PreviousMode
!= KernelMode
)
2038 ProbeForWrite(IoStatusBlock
,
2039 sizeof(IO_STATUS_BLOCK
),
2041 ProbeForWrite(FileInformation
,
2047 Status
= _SEH_GetExceptionCode();
2051 if(!NT_SUCCESS(Status
)) return Status
;
2054 /* Get File Object */
2055 Status
= ObReferenceObjectByHandle(FileHandle
,
2056 FILE_LIST_DIRECTORY
,
2059 (PVOID
*)&FileObject
,
2061 if (Status
!= STATUS_SUCCESS
) return(Status
);
2063 /* Get Event Object */
2066 Status
= ObReferenceObjectByHandle(PEvent
,
2072 if (Status
!= STATUS_SUCCESS
) return(Status
);
2073 KeClearEvent(Event
);
2076 /* Check if this is a direct open or not */
2077 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2079 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2083 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2086 /* Check if we should use Sync IO or not */
2087 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2089 /* Use File Object event */
2090 KeClearEvent(&FileObject
->Event
);
2097 /* Allocate the IRP */
2098 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2100 ObDereferenceObject(FileObject
);
2101 return STATUS_INSUFFICIENT_RESOURCES
;
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
;
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
;
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
;
2129 /* Call the Driver */
2130 Status
= IoCallDriver(DeviceObject
, Irp
);
2131 if (Status
== STATUS_PENDING
)
2135 KeWaitForSingleObject(&FileObject
->Event
,
2138 FileObject
->Flags
& FO_ALERTABLE_IO
,
2140 Status
= FileObject
->FinalStatus
;
2144 /* Return the Status */
2152 NtQueryEaFile(IN HANDLE FileHandle
,
2153 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2156 IN BOOLEAN ReturnSingleEntry
,
2157 IN PVOID EaList OPTIONAL
,
2158 IN ULONG EaListLength
,
2159 IN PULONG EaIndex OPTIONAL
,
2160 IN BOOLEAN RestartScan
)
2163 return STATUS_NOT_IMPLEMENTED
;
2168 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2169 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2171 IO_STATUS_BLOCK IoStatusBlock
;
2176 Status
= ZwOpenFile(&FileHandle
,
2177 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2180 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2181 FILE_SYNCHRONOUS_IO_NONALERT
);
2182 if (!NT_SUCCESS (Status
))
2184 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2188 /* Get file attributes */
2189 Status
= ZwQueryInformationFile(FileHandle
,
2192 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2193 FileNetworkOpenInformation
);
2194 if (!NT_SUCCESS (Status
))
2196 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2199 ZwClose (FileHandle
);
2207 NtQueryInformationFile(HANDLE FileHandle
,
2208 PIO_STATUS_BLOCK IoStatusBlock
,
2209 PVOID FileInformation
,
2211 FILE_INFORMATION_CLASS FileInformationClass
)
2213 OBJECT_HANDLE_INFORMATION HandleInformation
;
2214 PFILE_OBJECT FileObject
;
2217 PDEVICE_OBJECT DeviceObject
;
2218 PIO_STACK_LOCATION StackPtr
;
2219 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2221 BOOLEAN LocalEvent
= FALSE
;
2222 BOOLEAN Failed
= FALSE
;
2224 ASSERT(IoStatusBlock
!= NULL
);
2225 ASSERT(FileInformation
!= NULL
);
2227 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2228 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2229 Length
, FileInformationClass
);
2231 /* Reference the Handle */
2232 Status
= ObReferenceObjectByHandle(FileHandle
,
2236 (PVOID
*)&FileObject
,
2237 &HandleInformation
);
2238 if (!NT_SUCCESS(Status
)) return Status
;
2240 /* Check information class specific access rights */
2241 switch (FileInformationClass
)
2243 case FileBasicInformation
:
2244 if (!(HandleInformation
.GrantedAccess
& FILE_READ_ATTRIBUTES
))
2248 case FilePositionInformation
:
2249 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2250 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2254 case FileAlignmentInformation
:
2255 if (!(FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
))
2265 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2266 ObDereferenceObject(FileObject
);
2267 return STATUS_ACCESS_DENIED
;
2270 DPRINT("FileObject %x\n", FileObject
);
2272 /* Check if this is a direct open or not */
2273 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2275 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2279 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2282 /* Check if we should use Sync IO or not */
2283 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2285 /* Use File Object event */
2286 KeClearEvent(&FileObject
->Event
);
2290 /* Use local event */
2291 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2295 /* Allocate the IRP */
2296 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2298 ObDereferenceObject(FileObject
);
2299 return STATUS_INSUFFICIENT_RESOURCES
;
2302 /* Allocate the System Buffer */
2303 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2308 ObDereferenceObject(FileObject
);
2309 return STATUS_INSUFFICIENT_RESOURCES
;
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;
2322 /* Set up Stack Data */
2323 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2324 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2325 StackPtr
->FileObject
= FileObject
;
2327 /* Set the Parameters */
2328 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2329 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2331 /* Call the Driver */
2332 Status
= IoCallDriver(DeviceObject
, Irp
);
2333 if (Status
== STATUS_PENDING
)
2337 KeWaitForSingleObject(&Event
,
2340 FileObject
->Flags
& FO_ALERTABLE_IO
,
2342 Status
= IoStatusBlock
->Status
;
2346 KeWaitForSingleObject(&FileObject
->Event
,
2349 FileObject
->Flags
& FO_ALERTABLE_IO
,
2351 Status
= FileObject
->FinalStatus
;
2355 /* Return the Status */
2364 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2365 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2368 IN BOOLEAN ReturnSingleEntry
,
2369 IN PVOID SidList OPTIONAL
,
2370 IN ULONG SidListLength
,
2371 IN PSID StartSid OPTIONAL
,
2372 IN BOOLEAN RestartScan
)
2375 return STATUS_NOT_IMPLEMENTED
;
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
,
2401 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2402 IN PULONG Key OPTIONAL
)
2404 NTSTATUS Status
= STATUS_SUCCESS
;
2405 PFILE_OBJECT FileObject
;
2407 PDEVICE_OBJECT DeviceObject
;
2408 PIO_STACK_LOCATION StackPtr
;
2409 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2410 BOOLEAN LocalEvent
= FALSE
;
2411 PKEVENT EventObject
= NULL
;
2413 DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2414 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2418 /* Validate User-Mode Buffers */
2419 if(PreviousMode
!= KernelMode
)
2423 ProbeForWrite(IoStatusBlock
,
2424 sizeof(IO_STATUS_BLOCK
),
2427 ProbeForWrite(Buffer
,
2434 Status
= _SEH_GetExceptionCode();
2438 if(!NT_SUCCESS(Status
)) return Status
;
2441 /* Get File Object */
2442 Status
= ObReferenceObjectByHandle(FileHandle
,
2446 (PVOID
*)&FileObject
,
2448 if (!NT_SUCCESS(Status
)) return Status
;
2450 /* Check the Byte Offset */
2452 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
2453 ByteOffset
->u
.HighPart
== 0xffffffff))
2455 /* a valid ByteOffset is required if asynch. op. */
2456 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2458 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2459 ObDereferenceObject(FileObject
);
2460 return STATUS_INVALID_PARAMETER
;
2463 /* Use the Current Byte OFfset */
2464 ByteOffset
= &FileObject
->CurrentByteOffset
;
2467 /* Check for event */
2471 Status
= ObReferenceObjectByHandle(Event
,
2475 (PVOID
*)&EventObject
,
2477 if (!NT_SUCCESS(Status
))
2479 ObDereferenceObject(FileObject
);
2482 KeClearEvent(EventObject
);
2485 /* Check if this is a direct open or not */
2486 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2488 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2492 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2495 /* Check if we should use Sync IO or not */
2496 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2498 /* Use File Object event */
2499 KeClearEvent(&FileObject
->Event
);
2506 /* Create the IRP */
2509 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2518 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2523 Status
= _SEH_GetExceptionCode();
2527 /* Cleanup if IRP Allocation Failed */
2528 if (!NT_SUCCESS(Status
))
2530 if (Event
) ObDereferenceObject(EventObject
);
2531 ObDereferenceObject(FileObject
);
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
;
2543 * Vfat doesn't handle non cached files correctly.
2545 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2548 /* Setup Stack Data */
2549 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2550 StackPtr
->FileObject
= FileObject
;
2551 StackPtr
->Parameters
.Read
.Key
= Key
? *Key
: 0;
2553 /* Call the Driver */
2554 Status
= IoCallDriver(DeviceObject
, Irp
);
2555 if (Status
== STATUS_PENDING
)
2559 KeWaitForSingleObject(&FileObject
->Event
,
2562 FileObject
->Flags
& FO_ALERTABLE_IO
,
2564 Status
= FileObject
->FinalStatus
;
2568 /* Return the Status */
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
)
2597 return(STATUS_NOT_IMPLEMENTED
);
2605 NtSetEaFile(IN HANDLE FileHandle
,
2606 IN PIO_STATUS_BLOCK IoStatusBlock
,
2608 IN ULONG EaBufferSize
)
2611 return STATUS_NOT_IMPLEMENTED
;
2618 NtSetInformationFile(HANDLE FileHandle
,
2619 PIO_STATUS_BLOCK IoStatusBlock
,
2620 PVOID FileInformation
,
2622 FILE_INFORMATION_CLASS FileInformationClass
)
2624 OBJECT_HANDLE_INFORMATION HandleInformation
;
2625 PIO_STACK_LOCATION StackPtr
;
2626 PFILE_OBJECT FileObject
;
2627 PDEVICE_OBJECT DeviceObject
;
2630 BOOLEAN LocalEvent
= FALSE
;
2631 NTSTATUS Status
= STATUS_SUCCESS
;
2632 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2633 BOOLEAN Failed
= FALSE
;
2635 ASSERT(IoStatusBlock
!= NULL
);
2636 ASSERT(FileInformation
!= NULL
);
2638 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2639 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2640 Length
, FileInformationClass
);
2642 /* Get the file object from the file handle */
2643 Status
= ObReferenceObjectByHandle(FileHandle
,
2647 (PVOID
*)&FileObject
,
2648 &HandleInformation
);
2649 if (!NT_SUCCESS(Status
)) return Status
;
2651 /* Check information class specific access rights */
2652 switch (FileInformationClass
)
2654 case FileBasicInformation
:
2655 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_ATTRIBUTES
))
2659 case FileDispositionInformation
:
2660 if (!(HandleInformation
.GrantedAccess
& DELETE
))
2664 case FilePositionInformation
:
2665 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2666 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2670 case FileEndOfFileInformation
:
2671 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
))
2681 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2682 ObDereferenceObject(FileObject
);
2683 return STATUS_ACCESS_DENIED
;
2686 DPRINT("FileObject %x\n", FileObject
);
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
)
2693 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2694 PIO_COMPLETION_CONTEXT Context
;
2696 if (Length
< sizeof(FILE_COMPLETION_INFORMATION
))
2698 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2702 /* Reference the Port */
2703 Status
= ObReferenceObjectByHandle(CompletionInfo
->IoCompletionHandle
,
2704 IO_COMPLETION_MODIFY_STATE
,
2709 if (NT_SUCCESS(Status
))
2711 /* Allocate the Context */
2712 Context
= ExAllocatePoolWithTag(PagedPool
,
2713 sizeof(IO_COMPLETION_CONTEXT
),
2714 TAG('I', 'o', 'C', 'p'));
2717 Context
->Key
= CompletionInfo
->CompletionKey
;
2718 Context
->Port
= Queue
;
2719 FileObject
->CompletionContext
= Context
;
2721 /* Dereference the Port now */
2722 ObDereferenceObject(Queue
);
2726 /* Complete the I/O */
2727 ObDereferenceObject(FileObject
);
2731 /* Check if this is a direct open or not */
2732 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2734 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2738 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2741 /* Check if we should use Sync IO or not */
2742 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2744 /* Use File Object event */
2745 KeClearEvent(&FileObject
->Event
);
2749 /* Use local event */
2750 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2754 /* Allocate the IRP */
2755 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2757 ObDereferenceObject(FileObject
);
2758 return STATUS_INSUFFICIENT_RESOURCES
;
2761 /* Allocate the System Buffer */
2762 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2767 ObDereferenceObject(FileObject
);
2768 return STATUS_INSUFFICIENT_RESOURCES
;
2771 /* Copy the data inside */
2772 MmSafeCopyFromUser(Irp
->AssociatedIrp
.SystemBuffer
, FileInformation
, Length
);
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;
2783 /* Set up Stack Data */
2784 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2785 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2786 StackPtr
->FileObject
= FileObject
;
2788 /* Set the Parameters */
2789 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2790 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2792 /* Call the Driver */
2793 Status
= IoCallDriver(DeviceObject
, Irp
);
2794 if (Status
== STATUS_PENDING
)
2798 KeWaitForSingleObject(&Event
,
2801 FileObject
->Flags
& FO_ALERTABLE_IO
,
2803 Status
= IoStatusBlock
->Status
;
2807 KeWaitForSingleObject(&FileObject
->Event
,
2810 FileObject
->Flags
& FO_ALERTABLE_IO
,
2812 Status
= FileObject
->FinalStatus
;
2816 /* Return the Status */
2825 NtSetQuotaInformationFile(HANDLE FileHandle
,
2826 PIO_STATUS_BLOCK IoStatusBlock
,
2827 PFILE_USER_QUOTA_INFORMATION Buffer
,
2831 return STATUS_NOT_IMPLEMENTED
;
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
)
2845 PFILE_OBJECT FileObject
= NULL
;
2846 PLARGE_INTEGER LocalLength
= NULL
;
2848 PIO_STACK_LOCATION StackPtr
;
2849 PDEVICE_OBJECT DeviceObject
;
2851 BOOLEAN LocalEvent
= FALSE
;
2852 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2853 NTSTATUS Status
= STATUS_SUCCESS
;
2854 OBJECT_HANDLE_INFORMATION HandleInformation
;
2856 /* FIXME: instead of this, use SEH */
2857 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
2859 /* Get File Object */
2860 Status
= ObReferenceObjectByHandle(FileHandle
,
2864 (PVOID
*)&FileObject
,
2865 &HandleInformation
);
2866 if (!NT_SUCCESS(Status
)) return Status
;
2868 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
2869 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2871 DPRINT1("Invalid access rights\n");
2872 ObDereferenceObject(FileObject
);
2873 return STATUS_ACCESS_DENIED
;
2876 /* Check if this is a direct open or not */
2877 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2879 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2883 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2886 /* Check if we should use Sync IO or not */
2887 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2889 /* Use File Object event */
2890 KeClearEvent(&FileObject
->Event
);
2894 /* Use local event */
2895 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2899 /* Allocate the IRP */
2900 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2902 ObDereferenceObject(FileObject
);
2903 return STATUS_INSUFFICIENT_RESOURCES
;
2906 /* Allocate local buffer */
2907 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2908 sizeof(LARGE_INTEGER
),
2913 ObDereferenceObject(FileObject
);
2914 return STATUS_INSUFFICIENT_RESOURCES
;
2916 *LocalLength
= *Length
;
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
;
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
;
2932 /* Set Parameters */
2933 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2934 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
2935 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
2937 /* Call the Driver */
2938 Status
= IoCallDriver(DeviceObject
, Irp
);
2939 if (Status
== STATUS_PENDING
)
2943 KeWaitForSingleObject(&Event
,
2946 FileObject
->Flags
& FO_ALERTABLE_IO
,
2948 Status
= IoStatusBlock
->Status
;
2952 KeWaitForSingleObject(&FileObject
->Event
,
2955 FileObject
->Flags
& FO_ALERTABLE_IO
,
2957 Status
= FileObject
->FinalStatus
;
2961 /* Return the Status */
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
,
2988 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2989 IN PULONG Key OPTIONAL
)
2991 OBJECT_HANDLE_INFORMATION HandleInformation
;
2992 NTSTATUS Status
= STATUS_SUCCESS
;
2993 PFILE_OBJECT FileObject
;
2995 PDEVICE_OBJECT DeviceObject
;
2996 PIO_STACK_LOCATION StackPtr
;
2997 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2998 BOOLEAN LocalEvent
= FALSE
;
2999 PKEVENT EventObject
= NULL
;
3001 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
3002 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
3005 /* Validate User-Mode Buffers */
3006 if(PreviousMode
!= KernelMode
)
3011 ProbeForWrite(IoStatusBlock
,
3012 sizeof(IO_STATUS_BLOCK
),
3015 ProbeForRead(Buffer
,
3022 Status
= _SEH_GetExceptionCode();
3026 if(!NT_SUCCESS(Status
)) return Status
;
3029 /* Get File Object */
3030 Status
= ObReferenceObjectByHandle(FileHandle
,
3034 (PVOID
*)&FileObject
,
3035 &HandleInformation
);
3036 if (!NT_SUCCESS(Status
)) return Status
;
3038 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3039 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)))
3041 DPRINT1("Invalid access rights\n");
3042 ObDereferenceObject(FileObject
);
3043 return STATUS_ACCESS_DENIED
;
3046 /* Check if we got write Access */
3047 if (HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
)
3049 /* Check the Byte Offset */
3051 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
3052 ByteOffset
->u
.HighPart
== 0xffffffff))
3054 /* a valid ByteOffset is required if asynch. op. */
3055 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3057 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3058 ObDereferenceObject(FileObject
);
3059 return STATUS_INVALID_PARAMETER
;
3062 /* Use the Current Byte OFfset */
3063 ByteOffset
= &FileObject
->CurrentByteOffset
;
3066 else if (HandleInformation
.GrantedAccess
& FILE_APPEND_DATA
)
3068 /* a valid ByteOffset is required if asynch. op. */
3069 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3071 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3072 ObDereferenceObject(FileObject
);
3073 return STATUS_INVALID_PARAMETER
;
3076 /* Give the drivers somethign to understand */
3077 ByteOffset
->u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3078 ByteOffset
->u
.HighPart
= 0xffffffff;
3081 /* Check if we got an event */
3085 Status
= ObReferenceObjectByHandle(Event
,
3089 (PVOID
*)&EventObject
,
3091 if (!NT_SUCCESS(Status
))
3093 ObDereferenceObject(FileObject
);
3096 KeClearEvent(EventObject
);
3099 /* Check if this is a direct open or not */
3100 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3102 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3106 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3109 /* Check if we should use Sync IO or not */
3110 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3112 /* Use File Object event */
3113 KeClearEvent(&FileObject
->Event
);
3123 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
3132 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3137 Status
= _SEH_GetExceptionCode();
3141 /* Cleanup on failure */
3142 if (!NT_SUCCESS(Status
))
3146 ObDereferenceObject(&EventObject
);
3148 ObDereferenceObject(FileObject
);
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
;
3160 * Vfat doesn't handle non cached files correctly.
3162 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
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
;
3171 /* Call the Driver */
3172 Status
= IoCallDriver(DeviceObject
, Irp
);
3173 if (Status
== STATUS_PENDING
)
3177 KeWaitForSingleObject(&FileObject
->Event
,
3180 FileObject
->Flags
& FO_ALERTABLE_IO
,
3182 Status
= FileObject
->FinalStatus
;
3186 /* Return the Status */
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
)
3215 return(STATUS_NOT_IMPLEMENTED
);