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 0x%p, Parent 0x%p, 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
)->Type
;
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 &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent
))->Name
,
73 BODY_TO_HEADER(Parent
)->Type
->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 0x%p\n", Parent
);
88 if (ParentObjectType
== IoDeviceObjectType
)
90 /* Parent is a devce object */
91 DeviceObject
= IoGetAttachedDevice((PDEVICE_OBJECT
)Parent
);
92 DPRINT("DeviceObject 0x%p\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", Status
);
129 DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
130 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
132 RtlpCreateUnicodeString(&(FileObject
->FileName
),
133 RemainingPath
, NonPagedPool
);
138 /* Parent is a file object */
139 if (RemainingPath
== NULL
)
141 CPRINT("Device is unnamed\n");
142 return STATUS_UNSUCCESSFUL
;
145 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
146 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
148 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
150 RtlpCreateUnicodeString(&(FileObject
->FileName
),
151 RemainingPath
, NonPagedPool
);
154 DPRINT("FileObject->FileName %wZ\n",
155 &FileObject
->FileName
);
156 FileObject
->DeviceObject
= DeviceObject
;
157 DPRINT("FileObject 0x%p DeviceObject 0x%p\n",
160 FileObject
->Vpb
= DeviceObject
->Vpb
;
161 FileObject
->Type
= IO_TYPE_FILE
;
163 return(STATUS_SUCCESS
);
168 IopDeleteFile(PVOID ObjectBody
)
170 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
172 PIO_STACK_LOCATION StackPtr
;
175 PDEVICE_OBJECT DeviceObject
;
177 DPRINT("IopDeleteFile()\n");
179 if (FileObject
->DeviceObject
)
181 /* Check if this is a direct open or not */
182 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
184 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
188 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
191 /* Clear and set up Events */
192 KeClearEvent(&FileObject
->Event
);
193 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
195 /* Allocate an IRP */
196 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
199 Irp
->UserEvent
= &Event
;
200 Irp
->UserIosb
= &Irp
->IoStatus
;
201 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
202 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
203 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
205 /* Set up Stack Pointer Data */
206 StackPtr
= IoGetNextIrpStackLocation(Irp
);
207 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
208 StackPtr
->DeviceObject
= DeviceObject
;
209 StackPtr
->FileObject
= FileObject
;
211 /* Call the FS Driver */
212 Status
= IoCallDriver(DeviceObject
, Irp
);
214 /* Wait for completion */
215 if (Status
== STATUS_PENDING
)
217 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
223 /* Clear the file name */
224 if (FileObject
->FileName
.Buffer
)
226 ExFreePool(FileObject
->FileName
.Buffer
);
227 FileObject
->FileName
.Buffer
= NULL
;
230 /* Free the completion context */
231 if (FileObject
->CompletionContext
)
233 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
234 ExFreePool(FileObject
->CompletionContext
);
240 IopSecurityFile(PVOID ObjectBody
,
241 SECURITY_OPERATION_CODE OperationCode
,
242 SECURITY_INFORMATION SecurityInformation
,
243 PSECURITY_DESCRIPTOR SecurityDescriptor
,
246 IO_STATUS_BLOCK IoStatusBlock
;
247 PIO_STACK_LOCATION StackPtr
;
248 PFILE_OBJECT FileObject
;
249 PDEVICE_OBJECT DeviceObject
;
252 BOOLEAN LocalEvent
= FALSE
;
254 NTSTATUS Status
= STATUS_SUCCESS
;
256 DPRINT("IopSecurityFile() called\n");
258 FileObject
= (PFILE_OBJECT
)ObjectBody
;
260 if (OperationCode
== QuerySecurityDescriptor
)
262 MajorFunction
= IRP_MJ_QUERY_SECURITY
;
263 DPRINT("Query security descriptor\n");
265 else if (OperationCode
== DeleteSecurityDescriptor
)
268 return STATUS_SUCCESS
;
270 else if (OperationCode
== AssignSecurityDescriptor
)
272 /* If this is a direct open, we can assign it */
273 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
275 /* Get the Device Object */
277 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
279 /* Assign the Security Descriptor */
280 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
282 return STATUS_SUCCESS
;
286 MajorFunction
= IRP_MJ_SET_SECURITY
;
287 DPRINT("Set security descriptor\n");
289 /* If this is a direct open, we can set it */
290 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
292 DPRINT1("Set SD unimplemented for Devices\n");
293 return STATUS_SUCCESS
;
297 /* Get the Device Object */
298 DPRINT1("FileObject: %p\n", FileObject
);
299 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
301 /* Check if we should use Sync IO or not */
302 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
304 /* Use File Object event */
305 KeClearEvent(&FileObject
->Event
);
309 /* Use local event */
310 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
314 /* Allocate the IRP */
315 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
318 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
319 Irp
->RequestorMode
= ExGetPreviousMode();
320 Irp
->UserIosb
= &IoStatusBlock
;
321 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
322 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
323 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
325 /* Set Stack Parameters */
326 StackPtr
= IoGetNextIrpStackLocation(Irp
);
327 StackPtr
->FileObject
= FileObject
;
330 if (OperationCode
== QuerySecurityDescriptor
)
332 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
= SecurityInformation
;
333 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
334 Irp
->UserBuffer
= SecurityDescriptor
;
338 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
= SecurityInformation
;
339 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
= SecurityDescriptor
;
342 ObReferenceObject(FileObject
);
344 /* Call the Driver */
345 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
347 if (Status
== STATUS_PENDING
)
351 KeWaitForSingleObject(&Event
,
354 FileObject
->Flags
& FO_ALERTABLE_IO
,
356 Status
= IoStatusBlock
.Status
;
360 KeWaitForSingleObject(&FileObject
->Event
,
363 FileObject
->Flags
& FO_ALERTABLE_IO
,
365 Status
= FileObject
->FinalStatus
;
369 /* This Driver doesn't implement Security, so try to give it a default */
370 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
372 if (OperationCode
== QuerySecurityDescriptor
)
374 /* Set a World Security Descriptor */
375 Status
= SeSetWorldSecurityDescriptor(SecurityInformation
,
381 /* It wasn't a query, so just fake success */
382 Status
= STATUS_SUCCESS
;
385 else if (OperationCode
== QuerySecurityDescriptor
)
388 *BufferLength
= IoStatusBlock
.Information
;
397 IopQueryNameFile(PVOID ObjectBody
,
398 POBJECT_NAME_INFORMATION ObjectNameInfo
,
402 POBJECT_NAME_INFORMATION LocalInfo
;
403 PFILE_OBJECT FileObject
;
404 ULONG LocalReturnLength
;
407 DPRINT1("IopQueryNameFile() called\n");
409 FileObject
= (PFILE_OBJECT
)ObjectBody
;
411 /* Allocate Buffer */
412 LocalInfo
= ExAllocatePool(PagedPool
,
413 sizeof(OBJECT_NAME_INFORMATION
) +
414 MAX_PATH
* sizeof(WCHAR
));
415 if (LocalInfo
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
418 Status
= ObQueryNameString(FileObject
->DeviceObject
,
420 MAX_PATH
* sizeof(WCHAR
),
422 if (!NT_SUCCESS (Status
))
424 ExFreePool (LocalInfo
);
427 DPRINT ("Device path: %wZ\n", &LocalInfo
->Name
);
429 /* Write Device Path */
430 Status
= RtlAppendUnicodeStringToString(&ObjectNameInfo
->Name
,
433 /* Query the File name */
434 Status
= IoQueryFileInformation(FileObject
,
439 if (Status
!= STATUS_SUCCESS
)
441 ExFreePool(LocalInfo
);
446 Status
= RtlAppendUnicodeToString(&ObjectNameInfo
->Name
,
447 ((PFILE_NAME_INFORMATION
)LocalInfo
)->FileName
);
448 DPRINT ("Total path: %wZ\n", &ObjectNameInfo
->Name
);
450 /* Free buffer and return */
451 ExFreePool(LocalInfo
);
457 IopCloseFile(PVOID ObjectBody
,
460 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
463 PIO_STACK_LOCATION StackPtr
;
465 PDEVICE_OBJECT DeviceObject
;
467 DPRINT("IopCloseFile()\n");
469 if (HandleCount
> 1 || FileObject
->DeviceObject
== NULL
) return;
471 /* Check if this is a direct open or not */
472 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
474 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
478 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
481 /* Clear and set up Events */
482 KeClearEvent(&FileObject
->Event
);
483 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
485 /* Allocate an IRP */
486 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
489 Irp
->UserEvent
= &Event
;
490 Irp
->UserIosb
= &Irp
->IoStatus
;
491 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
492 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
493 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
495 /* Set up Stack Pointer Data */
496 StackPtr
= IoGetNextIrpStackLocation(Irp
);
497 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
498 StackPtr
->FileObject
= FileObject
;
500 /* Call the FS Driver */
501 Status
= IoCallDriver(DeviceObject
, Irp
);
503 /* Wait for completion */
504 if (Status
== STATUS_PENDING
)
506 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
513 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
514 IN HANDLE Event OPTIONAL
,
515 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
516 IN PVOID UserApcContext OPTIONAL
,
517 OUT PIO_STATUS_BLOCK IoStatusBlock
,
518 IN ULONG IoControlCode
,
519 IN PVOID InputBuffer
,
520 IN ULONG InputBufferLength OPTIONAL
,
521 OUT PVOID OutputBuffer
,
522 IN ULONG OutputBufferLength OPTIONAL
,
525 NTSTATUS Status
= STATUS_SUCCESS
;
526 PFILE_OBJECT FileObject
;
527 PDEVICE_OBJECT DeviceObject
;
529 PIO_STACK_LOCATION StackPtr
;
530 PKEVENT EventObject
= NULL
;
531 BOOLEAN LocalEvent
= FALSE
;
532 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
534 DPRINT("IopDeviceFsIoControl(DeviceHandle 0x%p Event 0x%p UserApcRoutine 0x%p "
535 "UserApcContext 0x%p IoStatusBlock 0x%p IoControlCode %x "
536 "InputBuffer 0x%p InputBufferLength %x OutputBuffer 0x%p "
537 "OutputBufferLength 0x%p)\n",
538 DeviceHandle
,Event
,UserApcRoutine
,UserApcContext
,IoStatusBlock
,
539 IoControlCode
,InputBuffer
,InputBufferLength
,OutputBuffer
,
542 if (IoStatusBlock
== NULL
) return STATUS_ACCESS_VIOLATION
;
544 /* Check granted access against the access rights from IoContolCode */
545 Status
= ObReferenceObjectByHandle(DeviceHandle
,
546 (IoControlCode
>> 14) & 0x3,
549 (PVOID
*) &FileObject
,
551 if (!NT_SUCCESS(Status
)) return Status
;
553 /* Check for an event */
557 Status
= ObReferenceObjectByHandle(Event
,
561 (PVOID
*)&EventObject
,
563 if (!NT_SUCCESS(Status
))
565 ObDereferenceObject (FileObject
);
570 KeClearEvent(EventObject
);
573 /* Check if this is a direct open or not */
574 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
576 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
580 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
583 /* Check if we should use Sync IO or not */
584 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
586 /* Use File Object event */
587 KeClearEvent(&FileObject
->Event
);
591 /* Use local event */
596 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
606 /* Set some extra settings */
607 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
608 Irp
->RequestorMode
= PreviousMode
;
609 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
610 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
611 StackPtr
= IoGetNextIrpStackLocation(Irp
);
612 StackPtr
->FileObject
= FileObject
;
613 StackPtr
->MajorFunction
= IsDevIoCtl
?
614 IRP_MJ_DEVICE_CONTROL
: IRP_MJ_FILE_SYSTEM_CONTROL
;
616 /* Call the Driver */
617 Status
= IoCallDriver(DeviceObject
, Irp
);
618 if (Status
== STATUS_PENDING
)
622 KeWaitForSingleObject(&FileObject
->Event
,
625 FileObject
->Flags
& FO_ALERTABLE_IO
,
627 Status
= FileObject
->FinalStatus
;
631 /* Return the Status */
635 /* FUNCTIONS *****************************************************************/
642 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
644 IN BOOLEAN SetOperation
)
647 return STATUS_NOT_IMPLEMENTED
;
655 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
656 IN ULONG QuotaLength
,
657 OUT PULONG ErrorOffset
)
660 return STATUS_NOT_IMPLEMENTED
;
668 * Either causes a new file or directory to be created, or it
669 * opens an existing file, device, directory or volume, giving
670 * the caller a handle for the file object. This handle can be
671 * used by subsequent calls to manipulate data within the file
672 * or the file object's state of attributes.
676 * Points to a variable which receives the file handle
680 * Desired access to the file;
683 * Structure describing the file;
685 * IoStatusBlock (OUT)
686 * Receives information about the operation on return;
688 * AllocationSize [OPTIONAL]
689 * Initial size of the file in bytes;
692 * Attributes to create the file with;
695 * Type of shared access the caller would like to the
699 * Specifies what to do, depending on whether the
700 * file already exists;
703 * Options for creating a new file;
705 * EaBuffer [OPTIONAL]
712 * Type of file (normal, named pipe, mailslot) to create;
714 * ExtraCreateParameters [OPTIONAL]
715 * Additional creation data for named pipe and mailsots;
724 * Prototype taken from Bo Branten's ntifs.h v15.
725 * Description taken from old NtCreateFile's which is
726 * now a wrapper of this call.
734 IoCreateFile(OUT PHANDLE FileHandle
,
735 IN ACCESS_MASK DesiredAccess
,
736 IN POBJECT_ATTRIBUTES ObjectAttributes
,
737 OUT PIO_STATUS_BLOCK IoStatusBlock
,
738 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
739 IN ULONG FileAttributes
,
740 IN ULONG ShareAccess
,
741 IN ULONG CreateDisposition
,
742 IN ULONG CreateOptions
,
743 IN PVOID EaBuffer OPTIONAL
,
745 IN CREATE_FILE_TYPE CreateFileType
,
746 IN PVOID ExtraCreateParameters OPTIONAL
,
749 PFILE_OBJECT FileObject
= NULL
;
750 PDEVICE_OBJECT DeviceObject
;
752 PIO_STACK_LOCATION StackLoc
;
753 IO_SECURITY_CONTEXT SecurityContext
;
754 KPROCESSOR_MODE AccessMode
;
756 IO_STATUS_BLOCK LocalIoStatusBlock
;
757 LARGE_INTEGER SafeAllocationSize
;
758 PVOID SystemEaBuffer
= NULL
;
759 NTSTATUS Status
= STATUS_SUCCESS
;
761 DPRINT("IoCreateFile(FileHandle 0x%p, DesiredAccess %x, "
762 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
763 FileHandle
,DesiredAccess
,ObjectAttributes
,
764 ObjectAttributes
->ObjectName
->Buffer
);
766 ASSERT_IRQL(PASSIVE_LEVEL
);
768 if (IoStatusBlock
== NULL
|| FileHandle
== NULL
)
769 return STATUS_ACCESS_VIOLATION
;
773 if(Options
& IO_NO_PARAMETER_CHECKING
)
774 AccessMode
= KernelMode
;
776 AccessMode
= ExGetPreviousMode();
778 if(AccessMode
!= KernelMode
)
782 ProbeForWrite(FileHandle
,
785 ProbeForWrite(IoStatusBlock
,
786 sizeof(IO_STATUS_BLOCK
),
788 if(AllocationSize
!= NULL
)
790 ProbeForRead(AllocationSize
,
791 sizeof(LARGE_INTEGER
),
793 SafeAllocationSize
= *AllocationSize
;
796 SafeAllocationSize
.QuadPart
= 0;
798 if(EaBuffer
!= NULL
&& EaLength
> 0)
800 ProbeForRead(EaBuffer
,
804 /* marshal EaBuffer */
805 SystemEaBuffer
= ExAllocatePool(NonPagedPool
,
807 if(SystemEaBuffer
== NULL
)
809 Status
= STATUS_INSUFFICIENT_RESOURCES
;
813 RtlCopyMemory(SystemEaBuffer
,
820 Status
= _SEH_GetExceptionCode();
824 if(!NT_SUCCESS(Status
))
831 if(AllocationSize
!= NULL
)
832 SafeAllocationSize
= *AllocationSize
;
834 SafeAllocationSize
.QuadPart
= 0;
836 if(EaBuffer
!= NULL
&& EaLength
> 0)
838 SystemEaBuffer
= EaBuffer
;
842 if(Options
& IO_CHECK_CREATE_PARAMETERS
)
844 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
847 Status
= ObOpenObjectByName(ObjectAttributes
,
855 if (NT_SUCCESS(Status
))
857 Status
= ObReferenceObjectByHandle(LocalHandle
,
861 (PVOID
*)&DeviceObject
,
863 ZwClose(LocalHandle
);
864 if (!NT_SUCCESS(Status
))
868 if (BODY_TO_HEADER(DeviceObject
)->Type
!= IoDeviceObjectType
)
870 ObDereferenceObject (DeviceObject
);
871 return STATUS_OBJECT_NAME_COLLISION
;
874 FileObject
= IoCreateStreamFileObject(NULL
, DeviceObject
);
876 FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
877 DPRINT("%wZ\n", ObjectAttributes
->ObjectName
);
879 ObDereferenceObject (DeviceObject
);
883 if (FileObject
== NULL
)
885 Status
= ObCreateObject(AccessMode
,
893 (PVOID
*)&FileObject
);
894 if (!NT_SUCCESS(Status
))
896 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
900 RtlMapGenericMask(&DesiredAccess
,
901 &BODY_TO_HEADER(FileObject
)->Type
->TypeInfo
.GenericMapping
);
903 Status
= ObInsertObject ((PVOID
)FileObject
,
909 if (!NT_SUCCESS(Status
))
911 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
912 ObDereferenceObject (FileObject
);
916 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
918 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
920 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
922 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
925 if (CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
926 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
928 SecurityContext
.SecurityQos
= NULL
; /* ?? */
929 SecurityContext
.AccessState
= NULL
; /* ?? */
930 SecurityContext
.DesiredAccess
= DesiredAccess
;
931 SecurityContext
.FullCreateOptions
= 0; /* ?? */
933 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
934 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
936 DPRINT("FileObject 0x%p\n", FileObject
);
937 DPRINT("FileObject->DeviceObject 0x%p\n", FileObject
->DeviceObject
);
939 * Create a new IRP to hand to
940 * the FS driver: this may fail
941 * due to resource shortage.
943 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
946 ZwClose(LocalHandle
);
947 return STATUS_UNSUCCESSFUL
;
950 //trigger FileObject/Event dereferencing
951 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
952 Irp
->RequestorMode
= AccessMode
;
953 Irp
->UserIosb
= &LocalIoStatusBlock
;
954 Irp
->AssociatedIrp
.SystemBuffer
= SystemEaBuffer
;
955 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
956 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
957 Irp
->UserEvent
= &FileObject
->Event
;
958 Irp
->Overlay
.AllocationSize
= SafeAllocationSize
;
961 * Get the stack location for the new
962 * IRP and prepare it.
964 StackLoc
= IoGetNextIrpStackLocation(Irp
);
965 StackLoc
->MinorFunction
= 0;
966 StackLoc
->Flags
= (UCHAR
)Options
;
967 StackLoc
->Control
= 0;
968 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
969 StackLoc
->FileObject
= FileObject
;
971 switch (CreateFileType
)
974 case CreateFileTypeNone
:
975 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
976 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
977 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
978 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
979 StackLoc
->Parameters
.Create
.FileAttributes
= (USHORT
)FileAttributes
;
980 StackLoc
->Parameters
.Create
.ShareAccess
= (USHORT
)ShareAccess
;
981 StackLoc
->Parameters
.Create
.EaLength
= SystemEaBuffer
!= NULL
? EaLength
: 0;
984 case CreateFileTypeNamedPipe
:
985 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
986 StackLoc
->Parameters
.CreatePipe
.SecurityContext
= &SecurityContext
;
987 StackLoc
->Parameters
.CreatePipe
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
988 StackLoc
->Parameters
.CreatePipe
.Options
|= (CreateDisposition
<< 24);
989 StackLoc
->Parameters
.CreatePipe
.ShareAccess
= (USHORT
)ShareAccess
;
990 StackLoc
->Parameters
.CreatePipe
.Parameters
= ExtraCreateParameters
;
993 case CreateFileTypeMailslot
:
994 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
995 StackLoc
->Parameters
.CreateMailslot
.SecurityContext
= &SecurityContext
;
996 StackLoc
->Parameters
.CreateMailslot
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
997 StackLoc
->Parameters
.CreateMailslot
.Options
|= (CreateDisposition
<< 24);
998 StackLoc
->Parameters
.CreateMailslot
.ShareAccess
= (USHORT
)ShareAccess
;
999 StackLoc
->Parameters
.CreateMailslot
.Parameters
= ExtraCreateParameters
;
1004 * Now call the driver and
1005 * possibly wait if it can
1006 * not complete the request
1009 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
1010 DPRINT("Status :%x\n", Status
);
1012 if (Status
== STATUS_PENDING
)
1014 KeWaitForSingleObject(&FileObject
->Event
,
1019 Status
= LocalIoStatusBlock
.Status
;
1021 if (!NT_SUCCESS(Status
))
1023 DPRINT("Failing create request with status %x\n", Status
);
1024 FileObject
->DeviceObject
= NULL
;
1025 FileObject
->Vpb
= NULL
;
1027 ZwClose(LocalHandle
);
1033 *FileHandle
= LocalHandle
;
1034 *IoStatusBlock
= LocalIoStatusBlock
;
1038 Status
= _SEH_GetExceptionCode();
1043 /* cleanup EABuffer if captured */
1044 if(AccessMode
!= KernelMode
&& SystemEaBuffer
!= NULL
)
1046 ExFreePool(SystemEaBuffer
);
1049 ASSERT_IRQL(PASSIVE_LEVEL
);
1051 DPRINT("Finished IoCreateFile() (*FileHandle) 0x%p\n", (*FileHandle
));
1061 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
1062 IN ACCESS_MASK DesiredAccess
,
1063 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1064 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1065 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1066 IN ULONG FileAttributes
,
1067 IN ULONG ShareAccess
,
1068 IN ULONG Disposition
,
1069 IN ULONG CreateOptions
,
1070 IN PVOID EaBuffer OPTIONAL
,
1072 IN CREATE_FILE_TYPE CreateFileType
,
1073 IN PVOID ExtraCreateParameters OPTIONAL
,
1075 IN PVOID DeviceObject
)
1078 return STATUS_NOT_IMPLEMENTED
;
1083 * IoCreateStreamFileObject@8
1104 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
1105 PDEVICE_OBJECT DeviceObject
)
1107 PFILE_OBJECT CreatedFileObject
;
1110 /* FIXME: This function should call ObInsertObject. The "Lite" version
1111 doesnt. This function is also called from IoCreateFile for some
1112 reason. These hacks need to be removed.
1115 DPRINT("IoCreateStreamFileObject(FileObject 0x%p, DeviceObject 0x%p)\n",
1116 FileObject
, DeviceObject
);
1119 /* Create the File Object */
1120 Status
= ObCreateObject(KernelMode
,
1125 sizeof(FILE_OBJECT
),
1128 (PVOID
*)&CreatedFileObject
);
1129 if (!NT_SUCCESS(Status
))
1131 DPRINT1("Could not create FileObject\n");
1135 /* Choose Device Object */
1136 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1137 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1140 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1142 /* Set File Object Data */
1143 CreatedFileObject
->DeviceObject
= DeviceObject
;
1144 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
1145 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1146 CreatedFileObject
->Flags
|= FO_STREAM_FILE
;
1148 /* Initialize Lock and Event */
1149 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
1150 KeInitializeEvent(&CreatedFileObject
->Lock
, SynchronizationEvent
, TRUE
);
1153 return CreatedFileObject
;
1161 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1162 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1163 OUT PHANDLE FileObjectHandle OPTIONAL
)
1174 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1175 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1186 IoGetFileObjectGenericMapping(VOID
)
1188 return &IopFileMapping
;
1196 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
1198 /* Return the flag status */
1199 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
1207 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
1208 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
1211 return STATUS_NOT_IMPLEMENTED
;
1219 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1220 IN FILE_INFORMATION_CLASS FileInformationClass
,
1222 OUT PVOID FileInformation
,
1223 OUT PULONG ReturnedLength
)
1225 IO_STATUS_BLOCK IoStatusBlock
;
1227 PDEVICE_OBJECT DeviceObject
;
1228 PIO_STACK_LOCATION StackPtr
;
1229 BOOLEAN LocalEvent
= FALSE
;
1233 ASSERT(FileInformation
!= NULL
);
1235 Status
= ObReferenceObjectByPointer(FileObject
,
1236 FILE_READ_ATTRIBUTES
,
1239 if (!NT_SUCCESS(Status
)) return(Status
);
1241 DPRINT("FileObject 0x%p\n", FileObject
);
1243 /* Get the Device Object */
1244 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1246 /* Check if we should use Sync IO or not */
1247 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1249 /* Use File Object event */
1250 KeClearEvent(&FileObject
->Event
);
1254 /* Use local event */
1255 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1259 /* Allocate the IRP */
1260 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1263 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1264 Irp
->RequestorMode
= KernelMode
;
1265 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1266 Irp
->UserIosb
= &IoStatusBlock
;
1267 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1268 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1269 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1271 /* Set the Stack Data */
1272 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1273 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1274 StackPtr
->FileObject
= FileObject
;
1276 /* Set Parameters */
1277 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1278 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1280 /* Call the Driver */
1281 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
1283 if (Status
== STATUS_PENDING
)
1287 KeWaitForSingleObject(&Event
,
1290 FileObject
->Flags
& FO_ALERTABLE_IO
,
1292 Status
= IoStatusBlock
.Status
;
1296 KeWaitForSingleObject(&FileObject
->Event
,
1299 FileObject
->Flags
& FO_ALERTABLE_IO
,
1301 Status
= FileObject
->FinalStatus
;
1306 /* Return the Length and Status. ReturnedLength is NOT optional */
1307 *ReturnedLength
= IoStatusBlock
.Information
;
1316 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
1320 return STATUS_NOT_IMPLEMENTED
;
1324 * @name NtCancelIoFile
1326 * Cancel all pending I/O operations in the current thread for specified
1330 * Handle to file object to cancel requests for. No specific
1331 * access rights are needed.
1332 * @param IoStatusBlock
1333 * Pointer to status block which is filled with final completition
1334 * status on successful return.
1342 NtCancelIoFile(IN HANDLE FileHandle
,
1343 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1346 PFILE_OBJECT FileObject
;
1348 PLIST_ENTRY IrpEntry
;
1351 BOOLEAN OurIrpsInList
= FALSE
;
1352 LARGE_INTEGER Interval
;
1354 if ((ULONG_PTR
)IoStatusBlock
>= (ULONG_PTR
)MmUserProbeAddress
&&
1355 KeGetPreviousMode() == UserMode
)
1356 return STATUS_ACCESS_VIOLATION
;
1358 Status
= ObReferenceObjectByHandle(FileHandle
, 0, IoFileObjectType
,
1359 KeGetPreviousMode(), (PVOID
*)&FileObject
,
1361 if (!NT_SUCCESS(Status
))
1364 /* IRP cancellations are synchronized at APC_LEVEL. */
1365 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1368 * Walk the list of active IRPs and cancel the ones that belong to
1372 Thread
= PsGetCurrentThread();
1373 for (IrpEntry
= Thread
->IrpList
.Flink
;
1374 IrpEntry
!= &Thread
->IrpList
;
1375 IrpEntry
= IrpEntry
->Flink
)
1377 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1378 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1381 /* Don't break here, we want to cancel all IRPs for the file object. */
1382 OurIrpsInList
= TRUE
;
1386 KfLowerIrql(OldIrql
);
1388 while (OurIrpsInList
)
1390 OurIrpsInList
= FALSE
;
1392 /* Wait a short while and then look if all our IRPs were completed. */
1393 Interval
.QuadPart
= -1000000; /* 100 milliseconds */
1394 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1396 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1399 * Look in the list if all IRPs for the specified file object
1400 * are completed (or cancelled). If someone sends a new IRP
1401 * for our file object while we're here we can happily loop
1405 for (IrpEntry
= Thread
->IrpList
.Flink
;
1406 IrpEntry
!= &Thread
->IrpList
;
1407 IrpEntry
= IrpEntry
->Flink
)
1409 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1410 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1412 OurIrpsInList
= TRUE
;
1417 KfLowerIrql(OldIrql
);
1422 IoStatusBlock
->Status
= STATUS_SUCCESS
;
1423 IoStatusBlock
->Information
= 0;
1424 Status
= STATUS_SUCCESS
;
1428 Status
= STATUS_UNSUCCESSFUL
;
1432 ObDereferenceObject(FileObject
);
1442 * Entry point to call IoCreateFile with
1443 * default parameters.
1453 * Code originally in NtCreateFile moved in IoCreateFile.
1459 NtCreateFile(PHANDLE FileHandle
,
1460 ACCESS_MASK DesiredAccess
,
1461 POBJECT_ATTRIBUTES ObjectAttributes
,
1462 PIO_STATUS_BLOCK IoStatusBlock
,
1463 PLARGE_INTEGER AllocateSize
,
1464 ULONG FileAttributes
,
1466 ULONG CreateDisposition
,
1467 ULONG CreateOptions
,
1471 /* Call the I/O Function */
1472 return IoCreateFile(FileHandle
,
1490 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
1491 IN ACCESS_MASK DesiredAccess
,
1492 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1493 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1494 IN ULONG CreateOptions
,
1495 IN ULONG MailslotQuota
,
1496 IN ULONG MaxMessageSize
,
1497 IN PLARGE_INTEGER TimeOut
)
1499 MAILSLOT_CREATE_PARAMETERS Buffer
;
1501 DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, "
1502 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
1503 FileHandle
,DesiredAccess
,ObjectAttributes
,
1504 ObjectAttributes
->ObjectName
->Buffer
);
1507 /* Check for Timeout */
1511 Buffer
.TimeoutSpecified
= TRUE
;
1513 /* FIXME: Add SEH */
1514 Buffer
.ReadTimeout
= *TimeOut
;
1519 Buffer
.TimeoutSpecified
= FALSE
;
1523 Buffer
.MailslotQuota
= MailslotQuota
;
1524 Buffer
.MaximumMessageSize
= MaxMessageSize
;
1527 return IoCreateFile(FileHandle
,
1532 FILE_ATTRIBUTE_NORMAL
,
1533 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1538 CreateFileTypeMailslot
,
1545 NtCreateNamedPipeFile(PHANDLE FileHandle
,
1546 ACCESS_MASK DesiredAccess
,
1547 POBJECT_ATTRIBUTES ObjectAttributes
,
1548 PIO_STATUS_BLOCK IoStatusBlock
,
1550 ULONG CreateDisposition
,
1551 ULONG CreateOptions
,
1552 ULONG NamedPipeType
,
1554 ULONG CompletionMode
,
1555 ULONG MaximumInstances
,
1557 ULONG OutboundQuota
,
1558 PLARGE_INTEGER DefaultTimeout
)
1560 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
1562 DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, "
1563 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
1564 FileHandle
,DesiredAccess
,ObjectAttributes
,
1565 ObjectAttributes
->ObjectName
->Buffer
);
1568 /* Check for Timeout */
1572 Buffer
.TimeoutSpecified
= TRUE
;
1574 /* FIXME: Add SEH */
1575 Buffer
.DefaultTimeout
= *DefaultTimeout
;
1580 Buffer
.TimeoutSpecified
= FALSE
;
1584 Buffer
.NamedPipeType
= NamedPipeType
;
1585 Buffer
.ReadMode
= ReadMode
;
1586 Buffer
.CompletionMode
= CompletionMode
;
1587 Buffer
.MaximumInstances
= MaximumInstances
;
1588 Buffer
.InboundQuota
= InboundQuota
;
1589 Buffer
.OutboundQuota
= OutboundQuota
;
1592 return IoCreateFile(FileHandle
,
1597 FILE_ATTRIBUTE_NORMAL
,
1603 CreateFileTypeNamedPipe
,
1626 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
1629 return(STATUS_NOT_IMPLEMENTED
);
1637 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1638 IN HANDLE Event OPTIONAL
,
1639 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1640 IN PVOID UserApcContext OPTIONAL
,
1641 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1642 IN ULONG IoControlCode
,
1643 IN PVOID InputBuffer
,
1644 IN ULONG InputBufferLength OPTIONAL
,
1645 OUT PVOID OutputBuffer
,
1646 IN ULONG OutputBufferLength OPTIONAL
)
1648 /* Call the Generic Function */
1649 return IopDeviceFsIoControl(DeviceHandle
,
1667 NtFsControlFile(IN HANDLE DeviceHandle
,
1668 IN HANDLE Event OPTIONAL
,
1669 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1670 IN PVOID UserApcContext OPTIONAL
,
1671 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1672 IN ULONG IoControlCode
,
1673 IN PVOID InputBuffer
,
1674 IN ULONG InputBufferLength OPTIONAL
,
1675 OUT PVOID OutputBuffer
,
1676 IN ULONG OutputBufferLength OPTIONAL
)
1678 return IopDeviceFsIoControl(DeviceHandle
,
1693 NtFlushWriteBuffer(VOID
)
1695 KeFlushWriteBuffer();
1696 return STATUS_SUCCESS
;
1700 * FUNCTION: Flushes cached file data to disk
1702 * FileHandle = Points to the file
1703 * IoStatusBlock = Caller must supply storage to receive the result of
1704 * the flush buffers operation. The information field is
1705 * set to number of bytes flushed to disk.
1707 * REMARKS: This function maps to the win32 FlushFileBuffers
1711 NtFlushBuffersFile(IN HANDLE FileHandle
,
1712 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1714 PFILE_OBJECT FileObject
= NULL
;
1716 PIO_STACK_LOCATION StackPtr
;
1718 PDEVICE_OBJECT DeviceObject
;
1720 BOOLEAN LocalEvent
= FALSE
;
1721 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1723 /* Get the File Object */
1724 Status
= ObReferenceObjectByHandle(FileHandle
,
1728 (PVOID
*)&FileObject
,
1730 if (Status
!= STATUS_SUCCESS
) return(Status
);
1732 /* Check if this is a direct open or not */
1733 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1735 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1739 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1742 /* Check if we should use Sync IO or not */
1743 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1745 /* Use File Object event */
1746 KeClearEvent(&FileObject
->Event
);
1750 /* Use local event */
1751 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1755 /* Allocate the IRP */
1756 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
1758 ObDereferenceObject(FileObject
);
1759 return STATUS_INSUFFICIENT_RESOURCES
;
1762 /* Set up the IRP */
1763 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1764 Irp
->RequestorMode
= PreviousMode
;
1765 Irp
->UserIosb
= IoStatusBlock
;
1766 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1767 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1768 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1770 /* Set up Stack Data */
1771 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1772 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1773 StackPtr
->FileObject
= FileObject
;
1775 /* Call the Driver */
1776 Status
= IoCallDriver(DeviceObject
, Irp
);
1777 if (Status
== STATUS_PENDING
)
1781 KeWaitForSingleObject(&Event
,
1784 FileObject
->Flags
& FO_ALERTABLE_IO
,
1786 Status
= IoStatusBlock
->Status
;
1790 KeWaitForSingleObject(&FileObject
->Event
,
1793 FileObject
->Flags
& FO_ALERTABLE_IO
,
1795 Status
= FileObject
->FinalStatus
;
1799 /* Return the Status */
1808 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1809 IN HANDLE Event OPTIONAL
,
1810 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1811 IN PVOID ApcContext OPTIONAL
,
1812 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1814 IN ULONG BufferSize
,
1815 IN ULONG CompletionFilter
,
1816 IN BOOLEAN WatchTree
)
1819 PDEVICE_OBJECT DeviceObject
;
1820 PFILE_OBJECT FileObject
;
1821 PIO_STACK_LOCATION IoStack
;
1822 KPROCESSOR_MODE PreviousMode
;
1823 NTSTATUS Status
= STATUS_SUCCESS
;
1825 DPRINT("NtNotifyChangeDirectoryFile()\n");
1829 PreviousMode
= ExGetPreviousMode();
1831 if(PreviousMode
!= KernelMode
)
1835 ProbeForWrite(IoStatusBlock
,
1836 sizeof(IO_STATUS_BLOCK
),
1840 ProbeForWrite(Buffer
,
1847 Status
= _SEH_GetExceptionCode();
1851 if(!NT_SUCCESS(Status
))
1857 Status
= ObReferenceObjectByHandle(FileHandle
,
1858 FILE_LIST_DIRECTORY
,
1861 (PVOID
*)&FileObject
,
1863 if (Status
!= STATUS_SUCCESS
) return(Status
);
1866 DeviceObject
= FileObject
->DeviceObject
;
1869 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1872 ObDereferenceObject(FileObject
);
1873 return STATUS_UNSUCCESSFUL
;
1878 Event
= &FileObject
->Event
;
1881 /* Trigger FileObject/Event dereferencing */
1882 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1883 Irp
->RequestorMode
= PreviousMode
;
1884 Irp
->UserIosb
= IoStatusBlock
;
1885 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1886 Irp
->UserEvent
= Event
;
1887 KeResetEvent( Event
);
1888 Irp
->UserBuffer
= Buffer
;
1889 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1890 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1892 IoStack
= IoGetNextIrpStackLocation(Irp
);
1894 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1895 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1897 IoStack
->Control
= 0;
1898 IoStack
->DeviceObject
= DeviceObject
;
1899 IoStack
->FileObject
= FileObject
;
1903 IoStack
->Flags
= SL_WATCH_TREE
;
1906 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1907 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1909 Status
= IoCallDriver(FileObject
->DeviceObject
,Irp
);
1911 /* FIXME: Should we wait here or not for synchronously opened files? */
1921 NtLockFile(IN HANDLE FileHandle
,
1922 IN HANDLE EventHandle OPTIONAL
,
1923 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1924 IN PVOID ApcContext OPTIONAL
,
1925 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1926 IN PLARGE_INTEGER ByteOffset
,
1927 IN PLARGE_INTEGER Length
,
1929 IN BOOLEAN FailImmediately
,
1930 IN BOOLEAN ExclusiveLock
)
1932 PFILE_OBJECT FileObject
= NULL
;
1933 PLARGE_INTEGER LocalLength
= NULL
;
1935 PIO_STACK_LOCATION StackPtr
;
1936 PDEVICE_OBJECT DeviceObject
;
1937 PKEVENT Event
= NULL
;
1938 BOOLEAN LocalEvent
= FALSE
;
1939 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1940 NTSTATUS Status
= STATUS_SUCCESS
;
1941 OBJECT_HANDLE_INFORMATION HandleInformation
;
1943 /* FIXME: instead of this, use SEH */
1944 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
1946 /* Get File Object */
1947 Status
= ObReferenceObjectByHandle(FileHandle
,
1951 (PVOID
*)&FileObject
,
1952 &HandleInformation
);
1953 if (!NT_SUCCESS(Status
)) return Status
;
1955 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
1956 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1958 DPRINT1("Invalid access rights\n");
1959 ObDereferenceObject(FileObject
);
1960 return STATUS_ACCESS_DENIED
;
1963 /* Get Event Object */
1966 Status
= ObReferenceObjectByHandle(EventHandle
,
1972 if (Status
!= STATUS_SUCCESS
) return(Status
);
1973 KeClearEvent(Event
);
1976 /* Check if this is a direct open or not */
1977 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1979 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1983 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1986 /* Check if we should use Sync IO or not */
1987 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1989 /* Use File Object event */
1990 KeClearEvent(&FileObject
->Event
);
1997 /* Allocate the IRP */
1998 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2000 ObDereferenceObject(FileObject
);
2001 return STATUS_INSUFFICIENT_RESOURCES
;
2004 /* Allocate local buffer */
2005 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2006 sizeof(LARGE_INTEGER
),
2011 ObDereferenceObject(FileObject
);
2012 return STATUS_INSUFFICIENT_RESOURCES
;
2014 *LocalLength
= *Length
;
2016 /* Set up the IRP */
2017 Irp
->RequestorMode
= PreviousMode
;
2018 Irp
->UserIosb
= IoStatusBlock
;
2019 Irp
->UserEvent
= Event
;
2020 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2021 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2023 /* Set up Stack Data */
2024 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2025 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2026 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
2027 StackPtr
->FileObject
= FileObject
;
2029 /* Set Parameters */
2030 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2031 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
2032 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
2035 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
2036 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
2038 /* Call the Driver */
2039 FileObject
->LockOperation
= TRUE
;
2040 Status
= IoCallDriver(DeviceObject
, Irp
);
2041 if (Status
== STATUS_PENDING
)
2045 KeWaitForSingleObject(&FileObject
->Event
,
2048 FileObject
->Flags
& FO_ALERTABLE_IO
,
2050 Status
= FileObject
->FinalStatus
;
2054 /* Return the Status */
2063 * Opens an existing file (simpler than NtCreateFile).
2067 * Variable that receives the file handle on return;
2070 * Access desired by the caller to the file;
2073 * Structue describing the file to be opened;
2075 * IoStatusBlock (OUT)
2076 * Receives details about the result of the
2080 * Type of shared access the caller requires;
2083 * Options for the file open.
2095 NtOpenFile(PHANDLE FileHandle
,
2096 ACCESS_MASK DesiredAccess
,
2097 POBJECT_ATTRIBUTES ObjectAttributes
,
2098 PIO_STATUS_BLOCK IoStatusBlock
,
2102 /* Call the I/O Function */
2103 return IoCreateFile(FileHandle
,
2121 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2122 OUT PFILE_BASIC_INFORMATION FileInformation
)
2124 IO_STATUS_BLOCK IoStatusBlock
;
2129 Status
= ZwOpenFile(&FileHandle
,
2130 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2133 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2134 FILE_SYNCHRONOUS_IO_NONALERT
);
2135 if (!NT_SUCCESS (Status
))
2137 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2141 /* Get file attributes */
2142 Status
= ZwQueryInformationFile(FileHandle
,
2145 sizeof(FILE_BASIC_INFORMATION
),
2146 FileBasicInformation
);
2147 if (!NT_SUCCESS (Status
))
2149 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2152 ZwClose(FileHandle
);
2159 * FUNCTION: Queries a directory file.
2161 * FileHandle = Handle to a directory file
2162 * EventHandle = Handle to the event signaled on completion
2163 * ApcRoutine = Asynchroneous procedure callback, called on completion
2164 * ApcContext = Argument to the apc.
2165 * IoStatusBlock = Caller supplies storage for extended status information.
2166 * FileInformation = Caller supplies storage for the resulting information.
2168 * FileNameInformation FILE_NAMES_INFORMATION
2169 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2170 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2171 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2173 * Length = Size of the storage supplied
2174 * FileInformationClass = Indicates the type of information requested.
2175 * ReturnSingleEntry = Specify true if caller only requests the first
2177 * FileName = Initial directory name to query, that may contain wild
2179 * RestartScan = Number of times the action should be repeated
2180 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2181 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2182 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2186 NtQueryDirectoryFile(IN HANDLE FileHandle
,
2187 IN HANDLE PEvent OPTIONAL
,
2188 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2189 IN PVOID ApcContext OPTIONAL
,
2190 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2191 OUT PVOID FileInformation
,
2193 IN FILE_INFORMATION_CLASS FileInformationClass
,
2194 IN BOOLEAN ReturnSingleEntry
,
2195 IN PUNICODE_STRING FileName OPTIONAL
,
2196 IN BOOLEAN RestartScan
)
2199 PDEVICE_OBJECT DeviceObject
;
2200 PFILE_OBJECT FileObject
;
2201 PIO_STACK_LOCATION StackPtr
;
2202 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2203 NTSTATUS Status
= STATUS_SUCCESS
;
2204 BOOLEAN LocalEvent
= FALSE
;
2205 PKEVENT Event
= NULL
;
2207 DPRINT("NtQueryDirectoryFile()\n");
2210 /* Validate User-Mode Buffers */
2211 if(PreviousMode
!= KernelMode
)
2215 ProbeForWrite(IoStatusBlock
,
2216 sizeof(IO_STATUS_BLOCK
),
2218 ProbeForWrite(FileInformation
,
2224 Status
= _SEH_GetExceptionCode();
2228 if(!NT_SUCCESS(Status
)) return Status
;
2231 /* Get File Object */
2232 Status
= ObReferenceObjectByHandle(FileHandle
,
2233 FILE_LIST_DIRECTORY
,
2236 (PVOID
*)&FileObject
,
2238 if (Status
!= STATUS_SUCCESS
) return(Status
);
2240 /* Get Event Object */
2243 Status
= ObReferenceObjectByHandle(PEvent
,
2249 if (Status
!= STATUS_SUCCESS
) return(Status
);
2250 KeClearEvent(Event
);
2253 /* Check if this is a direct open or not */
2254 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2256 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2260 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2263 /* Check if we should use Sync IO or not */
2264 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2266 /* Use File Object event */
2267 KeClearEvent(&FileObject
->Event
);
2274 /* Allocate the IRP */
2275 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2277 ObDereferenceObject(FileObject
);
2278 return STATUS_INSUFFICIENT_RESOURCES
;
2281 /* Set up the IRP */
2282 Irp
->RequestorMode
= PreviousMode
;
2283 Irp
->UserIosb
= IoStatusBlock
;
2284 Irp
->UserEvent
= Event
;
2285 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2286 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2287 Irp
->UserBuffer
= FileInformation
;
2288 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2289 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2291 /* Set up Stack Data */
2292 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2293 StackPtr
->FileObject
= FileObject
;
2294 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2295 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2297 /* Set Parameters */
2298 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
= FileInformationClass
;
2299 StackPtr
->Parameters
.QueryDirectory
.FileName
= FileName
;
2300 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2301 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2302 StackPtr
->Flags
= 0;
2303 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2304 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2306 /* Call the Driver */
2307 Status
= IoCallDriver(DeviceObject
, Irp
);
2308 if (Status
== STATUS_PENDING
)
2312 KeWaitForSingleObject(&FileObject
->Event
,
2315 FileObject
->Flags
& FO_ALERTABLE_IO
,
2317 Status
= FileObject
->FinalStatus
;
2321 /* Return the Status */
2329 NtQueryEaFile(IN HANDLE FileHandle
,
2330 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2333 IN BOOLEAN ReturnSingleEntry
,
2334 IN PVOID EaList OPTIONAL
,
2335 IN ULONG EaListLength
,
2336 IN PULONG EaIndex OPTIONAL
,
2337 IN BOOLEAN RestartScan
)
2340 return STATUS_NOT_IMPLEMENTED
;
2345 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2346 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2348 IO_STATUS_BLOCK IoStatusBlock
;
2353 Status
= ZwOpenFile(&FileHandle
,
2354 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2357 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2358 FILE_SYNCHRONOUS_IO_NONALERT
);
2359 if (!NT_SUCCESS (Status
))
2361 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2365 /* Get file attributes */
2366 Status
= ZwQueryInformationFile(FileHandle
,
2369 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2370 FileNetworkOpenInformation
);
2371 if (!NT_SUCCESS (Status
))
2373 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2376 ZwClose (FileHandle
);
2384 NtQueryInformationFile(HANDLE FileHandle
,
2385 PIO_STATUS_BLOCK IoStatusBlock
,
2386 PVOID FileInformation
,
2388 FILE_INFORMATION_CLASS FileInformationClass
)
2390 OBJECT_HANDLE_INFORMATION HandleInformation
;
2391 PFILE_OBJECT FileObject
;
2394 PDEVICE_OBJECT DeviceObject
;
2395 PIO_STACK_LOCATION StackPtr
;
2396 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2398 BOOLEAN LocalEvent
= FALSE
;
2399 BOOLEAN Failed
= FALSE
;
2401 ASSERT(IoStatusBlock
!= NULL
);
2402 ASSERT(FileInformation
!= NULL
);
2404 DPRINT("NtQueryInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
2405 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2406 Length
, FileInformationClass
);
2408 /* Reference the Handle */
2409 Status
= ObReferenceObjectByHandle(FileHandle
,
2413 (PVOID
*)&FileObject
,
2414 &HandleInformation
);
2415 if (!NT_SUCCESS(Status
)) return Status
;
2417 /* Check information class specific access rights */
2418 switch (FileInformationClass
)
2420 case FileBasicInformation
:
2421 if (!(HandleInformation
.GrantedAccess
& FILE_READ_ATTRIBUTES
))
2425 case FilePositionInformation
:
2426 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2427 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2431 case FileAlignmentInformation
:
2432 if (!(FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
))
2442 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2443 ObDereferenceObject(FileObject
);
2444 return STATUS_ACCESS_DENIED
;
2447 DPRINT("FileObject 0x%p\n", FileObject
);
2449 /* Check if this is a direct open or not */
2450 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2452 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2456 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2459 /* Check if we should use Sync IO or not */
2460 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2462 /* Use File Object event */
2463 KeClearEvent(&FileObject
->Event
);
2467 /* Use local event */
2468 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2472 /* Allocate the IRP */
2473 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2475 ObDereferenceObject(FileObject
);
2476 return STATUS_INSUFFICIENT_RESOURCES
;
2479 /* Allocate the System Buffer */
2480 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2485 ObDereferenceObject(FileObject
);
2486 return STATUS_INSUFFICIENT_RESOURCES
;
2489 /* Set up the IRP */
2490 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2491 Irp
->RequestorMode
= PreviousMode
;
2492 Irp
->UserIosb
= IoStatusBlock
;
2493 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2494 Irp
->UserBuffer
= FileInformation
;
2495 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2496 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
2497 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2499 /* Set up Stack Data */
2500 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2501 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2502 StackPtr
->FileObject
= FileObject
;
2504 /* Set the Parameters */
2505 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2506 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2508 /* Call the Driver */
2509 Status
= IoCallDriver(DeviceObject
, Irp
);
2510 if (Status
== STATUS_PENDING
)
2514 KeWaitForSingleObject(&Event
,
2517 FileObject
->Flags
& FO_ALERTABLE_IO
,
2519 Status
= IoStatusBlock
->Status
;
2523 KeWaitForSingleObject(&FileObject
->Event
,
2526 FileObject
->Flags
& FO_ALERTABLE_IO
,
2528 Status
= FileObject
->FinalStatus
;
2532 /* Return the Status */
2541 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2542 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2545 IN BOOLEAN ReturnSingleEntry
,
2546 IN PVOID SidList OPTIONAL
,
2547 IN ULONG SidListLength
,
2548 IN PSID StartSid OPTIONAL
,
2549 IN BOOLEAN RestartScan
)
2552 return STATUS_NOT_IMPLEMENTED
;
2571 NtReadFile(IN HANDLE FileHandle
,
2572 IN HANDLE Event OPTIONAL
,
2573 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2574 IN PVOID ApcContext OPTIONAL
,
2575 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2578 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2579 IN PULONG Key OPTIONAL
)
2581 NTSTATUS Status
= STATUS_SUCCESS
;
2582 PFILE_OBJECT FileObject
;
2584 PDEVICE_OBJECT DeviceObject
;
2585 PIO_STACK_LOCATION StackPtr
;
2586 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2587 BOOLEAN LocalEvent
= FALSE
;
2588 PKEVENT EventObject
= NULL
;
2590 DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
2591 "IoStatusBlock 0x%p)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2595 /* Validate User-Mode Buffers */
2596 if(PreviousMode
!= KernelMode
)
2600 ProbeForWrite(IoStatusBlock
,
2601 sizeof(IO_STATUS_BLOCK
),
2604 ProbeForWrite(Buffer
,
2611 Status
= _SEH_GetExceptionCode();
2615 if(!NT_SUCCESS(Status
)) return Status
;
2618 /* Get File Object */
2619 Status
= ObReferenceObjectByHandle(FileHandle
,
2623 (PVOID
*)&FileObject
,
2625 if (!NT_SUCCESS(Status
)) return Status
;
2627 /* Check the Byte Offset */
2629 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
2630 ByteOffset
->u
.HighPart
== 0xffffffff))
2632 /* a valid ByteOffset is required if asynch. op. */
2633 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2635 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2636 ObDereferenceObject(FileObject
);
2637 return STATUS_INVALID_PARAMETER
;
2640 /* Use the Current Byte OFfset */
2641 ByteOffset
= &FileObject
->CurrentByteOffset
;
2644 /* Check for event */
2648 Status
= ObReferenceObjectByHandle(Event
,
2652 (PVOID
*)&EventObject
,
2654 if (!NT_SUCCESS(Status
))
2656 ObDereferenceObject(FileObject
);
2659 KeClearEvent(EventObject
);
2662 /* Check if this is a direct open or not */
2663 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2665 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2669 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2672 /* Check if we should use Sync IO or not */
2673 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2675 /* Use File Object event */
2676 KeClearEvent(&FileObject
->Event
);
2683 /* Create the IRP */
2686 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2695 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2700 Status
= _SEH_GetExceptionCode();
2704 /* Cleanup if IRP Allocation Failed */
2705 if (!NT_SUCCESS(Status
))
2707 if (Event
) ObDereferenceObject(EventObject
);
2708 ObDereferenceObject(FileObject
);
2712 /* Set up IRP Data */
2713 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2714 Irp
->RequestorMode
= PreviousMode
;
2715 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2716 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2717 Irp
->Flags
|= IRP_READ_OPERATION
;
2720 * Vfat doesn't handle non cached files correctly.
2722 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2725 /* Setup Stack Data */
2726 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2727 StackPtr
->FileObject
= FileObject
;
2728 StackPtr
->Parameters
.Read
.Key
= Key
? *Key
: 0;
2730 /* Call the Driver */
2731 Status
= IoCallDriver(DeviceObject
, Irp
);
2732 if (Status
== STATUS_PENDING
)
2736 KeWaitForSingleObject(&FileObject
->Event
,
2739 FileObject
->Flags
& FO_ALERTABLE_IO
,
2741 Status
= FileObject
->FinalStatus
;
2745 /* Return the Status */
2763 NtReadFileScatter(IN HANDLE FileHandle
,
2764 IN HANDLE Event OPTIONAL
,
2765 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2766 IN PVOID UserApcContext OPTIONAL
,
2767 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2768 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2769 IN ULONG BufferLength
,
2770 IN PLARGE_INTEGER ByteOffset
,
2771 IN PULONG Key OPTIONAL
)
2774 return(STATUS_NOT_IMPLEMENTED
);
2782 NtSetEaFile(IN HANDLE FileHandle
,
2783 IN PIO_STATUS_BLOCK IoStatusBlock
,
2785 IN ULONG EaBufferSize
)
2788 return STATUS_NOT_IMPLEMENTED
;
2795 NtSetInformationFile(HANDLE FileHandle
,
2796 PIO_STATUS_BLOCK IoStatusBlock
,
2797 PVOID FileInformation
,
2799 FILE_INFORMATION_CLASS FileInformationClass
)
2801 OBJECT_HANDLE_INFORMATION HandleInformation
;
2802 PIO_STACK_LOCATION StackPtr
;
2803 PFILE_OBJECT FileObject
;
2804 PDEVICE_OBJECT DeviceObject
;
2807 BOOLEAN LocalEvent
= FALSE
;
2808 NTSTATUS Status
= STATUS_SUCCESS
;
2809 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2810 BOOLEAN Failed
= FALSE
;
2812 ASSERT(IoStatusBlock
!= NULL
);
2813 ASSERT(FileInformation
!= NULL
);
2815 DPRINT("NtSetInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
2816 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2817 Length
, FileInformationClass
);
2819 /* Get the file object from the file handle */
2820 Status
= ObReferenceObjectByHandle(FileHandle
,
2824 (PVOID
*)&FileObject
,
2825 &HandleInformation
);
2826 if (!NT_SUCCESS(Status
)) return Status
;
2828 /* Check information class specific access rights */
2829 switch (FileInformationClass
)
2831 case FileBasicInformation
:
2832 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_ATTRIBUTES
))
2836 case FileDispositionInformation
:
2837 if (!(HandleInformation
.GrantedAccess
& DELETE
))
2841 case FilePositionInformation
:
2842 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2843 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2847 case FileEndOfFileInformation
:
2848 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
))
2858 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2859 ObDereferenceObject(FileObject
);
2860 return STATUS_ACCESS_DENIED
;
2863 DPRINT("FileObject 0x%p\n", FileObject
);
2865 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2866 /* Handle IO Completion Port quickly */
2867 if (FileInformationClass
== FileCompletionInformation
)
2870 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2871 PIO_COMPLETION_CONTEXT Context
;
2873 if (Length
< sizeof(FILE_COMPLETION_INFORMATION
))
2875 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2879 /* Reference the Port */
2880 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2881 IO_COMPLETION_MODIFY_STATE
,
2886 if (NT_SUCCESS(Status
))
2888 /* Allocate the Context */
2889 Context
= ExAllocatePoolWithTag(PagedPool
,
2890 sizeof(IO_COMPLETION_CONTEXT
),
2891 TAG('I', 'o', 'C', 'p'));
2894 Context
->Key
= CompletionInfo
->Key
;
2895 Context
->Port
= Queue
;
2896 FileObject
->CompletionContext
= Context
;
2898 /* Dereference the Port now */
2899 ObDereferenceObject(Queue
);
2903 /* Complete the I/O */
2904 ObDereferenceObject(FileObject
);
2908 /* Check if this is a direct open or not */
2909 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2911 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2915 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2918 /* Check if we should use Sync IO or not */
2919 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2921 /* Use File Object event */
2922 KeClearEvent(&FileObject
->Event
);
2926 /* Use local event */
2927 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2931 /* Allocate the IRP */
2932 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2934 ObDereferenceObject(FileObject
);
2935 return STATUS_INSUFFICIENT_RESOURCES
;
2938 /* Allocate the System Buffer */
2939 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2944 ObDereferenceObject(FileObject
);
2945 return STATUS_INSUFFICIENT_RESOURCES
;
2948 /* Copy the data inside */
2949 MmSafeCopyFromUser(Irp
->AssociatedIrp
.SystemBuffer
, FileInformation
, Length
);
2951 /* Set up the IRP */
2952 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2953 Irp
->RequestorMode
= PreviousMode
;
2954 Irp
->UserIosb
= IoStatusBlock
;
2955 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2956 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2957 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
2958 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2960 /* Set up Stack Data */
2961 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2962 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2963 StackPtr
->FileObject
= FileObject
;
2965 /* Set the Parameters */
2966 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2967 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2969 /* Call the Driver */
2970 Status
= IoCallDriver(DeviceObject
, Irp
);
2971 if (Status
== STATUS_PENDING
)
2975 KeWaitForSingleObject(&Event
,
2978 FileObject
->Flags
& FO_ALERTABLE_IO
,
2980 Status
= IoStatusBlock
->Status
;
2984 KeWaitForSingleObject(&FileObject
->Event
,
2987 FileObject
->Flags
& FO_ALERTABLE_IO
,
2989 Status
= FileObject
->FinalStatus
;
2993 /* Return the Status */
3002 NtSetQuotaInformationFile(HANDLE FileHandle
,
3003 PIO_STATUS_BLOCK IoStatusBlock
,
3004 PFILE_QUOTA_INFORMATION Buffer
,
3008 return STATUS_NOT_IMPLEMENTED
;
3016 NtUnlockFile(IN HANDLE FileHandle
,
3017 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3018 IN PLARGE_INTEGER ByteOffset
,
3019 IN PLARGE_INTEGER Length
,
3020 OUT PULONG Key OPTIONAL
)
3022 PFILE_OBJECT FileObject
= NULL
;
3023 PLARGE_INTEGER LocalLength
= NULL
;
3025 PIO_STACK_LOCATION StackPtr
;
3026 PDEVICE_OBJECT DeviceObject
;
3028 BOOLEAN LocalEvent
= FALSE
;
3029 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3030 NTSTATUS Status
= STATUS_SUCCESS
;
3031 OBJECT_HANDLE_INFORMATION HandleInformation
;
3033 /* FIXME: instead of this, use SEH */
3034 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
3036 /* Get File Object */
3037 Status
= ObReferenceObjectByHandle(FileHandle
,
3041 (PVOID
*)&FileObject
,
3042 &HandleInformation
);
3043 if (!NT_SUCCESS(Status
)) return Status
;
3045 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
3046 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3048 DPRINT1("Invalid access rights\n");
3049 ObDereferenceObject(FileObject
);
3050 return STATUS_ACCESS_DENIED
;
3053 /* Check if this is a direct open or not */
3054 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3056 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3060 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3063 /* Check if we should use Sync IO or not */
3064 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3066 /* Use File Object event */
3067 KeClearEvent(&FileObject
->Event
);
3071 /* Use local event */
3072 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3076 /* Allocate the IRP */
3077 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
3079 ObDereferenceObject(FileObject
);
3080 return STATUS_INSUFFICIENT_RESOURCES
;
3083 /* Allocate local buffer */
3084 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3085 sizeof(LARGE_INTEGER
),
3090 ObDereferenceObject(FileObject
);
3091 return STATUS_INSUFFICIENT_RESOURCES
;
3093 *LocalLength
= *Length
;
3095 /* Set up the IRP */
3096 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3097 Irp
->RequestorMode
= PreviousMode
;
3098 Irp
->UserIosb
= IoStatusBlock
;
3099 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
3100 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3101 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3103 /* Set up Stack Data */
3104 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3105 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3106 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3107 StackPtr
->FileObject
= FileObject
;
3109 /* Set Parameters */
3110 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3111 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
3112 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
3114 /* Call the Driver */
3115 Status
= IoCallDriver(DeviceObject
, Irp
);
3116 if (Status
== STATUS_PENDING
)
3120 KeWaitForSingleObject(&Event
,
3123 FileObject
->Flags
& FO_ALERTABLE_IO
,
3125 Status
= IoStatusBlock
->Status
;
3129 KeWaitForSingleObject(&FileObject
->Event
,
3132 FileObject
->Flags
& FO_ALERTABLE_IO
,
3134 Status
= FileObject
->FinalStatus
;
3138 /* Return the Status */
3158 NtWriteFile (IN HANDLE FileHandle
,
3159 IN HANDLE Event OPTIONAL
,
3160 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3161 IN PVOID ApcContext OPTIONAL
,
3162 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3165 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
3166 IN PULONG Key OPTIONAL
)
3168 OBJECT_HANDLE_INFORMATION HandleInformation
;
3169 NTSTATUS Status
= STATUS_SUCCESS
;
3170 PFILE_OBJECT FileObject
;
3172 PDEVICE_OBJECT DeviceObject
;
3173 PIO_STACK_LOCATION StackPtr
;
3174 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3175 BOOLEAN LocalEvent
= FALSE
;
3176 PKEVENT EventObject
= NULL
;
3178 DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
3179 "IoStatusBlock 0x%p)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
3182 /* Validate User-Mode Buffers */
3183 if(PreviousMode
!= KernelMode
)
3188 ProbeForWrite(IoStatusBlock
,
3189 sizeof(IO_STATUS_BLOCK
),
3192 ProbeForRead(Buffer
,
3199 Status
= _SEH_GetExceptionCode();
3203 if(!NT_SUCCESS(Status
)) return Status
;
3206 /* Get File Object */
3207 Status
= ObReferenceObjectByHandle(FileHandle
,
3211 (PVOID
*)&FileObject
,
3212 &HandleInformation
);
3213 if (!NT_SUCCESS(Status
)) return Status
;
3215 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3216 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)))
3218 DPRINT1("Invalid access rights\n");
3219 ObDereferenceObject(FileObject
);
3220 return STATUS_ACCESS_DENIED
;
3223 /* Check if we got write Access */
3224 if (HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
)
3226 /* Check the Byte Offset */
3228 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
3229 ByteOffset
->u
.HighPart
== 0xffffffff))
3231 /* a valid ByteOffset is required if asynch. op. */
3232 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3234 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3235 ObDereferenceObject(FileObject
);
3236 return STATUS_INVALID_PARAMETER
;
3239 /* Use the Current Byte OFfset */
3240 ByteOffset
= &FileObject
->CurrentByteOffset
;
3243 else if (HandleInformation
.GrantedAccess
& FILE_APPEND_DATA
)
3245 /* a valid ByteOffset is required if asynch. op. */
3246 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3248 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3249 ObDereferenceObject(FileObject
);
3250 return STATUS_INVALID_PARAMETER
;
3253 /* Give the drivers somethign to understand */
3254 ByteOffset
->u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3255 ByteOffset
->u
.HighPart
= 0xffffffff;
3258 /* Check if we got an event */
3262 Status
= ObReferenceObjectByHandle(Event
,
3266 (PVOID
*)&EventObject
,
3268 if (!NT_SUCCESS(Status
))
3270 ObDereferenceObject(FileObject
);
3273 KeClearEvent(EventObject
);
3276 /* Check if this is a direct open or not */
3277 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3279 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3283 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3286 /* Check if we should use Sync IO or not */
3287 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3289 /* Use File Object event */
3290 KeClearEvent(&FileObject
->Event
);
3300 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
3309 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3314 Status
= _SEH_GetExceptionCode();
3318 /* Cleanup on failure */
3319 if (!NT_SUCCESS(Status
))
3323 ObDereferenceObject(&EventObject
);
3325 ObDereferenceObject(FileObject
);
3329 /* Set up IRP Data */
3330 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3331 Irp
->RequestorMode
= PreviousMode
;
3332 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3333 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3334 Irp
->Flags
|= IRP_WRITE_OPERATION
;
3337 * Vfat doesn't handle non cached files correctly.
3339 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3342 /* Setup Stack Data */
3343 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3344 StackPtr
->FileObject
= FileObject
;
3345 StackPtr
->Parameters
.Write
.Key
= Key
? *Key
: 0;
3346 if (FileObject
->Flags
& FO_WRITE_THROUGH
) StackPtr
->Flags
= SL_WRITE_THROUGH
;
3348 /* Call the Driver */
3349 Status
= IoCallDriver(DeviceObject
, Irp
);
3350 if (Status
== STATUS_PENDING
)
3354 KeWaitForSingleObject(&FileObject
->Event
,
3357 FileObject
->Flags
& FO_ALERTABLE_IO
,
3359 Status
= FileObject
->FinalStatus
;
3363 /* Return the Status */
3381 NtWriteFileGather(IN HANDLE FileHandle
,
3382 IN HANDLE Event OPTIONAL
,
3383 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3384 IN PVOID UserApcContext OPTIONAL
,
3385 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3386 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3387 IN ULONG BufferLength
,
3388 IN PLARGE_INTEGER ByteOffset
,
3389 IN PULONG Key OPTIONAL
)
3392 return(STATUS_NOT_IMPLEMENTED
);