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 extern GENERIC_MAPPING IopFileMapping
;
23 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation
,
24 PSECURITY_DESCRIPTOR SecurityDescriptor
,
27 /* INTERNAL FUNCTIONS ********************************************************/
43 IopCreateFile(PVOID ObjectBody
,
46 POBJECT_CREATE_INFORMATION ObjectCreateInfo
)
48 PDEVICE_OBJECT DeviceObject
;
49 PFILE_OBJECT FileObject
= (PFILE_OBJECT
) ObjectBody
;
50 POBJECT_TYPE ParentObjectType
;
53 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
60 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
61 for the cache manager, so return STATUS_SUCCESS */
62 DPRINT("Parent object was NULL\n");
63 return(STATUS_SUCCESS
);
66 ParentObjectType
= BODY_TO_HEADER(Parent
)->ObjectType
;
68 if (ParentObjectType
!= IoDeviceObjectType
&&
69 ParentObjectType
!= IoFileObjectType
)
71 DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n",
72 &BODY_TO_HEADER(Parent
)->NameInfo
->Name
,
73 BODY_TO_HEADER(Parent
)->ObjectType
->Name
.Buffer
,
75 return(STATUS_UNSUCCESSFUL
);
78 Status
= ObReferenceObjectByPointer(Parent
,
79 STANDARD_RIGHTS_REQUIRED
,
82 if (!NT_SUCCESS(Status
))
84 CPRINT("Failed to reference parent object %x\n", Parent
);
88 if (ParentObjectType
== IoDeviceObjectType
)
90 /* Parent is a devce object */
91 DeviceObject
= IoGetAttachedDevice((PDEVICE_OBJECT
)Parent
);
92 DPRINT("DeviceObject %x\n", DeviceObject
);
94 if (RemainingPath
== NULL
)
96 FileObject
->Flags
= FileObject
->Flags
| FO_DIRECT_DEVICE_OPEN
;
97 FileObject
->FileName
.Buffer
= 0;
98 FileObject
->FileName
.Length
= FileObject
->FileName
.MaximumLength
= 0;
102 if ((DeviceObject
->DeviceType
!= FILE_DEVICE_FILE_SYSTEM
)
103 && (DeviceObject
->DeviceType
!= FILE_DEVICE_DISK
)
104 && (DeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
)
105 && (DeviceObject
->DeviceType
!= FILE_DEVICE_TAPE
)
106 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
)
107 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
108 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
110 CPRINT("Device was wrong type\n");
111 return(STATUS_UNSUCCESSFUL
);
114 if (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
115 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
116 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
118 if (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
120 DPRINT("Mount the logical volume\n");
121 Status
= IoMountVolume(DeviceObject
, FALSE
);
122 DPRINT("Status %x\n", Status
);
123 if (!NT_SUCCESS(Status
))
125 CPRINT("Failed to mount logical volume (Status %x)\n",
130 DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
131 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
133 RtlpCreateUnicodeString(&(FileObject
->FileName
),
134 RemainingPath
, NonPagedPool
);
139 /* Parent is a file object */
140 if (RemainingPath
== NULL
)
142 CPRINT("Device is unnamed\n");
143 return STATUS_UNSUCCESSFUL
;
146 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
147 DPRINT("DeviceObject %x\n", DeviceObject
);
149 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
151 RtlpCreateUnicodeString(&(FileObject
->FileName
),
152 RemainingPath
, NonPagedPool
);
155 DPRINT("FileObject->FileName %wZ\n",
156 &FileObject
->FileName
);
157 FileObject
->DeviceObject
= DeviceObject
;
158 DPRINT("FileObject %x DeviceObject %x\n",
161 FileObject
->Vpb
= DeviceObject
->Vpb
;
162 FileObject
->Type
= IO_TYPE_FILE
;
164 return(STATUS_SUCCESS
);
169 IopDeleteFile(PVOID ObjectBody
)
171 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
173 PIO_STACK_LOCATION StackPtr
;
176 PDEVICE_OBJECT DeviceObject
;
178 DPRINT("IopDeleteFile()\n");
180 if (FileObject
->DeviceObject
)
182 /* Check if this is a direct open or not */
183 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
185 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
189 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
192 /* Clear and set up Events */
193 KeClearEvent(&FileObject
->Event
);
194 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
196 /* Allocate an IRP */
197 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
200 Irp
->UserEvent
= &Event
;
201 Irp
->UserIosb
= &Irp
->IoStatus
;
202 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
203 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
204 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
206 /* Set up Stack Pointer Data */
207 StackPtr
= IoGetNextIrpStackLocation(Irp
);
208 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
209 StackPtr
->DeviceObject
= DeviceObject
;
210 StackPtr
->FileObject
= FileObject
;
212 /* Call the FS Driver */
213 Status
= IoCallDriver(DeviceObject
, Irp
);
215 /* Wait for completion */
216 if (Status
== STATUS_PENDING
)
218 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
224 /* Clear the file name */
225 if (FileObject
->FileName
.Buffer
)
227 ExFreePool(FileObject
->FileName
.Buffer
);
228 FileObject
->FileName
.Buffer
= NULL
;
231 /* Free the completion context */
232 if (FileObject
->CompletionContext
)
234 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
235 ExFreePool(FileObject
->CompletionContext
);
241 IopSecurityFile(PVOID ObjectBody
,
242 SECURITY_OPERATION_CODE OperationCode
,
243 SECURITY_INFORMATION SecurityInformation
,
244 PSECURITY_DESCRIPTOR SecurityDescriptor
,
247 IO_STATUS_BLOCK IoStatusBlock
;
248 PIO_STACK_LOCATION StackPtr
;
249 PFILE_OBJECT FileObject
;
250 PDEVICE_OBJECT DeviceObject
;
253 BOOLEAN LocalEvent
= FALSE
;
255 NTSTATUS Status
= STATUS_SUCCESS
;
257 DPRINT("IopSecurityFile() called\n");
259 FileObject
= (PFILE_OBJECT
)ObjectBody
;
261 if (OperationCode
== QuerySecurityDescriptor
)
263 MajorFunction
= IRP_MJ_QUERY_SECURITY
;
264 DPRINT("Query security descriptor\n");
266 else if (OperationCode
== DeleteSecurityDescriptor
)
269 return STATUS_SUCCESS
;
271 else if (OperationCode
== AssignSecurityDescriptor
)
273 /* If this is a direct open, we can assign it */
274 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
276 /* Get the Device Object */
278 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
280 /* Assign the Security Descriptor */
281 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
283 return STATUS_SUCCESS
;
287 MajorFunction
= IRP_MJ_SET_SECURITY
;
288 DPRINT("Set security descriptor\n");
290 /* If this is a direct open, we can set it */
291 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
293 DPRINT1("Set SD unimplemented for Devices\n");
294 return STATUS_SUCCESS
;
298 /* Get the Device Object */
299 DPRINT1("FileObject: %p\n", FileObject
);
300 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
302 /* Check if we should use Sync IO or not */
303 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
305 /* Use File Object event */
306 KeClearEvent(&FileObject
->Event
);
310 /* Use local event */
311 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
315 /* Allocate the IRP */
316 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
319 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
320 Irp
->RequestorMode
= ExGetPreviousMode();
321 Irp
->UserIosb
= &IoStatusBlock
;
322 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
323 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
324 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
326 /* Set Stack Parameters */
327 StackPtr
= IoGetNextIrpStackLocation(Irp
);
328 StackPtr
->FileObject
= FileObject
;
331 if (OperationCode
== QuerySecurityDescriptor
)
333 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
= SecurityInformation
;
334 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
335 Irp
->UserBuffer
= SecurityDescriptor
;
339 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
= SecurityInformation
;
340 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
= SecurityDescriptor
;
343 ObReferenceObject(FileObject
);
345 /* Call the Driver */
346 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
348 if (Status
== STATUS_PENDING
)
352 KeWaitForSingleObject(&Event
,
355 FileObject
->Flags
& FO_ALERTABLE_IO
,
357 Status
= IoStatusBlock
.Status
;
361 KeWaitForSingleObject(&FileObject
->Event
,
364 FileObject
->Flags
& FO_ALERTABLE_IO
,
366 Status
= FileObject
->FinalStatus
;
370 /* This Driver doesn't implement Security, so try to give it a default */
371 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
373 if (OperationCode
== QuerySecurityDescriptor
)
375 /* Set a World Security Descriptor */
376 Status
= SeSetWorldSecurityDescriptor(SecurityInformation
,
382 /* It wasn't a query, so just fake success */
383 Status
= STATUS_SUCCESS
;
386 else if (OperationCode
== QuerySecurityDescriptor
)
389 *BufferLength
= IoStatusBlock
.Information
;
398 IopQueryNameFile(PVOID ObjectBody
,
399 POBJECT_NAME_INFORMATION ObjectNameInfo
,
404 PFILE_OBJECT FileObject
;
405 ULONG LocalReturnLength
;
408 DPRINT1("IopQueryNameFile() called\n");
410 FileObject
= (PFILE_OBJECT
)ObjectBody
;
412 /* Allocate Buffer */
413 LocalInfo
= ExAllocatePool(PagedPool
,
414 sizeof(OBJECT_NAME_INFORMATION
) +
415 MAX_PATH
* sizeof(WCHAR
));
416 if (LocalInfo
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
419 Status
= ObQueryNameString(FileObject
->DeviceObject
,
421 MAX_PATH
* sizeof(WCHAR
),
423 if (!NT_SUCCESS (Status
))
425 ExFreePool (LocalInfo
);
428 DPRINT ("Device path: %wZ\n", &LocalInfo
->Name
);
430 /* Write Device Path */
431 Status
= RtlAppendUnicodeStringToString(&ObjectNameInfo
->Name
,
432 &((POBJECT_NAME_INFORMATION
)LocalInfo
)->Name
);
434 /* Query the File name */
435 Status
= IoQueryFileInformation(FileObject
,
440 if (Status
!= STATUS_SUCCESS
)
442 ExFreePool(LocalInfo
);
447 Status
= RtlAppendUnicodeToString(&ObjectNameInfo
->Name
,
448 ((PFILE_NAME_INFORMATION
)LocalInfo
)->FileName
);
449 DPRINT ("Total path: %wZ\n", &ObjectNameInfo
->Name
);
451 /* Free buffer and return */
452 ExFreePool(LocalInfo
);
458 IopCloseFile(PVOID ObjectBody
,
461 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
464 PIO_STACK_LOCATION StackPtr
;
466 PDEVICE_OBJECT DeviceObject
;
468 DPRINT("IopCloseFile()\n");
470 if (HandleCount
> 1 || FileObject
->DeviceObject
== NULL
) return;
472 /* Check if this is a direct open or not */
473 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
475 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
479 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
482 /* Clear and set up Events */
483 KeClearEvent(&FileObject
->Event
);
484 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
486 /* Allocate an IRP */
487 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
490 Irp
->UserEvent
= &Event
;
491 Irp
->UserIosb
= &Irp
->IoStatus
;
492 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
493 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
494 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
496 /* Set up Stack Pointer Data */
497 StackPtr
= IoGetNextIrpStackLocation(Irp
);
498 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
499 StackPtr
->FileObject
= FileObject
;
501 /* Call the FS Driver */
502 Status
= IoCallDriver(DeviceObject
, Irp
);
504 /* Wait for completion */
505 if (Status
== STATUS_PENDING
)
507 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
514 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
515 IN HANDLE Event OPTIONAL
,
516 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
517 IN PVOID UserApcContext OPTIONAL
,
518 OUT PIO_STATUS_BLOCK IoStatusBlock
,
519 IN ULONG IoControlCode
,
520 IN PVOID InputBuffer
,
521 IN ULONG InputBufferLength OPTIONAL
,
522 OUT PVOID OutputBuffer
,
523 IN ULONG OutputBufferLength OPTIONAL
,
526 NTSTATUS Status
= STATUS_SUCCESS
;
527 PFILE_OBJECT FileObject
;
528 PDEVICE_OBJECT DeviceObject
;
530 PIO_STACK_LOCATION StackPtr
;
531 PKEVENT EventObject
= NULL
;
532 BOOLEAN LocalEvent
= FALSE
;
533 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
535 DPRINT("IopDeviceFsIoControl(DeviceHandle %x Event %x UserApcRoutine %x "
536 "UserApcContext %x IoStatusBlock %x IoControlCode %x "
537 "InputBuffer %x InputBufferLength %x OutputBuffer %x "
538 "OutputBufferLength %x)\n",
539 DeviceHandle
,Event
,UserApcRoutine
,UserApcContext
,IoStatusBlock
,
540 IoControlCode
,InputBuffer
,InputBufferLength
,OutputBuffer
,
543 if (IoStatusBlock
== NULL
) return STATUS_ACCESS_VIOLATION
;
545 /* Check granted access against the access rights from IoContolCode */
546 Status
= ObReferenceObjectByHandle(DeviceHandle
,
547 (IoControlCode
>> 14) & 0x3,
550 (PVOID
*) &FileObject
,
552 if (!NT_SUCCESS(Status
)) return Status
;
554 /* Check for an event */
558 Status
= ObReferenceObjectByHandle(Event
,
562 (PVOID
*)&EventObject
,
564 if (!NT_SUCCESS(Status
))
566 ObDereferenceObject (FileObject
);
571 KeClearEvent(EventObject
);
574 /* Check if this is a direct open or not */
575 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
577 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
581 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
584 /* Check if we should use Sync IO or not */
585 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
587 /* Use File Object event */
588 KeClearEvent(&FileObject
->Event
);
592 /* Use local event */
597 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
607 /* Set some extra settings */
608 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
609 Irp
->RequestorMode
= PreviousMode
;
610 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
611 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
612 StackPtr
= IoGetNextIrpStackLocation(Irp
);
613 StackPtr
->FileObject
= FileObject
;
614 StackPtr
->MajorFunction
= IsDevIoCtl
?
615 IRP_MJ_DEVICE_CONTROL
: IRP_MJ_FILE_SYSTEM_CONTROL
;
617 /* Call the Driver */
618 Status
= IoCallDriver(DeviceObject
, Irp
);
619 if (Status
== STATUS_PENDING
)
623 KeWaitForSingleObject(&FileObject
->Event
,
626 FileObject
->Flags
& FO_ALERTABLE_IO
,
628 Status
= FileObject
->FinalStatus
;
632 /* Return the Status */
636 /* FUNCTIONS *****************************************************************/
643 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
645 IN BOOLEAN SetOperation
)
648 return STATUS_NOT_IMPLEMENTED
;
656 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
657 IN ULONG QuotaLength
,
658 OUT PULONG ErrorOffset
)
661 return STATUS_NOT_IMPLEMENTED
;
669 * Either causes a new file or directory to be created, or it
670 * opens an existing file, device, directory or volume, giving
671 * the caller a handle for the file object. This handle can be
672 * used by subsequent calls to manipulate data within the file
673 * or the file object's state of attributes.
677 * Points to a variable which receives the file handle
681 * Desired access to the file;
684 * Structure describing the file;
686 * IoStatusBlock (OUT)
687 * Receives information about the operation on return;
689 * AllocationSize [OPTIONAL]
690 * Initial size of the file in bytes;
693 * Attributes to create the file with;
696 * Type of shared access the caller would like to the
700 * Specifies what to do, depending on whether the
701 * file already exists;
704 * Options for creating a new file;
706 * EaBuffer [OPTIONAL]
713 * Type of file (normal, named pipe, mailslot) to create;
715 * ExtraCreateParameters [OPTIONAL]
716 * Additional creation data for named pipe and mailsots;
725 * Prototype taken from Bo Branten's ntifs.h v15.
726 * Description taken from old NtCreateFile's which is
727 * now a wrapper of this call.
735 IoCreateFile(OUT PHANDLE FileHandle
,
736 IN ACCESS_MASK DesiredAccess
,
737 IN POBJECT_ATTRIBUTES ObjectAttributes
,
738 OUT PIO_STATUS_BLOCK IoStatusBlock
,
739 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
740 IN ULONG FileAttributes
,
741 IN ULONG ShareAccess
,
742 IN ULONG CreateDisposition
,
743 IN ULONG CreateOptions
,
744 IN PVOID EaBuffer OPTIONAL
,
746 IN CREATE_FILE_TYPE CreateFileType
,
747 IN PVOID ExtraCreateParameters OPTIONAL
,
750 PFILE_OBJECT FileObject
= NULL
;
751 PDEVICE_OBJECT DeviceObject
;
753 PIO_STACK_LOCATION StackLoc
;
754 IO_SECURITY_CONTEXT SecurityContext
;
755 KPROCESSOR_MODE AccessMode
;
757 IO_STATUS_BLOCK LocalIoStatusBlock
;
758 LARGE_INTEGER SafeAllocationSize
;
759 PVOID SystemEaBuffer
= NULL
;
760 NTSTATUS Status
= STATUS_SUCCESS
;
762 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
763 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
764 FileHandle
,DesiredAccess
,ObjectAttributes
,
765 ObjectAttributes
->ObjectName
->Buffer
);
767 ASSERT_IRQL(PASSIVE_LEVEL
);
769 if (IoStatusBlock
== NULL
|| FileHandle
== NULL
)
770 return STATUS_ACCESS_VIOLATION
;
774 if(Options
& IO_NO_PARAMETER_CHECKING
)
775 AccessMode
= KernelMode
;
777 AccessMode
= ExGetPreviousMode();
779 if(AccessMode
!= KernelMode
)
783 ProbeForWrite(FileHandle
,
786 ProbeForWrite(IoStatusBlock
,
787 sizeof(IO_STATUS_BLOCK
),
789 if(AllocationSize
!= NULL
)
791 ProbeForRead(AllocationSize
,
792 sizeof(LARGE_INTEGER
),
794 SafeAllocationSize
= *AllocationSize
;
797 SafeAllocationSize
.QuadPart
= 0;
799 if(EaBuffer
!= NULL
&& EaLength
> 0)
801 ProbeForRead(EaBuffer
,
805 /* marshal EaBuffer */
806 SystemEaBuffer
= ExAllocatePool(NonPagedPool
,
808 if(SystemEaBuffer
== NULL
)
810 Status
= STATUS_INSUFFICIENT_RESOURCES
;
814 RtlCopyMemory(SystemEaBuffer
,
821 Status
= _SEH_GetExceptionCode();
825 if(!NT_SUCCESS(Status
))
832 if(AllocationSize
!= NULL
)
833 SafeAllocationSize
= *AllocationSize
;
835 SafeAllocationSize
.QuadPart
= 0;
837 if(EaBuffer
!= NULL
&& EaLength
> 0)
839 SystemEaBuffer
= EaBuffer
;
843 if(Options
& IO_CHECK_CREATE_PARAMETERS
)
845 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
848 if (CreateDisposition
== FILE_OPEN
||
849 CreateDisposition
== FILE_OPEN_IF
)
852 Status
= ObOpenObjectByName(ObjectAttributes
,
860 if (NT_SUCCESS(Status
))
862 Status
= ObReferenceObjectByHandle(LocalHandle
,
866 (PVOID
*)&DeviceObject
,
868 ZwClose(LocalHandle
);
869 if (!NT_SUCCESS(Status
))
873 if (BODY_TO_HEADER(DeviceObject
)->ObjectType
!= IoDeviceObjectType
)
875 ObDereferenceObject (DeviceObject
);
876 return STATUS_OBJECT_NAME_COLLISION
;
879 FileObject
= IoCreateStreamFileObject(NULL
, DeviceObject
);
881 FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
882 DPRINT("%wZ\n", ObjectAttributes
->ObjectName
);
884 ObDereferenceObject (DeviceObject
);
889 if (FileObject
== NULL
)
891 Status
= ObCreateObject(AccessMode
,
899 (PVOID
*)&FileObject
);
900 if (!NT_SUCCESS(Status
))
902 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
906 RtlMapGenericMask(&DesiredAccess
,
907 &BODY_TO_HEADER(FileObject
)->ObjectType
->TypeInfo
.GenericMapping
);
909 Status
= ObInsertObject ((PVOID
)FileObject
,
915 if (!NT_SUCCESS(Status
))
917 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
918 ObDereferenceObject (FileObject
);
922 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
924 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
926 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
928 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
931 if (CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
932 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
934 SecurityContext
.SecurityQos
= NULL
; /* ?? */
935 SecurityContext
.AccessState
= NULL
; /* ?? */
936 SecurityContext
.DesiredAccess
= DesiredAccess
;
937 SecurityContext
.FullCreateOptions
= 0; /* ?? */
939 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
940 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
942 DPRINT("FileObject %x\n", FileObject
);
943 DPRINT("FileObject->DeviceObject %x\n", FileObject
->DeviceObject
);
945 * Create a new IRP to hand to
946 * the FS driver: this may fail
947 * due to resource shortage.
949 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
952 ZwClose(LocalHandle
);
953 return STATUS_UNSUCCESSFUL
;
956 //trigger FileObject/Event dereferencing
957 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
958 Irp
->RequestorMode
= AccessMode
;
959 Irp
->UserIosb
= &LocalIoStatusBlock
;
960 Irp
->AssociatedIrp
.SystemBuffer
= SystemEaBuffer
;
961 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
962 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
963 Irp
->UserEvent
= &FileObject
->Event
;
964 Irp
->Overlay
.AllocationSize
= SafeAllocationSize
;
967 * Get the stack location for the new
968 * IRP and prepare it.
970 StackLoc
= IoGetNextIrpStackLocation(Irp
);
971 StackLoc
->MinorFunction
= 0;
972 StackLoc
->Flags
= (UCHAR
)Options
;
973 StackLoc
->Control
= 0;
974 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
975 StackLoc
->FileObject
= FileObject
;
977 switch (CreateFileType
)
980 case CreateFileTypeNone
:
981 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
982 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
983 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
984 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
985 StackLoc
->Parameters
.Create
.FileAttributes
= (USHORT
)FileAttributes
;
986 StackLoc
->Parameters
.Create
.ShareAccess
= (USHORT
)ShareAccess
;
987 StackLoc
->Parameters
.Create
.EaLength
= SystemEaBuffer
!= NULL
? EaLength
: 0;
990 case CreateFileTypeNamedPipe
:
991 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
992 StackLoc
->Parameters
.CreatePipe
.SecurityContext
= &SecurityContext
;
993 StackLoc
->Parameters
.CreatePipe
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
994 StackLoc
->Parameters
.CreatePipe
.Options
|= (CreateDisposition
<< 24);
995 StackLoc
->Parameters
.CreatePipe
.ShareAccess
= (USHORT
)ShareAccess
;
996 StackLoc
->Parameters
.CreatePipe
.Parameters
= ExtraCreateParameters
;
999 case CreateFileTypeMailslot
:
1000 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
1001 StackLoc
->Parameters
.CreateMailslot
.SecurityContext
= &SecurityContext
;
1002 StackLoc
->Parameters
.CreateMailslot
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
1003 StackLoc
->Parameters
.CreateMailslot
.Options
|= (CreateDisposition
<< 24);
1004 StackLoc
->Parameters
.CreateMailslot
.ShareAccess
= (USHORT
)ShareAccess
;
1005 StackLoc
->Parameters
.CreateMailslot
.Parameters
= ExtraCreateParameters
;
1010 * Now call the driver and
1011 * possibly wait if it can
1012 * not complete the request
1015 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
1016 DPRINT("Status :%x\n", Status
);
1018 if (Status
== STATUS_PENDING
)
1020 KeWaitForSingleObject(&FileObject
->Event
,
1025 Status
= LocalIoStatusBlock
.Status
;
1027 if (!NT_SUCCESS(Status
))
1029 DPRINT("Failing create request with status %x\n", Status
);
1030 FileObject
->DeviceObject
= NULL
;
1031 FileObject
->Vpb
= NULL
;
1033 ZwClose(LocalHandle
);
1039 *FileHandle
= LocalHandle
;
1040 *IoStatusBlock
= LocalIoStatusBlock
;
1044 Status
= _SEH_GetExceptionCode();
1049 /* cleanup EABuffer if captured */
1050 if(AccessMode
!= KernelMode
&& SystemEaBuffer
!= NULL
)
1052 ExFreePool(SystemEaBuffer
);
1055 ASSERT_IRQL(PASSIVE_LEVEL
);
1057 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle
));
1067 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
1068 IN ACCESS_MASK DesiredAccess
,
1069 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1070 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1071 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1072 IN ULONG FileAttributes
,
1073 IN ULONG ShareAccess
,
1074 IN ULONG Disposition
,
1075 IN ULONG CreateOptions
,
1076 IN PVOID EaBuffer OPTIONAL
,
1078 IN CREATE_FILE_TYPE CreateFileType
,
1079 IN PVOID ExtraCreateParameters OPTIONAL
,
1081 IN PVOID DeviceObject
)
1084 return STATUS_NOT_IMPLEMENTED
;
1089 * IoCreateStreamFileObject@8
1110 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
1111 PDEVICE_OBJECT DeviceObject
)
1113 PFILE_OBJECT CreatedFileObject
;
1116 /* FIXME: This function should call ObInsertObject. The "Lite" version
1117 doesnt. This function is also called from IoCreateFile for some
1118 reason. These hacks need to be removed.
1121 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
1122 FileObject
, DeviceObject
);
1125 /* Create the File Object */
1126 Status
= ObCreateObject(KernelMode
,
1131 sizeof(FILE_OBJECT
),
1134 (PVOID
*)&CreatedFileObject
);
1135 if (!NT_SUCCESS(Status
))
1137 DPRINT1("Could not create FileObject\n");
1141 /* Choose Device Object */
1142 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1143 DPRINT("DeviceObject %x\n", DeviceObject
);
1146 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1148 /* Set File Object Data */
1149 CreatedFileObject
->DeviceObject
= DeviceObject
;
1150 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
1151 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1152 CreatedFileObject
->Flags
|= FO_STREAM_FILE
;
1154 /* Initialize Lock and Event */
1155 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
1156 KeInitializeEvent(&CreatedFileObject
->Lock
, SynchronizationEvent
, TRUE
);
1159 return CreatedFileObject
;
1167 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1168 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1169 OUT PHANDLE FileObjectHandle OPTIONAL
)
1180 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1181 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1192 IoGetFileObjectGenericMapping(VOID
)
1194 return &IopFileMapping
;
1202 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
1204 /* Return the flag status */
1205 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
1213 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
1214 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
1217 return STATUS_NOT_IMPLEMENTED
;
1225 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1226 IN FILE_INFORMATION_CLASS FileInformationClass
,
1228 OUT PVOID FileInformation
,
1229 OUT PULONG ReturnedLength
)
1231 IO_STATUS_BLOCK IoStatusBlock
;
1233 PDEVICE_OBJECT DeviceObject
;
1234 PIO_STACK_LOCATION StackPtr
;
1235 BOOLEAN LocalEvent
= FALSE
;
1239 ASSERT(FileInformation
!= NULL
);
1241 Status
= ObReferenceObjectByPointer(FileObject
,
1242 FILE_READ_ATTRIBUTES
,
1245 if (!NT_SUCCESS(Status
)) return(Status
);
1247 DPRINT("FileObject %x\n", FileObject
);
1249 /* Get the Device Object */
1250 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1252 /* Check if we should use Sync IO or not */
1253 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1255 /* Use File Object event */
1256 KeClearEvent(&FileObject
->Event
);
1260 /* Use local event */
1261 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1265 /* Allocate the IRP */
1266 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1269 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1270 Irp
->RequestorMode
= KernelMode
;
1271 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1272 Irp
->UserIosb
= &IoStatusBlock
;
1273 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1274 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1275 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1277 /* Set the Stack Data */
1278 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1279 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1280 StackPtr
->FileObject
= FileObject
;
1282 /* Set Parameters */
1283 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1284 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1286 /* Call the Driver */
1287 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
1289 if (Status
== STATUS_PENDING
)
1293 KeWaitForSingleObject(&Event
,
1296 FileObject
->Flags
& FO_ALERTABLE_IO
,
1298 Status
= IoStatusBlock
.Status
;
1302 KeWaitForSingleObject(&FileObject
->Event
,
1305 FileObject
->Flags
& FO_ALERTABLE_IO
,
1307 Status
= FileObject
->FinalStatus
;
1312 /* Return the Length and Status. ReturnedLength is NOT optional */
1313 *ReturnedLength
= IoStatusBlock
.Information
;
1322 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
1326 return STATUS_NOT_IMPLEMENTED
;
1330 * @name NtCancelIoFile
1332 * Cancel all pending I/O operations in the current thread for specified
1336 * Handle to file object to cancel requests for. No specific
1337 * access rights are needed.
1338 * @param IoStatusBlock
1339 * Pointer to status block which is filled with final completition
1340 * status on successful return.
1348 NtCancelIoFile(IN HANDLE FileHandle
,
1349 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1352 PFILE_OBJECT FileObject
;
1354 PLIST_ENTRY IrpEntry
;
1357 BOOLEAN OurIrpsInList
= FALSE
;
1358 LARGE_INTEGER Interval
;
1360 if ((ULONG_PTR
)IoStatusBlock
>= MmUserProbeAddress
&&
1361 KeGetPreviousMode() == UserMode
)
1362 return STATUS_ACCESS_VIOLATION
;
1364 Status
= ObReferenceObjectByHandle(FileHandle
, 0, IoFileObjectType
,
1365 KeGetPreviousMode(), (PVOID
*)&FileObject
,
1367 if (!NT_SUCCESS(Status
))
1370 /* IRP cancellations are synchronized at APC_LEVEL. */
1371 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1374 * Walk the list of active IRPs and cancel the ones that belong to
1378 Thread
= PsGetCurrentThread();
1379 for (IrpEntry
= Thread
->IrpList
.Flink
;
1380 IrpEntry
!= &Thread
->IrpList
;
1381 IrpEntry
= IrpEntry
->Flink
)
1383 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1384 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1387 /* Don't break here, we want to cancel all IRPs for the file object. */
1388 OurIrpsInList
= TRUE
;
1392 KfLowerIrql(OldIrql
);
1394 while (OurIrpsInList
)
1396 OurIrpsInList
= FALSE
;
1398 /* Wait a short while and then look if all our IRPs were completed. */
1399 Interval
.QuadPart
= -1000000; /* 100 milliseconds */
1400 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1402 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1405 * Look in the list if all IRPs for the specified file object
1406 * are completed (or cancelled). If someone sends a new IRP
1407 * for our file object while we're here we can happily loop
1411 for (IrpEntry
= Thread
->IrpList
.Flink
;
1412 IrpEntry
!= &Thread
->IrpList
;
1413 IrpEntry
= IrpEntry
->Flink
)
1415 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1416 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1418 OurIrpsInList
= TRUE
;
1423 KfLowerIrql(OldIrql
);
1428 IoStatusBlock
->Status
= STATUS_SUCCESS
;
1429 IoStatusBlock
->Information
= 0;
1430 Status
= STATUS_SUCCESS
;
1434 Status
= STATUS_UNSUCCESSFUL
;
1438 ObDereferenceObject(FileObject
);
1448 * Entry point to call IoCreateFile with
1449 * default parameters.
1459 * Code originally in NtCreateFile moved in IoCreateFile.
1465 NtCreateFile(PHANDLE FileHandle
,
1466 ACCESS_MASK DesiredAccess
,
1467 POBJECT_ATTRIBUTES ObjectAttributes
,
1468 PIO_STATUS_BLOCK IoStatusBlock
,
1469 PLARGE_INTEGER AllocateSize
,
1470 ULONG FileAttributes
,
1472 ULONG CreateDisposition
,
1473 ULONG CreateOptions
,
1477 /* Call the I/O Function */
1478 return IoCreateFile(FileHandle
,
1496 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
1497 IN ACCESS_MASK DesiredAccess
,
1498 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1499 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1500 IN ULONG CreateOptions
,
1501 IN ULONG MailslotQuota
,
1502 IN ULONG MaxMessageSize
,
1503 IN PLARGE_INTEGER TimeOut
)
1505 MAILSLOT_CREATE_PARAMETERS Buffer
;
1507 DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
1508 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1509 FileHandle
,DesiredAccess
,ObjectAttributes
,
1510 ObjectAttributes
->ObjectName
->Buffer
);
1513 /* Check for Timeout */
1517 Buffer
.TimeoutSpecified
= TRUE
;
1519 /* FIXME: Add SEH */
1520 Buffer
.ReadTimeout
= *TimeOut
;
1525 Buffer
.TimeoutSpecified
= FALSE
;
1529 Buffer
.MailslotQuota
= MailslotQuota
;
1530 Buffer
.MaximumMessageSize
= MaxMessageSize
;
1533 return IoCreateFile(FileHandle
,
1538 FILE_ATTRIBUTE_NORMAL
,
1539 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1544 CreateFileTypeMailslot
,
1551 NtCreateNamedPipeFile(PHANDLE FileHandle
,
1552 ACCESS_MASK DesiredAccess
,
1553 POBJECT_ATTRIBUTES ObjectAttributes
,
1554 PIO_STATUS_BLOCK IoStatusBlock
,
1556 ULONG CreateDisposition
,
1557 ULONG CreateOptions
,
1558 ULONG NamedPipeType
,
1560 ULONG CompletionMode
,
1561 ULONG MaximumInstances
,
1563 ULONG OutboundQuota
,
1564 PLARGE_INTEGER DefaultTimeout
)
1566 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
1568 DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
1569 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1570 FileHandle
,DesiredAccess
,ObjectAttributes
,
1571 ObjectAttributes
->ObjectName
->Buffer
);
1574 /* Check for Timeout */
1578 Buffer
.TimeoutSpecified
= TRUE
;
1580 /* FIXME: Add SEH */
1581 Buffer
.DefaultTimeout
= *DefaultTimeout
;
1586 Buffer
.TimeoutSpecified
= FALSE
;
1590 Buffer
.NamedPipeType
= NamedPipeType
;
1591 Buffer
.ReadMode
= ReadMode
;
1592 Buffer
.CompletionMode
= CompletionMode
;
1593 Buffer
.MaximumInstances
= MaximumInstances
;
1594 Buffer
.InboundQuota
= InboundQuota
;
1595 Buffer
.OutboundQuota
= OutboundQuota
;
1598 return IoCreateFile(FileHandle
,
1603 FILE_ATTRIBUTE_NORMAL
,
1609 CreateFileTypeNamedPipe
,
1632 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
1635 return(STATUS_NOT_IMPLEMENTED
);
1643 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1644 IN HANDLE Event OPTIONAL
,
1645 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1646 IN PVOID UserApcContext OPTIONAL
,
1647 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1648 IN ULONG IoControlCode
,
1649 IN PVOID InputBuffer
,
1650 IN ULONG InputBufferLength OPTIONAL
,
1651 OUT PVOID OutputBuffer
,
1652 IN ULONG OutputBufferLength OPTIONAL
)
1654 /* Call the Generic Function */
1655 return IopDeviceFsIoControl(DeviceHandle
,
1673 NtFsControlFile(IN HANDLE DeviceHandle
,
1674 IN HANDLE Event OPTIONAL
,
1675 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1676 IN PVOID UserApcContext OPTIONAL
,
1677 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1678 IN ULONG IoControlCode
,
1679 IN PVOID InputBuffer
,
1680 IN ULONG InputBufferLength OPTIONAL
,
1681 OUT PVOID OutputBuffer
,
1682 IN ULONG OutputBufferLength OPTIONAL
)
1684 return IopDeviceFsIoControl(DeviceHandle
,
1699 NtFlushWriteBuffer(VOID
)
1701 KeFlushWriteBuffer();
1702 return STATUS_SUCCESS
;
1706 * FUNCTION: Flushes cached file data to disk
1708 * FileHandle = Points to the file
1709 * IoStatusBlock = Caller must supply storage to receive the result of
1710 * the flush buffers operation. The information field is
1711 * set to number of bytes flushed to disk.
1713 * REMARKS: This function maps to the win32 FlushFileBuffers
1717 NtFlushBuffersFile(IN HANDLE FileHandle
,
1718 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1720 PFILE_OBJECT FileObject
= NULL
;
1722 PIO_STACK_LOCATION StackPtr
;
1724 PDEVICE_OBJECT DeviceObject
;
1726 BOOLEAN LocalEvent
= FALSE
;
1727 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1729 /* Get the File Object */
1730 Status
= ObReferenceObjectByHandle(FileHandle
,
1734 (PVOID
*)&FileObject
,
1736 if (Status
!= STATUS_SUCCESS
) return(Status
);
1738 /* Check if this is a direct open or not */
1739 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1741 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1745 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1748 /* Check if we should use Sync IO or not */
1749 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1751 /* Use File Object event */
1752 KeClearEvent(&FileObject
->Event
);
1756 /* Use local event */
1757 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1761 /* Allocate the IRP */
1762 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
1764 ObDereferenceObject(FileObject
);
1765 return STATUS_INSUFFICIENT_RESOURCES
;
1768 /* Set up the IRP */
1769 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1770 Irp
->RequestorMode
= PreviousMode
;
1771 Irp
->UserIosb
= IoStatusBlock
;
1772 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1773 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1774 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1776 /* Set up Stack Data */
1777 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1778 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1779 StackPtr
->FileObject
= FileObject
;
1781 /* Call the Driver */
1782 Status
= IoCallDriver(DeviceObject
, Irp
);
1783 if (Status
== STATUS_PENDING
)
1787 KeWaitForSingleObject(&Event
,
1790 FileObject
->Flags
& FO_ALERTABLE_IO
,
1792 Status
= IoStatusBlock
->Status
;
1796 KeWaitForSingleObject(&FileObject
->Event
,
1799 FileObject
->Flags
& FO_ALERTABLE_IO
,
1801 Status
= FileObject
->FinalStatus
;
1805 /* Return the Status */
1814 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1815 IN HANDLE Event OPTIONAL
,
1816 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1817 IN PVOID ApcContext OPTIONAL
,
1818 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1820 IN ULONG BufferSize
,
1821 IN ULONG CompletionFilter
,
1822 IN BOOLEAN WatchTree
)
1825 PDEVICE_OBJECT DeviceObject
;
1826 PFILE_OBJECT FileObject
;
1827 PIO_STACK_LOCATION IoStack
;
1828 KPROCESSOR_MODE PreviousMode
;
1829 NTSTATUS Status
= STATUS_SUCCESS
;
1831 DPRINT("NtNotifyChangeDirectoryFile()\n");
1835 PreviousMode
= ExGetPreviousMode();
1837 if(PreviousMode
!= KernelMode
)
1841 ProbeForWrite(IoStatusBlock
,
1842 sizeof(IO_STATUS_BLOCK
),
1846 ProbeForWrite(Buffer
,
1853 Status
= _SEH_GetExceptionCode();
1857 if(!NT_SUCCESS(Status
))
1863 Status
= ObReferenceObjectByHandle(FileHandle
,
1864 FILE_LIST_DIRECTORY
,
1867 (PVOID
*)&FileObject
,
1869 if (Status
!= STATUS_SUCCESS
) return(Status
);
1872 DeviceObject
= FileObject
->DeviceObject
;
1875 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1878 ObDereferenceObject(FileObject
);
1879 return STATUS_UNSUCCESSFUL
;
1884 Event
= &FileObject
->Event
;
1887 /* Trigger FileObject/Event dereferencing */
1888 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1889 Irp
->RequestorMode
= PreviousMode
;
1890 Irp
->UserIosb
= IoStatusBlock
;
1891 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1892 Irp
->UserEvent
= Event
;
1893 KeResetEvent( Event
);
1894 Irp
->UserBuffer
= Buffer
;
1895 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1896 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1898 IoStack
= IoGetNextIrpStackLocation(Irp
);
1900 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1901 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1903 IoStack
->Control
= 0;
1904 IoStack
->DeviceObject
= DeviceObject
;
1905 IoStack
->FileObject
= FileObject
;
1909 IoStack
->Flags
= SL_WATCH_TREE
;
1912 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1913 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1915 Status
= IoCallDriver(FileObject
->DeviceObject
,Irp
);
1917 /* FIXME: Should we wait here or not for synchronously opened files? */
1927 NtLockFile(IN HANDLE FileHandle
,
1928 IN HANDLE EventHandle OPTIONAL
,
1929 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1930 IN PVOID ApcContext OPTIONAL
,
1931 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1932 IN PLARGE_INTEGER ByteOffset
,
1933 IN PLARGE_INTEGER Length
,
1935 IN BOOLEAN FailImmediately
,
1936 IN BOOLEAN ExclusiveLock
)
1938 PFILE_OBJECT FileObject
= NULL
;
1939 PLARGE_INTEGER LocalLength
= NULL
;
1941 PIO_STACK_LOCATION StackPtr
;
1942 PDEVICE_OBJECT DeviceObject
;
1943 PKEVENT Event
= NULL
;
1944 BOOLEAN LocalEvent
= FALSE
;
1945 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1946 NTSTATUS Status
= STATUS_SUCCESS
;
1947 OBJECT_HANDLE_INFORMATION HandleInformation
;
1949 /* FIXME: instead of this, use SEH */
1950 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
1952 /* Get File Object */
1953 Status
= ObReferenceObjectByHandle(FileHandle
,
1957 (PVOID
*)&FileObject
,
1958 &HandleInformation
);
1959 if (!NT_SUCCESS(Status
)) return Status
;
1961 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
1962 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1964 DPRINT1("Invalid access rights\n");
1965 ObDereferenceObject(FileObject
);
1966 return STATUS_ACCESS_DENIED
;
1969 /* Get Event Object */
1972 Status
= ObReferenceObjectByHandle(EventHandle
,
1978 if (Status
!= STATUS_SUCCESS
) return(Status
);
1979 KeClearEvent(Event
);
1982 /* Check if this is a direct open or not */
1983 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1985 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1989 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1992 /* Check if we should use Sync IO or not */
1993 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1995 /* Use File Object event */
1996 KeClearEvent(&FileObject
->Event
);
2003 /* Allocate the IRP */
2004 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2006 ObDereferenceObject(FileObject
);
2007 return STATUS_INSUFFICIENT_RESOURCES
;
2010 /* Allocate local buffer */
2011 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2012 sizeof(LARGE_INTEGER
),
2017 ObDereferenceObject(FileObject
);
2018 return STATUS_INSUFFICIENT_RESOURCES
;
2020 *LocalLength
= *Length
;
2022 /* Set up the IRP */
2023 Irp
->RequestorMode
= PreviousMode
;
2024 Irp
->UserIosb
= IoStatusBlock
;
2025 Irp
->UserEvent
= Event
;
2026 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2027 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2029 /* Set up Stack Data */
2030 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2031 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2032 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
2033 StackPtr
->FileObject
= FileObject
;
2035 /* Set Parameters */
2036 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2037 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
2038 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
2041 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
2042 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
2044 /* Call the Driver */
2045 FileObject
->LockOperation
= TRUE
;
2046 Status
= IoCallDriver(DeviceObject
, Irp
);
2047 if (Status
== STATUS_PENDING
)
2051 KeWaitForSingleObject(&FileObject
->Event
,
2054 FileObject
->Flags
& FO_ALERTABLE_IO
,
2056 Status
= FileObject
->FinalStatus
;
2060 /* Return the Status */
2069 * Opens an existing file (simpler than NtCreateFile).
2073 * Variable that receives the file handle on return;
2076 * Access desired by the caller to the file;
2079 * Structue describing the file to be opened;
2081 * IoStatusBlock (OUT)
2082 * Receives details about the result of the
2086 * Type of shared access the caller requires;
2089 * Options for the file open.
2101 NtOpenFile(PHANDLE FileHandle
,
2102 ACCESS_MASK DesiredAccess
,
2103 POBJECT_ATTRIBUTES ObjectAttributes
,
2104 PIO_STATUS_BLOCK IoStatusBlock
,
2108 /* Call the I/O Function */
2109 return IoCreateFile(FileHandle
,
2127 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2128 OUT PFILE_BASIC_INFORMATION FileInformation
)
2130 IO_STATUS_BLOCK IoStatusBlock
;
2135 Status
= ZwOpenFile(&FileHandle
,
2136 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2139 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2140 FILE_SYNCHRONOUS_IO_NONALERT
);
2141 if (!NT_SUCCESS (Status
))
2143 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2147 /* Get file attributes */
2148 Status
= ZwQueryInformationFile(FileHandle
,
2151 sizeof(FILE_BASIC_INFORMATION
),
2152 FileBasicInformation
);
2153 if (!NT_SUCCESS (Status
))
2155 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2158 ZwClose(FileHandle
);
2165 * FUNCTION: Queries a directory file.
2167 * FileHandle = Handle to a directory file
2168 * EventHandle = Handle to the event signaled on completion
2169 * ApcRoutine = Asynchroneous procedure callback, called on completion
2170 * ApcContext = Argument to the apc.
2171 * IoStatusBlock = Caller supplies storage for extended status information.
2172 * FileInformation = Caller supplies storage for the resulting information.
2174 * FileNameInformation FILE_NAMES_INFORMATION
2175 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2176 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2177 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2179 * Length = Size of the storage supplied
2180 * FileInformationClass = Indicates the type of information requested.
2181 * ReturnSingleEntry = Specify true if caller only requests the first
2183 * FileName = Initial directory name to query, that may contain wild
2185 * RestartScan = Number of times the action should be repeated
2186 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2187 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2188 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2192 NtQueryDirectoryFile(IN HANDLE FileHandle
,
2193 IN HANDLE PEvent OPTIONAL
,
2194 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2195 IN PVOID ApcContext OPTIONAL
,
2196 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2197 OUT PVOID FileInformation
,
2199 IN FILE_INFORMATION_CLASS FileInformationClass
,
2200 IN BOOLEAN ReturnSingleEntry
,
2201 IN PUNICODE_STRING FileName OPTIONAL
,
2202 IN BOOLEAN RestartScan
)
2205 PDEVICE_OBJECT DeviceObject
;
2206 PFILE_OBJECT FileObject
;
2207 PIO_STACK_LOCATION StackPtr
;
2208 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2209 NTSTATUS Status
= STATUS_SUCCESS
;
2210 BOOLEAN LocalEvent
= FALSE
;
2211 PKEVENT Event
= NULL
;
2213 DPRINT("NtQueryDirectoryFile()\n");
2216 /* Validate User-Mode Buffers */
2217 if(PreviousMode
!= KernelMode
)
2221 ProbeForWrite(IoStatusBlock
,
2222 sizeof(IO_STATUS_BLOCK
),
2224 ProbeForWrite(FileInformation
,
2230 Status
= _SEH_GetExceptionCode();
2234 if(!NT_SUCCESS(Status
)) return Status
;
2237 /* Get File Object */
2238 Status
= ObReferenceObjectByHandle(FileHandle
,
2239 FILE_LIST_DIRECTORY
,
2242 (PVOID
*)&FileObject
,
2244 if (Status
!= STATUS_SUCCESS
) return(Status
);
2246 /* Get Event Object */
2249 Status
= ObReferenceObjectByHandle(PEvent
,
2255 if (Status
!= STATUS_SUCCESS
) return(Status
);
2256 KeClearEvent(Event
);
2259 /* Check if this is a direct open or not */
2260 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2262 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2266 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2269 /* Check if we should use Sync IO or not */
2270 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2272 /* Use File Object event */
2273 KeClearEvent(&FileObject
->Event
);
2280 /* Allocate the IRP */
2281 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2283 ObDereferenceObject(FileObject
);
2284 return STATUS_INSUFFICIENT_RESOURCES
;
2287 /* Set up the IRP */
2288 Irp
->RequestorMode
= PreviousMode
;
2289 Irp
->UserIosb
= IoStatusBlock
;
2290 Irp
->UserEvent
= Event
;
2291 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2292 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2293 Irp
->UserBuffer
= FileInformation
;
2294 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2295 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2297 /* Set up Stack Data */
2298 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2299 StackPtr
->FileObject
= FileObject
;
2300 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2301 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2303 /* Set Parameters */
2304 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
= FileInformationClass
;
2305 StackPtr
->Parameters
.QueryDirectory
.FileName
= FileName
;
2306 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2307 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2308 StackPtr
->Flags
= 0;
2309 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2310 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2312 /* Call the Driver */
2313 Status
= IoCallDriver(DeviceObject
, Irp
);
2314 if (Status
== STATUS_PENDING
)
2318 KeWaitForSingleObject(&FileObject
->Event
,
2321 FileObject
->Flags
& FO_ALERTABLE_IO
,
2323 Status
= FileObject
->FinalStatus
;
2327 /* Return the Status */
2335 NtQueryEaFile(IN HANDLE FileHandle
,
2336 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2339 IN BOOLEAN ReturnSingleEntry
,
2340 IN PVOID EaList OPTIONAL
,
2341 IN ULONG EaListLength
,
2342 IN PULONG EaIndex OPTIONAL
,
2343 IN BOOLEAN RestartScan
)
2346 return STATUS_NOT_IMPLEMENTED
;
2351 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2352 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2354 IO_STATUS_BLOCK IoStatusBlock
;
2359 Status
= ZwOpenFile(&FileHandle
,
2360 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2363 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2364 FILE_SYNCHRONOUS_IO_NONALERT
);
2365 if (!NT_SUCCESS (Status
))
2367 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2371 /* Get file attributes */
2372 Status
= ZwQueryInformationFile(FileHandle
,
2375 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2376 FileNetworkOpenInformation
);
2377 if (!NT_SUCCESS (Status
))
2379 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2382 ZwClose (FileHandle
);
2390 NtQueryInformationFile(HANDLE FileHandle
,
2391 PIO_STATUS_BLOCK IoStatusBlock
,
2392 PVOID FileInformation
,
2394 FILE_INFORMATION_CLASS FileInformationClass
)
2396 OBJECT_HANDLE_INFORMATION HandleInformation
;
2397 PFILE_OBJECT FileObject
;
2400 PDEVICE_OBJECT DeviceObject
;
2401 PIO_STACK_LOCATION StackPtr
;
2402 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2404 BOOLEAN LocalEvent
= FALSE
;
2405 BOOLEAN Failed
= FALSE
;
2407 ASSERT(IoStatusBlock
!= NULL
);
2408 ASSERT(FileInformation
!= NULL
);
2410 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2411 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2412 Length
, FileInformationClass
);
2414 /* Reference the Handle */
2415 Status
= ObReferenceObjectByHandle(FileHandle
,
2419 (PVOID
*)&FileObject
,
2420 &HandleInformation
);
2421 if (!NT_SUCCESS(Status
)) return Status
;
2423 /* Check information class specific access rights */
2424 switch (FileInformationClass
)
2426 case FileBasicInformation
:
2427 if (!(HandleInformation
.GrantedAccess
& FILE_READ_ATTRIBUTES
))
2431 case FilePositionInformation
:
2432 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2433 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2437 case FileAlignmentInformation
:
2438 if (!(FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
))
2448 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2449 ObDereferenceObject(FileObject
);
2450 return STATUS_ACCESS_DENIED
;
2453 DPRINT("FileObject %x\n", FileObject
);
2455 /* Check if this is a direct open or not */
2456 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2458 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2462 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2465 /* Check if we should use Sync IO or not */
2466 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2468 /* Use File Object event */
2469 KeClearEvent(&FileObject
->Event
);
2473 /* Use local event */
2474 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2478 /* Allocate the IRP */
2479 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2481 ObDereferenceObject(FileObject
);
2482 return STATUS_INSUFFICIENT_RESOURCES
;
2485 /* Allocate the System Buffer */
2486 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2491 ObDereferenceObject(FileObject
);
2492 return STATUS_INSUFFICIENT_RESOURCES
;
2495 /* Set up the IRP */
2496 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2497 Irp
->RequestorMode
= PreviousMode
;
2498 Irp
->UserIosb
= IoStatusBlock
;
2499 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2500 Irp
->UserBuffer
= FileInformation
;
2501 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2502 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
2503 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2505 /* Set up Stack Data */
2506 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2507 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2508 StackPtr
->FileObject
= FileObject
;
2510 /* Set the Parameters */
2511 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2512 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2514 /* Call the Driver */
2515 Status
= IoCallDriver(DeviceObject
, Irp
);
2516 if (Status
== STATUS_PENDING
)
2520 KeWaitForSingleObject(&Event
,
2523 FileObject
->Flags
& FO_ALERTABLE_IO
,
2525 Status
= IoStatusBlock
->Status
;
2529 KeWaitForSingleObject(&FileObject
->Event
,
2532 FileObject
->Flags
& FO_ALERTABLE_IO
,
2534 Status
= FileObject
->FinalStatus
;
2538 /* Return the Status */
2547 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2548 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2551 IN BOOLEAN ReturnSingleEntry
,
2552 IN PVOID SidList OPTIONAL
,
2553 IN ULONG SidListLength
,
2554 IN PSID StartSid OPTIONAL
,
2555 IN BOOLEAN RestartScan
)
2558 return STATUS_NOT_IMPLEMENTED
;
2577 NtReadFile(IN HANDLE FileHandle
,
2578 IN HANDLE Event OPTIONAL
,
2579 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2580 IN PVOID ApcContext OPTIONAL
,
2581 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2584 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2585 IN PULONG Key OPTIONAL
)
2587 NTSTATUS Status
= STATUS_SUCCESS
;
2588 PFILE_OBJECT FileObject
;
2590 PDEVICE_OBJECT DeviceObject
;
2591 PIO_STACK_LOCATION StackPtr
;
2592 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2593 BOOLEAN LocalEvent
= FALSE
;
2594 PKEVENT EventObject
= NULL
;
2596 DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2597 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2601 /* Validate User-Mode Buffers */
2602 if(PreviousMode
!= KernelMode
)
2606 ProbeForWrite(IoStatusBlock
,
2607 sizeof(IO_STATUS_BLOCK
),
2610 ProbeForWrite(Buffer
,
2617 Status
= _SEH_GetExceptionCode();
2621 if(!NT_SUCCESS(Status
)) return Status
;
2624 /* Get File Object */
2625 Status
= ObReferenceObjectByHandle(FileHandle
,
2629 (PVOID
*)&FileObject
,
2631 if (!NT_SUCCESS(Status
)) return Status
;
2633 /* Check the Byte Offset */
2635 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
2636 ByteOffset
->u
.HighPart
== 0xffffffff))
2638 /* a valid ByteOffset is required if asynch. op. */
2639 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2641 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2642 ObDereferenceObject(FileObject
);
2643 return STATUS_INVALID_PARAMETER
;
2646 /* Use the Current Byte OFfset */
2647 ByteOffset
= &FileObject
->CurrentByteOffset
;
2650 /* Check for event */
2654 Status
= ObReferenceObjectByHandle(Event
,
2658 (PVOID
*)&EventObject
,
2660 if (!NT_SUCCESS(Status
))
2662 ObDereferenceObject(FileObject
);
2665 KeClearEvent(EventObject
);
2668 /* Check if this is a direct open or not */
2669 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2671 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2675 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2678 /* Check if we should use Sync IO or not */
2679 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2681 /* Use File Object event */
2682 KeClearEvent(&FileObject
->Event
);
2689 /* Create the IRP */
2692 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2701 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2706 Status
= _SEH_GetExceptionCode();
2710 /* Cleanup if IRP Allocation Failed */
2711 if (!NT_SUCCESS(Status
))
2713 if (Event
) ObDereferenceObject(EventObject
);
2714 ObDereferenceObject(FileObject
);
2718 /* Set up IRP Data */
2719 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2720 Irp
->RequestorMode
= PreviousMode
;
2721 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2722 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2723 Irp
->Flags
|= IRP_READ_OPERATION
;
2726 * Vfat doesn't handle non cached files correctly.
2728 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2731 /* Setup Stack Data */
2732 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2733 StackPtr
->FileObject
= FileObject
;
2734 StackPtr
->Parameters
.Read
.Key
= Key
? *Key
: 0;
2736 /* Call the Driver */
2737 Status
= IoCallDriver(DeviceObject
, Irp
);
2738 if (Status
== STATUS_PENDING
)
2742 KeWaitForSingleObject(&FileObject
->Event
,
2745 FileObject
->Flags
& FO_ALERTABLE_IO
,
2747 Status
= FileObject
->FinalStatus
;
2751 /* Return the Status */
2769 NtReadFileScatter(IN HANDLE FileHandle
,
2770 IN HANDLE Event OPTIONAL
,
2771 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2772 IN PVOID UserApcContext OPTIONAL
,
2773 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2774 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2775 IN ULONG BufferLength
,
2776 IN PLARGE_INTEGER ByteOffset
,
2777 IN PULONG Key OPTIONAL
)
2780 return(STATUS_NOT_IMPLEMENTED
);
2788 NtSetEaFile(IN HANDLE FileHandle
,
2789 IN PIO_STATUS_BLOCK IoStatusBlock
,
2791 IN ULONG EaBufferSize
)
2794 return STATUS_NOT_IMPLEMENTED
;
2801 NtSetInformationFile(HANDLE FileHandle
,
2802 PIO_STATUS_BLOCK IoStatusBlock
,
2803 PVOID FileInformation
,
2805 FILE_INFORMATION_CLASS FileInformationClass
)
2807 OBJECT_HANDLE_INFORMATION HandleInformation
;
2808 PIO_STACK_LOCATION StackPtr
;
2809 PFILE_OBJECT FileObject
;
2810 PDEVICE_OBJECT DeviceObject
;
2813 BOOLEAN LocalEvent
= FALSE
;
2814 NTSTATUS Status
= STATUS_SUCCESS
;
2815 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2816 BOOLEAN Failed
= FALSE
;
2818 ASSERT(IoStatusBlock
!= NULL
);
2819 ASSERT(FileInformation
!= NULL
);
2821 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2822 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2823 Length
, FileInformationClass
);
2825 /* Get the file object from the file handle */
2826 Status
= ObReferenceObjectByHandle(FileHandle
,
2830 (PVOID
*)&FileObject
,
2831 &HandleInformation
);
2832 if (!NT_SUCCESS(Status
)) return Status
;
2834 /* Check information class specific access rights */
2835 switch (FileInformationClass
)
2837 case FileBasicInformation
:
2838 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_ATTRIBUTES
))
2842 case FileDispositionInformation
:
2843 if (!(HandleInformation
.GrantedAccess
& DELETE
))
2847 case FilePositionInformation
:
2848 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2849 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2853 case FileEndOfFileInformation
:
2854 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
))
2864 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2865 ObDereferenceObject(FileObject
);
2866 return STATUS_ACCESS_DENIED
;
2869 DPRINT("FileObject %x\n", FileObject
);
2871 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2872 /* Handle IO Completion Port quickly */
2873 if (FileInformationClass
== FileCompletionInformation
)
2876 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2877 PIO_COMPLETION_CONTEXT Context
;
2879 if (Length
< sizeof(FILE_COMPLETION_INFORMATION
))
2881 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2885 /* Reference the Port */
2886 Status
= ObReferenceObjectByHandle(CompletionInfo
->IoCompletionHandle
,
2887 IO_COMPLETION_MODIFY_STATE
,
2892 if (NT_SUCCESS(Status
))
2894 /* Allocate the Context */
2895 Context
= ExAllocatePoolWithTag(PagedPool
,
2896 sizeof(IO_COMPLETION_CONTEXT
),
2897 TAG('I', 'o', 'C', 'p'));
2900 Context
->Key
= CompletionInfo
->CompletionKey
;
2901 Context
->Port
= Queue
;
2902 FileObject
->CompletionContext
= Context
;
2904 /* Dereference the Port now */
2905 ObDereferenceObject(Queue
);
2909 /* Complete the I/O */
2910 ObDereferenceObject(FileObject
);
2914 /* Check if this is a direct open or not */
2915 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2917 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2921 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2924 /* Check if we should use Sync IO or not */
2925 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2927 /* Use File Object event */
2928 KeClearEvent(&FileObject
->Event
);
2932 /* Use local event */
2933 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2937 /* Allocate the IRP */
2938 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2940 ObDereferenceObject(FileObject
);
2941 return STATUS_INSUFFICIENT_RESOURCES
;
2944 /* Allocate the System Buffer */
2945 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2950 ObDereferenceObject(FileObject
);
2951 return STATUS_INSUFFICIENT_RESOURCES
;
2954 /* Copy the data inside */
2955 MmSafeCopyFromUser(Irp
->AssociatedIrp
.SystemBuffer
, FileInformation
, Length
);
2957 /* Set up the IRP */
2958 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2959 Irp
->RequestorMode
= PreviousMode
;
2960 Irp
->UserIosb
= IoStatusBlock
;
2961 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2962 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2963 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
2964 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2966 /* Set up Stack Data */
2967 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2968 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2969 StackPtr
->FileObject
= FileObject
;
2971 /* Set the Parameters */
2972 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2973 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2975 /* Call the Driver */
2976 Status
= IoCallDriver(DeviceObject
, Irp
);
2977 if (Status
== STATUS_PENDING
)
2981 KeWaitForSingleObject(&Event
,
2984 FileObject
->Flags
& FO_ALERTABLE_IO
,
2986 Status
= IoStatusBlock
->Status
;
2990 KeWaitForSingleObject(&FileObject
->Event
,
2993 FileObject
->Flags
& FO_ALERTABLE_IO
,
2995 Status
= FileObject
->FinalStatus
;
2999 /* Return the Status */
3008 NtSetQuotaInformationFile(HANDLE FileHandle
,
3009 PIO_STATUS_BLOCK IoStatusBlock
,
3010 PFILE_USER_QUOTA_INFORMATION Buffer
,
3014 return STATUS_NOT_IMPLEMENTED
;
3022 NtUnlockFile(IN HANDLE FileHandle
,
3023 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3024 IN PLARGE_INTEGER ByteOffset
,
3025 IN PLARGE_INTEGER Length
,
3026 OUT PULONG Key OPTIONAL
)
3028 PFILE_OBJECT FileObject
= NULL
;
3029 PLARGE_INTEGER LocalLength
= NULL
;
3031 PIO_STACK_LOCATION StackPtr
;
3032 PDEVICE_OBJECT DeviceObject
;
3034 BOOLEAN LocalEvent
= FALSE
;
3035 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3036 NTSTATUS Status
= STATUS_SUCCESS
;
3037 OBJECT_HANDLE_INFORMATION HandleInformation
;
3039 /* FIXME: instead of this, use SEH */
3040 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
3042 /* Get File Object */
3043 Status
= ObReferenceObjectByHandle(FileHandle
,
3047 (PVOID
*)&FileObject
,
3048 &HandleInformation
);
3049 if (!NT_SUCCESS(Status
)) return Status
;
3051 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
3052 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3054 DPRINT1("Invalid access rights\n");
3055 ObDereferenceObject(FileObject
);
3056 return STATUS_ACCESS_DENIED
;
3059 /* Check if this is a direct open or not */
3060 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3062 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3066 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3069 /* Check if we should use Sync IO or not */
3070 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3072 /* Use File Object event */
3073 KeClearEvent(&FileObject
->Event
);
3077 /* Use local event */
3078 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3082 /* Allocate the IRP */
3083 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
3085 ObDereferenceObject(FileObject
);
3086 return STATUS_INSUFFICIENT_RESOURCES
;
3089 /* Allocate local buffer */
3090 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3091 sizeof(LARGE_INTEGER
),
3096 ObDereferenceObject(FileObject
);
3097 return STATUS_INSUFFICIENT_RESOURCES
;
3099 *LocalLength
= *Length
;
3101 /* Set up the IRP */
3102 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3103 Irp
->RequestorMode
= PreviousMode
;
3104 Irp
->UserIosb
= IoStatusBlock
;
3105 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
3106 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3107 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3109 /* Set up Stack Data */
3110 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3111 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3112 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3113 StackPtr
->FileObject
= FileObject
;
3115 /* Set Parameters */
3116 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3117 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
3118 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
3120 /* Call the Driver */
3121 Status
= IoCallDriver(DeviceObject
, Irp
);
3122 if (Status
== STATUS_PENDING
)
3126 KeWaitForSingleObject(&Event
,
3129 FileObject
->Flags
& FO_ALERTABLE_IO
,
3131 Status
= IoStatusBlock
->Status
;
3135 KeWaitForSingleObject(&FileObject
->Event
,
3138 FileObject
->Flags
& FO_ALERTABLE_IO
,
3140 Status
= FileObject
->FinalStatus
;
3144 /* Return the Status */
3164 NtWriteFile (IN HANDLE FileHandle
,
3165 IN HANDLE Event OPTIONAL
,
3166 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3167 IN PVOID ApcContext OPTIONAL
,
3168 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3171 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
3172 IN PULONG Key OPTIONAL
)
3174 OBJECT_HANDLE_INFORMATION HandleInformation
;
3175 NTSTATUS Status
= STATUS_SUCCESS
;
3176 PFILE_OBJECT FileObject
;
3178 PDEVICE_OBJECT DeviceObject
;
3179 PIO_STACK_LOCATION StackPtr
;
3180 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3181 BOOLEAN LocalEvent
= FALSE
;
3182 PKEVENT EventObject
= NULL
;
3184 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
3185 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
3188 /* Validate User-Mode Buffers */
3189 if(PreviousMode
!= KernelMode
)
3194 ProbeForWrite(IoStatusBlock
,
3195 sizeof(IO_STATUS_BLOCK
),
3198 ProbeForRead(Buffer
,
3205 Status
= _SEH_GetExceptionCode();
3209 if(!NT_SUCCESS(Status
)) return Status
;
3212 /* Get File Object */
3213 Status
= ObReferenceObjectByHandle(FileHandle
,
3217 (PVOID
*)&FileObject
,
3218 &HandleInformation
);
3219 if (!NT_SUCCESS(Status
)) return Status
;
3221 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3222 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)))
3224 DPRINT1("Invalid access rights\n");
3225 ObDereferenceObject(FileObject
);
3226 return STATUS_ACCESS_DENIED
;
3229 /* Check if we got write Access */
3230 if (HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
)
3232 /* Check the Byte Offset */
3234 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
3235 ByteOffset
->u
.HighPart
== 0xffffffff))
3237 /* a valid ByteOffset is required if asynch. op. */
3238 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3240 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3241 ObDereferenceObject(FileObject
);
3242 return STATUS_INVALID_PARAMETER
;
3245 /* Use the Current Byte OFfset */
3246 ByteOffset
= &FileObject
->CurrentByteOffset
;
3249 else if (HandleInformation
.GrantedAccess
& FILE_APPEND_DATA
)
3251 /* a valid ByteOffset is required if asynch. op. */
3252 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3254 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3255 ObDereferenceObject(FileObject
);
3256 return STATUS_INVALID_PARAMETER
;
3259 /* Give the drivers somethign to understand */
3260 ByteOffset
->u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3261 ByteOffset
->u
.HighPart
= 0xffffffff;
3264 /* Check if we got an event */
3268 Status
= ObReferenceObjectByHandle(Event
,
3272 (PVOID
*)&EventObject
,
3274 if (!NT_SUCCESS(Status
))
3276 ObDereferenceObject(FileObject
);
3279 KeClearEvent(EventObject
);
3282 /* Check if this is a direct open or not */
3283 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3285 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3289 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3292 /* Check if we should use Sync IO or not */
3293 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3295 /* Use File Object event */
3296 KeClearEvent(&FileObject
->Event
);
3306 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
3315 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3320 Status
= _SEH_GetExceptionCode();
3324 /* Cleanup on failure */
3325 if (!NT_SUCCESS(Status
))
3329 ObDereferenceObject(&EventObject
);
3331 ObDereferenceObject(FileObject
);
3335 /* Set up IRP Data */
3336 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3337 Irp
->RequestorMode
= PreviousMode
;
3338 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3339 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3340 Irp
->Flags
|= IRP_WRITE_OPERATION
;
3343 * Vfat doesn't handle non cached files correctly.
3345 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3348 /* Setup Stack Data */
3349 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3350 StackPtr
->FileObject
= FileObject
;
3351 StackPtr
->Parameters
.Write
.Key
= Key
? *Key
: 0;
3352 if (FileObject
->Flags
& FO_WRITE_THROUGH
) StackPtr
->Flags
= SL_WRITE_THROUGH
;
3354 /* Call the Driver */
3355 Status
= IoCallDriver(DeviceObject
, Irp
);
3356 if (Status
== STATUS_PENDING
)
3360 KeWaitForSingleObject(&FileObject
->Event
,
3363 FileObject
->Flags
& FO_ALERTABLE_IO
,
3365 Status
= FileObject
->FinalStatus
;
3369 /* Return the Status */
3387 NtWriteFileGather(IN HANDLE FileHandle
,
3388 IN HANDLE Event OPTIONAL
,
3389 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3390 IN PVOID UserApcContext OPTIONAL
,
3391 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3392 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3393 IN ULONG BufferLength
,
3394 IN PLARGE_INTEGER ByteOffset
,
3395 IN PULONG Key OPTIONAL
)
3398 return(STATUS_NOT_IMPLEMENTED
);