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 /* FIXME: Header mess */
20 /* GLOBALS *******************************************************************/
22 extern GENERIC_MAPPING IopFileMapping
;
26 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation
,
27 PSECURITY_DESCRIPTOR SecurityDescriptor
,
30 /* INTERNAL FUNCTIONS ********************************************************/
46 IopCreateFile(PVOID ObjectBody
,
49 POBJECT_CREATE_INFORMATION ObjectCreateInfo
)
51 PDEVICE_OBJECT DeviceObject
;
52 PFILE_OBJECT FileObject
= (PFILE_OBJECT
) ObjectBody
;
53 POBJECT_TYPE ParentObjectType
;
56 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
63 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
64 for the cache manager, so return STATUS_SUCCESS */
65 DPRINT("Parent object was NULL\n");
66 return(STATUS_SUCCESS
);
69 ParentObjectType
= BODY_TO_HEADER(Parent
)->Type
;
71 if (ParentObjectType
!= IoDeviceObjectType
&&
72 ParentObjectType
!= IoFileObjectType
)
74 DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n",
75 &BODY_TO_HEADER(Parent
)->NameInfo
->Name
,
76 BODY_TO_HEADER(Parent
)->Type
->Name
.Buffer
,
78 return(STATUS_UNSUCCESSFUL
);
81 Status
= ObReferenceObjectByPointer(Parent
,
82 STANDARD_RIGHTS_REQUIRED
,
85 if (!NT_SUCCESS(Status
))
87 CPRINT("Failed to reference parent object %x\n", Parent
);
91 if (ParentObjectType
== IoDeviceObjectType
)
93 /* Parent is a devce object */
94 DeviceObject
= IoGetAttachedDevice((PDEVICE_OBJECT
)Parent
);
95 DPRINT("DeviceObject %x\n", DeviceObject
);
97 if (RemainingPath
== NULL
)
99 FileObject
->Flags
= FileObject
->Flags
| FO_DIRECT_DEVICE_OPEN
;
100 FileObject
->FileName
.Buffer
= 0;
101 FileObject
->FileName
.Length
= FileObject
->FileName
.MaximumLength
= 0;
105 if ((DeviceObject
->DeviceType
!= FILE_DEVICE_FILE_SYSTEM
)
106 && (DeviceObject
->DeviceType
!= FILE_DEVICE_DISK
)
107 && (DeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
)
108 && (DeviceObject
->DeviceType
!= FILE_DEVICE_TAPE
)
109 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
)
110 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
111 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
113 CPRINT("Device was wrong type\n");
114 return(STATUS_UNSUCCESSFUL
);
117 if (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
118 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
119 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
121 if (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
123 DPRINT("Mount the logical volume\n");
124 Status
= IoMountVolume(DeviceObject
, FALSE
);
125 DPRINT("Status %x\n", Status
);
126 if (!NT_SUCCESS(Status
))
128 CPRINT("Failed to mount logical volume (Status %x)\n", Status
);
132 DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
133 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
135 RtlpCreateUnicodeString(&(FileObject
->FileName
),
136 RemainingPath
, NonPagedPool
);
141 /* Parent is a file object */
142 if (RemainingPath
== NULL
)
144 CPRINT("Device is unnamed\n");
145 return STATUS_UNSUCCESSFUL
;
148 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
149 DPRINT("DeviceObject %x\n", DeviceObject
);
151 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
153 RtlpCreateUnicodeString(&(FileObject
->FileName
),
154 RemainingPath
, NonPagedPool
);
157 DPRINT("FileObject->FileName %wZ\n",
158 &FileObject
->FileName
);
159 FileObject
->DeviceObject
= DeviceObject
;
160 DPRINT("FileObject %x DeviceObject %x\n",
163 FileObject
->Vpb
= DeviceObject
->Vpb
;
164 FileObject
->Type
= IO_TYPE_FILE
;
166 return(STATUS_SUCCESS
);
171 IopDeleteFile(PVOID ObjectBody
)
173 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
175 PIO_STACK_LOCATION StackPtr
;
178 PDEVICE_OBJECT DeviceObject
;
180 DPRINT("IopDeleteFile()\n");
182 if (FileObject
->DeviceObject
)
184 /* Check if this is a direct open or not */
185 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
187 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
191 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
194 /* Clear and set up Events */
195 KeClearEvent(&FileObject
->Event
);
196 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
198 /* Allocate an IRP */
199 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
202 Irp
->UserEvent
= &Event
;
203 Irp
->UserIosb
= &Irp
->IoStatus
;
204 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
205 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
206 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
208 /* Set up Stack Pointer Data */
209 StackPtr
= IoGetNextIrpStackLocation(Irp
);
210 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
211 StackPtr
->DeviceObject
= DeviceObject
;
212 StackPtr
->FileObject
= FileObject
;
214 /* Call the FS Driver */
215 Status
= IoCallDriver(DeviceObject
, Irp
);
217 /* Wait for completion */
218 if (Status
== STATUS_PENDING
)
220 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
226 /* Clear the file name */
227 if (FileObject
->FileName
.Buffer
)
229 ExFreePool(FileObject
->FileName
.Buffer
);
230 FileObject
->FileName
.Buffer
= NULL
;
233 /* Free the completion context */
234 if (FileObject
->CompletionContext
)
236 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
237 ExFreePool(FileObject
->CompletionContext
);
243 IopSecurityFile(PVOID ObjectBody
,
244 SECURITY_OPERATION_CODE OperationCode
,
245 SECURITY_INFORMATION SecurityInformation
,
246 PSECURITY_DESCRIPTOR SecurityDescriptor
,
249 IO_STATUS_BLOCK IoStatusBlock
;
250 PIO_STACK_LOCATION StackPtr
;
251 PFILE_OBJECT FileObject
;
252 PDEVICE_OBJECT DeviceObject
;
255 BOOLEAN LocalEvent
= FALSE
;
257 NTSTATUS Status
= STATUS_SUCCESS
;
259 DPRINT("IopSecurityFile() called\n");
261 FileObject
= (PFILE_OBJECT
)ObjectBody
;
263 if (OperationCode
== QuerySecurityDescriptor
)
265 MajorFunction
= IRP_MJ_QUERY_SECURITY
;
266 DPRINT("Query security descriptor\n");
268 else if (OperationCode
== DeleteSecurityDescriptor
)
271 return STATUS_SUCCESS
;
273 else if (OperationCode
== AssignSecurityDescriptor
)
275 /* If this is a direct open, we can assign it */
276 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
278 /* Get the Device Object */
280 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
282 /* Assign the Security Descriptor */
283 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
285 return STATUS_SUCCESS
;
289 MajorFunction
= IRP_MJ_SET_SECURITY
;
290 DPRINT("Set security descriptor\n");
292 /* If this is a direct open, we can set it */
293 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
295 DPRINT1("Set SD unimplemented for Devices\n");
296 return STATUS_SUCCESS
;
300 /* Get the Device Object */
301 DPRINT1("FileObject: %p\n", FileObject
);
302 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
304 /* Check if we should use Sync IO or not */
305 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
307 /* Use File Object event */
308 KeClearEvent(&FileObject
->Event
);
312 /* Use local event */
313 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
317 /* Allocate the IRP */
318 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
321 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
322 Irp
->RequestorMode
= ExGetPreviousMode();
323 Irp
->UserIosb
= &IoStatusBlock
;
324 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
325 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
326 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
328 /* Set Stack Parameters */
329 StackPtr
= IoGetNextIrpStackLocation(Irp
);
330 StackPtr
->FileObject
= FileObject
;
333 if (OperationCode
== QuerySecurityDescriptor
)
335 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
= SecurityInformation
;
336 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
337 Irp
->UserBuffer
= SecurityDescriptor
;
341 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
= SecurityInformation
;
342 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
= SecurityDescriptor
;
345 ObReferenceObject(FileObject
);
347 /* Call the Driver */
348 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
350 if (Status
== STATUS_PENDING
)
354 KeWaitForSingleObject(&Event
,
357 FileObject
->Flags
& FO_ALERTABLE_IO
,
359 Status
= IoStatusBlock
.Status
;
363 KeWaitForSingleObject(&FileObject
->Event
,
366 FileObject
->Flags
& FO_ALERTABLE_IO
,
368 Status
= FileObject
->FinalStatus
;
372 /* This Driver doesn't implement Security, so try to give it a default */
373 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
375 if (OperationCode
== QuerySecurityDescriptor
)
377 /* Set a World Security Descriptor */
378 Status
= SeSetWorldSecurityDescriptor(SecurityInformation
,
384 /* It wasn't a query, so just fake success */
385 Status
= STATUS_SUCCESS
;
388 else if (OperationCode
== QuerySecurityDescriptor
)
391 *BufferLength
= IoStatusBlock
.Information
;
400 IopQueryNameFile(PVOID ObjectBody
,
401 POBJECT_NAME_INFORMATION ObjectNameInfo
,
406 PFILE_OBJECT FileObject
;
407 ULONG LocalReturnLength
;
410 DPRINT1("IopQueryNameFile() called\n");
412 FileObject
= (PFILE_OBJECT
)ObjectBody
;
414 /* Allocate Buffer */
415 LocalInfo
= ExAllocatePool(PagedPool
,
416 sizeof(OBJECT_NAME_INFORMATION
) +
417 MAX_PATH
* sizeof(WCHAR
));
418 if (LocalInfo
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
421 Status
= ObQueryNameString(FileObject
->DeviceObject
,
423 MAX_PATH
* sizeof(WCHAR
),
425 if (!NT_SUCCESS (Status
))
427 ExFreePool (LocalInfo
);
430 DPRINT ("Device path: %wZ\n", &LocalInfo
->Name
);
432 /* Write Device Path */
433 Status
= RtlAppendUnicodeStringToString(&ObjectNameInfo
->Name
,
434 &((POBJECT_NAME_INFORMATION
)LocalInfo
)->Name
);
436 /* Query the File name */
437 Status
= IoQueryFileInformation(FileObject
,
442 if (Status
!= STATUS_SUCCESS
)
444 ExFreePool(LocalInfo
);
449 Status
= RtlAppendUnicodeToString(&ObjectNameInfo
->Name
,
450 ((PFILE_NAME_INFORMATION
)LocalInfo
)->FileName
);
451 DPRINT ("Total path: %wZ\n", &ObjectNameInfo
->Name
);
453 /* Free buffer and return */
454 ExFreePool(LocalInfo
);
460 IopCloseFile(PVOID ObjectBody
,
463 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
466 PIO_STACK_LOCATION StackPtr
;
468 PDEVICE_OBJECT DeviceObject
;
470 DPRINT("IopCloseFile()\n");
472 if (HandleCount
> 1 || FileObject
->DeviceObject
== NULL
) return;
474 /* Check if this is a direct open or not */
475 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
477 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
481 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
484 /* Clear and set up Events */
485 KeClearEvent(&FileObject
->Event
);
486 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
488 /* Allocate an IRP */
489 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
492 Irp
->UserEvent
= &Event
;
493 Irp
->UserIosb
= &Irp
->IoStatus
;
494 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
495 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
496 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
498 /* Set up Stack Pointer Data */
499 StackPtr
= IoGetNextIrpStackLocation(Irp
);
500 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
501 StackPtr
->FileObject
= FileObject
;
503 /* Call the FS Driver */
504 Status
= IoCallDriver(DeviceObject
, Irp
);
506 /* Wait for completion */
507 if (Status
== STATUS_PENDING
)
509 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
516 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
517 IN HANDLE Event OPTIONAL
,
518 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
519 IN PVOID UserApcContext OPTIONAL
,
520 OUT PIO_STATUS_BLOCK IoStatusBlock
,
521 IN ULONG IoControlCode
,
522 IN PVOID InputBuffer
,
523 IN ULONG InputBufferLength OPTIONAL
,
524 OUT PVOID OutputBuffer
,
525 IN ULONG OutputBufferLength OPTIONAL
,
528 NTSTATUS Status
= STATUS_SUCCESS
;
529 PFILE_OBJECT FileObject
;
530 PDEVICE_OBJECT DeviceObject
;
532 PIO_STACK_LOCATION StackPtr
;
533 PKEVENT EventObject
= NULL
;
534 BOOLEAN LocalEvent
= FALSE
;
535 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
537 DPRINT("IopDeviceFsIoControl(DeviceHandle %x Event %x UserApcRoutine %x "
538 "UserApcContext %x IoStatusBlock %x IoControlCode %x "
539 "InputBuffer %x InputBufferLength %x OutputBuffer %x "
540 "OutputBufferLength %x)\n",
541 DeviceHandle
,Event
,UserApcRoutine
,UserApcContext
,IoStatusBlock
,
542 IoControlCode
,InputBuffer
,InputBufferLength
,OutputBuffer
,
545 if (IoStatusBlock
== NULL
) return STATUS_ACCESS_VIOLATION
;
547 /* Check granted access against the access rights from IoContolCode */
548 Status
= ObReferenceObjectByHandle(DeviceHandle
,
549 (IoControlCode
>> 14) & 0x3,
552 (PVOID
*) &FileObject
,
554 if (!NT_SUCCESS(Status
)) return Status
;
556 /* Check for an event */
560 Status
= ObReferenceObjectByHandle(Event
,
564 (PVOID
*)&EventObject
,
566 if (!NT_SUCCESS(Status
))
568 ObDereferenceObject (FileObject
);
573 KeClearEvent(EventObject
);
576 /* Check if this is a direct open or not */
577 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
579 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
583 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
586 /* Check if we should use Sync IO or not */
587 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
589 /* Use File Object event */
590 KeClearEvent(&FileObject
->Event
);
594 /* Use local event */
599 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
609 /* Set some extra settings */
610 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
611 Irp
->RequestorMode
= PreviousMode
;
612 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
613 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
614 StackPtr
= IoGetNextIrpStackLocation(Irp
);
615 StackPtr
->FileObject
= FileObject
;
616 StackPtr
->MajorFunction
= IsDevIoCtl
?
617 IRP_MJ_DEVICE_CONTROL
: IRP_MJ_FILE_SYSTEM_CONTROL
;
619 /* Call the Driver */
620 Status
= IoCallDriver(DeviceObject
, Irp
);
621 if (Status
== STATUS_PENDING
)
625 KeWaitForSingleObject(&FileObject
->Event
,
628 FileObject
->Flags
& FO_ALERTABLE_IO
,
630 Status
= FileObject
->FinalStatus
;
634 /* Return the Status */
638 /* FUNCTIONS *****************************************************************/
645 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
647 IN BOOLEAN SetOperation
)
650 return STATUS_NOT_IMPLEMENTED
;
658 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
659 IN ULONG QuotaLength
,
660 OUT PULONG ErrorOffset
)
663 return STATUS_NOT_IMPLEMENTED
;
671 * Either causes a new file or directory to be created, or it
672 * opens an existing file, device, directory or volume, giving
673 * the caller a handle for the file object. This handle can be
674 * used by subsequent calls to manipulate data within the file
675 * or the file object's state of attributes.
679 * Points to a variable which receives the file handle
683 * Desired access to the file;
686 * Structure describing the file;
688 * IoStatusBlock (OUT)
689 * Receives information about the operation on return;
691 * AllocationSize [OPTIONAL]
692 * Initial size of the file in bytes;
695 * Attributes to create the file with;
698 * Type of shared access the caller would like to the
702 * Specifies what to do, depending on whether the
703 * file already exists;
706 * Options for creating a new file;
708 * EaBuffer [OPTIONAL]
715 * Type of file (normal, named pipe, mailslot) to create;
717 * ExtraCreateParameters [OPTIONAL]
718 * Additional creation data for named pipe and mailsots;
727 * Prototype taken from Bo Branten's ntifs.h v15.
728 * Description taken from old NtCreateFile's which is
729 * now a wrapper of this call.
737 IoCreateFile(OUT PHANDLE FileHandle
,
738 IN ACCESS_MASK DesiredAccess
,
739 IN POBJECT_ATTRIBUTES ObjectAttributes
,
740 OUT PIO_STATUS_BLOCK IoStatusBlock
,
741 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
742 IN ULONG FileAttributes
,
743 IN ULONG ShareAccess
,
744 IN ULONG CreateDisposition
,
745 IN ULONG CreateOptions
,
746 IN PVOID EaBuffer OPTIONAL
,
748 IN CREATE_FILE_TYPE CreateFileType
,
749 IN PVOID ExtraCreateParameters OPTIONAL
,
752 PFILE_OBJECT FileObject
= NULL
;
753 PDEVICE_OBJECT DeviceObject
;
755 PIO_STACK_LOCATION StackLoc
;
756 IO_SECURITY_CONTEXT SecurityContext
;
757 KPROCESSOR_MODE AccessMode
;
759 IO_STATUS_BLOCK LocalIoStatusBlock
;
760 LARGE_INTEGER SafeAllocationSize
;
761 PVOID SystemEaBuffer
= NULL
;
762 NTSTATUS Status
= STATUS_SUCCESS
;
764 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
765 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
766 FileHandle
,DesiredAccess
,ObjectAttributes
,
767 ObjectAttributes
->ObjectName
->Buffer
);
769 ASSERT_IRQL(PASSIVE_LEVEL
);
771 if (IoStatusBlock
== NULL
|| FileHandle
== NULL
)
772 return STATUS_ACCESS_VIOLATION
;
776 if(Options
& IO_NO_PARAMETER_CHECKING
)
777 AccessMode
= KernelMode
;
779 AccessMode
= ExGetPreviousMode();
781 if(AccessMode
!= KernelMode
)
785 ProbeForWrite(FileHandle
,
788 ProbeForWrite(IoStatusBlock
,
789 sizeof(IO_STATUS_BLOCK
),
791 if(AllocationSize
!= NULL
)
793 ProbeForRead(AllocationSize
,
794 sizeof(LARGE_INTEGER
),
796 SafeAllocationSize
= *AllocationSize
;
799 SafeAllocationSize
.QuadPart
= 0;
801 if(EaBuffer
!= NULL
&& EaLength
> 0)
803 ProbeForRead(EaBuffer
,
807 /* marshal EaBuffer */
808 SystemEaBuffer
= ExAllocatePool(NonPagedPool
,
810 if(SystemEaBuffer
== NULL
)
812 Status
= STATUS_INSUFFICIENT_RESOURCES
;
816 RtlCopyMemory(SystemEaBuffer
,
823 Status
= _SEH_GetExceptionCode();
827 if(!NT_SUCCESS(Status
))
834 if(AllocationSize
!= NULL
)
835 SafeAllocationSize
= *AllocationSize
;
837 SafeAllocationSize
.QuadPart
= 0;
839 if(EaBuffer
!= NULL
&& EaLength
> 0)
841 SystemEaBuffer
= EaBuffer
;
845 if(Options
& IO_CHECK_CREATE_PARAMETERS
)
847 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
850 Status
= ObOpenObjectByName(ObjectAttributes
,
858 if (NT_SUCCESS(Status
))
860 Status
= ObReferenceObjectByHandle(LocalHandle
,
864 (PVOID
*)&DeviceObject
,
866 ZwClose(LocalHandle
);
867 if (!NT_SUCCESS(Status
))
871 if (BODY_TO_HEADER(DeviceObject
)->Type
!= IoDeviceObjectType
)
873 ObDereferenceObject (DeviceObject
);
874 return STATUS_OBJECT_NAME_COLLISION
;
877 FileObject
= IoCreateStreamFileObject(NULL
, DeviceObject
);
879 FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
880 DPRINT("%wZ\n", ObjectAttributes
->ObjectName
);
882 ObDereferenceObject (DeviceObject
);
886 if (FileObject
== NULL
)
888 Status
= ObCreateObject(AccessMode
,
896 (PVOID
*)&FileObject
);
897 if (!NT_SUCCESS(Status
))
899 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
903 RtlMapGenericMask(&DesiredAccess
,
904 &BODY_TO_HEADER(FileObject
)->Type
->TypeInfo
.GenericMapping
);
906 Status
= ObInsertObject ((PVOID
)FileObject
,
912 if (!NT_SUCCESS(Status
))
914 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
915 ObDereferenceObject (FileObject
);
919 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
921 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
923 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
925 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
928 if (CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
929 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
931 SecurityContext
.SecurityQos
= NULL
; /* ?? */
932 SecurityContext
.AccessState
= NULL
; /* ?? */
933 SecurityContext
.DesiredAccess
= DesiredAccess
;
934 SecurityContext
.FullCreateOptions
= 0; /* ?? */
936 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
937 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
939 DPRINT("FileObject %x\n", FileObject
);
940 DPRINT("FileObject->DeviceObject %x\n", FileObject
->DeviceObject
);
942 * Create a new IRP to hand to
943 * the FS driver: this may fail
944 * due to resource shortage.
946 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
949 ZwClose(LocalHandle
);
950 return STATUS_UNSUCCESSFUL
;
953 //trigger FileObject/Event dereferencing
954 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
955 Irp
->RequestorMode
= AccessMode
;
956 Irp
->UserIosb
= &LocalIoStatusBlock
;
957 Irp
->AssociatedIrp
.SystemBuffer
= SystemEaBuffer
;
958 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
959 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
960 Irp
->UserEvent
= &FileObject
->Event
;
961 Irp
->Overlay
.AllocationSize
= SafeAllocationSize
;
964 * Get the stack location for the new
965 * IRP and prepare it.
967 StackLoc
= IoGetNextIrpStackLocation(Irp
);
968 StackLoc
->MinorFunction
= 0;
969 StackLoc
->Flags
= (UCHAR
)Options
;
970 StackLoc
->Control
= 0;
971 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
972 StackLoc
->FileObject
= FileObject
;
974 switch (CreateFileType
)
977 case CreateFileTypeNone
:
978 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
979 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
980 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
981 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
982 StackLoc
->Parameters
.Create
.FileAttributes
= (USHORT
)FileAttributes
;
983 StackLoc
->Parameters
.Create
.ShareAccess
= (USHORT
)ShareAccess
;
984 StackLoc
->Parameters
.Create
.EaLength
= SystemEaBuffer
!= NULL
? EaLength
: 0;
987 case CreateFileTypeNamedPipe
:
988 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
989 StackLoc
->Parameters
.CreatePipe
.SecurityContext
= &SecurityContext
;
990 StackLoc
->Parameters
.CreatePipe
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
991 StackLoc
->Parameters
.CreatePipe
.Options
|= (CreateDisposition
<< 24);
992 StackLoc
->Parameters
.CreatePipe
.ShareAccess
= (USHORT
)ShareAccess
;
993 StackLoc
->Parameters
.CreatePipe
.Parameters
= ExtraCreateParameters
;
996 case CreateFileTypeMailslot
:
997 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
998 StackLoc
->Parameters
.CreateMailslot
.SecurityContext
= &SecurityContext
;
999 StackLoc
->Parameters
.CreateMailslot
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
1000 StackLoc
->Parameters
.CreateMailslot
.Options
|= (CreateDisposition
<< 24);
1001 StackLoc
->Parameters
.CreateMailslot
.ShareAccess
= (USHORT
)ShareAccess
;
1002 StackLoc
->Parameters
.CreateMailslot
.Parameters
= ExtraCreateParameters
;
1007 * Now call the driver and
1008 * possibly wait if it can
1009 * not complete the request
1012 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
1013 DPRINT("Status :%x\n", Status
);
1015 if (Status
== STATUS_PENDING
)
1017 KeWaitForSingleObject(&FileObject
->Event
,
1022 Status
= LocalIoStatusBlock
.Status
;
1024 if (!NT_SUCCESS(Status
))
1026 DPRINT("Failing create request with status %x\n", Status
);
1027 FileObject
->DeviceObject
= NULL
;
1028 FileObject
->Vpb
= NULL
;
1030 ZwClose(LocalHandle
);
1036 *FileHandle
= LocalHandle
;
1037 *IoStatusBlock
= LocalIoStatusBlock
;
1041 Status
= _SEH_GetExceptionCode();
1046 /* cleanup EABuffer if captured */
1047 if(AccessMode
!= KernelMode
&& SystemEaBuffer
!= NULL
)
1049 ExFreePool(SystemEaBuffer
);
1052 ASSERT_IRQL(PASSIVE_LEVEL
);
1054 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle
));
1064 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
1065 IN ACCESS_MASK DesiredAccess
,
1066 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1067 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1068 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1069 IN ULONG FileAttributes
,
1070 IN ULONG ShareAccess
,
1071 IN ULONG Disposition
,
1072 IN ULONG CreateOptions
,
1073 IN PVOID EaBuffer OPTIONAL
,
1075 IN CREATE_FILE_TYPE CreateFileType
,
1076 IN PVOID ExtraCreateParameters OPTIONAL
,
1078 IN PVOID DeviceObject
)
1081 return STATUS_NOT_IMPLEMENTED
;
1086 * IoCreateStreamFileObject@8
1107 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
1108 PDEVICE_OBJECT DeviceObject
)
1110 PFILE_OBJECT CreatedFileObject
;
1113 /* FIXME: This function should call ObInsertObject. The "Lite" version
1114 doesnt. This function is also called from IoCreateFile for some
1115 reason. These hacks need to be removed.
1118 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
1119 FileObject
, DeviceObject
);
1122 /* Create the File Object */
1123 Status
= ObCreateObject(KernelMode
,
1128 sizeof(FILE_OBJECT
),
1131 (PVOID
*)&CreatedFileObject
);
1132 if (!NT_SUCCESS(Status
))
1134 DPRINT1("Could not create FileObject\n");
1138 /* Choose Device Object */
1139 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1140 DPRINT("DeviceObject %x\n", DeviceObject
);
1143 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1145 /* Set File Object Data */
1146 CreatedFileObject
->DeviceObject
= DeviceObject
;
1147 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
1148 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1149 CreatedFileObject
->Flags
|= FO_STREAM_FILE
;
1151 /* Initialize Lock and Event */
1152 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
1153 KeInitializeEvent(&CreatedFileObject
->Lock
, SynchronizationEvent
, TRUE
);
1156 return CreatedFileObject
;
1164 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1165 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1166 OUT PHANDLE FileObjectHandle OPTIONAL
)
1177 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1178 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1189 IoGetFileObjectGenericMapping(VOID
)
1191 return &IopFileMapping
;
1199 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
1201 /* Return the flag status */
1202 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
1210 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
1211 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
1214 return STATUS_NOT_IMPLEMENTED
;
1222 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1223 IN FILE_INFORMATION_CLASS FileInformationClass
,
1225 OUT PVOID FileInformation
,
1226 OUT PULONG ReturnedLength
)
1228 IO_STATUS_BLOCK IoStatusBlock
;
1230 PDEVICE_OBJECT DeviceObject
;
1231 PIO_STACK_LOCATION StackPtr
;
1232 BOOLEAN LocalEvent
= FALSE
;
1236 ASSERT(FileInformation
!= NULL
);
1238 Status
= ObReferenceObjectByPointer(FileObject
,
1239 FILE_READ_ATTRIBUTES
,
1242 if (!NT_SUCCESS(Status
)) return(Status
);
1244 DPRINT("FileObject %x\n", FileObject
);
1246 /* Get the Device Object */
1247 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1249 /* Check if we should use Sync IO or not */
1250 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1252 /* Use File Object event */
1253 KeClearEvent(&FileObject
->Event
);
1257 /* Use local event */
1258 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1262 /* Allocate the IRP */
1263 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1266 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1267 Irp
->RequestorMode
= KernelMode
;
1268 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1269 Irp
->UserIosb
= &IoStatusBlock
;
1270 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1271 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1272 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1274 /* Set the Stack Data */
1275 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1276 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1277 StackPtr
->FileObject
= FileObject
;
1279 /* Set Parameters */
1280 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1281 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1283 /* Call the Driver */
1284 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
1286 if (Status
== STATUS_PENDING
)
1290 KeWaitForSingleObject(&Event
,
1293 FileObject
->Flags
& FO_ALERTABLE_IO
,
1295 Status
= IoStatusBlock
.Status
;
1299 KeWaitForSingleObject(&FileObject
->Event
,
1302 FileObject
->Flags
& FO_ALERTABLE_IO
,
1304 Status
= FileObject
->FinalStatus
;
1309 /* Return the Length and Status. ReturnedLength is NOT optional */
1310 *ReturnedLength
= IoStatusBlock
.Information
;
1319 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
1323 return STATUS_NOT_IMPLEMENTED
;
1327 * @name NtCancelIoFile
1329 * Cancel all pending I/O operations in the current thread for specified
1333 * Handle to file object to cancel requests for. No specific
1334 * access rights are needed.
1335 * @param IoStatusBlock
1336 * Pointer to status block which is filled with final completition
1337 * status on successful return.
1345 NtCancelIoFile(IN HANDLE FileHandle
,
1346 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1349 PFILE_OBJECT FileObject
;
1351 PLIST_ENTRY IrpEntry
;
1354 BOOLEAN OurIrpsInList
= FALSE
;
1355 LARGE_INTEGER Interval
;
1357 if ((ULONG_PTR
)IoStatusBlock
>= (ULONG_PTR
)MmUserProbeAddress
&&
1358 KeGetPreviousMode() == UserMode
)
1359 return STATUS_ACCESS_VIOLATION
;
1361 Status
= ObReferenceObjectByHandle(FileHandle
, 0, IoFileObjectType
,
1362 KeGetPreviousMode(), (PVOID
*)&FileObject
,
1364 if (!NT_SUCCESS(Status
))
1367 /* IRP cancellations are synchronized at APC_LEVEL. */
1368 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1371 * Walk the list of active IRPs and cancel the ones that belong to
1375 Thread
= PsGetCurrentThread();
1376 for (IrpEntry
= Thread
->IrpList
.Flink
;
1377 IrpEntry
!= &Thread
->IrpList
;
1378 IrpEntry
= IrpEntry
->Flink
)
1380 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1381 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1384 /* Don't break here, we want to cancel all IRPs for the file object. */
1385 OurIrpsInList
= TRUE
;
1389 KfLowerIrql(OldIrql
);
1391 while (OurIrpsInList
)
1393 OurIrpsInList
= FALSE
;
1395 /* Wait a short while and then look if all our IRPs were completed. */
1396 Interval
.QuadPart
= -1000000; /* 100 milliseconds */
1397 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1399 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1402 * Look in the list if all IRPs for the specified file object
1403 * are completed (or cancelled). If someone sends a new IRP
1404 * for our file object while we're here we can happily loop
1408 for (IrpEntry
= Thread
->IrpList
.Flink
;
1409 IrpEntry
!= &Thread
->IrpList
;
1410 IrpEntry
= IrpEntry
->Flink
)
1412 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1413 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1415 OurIrpsInList
= TRUE
;
1420 KfLowerIrql(OldIrql
);
1425 IoStatusBlock
->Status
= STATUS_SUCCESS
;
1426 IoStatusBlock
->Information
= 0;
1427 Status
= STATUS_SUCCESS
;
1431 Status
= STATUS_UNSUCCESSFUL
;
1435 ObDereferenceObject(FileObject
);
1445 * Entry point to call IoCreateFile with
1446 * default parameters.
1456 * Code originally in NtCreateFile moved in IoCreateFile.
1462 NtCreateFile(PHANDLE FileHandle
,
1463 ACCESS_MASK DesiredAccess
,
1464 POBJECT_ATTRIBUTES ObjectAttributes
,
1465 PIO_STATUS_BLOCK IoStatusBlock
,
1466 PLARGE_INTEGER AllocateSize
,
1467 ULONG FileAttributes
,
1469 ULONG CreateDisposition
,
1470 ULONG CreateOptions
,
1474 /* Call the I/O Function */
1475 return IoCreateFile(FileHandle
,
1493 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
1494 IN ACCESS_MASK DesiredAccess
,
1495 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1496 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1497 IN ULONG CreateOptions
,
1498 IN ULONG MailslotQuota
,
1499 IN ULONG MaxMessageSize
,
1500 IN PLARGE_INTEGER TimeOut
)
1502 MAILSLOT_CREATE_PARAMETERS Buffer
;
1504 DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
1505 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1506 FileHandle
,DesiredAccess
,ObjectAttributes
,
1507 ObjectAttributes
->ObjectName
->Buffer
);
1510 /* Check for Timeout */
1514 Buffer
.TimeoutSpecified
= TRUE
;
1516 /* FIXME: Add SEH */
1517 Buffer
.ReadTimeout
= *TimeOut
;
1522 Buffer
.TimeoutSpecified
= FALSE
;
1526 Buffer
.MailslotQuota
= MailslotQuota
;
1527 Buffer
.MaximumMessageSize
= MaxMessageSize
;
1530 return IoCreateFile(FileHandle
,
1535 FILE_ATTRIBUTE_NORMAL
,
1536 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1541 CreateFileTypeMailslot
,
1548 NtCreateNamedPipeFile(PHANDLE FileHandle
,
1549 ACCESS_MASK DesiredAccess
,
1550 POBJECT_ATTRIBUTES ObjectAttributes
,
1551 PIO_STATUS_BLOCK IoStatusBlock
,
1553 ULONG CreateDisposition
,
1554 ULONG CreateOptions
,
1555 ULONG NamedPipeType
,
1557 ULONG CompletionMode
,
1558 ULONG MaximumInstances
,
1560 ULONG OutboundQuota
,
1561 PLARGE_INTEGER DefaultTimeout
)
1563 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
1565 DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
1566 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1567 FileHandle
,DesiredAccess
,ObjectAttributes
,
1568 ObjectAttributes
->ObjectName
->Buffer
);
1571 /* Check for Timeout */
1575 Buffer
.TimeoutSpecified
= TRUE
;
1577 /* FIXME: Add SEH */
1578 Buffer
.DefaultTimeout
= *DefaultTimeout
;
1583 Buffer
.TimeoutSpecified
= FALSE
;
1587 Buffer
.NamedPipeType
= NamedPipeType
;
1588 Buffer
.ReadMode
= ReadMode
;
1589 Buffer
.CompletionMode
= CompletionMode
;
1590 Buffer
.MaximumInstances
= MaximumInstances
;
1591 Buffer
.InboundQuota
= InboundQuota
;
1592 Buffer
.OutboundQuota
= OutboundQuota
;
1595 return IoCreateFile(FileHandle
,
1600 FILE_ATTRIBUTE_NORMAL
,
1606 CreateFileTypeNamedPipe
,
1629 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
1632 return(STATUS_NOT_IMPLEMENTED
);
1640 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1641 IN HANDLE Event OPTIONAL
,
1642 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1643 IN PVOID UserApcContext OPTIONAL
,
1644 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1645 IN ULONG IoControlCode
,
1646 IN PVOID InputBuffer
,
1647 IN ULONG InputBufferLength OPTIONAL
,
1648 OUT PVOID OutputBuffer
,
1649 IN ULONG OutputBufferLength OPTIONAL
)
1651 /* Call the Generic Function */
1652 return IopDeviceFsIoControl(DeviceHandle
,
1670 NtFsControlFile(IN HANDLE DeviceHandle
,
1671 IN HANDLE Event OPTIONAL
,
1672 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1673 IN PVOID UserApcContext OPTIONAL
,
1674 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1675 IN ULONG IoControlCode
,
1676 IN PVOID InputBuffer
,
1677 IN ULONG InputBufferLength OPTIONAL
,
1678 OUT PVOID OutputBuffer
,
1679 IN ULONG OutputBufferLength OPTIONAL
)
1681 return IopDeviceFsIoControl(DeviceHandle
,
1696 NtFlushWriteBuffer(VOID
)
1698 KeFlushWriteBuffer();
1699 return STATUS_SUCCESS
;
1703 * FUNCTION: Flushes cached file data to disk
1705 * FileHandle = Points to the file
1706 * IoStatusBlock = Caller must supply storage to receive the result of
1707 * the flush buffers operation. The information field is
1708 * set to number of bytes flushed to disk.
1710 * REMARKS: This function maps to the win32 FlushFileBuffers
1714 NtFlushBuffersFile(IN HANDLE FileHandle
,
1715 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1717 PFILE_OBJECT FileObject
= NULL
;
1719 PIO_STACK_LOCATION StackPtr
;
1721 PDEVICE_OBJECT DeviceObject
;
1723 BOOLEAN LocalEvent
= FALSE
;
1724 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1726 /* Get the File Object */
1727 Status
= ObReferenceObjectByHandle(FileHandle
,
1731 (PVOID
*)&FileObject
,
1733 if (Status
!= STATUS_SUCCESS
) return(Status
);
1735 /* Check if this is a direct open or not */
1736 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1738 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1742 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1745 /* Check if we should use Sync IO or not */
1746 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1748 /* Use File Object event */
1749 KeClearEvent(&FileObject
->Event
);
1753 /* Use local event */
1754 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1758 /* Allocate the IRP */
1759 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
1761 ObDereferenceObject(FileObject
);
1762 return STATUS_INSUFFICIENT_RESOURCES
;
1765 /* Set up the IRP */
1766 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1767 Irp
->RequestorMode
= PreviousMode
;
1768 Irp
->UserIosb
= IoStatusBlock
;
1769 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1770 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1771 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1773 /* Set up Stack Data */
1774 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1775 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1776 StackPtr
->FileObject
= FileObject
;
1778 /* Call the Driver */
1779 Status
= IoCallDriver(DeviceObject
, Irp
);
1780 if (Status
== STATUS_PENDING
)
1784 KeWaitForSingleObject(&Event
,
1787 FileObject
->Flags
& FO_ALERTABLE_IO
,
1789 Status
= IoStatusBlock
->Status
;
1793 KeWaitForSingleObject(&FileObject
->Event
,
1796 FileObject
->Flags
& FO_ALERTABLE_IO
,
1798 Status
= FileObject
->FinalStatus
;
1802 /* Return the Status */
1811 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1812 IN HANDLE Event OPTIONAL
,
1813 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1814 IN PVOID ApcContext OPTIONAL
,
1815 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1817 IN ULONG BufferSize
,
1818 IN ULONG CompletionFilter
,
1819 IN BOOLEAN WatchTree
)
1822 PDEVICE_OBJECT DeviceObject
;
1823 PFILE_OBJECT FileObject
;
1824 PIO_STACK_LOCATION IoStack
;
1825 KPROCESSOR_MODE PreviousMode
;
1826 NTSTATUS Status
= STATUS_SUCCESS
;
1828 DPRINT("NtNotifyChangeDirectoryFile()\n");
1832 PreviousMode
= ExGetPreviousMode();
1834 if(PreviousMode
!= KernelMode
)
1838 ProbeForWrite(IoStatusBlock
,
1839 sizeof(IO_STATUS_BLOCK
),
1843 ProbeForWrite(Buffer
,
1850 Status
= _SEH_GetExceptionCode();
1854 if(!NT_SUCCESS(Status
))
1860 Status
= ObReferenceObjectByHandle(FileHandle
,
1861 FILE_LIST_DIRECTORY
,
1864 (PVOID
*)&FileObject
,
1866 if (Status
!= STATUS_SUCCESS
) return(Status
);
1869 DeviceObject
= FileObject
->DeviceObject
;
1872 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1875 ObDereferenceObject(FileObject
);
1876 return STATUS_UNSUCCESSFUL
;
1881 Event
= &FileObject
->Event
;
1884 /* Trigger FileObject/Event dereferencing */
1885 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1886 Irp
->RequestorMode
= PreviousMode
;
1887 Irp
->UserIosb
= IoStatusBlock
;
1888 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1889 Irp
->UserEvent
= Event
;
1890 KeResetEvent( Event
);
1891 Irp
->UserBuffer
= Buffer
;
1892 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1893 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1895 IoStack
= IoGetNextIrpStackLocation(Irp
);
1897 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1898 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1900 IoStack
->Control
= 0;
1901 IoStack
->DeviceObject
= DeviceObject
;
1902 IoStack
->FileObject
= FileObject
;
1906 IoStack
->Flags
= SL_WATCH_TREE
;
1909 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1910 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1912 Status
= IoCallDriver(FileObject
->DeviceObject
,Irp
);
1914 /* FIXME: Should we wait here or not for synchronously opened files? */
1924 NtLockFile(IN HANDLE FileHandle
,
1925 IN HANDLE EventHandle OPTIONAL
,
1926 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1927 IN PVOID ApcContext OPTIONAL
,
1928 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1929 IN PLARGE_INTEGER ByteOffset
,
1930 IN PLARGE_INTEGER Length
,
1932 IN BOOLEAN FailImmediately
,
1933 IN BOOLEAN ExclusiveLock
)
1935 PFILE_OBJECT FileObject
= NULL
;
1936 PLARGE_INTEGER LocalLength
= NULL
;
1938 PIO_STACK_LOCATION StackPtr
;
1939 PDEVICE_OBJECT DeviceObject
;
1940 PKEVENT Event
= NULL
;
1941 BOOLEAN LocalEvent
= FALSE
;
1942 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1943 NTSTATUS Status
= STATUS_SUCCESS
;
1944 OBJECT_HANDLE_INFORMATION HandleInformation
;
1946 /* FIXME: instead of this, use SEH */
1947 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
1949 /* Get File Object */
1950 Status
= ObReferenceObjectByHandle(FileHandle
,
1954 (PVOID
*)&FileObject
,
1955 &HandleInformation
);
1956 if (!NT_SUCCESS(Status
)) return Status
;
1958 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
1959 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1961 DPRINT1("Invalid access rights\n");
1962 ObDereferenceObject(FileObject
);
1963 return STATUS_ACCESS_DENIED
;
1966 /* Get Event Object */
1969 Status
= ObReferenceObjectByHandle(EventHandle
,
1975 if (Status
!= STATUS_SUCCESS
) return(Status
);
1976 KeClearEvent(Event
);
1979 /* Check if this is a direct open or not */
1980 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1982 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1986 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1989 /* Check if we should use Sync IO or not */
1990 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1992 /* Use File Object event */
1993 KeClearEvent(&FileObject
->Event
);
2000 /* Allocate the IRP */
2001 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2003 ObDereferenceObject(FileObject
);
2004 return STATUS_INSUFFICIENT_RESOURCES
;
2007 /* Allocate local buffer */
2008 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2009 sizeof(LARGE_INTEGER
),
2014 ObDereferenceObject(FileObject
);
2015 return STATUS_INSUFFICIENT_RESOURCES
;
2017 *LocalLength
= *Length
;
2019 /* Set up the IRP */
2020 Irp
->RequestorMode
= PreviousMode
;
2021 Irp
->UserIosb
= IoStatusBlock
;
2022 Irp
->UserEvent
= Event
;
2023 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2024 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2026 /* Set up Stack Data */
2027 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2028 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2029 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
2030 StackPtr
->FileObject
= FileObject
;
2032 /* Set Parameters */
2033 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2034 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
2035 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
2038 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
2039 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
2041 /* Call the Driver */
2042 FileObject
->LockOperation
= TRUE
;
2043 Status
= IoCallDriver(DeviceObject
, Irp
);
2044 if (Status
== STATUS_PENDING
)
2048 KeWaitForSingleObject(&FileObject
->Event
,
2051 FileObject
->Flags
& FO_ALERTABLE_IO
,
2053 Status
= FileObject
->FinalStatus
;
2057 /* Return the Status */
2066 * Opens an existing file (simpler than NtCreateFile).
2070 * Variable that receives the file handle on return;
2073 * Access desired by the caller to the file;
2076 * Structue describing the file to be opened;
2078 * IoStatusBlock (OUT)
2079 * Receives details about the result of the
2083 * Type of shared access the caller requires;
2086 * Options for the file open.
2098 NtOpenFile(PHANDLE FileHandle
,
2099 ACCESS_MASK DesiredAccess
,
2100 POBJECT_ATTRIBUTES ObjectAttributes
,
2101 PIO_STATUS_BLOCK IoStatusBlock
,
2105 /* Call the I/O Function */
2106 return IoCreateFile(FileHandle
,
2124 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2125 OUT PFILE_BASIC_INFORMATION FileInformation
)
2127 IO_STATUS_BLOCK IoStatusBlock
;
2132 Status
= ZwOpenFile(&FileHandle
,
2133 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2136 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2137 FILE_SYNCHRONOUS_IO_NONALERT
);
2138 if (!NT_SUCCESS (Status
))
2140 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2144 /* Get file attributes */
2145 Status
= ZwQueryInformationFile(FileHandle
,
2148 sizeof(FILE_BASIC_INFORMATION
),
2149 FileBasicInformation
);
2150 if (!NT_SUCCESS (Status
))
2152 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2155 ZwClose(FileHandle
);
2162 * FUNCTION: Queries a directory file.
2164 * FileHandle = Handle to a directory file
2165 * EventHandle = Handle to the event signaled on completion
2166 * ApcRoutine = Asynchroneous procedure callback, called on completion
2167 * ApcContext = Argument to the apc.
2168 * IoStatusBlock = Caller supplies storage for extended status information.
2169 * FileInformation = Caller supplies storage for the resulting information.
2171 * FileNameInformation FILE_NAMES_INFORMATION
2172 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2173 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2174 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2176 * Length = Size of the storage supplied
2177 * FileInformationClass = Indicates the type of information requested.
2178 * ReturnSingleEntry = Specify true if caller only requests the first
2180 * FileName = Initial directory name to query, that may contain wild
2182 * RestartScan = Number of times the action should be repeated
2183 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2184 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2185 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2189 NtQueryDirectoryFile(IN HANDLE FileHandle
,
2190 IN HANDLE PEvent OPTIONAL
,
2191 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2192 IN PVOID ApcContext OPTIONAL
,
2193 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2194 OUT PVOID FileInformation
,
2196 IN FILE_INFORMATION_CLASS FileInformationClass
,
2197 IN BOOLEAN ReturnSingleEntry
,
2198 IN PUNICODE_STRING FileName OPTIONAL
,
2199 IN BOOLEAN RestartScan
)
2202 PDEVICE_OBJECT DeviceObject
;
2203 PFILE_OBJECT FileObject
;
2204 PIO_STACK_LOCATION StackPtr
;
2205 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2206 NTSTATUS Status
= STATUS_SUCCESS
;
2207 BOOLEAN LocalEvent
= FALSE
;
2208 PKEVENT Event
= NULL
;
2210 DPRINT("NtQueryDirectoryFile()\n");
2213 /* Validate User-Mode Buffers */
2214 if(PreviousMode
!= KernelMode
)
2218 ProbeForWrite(IoStatusBlock
,
2219 sizeof(IO_STATUS_BLOCK
),
2221 ProbeForWrite(FileInformation
,
2227 Status
= _SEH_GetExceptionCode();
2231 if(!NT_SUCCESS(Status
)) return Status
;
2234 /* Get File Object */
2235 Status
= ObReferenceObjectByHandle(FileHandle
,
2236 FILE_LIST_DIRECTORY
,
2239 (PVOID
*)&FileObject
,
2241 if (Status
!= STATUS_SUCCESS
) return(Status
);
2243 /* Get Event Object */
2246 Status
= ObReferenceObjectByHandle(PEvent
,
2252 if (Status
!= STATUS_SUCCESS
) return(Status
);
2253 KeClearEvent(Event
);
2256 /* Check if this is a direct open or not */
2257 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2259 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2263 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2266 /* Check if we should use Sync IO or not */
2267 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2269 /* Use File Object event */
2270 KeClearEvent(&FileObject
->Event
);
2277 /* Allocate the IRP */
2278 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2280 ObDereferenceObject(FileObject
);
2281 return STATUS_INSUFFICIENT_RESOURCES
;
2284 /* Set up the IRP */
2285 Irp
->RequestorMode
= PreviousMode
;
2286 Irp
->UserIosb
= IoStatusBlock
;
2287 Irp
->UserEvent
= Event
;
2288 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2289 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2290 Irp
->UserBuffer
= FileInformation
;
2291 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2292 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2294 /* Set up Stack Data */
2295 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2296 StackPtr
->FileObject
= FileObject
;
2297 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2298 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2300 /* Set Parameters */
2301 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
= FileInformationClass
;
2302 StackPtr
->Parameters
.QueryDirectory
.FileName
= FileName
;
2303 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2304 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2305 StackPtr
->Flags
= 0;
2306 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2307 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2309 /* Call the Driver */
2310 Status
= IoCallDriver(DeviceObject
, Irp
);
2311 if (Status
== STATUS_PENDING
)
2315 KeWaitForSingleObject(&FileObject
->Event
,
2318 FileObject
->Flags
& FO_ALERTABLE_IO
,
2320 Status
= FileObject
->FinalStatus
;
2324 /* Return the Status */
2332 NtQueryEaFile(IN HANDLE FileHandle
,
2333 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2336 IN BOOLEAN ReturnSingleEntry
,
2337 IN PVOID EaList OPTIONAL
,
2338 IN ULONG EaListLength
,
2339 IN PULONG EaIndex OPTIONAL
,
2340 IN BOOLEAN RestartScan
)
2343 return STATUS_NOT_IMPLEMENTED
;
2348 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2349 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2351 IO_STATUS_BLOCK IoStatusBlock
;
2356 Status
= ZwOpenFile(&FileHandle
,
2357 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2360 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2361 FILE_SYNCHRONOUS_IO_NONALERT
);
2362 if (!NT_SUCCESS (Status
))
2364 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2368 /* Get file attributes */
2369 Status
= ZwQueryInformationFile(FileHandle
,
2372 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2373 FileNetworkOpenInformation
);
2374 if (!NT_SUCCESS (Status
))
2376 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2379 ZwClose (FileHandle
);
2387 NtQueryInformationFile(HANDLE FileHandle
,
2388 PIO_STATUS_BLOCK IoStatusBlock
,
2389 PVOID FileInformation
,
2391 FILE_INFORMATION_CLASS FileInformationClass
)
2393 OBJECT_HANDLE_INFORMATION HandleInformation
;
2394 PFILE_OBJECT FileObject
;
2397 PDEVICE_OBJECT DeviceObject
;
2398 PIO_STACK_LOCATION StackPtr
;
2399 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2401 BOOLEAN LocalEvent
= FALSE
;
2402 BOOLEAN Failed
= FALSE
;
2404 ASSERT(IoStatusBlock
!= NULL
);
2405 ASSERT(FileInformation
!= NULL
);
2407 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2408 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2409 Length
, FileInformationClass
);
2411 /* Reference the Handle */
2412 Status
= ObReferenceObjectByHandle(FileHandle
,
2416 (PVOID
*)&FileObject
,
2417 &HandleInformation
);
2418 if (!NT_SUCCESS(Status
)) return Status
;
2420 /* Check information class specific access rights */
2421 switch (FileInformationClass
)
2423 case FileBasicInformation
:
2424 if (!(HandleInformation
.GrantedAccess
& FILE_READ_ATTRIBUTES
))
2428 case FilePositionInformation
:
2429 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2430 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2434 case FileAlignmentInformation
:
2435 if (!(FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
))
2445 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2446 ObDereferenceObject(FileObject
);
2447 return STATUS_ACCESS_DENIED
;
2450 DPRINT("FileObject %x\n", FileObject
);
2452 /* Check if this is a direct open or not */
2453 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2455 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2459 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2462 /* Check if we should use Sync IO or not */
2463 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2465 /* Use File Object event */
2466 KeClearEvent(&FileObject
->Event
);
2470 /* Use local event */
2471 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2475 /* Allocate the IRP */
2476 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2478 ObDereferenceObject(FileObject
);
2479 return STATUS_INSUFFICIENT_RESOURCES
;
2482 /* Allocate the System Buffer */
2483 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2488 ObDereferenceObject(FileObject
);
2489 return STATUS_INSUFFICIENT_RESOURCES
;
2492 /* Set up the IRP */
2493 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2494 Irp
->RequestorMode
= PreviousMode
;
2495 Irp
->UserIosb
= IoStatusBlock
;
2496 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2497 Irp
->UserBuffer
= FileInformation
;
2498 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2499 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
2500 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2502 /* Set up Stack Data */
2503 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2504 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2505 StackPtr
->FileObject
= FileObject
;
2507 /* Set the Parameters */
2508 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2509 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2511 /* Call the Driver */
2512 Status
= IoCallDriver(DeviceObject
, Irp
);
2513 if (Status
== STATUS_PENDING
)
2517 KeWaitForSingleObject(&Event
,
2520 FileObject
->Flags
& FO_ALERTABLE_IO
,
2522 Status
= IoStatusBlock
->Status
;
2526 KeWaitForSingleObject(&FileObject
->Event
,
2529 FileObject
->Flags
& FO_ALERTABLE_IO
,
2531 Status
= FileObject
->FinalStatus
;
2535 /* Return the Status */
2544 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2545 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2548 IN BOOLEAN ReturnSingleEntry
,
2549 IN PVOID SidList OPTIONAL
,
2550 IN ULONG SidListLength
,
2551 IN PSID StartSid OPTIONAL
,
2552 IN BOOLEAN RestartScan
)
2555 return STATUS_NOT_IMPLEMENTED
;
2574 NtReadFile(IN HANDLE FileHandle
,
2575 IN HANDLE Event OPTIONAL
,
2576 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2577 IN PVOID ApcContext OPTIONAL
,
2578 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2581 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2582 IN PULONG Key OPTIONAL
)
2584 NTSTATUS Status
= STATUS_SUCCESS
;
2585 PFILE_OBJECT FileObject
;
2587 PDEVICE_OBJECT DeviceObject
;
2588 PIO_STACK_LOCATION StackPtr
;
2589 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2590 BOOLEAN LocalEvent
= FALSE
;
2591 PKEVENT EventObject
= NULL
;
2593 DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2594 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2598 /* Validate User-Mode Buffers */
2599 if(PreviousMode
!= KernelMode
)
2603 ProbeForWrite(IoStatusBlock
,
2604 sizeof(IO_STATUS_BLOCK
),
2607 ProbeForWrite(Buffer
,
2614 Status
= _SEH_GetExceptionCode();
2618 if(!NT_SUCCESS(Status
)) return Status
;
2621 /* Get File Object */
2622 Status
= ObReferenceObjectByHandle(FileHandle
,
2626 (PVOID
*)&FileObject
,
2628 if (!NT_SUCCESS(Status
)) return Status
;
2630 /* Check the Byte Offset */
2632 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
2633 ByteOffset
->u
.HighPart
== 0xffffffff))
2635 /* a valid ByteOffset is required if asynch. op. */
2636 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2638 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2639 ObDereferenceObject(FileObject
);
2640 return STATUS_INVALID_PARAMETER
;
2643 /* Use the Current Byte OFfset */
2644 ByteOffset
= &FileObject
->CurrentByteOffset
;
2647 /* Check for event */
2651 Status
= ObReferenceObjectByHandle(Event
,
2655 (PVOID
*)&EventObject
,
2657 if (!NT_SUCCESS(Status
))
2659 ObDereferenceObject(FileObject
);
2662 KeClearEvent(EventObject
);
2665 /* Check if this is a direct open or not */
2666 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2668 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2672 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2675 /* Check if we should use Sync IO or not */
2676 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2678 /* Use File Object event */
2679 KeClearEvent(&FileObject
->Event
);
2686 /* Create the IRP */
2689 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2698 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2703 Status
= _SEH_GetExceptionCode();
2707 /* Cleanup if IRP Allocation Failed */
2708 if (!NT_SUCCESS(Status
))
2710 if (Event
) ObDereferenceObject(EventObject
);
2711 ObDereferenceObject(FileObject
);
2715 /* Set up IRP Data */
2716 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2717 Irp
->RequestorMode
= PreviousMode
;
2718 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2719 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2720 Irp
->Flags
|= IRP_READ_OPERATION
;
2723 * Vfat doesn't handle non cached files correctly.
2725 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2728 /* Setup Stack Data */
2729 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2730 StackPtr
->FileObject
= FileObject
;
2731 StackPtr
->Parameters
.Read
.Key
= Key
? *Key
: 0;
2733 /* Call the Driver */
2734 Status
= IoCallDriver(DeviceObject
, Irp
);
2735 if (Status
== STATUS_PENDING
)
2739 KeWaitForSingleObject(&FileObject
->Event
,
2742 FileObject
->Flags
& FO_ALERTABLE_IO
,
2744 Status
= FileObject
->FinalStatus
;
2748 /* Return the Status */
2766 NtReadFileScatter(IN HANDLE FileHandle
,
2767 IN HANDLE Event OPTIONAL
,
2768 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2769 IN PVOID UserApcContext OPTIONAL
,
2770 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2771 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2772 IN ULONG BufferLength
,
2773 IN PLARGE_INTEGER ByteOffset
,
2774 IN PULONG Key OPTIONAL
)
2777 return(STATUS_NOT_IMPLEMENTED
);
2785 NtSetEaFile(IN HANDLE FileHandle
,
2786 IN PIO_STATUS_BLOCK IoStatusBlock
,
2788 IN ULONG EaBufferSize
)
2791 return STATUS_NOT_IMPLEMENTED
;
2798 NtSetInformationFile(HANDLE FileHandle
,
2799 PIO_STATUS_BLOCK IoStatusBlock
,
2800 PVOID FileInformation
,
2802 FILE_INFORMATION_CLASS FileInformationClass
)
2804 OBJECT_HANDLE_INFORMATION HandleInformation
;
2805 PIO_STACK_LOCATION StackPtr
;
2806 PFILE_OBJECT FileObject
;
2807 PDEVICE_OBJECT DeviceObject
;
2810 BOOLEAN LocalEvent
= FALSE
;
2811 NTSTATUS Status
= STATUS_SUCCESS
;
2812 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2813 BOOLEAN Failed
= FALSE
;
2815 ASSERT(IoStatusBlock
!= NULL
);
2816 ASSERT(FileInformation
!= NULL
);
2818 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2819 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2820 Length
, FileInformationClass
);
2822 /* Get the file object from the file handle */
2823 Status
= ObReferenceObjectByHandle(FileHandle
,
2827 (PVOID
*)&FileObject
,
2828 &HandleInformation
);
2829 if (!NT_SUCCESS(Status
)) return Status
;
2831 /* Check information class specific access rights */
2832 switch (FileInformationClass
)
2834 case FileBasicInformation
:
2835 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_ATTRIBUTES
))
2839 case FileDispositionInformation
:
2840 if (!(HandleInformation
.GrantedAccess
& DELETE
))
2844 case FilePositionInformation
:
2845 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2846 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2850 case FileEndOfFileInformation
:
2851 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
))
2861 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2862 ObDereferenceObject(FileObject
);
2863 return STATUS_ACCESS_DENIED
;
2866 DPRINT("FileObject %x\n", FileObject
);
2868 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2869 /* Handle IO Completion Port quickly */
2870 if (FileInformationClass
== FileCompletionInformation
)
2873 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2874 PIO_COMPLETION_CONTEXT Context
;
2876 if (Length
< sizeof(FILE_COMPLETION_INFORMATION
))
2878 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2882 /* Reference the Port */
2883 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2884 IO_COMPLETION_MODIFY_STATE
,
2889 if (NT_SUCCESS(Status
))
2891 /* Allocate the Context */
2892 Context
= ExAllocatePoolWithTag(PagedPool
,
2893 sizeof(IO_COMPLETION_CONTEXT
),
2894 TAG('I', 'o', 'C', 'p'));
2897 Context
->Key
= CompletionInfo
->Key
;
2898 Context
->Port
= Queue
;
2899 FileObject
->CompletionContext
= Context
;
2901 /* Dereference the Port now */
2902 ObDereferenceObject(Queue
);
2906 /* Complete the I/O */
2907 ObDereferenceObject(FileObject
);
2911 /* Check if this is a direct open or not */
2912 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2914 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2918 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2921 /* Check if we should use Sync IO or not */
2922 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2924 /* Use File Object event */
2925 KeClearEvent(&FileObject
->Event
);
2929 /* Use local event */
2930 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2934 /* Allocate the IRP */
2935 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2937 ObDereferenceObject(FileObject
);
2938 return STATUS_INSUFFICIENT_RESOURCES
;
2941 /* Allocate the System Buffer */
2942 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2947 ObDereferenceObject(FileObject
);
2948 return STATUS_INSUFFICIENT_RESOURCES
;
2951 /* Copy the data inside */
2952 MmSafeCopyFromUser(Irp
->AssociatedIrp
.SystemBuffer
, FileInformation
, Length
);
2954 /* Set up the IRP */
2955 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2956 Irp
->RequestorMode
= PreviousMode
;
2957 Irp
->UserIosb
= IoStatusBlock
;
2958 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2959 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2960 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
2961 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2963 /* Set up Stack Data */
2964 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2965 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2966 StackPtr
->FileObject
= FileObject
;
2968 /* Set the Parameters */
2969 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2970 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2972 /* Call the Driver */
2973 Status
= IoCallDriver(DeviceObject
, Irp
);
2974 if (Status
== STATUS_PENDING
)
2978 KeWaitForSingleObject(&Event
,
2981 FileObject
->Flags
& FO_ALERTABLE_IO
,
2983 Status
= IoStatusBlock
->Status
;
2987 KeWaitForSingleObject(&FileObject
->Event
,
2990 FileObject
->Flags
& FO_ALERTABLE_IO
,
2992 Status
= FileObject
->FinalStatus
;
2996 /* Return the Status */
3005 NtSetQuotaInformationFile(HANDLE FileHandle
,
3006 PIO_STATUS_BLOCK IoStatusBlock
,
3007 PFILE_USER_QUOTA_INFORMATION Buffer
,
3011 return STATUS_NOT_IMPLEMENTED
;
3019 NtUnlockFile(IN HANDLE FileHandle
,
3020 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3021 IN PLARGE_INTEGER ByteOffset
,
3022 IN PLARGE_INTEGER Length
,
3023 OUT PULONG Key OPTIONAL
)
3025 PFILE_OBJECT FileObject
= NULL
;
3026 PLARGE_INTEGER LocalLength
= NULL
;
3028 PIO_STACK_LOCATION StackPtr
;
3029 PDEVICE_OBJECT DeviceObject
;
3031 BOOLEAN LocalEvent
= FALSE
;
3032 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3033 NTSTATUS Status
= STATUS_SUCCESS
;
3034 OBJECT_HANDLE_INFORMATION HandleInformation
;
3036 /* FIXME: instead of this, use SEH */
3037 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
3039 /* Get File Object */
3040 Status
= ObReferenceObjectByHandle(FileHandle
,
3044 (PVOID
*)&FileObject
,
3045 &HandleInformation
);
3046 if (!NT_SUCCESS(Status
)) return Status
;
3048 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
3049 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3051 DPRINT1("Invalid access rights\n");
3052 ObDereferenceObject(FileObject
);
3053 return STATUS_ACCESS_DENIED
;
3056 /* Check if this is a direct open or not */
3057 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3059 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3063 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3066 /* Check if we should use Sync IO or not */
3067 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3069 /* Use File Object event */
3070 KeClearEvent(&FileObject
->Event
);
3074 /* Use local event */
3075 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3079 /* Allocate the IRP */
3080 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
3082 ObDereferenceObject(FileObject
);
3083 return STATUS_INSUFFICIENT_RESOURCES
;
3086 /* Allocate local buffer */
3087 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3088 sizeof(LARGE_INTEGER
),
3093 ObDereferenceObject(FileObject
);
3094 return STATUS_INSUFFICIENT_RESOURCES
;
3096 *LocalLength
= *Length
;
3098 /* Set up the IRP */
3099 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3100 Irp
->RequestorMode
= PreviousMode
;
3101 Irp
->UserIosb
= IoStatusBlock
;
3102 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
3103 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3104 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3106 /* Set up Stack Data */
3107 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3108 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3109 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3110 StackPtr
->FileObject
= FileObject
;
3112 /* Set Parameters */
3113 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3114 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
3115 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
3117 /* Call the Driver */
3118 Status
= IoCallDriver(DeviceObject
, Irp
);
3119 if (Status
== STATUS_PENDING
)
3123 KeWaitForSingleObject(&Event
,
3126 FileObject
->Flags
& FO_ALERTABLE_IO
,
3128 Status
= IoStatusBlock
->Status
;
3132 KeWaitForSingleObject(&FileObject
->Event
,
3135 FileObject
->Flags
& FO_ALERTABLE_IO
,
3137 Status
= FileObject
->FinalStatus
;
3141 /* Return the Status */
3161 NtWriteFile (IN HANDLE FileHandle
,
3162 IN HANDLE Event OPTIONAL
,
3163 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3164 IN PVOID ApcContext OPTIONAL
,
3165 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3168 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
3169 IN PULONG Key OPTIONAL
)
3171 OBJECT_HANDLE_INFORMATION HandleInformation
;
3172 NTSTATUS Status
= STATUS_SUCCESS
;
3173 PFILE_OBJECT FileObject
;
3175 PDEVICE_OBJECT DeviceObject
;
3176 PIO_STACK_LOCATION StackPtr
;
3177 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3178 BOOLEAN LocalEvent
= FALSE
;
3179 PKEVENT EventObject
= NULL
;
3181 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
3182 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
3185 /* Validate User-Mode Buffers */
3186 if(PreviousMode
!= KernelMode
)
3191 ProbeForWrite(IoStatusBlock
,
3192 sizeof(IO_STATUS_BLOCK
),
3195 ProbeForRead(Buffer
,
3202 Status
= _SEH_GetExceptionCode();
3206 if(!NT_SUCCESS(Status
)) return Status
;
3209 /* Get File Object */
3210 Status
= ObReferenceObjectByHandle(FileHandle
,
3214 (PVOID
*)&FileObject
,
3215 &HandleInformation
);
3216 if (!NT_SUCCESS(Status
)) return Status
;
3218 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3219 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)))
3221 DPRINT1("Invalid access rights\n");
3222 ObDereferenceObject(FileObject
);
3223 return STATUS_ACCESS_DENIED
;
3226 /* Check if we got write Access */
3227 if (HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
)
3229 /* Check the Byte Offset */
3231 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
3232 ByteOffset
->u
.HighPart
== 0xffffffff))
3234 /* a valid ByteOffset is required if asynch. op. */
3235 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3237 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3238 ObDereferenceObject(FileObject
);
3239 return STATUS_INVALID_PARAMETER
;
3242 /* Use the Current Byte OFfset */
3243 ByteOffset
= &FileObject
->CurrentByteOffset
;
3246 else if (HandleInformation
.GrantedAccess
& FILE_APPEND_DATA
)
3248 /* a valid ByteOffset is required if asynch. op. */
3249 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3251 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3252 ObDereferenceObject(FileObject
);
3253 return STATUS_INVALID_PARAMETER
;
3256 /* Give the drivers somethign to understand */
3257 ByteOffset
->u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3258 ByteOffset
->u
.HighPart
= 0xffffffff;
3261 /* Check if we got an event */
3265 Status
= ObReferenceObjectByHandle(Event
,
3269 (PVOID
*)&EventObject
,
3271 if (!NT_SUCCESS(Status
))
3273 ObDereferenceObject(FileObject
);
3276 KeClearEvent(EventObject
);
3279 /* Check if this is a direct open or not */
3280 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3282 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3286 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3289 /* Check if we should use Sync IO or not */
3290 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3292 /* Use File Object event */
3293 KeClearEvent(&FileObject
->Event
);
3303 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
3312 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3317 Status
= _SEH_GetExceptionCode();
3321 /* Cleanup on failure */
3322 if (!NT_SUCCESS(Status
))
3326 ObDereferenceObject(&EventObject
);
3328 ObDereferenceObject(FileObject
);
3332 /* Set up IRP Data */
3333 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3334 Irp
->RequestorMode
= PreviousMode
;
3335 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3336 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3337 Irp
->Flags
|= IRP_WRITE_OPERATION
;
3340 * Vfat doesn't handle non cached files correctly.
3342 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3345 /* Setup Stack Data */
3346 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3347 StackPtr
->FileObject
= FileObject
;
3348 StackPtr
->Parameters
.Write
.Key
= Key
? *Key
: 0;
3349 if (FileObject
->Flags
& FO_WRITE_THROUGH
) StackPtr
->Flags
= SL_WRITE_THROUGH
;
3351 /* Call the Driver */
3352 Status
= IoCallDriver(DeviceObject
, Irp
);
3353 if (Status
== STATUS_PENDING
)
3357 KeWaitForSingleObject(&FileObject
->Event
,
3360 FileObject
->Flags
& FO_ALERTABLE_IO
,
3362 Status
= FileObject
->FinalStatus
;
3366 /* Return the Status */
3384 NtWriteFileGather(IN HANDLE FileHandle
,
3385 IN HANDLE Event OPTIONAL
,
3386 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3387 IN PVOID UserApcContext OPTIONAL
,
3388 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3389 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3390 IN ULONG BufferLength
,
3391 IN PLARGE_INTEGER ByteOffset
,
3392 IN PULONG Key OPTIONAL
)
3395 return(STATUS_NOT_IMPLEMENTED
);