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 RtlCreateUnicodeString(&FileObject
->FileName
, RemainingPath
);
137 /* Parent is a file object */
138 if (RemainingPath
== NULL
)
140 CPRINT("Device is unnamed\n");
141 return STATUS_UNSUCCESSFUL
;
144 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
145 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
147 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
149 RtlCreateUnicodeString(&FileObject
->FileName
, RemainingPath
);
152 DPRINT("FileObject->FileName %wZ\n",
153 &FileObject
->FileName
);
154 FileObject
->DeviceObject
= DeviceObject
;
155 DPRINT("FileObject 0x%p DeviceObject 0x%p\n",
158 FileObject
->Vpb
= DeviceObject
->Vpb
;
159 FileObject
->Type
= IO_TYPE_FILE
;
161 return(STATUS_SUCCESS
);
166 IopDeleteFile(PVOID ObjectBody
)
168 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
170 PIO_STACK_LOCATION StackPtr
;
173 PDEVICE_OBJECT DeviceObject
;
175 DPRINT("IopDeleteFile()\n");
177 if (FileObject
->DeviceObject
)
179 /* Check if this is a direct open or not */
180 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
182 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
186 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
189 /* Clear and set up Events */
190 KeClearEvent(&FileObject
->Event
);
191 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
193 /* Allocate an IRP */
194 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
197 Irp
->UserEvent
= &Event
;
198 Irp
->UserIosb
= &Irp
->IoStatus
;
199 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
200 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
201 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
203 /* Set up Stack Pointer Data */
204 StackPtr
= IoGetNextIrpStackLocation(Irp
);
205 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
206 StackPtr
->DeviceObject
= DeviceObject
;
207 StackPtr
->FileObject
= FileObject
;
209 /* Call the FS Driver */
210 Status
= IoCallDriver(DeviceObject
, Irp
);
212 /* Wait for completion */
213 if (Status
== STATUS_PENDING
)
215 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
221 /* Clear the file name */
222 if (FileObject
->FileName
.Buffer
)
224 ExFreePool(FileObject
->FileName
.Buffer
);
225 FileObject
->FileName
.Buffer
= NULL
;
228 /* Free the completion context */
229 if (FileObject
->CompletionContext
)
231 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
232 ExFreePool(FileObject
->CompletionContext
);
238 IopSecurityFile(PVOID ObjectBody
,
239 SECURITY_OPERATION_CODE OperationCode
,
240 SECURITY_INFORMATION SecurityInformation
,
241 PSECURITY_DESCRIPTOR SecurityDescriptor
,
243 PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
245 PGENERIC_MAPPING GenericMapping
)
247 IO_STATUS_BLOCK IoStatusBlock
;
248 PIO_STACK_LOCATION StackPtr
;
249 PFILE_OBJECT FileObject
;
250 PDEVICE_OBJECT DeviceObject
;
253 BOOLEAN LocalEvent
= FALSE
;
255 NTSTATUS Status
= STATUS_SUCCESS
;
257 DPRINT("IopSecurityFile() called\n");
259 FileObject
= (PFILE_OBJECT
)ObjectBody
;
261 if (OperationCode
== QuerySecurityDescriptor
)
263 MajorFunction
= IRP_MJ_QUERY_SECURITY
;
264 DPRINT("Query security descriptor\n");
266 else if (OperationCode
== DeleteSecurityDescriptor
)
269 return STATUS_SUCCESS
;
271 else if (OperationCode
== AssignSecurityDescriptor
)
273 /* If this is a direct open, we can assign it */
274 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
276 /* Get the Device Object */
278 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
280 /* Assign the Security Descriptor */
281 DeviceObject
->SecurityDescriptor
= SecurityDescriptor
;
283 return STATUS_SUCCESS
;
287 MajorFunction
= IRP_MJ_SET_SECURITY
;
288 DPRINT("Set security descriptor\n");
290 /* If this is a direct open, we can set it */
291 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
293 DPRINT1("Set SD unimplemented for Devices\n");
294 return STATUS_SUCCESS
;
298 /* Get the Device Object */
299 DPRINT1("FileObject: %p\n", FileObject
);
300 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
302 /* Check if we should use Sync IO or not */
303 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
305 /* Use File Object event */
306 KeClearEvent(&FileObject
->Event
);
310 /* Use local event */
311 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
315 /* Allocate the IRP */
316 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
319 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
320 Irp
->RequestorMode
= ExGetPreviousMode();
321 Irp
->UserIosb
= &IoStatusBlock
;
322 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
323 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
324 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
326 /* Set Stack Parameters */
327 StackPtr
= IoGetNextIrpStackLocation(Irp
);
328 StackPtr
->MajorFunction
= MajorFunction
;
329 StackPtr
->FileObject
= FileObject
;
332 if (OperationCode
== QuerySecurityDescriptor
)
334 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
= SecurityInformation
;
335 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
336 Irp
->UserBuffer
= SecurityDescriptor
;
340 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
= SecurityInformation
;
341 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
= SecurityDescriptor
;
344 ObReferenceObject(FileObject
);
346 /* Call the Driver */
347 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
349 if (Status
== STATUS_PENDING
)
353 KeWaitForSingleObject(&Event
,
356 FileObject
->Flags
& FO_ALERTABLE_IO
,
358 Status
= IoStatusBlock
.Status
;
362 KeWaitForSingleObject(&FileObject
->Event
,
365 FileObject
->Flags
& FO_ALERTABLE_IO
,
367 Status
= FileObject
->FinalStatus
;
371 /* This Driver doesn't implement Security, so try to give it a default */
372 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
374 if (OperationCode
== QuerySecurityDescriptor
)
376 /* Set a World Security Descriptor */
377 Status
= SeSetWorldSecurityDescriptor(SecurityInformation
,
383 /* It wasn't a query, so just fake success */
384 Status
= STATUS_SUCCESS
;
387 else if (OperationCode
== QuerySecurityDescriptor
)
390 *BufferLength
= IoStatusBlock
.Information
;
399 IopQueryNameFile(PVOID ObjectBody
,
400 POBJECT_NAME_INFORMATION ObjectNameInfo
,
404 POBJECT_NAME_INFORMATION LocalInfo
;
405 PFILE_OBJECT FileObject
;
406 ULONG LocalReturnLength
;
409 DPRINT1("IopQueryNameFile() called\n");
411 FileObject
= (PFILE_OBJECT
)ObjectBody
;
413 /* Allocate Buffer */
414 LocalInfo
= ExAllocatePool(PagedPool
,
415 sizeof(OBJECT_NAME_INFORMATION
) +
416 MAX_PATH
* sizeof(WCHAR
));
417 if (LocalInfo
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
420 Status
= ObQueryNameString(FileObject
->DeviceObject
,
422 MAX_PATH
* sizeof(WCHAR
),
424 if (!NT_SUCCESS (Status
))
426 ExFreePool (LocalInfo
);
429 DPRINT ("Device path: %wZ\n", &LocalInfo
->Name
);
431 /* Write Device Path */
432 Status
= RtlAppendUnicodeStringToString(&ObjectNameInfo
->Name
,
435 /* Query the File name */
436 Status
= IoQueryFileInformation(FileObject
,
441 if (Status
!= STATUS_SUCCESS
)
443 ExFreePool(LocalInfo
);
448 Status
= RtlAppendUnicodeToString(&ObjectNameInfo
->Name
,
449 ((PFILE_NAME_INFORMATION
)LocalInfo
)->FileName
);
450 DPRINT ("Total path: %wZ\n", &ObjectNameInfo
->Name
);
452 /* Free buffer and return */
453 ExFreePool(LocalInfo
);
459 IopCloseFile(PVOID ObjectBody
,
462 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
465 PIO_STACK_LOCATION StackPtr
;
467 PDEVICE_OBJECT DeviceObject
;
469 DPRINT("IopCloseFile()\n");
471 if (HandleCount
> 1 || FileObject
->DeviceObject
== NULL
) return;
473 /* Check if this is a direct open or not */
474 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
476 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
480 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
483 /* Clear and set up Events */
484 KeClearEvent(&FileObject
->Event
);
485 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
487 /* Allocate an IRP */
488 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
491 Irp
->UserEvent
= &Event
;
492 Irp
->UserIosb
= &Irp
->IoStatus
;
493 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
494 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
495 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
497 /* Set up Stack Pointer Data */
498 StackPtr
= IoGetNextIrpStackLocation(Irp
);
499 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
500 StackPtr
->FileObject
= FileObject
;
502 /* Call the FS Driver */
503 Status
= IoCallDriver(DeviceObject
, Irp
);
505 /* Wait for completion */
506 if (Status
== STATUS_PENDING
)
508 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
515 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
516 IN HANDLE Event OPTIONAL
,
517 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
518 IN PVOID UserApcContext OPTIONAL
,
519 OUT PIO_STATUS_BLOCK IoStatusBlock
,
520 IN ULONG IoControlCode
,
521 IN PVOID InputBuffer
,
522 IN ULONG InputBufferLength OPTIONAL
,
523 OUT PVOID OutputBuffer
,
524 IN ULONG OutputBufferLength OPTIONAL
,
527 NTSTATUS Status
= STATUS_SUCCESS
;
528 PFILE_OBJECT FileObject
;
529 PDEVICE_OBJECT DeviceObject
;
531 PIO_STACK_LOCATION StackPtr
;
532 PKEVENT EventObject
= NULL
;
533 BOOLEAN LocalEvent
= FALSE
;
534 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
536 DPRINT("IopDeviceFsIoControl(DeviceHandle 0x%p Event 0x%p UserApcRoutine 0x%p "
537 "UserApcContext 0x%p IoStatusBlock 0x%p IoControlCode %x "
538 "InputBuffer 0x%p InputBufferLength %x OutputBuffer 0x%p "
539 "OutputBufferLength 0x%p)\n",
540 DeviceHandle
,Event
,UserApcRoutine
,UserApcContext
,IoStatusBlock
,
541 IoControlCode
,InputBuffer
,InputBufferLength
,OutputBuffer
,
544 if (IoStatusBlock
== NULL
) return STATUS_ACCESS_VIOLATION
;
546 /* Check granted access against the access rights from IoContolCode */
547 Status
= ObReferenceObjectByHandle(DeviceHandle
,
548 (IoControlCode
>> 14) & 0x3,
551 (PVOID
*) &FileObject
,
553 if (!NT_SUCCESS(Status
)) return Status
;
555 /* Check for an event */
559 Status
= ObReferenceObjectByHandle(Event
,
563 (PVOID
*)&EventObject
,
565 if (!NT_SUCCESS(Status
))
567 ObDereferenceObject (FileObject
);
572 KeClearEvent(EventObject
);
575 /* Check if this is a direct open or not */
576 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
578 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
582 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
585 /* Check if we should use Sync IO or not */
586 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
588 /* Use File Object event */
589 KeClearEvent(&FileObject
->Event
);
593 /* Use local event */
598 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
608 /* Set some extra settings */
609 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
610 Irp
->RequestorMode
= PreviousMode
;
611 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
612 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
613 StackPtr
= IoGetNextIrpStackLocation(Irp
);
614 StackPtr
->FileObject
= FileObject
;
615 StackPtr
->MajorFunction
= IsDevIoCtl
?
616 IRP_MJ_DEVICE_CONTROL
: IRP_MJ_FILE_SYSTEM_CONTROL
;
618 /* Call the Driver */
619 Status
= IoCallDriver(DeviceObject
, Irp
);
620 if (Status
== STATUS_PENDING
)
624 KeWaitForSingleObject(&FileObject
->Event
,
627 FileObject
->Flags
& FO_ALERTABLE_IO
,
629 Status
= FileObject
->FinalStatus
;
633 /* Return the Status */
637 /* FUNCTIONS *****************************************************************/
644 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
646 IN BOOLEAN SetOperation
)
649 return STATUS_NOT_IMPLEMENTED
;
657 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
658 IN ULONG QuotaLength
,
659 OUT PULONG ErrorOffset
)
662 return STATUS_NOT_IMPLEMENTED
;
670 * Either causes a new file or directory to be created, or it
671 * opens an existing file, device, directory or volume, giving
672 * the caller a handle for the file object. This handle can be
673 * used by subsequent calls to manipulate data within the file
674 * or the file object's state of attributes.
678 * Points to a variable which receives the file handle
682 * Desired access to the file;
685 * Structure describing the file;
687 * IoStatusBlock (OUT)
688 * Receives information about the operation on return;
690 * AllocationSize [OPTIONAL]
691 * Initial size of the file in bytes;
694 * Attributes to create the file with;
697 * Type of shared access the caller would like to the
701 * Specifies what to do, depending on whether the
702 * file already exists;
705 * Options for creating a new file;
707 * EaBuffer [OPTIONAL]
714 * Type of file (normal, named pipe, mailslot) to create;
716 * ExtraCreateParameters [OPTIONAL]
717 * Additional creation data for named pipe and mailsots;
726 * Prototype taken from Bo Branten's ntifs.h v15.
727 * Description taken from old NtCreateFile's which is
728 * now a wrapper of this call.
736 IoCreateFile(OUT PHANDLE FileHandle
,
737 IN ACCESS_MASK DesiredAccess
,
738 IN POBJECT_ATTRIBUTES ObjectAttributes
,
739 OUT PIO_STATUS_BLOCK IoStatusBlock
,
740 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
741 IN ULONG FileAttributes
,
742 IN ULONG ShareAccess
,
743 IN ULONG CreateDisposition
,
744 IN ULONG CreateOptions
,
745 IN PVOID EaBuffer OPTIONAL
,
747 IN CREATE_FILE_TYPE CreateFileType
,
748 IN PVOID ExtraCreateParameters OPTIONAL
,
751 PFILE_OBJECT FileObject
= NULL
;
752 PDEVICE_OBJECT DeviceObject
;
754 PEXTENDED_IO_STACK_LOCATION StackLoc
;
755 IO_SECURITY_CONTEXT SecurityContext
;
756 KPROCESSOR_MODE AccessMode
;
758 LARGE_INTEGER SafeAllocationSize
;
759 PVOID SystemEaBuffer
= NULL
;
760 NTSTATUS Status
= STATUS_SUCCESS
;
762 ACCESS_STATE AccessState
;
764 DPRINT("IoCreateFile(FileHandle 0x%p, DesiredAccess %x, "
765 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
766 FileHandle
,DesiredAccess
,ObjectAttributes
,
767 ObjectAttributes
->ObjectName
->Buffer
);
769 ASSERT_IRQL(PASSIVE_LEVEL
);
771 if (IoStatusBlock
== NULL
|| FileHandle
== NULL
)
772 return STATUS_ACCESS_VIOLATION
;
776 if(Options
& IO_NO_PARAMETER_CHECKING
)
777 AccessMode
= KernelMode
;
779 AccessMode
= ExGetPreviousMode();
781 if(AccessMode
!= KernelMode
)
785 ProbeForWriteHandle(FileHandle
);
786 ProbeForWrite(IoStatusBlock
,
787 sizeof(IO_STATUS_BLOCK
),
789 if(AllocationSize
!= NULL
)
791 SafeAllocationSize
= ProbeForReadLargeInteger(AllocationSize
);
794 SafeAllocationSize
.QuadPart
= 0;
796 if(EaBuffer
!= NULL
&& EaLength
> 0)
798 ProbeForRead(EaBuffer
,
802 /* marshal EaBuffer */
803 SystemEaBuffer
= ExAllocatePool(NonPagedPool
,
805 if(SystemEaBuffer
== NULL
)
807 Status
= STATUS_INSUFFICIENT_RESOURCES
;
811 RtlCopyMemory(SystemEaBuffer
,
818 Status
= _SEH_GetExceptionCode();
822 if(!NT_SUCCESS(Status
))
829 if(AllocationSize
!= NULL
)
830 SafeAllocationSize
= *AllocationSize
;
832 SafeAllocationSize
.QuadPart
= 0;
834 if(EaBuffer
!= NULL
&& EaLength
> 0)
836 SystemEaBuffer
= EaBuffer
;
840 if(Options
& IO_CHECK_CREATE_PARAMETERS
)
842 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
845 /* First try to open an existing named object */
846 Status
= ObOpenObjectByName(ObjectAttributes
,
854 if (NT_SUCCESS(Status
))
856 OBJECT_CREATE_INFORMATION ObjectCreateInfo
;
857 OBJECT_ATTRIBUTES tmpObjectAttributes
;
858 UNICODE_STRING ObjectName
;
860 Status
= ObReferenceObjectByHandle(LocalHandle
,
864 (PVOID
*)&DeviceObject
,
866 ZwClose(LocalHandle
);
867 if (!NT_SUCCESS(Status
))
871 if (BODY_TO_HEADER(DeviceObject
)->Type
!= IoDeviceObjectType
)
873 ObDereferenceObject (DeviceObject
);
874 return STATUS_OBJECT_NAME_COLLISION
;
877 Status
= ObpCaptureObjectAttributes(ObjectAttributes
,
882 if (!NT_SUCCESS(Status
))
884 ObDereferenceObject (DeviceObject
);
888 InitializeObjectAttributes(&tmpObjectAttributes
,
890 ObjectCreateInfo
.Attributes
& OBJ_INHERIT
,
893 ObpReleaseCapturedAttributes(&ObjectCreateInfo
);
894 if (ObjectName
.Buffer
) ExFreePool(ObjectName
.Buffer
);
898 Status
= ObCreateObject(KernelMode
,
900 &tmpObjectAttributes
,
906 (PVOID
*)&FileObject
);
909 /* Set File Object Data */
910 FileObject
->DeviceObject
= IoGetAttachedDevice(DeviceObject
);
911 FileObject
->Vpb
= FileObject
->DeviceObject
->Vpb
;
914 FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
915 DPRINT("%wZ\n", ObjectAttributes
->ObjectName
);
917 ObDereferenceObject (DeviceObject
);
921 if (FileObject
== NULL
)
923 Status
= ObCreateObject(AccessMode
,
931 (PVOID
*)&FileObject
);
932 if (!NT_SUCCESS(Status
))
934 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
938 RtlMapGenericMask(&DesiredAccess
,
939 &BODY_TO_HEADER(FileObject
)->Type
->TypeInfo
.GenericMapping
);
941 Status
= ObInsertObject ((PVOID
)FileObject
,
947 if (!NT_SUCCESS(Status
))
949 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
950 ObMakeTemporaryObject(FileObject
);
951 ObDereferenceObject (FileObject
);
955 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
957 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
959 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
961 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
964 if (CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
965 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
968 * FIXME: We should get the access state from Ob once this function becomes
969 * a parse routine once the Ob is refactored.
971 SeCreateAccessState(&AccessState
, &AuxData
, FILE_ALL_ACCESS
, NULL
);
973 SecurityContext
.SecurityQos
= NULL
; /* ?? */
974 SecurityContext
.AccessState
= &AccessState
;
975 SecurityContext
.DesiredAccess
= DesiredAccess
;
976 SecurityContext
.FullCreateOptions
= 0; /* ?? */
978 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
979 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
981 DPRINT("FileObject 0x%p\n", FileObject
);
982 DPRINT("FileObject->DeviceObject 0x%p\n", FileObject
->DeviceObject
);
984 * Create a new IRP to hand to
985 * the FS driver: this may fail
986 * due to resource shortage.
988 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
991 ZwClose(LocalHandle
);
992 return STATUS_UNSUCCESSFUL
;
995 //trigger FileObject/Event dereferencing
996 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
997 Irp
->RequestorMode
= AccessMode
;
998 Irp
->UserIosb
= IoStatusBlock
;
999 Irp
->AssociatedIrp
.SystemBuffer
= SystemEaBuffer
;
1000 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
1001 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1002 Irp
->UserEvent
= &FileObject
->Event
;
1003 Irp
->Overlay
.AllocationSize
= SafeAllocationSize
;
1006 * Get the stack location for the new
1007 * IRP and prepare it.
1009 StackLoc
= (PEXTENDED_IO_STACK_LOCATION
)IoGetNextIrpStackLocation(Irp
);
1010 StackLoc
->MinorFunction
= 0;
1011 StackLoc
->Flags
= (UCHAR
)Options
;
1012 StackLoc
->Control
= 0;
1013 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
1014 StackLoc
->FileObject
= FileObject
;
1016 switch (CreateFileType
)
1019 case CreateFileTypeNone
:
1020 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
1021 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
1022 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
1023 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
1024 StackLoc
->Parameters
.Create
.FileAttributes
= (USHORT
)FileAttributes
;
1025 StackLoc
->Parameters
.Create
.ShareAccess
= (USHORT
)ShareAccess
;
1026 StackLoc
->Parameters
.Create
.EaLength
= SystemEaBuffer
!= NULL
? EaLength
: 0;
1029 case CreateFileTypeNamedPipe
:
1030 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
1031 StackLoc
->Parameters
.CreatePipe
.SecurityContext
= &SecurityContext
;
1032 StackLoc
->Parameters
.CreatePipe
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
1033 StackLoc
->Parameters
.CreatePipe
.Options
|= (CreateDisposition
<< 24);
1034 StackLoc
->Parameters
.CreatePipe
.ShareAccess
= (USHORT
)ShareAccess
;
1035 StackLoc
->Parameters
.CreatePipe
.Parameters
= ExtraCreateParameters
;
1038 case CreateFileTypeMailslot
:
1039 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
1040 StackLoc
->Parameters
.CreateMailslot
.SecurityContext
= &SecurityContext
;
1041 StackLoc
->Parameters
.CreateMailslot
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
1042 StackLoc
->Parameters
.CreateMailslot
.Options
|= (CreateDisposition
<< 24);
1043 StackLoc
->Parameters
.CreateMailslot
.ShareAccess
= (USHORT
)ShareAccess
;
1044 StackLoc
->Parameters
.CreateMailslot
.Parameters
= ExtraCreateParameters
;
1049 * Now call the driver and
1050 * possibly wait if it can
1051 * not complete the request
1054 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
1055 DPRINT("Status :%x\n", Status
);
1057 if (Status
== STATUS_PENDING
)
1059 KeWaitForSingleObject(&FileObject
->Event
,
1064 Status
= IoStatusBlock
->Status
;
1066 if (!NT_SUCCESS(Status
))
1068 DPRINT("Failing create request with status %x\n", Status
);
1069 FileObject
->DeviceObject
= NULL
;
1070 FileObject
->Vpb
= NULL
;
1072 ZwClose(LocalHandle
);
1078 *FileHandle
= LocalHandle
;
1082 Status
= _SEH_GetExceptionCode();
1087 /* cleanup EABuffer if captured */
1088 if(AccessMode
!= KernelMode
&& SystemEaBuffer
!= NULL
)
1090 ExFreePool(SystemEaBuffer
);
1093 ASSERT_IRQL(PASSIVE_LEVEL
);
1095 DPRINT("Finished IoCreateFile() (*FileHandle) 0x%p\n", (*FileHandle
));
1105 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
1106 IN ACCESS_MASK DesiredAccess
,
1107 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1108 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1109 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1110 IN ULONG FileAttributes
,
1111 IN ULONG ShareAccess
,
1112 IN ULONG Disposition
,
1113 IN ULONG CreateOptions
,
1114 IN PVOID EaBuffer OPTIONAL
,
1116 IN CREATE_FILE_TYPE CreateFileType
,
1117 IN PVOID ExtraCreateParameters OPTIONAL
,
1119 IN PVOID DeviceObject
)
1122 return STATUS_NOT_IMPLEMENTED
;
1127 * IoCreateStreamFileObject@8
1148 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
1149 PDEVICE_OBJECT DeviceObject
)
1151 PFILE_OBJECT CreatedFileObject
;
1154 /* FIXME: This function should call ObInsertObject. The "Lite" version
1155 doesnt. This function is also called from IoCreateFile for some
1156 reason. These hacks need to be removed.
1159 DPRINT("IoCreateStreamFileObject(FileObject 0x%p, DeviceObject 0x%p)\n",
1160 FileObject
, DeviceObject
);
1163 /* Create the File Object */
1164 Status
= ObCreateObject(KernelMode
,
1169 sizeof(FILE_OBJECT
),
1172 (PVOID
*)&CreatedFileObject
);
1173 if (!NT_SUCCESS(Status
))
1175 DPRINT1("Could not create FileObject\n");
1179 /* Choose Device Object */
1180 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1181 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1184 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1186 /* Set File Object Data */
1187 CreatedFileObject
->DeviceObject
= DeviceObject
;
1188 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
1189 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1190 CreatedFileObject
->Flags
|= FO_STREAM_FILE
;
1192 /* Initialize Lock and Event */
1193 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
1194 KeInitializeEvent(&CreatedFileObject
->Lock
, SynchronizationEvent
, TRUE
);
1197 return CreatedFileObject
;
1205 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1206 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1207 OUT PHANDLE FileObjectHandle OPTIONAL
)
1218 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1219 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1230 IoGetFileObjectGenericMapping(VOID
)
1232 return &IopFileMapping
;
1240 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
1242 /* Return the flag status */
1243 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
1251 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
1252 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
1255 return STATUS_NOT_IMPLEMENTED
;
1263 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1264 IN FILE_INFORMATION_CLASS FileInformationClass
,
1266 OUT PVOID FileInformation
,
1267 OUT PULONG ReturnedLength
)
1269 IO_STATUS_BLOCK IoStatusBlock
;
1271 PDEVICE_OBJECT DeviceObject
;
1272 PIO_STACK_LOCATION StackPtr
;
1273 BOOLEAN LocalEvent
= FALSE
;
1277 ASSERT(FileInformation
!= NULL
);
1279 Status
= ObReferenceObjectByPointer(FileObject
,
1280 FILE_READ_ATTRIBUTES
,
1283 if (!NT_SUCCESS(Status
)) return(Status
);
1285 DPRINT("FileObject 0x%p\n", FileObject
);
1287 /* Get the Device Object */
1288 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1290 /* Check if we should use Sync IO or not */
1291 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1293 /* Use File Object event */
1294 KeClearEvent(&FileObject
->Event
);
1298 /* Use local event */
1299 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1303 /* Allocate the IRP */
1304 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1307 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1308 Irp
->RequestorMode
= KernelMode
;
1309 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1310 Irp
->UserIosb
= &IoStatusBlock
;
1311 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1312 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1313 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1315 /* Set the Stack Data */
1316 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1317 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1318 StackPtr
->FileObject
= FileObject
;
1320 /* Set Parameters */
1321 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1322 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1324 /* Call the Driver */
1325 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
1327 if (Status
== STATUS_PENDING
)
1331 KeWaitForSingleObject(&Event
,
1334 FileObject
->Flags
& FO_ALERTABLE_IO
,
1336 Status
= IoStatusBlock
.Status
;
1340 KeWaitForSingleObject(&FileObject
->Event
,
1343 FileObject
->Flags
& FO_ALERTABLE_IO
,
1345 Status
= FileObject
->FinalStatus
;
1350 /* Return the Length and Status. ReturnedLength is NOT optional */
1351 *ReturnedLength
= IoStatusBlock
.Information
;
1360 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
1364 return STATUS_NOT_IMPLEMENTED
;
1368 * @name NtCancelIoFile
1370 * Cancel all pending I/O operations in the current thread for specified
1374 * Handle to file object to cancel requests for. No specific
1375 * access rights are needed.
1376 * @param IoStatusBlock
1377 * Pointer to status block which is filled with final completition
1378 * status on successful return.
1386 NtCancelIoFile(IN HANDLE FileHandle
,
1387 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1389 PFILE_OBJECT FileObject
;
1393 BOOLEAN OurIrpsInList
= FALSE
;
1394 LARGE_INTEGER Interval
;
1395 KPROCESSOR_MODE PreviousMode
;
1396 NTSTATUS Status
= STATUS_SUCCESS
;
1400 PreviousMode
= KeGetPreviousMode();
1402 if (PreviousMode
!= KernelMode
)
1406 ProbeForWrite(IoStatusBlock
,
1407 sizeof(IO_STATUS_BLOCK
),
1412 Status
= _SEH_GetExceptionCode();
1416 if (!NT_SUCCESS(Status
)) return Status
;
1419 Status
= ObReferenceObjectByHandle(FileHandle
,
1423 (PVOID
*)&FileObject
,
1425 if (!NT_SUCCESS(Status
))
1428 /* IRP cancellations are synchronized at APC_LEVEL. */
1429 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1432 * Walk the list of active IRPs and cancel the ones that belong to
1436 Thread
= PsGetCurrentThread();
1438 LIST_FOR_EACH(Irp
, &Thread
->IrpList
, IRP
, ThreadListEntry
)
1440 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1443 /* Don't break here, we want to cancel all IRPs for the file object. */
1444 OurIrpsInList
= TRUE
;
1448 KfLowerIrql(OldIrql
);
1450 while (OurIrpsInList
)
1452 OurIrpsInList
= FALSE
;
1454 /* Wait a short while and then look if all our IRPs were completed. */
1455 Interval
.QuadPart
= -1000000; /* 100 milliseconds */
1456 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1458 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1461 * Look in the list if all IRPs for the specified file object
1462 * are completed (or cancelled). If someone sends a new IRP
1463 * for our file object while we're here we can happily loop
1467 LIST_FOR_EACH(Irp
, &Thread
->IrpList
, IRP
, ThreadListEntry
)
1469 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1471 OurIrpsInList
= TRUE
;
1476 KfLowerIrql(OldIrql
);
1481 IoStatusBlock
->Status
= STATUS_SUCCESS
;
1482 IoStatusBlock
->Information
= 0;
1483 Status
= STATUS_SUCCESS
;
1487 Status
= STATUS_UNSUCCESSFUL
;
1491 ObDereferenceObject(FileObject
);
1501 * Entry point to call IoCreateFile with
1502 * default parameters.
1512 * Code originally in NtCreateFile moved in IoCreateFile.
1518 NtCreateFile(PHANDLE FileHandle
,
1519 ACCESS_MASK DesiredAccess
,
1520 POBJECT_ATTRIBUTES ObjectAttributes
,
1521 PIO_STATUS_BLOCK IoStatusBlock
,
1522 PLARGE_INTEGER AllocateSize
,
1523 ULONG FileAttributes
,
1525 ULONG CreateDisposition
,
1526 ULONG CreateOptions
,
1530 /* Call the I/O Function */
1531 return IoCreateFile(FileHandle
,
1549 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
1550 IN ACCESS_MASK DesiredAccess
,
1551 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1552 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1553 IN ULONG CreateOptions
,
1554 IN ULONG MailslotQuota
,
1555 IN ULONG MaxMessageSize
,
1556 IN PLARGE_INTEGER TimeOut
)
1558 MAILSLOT_CREATE_PARAMETERS Buffer
;
1560 DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, "
1561 "ObjectAttributes 0x%p)\n",
1562 FileHandle
,DesiredAccess
,ObjectAttributes
);
1566 /* Check for Timeout */
1567 if (TimeOut
!= NULL
)
1569 if (KeGetPreviousMode() != KernelMode
)
1571 NTSTATUS Status
= STATUS_SUCCESS
;
1575 Buffer
.ReadTimeout
= ProbeForReadLargeInteger(TimeOut
);
1579 Status
= _SEH_GetExceptionCode();
1583 if (!NT_SUCCESS(Status
)) return Status
;
1587 Buffer
.ReadTimeout
= *TimeOut
;
1590 Buffer
.TimeoutSpecified
= TRUE
;
1594 Buffer
.TimeoutSpecified
= FALSE
;
1598 Buffer
.MailslotQuota
= MailslotQuota
;
1599 Buffer
.MaximumMessageSize
= MaxMessageSize
;
1602 return IoCreateFile(FileHandle
,
1607 FILE_ATTRIBUTE_NORMAL
,
1608 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1613 CreateFileTypeMailslot
,
1620 NtCreateNamedPipeFile(PHANDLE FileHandle
,
1621 ACCESS_MASK DesiredAccess
,
1622 POBJECT_ATTRIBUTES ObjectAttributes
,
1623 PIO_STATUS_BLOCK IoStatusBlock
,
1625 ULONG CreateDisposition
,
1626 ULONG CreateOptions
,
1627 ULONG NamedPipeType
,
1629 ULONG CompletionMode
,
1630 ULONG MaximumInstances
,
1632 ULONG OutboundQuota
,
1633 PLARGE_INTEGER DefaultTimeout
)
1635 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
1637 DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, "
1638 "ObjectAttributes 0x%p)\n",
1639 FileHandle
,DesiredAccess
,ObjectAttributes
);
1643 /* Check for Timeout */
1644 if (DefaultTimeout
!= NULL
)
1646 if (KeGetPreviousMode() != KernelMode
)
1648 NTSTATUS Status
= STATUS_SUCCESS
;
1652 Buffer
.DefaultTimeout
= ProbeForReadLargeInteger(DefaultTimeout
);
1656 Status
= _SEH_GetExceptionCode();
1660 if (!NT_SUCCESS(Status
)) return Status
;
1664 Buffer
.DefaultTimeout
= *DefaultTimeout
;
1667 Buffer
.TimeoutSpecified
= TRUE
;
1670 Buffer
.TimeoutSpecified
= FALSE
;
1673 Buffer
.NamedPipeType
= NamedPipeType
;
1674 Buffer
.ReadMode
= ReadMode
;
1675 Buffer
.CompletionMode
= CompletionMode
;
1676 Buffer
.MaximumInstances
= MaximumInstances
;
1677 Buffer
.InboundQuota
= InboundQuota
;
1678 Buffer
.OutboundQuota
= OutboundQuota
;
1681 return IoCreateFile(FileHandle
,
1686 FILE_ATTRIBUTE_NORMAL
,
1692 CreateFileTypeNamedPipe
,
1715 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
1718 return(STATUS_NOT_IMPLEMENTED
);
1726 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1727 IN HANDLE Event OPTIONAL
,
1728 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1729 IN PVOID UserApcContext OPTIONAL
,
1730 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1731 IN ULONG IoControlCode
,
1732 IN PVOID InputBuffer
,
1733 IN ULONG InputBufferLength OPTIONAL
,
1734 OUT PVOID OutputBuffer
,
1735 IN ULONG OutputBufferLength OPTIONAL
)
1737 /* Call the Generic Function */
1738 return IopDeviceFsIoControl(DeviceHandle
,
1756 NtFsControlFile(IN HANDLE DeviceHandle
,
1757 IN HANDLE Event OPTIONAL
,
1758 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1759 IN PVOID UserApcContext OPTIONAL
,
1760 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1761 IN ULONG IoControlCode
,
1762 IN PVOID InputBuffer
,
1763 IN ULONG InputBufferLength OPTIONAL
,
1764 OUT PVOID OutputBuffer
,
1765 IN ULONG OutputBufferLength OPTIONAL
)
1767 return IopDeviceFsIoControl(DeviceHandle
,
1782 NtFlushWriteBuffer(VOID
)
1786 KeFlushWriteBuffer();
1787 return STATUS_SUCCESS
;
1791 * FUNCTION: Flushes cached file data to disk
1793 * FileHandle = Points to the file
1794 * IoStatusBlock = Caller must supply storage to receive the result of
1795 * the flush buffers operation. The information field is
1796 * set to number of bytes flushed to disk.
1798 * REMARKS: This function maps to the win32 FlushFileBuffers
1802 NtFlushBuffersFile(IN HANDLE FileHandle
,
1803 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1805 PFILE_OBJECT FileObject
= NULL
;
1807 PIO_STACK_LOCATION StackPtr
;
1808 NTSTATUS Status
= STATUS_SUCCESS
;
1809 PDEVICE_OBJECT DeviceObject
;
1811 BOOLEAN LocalEvent
= FALSE
;
1812 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
1813 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1814 KPROCESSOR_MODE PreviousMode
;
1818 PreviousMode
= KeGetPreviousMode();
1820 if (PreviousMode
!= KernelMode
)
1824 ProbeForWrite(IoStatusBlock
,
1825 sizeof(IO_STATUS_BLOCK
),
1830 Status
= _SEH_GetExceptionCode();
1834 if (!NT_SUCCESS(Status
)) return Status
;
1837 /* Get the File Object */
1838 Status
= ObReferenceObjectByHandle(FileHandle
,
1842 (PVOID
*)&FileObject
,
1844 if (!NT_SUCCESS(Status
)) return(Status
);
1846 /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1847 granted. However, if this is a named pipe, make sure we don't ask for
1848 FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1850 if (!(FileObject
->Flags
& FO_NAMED_PIPE
))
1851 DesiredAccess
|= FILE_APPEND_DATA
;
1852 if (!RtlAreAnyAccessesGranted(ObjectHandleInfo
.GrantedAccess
,
1855 ObDereferenceObject(FileObject
);
1856 return STATUS_ACCESS_DENIED
;
1859 /* Check if this is a direct open or not */
1860 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1862 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1866 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1869 /* Check if we should use Sync IO or not */
1870 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1872 /* Use File Object event */
1873 KeClearEvent(&FileObject
->Event
);
1877 /* Use local event */
1878 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1882 /* Allocate the IRP */
1883 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
1885 ObDereferenceObject(FileObject
);
1886 return STATUS_INSUFFICIENT_RESOURCES
;
1889 /* Set up the IRP */
1890 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1891 Irp
->RequestorMode
= PreviousMode
;
1892 Irp
->UserIosb
= IoStatusBlock
;
1893 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1894 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1895 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1897 /* Set up Stack Data */
1898 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1899 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1900 StackPtr
->FileObject
= FileObject
;
1902 /* Call the Driver */
1903 Status
= IoCallDriver(DeviceObject
, Irp
);
1904 if (Status
== STATUS_PENDING
)
1908 KeWaitForSingleObject(&Event
,
1911 FileObject
->Flags
& FO_ALERTABLE_IO
,
1913 Status
= IoStatusBlock
->Status
;
1917 KeWaitForSingleObject(&FileObject
->Event
,
1920 FileObject
->Flags
& FO_ALERTABLE_IO
,
1922 Status
= FileObject
->FinalStatus
;
1926 /* Return the Status */
1935 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1936 IN HANDLE Event OPTIONAL
,
1937 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1938 IN PVOID ApcContext OPTIONAL
,
1939 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1941 IN ULONG BufferSize
,
1942 IN ULONG CompletionFilter
,
1943 IN BOOLEAN WatchTree
)
1946 PDEVICE_OBJECT DeviceObject
;
1947 PFILE_OBJECT FileObject
;
1948 PIO_STACK_LOCATION IoStack
;
1949 KPROCESSOR_MODE PreviousMode
;
1950 NTSTATUS Status
= STATUS_SUCCESS
;
1952 DPRINT("NtNotifyChangeDirectoryFile()\n");
1956 PreviousMode
= ExGetPreviousMode();
1958 if(PreviousMode
!= KernelMode
)
1962 ProbeForWrite(IoStatusBlock
,
1963 sizeof(IO_STATUS_BLOCK
),
1967 ProbeForWrite(Buffer
,
1974 Status
= _SEH_GetExceptionCode();
1978 if(!NT_SUCCESS(Status
))
1984 Status
= ObReferenceObjectByHandle(FileHandle
,
1985 FILE_LIST_DIRECTORY
,
1988 (PVOID
*)&FileObject
,
1990 if (Status
!= STATUS_SUCCESS
) return(Status
);
1993 DeviceObject
= FileObject
->DeviceObject
;
1996 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1999 ObDereferenceObject(FileObject
);
2000 return STATUS_UNSUCCESSFUL
;
2005 Event
= &FileObject
->Event
;
2008 /* Trigger FileObject/Event dereferencing */
2009 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2010 Irp
->RequestorMode
= PreviousMode
;
2011 Irp
->UserIosb
= IoStatusBlock
;
2012 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2013 Irp
->UserEvent
= Event
;
2014 KeResetEvent( Event
);
2015 Irp
->UserBuffer
= Buffer
;
2016 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2017 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2019 IoStack
= IoGetNextIrpStackLocation(Irp
);
2021 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2022 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
2024 IoStack
->Control
= 0;
2025 IoStack
->DeviceObject
= DeviceObject
;
2026 IoStack
->FileObject
= FileObject
;
2030 IoStack
->Flags
= SL_WATCH_TREE
;
2033 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
2034 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
2036 Status
= IoCallDriver(FileObject
->DeviceObject
,Irp
);
2038 /* FIXME: Should we wait here or not for synchronously opened files? */
2048 NtLockFile(IN HANDLE FileHandle
,
2049 IN HANDLE EventHandle OPTIONAL
,
2050 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2051 IN PVOID ApcContext OPTIONAL
,
2052 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2053 IN PLARGE_INTEGER ByteOffset
,
2054 IN PLARGE_INTEGER Length
,
2056 IN BOOLEAN FailImmediately
,
2057 IN BOOLEAN ExclusiveLock
)
2059 PFILE_OBJECT FileObject
= NULL
;
2060 PLARGE_INTEGER LocalLength
= NULL
;
2062 PIO_STACK_LOCATION StackPtr
;
2063 PDEVICE_OBJECT DeviceObject
;
2064 PKEVENT Event
= NULL
;
2065 BOOLEAN LocalEvent
= FALSE
;
2066 KPROCESSOR_MODE PreviousMode
;
2067 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2068 NTSTATUS Status
= STATUS_SUCCESS
;
2069 OBJECT_HANDLE_INFORMATION HandleInformation
;
2073 PreviousMode
= KeGetPreviousMode();
2075 CapturedByteOffset
.QuadPart
= 0;
2076 CapturedLength
.QuadPart
= 0;
2078 /* Get File Object */
2079 Status
= ObReferenceObjectByHandle(FileHandle
,
2083 (PVOID
*)&FileObject
,
2084 &HandleInformation
);
2085 if (!NT_SUCCESS(Status
)) return Status
;
2087 if (PreviousMode
!= KernelMode
)
2089 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless
2090 we're in KernelMode! */
2091 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2093 DPRINT1("Invalid access rights\n");
2094 ObDereferenceObject(FileObject
);
2095 return STATUS_ACCESS_DENIED
;
2100 ProbeForWrite(IoStatusBlock
,
2101 sizeof(IO_STATUS_BLOCK
),
2103 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2104 CapturedLength
= ProbeForReadLargeInteger(Length
);
2108 Status
= _SEH_GetExceptionCode();
2112 if (!NT_SUCCESS(Status
))
2114 ObDereferenceObject(FileObject
);
2120 CapturedByteOffset
= *ByteOffset
;
2121 CapturedLength
= *Length
;
2124 /* Get Event Object */
2127 Status
= ObReferenceObjectByHandle(EventHandle
,
2133 if (Status
!= STATUS_SUCCESS
) return(Status
);
2134 KeClearEvent(Event
);
2137 /* Check if this is a direct open or not */
2138 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2140 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2144 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2147 /* Check if we should use Sync IO or not */
2148 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2150 /* Use File Object event */
2151 KeClearEvent(&FileObject
->Event
);
2158 /* Allocate the IRP */
2159 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2161 ObDereferenceObject(FileObject
);
2162 return STATUS_INSUFFICIENT_RESOURCES
;
2165 /* Allocate local buffer */
2166 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2167 sizeof(LARGE_INTEGER
),
2172 ObDereferenceObject(FileObject
);
2173 return STATUS_INSUFFICIENT_RESOURCES
;
2175 *LocalLength
= CapturedLength
;
2177 /* Set up the IRP */
2178 Irp
->RequestorMode
= PreviousMode
;
2179 Irp
->UserIosb
= IoStatusBlock
;
2180 Irp
->UserEvent
= Event
;
2181 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2182 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2184 /* Set up Stack Data */
2185 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2186 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2187 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
2188 StackPtr
->FileObject
= FileObject
;
2190 /* Set Parameters */
2191 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2192 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
2193 StackPtr
->Parameters
.LockControl
.Key
= Key
;
2196 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
2197 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
2199 /* Call the Driver */
2200 FileObject
->LockOperation
= TRUE
;
2201 Status
= IoCallDriver(DeviceObject
, Irp
);
2202 if (Status
== STATUS_PENDING
)
2206 KeWaitForSingleObject(&FileObject
->Event
,
2209 FileObject
->Flags
& FO_ALERTABLE_IO
,
2211 Status
= FileObject
->FinalStatus
;
2215 /* Return the Status */
2224 * Opens an existing file (simpler than NtCreateFile).
2228 * Variable that receives the file handle on return;
2231 * Access desired by the caller to the file;
2234 * Structue describing the file to be opened;
2236 * IoStatusBlock (OUT)
2237 * Receives details about the result of the
2241 * Type of shared access the caller requires;
2244 * Options for the file open.
2256 NtOpenFile(PHANDLE FileHandle
,
2257 ACCESS_MASK DesiredAccess
,
2258 POBJECT_ATTRIBUTES ObjectAttributes
,
2259 PIO_STATUS_BLOCK IoStatusBlock
,
2263 /* Call the I/O Function */
2264 return IoCreateFile(FileHandle
,
2281 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2282 IN FILE_INFORMATION_CLASS FileInformationClass
,
2283 OUT PVOID FileInformation
)
2285 IO_STATUS_BLOCK IoStatusBlock
;
2288 KPROCESSOR_MODE AccessMode
;
2289 UNICODE_STRING ObjectName
;
2290 OBJECT_CREATE_INFORMATION ObjectCreateInfo
;
2291 OBJECT_ATTRIBUTES LocalObjectAttributes
;
2295 FILE_BASIC_INFORMATION BasicInformation
;
2296 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInformation
;
2297 }LocalFileInformation
;
2299 if (FileInformationClass
== FileBasicInformation
)
2301 BufferSize
= sizeof(FILE_BASIC_INFORMATION
);
2303 else if (FileInformationClass
== FileNetworkOpenInformation
)
2305 BufferSize
= sizeof(FILE_NETWORK_OPEN_INFORMATION
);
2309 return STATUS_INVALID_PARAMETER
;
2312 AccessMode
= ExGetPreviousMode();
2314 if (AccessMode
!= KernelMode
)
2316 Status
= STATUS_SUCCESS
;
2319 ProbeForWrite(FileInformation
,
2325 Status
= _SEH_GetExceptionCode();
2328 if (NT_SUCCESS(Status
))
2330 Status
= ObpCaptureObjectAttributes(ObjectAttributes
,
2336 if (!NT_SUCCESS(Status
))
2340 InitializeObjectAttributes(&LocalObjectAttributes
,
2342 ObjectCreateInfo
.Attributes
,
2343 ObjectCreateInfo
.RootDirectory
,
2344 ObjectCreateInfo
.SecurityDescriptor
);
2348 Status
= ZwOpenFile(&FileHandle
,
2349 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2350 AccessMode
== KernelMode
? ObjectAttributes
: &LocalObjectAttributes
,
2353 FILE_SYNCHRONOUS_IO_NONALERT
);
2354 if (AccessMode
!= KernelMode
)
2356 ObpReleaseCapturedAttributes(&ObjectCreateInfo
);
2357 ExFreePool(ObjectName
.Buffer
);
2359 if (!NT_SUCCESS (Status
))
2361 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2365 /* Get file attributes */
2366 Status
= ZwQueryInformationFile(FileHandle
,
2368 AccessMode
== KernelMode
? FileInformation
: &LocalFileInformation
,
2370 FileInformationClass
);
2371 if (!NT_SUCCESS (Status
))
2373 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2375 ZwClose(FileHandle
);
2377 if (NT_SUCCESS(Status
) && AccessMode
!= KernelMode
)
2381 memcpy(FileInformation
, &LocalFileInformation
, BufferSize
);
2385 Status
= _SEH_GetExceptionCode();
2394 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2395 OUT PFILE_BASIC_INFORMATION FileInformation
)
2397 return IopQueryAttributesFile(ObjectAttributes
,
2398 FileBasicInformation
,
2402 static NTSTATUS NTAPI
2403 IopQueryDirectoryFileCompletion(IN PDEVICE_OBJECT DeviceObject
,
2409 DPRINT("IopQueryDirectoryFileCompletion was called for \'%wZ\'\n", Context
);
2411 ExFreePool(Context
);
2413 return STATUS_SUCCESS
;
2420 * FUNCTION: Queries a directory file.
2422 * FileHandle = Handle to a directory file
2423 * EventHandle = Handle to the event signaled on completion
2424 * ApcRoutine = Asynchroneous procedure callback, called on completion
2425 * ApcContext = Argument to the apc.
2426 * IoStatusBlock = Caller supplies storage for extended status information.
2427 * FileInformation = Caller supplies storage for the resulting information.
2429 * FileNameInformation FILE_NAMES_INFORMATION
2430 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2431 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2432 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2434 * Length = Size of the storage supplied
2435 * FileInformationClass = Indicates the type of information requested.
2436 * ReturnSingleEntry = Specify true if caller only requests the first
2438 * FileName = Initial directory name to query, that may contain wild
2440 * RestartScan = Number of times the action should be repeated
2441 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2442 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2443 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2447 NtQueryDirectoryFile(IN HANDLE FileHandle
,
2448 IN HANDLE PEvent OPTIONAL
,
2449 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2450 IN PVOID ApcContext OPTIONAL
,
2451 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2452 OUT PVOID FileInformation
,
2454 IN FILE_INFORMATION_CLASS FileInformationClass
,
2455 IN BOOLEAN ReturnSingleEntry
,
2456 IN PUNICODE_STRING FileName OPTIONAL
,
2457 IN BOOLEAN RestartScan
)
2460 PDEVICE_OBJECT DeviceObject
;
2461 PFILE_OBJECT FileObject
= NULL
;
2462 PIO_STACK_LOCATION StackPtr
;
2463 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2464 NTSTATUS Status
= STATUS_SUCCESS
;
2465 BOOLEAN LocalEvent
= FALSE
;
2466 PKEVENT Event
= NULL
;
2467 PUNICODE_STRING SearchPattern
= NULL
;
2469 DPRINT("NtQueryDirectoryFile()\n");
2472 /* Validate User-Mode Buffers */
2473 if(PreviousMode
!= KernelMode
)
2477 ProbeForWrite(IoStatusBlock
,
2478 sizeof(IO_STATUS_BLOCK
),
2480 ProbeForWrite(FileInformation
,
2485 UNICODE_STRING CapturedFileName
;
2487 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
2488 ProbeForRead(CapturedFileName
.Buffer
,
2489 CapturedFileName
.MaximumLength
,
2491 SearchPattern
= ExAllocatePool(NonPagedPool
, CapturedFileName
.Length
+ sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
2492 if (SearchPattern
== NULL
)
2494 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2497 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)SearchPattern
+ sizeof(UNICODE_STRING
));
2498 SearchPattern
->MaximumLength
= CapturedFileName
.Length
+ sizeof(WCHAR
);
2499 RtlCopyUnicodeString(SearchPattern
, &CapturedFileName
);
2504 Status
= _SEH_GetExceptionCode();
2508 if(!NT_SUCCESS(Status
))
2514 /* Get File Object */
2515 Status
= ObReferenceObjectByHandle(FileHandle
,
2516 FILE_LIST_DIRECTORY
,
2519 (PVOID
*)&FileObject
,
2521 if (!NT_SUCCESS(Status
))
2526 /* Get Event Object */
2529 Status
= ObReferenceObjectByHandle(PEvent
,
2535 if (!NT_SUCCESS(Status
))
2540 KeClearEvent(Event
);
2543 /* Check if this is a direct open or not */
2544 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2546 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2550 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2553 /* Check if we should use Sync IO or not */
2554 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2556 /* Use File Object event */
2557 KeClearEvent(&FileObject
->Event
);
2564 /* Allocate the IRP */
2565 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2567 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2571 /* Set up the IRP */
2572 Irp
->RequestorMode
= PreviousMode
;
2573 Irp
->UserIosb
= IoStatusBlock
;
2574 Irp
->UserEvent
= Event
;
2575 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2576 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2577 Irp
->UserBuffer
= FileInformation
;
2578 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2579 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2581 /* Set up Stack Data */
2582 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2583 StackPtr
->FileObject
= FileObject
;
2584 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2585 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2587 /* Set Parameters */
2588 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
= FileInformationClass
;
2589 StackPtr
->Parameters
.QueryDirectory
.FileName
= SearchPattern
? SearchPattern
: FileName
;
2590 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2591 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2592 StackPtr
->Flags
= 0;
2593 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2594 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2598 IoSetCompletionRoutine(Irp
,
2599 IopQueryDirectoryFileCompletion
,
2606 /* Call the Driver */
2607 Status
= IoCallDriver(DeviceObject
, Irp
);
2608 if (Status
== STATUS_PENDING
)
2612 KeWaitForSingleObject(&FileObject
->Event
,
2615 FileObject
->Flags
& FO_ALERTABLE_IO
,
2617 Status
= FileObject
->FinalStatus
;
2621 /* don't dereference the event anymore! */
2624 /* don't free the search pattern string */
2625 SearchPattern
= NULL
;
2628 if (FileObject
!= NULL
)
2630 ObDereferenceObject(FileObject
);
2634 ObDereferenceObject(Event
);
2636 if (SearchPattern
!= NULL
)
2638 ExFreePool(SearchPattern
);
2641 /* Return the Status */
2649 NtQueryEaFile(IN HANDLE FileHandle
,
2650 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2653 IN BOOLEAN ReturnSingleEntry
,
2654 IN PVOID EaList OPTIONAL
,
2655 IN ULONG EaListLength
,
2656 IN PULONG EaIndex OPTIONAL
,
2657 IN BOOLEAN RestartScan
)
2660 return STATUS_NOT_IMPLEMENTED
;
2665 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2666 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2668 return IopQueryAttributesFile(ObjectAttributes
,
2669 FileNetworkOpenInformation
,
2677 NtQueryInformationFile(HANDLE FileHandle
,
2678 PIO_STATUS_BLOCK IoStatusBlock
,
2679 PVOID FileInformation
,
2681 FILE_INFORMATION_CLASS FileInformationClass
)
2683 OBJECT_HANDLE_INFORMATION HandleInformation
;
2684 PFILE_OBJECT FileObject
;
2687 PDEVICE_OBJECT DeviceObject
;
2688 PIO_STACK_LOCATION StackPtr
;
2689 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2691 BOOLEAN LocalEvent
= FALSE
;
2692 BOOLEAN Failed
= FALSE
;
2694 ASSERT(IoStatusBlock
!= NULL
);
2695 ASSERT(FileInformation
!= NULL
);
2697 DPRINT("NtQueryInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
2698 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2699 Length
, FileInformationClass
);
2701 /* Reference the Handle */
2702 Status
= ObReferenceObjectByHandle(FileHandle
,
2706 (PVOID
*)&FileObject
,
2707 &HandleInformation
);
2708 if (!NT_SUCCESS(Status
)) return Status
;
2710 /* Check information class specific access rights */
2711 switch (FileInformationClass
)
2713 case FileBasicInformation
:
2714 if (!(HandleInformation
.GrantedAccess
& FILE_READ_ATTRIBUTES
))
2718 case FilePositionInformation
:
2719 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2720 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2730 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2731 ObDereferenceObject(FileObject
);
2732 return STATUS_ACCESS_DENIED
;
2735 if (FileInformationClass
== FilePositionInformation
)
2737 if (Length
< sizeof(FILE_POSITION_INFORMATION
))
2739 Status
= STATUS_BUFFER_OVERFLOW
;
2745 ((PFILE_POSITION_INFORMATION
)FileInformation
)->CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2746 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2747 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2751 Status
= _SEH_GetExceptionCode();
2755 ObDereferenceObject(FileObject
);
2759 DPRINT("FileObject 0x%p\n", FileObject
);
2761 /* Check if this is a direct open or not */
2762 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2764 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2768 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2771 if (FileInformationClass
== FileAlignmentInformation
)
2773 if (Length
< sizeof(FILE_ALIGNMENT_INFORMATION
))
2775 Status
= STATUS_BUFFER_OVERFLOW
;
2781 ((PFILE_ALIGNMENT_INFORMATION
)FileInformation
)->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2782 IoStatusBlock
->Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2783 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2787 Status
= _SEH_GetExceptionCode();
2791 ObDereferenceObject(FileObject
);
2795 /* Check if we should use Sync IO or not */
2796 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2798 /* Use File Object event */
2799 KeClearEvent(&FileObject
->Event
);
2803 /* Use local event */
2804 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2808 /* Allocate the IRP */
2809 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2811 ObDereferenceObject(FileObject
);
2812 return STATUS_INSUFFICIENT_RESOURCES
;
2815 /* Allocate the System Buffer */
2816 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2821 ObDereferenceObject(FileObject
);
2822 return STATUS_INSUFFICIENT_RESOURCES
;
2825 /* Set up the IRP */
2826 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2827 Irp
->RequestorMode
= PreviousMode
;
2828 Irp
->UserIosb
= IoStatusBlock
;
2829 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2830 Irp
->UserBuffer
= FileInformation
;
2831 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2832 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
2833 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2835 /* Set up Stack Data */
2836 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2837 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2838 StackPtr
->FileObject
= FileObject
;
2840 /* Set the Parameters */
2841 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2842 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2844 /* Call the Driver */
2845 Status
= IoCallDriver(DeviceObject
, Irp
);
2846 if (Status
== STATUS_PENDING
)
2850 KeWaitForSingleObject(&Event
,
2853 FileObject
->Flags
& FO_ALERTABLE_IO
,
2855 Status
= IoStatusBlock
->Status
;
2859 KeWaitForSingleObject(&FileObject
->Event
,
2862 FileObject
->Flags
& FO_ALERTABLE_IO
,
2864 Status
= FileObject
->FinalStatus
;
2868 /* Return the Status */
2877 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2878 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2881 IN BOOLEAN ReturnSingleEntry
,
2882 IN PVOID SidList OPTIONAL
,
2883 IN ULONG SidListLength
,
2884 IN PSID StartSid OPTIONAL
,
2885 IN BOOLEAN RestartScan
)
2888 return STATUS_NOT_IMPLEMENTED
;
2907 NtReadFile(IN HANDLE FileHandle
,
2908 IN HANDLE Event OPTIONAL
,
2909 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2910 IN PVOID ApcContext OPTIONAL
,
2911 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2914 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2915 IN PULONG Key OPTIONAL
)
2917 NTSTATUS Status
= STATUS_SUCCESS
;
2918 PFILE_OBJECT FileObject
;
2920 PDEVICE_OBJECT DeviceObject
;
2921 PIO_STACK_LOCATION StackPtr
;
2922 KPROCESSOR_MODE PreviousMode
;
2923 BOOLEAN LocalEvent
= FALSE
;
2924 PKEVENT EventObject
= NULL
;
2925 LARGE_INTEGER CapturedByteOffset
;
2927 DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
2928 "IoStatusBlock 0x%p)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2933 PreviousMode
= KeGetPreviousMode();
2934 CapturedByteOffset
.QuadPart
= 0;
2936 /* Validate User-Mode Buffers */
2937 if(PreviousMode
!= KernelMode
)
2941 ProbeForWrite(IoStatusBlock
,
2942 sizeof(IO_STATUS_BLOCK
),
2944 ProbeForWrite(Buffer
,
2947 if (ByteOffset
!= NULL
)
2949 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2951 /* FIXME - probe other pointers and capture information */
2955 Status
= _SEH_GetExceptionCode();
2959 if(!NT_SUCCESS(Status
)) return Status
;
2963 if (ByteOffset
!= NULL
)
2965 CapturedByteOffset
= *ByteOffset
;
2969 /* Get File Object */
2970 Status
= ObReferenceObjectByHandle(FileHandle
,
2974 (PVOID
*)&FileObject
,
2976 if (!NT_SUCCESS(Status
)) return Status
;
2978 /* Check the Byte Offset */
2979 if (ByteOffset
== NULL
||
2980 (CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
2981 CapturedByteOffset
.u
.HighPart
== -1))
2983 /* a valid ByteOffset is required if asynch. op. */
2984 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2986 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2987 ObDereferenceObject(FileObject
);
2988 return STATUS_INVALID_PARAMETER
;
2991 /* Use the Current Byte OFfset */
2992 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2995 /* Check for event */
2999 Status
= ObReferenceObjectByHandle(Event
,
3003 (PVOID
*)&EventObject
,
3005 if (!NT_SUCCESS(Status
))
3007 ObDereferenceObject(FileObject
);
3010 KeClearEvent(EventObject
);
3013 /* Check if this is a direct open or not */
3014 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3016 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3020 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3023 /* Check if we should use Sync IO or not */
3024 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3026 /* Use File Object event */
3027 KeClearEvent(&FileObject
->Event
);
3034 /* Create the IRP */
3037 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
3041 &CapturedByteOffset
,
3046 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3051 Status
= _SEH_GetExceptionCode();
3055 /* Cleanup if IRP Allocation Failed */
3056 if (!NT_SUCCESS(Status
))
3058 if (Event
) ObDereferenceObject(EventObject
);
3059 ObDereferenceObject(FileObject
);
3063 /* Set up IRP Data */
3064 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3065 Irp
->RequestorMode
= PreviousMode
;
3066 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3067 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3068 Irp
->Flags
|= IRP_READ_OPERATION
;
3071 * Vfat doesn't handle non cached files correctly.
3073 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3076 /* Setup Stack Data */
3077 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3078 StackPtr
->FileObject
= FileObject
;
3079 StackPtr
->Parameters
.Read
.Key
= Key
? *Key
: 0;
3081 /* Call the Driver */
3082 Status
= IoCallDriver(DeviceObject
, Irp
);
3083 if (Status
== STATUS_PENDING
)
3087 KeWaitForSingleObject(&FileObject
->Event
,
3090 FileObject
->Flags
& FO_ALERTABLE_IO
,
3092 Status
= FileObject
->FinalStatus
;
3096 /* Return the Status */
3114 NtReadFileScatter(IN HANDLE FileHandle
,
3115 IN HANDLE Event OPTIONAL
,
3116 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3117 IN PVOID UserApcContext OPTIONAL
,
3118 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3119 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3120 IN ULONG BufferLength
,
3121 IN PLARGE_INTEGER ByteOffset
,
3122 IN PULONG Key OPTIONAL
)
3125 return(STATUS_NOT_IMPLEMENTED
);
3133 NtSetEaFile(IN HANDLE FileHandle
,
3134 IN PIO_STATUS_BLOCK IoStatusBlock
,
3136 IN ULONG EaBufferSize
)
3139 return STATUS_NOT_IMPLEMENTED
;
3146 NtSetInformationFile(HANDLE FileHandle
,
3147 PIO_STATUS_BLOCK IoStatusBlock
,
3148 PVOID FileInformation
,
3150 FILE_INFORMATION_CLASS FileInformationClass
)
3152 OBJECT_HANDLE_INFORMATION HandleInformation
;
3153 PIO_STACK_LOCATION StackPtr
;
3154 PFILE_OBJECT FileObject
;
3155 PDEVICE_OBJECT DeviceObject
;
3158 BOOLEAN LocalEvent
= FALSE
;
3159 NTSTATUS Status
= STATUS_SUCCESS
;
3160 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3161 BOOLEAN Failed
= FALSE
;
3163 DPRINT("NtSetInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
3164 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
3165 Length
, FileInformationClass
);
3167 if (PreviousMode
!= KernelMode
)
3171 if (IoStatusBlock
!= NULL
)
3173 ProbeForWrite(IoStatusBlock
,
3174 sizeof(IO_STATUS_BLOCK
),
3180 ProbeForRead(FileInformation
,
3187 Status
= _SEH_GetExceptionCode();
3191 if (!NT_SUCCESS(Status
))
3198 ASSERT(IoStatusBlock
!= NULL
);
3199 ASSERT(FileInformation
!= NULL
);
3202 /* Get the file object from the file handle */
3203 Status
= ObReferenceObjectByHandle(FileHandle
,
3207 (PVOID
*)&FileObject
,
3208 &HandleInformation
);
3209 if (!NT_SUCCESS(Status
)) return Status
;
3211 /* Check information class specific access rights */
3212 switch (FileInformationClass
)
3214 case FileBasicInformation
:
3215 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_ATTRIBUTES
))
3219 case FileDispositionInformation
:
3220 if (!(HandleInformation
.GrantedAccess
& DELETE
))
3224 case FilePositionInformation
:
3225 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
3226 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3230 case FileEndOfFileInformation
:
3231 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
))
3241 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
3242 ObDereferenceObject(FileObject
);
3243 return STATUS_ACCESS_DENIED
;
3246 DPRINT("FileObject 0x%p\n", FileObject
);
3248 if (FileInformationClass
== FilePositionInformation
)
3250 if (Length
< sizeof(FILE_POSITION_INFORMATION
))
3252 Status
= STATUS_BUFFER_OVERFLOW
;
3258 FileObject
->CurrentByteOffset
= ((PFILE_POSITION_INFORMATION
)FileInformation
)->CurrentByteOffset
;
3259 IoStatusBlock
->Information
= 0;
3260 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
3264 Status
= _SEH_GetExceptionCode();
3268 ObDereferenceObject(FileObject
);
3272 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3273 /* Handle IO Completion Port quickly */
3274 if (FileInformationClass
== FileCompletionInformation
)
3277 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
3278 PIO_COMPLETION_CONTEXT Context
;
3280 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
|| FileObject
->CompletionContext
!= NULL
)
3282 Status
= STATUS_INVALID_PARAMETER
;
3286 if (Length
< sizeof(FILE_COMPLETION_INFORMATION
))
3288 Status
= STATUS_INFO_LENGTH_MISMATCH
;
3292 /* Reference the Port */
3293 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
, /* FIXME - protect with SEH! */
3294 IO_COMPLETION_MODIFY_STATE
,
3299 if (NT_SUCCESS(Status
))
3301 /* Allocate the Context */
3302 Context
= ExAllocatePoolWithTag(PagedPool
,
3303 sizeof(IO_COMPLETION_CONTEXT
),
3304 TAG('I', 'o', 'C', 'p'));
3306 if (Context
!= NULL
)
3309 Context
->Key
= CompletionInfo
->Key
; /* FIXME - protect with SEH! */
3310 Context
->Port
= Queue
;
3312 if (InterlockedCompareExchangePointer(&FileObject
->CompletionContext
,
3316 /* someone else set the completion port in the
3318 ExFreePool(Context
);
3319 ObDereferenceObject(Queue
);
3320 Status
= STATUS_INVALID_PARAMETER
;
3325 /* Dereference the Port now */
3326 ObDereferenceObject(Queue
);
3327 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3333 /* Complete the I/O */
3334 ObDereferenceObject(FileObject
);
3338 /* Check if this is a direct open or not */
3339 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3341 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3345 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3348 /* Check if we should use Sync IO or not */
3349 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3351 /* Use File Object event */
3352 KeClearEvent(&FileObject
->Event
);
3356 /* Use local event */
3357 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3361 /* Allocate the IRP */
3362 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
3364 ObDereferenceObject(FileObject
);
3365 return STATUS_INSUFFICIENT_RESOURCES
;
3368 /* Allocate the System Buffer */
3369 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
3373 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3377 /* Copy the data inside */
3378 if (PreviousMode
!= KernelMode
)
3382 /* no need to probe again */
3383 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3389 Status
= _SEH_GetExceptionCode();
3393 if (!NT_SUCCESS(Status
))
3395 ExFreePoolWithTag(Irp
->AssociatedIrp
.SystemBuffer
,
3397 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3400 ObDereferenceObject(FileObject
);
3406 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3411 /* Set up the IRP */
3412 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3413 Irp
->RequestorMode
= PreviousMode
;
3414 Irp
->UserIosb
= IoStatusBlock
;
3415 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
3416 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3417 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
3418 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3420 /* Set up Stack Data */
3421 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3422 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
3423 StackPtr
->FileObject
= FileObject
;
3425 /* Set the Parameters */
3426 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
3427 StackPtr
->Parameters
.SetFile
.Length
= Length
;
3429 /* Call the Driver */
3430 Status
= IoCallDriver(DeviceObject
, Irp
);
3431 if (Status
== STATUS_PENDING
)
3435 KeWaitForSingleObject(&Event
,
3438 FileObject
->Flags
& FO_ALERTABLE_IO
,
3442 Status
= IoStatusBlock
->Status
;
3446 Status
= _SEH_GetExceptionCode();
3452 KeWaitForSingleObject(&FileObject
->Event
,
3455 FileObject
->Flags
& FO_ALERTABLE_IO
,
3459 Status
= FileObject
->FinalStatus
;
3463 Status
= _SEH_GetExceptionCode();
3469 /* Return the Status */
3478 NtSetQuotaInformationFile(HANDLE FileHandle
,
3479 PIO_STATUS_BLOCK IoStatusBlock
,
3484 return STATUS_NOT_IMPLEMENTED
;
3492 NtUnlockFile(IN HANDLE FileHandle
,
3493 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3494 IN PLARGE_INTEGER ByteOffset
,
3495 IN PLARGE_INTEGER Length
,
3496 IN ULONG Key OPTIONAL
)
3498 PFILE_OBJECT FileObject
= NULL
;
3499 PLARGE_INTEGER LocalLength
= NULL
;
3501 PIO_STACK_LOCATION StackPtr
;
3502 PDEVICE_OBJECT DeviceObject
;
3504 BOOLEAN LocalEvent
= FALSE
;
3505 KPROCESSOR_MODE PreviousMode
;
3506 NTSTATUS Status
= STATUS_SUCCESS
;
3507 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3508 OBJECT_HANDLE_INFORMATION HandleInformation
;
3512 PreviousMode
= KeGetPreviousMode();
3514 CapturedByteOffset
.QuadPart
= 0;
3515 CapturedLength
.QuadPart
= 0;
3517 /* Get File Object */
3518 Status
= ObReferenceObjectByHandle(FileHandle
,
3522 (PVOID
*)&FileObject
,
3523 &HandleInformation
);
3524 if (!NT_SUCCESS(Status
)) return Status
;
3526 if (PreviousMode
!= KernelMode
)
3528 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless we're
3530 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3532 DPRINT1("Invalid access rights\n");
3533 ObDereferenceObject(FileObject
);
3534 return STATUS_ACCESS_DENIED
;
3539 ProbeForWrite(IoStatusBlock
,
3540 sizeof(IO_STATUS_BLOCK
),
3542 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3543 CapturedLength
= ProbeForReadLargeInteger(Length
);
3547 Status
= _SEH_GetExceptionCode();
3551 if (!NT_SUCCESS(Status
))
3553 ObDereferenceObject(FileObject
);
3559 CapturedByteOffset
= *ByteOffset
;
3560 CapturedLength
= *Length
;
3563 /* Check if this is a direct open or not */
3564 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3566 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3570 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3573 /* Check if we should use Sync IO or not */
3574 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3576 /* Use File Object event */
3577 KeClearEvent(&FileObject
->Event
);
3581 /* Use local event */
3582 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3586 /* Allocate the IRP */
3587 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
3589 ObDereferenceObject(FileObject
);
3590 return STATUS_INSUFFICIENT_RESOURCES
;
3593 /* Allocate local buffer */
3594 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3595 sizeof(LARGE_INTEGER
),
3600 ObDereferenceObject(FileObject
);
3601 return STATUS_INSUFFICIENT_RESOURCES
;
3603 *LocalLength
= CapturedLength
;
3605 /* Set up the IRP */
3606 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3607 Irp
->RequestorMode
= PreviousMode
;
3608 Irp
->UserIosb
= IoStatusBlock
;
3609 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
3610 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3611 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3613 /* Set up Stack Data */
3614 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3615 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3616 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3617 StackPtr
->FileObject
= FileObject
;
3619 /* Set Parameters */
3620 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3621 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3622 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3624 /* Call the Driver */
3625 Status
= IoCallDriver(DeviceObject
, Irp
);
3626 if (Status
== STATUS_PENDING
)
3630 KeWaitForSingleObject(&Event
,
3633 FileObject
->Flags
& FO_ALERTABLE_IO
,
3635 Status
= IoStatusBlock
->Status
;
3639 KeWaitForSingleObject(&FileObject
->Event
,
3642 FileObject
->Flags
& FO_ALERTABLE_IO
,
3644 Status
= FileObject
->FinalStatus
;
3648 /* Return the Status */
3668 NtWriteFile (IN HANDLE FileHandle
,
3669 IN HANDLE Event OPTIONAL
,
3670 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3671 IN PVOID ApcContext OPTIONAL
,
3672 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3675 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
3676 IN PULONG Key OPTIONAL
)
3678 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3679 NTSTATUS Status
= STATUS_SUCCESS
;
3680 PFILE_OBJECT FileObject
;
3682 PDEVICE_OBJECT DeviceObject
;
3683 PIO_STACK_LOCATION StackPtr
;
3684 KPROCESSOR_MODE PreviousMode
;
3685 BOOLEAN LocalEvent
= FALSE
;
3686 PKEVENT EventObject
= NULL
;
3687 LARGE_INTEGER CapturedByteOffset
;
3688 ULONG CapturedKey
= 0;
3689 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
3691 DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
3692 "IoStatusBlock 0x%p)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
3697 PreviousMode
= KeGetPreviousMode();
3698 CapturedByteOffset
.QuadPart
= 0;
3700 /* Validate User-Mode Buffers */
3701 if(PreviousMode
!= KernelMode
)
3705 ProbeForWrite(IoStatusBlock
,
3706 sizeof(IO_STATUS_BLOCK
),
3709 ProbeForRead(Buffer
,
3712 if (ByteOffset
!= NULL
)
3714 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3719 CapturedKey
= ProbeForReadUlong(Key
);
3724 Status
= _SEH_GetExceptionCode();
3728 if(!NT_SUCCESS(Status
)) return Status
;
3732 if (ByteOffset
!= NULL
)
3734 CapturedByteOffset
= *ByteOffset
;
3742 /* Get File Object */
3743 Status
= ObReferenceObjectByHandle(FileHandle
,
3747 (PVOID
*)&FileObject
,
3749 if (!NT_SUCCESS(Status
)) return Status
;
3751 /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
3752 granted. However, if this is a named pipe, make sure we don't ask for
3753 FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
3755 if (!(FileObject
->Flags
& FO_NAMED_PIPE
))
3756 DesiredAccess
|= FILE_APPEND_DATA
;
3757 if (!RtlAreAnyAccessesGranted(ObjectHandleInfo
.GrantedAccess
,
3760 ObDereferenceObject(FileObject
);
3761 return STATUS_ACCESS_DENIED
;
3764 /* Check if we got write Access */
3765 if (ObjectHandleInfo
.GrantedAccess
& FILE_WRITE_DATA
)
3767 /* Check the Byte Offset */
3768 if (ByteOffset
== NULL
||
3769 (CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
3770 CapturedByteOffset
.u
.HighPart
== -1))
3772 /* a valid ByteOffset is required if asynch. op. */
3773 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3775 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3776 ObDereferenceObject(FileObject
);
3777 return STATUS_INVALID_PARAMETER
;
3780 /* Use the Current Byte OFfset */
3781 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3784 else if ((ObjectHandleInfo
.GrantedAccess
& FILE_APPEND_DATA
) &&
3785 !(FileObject
->Flags
& FO_NAMED_PIPE
))
3787 /* a valid ByteOffset is required if asynch. op. */
3788 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3790 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3791 ObDereferenceObject(FileObject
);
3792 return STATUS_INVALID_PARAMETER
;
3795 /* Give the drivers somethign to understand */
3796 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3797 CapturedByteOffset
.u
.HighPart
= 0xffffffff;
3800 /* Check if we got an event */
3804 Status
= ObReferenceObjectByHandle(Event
,
3808 (PVOID
*)&EventObject
,
3810 if (!NT_SUCCESS(Status
))
3812 ObDereferenceObject(FileObject
);
3815 KeClearEvent(EventObject
);
3818 /* Check if this is a direct open or not */
3819 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3821 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3825 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3828 /* Check if we should use Sync IO or not */
3829 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3831 /* Use File Object event */
3832 KeClearEvent(&FileObject
->Event
);
3842 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
3846 &CapturedByteOffset
,
3851 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3856 Status
= _SEH_GetExceptionCode();
3860 /* Cleanup on failure */
3861 if (!NT_SUCCESS(Status
))
3865 ObDereferenceObject(&EventObject
);
3867 ObDereferenceObject(FileObject
);
3871 /* Set up IRP Data */
3872 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3873 Irp
->RequestorMode
= PreviousMode
;
3874 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3875 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3876 Irp
->Flags
|= IRP_WRITE_OPERATION
;
3879 * Vfat doesn't handle non cached files correctly.
3881 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3884 /* Setup Stack Data */
3885 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3886 StackPtr
->FileObject
= FileObject
;
3887 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3888 if (FileObject
->Flags
& FO_WRITE_THROUGH
) StackPtr
->Flags
= SL_WRITE_THROUGH
;
3890 /* Call the Driver */
3891 Status
= IoCallDriver(DeviceObject
, Irp
);
3892 if (Status
== STATUS_PENDING
)
3896 KeWaitForSingleObject(&FileObject
->Event
,
3899 FileObject
->Flags
& FO_ALERTABLE_IO
,
3901 Status
= FileObject
->FinalStatus
;
3905 /* Return the Status */
3923 NtWriteFileGather(IN HANDLE FileHandle
,
3924 IN HANDLE Event OPTIONAL
,
3925 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3926 IN PVOID UserApcContext OPTIONAL
,
3927 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3928 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3929 IN ULONG BufferLength
,
3930 IN PLARGE_INTEGER ByteOffset
,
3931 IN PULONG Key OPTIONAL
)
3934 return(STATUS_NOT_IMPLEMENTED
);