2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/file.c
5 * PURPOSE: I/O File Object & NT File Handle Access/Managment of Files.
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS *******************************************************************/
19 #define TAG_SYSB TAG('S', 'Y', 'S', 'B')
20 #define TAG_LOCK TAG('F','l','c','k')
21 #define TAG_FILE_NAME TAG('F', 'N', 'A', 'M')
23 extern GENERIC_MAPPING IopFileMapping
;
27 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation
,
28 PSECURITY_DESCRIPTOR SecurityDescriptor
,
31 /* INTERNAL FUNCTIONS ********************************************************/
47 IopCreateFile(PVOID ObjectBody
,
50 POBJECT_CREATE_INFORMATION ObjectCreateInfo
)
52 PDEVICE_OBJECT DeviceObject
;
53 PFILE_OBJECT FileObject
= (PFILE_OBJECT
) ObjectBody
;
54 POBJECT_TYPE ParentObjectType
;
57 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
64 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
65 for the cache manager, so return STATUS_SUCCESS */
66 DPRINT("Parent object was NULL\n");
67 return(STATUS_SUCCESS
);
70 ParentObjectType
= BODY_TO_HEADER(Parent
)->ObjectType
;
72 if (ParentObjectType
!= IoDeviceObjectType
&&
73 ParentObjectType
!= IoFileObjectType
)
75 DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n",
76 &BODY_TO_HEADER(Parent
)->NameInfo
->Name
,
77 BODY_TO_HEADER(Parent
)->ObjectType
->Name
.Buffer
,
79 return(STATUS_UNSUCCESSFUL
);
82 Status
= ObReferenceObjectByPointer(Parent
,
83 STANDARD_RIGHTS_REQUIRED
,
86 if (!NT_SUCCESS(Status
))
88 CPRINT("Failed to reference parent object %x\n", Parent
);
92 if (ParentObjectType
== IoDeviceObjectType
)
94 /* Parent is a devce object */
95 DeviceObject
= IoGetAttachedDevice((PDEVICE_OBJECT
)Parent
);
96 DPRINT("DeviceObject %x\n", DeviceObject
);
98 if (RemainingPath
== NULL
)
100 FileObject
->Flags
= FileObject
->Flags
| FO_DIRECT_DEVICE_OPEN
;
101 FileObject
->FileName
.Buffer
= 0;
102 FileObject
->FileName
.Length
= FileObject
->FileName
.MaximumLength
= 0;
106 if ((DeviceObject
->DeviceType
!= FILE_DEVICE_FILE_SYSTEM
)
107 && (DeviceObject
->DeviceType
!= FILE_DEVICE_DISK
)
108 && (DeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
)
109 && (DeviceObject
->DeviceType
!= FILE_DEVICE_TAPE
)
110 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
)
111 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
112 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
114 CPRINT("Device was wrong type\n");
115 return(STATUS_UNSUCCESSFUL
);
118 if (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
119 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
120 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
122 if (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
124 DPRINT("Mount the logical volume\n");
125 Status
= IoMountVolume(DeviceObject
, FALSE
);
126 DPRINT("Status %x\n", Status
);
127 if (!NT_SUCCESS(Status
))
129 CPRINT("Failed to mount logical volume (Status %x)\n",
134 DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
135 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
137 RtlpCreateUnicodeString(&(FileObject
->FileName
),
138 RemainingPath
, NonPagedPool
);
143 /* Parent is a file object */
144 if (RemainingPath
== NULL
)
146 CPRINT("Device is unnamed\n");
147 return STATUS_UNSUCCESSFUL
;
150 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
151 DPRINT("DeviceObject %x\n", DeviceObject
);
153 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
155 RtlpCreateUnicodeString(&(FileObject
->FileName
),
156 RemainingPath
, NonPagedPool
);
159 DPRINT("FileObject->FileName %wZ\n",
160 &FileObject
->FileName
);
161 FileObject
->DeviceObject
= DeviceObject
;
162 DPRINT("FileObject %x DeviceObject %x\n",
165 FileObject
->Vpb
= DeviceObject
->Vpb
;
166 FileObject
->Type
= IO_TYPE_FILE
;
168 return(STATUS_SUCCESS
);
173 IopDeleteFile(PVOID ObjectBody
)
175 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
177 PIO_STACK_LOCATION StackPtr
;
180 PDEVICE_OBJECT DeviceObject
;
182 DPRINT("IopDeleteFile()\n");
184 if (FileObject
->DeviceObject
)
186 /* Check if this is a direct open or not */
187 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
189 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
193 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
196 /* Clear and set up Events */
197 KeClearEvent(&FileObject
->Event
);
198 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
200 /* Allocate an IRP */
201 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
204 Irp
->UserEvent
= &Event
;
205 Irp
->UserIosb
= &Irp
->IoStatus
;
206 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
207 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
208 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
210 /* Set up Stack Pointer Data */
211 StackPtr
= IoGetNextIrpStackLocation(Irp
);
212 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
213 StackPtr
->DeviceObject
= DeviceObject
;
214 StackPtr
->FileObject
= FileObject
;
216 /* Call the FS Driver */
217 Status
= IoCallDriver(DeviceObject
, Irp
);
219 /* Wait for completion */
220 if (Status
== STATUS_PENDING
)
222 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
228 /* Clear the file name */
229 if (FileObject
->FileName
.Buffer
)
231 ExFreePool(FileObject
->FileName
.Buffer
);
232 FileObject
->FileName
.Buffer
= NULL
;
235 /* Free the completion context */
236 if (FileObject
->CompletionContext
)
238 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
239 ExFreePool(FileObject
->CompletionContext
);
245 IopSecurityFile(PVOID ObjectBody
,
246 SECURITY_OPERATION_CODE OperationCode
,
247 SECURITY_INFORMATION SecurityInformation
,
248 PSECURITY_DESCRIPTOR SecurityDescriptor
,
251 IO_STATUS_BLOCK IoStatusBlock
;
252 PIO_STACK_LOCATION StackPtr
;
253 PFILE_OBJECT FileObject
;
254 PDEVICE_OBJECT DeviceObject
;
257 BOOLEAN LocalEvent
= FALSE
;
259 NTSTATUS Status
= STATUS_SUCCESS
;
261 DPRINT("IopSecurityFile() called\n");
263 FileObject
= (PFILE_OBJECT
)ObjectBody
;
265 if (OperationCode
== QuerySecurityDescriptor
)
267 MajorFunction
= IRP_MJ_QUERY_SECURITY
;
268 DPRINT("Query security descriptor\n");
270 else if (OperationCode
== DeleteSecurityDescriptor
)
273 return STATUS_SUCCESS
;
275 else if (OperationCode
== AssignSecurityDescriptor
)
277 /* If this is a direct open, we can assign it */
278 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
280 /* Get the Device Object */
282 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
284 /* Assign the Security Descriptor */
285 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
287 return STATUS_SUCCESS
;
291 MajorFunction
= IRP_MJ_SET_SECURITY
;
292 DPRINT("Set security descriptor\n");
294 /* If this is a direct open, we can set it */
295 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
297 DPRINT1("Set SD unimplemented for Devices\n");
298 return STATUS_SUCCESS
;
302 /* Get the Device Object */
303 DPRINT1("FileObject: %p\n", FileObject
);
304 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
306 /* Check if we should use Sync IO or not */
307 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
309 /* Use File Object event */
310 KeClearEvent(&FileObject
->Event
);
314 /* Use local event */
315 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
319 /* Allocate the IRP */
320 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
323 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
324 Irp
->RequestorMode
= ExGetPreviousMode();
325 Irp
->UserIosb
= &IoStatusBlock
;
326 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
327 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
328 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
330 /* Set Stack Parameters */
331 StackPtr
= IoGetNextIrpStackLocation(Irp
);
332 StackPtr
->FileObject
= FileObject
;
335 if (OperationCode
== QuerySecurityDescriptor
)
337 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
= SecurityInformation
;
338 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
339 Irp
->UserBuffer
= SecurityDescriptor
;
343 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
= SecurityInformation
;
344 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
= SecurityDescriptor
;
347 ObReferenceObject(FileObject
);
349 /* Call the Driver */
350 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
352 if (Status
== STATUS_PENDING
)
356 KeWaitForSingleObject(&Event
,
359 FileObject
->Flags
& FO_ALERTABLE_IO
,
361 Status
= IoStatusBlock
.Status
;
365 KeWaitForSingleObject(&FileObject
->Event
,
368 FileObject
->Flags
& FO_ALERTABLE_IO
,
370 Status
= FileObject
->FinalStatus
;
374 /* This Driver doesn't implement Security, so try to give it a default */
375 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
377 if (OperationCode
== QuerySecurityDescriptor
)
379 /* Set a World Security Descriptor */
380 Status
= SeSetWorldSecurityDescriptor(SecurityInformation
,
386 /* It wasn't a query, so just fake success */
387 Status
= STATUS_SUCCESS
;
390 else if (OperationCode
== QuerySecurityDescriptor
)
393 *BufferLength
= IoStatusBlock
.Information
;
402 IopQueryNameFile(PVOID ObjectBody
,
403 POBJECT_NAME_INFORMATION ObjectNameInfo
,
408 PFILE_OBJECT FileObject
;
409 ULONG LocalReturnLength
;
412 DPRINT1("IopQueryNameFile() called\n");
414 FileObject
= (PFILE_OBJECT
)ObjectBody
;
416 /* Allocate Buffer */
417 LocalInfo
= ExAllocatePool(PagedPool
,
418 sizeof(OBJECT_NAME_INFORMATION
) +
419 MAX_PATH
* sizeof(WCHAR
));
420 if (LocalInfo
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
423 Status
= ObQueryNameString(FileObject
->DeviceObject
,
425 MAX_PATH
* sizeof(WCHAR
),
427 if (!NT_SUCCESS (Status
))
429 ExFreePool (LocalInfo
);
432 DPRINT ("Device path: %wZ\n", &LocalInfo
->Name
);
434 /* Write Device Path */
435 Status
= RtlAppendUnicodeStringToString(&ObjectNameInfo
->Name
,
436 &((POBJECT_NAME_INFORMATION
)LocalInfo
)->Name
);
438 /* Query the File name */
439 Status
= IoQueryFileInformation(FileObject
,
444 if (Status
!= STATUS_SUCCESS
)
446 ExFreePool(LocalInfo
);
451 Status
= RtlAppendUnicodeToString(&ObjectNameInfo
->Name
,
452 ((PFILE_NAME_INFORMATION
)LocalInfo
)->FileName
);
453 DPRINT ("Total path: %wZ\n", &ObjectNameInfo
->Name
);
455 /* Free buffer and return */
456 ExFreePool(LocalInfo
);
462 IopCloseFile(PVOID ObjectBody
,
465 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
468 PIO_STACK_LOCATION StackPtr
;
470 PDEVICE_OBJECT DeviceObject
;
472 DPRINT("IopCloseFile()\n");
474 if (HandleCount
> 1 || FileObject
->DeviceObject
== NULL
) return;
476 /* Check if this is a direct open or not */
477 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
479 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
483 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
486 /* Clear and set up Events */
487 KeClearEvent(&FileObject
->Event
);
488 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
490 /* Allocate an IRP */
491 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
494 Irp
->UserEvent
= &Event
;
495 Irp
->UserIosb
= &Irp
->IoStatus
;
496 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
497 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
498 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
500 /* Set up Stack Pointer Data */
501 StackPtr
= IoGetNextIrpStackLocation(Irp
);
502 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
503 StackPtr
->FileObject
= FileObject
;
505 /* Call the FS Driver */
506 Status
= IoCallDriver(DeviceObject
, Irp
);
508 /* Wait for completion */
509 if (Status
== STATUS_PENDING
)
511 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
518 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
519 IN HANDLE Event OPTIONAL
,
520 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
521 IN PVOID UserApcContext OPTIONAL
,
522 OUT PIO_STATUS_BLOCK IoStatusBlock
,
523 IN ULONG IoControlCode
,
524 IN PVOID InputBuffer
,
525 IN ULONG InputBufferLength OPTIONAL
,
526 OUT PVOID OutputBuffer
,
527 IN ULONG OutputBufferLength OPTIONAL
,
530 NTSTATUS Status
= STATUS_SUCCESS
;
531 PFILE_OBJECT FileObject
;
532 PDEVICE_OBJECT DeviceObject
;
534 PIO_STACK_LOCATION StackPtr
;
535 PKEVENT EventObject
= NULL
;
536 BOOLEAN LocalEvent
= FALSE
;
537 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
539 DPRINT("IopDeviceFsIoControl(DeviceHandle %x Event %x UserApcRoutine %x "
540 "UserApcContext %x IoStatusBlock %x IoControlCode %x "
541 "InputBuffer %x InputBufferLength %x OutputBuffer %x "
542 "OutputBufferLength %x)\n",
543 DeviceHandle
,Event
,UserApcRoutine
,UserApcContext
,IoStatusBlock
,
544 IoControlCode
,InputBuffer
,InputBufferLength
,OutputBuffer
,
547 if (IoStatusBlock
== NULL
) return STATUS_ACCESS_VIOLATION
;
549 /* Check granted access against the access rights from IoContolCode */
550 Status
= ObReferenceObjectByHandle(DeviceHandle
,
551 (IoControlCode
>> 14) & 0x3,
554 (PVOID
*) &FileObject
,
556 if (!NT_SUCCESS(Status
)) return Status
;
558 /* Check for an event */
562 Status
= ObReferenceObjectByHandle(Event
,
566 (PVOID
*)&EventObject
,
568 if (!NT_SUCCESS(Status
))
570 ObDereferenceObject (FileObject
);
575 KeClearEvent(EventObject
);
578 /* Check if this is a direct open or not */
579 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
581 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
585 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
588 /* Check if we should use Sync IO or not */
589 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
591 /* Use File Object event */
592 KeClearEvent(&FileObject
->Event
);
596 /* Use local event */
601 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
611 /* Set some extra settings */
612 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
613 Irp
->RequestorMode
= PreviousMode
;
614 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
615 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
616 StackPtr
= IoGetNextIrpStackLocation(Irp
);
617 StackPtr
->FileObject
= FileObject
;
618 StackPtr
->MajorFunction
= IsDevIoCtl
?
619 IRP_MJ_DEVICE_CONTROL
: IRP_MJ_FILE_SYSTEM_CONTROL
;
621 /* Call the Driver */
622 Status
= IoCallDriver(DeviceObject
, Irp
);
623 if (Status
== STATUS_PENDING
)
627 KeWaitForSingleObject(&FileObject
->Event
,
630 FileObject
->Flags
& FO_ALERTABLE_IO
,
632 Status
= FileObject
->FinalStatus
;
636 /* Return the Status */
640 /* FUNCTIONS *****************************************************************/
647 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
649 IN BOOLEAN SetOperation
)
652 return STATUS_NOT_IMPLEMENTED
;
660 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
661 IN ULONG QuotaLength
,
662 OUT PULONG ErrorOffset
)
665 return STATUS_NOT_IMPLEMENTED
;
673 * Either causes a new file or directory to be created, or it
674 * opens an existing file, device, directory or volume, giving
675 * the caller a handle for the file object. This handle can be
676 * used by subsequent calls to manipulate data within the file
677 * or the file object's state of attributes.
681 * Points to a variable which receives the file handle
685 * Desired access to the file;
688 * Structure describing the file;
690 * IoStatusBlock (OUT)
691 * Receives information about the operation on return;
693 * AllocationSize [OPTIONAL]
694 * Initial size of the file in bytes;
697 * Attributes to create the file with;
700 * Type of shared access the caller would like to the
704 * Specifies what to do, depending on whether the
705 * file already exists;
708 * Options for creating a new file;
710 * EaBuffer [OPTIONAL]
717 * Type of file (normal, named pipe, mailslot) to create;
719 * ExtraCreateParameters [OPTIONAL]
720 * Additional creation data for named pipe and mailsots;
729 * Prototype taken from Bo Branten's ntifs.h v15.
730 * Description taken from old NtCreateFile's which is
731 * now a wrapper of this call.
739 IoCreateFile(OUT PHANDLE FileHandle
,
740 IN ACCESS_MASK DesiredAccess
,
741 IN POBJECT_ATTRIBUTES ObjectAttributes
,
742 OUT PIO_STATUS_BLOCK IoStatusBlock
,
743 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
744 IN ULONG FileAttributes
,
745 IN ULONG ShareAccess
,
746 IN ULONG CreateDisposition
,
747 IN ULONG CreateOptions
,
748 IN PVOID EaBuffer OPTIONAL
,
750 IN CREATE_FILE_TYPE CreateFileType
,
751 IN PVOID ExtraCreateParameters OPTIONAL
,
754 PFILE_OBJECT FileObject
= NULL
;
755 PDEVICE_OBJECT DeviceObject
;
757 PIO_STACK_LOCATION StackLoc
;
758 IO_SECURITY_CONTEXT SecurityContext
;
759 KPROCESSOR_MODE AccessMode
;
761 IO_STATUS_BLOCK LocalIoStatusBlock
;
762 LARGE_INTEGER SafeAllocationSize
;
763 PVOID SystemEaBuffer
= NULL
;
764 NTSTATUS Status
= STATUS_SUCCESS
;
766 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
767 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
768 FileHandle
,DesiredAccess
,ObjectAttributes
,
769 ObjectAttributes
->ObjectName
->Buffer
);
771 ASSERT_IRQL(PASSIVE_LEVEL
);
773 if (IoStatusBlock
== NULL
|| FileHandle
== NULL
)
774 return STATUS_ACCESS_VIOLATION
;
778 if(Options
& IO_NO_PARAMETER_CHECKING
)
779 AccessMode
= KernelMode
;
781 AccessMode
= ExGetPreviousMode();
783 if(AccessMode
!= KernelMode
)
787 ProbeForWrite(FileHandle
,
790 ProbeForWrite(IoStatusBlock
,
791 sizeof(IO_STATUS_BLOCK
),
793 if(AllocationSize
!= NULL
)
795 ProbeForRead(AllocationSize
,
796 sizeof(LARGE_INTEGER
),
798 SafeAllocationSize
= *AllocationSize
;
801 SafeAllocationSize
.QuadPart
= 0;
803 if(EaBuffer
!= NULL
&& EaLength
> 0)
805 ProbeForRead(EaBuffer
,
809 /* marshal EaBuffer */
810 SystemEaBuffer
= ExAllocatePool(NonPagedPool
,
812 if(SystemEaBuffer
== NULL
)
814 Status
= STATUS_INSUFFICIENT_RESOURCES
;
818 RtlCopyMemory(SystemEaBuffer
,
825 Status
= _SEH_GetExceptionCode();
829 if(!NT_SUCCESS(Status
))
836 if(AllocationSize
!= NULL
)
837 SafeAllocationSize
= *AllocationSize
;
839 SafeAllocationSize
.QuadPart
= 0;
841 if(EaBuffer
!= NULL
&& EaLength
> 0)
843 SystemEaBuffer
= EaBuffer
;
847 if(Options
& IO_CHECK_CREATE_PARAMETERS
)
849 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
852 if (CreateDisposition
== FILE_OPEN
||
853 CreateDisposition
== FILE_OPEN_IF
)
856 Status
= ObOpenObjectByName(ObjectAttributes
,
864 if (NT_SUCCESS(Status
))
866 Status
= ObReferenceObjectByHandle(LocalHandle
,
870 (PVOID
*)&DeviceObject
,
872 ZwClose(LocalHandle
);
873 if (!NT_SUCCESS(Status
))
877 if (BODY_TO_HEADER(DeviceObject
)->ObjectType
!= IoDeviceObjectType
)
879 ObDereferenceObject (DeviceObject
);
880 return STATUS_OBJECT_NAME_COLLISION
;
883 FileObject
= IoCreateStreamFileObject(NULL
, DeviceObject
);
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
;
1153 CreatedFileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
1154 CreatedFileObject
->Flags
|= FO_STREAM_FILE
;
1156 /* Initialize Lock and Event */
1157 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
1158 KeInitializeEvent(&CreatedFileObject
->Lock
, SynchronizationEvent
, TRUE
);
1161 return CreatedFileObject
;
1169 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1170 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1171 OUT PHANDLE FileObjectHandle OPTIONAL
)
1182 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1183 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1194 IoGetFileObjectGenericMapping(VOID
)
1196 return &IopFileMapping
;
1204 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
1206 /* Return the flag status */
1207 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
1215 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
1216 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
1219 return STATUS_NOT_IMPLEMENTED
;
1227 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1228 IN FILE_INFORMATION_CLASS FileInformationClass
,
1230 OUT PVOID FileInformation
,
1231 OUT PULONG ReturnedLength
)
1233 IO_STATUS_BLOCK IoStatusBlock
;
1235 PDEVICE_OBJECT DeviceObject
;
1236 PIO_STACK_LOCATION StackPtr
;
1237 BOOLEAN LocalEvent
= FALSE
;
1241 ASSERT(FileInformation
!= NULL
);
1243 Status
= ObReferenceObjectByPointer(FileObject
,
1244 FILE_READ_ATTRIBUTES
,
1247 if (!NT_SUCCESS(Status
)) return(Status
);
1249 DPRINT("FileObject %x\n", FileObject
);
1251 /* Get the Device Object */
1252 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1254 /* Check if we should use Sync IO or not */
1255 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1257 /* Use File Object event */
1258 KeClearEvent(&FileObject
->Event
);
1262 /* Use local event */
1263 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1267 /* Allocate the IRP */
1268 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1271 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1272 Irp
->RequestorMode
= KernelMode
;
1273 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1274 Irp
->UserIosb
= &IoStatusBlock
;
1275 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1276 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1277 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1279 /* Set the Stack Data */
1280 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1281 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1282 StackPtr
->FileObject
= FileObject
;
1284 /* Set Parameters */
1285 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1286 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1288 /* Call the Driver */
1289 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
1291 if (Status
== STATUS_PENDING
)
1295 KeWaitForSingleObject(&Event
,
1298 FileObject
->Flags
& FO_ALERTABLE_IO
,
1300 Status
= IoStatusBlock
.Status
;
1304 KeWaitForSingleObject(&FileObject
->Event
,
1307 FileObject
->Flags
& FO_ALERTABLE_IO
,
1309 Status
= FileObject
->FinalStatus
;
1314 /* Return the Length and Status. ReturnedLength is NOT optional */
1315 *ReturnedLength
= IoStatusBlock
.Information
;
1324 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
1328 return STATUS_NOT_IMPLEMENTED
;
1332 * @name NtCancelIoFile
1334 * Cancel all pending I/O operations in the current thread for specified
1338 * Handle to file object to cancel requests for. No specific
1339 * access rights are needed.
1340 * @param IoStatusBlock
1341 * Pointer to status block which is filled with final completition
1342 * status on successful return.
1350 NtCancelIoFile(IN HANDLE FileHandle
,
1351 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1354 PFILE_OBJECT FileObject
;
1356 PLIST_ENTRY IrpEntry
;
1359 BOOLEAN OurIrpsInList
= FALSE
;
1360 LARGE_INTEGER Interval
;
1362 if ((ULONG_PTR
)IoStatusBlock
>= MmUserProbeAddress
&&
1363 KeGetPreviousMode() == UserMode
)
1364 return STATUS_ACCESS_VIOLATION
;
1366 Status
= ObReferenceObjectByHandle(FileHandle
, 0, IoFileObjectType
,
1367 KeGetPreviousMode(), (PVOID
*)&FileObject
,
1369 if (!NT_SUCCESS(Status
))
1372 /* IRP cancellations are synchronized at APC_LEVEL. */
1373 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1376 * Walk the list of active IRPs and cancel the ones that belong to
1380 Thread
= PsGetCurrentThread();
1381 for (IrpEntry
= Thread
->IrpList
.Flink
;
1382 IrpEntry
!= &Thread
->IrpList
;
1383 IrpEntry
= IrpEntry
->Flink
)
1385 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1386 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1389 /* Don't break here, we want to cancel all IRPs for the file object. */
1390 OurIrpsInList
= TRUE
;
1394 KfLowerIrql(OldIrql
);
1396 while (OurIrpsInList
)
1398 OurIrpsInList
= FALSE
;
1400 /* Wait a short while and then look if all our IRPs were completed. */
1401 Interval
.QuadPart
= -1000000; /* 100 milliseconds */
1402 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1404 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1407 * Look in the list if all IRPs for the specified file object
1408 * are completed (or cancelled). If someone sends a new IRP
1409 * for our file object while we're here we can happily loop
1413 for (IrpEntry
= Thread
->IrpList
.Flink
;
1414 IrpEntry
!= &Thread
->IrpList
;
1415 IrpEntry
= IrpEntry
->Flink
)
1417 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1418 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1420 OurIrpsInList
= TRUE
;
1425 KfLowerIrql(OldIrql
);
1430 IoStatusBlock
->Status
= STATUS_SUCCESS
;
1431 IoStatusBlock
->Information
= 0;
1432 Status
= STATUS_SUCCESS
;
1436 Status
= STATUS_UNSUCCESSFUL
;
1440 ObDereferenceObject(FileObject
);
1450 * Entry point to call IoCreateFile with
1451 * default parameters.
1461 * Code originally in NtCreateFile moved in IoCreateFile.
1467 NtCreateFile(PHANDLE FileHandle
,
1468 ACCESS_MASK DesiredAccess
,
1469 POBJECT_ATTRIBUTES ObjectAttributes
,
1470 PIO_STATUS_BLOCK IoStatusBlock
,
1471 PLARGE_INTEGER AllocateSize
,
1472 ULONG FileAttributes
,
1474 ULONG CreateDisposition
,
1475 ULONG CreateOptions
,
1479 /* Call the I/O Function */
1480 return IoCreateFile(FileHandle
,
1498 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
1499 IN ACCESS_MASK DesiredAccess
,
1500 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1501 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1502 IN ULONG CreateOptions
,
1503 IN ULONG MailslotQuota
,
1504 IN ULONG MaxMessageSize
,
1505 IN PLARGE_INTEGER TimeOut
)
1507 MAILSLOT_CREATE_PARAMETERS Buffer
;
1509 DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
1510 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1511 FileHandle
,DesiredAccess
,ObjectAttributes
,
1512 ObjectAttributes
->ObjectName
->Buffer
);
1515 /* Check for Timeout */
1519 Buffer
.TimeoutSpecified
= TRUE
;
1521 /* FIXME: Add SEH */
1522 Buffer
.ReadTimeout
= *TimeOut
;
1527 Buffer
.TimeoutSpecified
= FALSE
;
1531 Buffer
.MailslotQuota
= MailslotQuota
;
1532 Buffer
.MaximumMessageSize
= MaxMessageSize
;
1535 return IoCreateFile(FileHandle
,
1540 FILE_ATTRIBUTE_NORMAL
,
1541 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1546 CreateFileTypeMailslot
,
1553 NtCreateNamedPipeFile(PHANDLE FileHandle
,
1554 ACCESS_MASK DesiredAccess
,
1555 POBJECT_ATTRIBUTES ObjectAttributes
,
1556 PIO_STATUS_BLOCK IoStatusBlock
,
1558 ULONG CreateDisposition
,
1559 ULONG CreateOptions
,
1560 ULONG NamedPipeType
,
1562 ULONG CompletionMode
,
1563 ULONG MaximumInstances
,
1565 ULONG OutboundQuota
,
1566 PLARGE_INTEGER DefaultTimeout
)
1568 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
1570 DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
1571 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1572 FileHandle
,DesiredAccess
,ObjectAttributes
,
1573 ObjectAttributes
->ObjectName
->Buffer
);
1576 /* Check for Timeout */
1580 Buffer
.TimeoutSpecified
= TRUE
;
1582 /* FIXME: Add SEH */
1583 Buffer
.DefaultTimeout
= *DefaultTimeout
;
1588 Buffer
.TimeoutSpecified
= FALSE
;
1592 Buffer
.NamedPipeType
= NamedPipeType
;
1593 Buffer
.ReadMode
= ReadMode
;
1594 Buffer
.CompletionMode
= CompletionMode
;
1595 Buffer
.MaximumInstances
= MaximumInstances
;
1596 Buffer
.InboundQuota
= InboundQuota
;
1597 Buffer
.OutboundQuota
= OutboundQuota
;
1600 return IoCreateFile(FileHandle
,
1605 FILE_ATTRIBUTE_NORMAL
,
1611 CreateFileTypeNamedPipe
,
1634 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
1637 return(STATUS_NOT_IMPLEMENTED
);
1645 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1646 IN HANDLE Event OPTIONAL
,
1647 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1648 IN PVOID UserApcContext OPTIONAL
,
1649 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1650 IN ULONG IoControlCode
,
1651 IN PVOID InputBuffer
,
1652 IN ULONG InputBufferLength OPTIONAL
,
1653 OUT PVOID OutputBuffer
,
1654 IN ULONG OutputBufferLength OPTIONAL
)
1656 /* Call the Generic Function */
1657 return IopDeviceFsIoControl(DeviceHandle
,
1675 NtFsControlFile(IN HANDLE DeviceHandle
,
1676 IN HANDLE Event OPTIONAL
,
1677 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1678 IN PVOID UserApcContext OPTIONAL
,
1679 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1680 IN ULONG IoControlCode
,
1681 IN PVOID InputBuffer
,
1682 IN ULONG InputBufferLength OPTIONAL
,
1683 OUT PVOID OutputBuffer
,
1684 IN ULONG OutputBufferLength OPTIONAL
)
1686 return IopDeviceFsIoControl(DeviceHandle
,
1701 NtFlushWriteBuffer(VOID
)
1703 KeFlushWriteBuffer();
1704 return STATUS_SUCCESS
;
1708 * FUNCTION: Flushes cached file data to disk
1710 * FileHandle = Points to the file
1711 * IoStatusBlock = Caller must supply storage to receive the result of
1712 * the flush buffers operation. The information field is
1713 * set to number of bytes flushed to disk.
1715 * REMARKS: This function maps to the win32 FlushFileBuffers
1719 NtFlushBuffersFile(IN HANDLE FileHandle
,
1720 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1722 PFILE_OBJECT FileObject
= NULL
;
1724 PIO_STACK_LOCATION StackPtr
;
1726 PDEVICE_OBJECT DeviceObject
;
1728 BOOLEAN LocalEvent
= FALSE
;
1729 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1731 /* Get the File Object */
1732 Status
= ObReferenceObjectByHandle(FileHandle
,
1736 (PVOID
*)&FileObject
,
1738 if (Status
!= STATUS_SUCCESS
) return(Status
);
1740 /* Check if this is a direct open or not */
1741 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1743 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1747 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1750 /* Check if we should use Sync IO or not */
1751 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1753 /* Use File Object event */
1754 KeClearEvent(&FileObject
->Event
);
1758 /* Use local event */
1759 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1763 /* Allocate the IRP */
1764 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
1766 ObDereferenceObject(FileObject
);
1767 return STATUS_INSUFFICIENT_RESOURCES
;
1770 /* Set up the IRP */
1771 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1772 Irp
->RequestorMode
= PreviousMode
;
1773 Irp
->UserIosb
= IoStatusBlock
;
1774 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1775 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1776 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1778 /* Set up Stack Data */
1779 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1780 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1781 StackPtr
->FileObject
= FileObject
;
1783 /* Call the Driver */
1784 Status
= IoCallDriver(DeviceObject
, Irp
);
1785 if (Status
== STATUS_PENDING
)
1789 KeWaitForSingleObject(&Event
,
1792 FileObject
->Flags
& FO_ALERTABLE_IO
,
1794 Status
= IoStatusBlock
->Status
;
1798 KeWaitForSingleObject(&FileObject
->Event
,
1801 FileObject
->Flags
& FO_ALERTABLE_IO
,
1803 Status
= FileObject
->FinalStatus
;
1807 /* Return the Status */
1816 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1817 IN HANDLE Event OPTIONAL
,
1818 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1819 IN PVOID ApcContext OPTIONAL
,
1820 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1822 IN ULONG BufferSize
,
1823 IN ULONG CompletionFilter
,
1824 IN BOOLEAN WatchTree
)
1827 PDEVICE_OBJECT DeviceObject
;
1828 PFILE_OBJECT FileObject
;
1829 PIO_STACK_LOCATION IoStack
;
1830 KPROCESSOR_MODE PreviousMode
;
1831 NTSTATUS Status
= STATUS_SUCCESS
;
1833 DPRINT("NtNotifyChangeDirectoryFile()\n");
1837 PreviousMode
= ExGetPreviousMode();
1839 if(PreviousMode
!= KernelMode
)
1843 ProbeForWrite(IoStatusBlock
,
1844 sizeof(IO_STATUS_BLOCK
),
1848 ProbeForWrite(Buffer
,
1855 Status
= _SEH_GetExceptionCode();
1859 if(!NT_SUCCESS(Status
))
1865 Status
= ObReferenceObjectByHandle(FileHandle
,
1866 FILE_LIST_DIRECTORY
,
1869 (PVOID
*)&FileObject
,
1871 if (Status
!= STATUS_SUCCESS
) return(Status
);
1874 DeviceObject
= FileObject
->DeviceObject
;
1877 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1880 ObDereferenceObject(FileObject
);
1881 return STATUS_UNSUCCESSFUL
;
1886 Event
= &FileObject
->Event
;
1889 /* Trigger FileObject/Event dereferencing */
1890 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1891 Irp
->RequestorMode
= PreviousMode
;
1892 Irp
->UserIosb
= IoStatusBlock
;
1893 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1894 Irp
->UserEvent
= Event
;
1895 KeResetEvent( Event
);
1896 Irp
->UserBuffer
= Buffer
;
1897 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1898 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1900 IoStack
= IoGetNextIrpStackLocation(Irp
);
1902 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1903 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1905 IoStack
->Control
= 0;
1906 IoStack
->DeviceObject
= DeviceObject
;
1907 IoStack
->FileObject
= FileObject
;
1911 IoStack
->Flags
= SL_WATCH_TREE
;
1914 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1915 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1917 Status
= IoCallDriver(FileObject
->DeviceObject
,Irp
);
1919 /* FIXME: Should we wait here or not for synchronously opened files? */
1929 NtLockFile(IN HANDLE FileHandle
,
1930 IN HANDLE EventHandle OPTIONAL
,
1931 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1932 IN PVOID ApcContext OPTIONAL
,
1933 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1934 IN PLARGE_INTEGER ByteOffset
,
1935 IN PLARGE_INTEGER Length
,
1937 IN BOOLEAN FailImmediately
,
1938 IN BOOLEAN ExclusiveLock
)
1940 PFILE_OBJECT FileObject
= NULL
;
1941 PLARGE_INTEGER LocalLength
= NULL
;
1943 PIO_STACK_LOCATION StackPtr
;
1944 PDEVICE_OBJECT DeviceObject
;
1945 PKEVENT Event
= NULL
;
1946 BOOLEAN LocalEvent
= FALSE
;
1947 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1948 NTSTATUS Status
= STATUS_SUCCESS
;
1949 OBJECT_HANDLE_INFORMATION HandleInformation
;
1951 /* FIXME: instead of this, use SEH */
1952 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
1954 /* Get File Object */
1955 Status
= ObReferenceObjectByHandle(FileHandle
,
1959 (PVOID
*)&FileObject
,
1960 &HandleInformation
);
1961 if (!NT_SUCCESS(Status
)) return Status
;
1963 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
1964 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1966 DPRINT1("Invalid access rights\n");
1967 ObDereferenceObject(FileObject
);
1968 return STATUS_ACCESS_DENIED
;
1971 /* Get Event Object */
1974 Status
= ObReferenceObjectByHandle(EventHandle
,
1980 if (Status
!= STATUS_SUCCESS
) return(Status
);
1981 KeClearEvent(Event
);
1984 /* Check if this is a direct open or not */
1985 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1987 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1991 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1994 /* Check if we should use Sync IO or not */
1995 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1997 /* Use File Object event */
1998 KeClearEvent(&FileObject
->Event
);
2005 /* Allocate the IRP */
2006 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2008 ObDereferenceObject(FileObject
);
2009 return STATUS_INSUFFICIENT_RESOURCES
;
2012 /* Allocate local buffer */
2013 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2014 sizeof(LARGE_INTEGER
),
2019 ObDereferenceObject(FileObject
);
2020 return STATUS_INSUFFICIENT_RESOURCES
;
2022 *LocalLength
= *Length
;
2024 /* Set up the IRP */
2025 Irp
->RequestorMode
= PreviousMode
;
2026 Irp
->UserIosb
= IoStatusBlock
;
2027 Irp
->UserEvent
= Event
;
2028 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2029 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2031 /* Set up Stack Data */
2032 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2033 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2034 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
2035 StackPtr
->FileObject
= FileObject
;
2037 /* Set Parameters */
2038 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2039 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
2040 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
2043 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
2044 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
2046 /* Call the Driver */
2047 FileObject
->LockOperation
= TRUE
;
2048 Status
= IoCallDriver(DeviceObject
, Irp
);
2049 if (Status
== STATUS_PENDING
)
2053 KeWaitForSingleObject(&FileObject
->Event
,
2056 FileObject
->Flags
& FO_ALERTABLE_IO
,
2058 Status
= FileObject
->FinalStatus
;
2062 /* Return the Status */
2071 * Opens an existing file (simpler than NtCreateFile).
2075 * Variable that receives the file handle on return;
2078 * Access desired by the caller to the file;
2081 * Structue describing the file to be opened;
2083 * IoStatusBlock (OUT)
2084 * Receives details about the result of the
2088 * Type of shared access the caller requires;
2091 * Options for the file open.
2103 NtOpenFile(PHANDLE FileHandle
,
2104 ACCESS_MASK DesiredAccess
,
2105 POBJECT_ATTRIBUTES ObjectAttributes
,
2106 PIO_STATUS_BLOCK IoStatusBlock
,
2110 /* Call the I/O Function */
2111 return IoCreateFile(FileHandle
,
2129 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2130 OUT PFILE_BASIC_INFORMATION FileInformation
)
2132 IO_STATUS_BLOCK IoStatusBlock
;
2137 Status
= ZwOpenFile(&FileHandle
,
2138 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2141 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2142 FILE_SYNCHRONOUS_IO_NONALERT
);
2143 if (!NT_SUCCESS (Status
))
2145 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2149 /* Get file attributes */
2150 Status
= ZwQueryInformationFile(FileHandle
,
2153 sizeof(FILE_BASIC_INFORMATION
),
2154 FileBasicInformation
);
2155 if (!NT_SUCCESS (Status
))
2157 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2160 ZwClose(FileHandle
);
2167 * FUNCTION: Queries a directory file.
2169 * FileHandle = Handle to a directory file
2170 * EventHandle = Handle to the event signaled on completion
2171 * ApcRoutine = Asynchroneous procedure callback, called on completion
2172 * ApcContext = Argument to the apc.
2173 * IoStatusBlock = Caller supplies storage for extended status information.
2174 * FileInformation = Caller supplies storage for the resulting information.
2176 * FileNameInformation FILE_NAMES_INFORMATION
2177 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2178 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2179 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2181 * Length = Size of the storage supplied
2182 * FileInformationClass = Indicates the type of information requested.
2183 * ReturnSingleEntry = Specify true if caller only requests the first
2185 * FileName = Initial directory name to query, that may contain wild
2187 * RestartScan = Number of times the action should be repeated
2188 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2189 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2190 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2194 NtQueryDirectoryFile(IN HANDLE FileHandle
,
2195 IN HANDLE PEvent OPTIONAL
,
2196 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2197 IN PVOID ApcContext OPTIONAL
,
2198 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2199 OUT PVOID FileInformation
,
2201 IN FILE_INFORMATION_CLASS FileInformationClass
,
2202 IN BOOLEAN ReturnSingleEntry
,
2203 IN PUNICODE_STRING FileName OPTIONAL
,
2204 IN BOOLEAN RestartScan
)
2207 PDEVICE_OBJECT DeviceObject
;
2208 PFILE_OBJECT FileObject
;
2209 PIO_STACK_LOCATION StackPtr
;
2210 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2211 NTSTATUS Status
= STATUS_SUCCESS
;
2212 BOOLEAN LocalEvent
= FALSE
;
2213 PKEVENT Event
= NULL
;
2215 DPRINT("NtQueryDirectoryFile()\n");
2218 /* Validate User-Mode Buffers */
2219 if(PreviousMode
!= KernelMode
)
2223 ProbeForWrite(IoStatusBlock
,
2224 sizeof(IO_STATUS_BLOCK
),
2226 ProbeForWrite(FileInformation
,
2232 Status
= _SEH_GetExceptionCode();
2236 if(!NT_SUCCESS(Status
)) return Status
;
2239 /* Get File Object */
2240 Status
= ObReferenceObjectByHandle(FileHandle
,
2241 FILE_LIST_DIRECTORY
,
2244 (PVOID
*)&FileObject
,
2246 if (Status
!= STATUS_SUCCESS
) return(Status
);
2248 /* Get Event Object */
2251 Status
= ObReferenceObjectByHandle(PEvent
,
2257 if (Status
!= STATUS_SUCCESS
) return(Status
);
2258 KeClearEvent(Event
);
2261 /* Check if this is a direct open or not */
2262 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2264 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2268 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2271 /* Check if we should use Sync IO or not */
2272 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2274 /* Use File Object event */
2275 KeClearEvent(&FileObject
->Event
);
2282 /* Allocate the IRP */
2283 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2285 ObDereferenceObject(FileObject
);
2286 return STATUS_INSUFFICIENT_RESOURCES
;
2289 /* Set up the IRP */
2290 Irp
->RequestorMode
= PreviousMode
;
2291 Irp
->UserIosb
= IoStatusBlock
;
2292 Irp
->UserEvent
= Event
;
2293 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2294 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2295 Irp
->UserBuffer
= FileInformation
;
2296 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2297 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2299 /* Set up Stack Data */
2300 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2301 StackPtr
->FileObject
= FileObject
;
2302 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2303 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2305 /* Set Parameters */
2306 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
= FileInformationClass
;
2307 StackPtr
->Parameters
.QueryDirectory
.FileName
= FileName
;
2308 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2309 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2310 StackPtr
->Flags
= 0;
2311 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2312 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2314 /* Call the Driver */
2315 Status
= IoCallDriver(DeviceObject
, Irp
);
2316 if (Status
== STATUS_PENDING
)
2320 KeWaitForSingleObject(&FileObject
->Event
,
2323 FileObject
->Flags
& FO_ALERTABLE_IO
,
2325 Status
= FileObject
->FinalStatus
;
2329 /* Return the Status */
2337 NtQueryEaFile(IN HANDLE FileHandle
,
2338 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2341 IN BOOLEAN ReturnSingleEntry
,
2342 IN PVOID EaList OPTIONAL
,
2343 IN ULONG EaListLength
,
2344 IN PULONG EaIndex OPTIONAL
,
2345 IN BOOLEAN RestartScan
)
2348 return STATUS_NOT_IMPLEMENTED
;
2353 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2354 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2356 IO_STATUS_BLOCK IoStatusBlock
;
2361 Status
= ZwOpenFile(&FileHandle
,
2362 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2365 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2366 FILE_SYNCHRONOUS_IO_NONALERT
);
2367 if (!NT_SUCCESS (Status
))
2369 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2373 /* Get file attributes */
2374 Status
= ZwQueryInformationFile(FileHandle
,
2377 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2378 FileNetworkOpenInformation
);
2379 if (!NT_SUCCESS (Status
))
2381 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2384 ZwClose (FileHandle
);
2392 NtQueryInformationFile(HANDLE FileHandle
,
2393 PIO_STATUS_BLOCK IoStatusBlock
,
2394 PVOID FileInformation
,
2396 FILE_INFORMATION_CLASS FileInformationClass
)
2398 OBJECT_HANDLE_INFORMATION HandleInformation
;
2399 PFILE_OBJECT FileObject
;
2402 PDEVICE_OBJECT DeviceObject
;
2403 PIO_STACK_LOCATION StackPtr
;
2404 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2406 BOOLEAN LocalEvent
= FALSE
;
2407 BOOLEAN Failed
= FALSE
;
2409 ASSERT(IoStatusBlock
!= NULL
);
2410 ASSERT(FileInformation
!= NULL
);
2412 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2413 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2414 Length
, FileInformationClass
);
2416 /* Reference the Handle */
2417 Status
= ObReferenceObjectByHandle(FileHandle
,
2421 (PVOID
*)&FileObject
,
2422 &HandleInformation
);
2423 if (!NT_SUCCESS(Status
)) return Status
;
2425 /* Check information class specific access rights */
2426 switch (FileInformationClass
)
2428 case FileBasicInformation
:
2429 if (!(HandleInformation
.GrantedAccess
& FILE_READ_ATTRIBUTES
))
2433 case FilePositionInformation
:
2434 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2435 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2439 case FileAlignmentInformation
:
2440 if (!(FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
))
2450 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2451 ObDereferenceObject(FileObject
);
2452 return STATUS_ACCESS_DENIED
;
2455 DPRINT("FileObject %x\n", FileObject
);
2457 /* Check if this is a direct open or not */
2458 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2460 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2464 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2467 /* Check if we should use Sync IO or not */
2468 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2470 /* Use File Object event */
2471 KeClearEvent(&FileObject
->Event
);
2475 /* Use local event */
2476 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2480 /* Allocate the IRP */
2481 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2483 ObDereferenceObject(FileObject
);
2484 return STATUS_INSUFFICIENT_RESOURCES
;
2487 /* Allocate the System Buffer */
2488 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2493 ObDereferenceObject(FileObject
);
2494 return STATUS_INSUFFICIENT_RESOURCES
;
2497 /* Set up the IRP */
2498 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2499 Irp
->RequestorMode
= PreviousMode
;
2500 Irp
->UserIosb
= IoStatusBlock
;
2501 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2502 Irp
->UserBuffer
= FileInformation
;
2503 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2504 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
2505 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2507 /* Set up Stack Data */
2508 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2509 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2510 StackPtr
->FileObject
= FileObject
;
2512 /* Set the Parameters */
2513 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2514 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2516 /* Call the Driver */
2517 Status
= IoCallDriver(DeviceObject
, Irp
);
2518 if (Status
== STATUS_PENDING
)
2522 KeWaitForSingleObject(&Event
,
2525 FileObject
->Flags
& FO_ALERTABLE_IO
,
2527 Status
= IoStatusBlock
->Status
;
2531 KeWaitForSingleObject(&FileObject
->Event
,
2534 FileObject
->Flags
& FO_ALERTABLE_IO
,
2536 Status
= FileObject
->FinalStatus
;
2540 /* Return the Status */
2549 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2550 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2553 IN BOOLEAN ReturnSingleEntry
,
2554 IN PVOID SidList OPTIONAL
,
2555 IN ULONG SidListLength
,
2556 IN PSID StartSid OPTIONAL
,
2557 IN BOOLEAN RestartScan
)
2560 return STATUS_NOT_IMPLEMENTED
;
2579 NtReadFile(IN HANDLE FileHandle
,
2580 IN HANDLE Event OPTIONAL
,
2581 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2582 IN PVOID ApcContext OPTIONAL
,
2583 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2586 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2587 IN PULONG Key OPTIONAL
)
2589 NTSTATUS Status
= STATUS_SUCCESS
;
2590 PFILE_OBJECT FileObject
;
2592 PDEVICE_OBJECT DeviceObject
;
2593 PIO_STACK_LOCATION StackPtr
;
2594 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2595 BOOLEAN LocalEvent
= FALSE
;
2596 PKEVENT EventObject
= NULL
;
2598 DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2599 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2603 /* Validate User-Mode Buffers */
2604 if(PreviousMode
!= KernelMode
)
2608 ProbeForWrite(IoStatusBlock
,
2609 sizeof(IO_STATUS_BLOCK
),
2612 ProbeForWrite(Buffer
,
2619 Status
= _SEH_GetExceptionCode();
2623 if(!NT_SUCCESS(Status
)) return Status
;
2626 /* Get File Object */
2627 Status
= ObReferenceObjectByHandle(FileHandle
,
2631 (PVOID
*)&FileObject
,
2633 if (!NT_SUCCESS(Status
)) return Status
;
2635 /* Check the Byte Offset */
2637 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
2638 ByteOffset
->u
.HighPart
== 0xffffffff))
2640 /* a valid ByteOffset is required if asynch. op. */
2641 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2643 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2644 ObDereferenceObject(FileObject
);
2645 return STATUS_INVALID_PARAMETER
;
2648 /* Use the Current Byte OFfset */
2649 ByteOffset
= &FileObject
->CurrentByteOffset
;
2652 /* Check for event */
2656 Status
= ObReferenceObjectByHandle(Event
,
2660 (PVOID
*)&EventObject
,
2662 if (!NT_SUCCESS(Status
))
2664 ObDereferenceObject(FileObject
);
2667 KeClearEvent(EventObject
);
2670 /* Check if this is a direct open or not */
2671 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2673 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2677 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2680 /* Check if we should use Sync IO or not */
2681 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2683 /* Use File Object event */
2684 KeClearEvent(&FileObject
->Event
);
2691 /* Create the IRP */
2694 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2703 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2708 Status
= _SEH_GetExceptionCode();
2712 /* Cleanup if IRP Allocation Failed */
2713 if (!NT_SUCCESS(Status
))
2715 if (Event
) ObDereferenceObject(EventObject
);
2716 ObDereferenceObject(FileObject
);
2720 /* Set up IRP Data */
2721 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2722 Irp
->RequestorMode
= PreviousMode
;
2723 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2724 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2725 Irp
->Flags
|= IRP_READ_OPERATION
;
2728 * Vfat doesn't handle non cached files correctly.
2730 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2733 /* Setup Stack Data */
2734 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2735 StackPtr
->FileObject
= FileObject
;
2736 StackPtr
->Parameters
.Read
.Key
= Key
? *Key
: 0;
2738 /* Call the Driver */
2739 Status
= IoCallDriver(DeviceObject
, Irp
);
2740 if (Status
== STATUS_PENDING
)
2744 KeWaitForSingleObject(&FileObject
->Event
,
2747 FileObject
->Flags
& FO_ALERTABLE_IO
,
2749 Status
= FileObject
->FinalStatus
;
2753 /* Return the Status */
2771 NtReadFileScatter(IN HANDLE FileHandle
,
2772 IN HANDLE Event OPTIONAL
,
2773 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2774 IN PVOID UserApcContext OPTIONAL
,
2775 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2776 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2777 IN ULONG BufferLength
,
2778 IN PLARGE_INTEGER ByteOffset
,
2779 IN PULONG Key OPTIONAL
)
2782 return(STATUS_NOT_IMPLEMENTED
);
2790 NtSetEaFile(IN HANDLE FileHandle
,
2791 IN PIO_STATUS_BLOCK IoStatusBlock
,
2793 IN ULONG EaBufferSize
)
2796 return STATUS_NOT_IMPLEMENTED
;
2803 NtSetInformationFile(HANDLE FileHandle
,
2804 PIO_STATUS_BLOCK IoStatusBlock
,
2805 PVOID FileInformation
,
2807 FILE_INFORMATION_CLASS FileInformationClass
)
2809 OBJECT_HANDLE_INFORMATION HandleInformation
;
2810 PIO_STACK_LOCATION StackPtr
;
2811 PFILE_OBJECT FileObject
;
2812 PDEVICE_OBJECT DeviceObject
;
2815 BOOLEAN LocalEvent
= FALSE
;
2816 NTSTATUS Status
= STATUS_SUCCESS
;
2817 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2818 BOOLEAN Failed
= FALSE
;
2820 ASSERT(IoStatusBlock
!= NULL
);
2821 ASSERT(FileInformation
!= NULL
);
2823 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2824 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2825 Length
, FileInformationClass
);
2827 /* Get the file object from the file handle */
2828 Status
= ObReferenceObjectByHandle(FileHandle
,
2832 (PVOID
*)&FileObject
,
2833 &HandleInformation
);
2834 if (!NT_SUCCESS(Status
)) return Status
;
2836 /* Check information class specific access rights */
2837 switch (FileInformationClass
)
2839 case FileBasicInformation
:
2840 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_ATTRIBUTES
))
2844 case FileDispositionInformation
:
2845 if (!(HandleInformation
.GrantedAccess
& DELETE
))
2849 case FilePositionInformation
:
2850 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2851 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2855 case FileEndOfFileInformation
:
2856 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
))
2866 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2867 ObDereferenceObject(FileObject
);
2868 return STATUS_ACCESS_DENIED
;
2871 DPRINT("FileObject %x\n", FileObject
);
2873 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2874 /* Handle IO Completion Port quickly */
2875 if (FileInformationClass
== FileCompletionInformation
)
2878 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2879 PIO_COMPLETION_CONTEXT Context
;
2881 if (Length
< sizeof(FILE_COMPLETION_INFORMATION
))
2883 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2887 /* Reference the Port */
2888 Status
= ObReferenceObjectByHandle(CompletionInfo
->IoCompletionHandle
,
2889 IO_COMPLETION_MODIFY_STATE
,
2894 if (NT_SUCCESS(Status
))
2896 /* Allocate the Context */
2897 Context
= ExAllocatePoolWithTag(PagedPool
,
2898 sizeof(IO_COMPLETION_CONTEXT
),
2899 TAG('I', 'o', 'C', 'p'));
2902 Context
->Key
= CompletionInfo
->CompletionKey
;
2903 Context
->Port
= Queue
;
2904 FileObject
->CompletionContext
= Context
;
2906 /* Dereference the Port now */
2907 ObDereferenceObject(Queue
);
2911 /* Complete the I/O */
2912 ObDereferenceObject(FileObject
);
2916 /* Check if this is a direct open or not */
2917 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2919 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2923 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2926 /* Check if we should use Sync IO or not */
2927 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2929 /* Use File Object event */
2930 KeClearEvent(&FileObject
->Event
);
2934 /* Use local event */
2935 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2939 /* Allocate the IRP */
2940 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2942 ObDereferenceObject(FileObject
);
2943 return STATUS_INSUFFICIENT_RESOURCES
;
2946 /* Allocate the System Buffer */
2947 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2952 ObDereferenceObject(FileObject
);
2953 return STATUS_INSUFFICIENT_RESOURCES
;
2956 /* Copy the data inside */
2957 MmSafeCopyFromUser(Irp
->AssociatedIrp
.SystemBuffer
, FileInformation
, Length
);
2959 /* Set up the IRP */
2960 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2961 Irp
->RequestorMode
= PreviousMode
;
2962 Irp
->UserIosb
= IoStatusBlock
;
2963 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2964 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2965 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
2966 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2968 /* Set up Stack Data */
2969 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2970 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2971 StackPtr
->FileObject
= FileObject
;
2973 /* Set the Parameters */
2974 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2975 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2977 /* Call the Driver */
2978 Status
= IoCallDriver(DeviceObject
, Irp
);
2979 if (Status
== STATUS_PENDING
)
2983 KeWaitForSingleObject(&Event
,
2986 FileObject
->Flags
& FO_ALERTABLE_IO
,
2988 Status
= IoStatusBlock
->Status
;
2992 KeWaitForSingleObject(&FileObject
->Event
,
2995 FileObject
->Flags
& FO_ALERTABLE_IO
,
2997 Status
= FileObject
->FinalStatus
;
3001 /* Return the Status */
3010 NtSetQuotaInformationFile(HANDLE FileHandle
,
3011 PIO_STATUS_BLOCK IoStatusBlock
,
3012 PFILE_USER_QUOTA_INFORMATION Buffer
,
3016 return STATUS_NOT_IMPLEMENTED
;
3024 NtUnlockFile(IN HANDLE FileHandle
,
3025 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3026 IN PLARGE_INTEGER ByteOffset
,
3027 IN PLARGE_INTEGER Length
,
3028 OUT PULONG Key OPTIONAL
)
3030 PFILE_OBJECT FileObject
= NULL
;
3031 PLARGE_INTEGER LocalLength
= NULL
;
3033 PIO_STACK_LOCATION StackPtr
;
3034 PDEVICE_OBJECT DeviceObject
;
3036 BOOLEAN LocalEvent
= FALSE
;
3037 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3038 NTSTATUS Status
= STATUS_SUCCESS
;
3039 OBJECT_HANDLE_INFORMATION HandleInformation
;
3041 /* FIXME: instead of this, use SEH */
3042 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
3044 /* Get File Object */
3045 Status
= ObReferenceObjectByHandle(FileHandle
,
3049 (PVOID
*)&FileObject
,
3050 &HandleInformation
);
3051 if (!NT_SUCCESS(Status
)) return Status
;
3053 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
3054 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3056 DPRINT1("Invalid access rights\n");
3057 ObDereferenceObject(FileObject
);
3058 return STATUS_ACCESS_DENIED
;
3061 /* Check if this is a direct open or not */
3062 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3064 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3068 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3071 /* Check if we should use Sync IO or not */
3072 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3074 /* Use File Object event */
3075 KeClearEvent(&FileObject
->Event
);
3079 /* Use local event */
3080 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3084 /* Allocate the IRP */
3085 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
3087 ObDereferenceObject(FileObject
);
3088 return STATUS_INSUFFICIENT_RESOURCES
;
3091 /* Allocate local buffer */
3092 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3093 sizeof(LARGE_INTEGER
),
3098 ObDereferenceObject(FileObject
);
3099 return STATUS_INSUFFICIENT_RESOURCES
;
3101 *LocalLength
= *Length
;
3103 /* Set up the IRP */
3104 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3105 Irp
->RequestorMode
= PreviousMode
;
3106 Irp
->UserIosb
= IoStatusBlock
;
3107 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
3108 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3109 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3111 /* Set up Stack Data */
3112 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3113 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3114 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3115 StackPtr
->FileObject
= FileObject
;
3117 /* Set Parameters */
3118 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3119 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
3120 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
3122 /* Call the Driver */
3123 Status
= IoCallDriver(DeviceObject
, Irp
);
3124 if (Status
== STATUS_PENDING
)
3128 KeWaitForSingleObject(&Event
,
3131 FileObject
->Flags
& FO_ALERTABLE_IO
,
3133 Status
= IoStatusBlock
->Status
;
3137 KeWaitForSingleObject(&FileObject
->Event
,
3140 FileObject
->Flags
& FO_ALERTABLE_IO
,
3142 Status
= FileObject
->FinalStatus
;
3146 /* Return the Status */
3166 NtWriteFile (IN HANDLE FileHandle
,
3167 IN HANDLE Event OPTIONAL
,
3168 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3169 IN PVOID ApcContext OPTIONAL
,
3170 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3173 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
3174 IN PULONG Key OPTIONAL
)
3176 OBJECT_HANDLE_INFORMATION HandleInformation
;
3177 NTSTATUS Status
= STATUS_SUCCESS
;
3178 PFILE_OBJECT FileObject
;
3180 PDEVICE_OBJECT DeviceObject
;
3181 PIO_STACK_LOCATION StackPtr
;
3182 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3183 BOOLEAN LocalEvent
= FALSE
;
3184 PKEVENT EventObject
= NULL
;
3186 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
3187 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
3190 /* Validate User-Mode Buffers */
3191 if(PreviousMode
!= KernelMode
)
3196 ProbeForWrite(IoStatusBlock
,
3197 sizeof(IO_STATUS_BLOCK
),
3200 ProbeForRead(Buffer
,
3207 Status
= _SEH_GetExceptionCode();
3211 if(!NT_SUCCESS(Status
)) return Status
;
3214 /* Get File Object */
3215 Status
= ObReferenceObjectByHandle(FileHandle
,
3219 (PVOID
*)&FileObject
,
3220 &HandleInformation
);
3221 if (!NT_SUCCESS(Status
)) return Status
;
3223 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3224 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)))
3226 DPRINT1("Invalid access rights\n");
3227 ObDereferenceObject(FileObject
);
3228 return STATUS_ACCESS_DENIED
;
3231 /* Check if we got write Access */
3232 if (HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
)
3234 /* Check the Byte Offset */
3236 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
3237 ByteOffset
->u
.HighPart
== 0xffffffff))
3239 /* a valid ByteOffset is required if asynch. op. */
3240 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3242 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3243 ObDereferenceObject(FileObject
);
3244 return STATUS_INVALID_PARAMETER
;
3247 /* Use the Current Byte OFfset */
3248 ByteOffset
= &FileObject
->CurrentByteOffset
;
3251 else if (HandleInformation
.GrantedAccess
& FILE_APPEND_DATA
)
3253 /* a valid ByteOffset is required if asynch. op. */
3254 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3256 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3257 ObDereferenceObject(FileObject
);
3258 return STATUS_INVALID_PARAMETER
;
3261 /* Give the drivers somethign to understand */
3262 ByteOffset
->u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3263 ByteOffset
->u
.HighPart
= 0xffffffff;
3266 /* Check if we got an event */
3270 Status
= ObReferenceObjectByHandle(Event
,
3274 (PVOID
*)&EventObject
,
3276 if (!NT_SUCCESS(Status
))
3278 ObDereferenceObject(FileObject
);
3281 KeClearEvent(EventObject
);
3284 /* Check if this is a direct open or not */
3285 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3287 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3291 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3294 /* Check if we should use Sync IO or not */
3295 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3297 /* Use File Object event */
3298 KeClearEvent(&FileObject
->Event
);
3308 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
3317 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3322 Status
= _SEH_GetExceptionCode();
3326 /* Cleanup on failure */
3327 if (!NT_SUCCESS(Status
))
3331 ObDereferenceObject(&EventObject
);
3333 ObDereferenceObject(FileObject
);
3337 /* Set up IRP Data */
3338 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3339 Irp
->RequestorMode
= PreviousMode
;
3340 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3341 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3342 Irp
->Flags
|= IRP_WRITE_OPERATION
;
3345 * Vfat doesn't handle non cached files correctly.
3347 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3350 /* Setup Stack Data */
3351 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3352 StackPtr
->FileObject
= FileObject
;
3353 StackPtr
->Parameters
.Write
.Key
= Key
? *Key
: 0;
3354 if (FileObject
->Flags
& FO_WRITE_THROUGH
) StackPtr
->Flags
= SL_WRITE_THROUGH
;
3356 /* Call the Driver */
3357 Status
= IoCallDriver(DeviceObject
, Irp
);
3358 if (Status
== STATUS_PENDING
)
3362 KeWaitForSingleObject(&FileObject
->Event
,
3365 FileObject
->Flags
& FO_ALERTABLE_IO
,
3367 Status
= FileObject
->FinalStatus
;
3371 /* Return the Status */
3389 NtWriteFileGather(IN HANDLE FileHandle
,
3390 IN HANDLE Event OPTIONAL
,
3391 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3392 IN PVOID UserApcContext OPTIONAL
,
3393 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3394 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3395 IN ULONG BufferLength
,
3396 IN PLARGE_INTEGER ByteOffset
,
3397 IN PULONG Key OPTIONAL
)
3400 return(STATUS_NOT_IMPLEMENTED
);