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 ********************************************************/
36 IopLockFileCompletionRoutine(IN PDEVICE_OBJECT DeviceObject
,
41 return STATUS_SUCCESS
;
42 // FIXME: Should I call IoFreeIrp and return STATUS_MORE_PROCESSING_REQUIRED?
59 IopCreateFile(PVOID ObjectBody
,
62 POBJECT_ATTRIBUTES ObjectAttributes
)
64 PDEVICE_OBJECT DeviceObject
;
65 PFILE_OBJECT FileObject
= (PFILE_OBJECT
) ObjectBody
;
66 POBJECT_TYPE ParentObjectType
;
69 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
76 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
77 for the cache manager, so return STATUS_SUCCESS */
78 DPRINT("Parent object was NULL\n");
79 return(STATUS_SUCCESS
);
82 ParentObjectType
= BODY_TO_HEADER(Parent
)->ObjectType
;
84 if (ParentObjectType
!= IoDeviceObjectType
&&
85 ParentObjectType
!= IoFileObjectType
)
87 DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n",
88 &BODY_TO_HEADER(Parent
)->Name
,
89 BODY_TO_HEADER(Parent
)->ObjectType
->TypeName
.Buffer
,
91 return(STATUS_UNSUCCESSFUL
);
94 Status
= ObReferenceObjectByPointer(Parent
,
95 STANDARD_RIGHTS_REQUIRED
,
98 if (!NT_SUCCESS(Status
))
100 CPRINT("Failed to reference parent object %x\n", Parent
);
104 if (ParentObjectType
== IoDeviceObjectType
)
106 /* Parent is a devce object */
107 DeviceObject
= IoGetAttachedDevice((PDEVICE_OBJECT
)Parent
);
108 DPRINT("DeviceObject %x\n", DeviceObject
);
110 if (RemainingPath
== NULL
)
112 FileObject
->Flags
= FileObject
->Flags
| FO_DIRECT_DEVICE_OPEN
;
113 FileObject
->FileName
.Buffer
= 0;
114 FileObject
->FileName
.Length
= FileObject
->FileName
.MaximumLength
= 0;
118 if ((DeviceObject
->DeviceType
!= FILE_DEVICE_FILE_SYSTEM
)
119 && (DeviceObject
->DeviceType
!= FILE_DEVICE_DISK
)
120 && (DeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
)
121 && (DeviceObject
->DeviceType
!= FILE_DEVICE_TAPE
)
122 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
)
123 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
124 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
126 CPRINT("Device was wrong type\n");
127 return(STATUS_UNSUCCESSFUL
);
130 if (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
131 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
132 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
134 if (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
136 DPRINT("Mount the logical volume\n");
137 Status
= IoMountVolume(DeviceObject
, FALSE
);
138 DPRINT("Status %x\n", Status
);
139 if (!NT_SUCCESS(Status
))
141 CPRINT("Failed to mount logical volume (Status %x)\n",
146 DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
147 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
149 RtlpCreateUnicodeString(&(FileObject
->FileName
),
150 RemainingPath
, NonPagedPool
);
155 /* Parent is a file object */
156 if (RemainingPath
== NULL
)
158 CPRINT("Device is unnamed\n");
159 return STATUS_UNSUCCESSFUL
;
162 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
163 DPRINT("DeviceObject %x\n", DeviceObject
);
165 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
167 RtlpCreateUnicodeString(&(FileObject
->FileName
),
168 RemainingPath
, NonPagedPool
);
171 DPRINT("FileObject->FileName %wZ\n",
172 &FileObject
->FileName
);
173 FileObject
->DeviceObject
= DeviceObject
;
174 DPRINT("FileObject %x DeviceObject %x\n",
177 FileObject
->Vpb
= DeviceObject
->Vpb
;
178 FileObject
->Type
= IO_TYPE_FILE
;
180 return(STATUS_SUCCESS
);
185 IopDeleteFile(PVOID ObjectBody
)
187 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
189 PIO_STACK_LOCATION StackPtr
;
192 PDEVICE_OBJECT DeviceObject
;
194 DPRINT("IopDeleteFile()\n");
196 if (FileObject
->DeviceObject
)
198 /* Check if this is a direct open or not */
199 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
201 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
205 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
208 /* Clear and set up Events */
209 KeClearEvent(&FileObject
->Event
);
210 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
212 /* Allocate an IRP */
213 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
216 Irp
->UserEvent
= &Event
;
217 Irp
->UserIosb
= &Irp
->IoStatus
;
218 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
219 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
220 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
222 /* Set up Stack Pointer Data */
223 StackPtr
= IoGetNextIrpStackLocation(Irp
);
224 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
225 StackPtr
->DeviceObject
= DeviceObject
;
226 StackPtr
->FileObject
= FileObject
;
228 /* Call the FS Driver */
229 Status
= IoCallDriver(DeviceObject
, Irp
);
231 /* Wait for completion */
232 if (Status
== STATUS_PENDING
)
234 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
240 /* Clear the file name */
241 if (FileObject
->FileName
.Buffer
)
243 ExFreePool(FileObject
->FileName
.Buffer
);
244 FileObject
->FileName
.Buffer
= NULL
;
247 /* Free the completion context */
248 if (FileObject
->CompletionContext
)
250 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
251 ExFreePool(FileObject
->CompletionContext
);
257 IopSecurityFile(PVOID ObjectBody
,
258 SECURITY_OPERATION_CODE OperationCode
,
259 SECURITY_INFORMATION SecurityInformation
,
260 PSECURITY_DESCRIPTOR SecurityDescriptor
,
263 IO_STATUS_BLOCK IoStatusBlock
;
264 PIO_STACK_LOCATION StackPtr
;
265 PFILE_OBJECT FileObject
;
266 PDEVICE_OBJECT DeviceObject
;
269 BOOLEAN LocalEvent
= FALSE
;
271 NTSTATUS Status
= STATUS_SUCCESS
;
273 DPRINT("IopSecurityFile() called\n");
275 FileObject
= (PFILE_OBJECT
)ObjectBody
;
277 if (OperationCode
== QuerySecurityDescriptor
)
279 MajorFunction
= IRP_MJ_QUERY_SECURITY
;
280 DPRINT("Query security descriptor\n");
282 else if (OperationCode
== DeleteSecurityDescriptor
)
285 return STATUS_SUCCESS
;
287 else if (OperationCode
== AssignSecurityDescriptor
)
289 /* If this is a direct open, we can assign it */
290 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
292 /* Get the Device Object */
294 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
296 /* Assign the Security Descriptor */
297 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
299 return STATUS_SUCCESS
;
303 MajorFunction
= IRP_MJ_SET_SECURITY
;
304 DPRINT("Set security descriptor\n");
306 /* If this is a direct open, we can set it */
307 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
309 DPRINT1("Set SD unimplemented for Devices\n");
310 return STATUS_SUCCESS
;
314 /* Get the Device Object */
315 DPRINT1("FileObject: %p\n", FileObject
);
316 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
318 /* Check if we should use Sync IO or not */
319 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
321 /* Use File Object event */
322 KeClearEvent(&FileObject
->Event
);
326 /* Use local event */
327 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
331 /* Allocate the IRP */
332 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
335 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
336 Irp
->RequestorMode
= ExGetPreviousMode();
337 Irp
->UserIosb
= &IoStatusBlock
;
338 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
339 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
340 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
342 /* Set Stack Parameters */
343 StackPtr
= IoGetNextIrpStackLocation(Irp
);
344 StackPtr
->FileObject
= FileObject
;
347 if (OperationCode
== QuerySecurityDescriptor
)
349 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
= SecurityInformation
;
350 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
351 Irp
->UserBuffer
= SecurityDescriptor
;
355 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
= SecurityInformation
;
356 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
= SecurityDescriptor
;
359 /* Call the Driver */
360 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
362 if (Status
== STATUS_PENDING
)
366 KeWaitForSingleObject(&Event
,
369 FileObject
->Flags
& FO_ALERTABLE_IO
,
371 Status
= IoStatusBlock
.Status
;
375 KeWaitForSingleObject(&FileObject
->Event
,
378 FileObject
->Flags
& FO_ALERTABLE_IO
,
380 Status
= FileObject
->FinalStatus
;
384 /* This Driver doesn't implement Security, so try to give it a default */
385 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
387 if (OperationCode
== QuerySecurityDescriptor
)
389 /* Set a World Security Descriptor */
390 Status
= SeSetWorldSecurityDescriptor(SecurityInformation
,
396 /* It wasn't a query, so just fake success */
397 Status
= STATUS_SUCCESS
;
400 else if (OperationCode
== QuerySecurityDescriptor
)
403 *BufferLength
= IoStatusBlock
.Information
;
412 IopQueryNameFile(PVOID ObjectBody
,
413 POBJECT_NAME_INFORMATION ObjectNameInfo
,
418 PFILE_OBJECT FileObject
;
419 ULONG LocalReturnLength
;
422 DPRINT1("IopQueryNameFile() called\n");
424 FileObject
= (PFILE_OBJECT
)ObjectBody
;
426 /* Allocate Buffer */
427 LocalInfo
= ExAllocatePool(PagedPool
,
428 sizeof(OBJECT_NAME_INFORMATION
) +
429 MAX_PATH
* sizeof(WCHAR
));
430 if (LocalInfo
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
433 Status
= ObQueryNameString(FileObject
->DeviceObject
,
435 MAX_PATH
* sizeof(WCHAR
),
437 if (!NT_SUCCESS (Status
))
439 ExFreePool (LocalInfo
);
442 DPRINT ("Device path: %wZ\n", &LocalInfo
->Name
);
444 /* Write Device Path */
445 Status
= RtlAppendUnicodeStringToString(&ObjectNameInfo
->Name
,
446 &((POBJECT_NAME_INFORMATION
)LocalInfo
)->Name
);
448 /* Query the File name */
449 Status
= IoQueryFileInformation(FileObject
,
454 if (Status
!= STATUS_SUCCESS
)
456 ExFreePool(LocalInfo
);
461 Status
= RtlAppendUnicodeToString(&ObjectNameInfo
->Name
,
462 ((PFILE_NAME_INFORMATION
)LocalInfo
)->FileName
);
463 DPRINT ("Total path: %wZ\n", &ObjectNameInfo
->Name
);
465 /* Free buffer and return */
466 ExFreePool(LocalInfo
);
472 IopCloseFile(PVOID ObjectBody
,
475 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
478 PIO_STACK_LOCATION StackPtr
;
480 PDEVICE_OBJECT DeviceObject
;
482 DPRINT("IopCloseFile()\n");
484 if (HandleCount
> 1 || FileObject
->DeviceObject
== NULL
) return;
486 /* Check if this is a direct open or not */
487 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
489 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
493 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
496 /* Clear and set up Events */
497 KeClearEvent(&FileObject
->Event
);
498 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
500 /* Allocate an IRP */
501 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
504 Irp
->UserEvent
= &Event
;
505 Irp
->UserIosb
= &Irp
->IoStatus
;
506 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
507 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
508 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
510 /* Set up Stack Pointer Data */
511 StackPtr
= IoGetNextIrpStackLocation(Irp
);
512 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
513 StackPtr
->FileObject
= FileObject
;
515 /* Call the FS Driver */
516 Status
= IoCallDriver(DeviceObject
, Irp
);
518 /* Wait for completion */
519 if (Status
== STATUS_PENDING
)
521 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
526 /* FUNCTIONS *****************************************************************/
533 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
535 IN BOOLEAN SetOperation
)
538 return STATUS_NOT_IMPLEMENTED
;
546 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
547 IN ULONG QuotaLength
,
548 OUT PULONG ErrorOffset
)
551 return STATUS_NOT_IMPLEMENTED
;
559 * Either causes a new file or directory to be created, or it
560 * opens an existing file, device, directory or volume, giving
561 * the caller a handle for the file object. This handle can be
562 * used by subsequent calls to manipulate data within the file
563 * or the file object's state of attributes.
567 * Points to a variable which receives the file handle
571 * Desired access to the file;
574 * Structure describing the file;
576 * IoStatusBlock (OUT)
577 * Receives information about the operation on return;
579 * AllocationSize [OPTIONAL]
580 * Initial size of the file in bytes;
583 * Attributes to create the file with;
586 * Type of shared access the caller would like to the
590 * Specifies what to do, depending on whether the
591 * file already exists;
594 * Options for creating a new file;
596 * EaBuffer [OPTIONAL]
603 * Type of file (normal, named pipe, mailslot) to create;
605 * ExtraCreateParameters [OPTIONAL]
606 * Additional creation data for named pipe and mailsots;
615 * Prototype taken from Bo Branten's ntifs.h v15.
616 * Description taken from old NtCreateFile's which is
617 * now a wrapper of this call.
625 IoCreateFile(OUT PHANDLE FileHandle
,
626 IN ACCESS_MASK DesiredAccess
,
627 IN POBJECT_ATTRIBUTES ObjectAttributes
,
628 OUT PIO_STATUS_BLOCK IoStatusBlock
,
629 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
630 IN ULONG FileAttributes
,
631 IN ULONG ShareAccess
,
632 IN ULONG CreateDisposition
,
633 IN ULONG CreateOptions
,
634 IN PVOID EaBuffer OPTIONAL
,
636 IN CREATE_FILE_TYPE CreateFileType
,
637 IN PVOID ExtraCreateParameters OPTIONAL
,
640 PFILE_OBJECT FileObject
= NULL
;
641 PDEVICE_OBJECT DeviceObject
;
643 PIO_STACK_LOCATION StackLoc
;
644 IO_SECURITY_CONTEXT SecurityContext
;
645 KPROCESSOR_MODE AccessMode
;
647 IO_STATUS_BLOCK LocalIoStatusBlock
;
648 LARGE_INTEGER SafeAllocationSize
;
649 PVOID SystemEaBuffer
= NULL
;
650 NTSTATUS Status
= STATUS_SUCCESS
;
652 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
653 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
654 FileHandle
,DesiredAccess
,ObjectAttributes
,
655 ObjectAttributes
->ObjectName
->Buffer
);
657 ASSERT_IRQL(PASSIVE_LEVEL
);
659 if (IoStatusBlock
== NULL
|| FileHandle
== NULL
)
660 return STATUS_ACCESS_VIOLATION
;
664 if(Options
& IO_NO_PARAMETER_CHECKING
)
665 AccessMode
= KernelMode
;
667 AccessMode
= ExGetPreviousMode();
669 if(AccessMode
!= KernelMode
)
673 ProbeForWrite(FileHandle
,
676 ProbeForWrite(IoStatusBlock
,
677 sizeof(IO_STATUS_BLOCK
),
679 if(AllocationSize
!= NULL
)
681 ProbeForRead(AllocationSize
,
682 sizeof(LARGE_INTEGER
),
684 SafeAllocationSize
= *AllocationSize
;
687 SafeAllocationSize
.QuadPart
= 0;
689 if(EaBuffer
!= NULL
&& EaLength
> 0)
691 ProbeForRead(EaBuffer
,
695 /* marshal EaBuffer */
696 SystemEaBuffer
= ExAllocatePool(NonPagedPool
,
698 if(SystemEaBuffer
== NULL
)
700 Status
= STATUS_INSUFFICIENT_RESOURCES
;
704 RtlCopyMemory(SystemEaBuffer
,
711 Status
= _SEH_GetExceptionCode();
715 if(!NT_SUCCESS(Status
))
722 if(AllocationSize
!= NULL
)
723 SafeAllocationSize
= *AllocationSize
;
725 SafeAllocationSize
.QuadPart
= 0;
727 if(EaBuffer
!= NULL
&& EaLength
> 0)
729 SystemEaBuffer
= EaBuffer
;
733 if(Options
& IO_CHECK_CREATE_PARAMETERS
)
735 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
738 if (CreateDisposition
== FILE_OPEN
||
739 CreateDisposition
== FILE_OPEN_IF
)
741 Status
= ObOpenObjectByName(ObjectAttributes
,
748 if (NT_SUCCESS(Status
))
750 Status
= ObReferenceObjectByHandle(LocalHandle
,
754 (PVOID
*)&DeviceObject
,
756 ZwClose(LocalHandle
);
757 if (!NT_SUCCESS(Status
))
761 if (BODY_TO_HEADER(DeviceObject
)->ObjectType
!= IoDeviceObjectType
)
763 ObDereferenceObject (DeviceObject
);
764 return STATUS_OBJECT_NAME_COLLISION
;
767 FileObject
= IoCreateStreamFileObject(NULL
, DeviceObject
);
768 ObDereferenceObject (DeviceObject
);
773 if (FileObject
== NULL
)
775 Status
= ObCreateObject(AccessMode
,
783 (PVOID
*)&FileObject
);
784 if (!NT_SUCCESS(Status
))
786 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
790 RtlMapGenericMask(&DesiredAccess
,
791 BODY_TO_HEADER(FileObject
)->ObjectType
->Mapping
);
793 Status
= ObInsertObject ((PVOID
)FileObject
,
799 if (!NT_SUCCESS(Status
))
801 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
802 ObDereferenceObject (FileObject
);
806 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
808 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
810 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
812 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
815 if (CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
816 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
818 SecurityContext
.SecurityQos
= NULL
; /* ?? */
819 SecurityContext
.AccessState
= NULL
; /* ?? */
820 SecurityContext
.DesiredAccess
= DesiredAccess
;
821 SecurityContext
.FullCreateOptions
= 0; /* ?? */
823 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
824 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
826 DPRINT("FileObject %x\n", FileObject
);
827 DPRINT("FileObject->DeviceObject %x\n", FileObject
->DeviceObject
);
829 * Create a new IRP to hand to
830 * the FS driver: this may fail
831 * due to resource shortage.
833 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
836 ZwClose(LocalHandle
);
837 return STATUS_UNSUCCESSFUL
;
840 //trigger FileObject/Event dereferencing
841 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
842 Irp
->RequestorMode
= AccessMode
;
843 Irp
->UserIosb
= &LocalIoStatusBlock
;
844 Irp
->AssociatedIrp
.SystemBuffer
= SystemEaBuffer
;
845 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
846 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
847 Irp
->UserEvent
= &FileObject
->Event
;
848 Irp
->Overlay
.AllocationSize
= SafeAllocationSize
;
851 * Get the stack location for the new
852 * IRP and prepare it.
854 StackLoc
= IoGetNextIrpStackLocation(Irp
);
855 StackLoc
->MinorFunction
= 0;
856 StackLoc
->Flags
= (UCHAR
)Options
;
857 StackLoc
->Control
= 0;
858 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
859 StackLoc
->FileObject
= FileObject
;
861 switch (CreateFileType
)
864 case CreateFileTypeNone
:
865 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
866 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
867 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
868 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
869 StackLoc
->Parameters
.Create
.FileAttributes
= (USHORT
)FileAttributes
;
870 StackLoc
->Parameters
.Create
.ShareAccess
= (USHORT
)ShareAccess
;
871 StackLoc
->Parameters
.Create
.EaLength
= SystemEaBuffer
!= NULL
? EaLength
: 0;
874 case CreateFileTypeNamedPipe
:
875 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
876 StackLoc
->Parameters
.CreatePipe
.SecurityContext
= &SecurityContext
;
877 StackLoc
->Parameters
.CreatePipe
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
878 StackLoc
->Parameters
.CreatePipe
.Options
|= (CreateDisposition
<< 24);
879 StackLoc
->Parameters
.CreatePipe
.ShareAccess
= (USHORT
)ShareAccess
;
880 StackLoc
->Parameters
.CreatePipe
.Parameters
= ExtraCreateParameters
;
883 case CreateFileTypeMailslot
:
884 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
885 StackLoc
->Parameters
.CreateMailslot
.SecurityContext
= &SecurityContext
;
886 StackLoc
->Parameters
.CreateMailslot
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
887 StackLoc
->Parameters
.CreateMailslot
.Options
|= (CreateDisposition
<< 24);
888 StackLoc
->Parameters
.CreateMailslot
.ShareAccess
= (USHORT
)ShareAccess
;
889 StackLoc
->Parameters
.CreateMailslot
.Parameters
= ExtraCreateParameters
;
894 * Now call the driver and
895 * possibly wait if it can
896 * not complete the request
899 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
900 DPRINT("Status :%x\n", Status
);
902 if (Status
== STATUS_PENDING
)
904 KeWaitForSingleObject(&FileObject
->Event
,
909 Status
= LocalIoStatusBlock
.Status
;
911 if (!NT_SUCCESS(Status
))
913 DPRINT("Failing create request with status %x\n", Status
);
914 FileObject
->DeviceObject
= NULL
;
915 FileObject
->Vpb
= NULL
;
917 ZwClose(LocalHandle
);
923 *FileHandle
= LocalHandle
;
924 *IoStatusBlock
= LocalIoStatusBlock
;
928 Status
= _SEH_GetExceptionCode();
933 /* cleanup EABuffer if captured */
934 if(AccessMode
!= KernelMode
&& SystemEaBuffer
!= NULL
)
936 ExFreePool(SystemEaBuffer
);
939 ASSERT_IRQL(PASSIVE_LEVEL
);
941 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle
));
951 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
952 IN ACCESS_MASK DesiredAccess
,
953 IN POBJECT_ATTRIBUTES ObjectAttributes
,
954 OUT PIO_STATUS_BLOCK IoStatusBlock
,
955 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
956 IN ULONG FileAttributes
,
957 IN ULONG ShareAccess
,
958 IN ULONG Disposition
,
959 IN ULONG CreateOptions
,
960 IN PVOID EaBuffer OPTIONAL
,
962 IN CREATE_FILE_TYPE CreateFileType
,
963 IN PVOID ExtraCreateParameters OPTIONAL
,
965 IN PVOID DeviceObject
)
968 return STATUS_NOT_IMPLEMENTED
;
973 * IoCreateStreamFileObject@8
994 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
995 PDEVICE_OBJECT DeviceObject
)
997 PFILE_OBJECT CreatedFileObject
;
1000 /* FIXME: This function should call ObInsertObject. The "Lite" version
1001 doesnt. This function is also called from IoCreateFile for some
1002 reason. These hacks need to be removed.
1005 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
1006 FileObject
, DeviceObject
);
1009 /* Create the File Object */
1010 Status
= ObCreateObject(KernelMode
,
1015 sizeof(FILE_OBJECT
),
1018 (PVOID
*)&CreatedFileObject
);
1019 if (!NT_SUCCESS(Status
))
1021 DPRINT1("Could not create FileObject\n");
1025 /* Choose Device Object */
1026 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1027 DPRINT("DeviceObject %x\n", DeviceObject
);
1030 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1032 /* Set File Object Data */
1033 CreatedFileObject
->DeviceObject
= DeviceObject
;
1034 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
1035 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1037 CreatedFileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
1038 //CreatedFileObject->Flags = FO_STREAM_FILE;
1040 /* Initialize Lock and Event */
1041 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
1042 KeInitializeEvent(&CreatedFileObject
->Lock
, SynchronizationEvent
, TRUE
);
1045 return CreatedFileObject
;
1053 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1054 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1055 OUT PHANDLE FileObjectHandle OPTIONAL
)
1066 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1067 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1078 IoGetFileObjectGenericMapping(VOID
)
1080 return &IopFileMapping
;
1088 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
1090 /* Return the flag status */
1091 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
1099 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
1100 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
1103 return STATUS_NOT_IMPLEMENTED
;
1111 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1112 IN FILE_INFORMATION_CLASS FileInformationClass
,
1114 OUT PVOID FileInformation
,
1115 OUT PULONG ReturnedLength
)
1117 IO_STATUS_BLOCK IoStatusBlock
;
1119 PDEVICE_OBJECT DeviceObject
;
1120 PIO_STACK_LOCATION StackPtr
;
1121 BOOLEAN LocalEvent
= FALSE
;
1125 ASSERT(FileInformation
!= NULL
);
1127 Status
= ObReferenceObjectByPointer(FileObject
,
1128 FILE_READ_ATTRIBUTES
,
1131 if (!NT_SUCCESS(Status
)) return(Status
);
1133 DPRINT("FileObject %x\n", FileObject
);
1135 /* Get the Device Object */
1136 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1138 /* Check if we should use Sync IO or not */
1139 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1141 /* Use File Object event */
1142 KeClearEvent(&FileObject
->Event
);
1146 /* Use local event */
1147 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1151 /* Allocate the IRP */
1152 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1155 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1156 Irp
->RequestorMode
= KernelMode
;
1157 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1158 Irp
->UserIosb
= &IoStatusBlock
;
1159 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1160 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1161 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1163 /* Set the Stack Data */
1164 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1165 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1166 StackPtr
->FileObject
= FileObject
;
1168 /* Set Parameters */
1169 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1170 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1172 /* Call the Driver */
1173 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
1175 if (Status
== STATUS_PENDING
)
1179 KeWaitForSingleObject(&Event
,
1182 FileObject
->Flags
& FO_ALERTABLE_IO
,
1184 Status
= IoStatusBlock
.Status
;
1188 KeWaitForSingleObject(&FileObject
->Event
,
1191 FileObject
->Flags
& FO_ALERTABLE_IO
,
1193 Status
= FileObject
->FinalStatus
;
1198 /* Return the Length and Status. ReturnedLength is NOT optional */
1199 *ReturnedLength
= IoStatusBlock
.Information
;
1208 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
1212 return STATUS_NOT_IMPLEMENTED
;
1216 * @name NtCancelIoFile
1218 * Cancel all pending I/O operations in the current thread for specified
1222 * Handle to file object to cancel requests for. No specific
1223 * access rights are needed.
1224 * @param IoStatusBlock
1225 * Pointer to status block which is filled with final completition
1226 * status on successful return.
1234 NtCancelIoFile(IN HANDLE FileHandle
,
1235 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1238 PFILE_OBJECT FileObject
;
1240 PLIST_ENTRY IrpEntry
;
1243 BOOLEAN OurIrpsInList
= FALSE
;
1244 LARGE_INTEGER Interval
;
1246 if ((ULONG_PTR
)IoStatusBlock
>= MmUserProbeAddress
&&
1247 KeGetPreviousMode() == UserMode
)
1248 return STATUS_ACCESS_VIOLATION
;
1250 Status
= ObReferenceObjectByHandle(FileHandle
, 0, IoFileObjectType
,
1251 KeGetPreviousMode(), (PVOID
*)&FileObject
,
1253 if (!NT_SUCCESS(Status
))
1256 /* IRP cancellations are synchronized at APC_LEVEL. */
1257 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1260 * Walk the list of active IRPs and cancel the ones that belong to
1264 Thread
= PsGetCurrentThread();
1265 for (IrpEntry
= Thread
->IrpList
.Flink
;
1266 IrpEntry
!= &Thread
->IrpList
;
1267 IrpEntry
= IrpEntry
->Flink
)
1269 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1270 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1273 /* Don't break here, we want to cancel all IRPs for the file object. */
1274 OurIrpsInList
= TRUE
;
1278 KfLowerIrql(OldIrql
);
1280 while (OurIrpsInList
)
1282 OurIrpsInList
= FALSE
;
1284 /* Wait a short while and then look if all our IRPs were completed. */
1285 Interval
.QuadPart
= -1000000; /* 100 milliseconds */
1286 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1288 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1291 * Look in the list if all IRPs for the specified file object
1292 * are completed (or cancelled). If someone sends a new IRP
1293 * for our file object while we're here we can happily loop
1297 for (IrpEntry
= Thread
->IrpList
.Flink
;
1298 IrpEntry
!= &Thread
->IrpList
;
1299 IrpEntry
= IrpEntry
->Flink
)
1301 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1302 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1304 OurIrpsInList
= TRUE
;
1309 KfLowerIrql(OldIrql
);
1314 IoStatusBlock
->Status
= STATUS_SUCCESS
;
1315 IoStatusBlock
->Information
= 0;
1316 Status
= STATUS_SUCCESS
;
1320 Status
= STATUS_UNSUCCESSFUL
;
1324 ObDereferenceObject(FileObject
);
1334 * Entry point to call IoCreateFile with
1335 * default parameters.
1345 * Code originally in NtCreateFile moved in IoCreateFile.
1351 NtCreateFile(PHANDLE FileHandle
,
1352 ACCESS_MASK DesiredAccess
,
1353 POBJECT_ATTRIBUTES ObjectAttributes
,
1354 PIO_STATUS_BLOCK IoStatusBlock
,
1355 PLARGE_INTEGER AllocateSize
,
1356 ULONG FileAttributes
,
1358 ULONG CreateDisposition
,
1359 ULONG CreateOptions
,
1363 /* Call the I/O Function */
1364 return IoCreateFile(FileHandle
,
1382 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
1383 IN ACCESS_MASK DesiredAccess
,
1384 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1385 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1386 IN ULONG CreateOptions
,
1387 IN ULONG MailslotQuota
,
1388 IN ULONG MaxMessageSize
,
1389 IN PLARGE_INTEGER TimeOut
)
1391 MAILSLOT_CREATE_PARAMETERS Buffer
;
1393 DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
1394 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1395 FileHandle
,DesiredAccess
,ObjectAttributes
,
1396 ObjectAttributes
->ObjectName
->Buffer
);
1399 /* Check for Timeout */
1403 Buffer
.TimeoutSpecified
= TRUE
;
1405 /* FIXME: Add SEH */
1406 Buffer
.ReadTimeout
= *TimeOut
;
1411 Buffer
.TimeoutSpecified
= FALSE
;
1415 Buffer
.MailslotQuota
= MailslotQuota
;
1416 Buffer
.MaximumMessageSize
= MaxMessageSize
;
1419 return IoCreateFile(FileHandle
,
1424 FILE_ATTRIBUTE_NORMAL
,
1425 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1430 CreateFileTypeMailslot
,
1437 NtCreateNamedPipeFile(PHANDLE FileHandle
,
1438 ACCESS_MASK DesiredAccess
,
1439 POBJECT_ATTRIBUTES ObjectAttributes
,
1440 PIO_STATUS_BLOCK IoStatusBlock
,
1442 ULONG CreateDisposition
,
1443 ULONG CreateOptions
,
1444 ULONG NamedPipeType
,
1446 ULONG CompletionMode
,
1447 ULONG MaximumInstances
,
1449 ULONG OutboundQuota
,
1450 PLARGE_INTEGER DefaultTimeout
)
1452 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
1454 DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
1455 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1456 FileHandle
,DesiredAccess
,ObjectAttributes
,
1457 ObjectAttributes
->ObjectName
->Buffer
);
1460 /* Check for Timeout */
1464 Buffer
.TimeoutSpecified
= TRUE
;
1466 /* FIXME: Add SEH */
1467 Buffer
.DefaultTimeout
= *DefaultTimeout
;
1472 Buffer
.TimeoutSpecified
= FALSE
;
1476 Buffer
.NamedPipeType
= NamedPipeType
;
1477 Buffer
.ReadMode
= ReadMode
;
1478 Buffer
.CompletionMode
= CompletionMode
;
1479 Buffer
.MaximumInstances
= MaximumInstances
;
1480 Buffer
.InboundQuota
= InboundQuota
;
1481 Buffer
.OutboundQuota
= OutboundQuota
;
1484 return IoCreateFile(FileHandle
,
1489 FILE_ATTRIBUTE_NORMAL
,
1495 CreateFileTypeNamedPipe
,
1518 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
1521 return(STATUS_NOT_IMPLEMENTED
);
1526 NtFlushWriteBuffer(VOID
)
1528 KeFlushWriteBuffer();
1529 return STATUS_SUCCESS
;
1533 * FUNCTION: Flushes cached file data to disk
1535 * FileHandle = Points to the file
1536 * IoStatusBlock = Caller must supply storage to receive the result of
1537 * the flush buffers operation. The information field is
1538 * set to number of bytes flushed to disk.
1540 * REMARKS: This function maps to the win32 FlushFileBuffers
1544 NtFlushBuffersFile(IN HANDLE FileHandle
,
1545 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1547 PFILE_OBJECT FileObject
= NULL
;
1549 PIO_STACK_LOCATION StackPtr
;
1551 PDEVICE_OBJECT DeviceObject
;
1553 BOOLEAN LocalEvent
= FALSE
;
1554 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1556 /* Get the File Object */
1557 Status
= ObReferenceObjectByHandle(FileHandle
,
1561 (PVOID
*)&FileObject
,
1563 if (Status
!= STATUS_SUCCESS
) return(Status
);
1565 /* Check if this is a direct open or not */
1566 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1568 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1572 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1575 /* Check if we should use Sync IO or not */
1576 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1578 /* Use File Object event */
1579 KeClearEvent(&FileObject
->Event
);
1583 /* Use local event */
1584 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1588 /* Allocate the IRP */
1589 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
)))
1591 ObDereferenceObject(FileObject
);
1592 return STATUS_INSUFFICIENT_RESOURCES
;
1595 /* Set up the IRP */
1596 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1597 Irp
->RequestorMode
= PreviousMode
;
1598 Irp
->UserIosb
= IoStatusBlock
;
1599 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1600 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1601 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1603 /* Set up Stack Data */
1604 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1605 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1606 StackPtr
->FileObject
= FileObject
;
1608 /* Call the Driver */
1609 Status
= IoCallDriver(DeviceObject
, Irp
);
1610 if (Status
== STATUS_PENDING
)
1614 KeWaitForSingleObject(&Event
,
1617 FileObject
->Flags
& FO_ALERTABLE_IO
,
1619 Status
= IoStatusBlock
->Status
;
1623 KeWaitForSingleObject(&FileObject
->Event
,
1626 FileObject
->Flags
& FO_ALERTABLE_IO
,
1628 Status
= FileObject
->FinalStatus
;
1632 /* Return the Status */
1641 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1642 IN HANDLE Event OPTIONAL
,
1643 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1644 IN PVOID ApcContext OPTIONAL
,
1645 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1647 IN ULONG BufferSize
,
1648 IN ULONG CompletionFilter
,
1649 IN BOOLEAN WatchTree
)
1652 PDEVICE_OBJECT DeviceObject
;
1653 PFILE_OBJECT FileObject
;
1654 PIO_STACK_LOCATION IoStack
;
1655 KPROCESSOR_MODE PreviousMode
;
1656 NTSTATUS Status
= STATUS_SUCCESS
;
1658 DPRINT("NtNotifyChangeDirectoryFile()\n");
1662 PreviousMode
= ExGetPreviousMode();
1664 if(PreviousMode
!= KernelMode
)
1668 ProbeForWrite(IoStatusBlock
,
1669 sizeof(IO_STATUS_BLOCK
),
1673 ProbeForWrite(Buffer
,
1680 Status
= _SEH_GetExceptionCode();
1684 if(!NT_SUCCESS(Status
))
1690 Status
= ObReferenceObjectByHandle(FileHandle
,
1691 FILE_LIST_DIRECTORY
,
1694 (PVOID
*)&FileObject
,
1696 if (Status
!= STATUS_SUCCESS
) return(Status
);
1699 DeviceObject
= FileObject
->DeviceObject
;
1702 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1705 ObDereferenceObject(FileObject
);
1706 return STATUS_UNSUCCESSFUL
;
1711 Event
= &FileObject
->Event
;
1714 /* Trigger FileObject/Event dereferencing */
1715 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1716 Irp
->RequestorMode
= PreviousMode
;
1717 Irp
->UserIosb
= IoStatusBlock
;
1718 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1719 Irp
->UserEvent
= Event
;
1720 KeResetEvent( Event
);
1721 Irp
->UserBuffer
= Buffer
;
1722 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1723 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1725 IoStack
= IoGetNextIrpStackLocation(Irp
);
1727 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1728 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1730 IoStack
->Control
= 0;
1731 IoStack
->DeviceObject
= DeviceObject
;
1732 IoStack
->FileObject
= FileObject
;
1736 IoStack
->Flags
= SL_WATCH_TREE
;
1739 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1740 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1742 Status
= IoCallDriver(FileObject
->DeviceObject
,Irp
);
1744 /* FIXME: Should we wait here or not for synchronously opened files? */
1754 NtLockFile(IN HANDLE FileHandle
,
1755 IN HANDLE EventHandle OPTIONAL
,
1756 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1757 IN PVOID ApcContext OPTIONAL
,
1758 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1759 IN PLARGE_INTEGER ByteOffset
,
1760 IN PLARGE_INTEGER Length
,
1762 IN BOOLEAN FailImmediatedly
,
1763 IN BOOLEAN ExclusiveLock
1766 PFILE_OBJECT FileObject
= NULL
;
1767 PLARGE_INTEGER LocalLength
= NULL
;
1768 PKEVENT Event
= NULL
;
1770 PIO_STACK_LOCATION StackPtr
;
1771 PDEVICE_OBJECT DeviceObject
;
1772 KPROCESSOR_MODE PreviousMode
;
1775 // FIXME: instead of this, use SEH when available?
1776 if (!Length
|| !ByteOffset
)
1778 Status
= STATUS_INVALID_PARAMETER
;
1782 PreviousMode
= ExGetPreviousMode();
1784 Status
= ObReferenceObjectByHandle(FileHandle
,
1788 (PVOID
*)&FileObject
,
1790 if (!NT_SUCCESS(Status
))
1795 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1797 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,
1801 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1805 if (EventHandle
!= NULL
&& !FailImmediatedly
)
1807 Status
= ObReferenceObjectByHandle(EventHandle
,
1813 if (!NT_SUCCESS(Status
))
1820 Event
= &FileObject
->Event
;
1821 KeResetEvent(Event
);
1824 /* Trigger FileObject/Event dereferencing */
1825 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1827 Irp
->RequestorMode
= PreviousMode
;
1828 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1829 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1831 Irp
->UserEvent
= Event
;
1832 Irp
->UserIosb
= IoStatusBlock
;
1833 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1835 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1836 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1837 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1838 StackPtr
->FileObject
= FileObject
;
1841 StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1843 if (FailImmediatedly
)
1844 StackPtr
->Flags
|= SL_FAIL_IMMEDIATELY
;
1846 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1847 sizeof(LARGE_INTEGER
),
1851 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1855 *LocalLength
= *Length
;
1857 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1858 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
1859 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
1861 IoSetCompletionRoutine(Irp
,
1862 IopLockFileCompletionRoutine
,
1868 /* Can't touch FileObject after IoCallDriver since it might be freed */
1869 Status
= IofCallDriver(DeviceObject
, Irp
);
1870 if (Status
== STATUS_PENDING
&& (FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
1872 Status
= KeWaitForSingleObject(Event
,
1875 FileObject
->Flags
& FO_ALERTABLE_IO
,
1878 if (Status
!= STATUS_WAIT_0
)
1880 DPRINT1("NtLockFile -> KeWaitForSingleObject failed!\n");
1882 * FIXME: Should do some special processing here if alertable wait
1883 * was interupted by user apc or a thread alert (STATUS_ALERTED, STATUS_USER_APC)
1885 return Status
; /* Set status to something else? */
1888 Status
= IoStatusBlock
->Status
;
1895 ExFreePool(LocalLength
);
1901 ObDereferenceObject(Event
);
1904 ObDereferenceObject(FileObject
);
1914 * Opens an existing file (simpler than NtCreateFile).
1918 * Variable that receives the file handle on return;
1921 * Access desired by the caller to the file;
1924 * Structue describing the file to be opened;
1926 * IoStatusBlock (OUT)
1927 * Receives details about the result of the
1931 * Type of shared access the caller requires;
1934 * Options for the file open.
1946 NtOpenFile(PHANDLE FileHandle
,
1947 ACCESS_MASK DesiredAccess
,
1948 POBJECT_ATTRIBUTES ObjectAttributes
,
1949 PIO_STATUS_BLOCK IoStatusBlock
,
1953 /* Call the I/O Function */
1954 return IoCreateFile(FileHandle
,
1972 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1973 OUT PFILE_BASIC_INFORMATION FileInformation
)
1975 IO_STATUS_BLOCK IoStatusBlock
;
1980 Status
= ZwOpenFile(&FileHandle
,
1981 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
1984 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1985 FILE_SYNCHRONOUS_IO_NONALERT
);
1986 if (!NT_SUCCESS (Status
))
1988 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
1992 /* Get file attributes */
1993 Status
= ZwQueryInformationFile(FileHandle
,
1996 sizeof(FILE_BASIC_INFORMATION
),
1997 FileBasicInformation
);
1998 if (!NT_SUCCESS (Status
))
2000 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2003 ZwClose(FileHandle
);
2010 * FUNCTION: Queries a directory file.
2012 * FileHandle = Handle to a directory file
2013 * EventHandle = Handle to the event signaled on completion
2014 * ApcRoutine = Asynchroneous procedure callback, called on completion
2015 * ApcContext = Argument to the apc.
2016 * IoStatusBlock = Caller supplies storage for extended status information.
2017 * FileInformation = Caller supplies storage for the resulting information.
2019 * FileNameInformation FILE_NAMES_INFORMATION
2020 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2021 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2022 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2024 * Length = Size of the storage supplied
2025 * FileInformationClass = Indicates the type of information requested.
2026 * ReturnSingleEntry = Specify true if caller only requests the first
2028 * FileName = Initial directory name to query, that may contain wild
2030 * RestartScan = Number of times the action should be repeated
2031 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2032 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2033 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2037 NtQueryDirectoryFile(IN HANDLE FileHandle
,
2038 IN HANDLE PEvent OPTIONAL
,
2039 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2040 IN PVOID ApcContext OPTIONAL
,
2041 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2042 OUT PVOID FileInformation
,
2044 IN FILE_INFORMATION_CLASS FileInformationClass
,
2045 IN BOOLEAN ReturnSingleEntry
,
2046 IN PUNICODE_STRING FileName OPTIONAL
,
2047 IN BOOLEAN RestartScan
)
2050 PDEVICE_OBJECT DeviceObject
;
2051 PFILE_OBJECT FileObject
;
2052 PIO_STACK_LOCATION StackPtr
;
2053 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2054 NTSTATUS Status
= STATUS_SUCCESS
;
2055 BOOLEAN LocalEvent
= FALSE
;
2056 PKEVENT Event
= NULL
;
2058 DPRINT("NtQueryDirectoryFile()\n");
2061 /* Validate User-Mode Buffers */
2062 if(PreviousMode
!= KernelMode
)
2066 ProbeForWrite(IoStatusBlock
,
2067 sizeof(IO_STATUS_BLOCK
),
2069 ProbeForWrite(FileInformation
,
2075 Status
= _SEH_GetExceptionCode();
2079 if(!NT_SUCCESS(Status
)) return Status
;
2082 /* Get File Object */
2083 Status
= ObReferenceObjectByHandle(FileHandle
,
2084 FILE_LIST_DIRECTORY
,
2087 (PVOID
*)&FileObject
,
2089 if (Status
!= STATUS_SUCCESS
) return(Status
);
2091 /* Get Event Object */
2094 Status
= ObReferenceObjectByHandle(PEvent
,
2100 if (Status
!= STATUS_SUCCESS
) return(Status
);
2101 KeClearEvent(Event
);
2104 /* Check if this is a direct open or not */
2105 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2107 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2111 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2114 /* Check if we should use Sync IO or not */
2115 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2117 /* Use File Object event */
2118 KeClearEvent(&FileObject
->Event
);
2125 /* Allocate the IRP */
2126 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
)))
2128 ObDereferenceObject(FileObject
);
2129 return STATUS_INSUFFICIENT_RESOURCES
;
2132 /* Set up the IRP */
2133 Irp
->RequestorMode
= PreviousMode
;
2134 Irp
->UserIosb
= IoStatusBlock
;
2135 Irp
->UserEvent
= Event
;
2136 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2137 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2138 Irp
->UserBuffer
= FileInformation
;
2139 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2140 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2142 /* Set up Stack Data */
2143 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2144 StackPtr
->FileObject
= FileObject
;
2145 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2146 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2148 /* Set Parameters */
2149 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
= FileInformationClass
;
2150 StackPtr
->Parameters
.QueryDirectory
.FileName
= FileName
;
2151 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2152 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2153 StackPtr
->Flags
= 0;
2154 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2155 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2157 /* Call the Driver */
2158 Status
= IoCallDriver(DeviceObject
, Irp
);
2159 if (Status
== STATUS_PENDING
)
2163 KeWaitForSingleObject(&FileObject
->Event
,
2166 FileObject
->Flags
& FO_ALERTABLE_IO
,
2168 Status
= FileObject
->FinalStatus
;
2172 /* Return the Status */
2180 NtQueryEaFile(IN HANDLE FileHandle
,
2181 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2184 IN BOOLEAN ReturnSingleEntry
,
2185 IN PVOID EaList OPTIONAL
,
2186 IN ULONG EaListLength
,
2187 IN PULONG EaIndex OPTIONAL
,
2188 IN BOOLEAN RestartScan
)
2191 return STATUS_NOT_IMPLEMENTED
;
2196 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2197 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2199 IO_STATUS_BLOCK IoStatusBlock
;
2204 Status
= ZwOpenFile(&FileHandle
,
2205 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2208 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2209 FILE_SYNCHRONOUS_IO_NONALERT
);
2210 if (!NT_SUCCESS (Status
))
2212 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2216 /* Get file attributes */
2217 Status
= ZwQueryInformationFile(FileHandle
,
2220 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2221 FileNetworkOpenInformation
);
2222 if (!NT_SUCCESS (Status
))
2224 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2227 ZwClose (FileHandle
);
2235 NtQueryInformationFile(HANDLE FileHandle
,
2236 PIO_STATUS_BLOCK IoStatusBlock
,
2237 PVOID FileInformation
,
2239 FILE_INFORMATION_CLASS FileInformationClass
)
2241 OBJECT_HANDLE_INFORMATION HandleInformation
;
2242 PFILE_OBJECT FileObject
;
2245 PDEVICE_OBJECT DeviceObject
;
2246 PIO_STACK_LOCATION StackPtr
;
2247 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2249 BOOLEAN LocalEvent
= FALSE
;
2250 BOOLEAN Failed
= FALSE
;
2252 ASSERT(IoStatusBlock
!= NULL
);
2253 ASSERT(FileInformation
!= NULL
);
2255 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2256 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2257 Length
, FileInformationClass
);
2259 /* Reference the Handle */
2260 Status
= ObReferenceObjectByHandle(FileHandle
,
2264 (PVOID
*)&FileObject
,
2265 &HandleInformation
);
2266 if (!NT_SUCCESS(Status
)) return Status
;
2268 /* Check information class specific access rights */
2269 switch (FileInformationClass
)
2271 case FileBasicInformation
:
2272 if (!(HandleInformation
.GrantedAccess
& FILE_READ_ATTRIBUTES
))
2276 case FilePositionInformation
:
2277 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2278 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2282 case FileAlignmentInformation
:
2283 if (!(FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
))
2293 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2294 ObDereferenceObject(FileObject
);
2295 return STATUS_ACCESS_DENIED
;
2298 DPRINT("FileObject %x\n", FileObject
);
2300 /* Check if this is a direct open or not */
2301 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2303 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2307 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2310 /* Check if we should use Sync IO or not */
2311 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2313 /* Use File Object event */
2314 KeClearEvent(&FileObject
->Event
);
2318 /* Use local event */
2319 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2323 /* Allocate the IRP */
2324 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
)))
2326 ObDereferenceObject(FileObject
);
2327 return STATUS_INSUFFICIENT_RESOURCES
;
2330 /* Allocate the System Buffer */
2331 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2336 ObDereferenceObject(FileObject
);
2337 return STATUS_INSUFFICIENT_RESOURCES
;
2340 /* Set up the IRP */
2341 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2342 Irp
->RequestorMode
= PreviousMode
;
2343 Irp
->UserIosb
= IoStatusBlock
;
2344 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2345 Irp
->UserBuffer
= FileInformation
;
2346 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2347 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
2348 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2350 /* Set up Stack Data */
2351 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2352 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2353 StackPtr
->FileObject
= FileObject
;
2355 /* Set the Parameters */
2356 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2357 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2359 /* Call the Driver */
2360 Status
= IoCallDriver(DeviceObject
, Irp
);
2361 if (Status
== STATUS_PENDING
)
2365 KeWaitForSingleObject(&Event
,
2368 FileObject
->Flags
& FO_ALERTABLE_IO
,
2370 Status
= IoStatusBlock
->Status
;
2374 KeWaitForSingleObject(&FileObject
->Event
,
2377 FileObject
->Flags
& FO_ALERTABLE_IO
,
2379 Status
= FileObject
->FinalStatus
;
2383 /* Return the Status */
2392 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2393 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2396 IN BOOLEAN ReturnSingleEntry
,
2397 IN PVOID SidList OPTIONAL
,
2398 IN ULONG SidListLength
,
2399 IN PSID StartSid OPTIONAL
,
2400 IN BOOLEAN RestartScan
)
2403 return STATUS_NOT_IMPLEMENTED
;
2422 NtReadFile(IN HANDLE FileHandle
,
2423 IN HANDLE Event OPTIONAL
,
2424 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2425 IN PVOID ApcContext OPTIONAL
,
2426 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2429 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2430 IN PULONG Key OPTIONAL
)
2432 NTSTATUS Status
= STATUS_SUCCESS
;
2433 PFILE_OBJECT FileObject
;
2435 PDEVICE_OBJECT DeviceObject
;
2436 PIO_STACK_LOCATION StackPtr
;
2437 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2438 BOOLEAN LocalEvent
= FALSE
;
2439 PKEVENT EventObject
= NULL
;
2441 DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2442 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2446 /* Validate User-Mode Buffers */
2447 if(PreviousMode
!= KernelMode
)
2451 ProbeForWrite(IoStatusBlock
,
2452 sizeof(IO_STATUS_BLOCK
),
2455 ProbeForWrite(Buffer
,
2462 Status
= _SEH_GetExceptionCode();
2466 if(!NT_SUCCESS(Status
)) return Status
;
2469 /* Get File Object */
2470 Status
= ObReferenceObjectByHandle(FileHandle
,
2474 (PVOID
*)&FileObject
,
2476 if (!NT_SUCCESS(Status
)) return Status
;
2478 /* Check the Byte Offset */
2480 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
2481 ByteOffset
->u
.HighPart
== 0xffffffff))
2483 /* a valid ByteOffset is required if asynch. op. */
2484 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2486 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2487 ObDereferenceObject(FileObject
);
2488 return STATUS_INVALID_PARAMETER
;
2491 /* Use the Current Byte OFfset */
2492 ByteOffset
= &FileObject
->CurrentByteOffset
;
2495 /* Check for event */
2499 Status
= ObReferenceObjectByHandle(Event
,
2503 (PVOID
*)&EventObject
,
2505 if (!NT_SUCCESS(Status
))
2507 ObDereferenceObject(FileObject
);
2510 KeClearEvent(EventObject
);
2513 /* Check if this is a direct open or not */
2514 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2516 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2520 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2523 /* Check if we should use Sync IO or not */
2524 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2526 /* Use File Object event */
2527 KeClearEvent(&FileObject
->Event
);
2534 /* Create the IRP */
2537 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2546 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2551 Status
= _SEH_GetExceptionCode();
2555 /* Cleanup if IRP Allocation Failed */
2556 if (!NT_SUCCESS(Status
))
2558 if (Event
) ObDereferenceObject(EventObject
);
2559 ObDereferenceObject(FileObject
);
2563 /* Set up IRP Data */
2564 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2565 Irp
->RequestorMode
= PreviousMode
;
2566 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2567 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2568 Irp
->Flags
|= IRP_READ_OPERATION
;
2569 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2571 /* Setup Stack Data */
2572 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2573 StackPtr
->FileObject
= FileObject
;
2574 StackPtr
->Parameters
.Read
.Key
= Key
? *Key
: 0;
2576 /* Call the Driver */
2577 Status
= IoCallDriver(DeviceObject
, Irp
);
2578 if (Status
== STATUS_PENDING
)
2582 KeWaitForSingleObject(&FileObject
->Event
,
2585 FileObject
->Flags
& FO_ALERTABLE_IO
,
2587 Status
= FileObject
->FinalStatus
;
2591 /* Return the Status */
2609 NtReadFileScatter(IN HANDLE FileHandle
,
2610 IN HANDLE Event OPTIONAL
,
2611 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2612 IN PVOID UserApcContext OPTIONAL
,
2613 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2614 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2615 IN ULONG BufferLength
,
2616 IN PLARGE_INTEGER ByteOffset
,
2617 IN PULONG Key OPTIONAL
)
2620 return(STATUS_NOT_IMPLEMENTED
);
2628 NtSetEaFile(IN HANDLE FileHandle
,
2629 IN PIO_STATUS_BLOCK IoStatusBlock
,
2631 IN ULONG EaBufferSize
)
2634 return STATUS_NOT_IMPLEMENTED
;
2641 NtSetInformationFile(HANDLE FileHandle
,
2642 PIO_STATUS_BLOCK IoStatusBlock
,
2643 PVOID FileInformation
,
2645 FILE_INFORMATION_CLASS FileInformationClass
)
2647 OBJECT_HANDLE_INFORMATION HandleInformation
;
2648 PIO_STACK_LOCATION StackPtr
;
2649 PFILE_OBJECT FileObject
;
2650 PDEVICE_OBJECT DeviceObject
;
2653 BOOLEAN LocalEvent
= FALSE
;
2654 NTSTATUS Status
= STATUS_SUCCESS
;
2655 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2656 BOOLEAN Failed
= FALSE
;
2658 ASSERT(IoStatusBlock
!= NULL
);
2659 ASSERT(FileInformation
!= NULL
);
2661 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2662 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2663 Length
, FileInformationClass
);
2665 /* Get the file object from the file handle */
2666 Status
= ObReferenceObjectByHandle(FileHandle
,
2670 (PVOID
*)&FileObject
,
2671 &HandleInformation
);
2672 if (!NT_SUCCESS(Status
)) return Status
;
2674 /* Check information class specific access rights */
2675 switch (FileInformationClass
)
2677 case FileBasicInformation
:
2678 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_ATTRIBUTES
))
2682 case FileDispositionInformation
:
2683 if (!(HandleInformation
.GrantedAccess
& DELETE
))
2687 case FilePositionInformation
:
2688 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2689 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2693 case FileEndOfFileInformation
:
2694 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
))
2704 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2705 ObDereferenceObject(FileObject
);
2706 return STATUS_ACCESS_DENIED
;
2709 DPRINT("FileObject %x\n", FileObject
);
2711 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2712 /* Handle IO Completion Port quickly */
2713 if (FileInformationClass
== FileCompletionInformation
)
2716 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2717 PIO_COMPLETION_CONTEXT Context
;
2719 if (Length
< sizeof(FILE_COMPLETION_INFORMATION
))
2721 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2725 /* Reference the Port */
2726 Status
= ObReferenceObjectByHandle(CompletionInfo
->IoCompletionHandle
,
2727 IO_COMPLETION_MODIFY_STATE
,
2732 if (NT_SUCCESS(Status
))
2734 /* Allocate the Context */
2735 Context
= ExAllocatePoolWithTag(PagedPool
,
2736 sizeof(IO_COMPLETION_CONTEXT
),
2737 TAG('I', 'o', 'C', 'p'));
2740 Context
->Key
= CompletionInfo
->CompletionKey
;
2741 Context
->Port
= Queue
;
2742 FileObject
->CompletionContext
= Context
;
2744 /* Dereference the Port now */
2745 ObDereferenceObject(Queue
);
2749 /* Complete the I/O */
2750 ObDereferenceObject(FileObject
);
2754 /* Check if this is a direct open or not */
2755 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2757 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2761 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2764 /* Check if we should use Sync IO or not */
2765 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2767 /* Use File Object event */
2768 KeClearEvent(&FileObject
->Event
);
2772 /* Use local event */
2773 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2777 /* Allocate the IRP */
2778 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
)))
2780 ObDereferenceObject(FileObject
);
2781 return STATUS_INSUFFICIENT_RESOURCES
;
2784 /* Allocate the System Buffer */
2785 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2790 ObDereferenceObject(FileObject
);
2791 return STATUS_INSUFFICIENT_RESOURCES
;
2794 /* Copy the data inside */
2795 MmSafeCopyFromUser(Irp
->AssociatedIrp
.SystemBuffer
, FileInformation
, Length
);
2797 /* Set up the IRP */
2798 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2799 Irp
->RequestorMode
= PreviousMode
;
2800 Irp
->UserIosb
= IoStatusBlock
;
2801 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2802 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2803 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
2804 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2806 /* Set up Stack Data */
2807 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2808 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2809 StackPtr
->FileObject
= FileObject
;
2811 /* Set the Parameters */
2812 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2813 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2815 /* Call the Driver */
2816 Status
= IoCallDriver(DeviceObject
, Irp
);
2817 if (Status
== STATUS_PENDING
)
2821 KeWaitForSingleObject(&Event
,
2824 FileObject
->Flags
& FO_ALERTABLE_IO
,
2826 Status
= IoStatusBlock
->Status
;
2830 KeWaitForSingleObject(&FileObject
->Event
,
2833 FileObject
->Flags
& FO_ALERTABLE_IO
,
2835 Status
= FileObject
->FinalStatus
;
2839 /* Return the Status */
2848 NtSetQuotaInformationFile(HANDLE FileHandle
,
2849 PIO_STATUS_BLOCK IoStatusBlock
,
2850 PFILE_USER_QUOTA_INFORMATION Buffer
,
2854 return STATUS_NOT_IMPLEMENTED
;
2862 NtUnlockFile(IN HANDLE FileHandle
,
2863 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2864 IN PLARGE_INTEGER ByteOffset
,
2865 IN PLARGE_INTEGER Length
,
2866 OUT PULONG Key OPTIONAL
)
2868 PFILE_OBJECT FileObject
= NULL
;
2869 PLARGE_INTEGER LocalLength
= NULL
;
2871 PIO_STACK_LOCATION StackPtr
;
2872 PDEVICE_OBJECT DeviceObject
;
2873 KPROCESSOR_MODE PreviousMode
;
2876 // FIXME: instead of this, use SEH when available
2877 if (!Length
|| !ByteOffset
)
2879 Status
= STATUS_INVALID_PARAMETER
;
2883 PreviousMode
= ExGetPreviousMode();
2886 * BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and mode=UserMode
2887 * It should ONLY fail if we desire an access that conflict with granted access!
2889 Status
= ObReferenceObjectByHandle(FileHandle
,
2890 0, //FILE_READ_DATA,//BUGBUG: have to use something...but shouldn't have to!
2893 (PVOID
*)&FileObject
,
2895 if (!NT_SUCCESS(Status
))
2900 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2902 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,
2906 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2910 /* Trigger FileObject/Event dereferencing */
2911 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2912 Irp
->RequestorMode
= PreviousMode
;
2913 Irp
->UserIosb
= IoStatusBlock
;
2914 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2916 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2917 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2918 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2919 StackPtr
->DeviceObject
= DeviceObject
;
2920 StackPtr
->FileObject
= FileObject
;
2922 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2923 sizeof(LARGE_INTEGER
),
2927 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2931 *LocalLength
= *Length
;
2933 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2934 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
2935 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
2937 /* Allways synchronous */
2938 Status
= IofCallDriver(DeviceObject
, Irp
);
2940 ExFreePool(LocalLength
);
2946 ExFreePool(LocalLength
);
2952 ObDereferenceObject(FileObject
);
2973 NtWriteFile (IN HANDLE FileHandle
,
2974 IN HANDLE Event OPTIONAL
,
2975 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2976 IN PVOID ApcContext OPTIONAL
,
2977 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2980 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2981 IN PULONG Key OPTIONAL
)
2983 OBJECT_HANDLE_INFORMATION HandleInformation
;
2984 NTSTATUS Status
= STATUS_SUCCESS
;
2985 PFILE_OBJECT FileObject
;
2987 PDEVICE_OBJECT DeviceObject
;
2988 PIO_STACK_LOCATION StackPtr
;
2989 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2990 BOOLEAN LocalEvent
= FALSE
;
2991 PKEVENT EventObject
= NULL
;
2993 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2994 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2997 /* Validate User-Mode Buffers */
2998 if(PreviousMode
!= KernelMode
)
3003 ProbeForWrite(IoStatusBlock
,
3004 sizeof(IO_STATUS_BLOCK
),
3007 ProbeForRead(Buffer
,
3014 Status
= _SEH_GetExceptionCode();
3018 if(!NT_SUCCESS(Status
)) return Status
;
3021 /* Get File Object */
3022 Status
= ObReferenceObjectByHandle(FileHandle
,
3026 (PVOID
*)&FileObject
,
3027 &HandleInformation
);
3028 if (!NT_SUCCESS(Status
)) return Status
;
3030 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3031 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)))
3033 DPRINT1("Invalid access rights\n");
3034 ObDereferenceObject(FileObject
);
3035 return STATUS_ACCESS_DENIED
;
3038 /* Check if we got write Access */
3039 if (HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
)
3041 /* Check the Byte Offset */
3043 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
3044 ByteOffset
->u
.HighPart
== 0xffffffff))
3046 /* a valid ByteOffset is required if asynch. op. */
3047 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3049 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3050 ObDereferenceObject(FileObject
);
3051 return STATUS_INVALID_PARAMETER
;
3054 /* Use the Current Byte OFfset */
3055 ByteOffset
= &FileObject
->CurrentByteOffset
;
3058 else if (HandleInformation
.GrantedAccess
& FILE_APPEND_DATA
)
3060 /* a valid ByteOffset is required if asynch. op. */
3061 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3063 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3064 ObDereferenceObject(FileObject
);
3065 return STATUS_INVALID_PARAMETER
;
3068 /* Give the drivers somethign to understand */
3069 ByteOffset
->u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3070 ByteOffset
->u
.HighPart
= 0xffffffff;
3073 /* Check if we got an event */
3077 Status
= ObReferenceObjectByHandle(Event
,
3081 (PVOID
*)&EventObject
,
3083 if (!NT_SUCCESS(Status
))
3085 ObDereferenceObject(FileObject
);
3088 KeClearEvent(EventObject
);
3091 /* Check if this is a direct open or not */
3092 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3094 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3098 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3101 /* Check if we should use Sync IO or not */
3102 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3104 /* Use File Object event */
3105 KeClearEvent(&FileObject
->Event
);
3115 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
3116 FileObject
->DeviceObject
,
3124 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3129 Status
= _SEH_GetExceptionCode();
3133 /* Cleanup on failure */
3134 if (!NT_SUCCESS(Status
))
3138 ObDereferenceObject(&EventObject
);
3140 ObDereferenceObject(FileObject
);
3144 /* Set up IRP Data */
3145 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3146 Irp
->RequestorMode
= PreviousMode
;
3147 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3148 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3149 Irp
->Flags
|= IRP_WRITE_OPERATION
;
3150 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3152 /* Setup Stack Data */
3153 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3154 StackPtr
->FileObject
= FileObject
;
3155 StackPtr
->Parameters
.Write
.Key
= Key
? *Key
: 0;
3156 if (FileObject
->Flags
& FO_WRITE_THROUGH
) StackPtr
->Flags
= SL_WRITE_THROUGH
;
3158 /* Call the Driver */
3159 Status
= IoCallDriver(DeviceObject
, Irp
);
3160 if (Status
== STATUS_PENDING
)
3164 KeWaitForSingleObject(&FileObject
->Event
,
3167 FileObject
->Flags
& FO_ALERTABLE_IO
,
3169 Status
= FileObject
->FinalStatus
;
3173 /* Return the Status */
3191 NtWriteFileGather(IN HANDLE FileHandle
,
3192 IN HANDLE Event OPTIONAL
,
3193 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3194 IN PVOID UserApcContext OPTIONAL
,
3195 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3196 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3197 IN ULONG BufferLength
,
3198 IN PLARGE_INTEGER ByteOffset
,
3199 IN PULONG Key OPTIONAL
)
3202 return(STATUS_NOT_IMPLEMENTED
);