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 PIO_STACK_LOCATION StackLoc
;
755 IO_SECURITY_CONTEXT SecurityContext
;
756 KPROCESSOR_MODE AccessMode
;
758 IO_STATUS_BLOCK LocalIoStatusBlock
;
759 LARGE_INTEGER SafeAllocationSize
;
760 PVOID SystemEaBuffer
= NULL
;
761 NTSTATUS Status
= STATUS_SUCCESS
;
763 DPRINT("IoCreateFile(FileHandle 0x%p, DesiredAccess %x, "
764 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
765 FileHandle
,DesiredAccess
,ObjectAttributes
,
766 ObjectAttributes
->ObjectName
->Buffer
);
768 ASSERT_IRQL(PASSIVE_LEVEL
);
770 if (IoStatusBlock
== NULL
|| FileHandle
== NULL
)
771 return STATUS_ACCESS_VIOLATION
;
775 if(Options
& IO_NO_PARAMETER_CHECKING
)
776 AccessMode
= KernelMode
;
778 AccessMode
= ExGetPreviousMode();
780 if(AccessMode
!= KernelMode
)
784 ProbeForWrite(FileHandle
,
787 ProbeForWrite(IoStatusBlock
,
788 sizeof(IO_STATUS_BLOCK
),
790 if(AllocationSize
!= NULL
)
792 ProbeForRead(AllocationSize
,
793 sizeof(LARGE_INTEGER
),
795 SafeAllocationSize
= *AllocationSize
;
798 SafeAllocationSize
.QuadPart
= 0;
800 if(EaBuffer
!= NULL
&& EaLength
> 0)
802 ProbeForRead(EaBuffer
,
806 /* marshal EaBuffer */
807 SystemEaBuffer
= ExAllocatePool(NonPagedPool
,
809 if(SystemEaBuffer
== NULL
)
811 Status
= STATUS_INSUFFICIENT_RESOURCES
;
815 RtlCopyMemory(SystemEaBuffer
,
822 Status
= _SEH_GetExceptionCode();
826 if(!NT_SUCCESS(Status
))
833 if(AllocationSize
!= NULL
)
834 SafeAllocationSize
= *AllocationSize
;
836 SafeAllocationSize
.QuadPart
= 0;
838 if(EaBuffer
!= NULL
&& EaLength
> 0)
840 SystemEaBuffer
= EaBuffer
;
844 if(Options
& IO_CHECK_CREATE_PARAMETERS
)
846 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
849 /* First try to open an existing named object */
850 Status
= ObOpenObjectByName(ObjectAttributes
,
858 if (NT_SUCCESS(Status
))
860 OBJECT_CREATE_INFORMATION ObjectCreateInfo
;
861 OBJECT_ATTRIBUTES tmpObjectAttributes
;
862 UNICODE_STRING ObjectName
;
864 Status
= ObReferenceObjectByHandle(LocalHandle
,
868 (PVOID
*)&DeviceObject
,
870 ZwClose(LocalHandle
);
871 if (!NT_SUCCESS(Status
))
875 if (BODY_TO_HEADER(DeviceObject
)->Type
!= IoDeviceObjectType
)
877 ObDereferenceObject (DeviceObject
);
878 return STATUS_OBJECT_NAME_COLLISION
;
881 Status
= ObpCaptureObjectAttributes(ObjectAttributes
,
886 if (!NT_SUCCESS(Status
))
888 ObDereferenceObject (DeviceObject
);
892 InitializeObjectAttributes(&tmpObjectAttributes
,
894 ObjectCreateInfo
.Attributes
& OBJ_INHERIT
,
897 ObpReleaseCapturedAttributes(&ObjectCreateInfo
);
898 if (ObjectName
.Buffer
) ExFreePool(ObjectName
.Buffer
);
902 Status
= ObCreateObject(KernelMode
,
904 &tmpObjectAttributes
,
910 (PVOID
*)&FileObject
);
913 /* Set File Object Data */
914 FileObject
->DeviceObject
= IoGetAttachedDevice(DeviceObject
);
915 FileObject
->Vpb
= FileObject
->DeviceObject
->Vpb
;
918 FileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
919 DPRINT("%wZ\n", ObjectAttributes
->ObjectName
);
921 ObDereferenceObject (DeviceObject
);
925 if (FileObject
== NULL
)
927 Status
= ObCreateObject(AccessMode
,
935 (PVOID
*)&FileObject
);
936 if (!NT_SUCCESS(Status
))
938 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
942 RtlMapGenericMask(&DesiredAccess
,
943 &BODY_TO_HEADER(FileObject
)->Type
->TypeInfo
.GenericMapping
);
945 Status
= ObInsertObject ((PVOID
)FileObject
,
951 if (!NT_SUCCESS(Status
))
953 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
954 ObMakeTemporaryObject(FileObject
);
955 ObDereferenceObject (FileObject
);
959 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
961 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
963 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
965 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
968 if (CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
969 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
971 SecurityContext
.SecurityQos
= NULL
; /* ?? */
972 SecurityContext
.AccessState
= NULL
; /* ?? */
973 SecurityContext
.DesiredAccess
= DesiredAccess
;
974 SecurityContext
.FullCreateOptions
= 0; /* ?? */
976 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
977 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
979 DPRINT("FileObject 0x%p\n", FileObject
);
980 DPRINT("FileObject->DeviceObject 0x%p\n", FileObject
->DeviceObject
);
982 * Create a new IRP to hand to
983 * the FS driver: this may fail
984 * due to resource shortage.
986 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
989 ZwClose(LocalHandle
);
990 return STATUS_UNSUCCESSFUL
;
993 //trigger FileObject/Event dereferencing
994 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
995 Irp
->RequestorMode
= AccessMode
;
996 Irp
->UserIosb
= &LocalIoStatusBlock
;
997 Irp
->AssociatedIrp
.SystemBuffer
= SystemEaBuffer
;
998 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
999 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1000 Irp
->UserEvent
= &FileObject
->Event
;
1001 Irp
->Overlay
.AllocationSize
= SafeAllocationSize
;
1004 * Get the stack location for the new
1005 * IRP and prepare it.
1007 StackLoc
= IoGetNextIrpStackLocation(Irp
);
1008 StackLoc
->MinorFunction
= 0;
1009 StackLoc
->Flags
= (UCHAR
)Options
;
1010 StackLoc
->Control
= 0;
1011 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
1012 StackLoc
->FileObject
= FileObject
;
1014 switch (CreateFileType
)
1017 case CreateFileTypeNone
:
1018 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
1019 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
1020 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
1021 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
1022 StackLoc
->Parameters
.Create
.FileAttributes
= (USHORT
)FileAttributes
;
1023 StackLoc
->Parameters
.Create
.ShareAccess
= (USHORT
)ShareAccess
;
1024 StackLoc
->Parameters
.Create
.EaLength
= SystemEaBuffer
!= NULL
? EaLength
: 0;
1027 case CreateFileTypeNamedPipe
:
1028 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
1029 StackLoc
->Parameters
.CreatePipe
.SecurityContext
= &SecurityContext
;
1030 StackLoc
->Parameters
.CreatePipe
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
1031 StackLoc
->Parameters
.CreatePipe
.Options
|= (CreateDisposition
<< 24);
1032 StackLoc
->Parameters
.CreatePipe
.ShareAccess
= (USHORT
)ShareAccess
;
1033 StackLoc
->Parameters
.CreatePipe
.Parameters
= ExtraCreateParameters
;
1036 case CreateFileTypeMailslot
:
1037 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
1038 StackLoc
->Parameters
.CreateMailslot
.SecurityContext
= &SecurityContext
;
1039 StackLoc
->Parameters
.CreateMailslot
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
1040 StackLoc
->Parameters
.CreateMailslot
.Options
|= (CreateDisposition
<< 24);
1041 StackLoc
->Parameters
.CreateMailslot
.ShareAccess
= (USHORT
)ShareAccess
;
1042 StackLoc
->Parameters
.CreateMailslot
.Parameters
= ExtraCreateParameters
;
1047 * Now call the driver and
1048 * possibly wait if it can
1049 * not complete the request
1052 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
1053 DPRINT("Status :%x\n", Status
);
1055 if (Status
== STATUS_PENDING
)
1057 KeWaitForSingleObject(&FileObject
->Event
,
1062 Status
= LocalIoStatusBlock
.Status
;
1064 if (!NT_SUCCESS(Status
))
1066 DPRINT("Failing create request with status %x\n", Status
);
1067 FileObject
->DeviceObject
= NULL
;
1068 FileObject
->Vpb
= NULL
;
1070 ZwClose(LocalHandle
);
1076 *FileHandle
= LocalHandle
;
1077 *IoStatusBlock
= LocalIoStatusBlock
;
1081 Status
= _SEH_GetExceptionCode();
1086 /* cleanup EABuffer if captured */
1087 if(AccessMode
!= KernelMode
&& SystemEaBuffer
!= NULL
)
1089 ExFreePool(SystemEaBuffer
);
1092 ASSERT_IRQL(PASSIVE_LEVEL
);
1094 DPRINT("Finished IoCreateFile() (*FileHandle) 0x%p\n", (*FileHandle
));
1104 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
1105 IN ACCESS_MASK DesiredAccess
,
1106 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1107 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1108 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
1109 IN ULONG FileAttributes
,
1110 IN ULONG ShareAccess
,
1111 IN ULONG Disposition
,
1112 IN ULONG CreateOptions
,
1113 IN PVOID EaBuffer OPTIONAL
,
1115 IN CREATE_FILE_TYPE CreateFileType
,
1116 IN PVOID ExtraCreateParameters OPTIONAL
,
1118 IN PVOID DeviceObject
)
1121 return STATUS_NOT_IMPLEMENTED
;
1126 * IoCreateStreamFileObject@8
1147 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
1148 PDEVICE_OBJECT DeviceObject
)
1150 PFILE_OBJECT CreatedFileObject
;
1153 /* FIXME: This function should call ObInsertObject. The "Lite" version
1154 doesnt. This function is also called from IoCreateFile for some
1155 reason. These hacks need to be removed.
1158 DPRINT("IoCreateStreamFileObject(FileObject 0x%p, DeviceObject 0x%p)\n",
1159 FileObject
, DeviceObject
);
1162 /* Create the File Object */
1163 Status
= ObCreateObject(KernelMode
,
1168 sizeof(FILE_OBJECT
),
1171 (PVOID
*)&CreatedFileObject
);
1172 if (!NT_SUCCESS(Status
))
1174 DPRINT1("Could not create FileObject\n");
1178 /* Choose Device Object */
1179 if (FileObject
) DeviceObject
= FileObject
->DeviceObject
;
1180 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1183 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1185 /* Set File Object Data */
1186 CreatedFileObject
->DeviceObject
= DeviceObject
;
1187 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
1188 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1189 CreatedFileObject
->Flags
|= FO_STREAM_FILE
;
1191 /* Initialize Lock and Event */
1192 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
1193 KeInitializeEvent(&CreatedFileObject
->Lock
, SynchronizationEvent
, TRUE
);
1196 return CreatedFileObject
;
1204 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1205 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1206 OUT PHANDLE FileObjectHandle OPTIONAL
)
1217 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1218 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1229 IoGetFileObjectGenericMapping(VOID
)
1231 return &IopFileMapping
;
1239 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
1241 /* Return the flag status */
1242 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
1250 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
1251 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
1254 return STATUS_NOT_IMPLEMENTED
;
1262 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1263 IN FILE_INFORMATION_CLASS FileInformationClass
,
1265 OUT PVOID FileInformation
,
1266 OUT PULONG ReturnedLength
)
1268 IO_STATUS_BLOCK IoStatusBlock
;
1270 PDEVICE_OBJECT DeviceObject
;
1271 PIO_STACK_LOCATION StackPtr
;
1272 BOOLEAN LocalEvent
= FALSE
;
1276 ASSERT(FileInformation
!= NULL
);
1278 Status
= ObReferenceObjectByPointer(FileObject
,
1279 FILE_READ_ATTRIBUTES
,
1282 if (!NT_SUCCESS(Status
)) return(Status
);
1284 DPRINT("FileObject 0x%p\n", FileObject
);
1286 /* Get the Device Object */
1287 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1289 /* Check if we should use Sync IO or not */
1290 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1292 /* Use File Object event */
1293 KeClearEvent(&FileObject
->Event
);
1297 /* Use local event */
1298 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1302 /* Allocate the IRP */
1303 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1306 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1307 Irp
->RequestorMode
= KernelMode
;
1308 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1309 Irp
->UserIosb
= &IoStatusBlock
;
1310 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1311 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1312 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1314 /* Set the Stack Data */
1315 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1316 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1317 StackPtr
->FileObject
= FileObject
;
1319 /* Set Parameters */
1320 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1321 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1323 /* Call the Driver */
1324 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
1326 if (Status
== STATUS_PENDING
)
1330 KeWaitForSingleObject(&Event
,
1333 FileObject
->Flags
& FO_ALERTABLE_IO
,
1335 Status
= IoStatusBlock
.Status
;
1339 KeWaitForSingleObject(&FileObject
->Event
,
1342 FileObject
->Flags
& FO_ALERTABLE_IO
,
1344 Status
= FileObject
->FinalStatus
;
1349 /* Return the Length and Status. ReturnedLength is NOT optional */
1350 *ReturnedLength
= IoStatusBlock
.Information
;
1359 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
1363 return STATUS_NOT_IMPLEMENTED
;
1367 * @name NtCancelIoFile
1369 * Cancel all pending I/O operations in the current thread for specified
1373 * Handle to file object to cancel requests for. No specific
1374 * access rights are needed.
1375 * @param IoStatusBlock
1376 * Pointer to status block which is filled with final completition
1377 * status on successful return.
1385 NtCancelIoFile(IN HANDLE FileHandle
,
1386 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1389 PFILE_OBJECT FileObject
;
1391 PLIST_ENTRY IrpEntry
;
1394 BOOLEAN OurIrpsInList
= FALSE
;
1395 LARGE_INTEGER Interval
;
1397 if ((ULONG_PTR
)IoStatusBlock
>= (ULONG_PTR
)MmUserProbeAddress
&&
1398 KeGetPreviousMode() == UserMode
)
1399 return STATUS_ACCESS_VIOLATION
;
1401 Status
= ObReferenceObjectByHandle(FileHandle
, 0, IoFileObjectType
,
1402 KeGetPreviousMode(), (PVOID
*)&FileObject
,
1404 if (!NT_SUCCESS(Status
))
1407 /* IRP cancellations are synchronized at APC_LEVEL. */
1408 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1411 * Walk the list of active IRPs and cancel the ones that belong to
1415 Thread
= PsGetCurrentThread();
1416 for (IrpEntry
= Thread
->IrpList
.Flink
;
1417 IrpEntry
!= &Thread
->IrpList
;
1418 IrpEntry
= IrpEntry
->Flink
)
1420 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1421 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1424 /* Don't break here, we want to cancel all IRPs for the file object. */
1425 OurIrpsInList
= TRUE
;
1429 KfLowerIrql(OldIrql
);
1431 while (OurIrpsInList
)
1433 OurIrpsInList
= FALSE
;
1435 /* Wait a short while and then look if all our IRPs were completed. */
1436 Interval
.QuadPart
= -1000000; /* 100 milliseconds */
1437 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1439 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1442 * Look in the list if all IRPs for the specified file object
1443 * are completed (or cancelled). If someone sends a new IRP
1444 * for our file object while we're here we can happily loop
1448 for (IrpEntry
= Thread
->IrpList
.Flink
;
1449 IrpEntry
!= &Thread
->IrpList
;
1450 IrpEntry
= IrpEntry
->Flink
)
1452 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1453 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1455 OurIrpsInList
= TRUE
;
1460 KfLowerIrql(OldIrql
);
1465 IoStatusBlock
->Status
= STATUS_SUCCESS
;
1466 IoStatusBlock
->Information
= 0;
1467 Status
= STATUS_SUCCESS
;
1471 Status
= STATUS_UNSUCCESSFUL
;
1475 ObDereferenceObject(FileObject
);
1485 * Entry point to call IoCreateFile with
1486 * default parameters.
1496 * Code originally in NtCreateFile moved in IoCreateFile.
1502 NtCreateFile(PHANDLE FileHandle
,
1503 ACCESS_MASK DesiredAccess
,
1504 POBJECT_ATTRIBUTES ObjectAttributes
,
1505 PIO_STATUS_BLOCK IoStatusBlock
,
1506 PLARGE_INTEGER AllocateSize
,
1507 ULONG FileAttributes
,
1509 ULONG CreateDisposition
,
1510 ULONG CreateOptions
,
1514 /* Call the I/O Function */
1515 return IoCreateFile(FileHandle
,
1533 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
1534 IN ACCESS_MASK DesiredAccess
,
1535 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1536 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1537 IN ULONG CreateOptions
,
1538 IN ULONG MailslotQuota
,
1539 IN ULONG MaxMessageSize
,
1540 IN PLARGE_INTEGER TimeOut
)
1542 MAILSLOT_CREATE_PARAMETERS Buffer
;
1544 DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, "
1545 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
1546 FileHandle
,DesiredAccess
,ObjectAttributes
,
1547 ObjectAttributes
->ObjectName
->Buffer
);
1550 /* Check for Timeout */
1554 Buffer
.TimeoutSpecified
= TRUE
;
1556 /* FIXME: Add SEH */
1557 Buffer
.ReadTimeout
= *TimeOut
;
1562 Buffer
.TimeoutSpecified
= FALSE
;
1566 Buffer
.MailslotQuota
= MailslotQuota
;
1567 Buffer
.MaximumMessageSize
= MaxMessageSize
;
1570 return IoCreateFile(FileHandle
,
1575 FILE_ATTRIBUTE_NORMAL
,
1576 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1581 CreateFileTypeMailslot
,
1588 NtCreateNamedPipeFile(PHANDLE FileHandle
,
1589 ACCESS_MASK DesiredAccess
,
1590 POBJECT_ATTRIBUTES ObjectAttributes
,
1591 PIO_STATUS_BLOCK IoStatusBlock
,
1593 ULONG CreateDisposition
,
1594 ULONG CreateOptions
,
1595 ULONG NamedPipeType
,
1597 ULONG CompletionMode
,
1598 ULONG MaximumInstances
,
1600 ULONG OutboundQuota
,
1601 PLARGE_INTEGER DefaultTimeout
)
1603 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
1605 DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, "
1606 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
1607 FileHandle
,DesiredAccess
,ObjectAttributes
,
1608 ObjectAttributes
->ObjectName
->Buffer
);
1611 /* Check for Timeout */
1615 Buffer
.TimeoutSpecified
= TRUE
;
1617 /* FIXME: Add SEH */
1618 Buffer
.DefaultTimeout
= *DefaultTimeout
;
1623 Buffer
.TimeoutSpecified
= FALSE
;
1627 Buffer
.NamedPipeType
= NamedPipeType
;
1628 Buffer
.ReadMode
= ReadMode
;
1629 Buffer
.CompletionMode
= CompletionMode
;
1630 Buffer
.MaximumInstances
= MaximumInstances
;
1631 Buffer
.InboundQuota
= InboundQuota
;
1632 Buffer
.OutboundQuota
= OutboundQuota
;
1635 return IoCreateFile(FileHandle
,
1640 FILE_ATTRIBUTE_NORMAL
,
1646 CreateFileTypeNamedPipe
,
1669 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
1672 return(STATUS_NOT_IMPLEMENTED
);
1680 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1681 IN HANDLE Event OPTIONAL
,
1682 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1683 IN PVOID UserApcContext OPTIONAL
,
1684 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1685 IN ULONG IoControlCode
,
1686 IN PVOID InputBuffer
,
1687 IN ULONG InputBufferLength OPTIONAL
,
1688 OUT PVOID OutputBuffer
,
1689 IN ULONG OutputBufferLength OPTIONAL
)
1691 /* Call the Generic Function */
1692 return IopDeviceFsIoControl(DeviceHandle
,
1710 NtFsControlFile(IN HANDLE DeviceHandle
,
1711 IN HANDLE Event OPTIONAL
,
1712 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1713 IN PVOID UserApcContext OPTIONAL
,
1714 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1715 IN ULONG IoControlCode
,
1716 IN PVOID InputBuffer
,
1717 IN ULONG InputBufferLength OPTIONAL
,
1718 OUT PVOID OutputBuffer
,
1719 IN ULONG OutputBufferLength OPTIONAL
)
1721 return IopDeviceFsIoControl(DeviceHandle
,
1736 NtFlushWriteBuffer(VOID
)
1738 KeFlushWriteBuffer();
1739 return STATUS_SUCCESS
;
1743 * FUNCTION: Flushes cached file data to disk
1745 * FileHandle = Points to the file
1746 * IoStatusBlock = Caller must supply storage to receive the result of
1747 * the flush buffers operation. The information field is
1748 * set to number of bytes flushed to disk.
1750 * REMARKS: This function maps to the win32 FlushFileBuffers
1754 NtFlushBuffersFile(IN HANDLE FileHandle
,
1755 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1757 PFILE_OBJECT FileObject
= NULL
;
1759 PIO_STACK_LOCATION StackPtr
;
1761 PDEVICE_OBJECT DeviceObject
;
1763 BOOLEAN LocalEvent
= FALSE
;
1764 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1766 /* Get the File Object */
1767 Status
= ObReferenceObjectByHandle(FileHandle
,
1771 (PVOID
*)&FileObject
,
1773 if (Status
!= STATUS_SUCCESS
) return(Status
);
1775 /* Check if this is a direct open or not */
1776 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1778 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1782 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1785 /* Check if we should use Sync IO or not */
1786 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1788 /* Use File Object event */
1789 KeClearEvent(&FileObject
->Event
);
1793 /* Use local event */
1794 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1798 /* Allocate the IRP */
1799 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
1801 ObDereferenceObject(FileObject
);
1802 return STATUS_INSUFFICIENT_RESOURCES
;
1805 /* Set up the IRP */
1806 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1807 Irp
->RequestorMode
= PreviousMode
;
1808 Irp
->UserIosb
= IoStatusBlock
;
1809 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1810 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1811 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1813 /* Set up Stack Data */
1814 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1815 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1816 StackPtr
->FileObject
= FileObject
;
1818 /* Call the Driver */
1819 Status
= IoCallDriver(DeviceObject
, Irp
);
1820 if (Status
== STATUS_PENDING
)
1824 KeWaitForSingleObject(&Event
,
1827 FileObject
->Flags
& FO_ALERTABLE_IO
,
1829 Status
= IoStatusBlock
->Status
;
1833 KeWaitForSingleObject(&FileObject
->Event
,
1836 FileObject
->Flags
& FO_ALERTABLE_IO
,
1838 Status
= FileObject
->FinalStatus
;
1842 /* Return the Status */
1851 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1852 IN HANDLE Event OPTIONAL
,
1853 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1854 IN PVOID ApcContext OPTIONAL
,
1855 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1857 IN ULONG BufferSize
,
1858 IN ULONG CompletionFilter
,
1859 IN BOOLEAN WatchTree
)
1862 PDEVICE_OBJECT DeviceObject
;
1863 PFILE_OBJECT FileObject
;
1864 PIO_STACK_LOCATION IoStack
;
1865 KPROCESSOR_MODE PreviousMode
;
1866 NTSTATUS Status
= STATUS_SUCCESS
;
1868 DPRINT("NtNotifyChangeDirectoryFile()\n");
1872 PreviousMode
= ExGetPreviousMode();
1874 if(PreviousMode
!= KernelMode
)
1878 ProbeForWrite(IoStatusBlock
,
1879 sizeof(IO_STATUS_BLOCK
),
1883 ProbeForWrite(Buffer
,
1890 Status
= _SEH_GetExceptionCode();
1894 if(!NT_SUCCESS(Status
))
1900 Status
= ObReferenceObjectByHandle(FileHandle
,
1901 FILE_LIST_DIRECTORY
,
1904 (PVOID
*)&FileObject
,
1906 if (Status
!= STATUS_SUCCESS
) return(Status
);
1909 DeviceObject
= FileObject
->DeviceObject
;
1912 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1915 ObDereferenceObject(FileObject
);
1916 return STATUS_UNSUCCESSFUL
;
1921 Event
= &FileObject
->Event
;
1924 /* Trigger FileObject/Event dereferencing */
1925 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1926 Irp
->RequestorMode
= PreviousMode
;
1927 Irp
->UserIosb
= IoStatusBlock
;
1928 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1929 Irp
->UserEvent
= Event
;
1930 KeResetEvent( Event
);
1931 Irp
->UserBuffer
= Buffer
;
1932 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1933 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1935 IoStack
= IoGetNextIrpStackLocation(Irp
);
1937 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1938 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1940 IoStack
->Control
= 0;
1941 IoStack
->DeviceObject
= DeviceObject
;
1942 IoStack
->FileObject
= FileObject
;
1946 IoStack
->Flags
= SL_WATCH_TREE
;
1949 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1950 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1952 Status
= IoCallDriver(FileObject
->DeviceObject
,Irp
);
1954 /* FIXME: Should we wait here or not for synchronously opened files? */
1964 NtLockFile(IN HANDLE FileHandle
,
1965 IN HANDLE EventHandle OPTIONAL
,
1966 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1967 IN PVOID ApcContext OPTIONAL
,
1968 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1969 IN PLARGE_INTEGER ByteOffset
,
1970 IN PLARGE_INTEGER Length
,
1972 IN BOOLEAN FailImmediately
,
1973 IN BOOLEAN ExclusiveLock
)
1975 PFILE_OBJECT FileObject
= NULL
;
1976 PLARGE_INTEGER LocalLength
= NULL
;
1978 PIO_STACK_LOCATION StackPtr
;
1979 PDEVICE_OBJECT DeviceObject
;
1980 PKEVENT Event
= NULL
;
1981 BOOLEAN LocalEvent
= FALSE
;
1982 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1983 NTSTATUS Status
= STATUS_SUCCESS
;
1984 OBJECT_HANDLE_INFORMATION HandleInformation
;
1986 /* FIXME: instead of this, use SEH */
1987 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
1989 /* Get File Object */
1990 Status
= ObReferenceObjectByHandle(FileHandle
,
1994 (PVOID
*)&FileObject
,
1995 &HandleInformation
);
1996 if (!NT_SUCCESS(Status
)) return Status
;
1998 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
1999 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2001 DPRINT1("Invalid access rights\n");
2002 ObDereferenceObject(FileObject
);
2003 return STATUS_ACCESS_DENIED
;
2006 /* Get Event Object */
2009 Status
= ObReferenceObjectByHandle(EventHandle
,
2015 if (Status
!= STATUS_SUCCESS
) return(Status
);
2016 KeClearEvent(Event
);
2019 /* Check if this is a direct open or not */
2020 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2022 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2026 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2029 /* Check if we should use Sync IO or not */
2030 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2032 /* Use File Object event */
2033 KeClearEvent(&FileObject
->Event
);
2040 /* Allocate the IRP */
2041 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2043 ObDereferenceObject(FileObject
);
2044 return STATUS_INSUFFICIENT_RESOURCES
;
2047 /* Allocate local buffer */
2048 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2049 sizeof(LARGE_INTEGER
),
2054 ObDereferenceObject(FileObject
);
2055 return STATUS_INSUFFICIENT_RESOURCES
;
2057 *LocalLength
= *Length
;
2059 /* Set up the IRP */
2060 Irp
->RequestorMode
= PreviousMode
;
2061 Irp
->UserIosb
= IoStatusBlock
;
2062 Irp
->UserEvent
= Event
;
2063 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2064 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2066 /* Set up Stack Data */
2067 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2068 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2069 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
2070 StackPtr
->FileObject
= FileObject
;
2072 /* Set Parameters */
2073 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2074 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
2075 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
2078 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
2079 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
2081 /* Call the Driver */
2082 FileObject
->LockOperation
= TRUE
;
2083 Status
= IoCallDriver(DeviceObject
, Irp
);
2084 if (Status
== STATUS_PENDING
)
2088 KeWaitForSingleObject(&FileObject
->Event
,
2091 FileObject
->Flags
& FO_ALERTABLE_IO
,
2093 Status
= FileObject
->FinalStatus
;
2097 /* Return the Status */
2106 * Opens an existing file (simpler than NtCreateFile).
2110 * Variable that receives the file handle on return;
2113 * Access desired by the caller to the file;
2116 * Structue describing the file to be opened;
2118 * IoStatusBlock (OUT)
2119 * Receives details about the result of the
2123 * Type of shared access the caller requires;
2126 * Options for the file open.
2138 NtOpenFile(PHANDLE FileHandle
,
2139 ACCESS_MASK DesiredAccess
,
2140 POBJECT_ATTRIBUTES ObjectAttributes
,
2141 PIO_STATUS_BLOCK IoStatusBlock
,
2145 /* Call the I/O Function */
2146 return IoCreateFile(FileHandle
,
2164 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2165 OUT PFILE_BASIC_INFORMATION FileInformation
)
2167 IO_STATUS_BLOCK IoStatusBlock
;
2172 Status
= ZwOpenFile(&FileHandle
,
2173 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2176 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2177 FILE_SYNCHRONOUS_IO_NONALERT
);
2178 if (!NT_SUCCESS (Status
))
2180 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2184 /* Get file attributes */
2185 Status
= ZwQueryInformationFile(FileHandle
,
2188 sizeof(FILE_BASIC_INFORMATION
),
2189 FileBasicInformation
);
2190 if (!NT_SUCCESS (Status
))
2192 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2195 ZwClose(FileHandle
);
2202 * FUNCTION: Queries a directory file.
2204 * FileHandle = Handle to a directory file
2205 * EventHandle = Handle to the event signaled on completion
2206 * ApcRoutine = Asynchroneous procedure callback, called on completion
2207 * ApcContext = Argument to the apc.
2208 * IoStatusBlock = Caller supplies storage for extended status information.
2209 * FileInformation = Caller supplies storage for the resulting information.
2211 * FileNameInformation FILE_NAMES_INFORMATION
2212 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2213 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2214 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2216 * Length = Size of the storage supplied
2217 * FileInformationClass = Indicates the type of information requested.
2218 * ReturnSingleEntry = Specify true if caller only requests the first
2220 * FileName = Initial directory name to query, that may contain wild
2222 * RestartScan = Number of times the action should be repeated
2223 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2224 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2225 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2229 NtQueryDirectoryFile(IN HANDLE FileHandle
,
2230 IN HANDLE PEvent OPTIONAL
,
2231 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2232 IN PVOID ApcContext OPTIONAL
,
2233 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2234 OUT PVOID FileInformation
,
2236 IN FILE_INFORMATION_CLASS FileInformationClass
,
2237 IN BOOLEAN ReturnSingleEntry
,
2238 IN PUNICODE_STRING FileName OPTIONAL
,
2239 IN BOOLEAN RestartScan
)
2242 PDEVICE_OBJECT DeviceObject
;
2243 PFILE_OBJECT FileObject
;
2244 PIO_STACK_LOCATION StackPtr
;
2245 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2246 NTSTATUS Status
= STATUS_SUCCESS
;
2247 BOOLEAN LocalEvent
= FALSE
;
2248 PKEVENT Event
= NULL
;
2250 DPRINT("NtQueryDirectoryFile()\n");
2253 /* Validate User-Mode Buffers */
2254 if(PreviousMode
!= KernelMode
)
2258 ProbeForWrite(IoStatusBlock
,
2259 sizeof(IO_STATUS_BLOCK
),
2261 ProbeForWrite(FileInformation
,
2267 Status
= _SEH_GetExceptionCode();
2271 if(!NT_SUCCESS(Status
)) return Status
;
2274 /* Get File Object */
2275 Status
= ObReferenceObjectByHandle(FileHandle
,
2276 FILE_LIST_DIRECTORY
,
2279 (PVOID
*)&FileObject
,
2281 if (Status
!= STATUS_SUCCESS
) return(Status
);
2283 /* Get Event Object */
2286 Status
= ObReferenceObjectByHandle(PEvent
,
2292 if (Status
!= STATUS_SUCCESS
) return(Status
);
2293 KeClearEvent(Event
);
2296 /* Check if this is a direct open or not */
2297 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2299 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2303 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2306 /* Check if we should use Sync IO or not */
2307 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2309 /* Use File Object event */
2310 KeClearEvent(&FileObject
->Event
);
2317 /* Allocate the IRP */
2318 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2320 ObDereferenceObject(FileObject
);
2321 return STATUS_INSUFFICIENT_RESOURCES
;
2324 /* Set up the IRP */
2325 Irp
->RequestorMode
= PreviousMode
;
2326 Irp
->UserIosb
= IoStatusBlock
;
2327 Irp
->UserEvent
= Event
;
2328 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2329 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2330 Irp
->UserBuffer
= FileInformation
;
2331 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2332 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2334 /* Set up Stack Data */
2335 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2336 StackPtr
->FileObject
= FileObject
;
2337 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2338 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2340 /* Set Parameters */
2341 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
= FileInformationClass
;
2342 StackPtr
->Parameters
.QueryDirectory
.FileName
= FileName
;
2343 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2344 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2345 StackPtr
->Flags
= 0;
2346 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2347 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2349 /* Call the Driver */
2350 Status
= IoCallDriver(DeviceObject
, Irp
);
2351 if (Status
== STATUS_PENDING
)
2355 KeWaitForSingleObject(&FileObject
->Event
,
2358 FileObject
->Flags
& FO_ALERTABLE_IO
,
2360 Status
= FileObject
->FinalStatus
;
2364 /* Return the Status */
2372 NtQueryEaFile(IN HANDLE FileHandle
,
2373 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2376 IN BOOLEAN ReturnSingleEntry
,
2377 IN PVOID EaList OPTIONAL
,
2378 IN ULONG EaListLength
,
2379 IN PULONG EaIndex OPTIONAL
,
2380 IN BOOLEAN RestartScan
)
2383 return STATUS_NOT_IMPLEMENTED
;
2388 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2389 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2391 IO_STATUS_BLOCK IoStatusBlock
;
2396 Status
= ZwOpenFile(&FileHandle
,
2397 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2400 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2401 FILE_SYNCHRONOUS_IO_NONALERT
);
2402 if (!NT_SUCCESS (Status
))
2404 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2408 /* Get file attributes */
2409 Status
= ZwQueryInformationFile(FileHandle
,
2412 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2413 FileNetworkOpenInformation
);
2414 if (!NT_SUCCESS (Status
))
2416 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2419 ZwClose (FileHandle
);
2427 NtQueryInformationFile(HANDLE FileHandle
,
2428 PIO_STATUS_BLOCK IoStatusBlock
,
2429 PVOID FileInformation
,
2431 FILE_INFORMATION_CLASS FileInformationClass
)
2433 OBJECT_HANDLE_INFORMATION HandleInformation
;
2434 PFILE_OBJECT FileObject
;
2437 PDEVICE_OBJECT DeviceObject
;
2438 PIO_STACK_LOCATION StackPtr
;
2439 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2441 BOOLEAN LocalEvent
= FALSE
;
2442 BOOLEAN Failed
= FALSE
;
2444 ASSERT(IoStatusBlock
!= NULL
);
2445 ASSERT(FileInformation
!= NULL
);
2447 DPRINT("NtQueryInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
2448 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2449 Length
, FileInformationClass
);
2451 /* Reference the Handle */
2452 Status
= ObReferenceObjectByHandle(FileHandle
,
2456 (PVOID
*)&FileObject
,
2457 &HandleInformation
);
2458 if (!NT_SUCCESS(Status
)) return Status
;
2460 /* Check information class specific access rights */
2461 switch (FileInformationClass
)
2463 case FileBasicInformation
:
2464 if (!(HandleInformation
.GrantedAccess
& FILE_READ_ATTRIBUTES
))
2468 case FilePositionInformation
:
2469 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2470 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2480 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2481 ObDereferenceObject(FileObject
);
2482 return STATUS_ACCESS_DENIED
;
2485 if (FileInformationClass
== FilePositionInformation
)
2487 if (Length
< sizeof(FILE_POSITION_INFORMATION
))
2489 Status
= STATUS_BUFFER_OVERFLOW
;
2495 ((PFILE_POSITION_INFORMATION
)FileInformation
)->CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2496 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2497 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2501 Status
= _SEH_GetExceptionCode();
2505 ObDereferenceObject(FileObject
);
2509 DPRINT("FileObject 0x%p\n", FileObject
);
2511 /* Check if this is a direct open or not */
2512 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2514 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2518 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2521 if (FileInformationClass
== FileAlignmentInformation
)
2523 if (Length
< sizeof(FILE_ALIGNMENT_INFORMATION
))
2525 Status
= STATUS_BUFFER_OVERFLOW
;
2531 ((PFILE_ALIGNMENT_INFORMATION
)FileInformation
)->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2532 IoStatusBlock
->Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2533 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2537 Status
= _SEH_GetExceptionCode();
2541 ObDereferenceObject(FileObject
);
2545 /* Check if we should use Sync IO or not */
2546 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2548 /* Use File Object event */
2549 KeClearEvent(&FileObject
->Event
);
2553 /* Use local event */
2554 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2558 /* Allocate the IRP */
2559 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
2561 ObDereferenceObject(FileObject
);
2562 return STATUS_INSUFFICIENT_RESOURCES
;
2565 /* Allocate the System Buffer */
2566 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2571 ObDereferenceObject(FileObject
);
2572 return STATUS_INSUFFICIENT_RESOURCES
;
2575 /* Set up the IRP */
2576 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2577 Irp
->RequestorMode
= PreviousMode
;
2578 Irp
->UserIosb
= IoStatusBlock
;
2579 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2580 Irp
->UserBuffer
= FileInformation
;
2581 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2582 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
2583 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2585 /* Set up Stack Data */
2586 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2587 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2588 StackPtr
->FileObject
= FileObject
;
2590 /* Set the Parameters */
2591 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2592 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2594 /* Call the Driver */
2595 Status
= IoCallDriver(DeviceObject
, Irp
);
2596 if (Status
== STATUS_PENDING
)
2600 KeWaitForSingleObject(&Event
,
2603 FileObject
->Flags
& FO_ALERTABLE_IO
,
2605 Status
= IoStatusBlock
->Status
;
2609 KeWaitForSingleObject(&FileObject
->Event
,
2612 FileObject
->Flags
& FO_ALERTABLE_IO
,
2614 Status
= FileObject
->FinalStatus
;
2618 /* Return the Status */
2627 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2628 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2631 IN BOOLEAN ReturnSingleEntry
,
2632 IN PVOID SidList OPTIONAL
,
2633 IN ULONG SidListLength
,
2634 IN PSID StartSid OPTIONAL
,
2635 IN BOOLEAN RestartScan
)
2638 return STATUS_NOT_IMPLEMENTED
;
2657 NtReadFile(IN HANDLE FileHandle
,
2658 IN HANDLE Event OPTIONAL
,
2659 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2660 IN PVOID ApcContext OPTIONAL
,
2661 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2664 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2665 IN PULONG Key OPTIONAL
)
2667 NTSTATUS Status
= STATUS_SUCCESS
;
2668 PFILE_OBJECT FileObject
;
2670 PDEVICE_OBJECT DeviceObject
;
2671 PIO_STACK_LOCATION StackPtr
;
2672 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2673 BOOLEAN LocalEvent
= FALSE
;
2674 PKEVENT EventObject
= NULL
;
2676 DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
2677 "IoStatusBlock 0x%p)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2681 /* Validate User-Mode Buffers */
2682 if(PreviousMode
!= KernelMode
)
2686 ProbeForWrite(IoStatusBlock
,
2687 sizeof(IO_STATUS_BLOCK
),
2690 ProbeForWrite(Buffer
,
2697 Status
= _SEH_GetExceptionCode();
2701 if(!NT_SUCCESS(Status
)) return Status
;
2704 /* Get File Object */
2705 Status
= ObReferenceObjectByHandle(FileHandle
,
2709 (PVOID
*)&FileObject
,
2711 if (!NT_SUCCESS(Status
)) return Status
;
2713 /* Check the Byte Offset */
2715 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
2716 ByteOffset
->u
.HighPart
== -1))
2718 /* a valid ByteOffset is required if asynch. op. */
2719 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2721 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2722 ObDereferenceObject(FileObject
);
2723 return STATUS_INVALID_PARAMETER
;
2726 /* Use the Current Byte OFfset */
2727 ByteOffset
= &FileObject
->CurrentByteOffset
;
2730 /* Check for event */
2734 Status
= ObReferenceObjectByHandle(Event
,
2738 (PVOID
*)&EventObject
,
2740 if (!NT_SUCCESS(Status
))
2742 ObDereferenceObject(FileObject
);
2745 KeClearEvent(EventObject
);
2748 /* Check if this is a direct open or not */
2749 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2751 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2755 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2758 /* Check if we should use Sync IO or not */
2759 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2761 /* Use File Object event */
2762 KeClearEvent(&FileObject
->Event
);
2769 /* Create the IRP */
2772 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2781 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2786 Status
= _SEH_GetExceptionCode();
2790 /* Cleanup if IRP Allocation Failed */
2791 if (!NT_SUCCESS(Status
))
2793 if (Event
) ObDereferenceObject(EventObject
);
2794 ObDereferenceObject(FileObject
);
2798 /* Set up IRP Data */
2799 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2800 Irp
->RequestorMode
= PreviousMode
;
2801 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2802 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2803 Irp
->Flags
|= IRP_READ_OPERATION
;
2806 * Vfat doesn't handle non cached files correctly.
2808 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2811 /* Setup Stack Data */
2812 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2813 StackPtr
->FileObject
= FileObject
;
2814 StackPtr
->Parameters
.Read
.Key
= Key
? *Key
: 0;
2816 /* Call the Driver */
2817 Status
= IoCallDriver(DeviceObject
, Irp
);
2818 if (Status
== STATUS_PENDING
)
2822 KeWaitForSingleObject(&FileObject
->Event
,
2825 FileObject
->Flags
& FO_ALERTABLE_IO
,
2827 Status
= FileObject
->FinalStatus
;
2831 /* Return the Status */
2849 NtReadFileScatter(IN HANDLE FileHandle
,
2850 IN HANDLE Event OPTIONAL
,
2851 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2852 IN PVOID UserApcContext OPTIONAL
,
2853 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2854 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2855 IN ULONG BufferLength
,
2856 IN PLARGE_INTEGER ByteOffset
,
2857 IN PULONG Key OPTIONAL
)
2860 return(STATUS_NOT_IMPLEMENTED
);
2868 NtSetEaFile(IN HANDLE FileHandle
,
2869 IN PIO_STATUS_BLOCK IoStatusBlock
,
2871 IN ULONG EaBufferSize
)
2874 return STATUS_NOT_IMPLEMENTED
;
2881 NtSetInformationFile(HANDLE FileHandle
,
2882 PIO_STATUS_BLOCK IoStatusBlock
,
2883 PVOID FileInformation
,
2885 FILE_INFORMATION_CLASS FileInformationClass
)
2887 OBJECT_HANDLE_INFORMATION HandleInformation
;
2888 PIO_STACK_LOCATION StackPtr
;
2889 PFILE_OBJECT FileObject
;
2890 PDEVICE_OBJECT DeviceObject
;
2893 BOOLEAN LocalEvent
= FALSE
;
2894 NTSTATUS Status
= STATUS_SUCCESS
;
2895 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2896 BOOLEAN Failed
= FALSE
;
2898 DPRINT("NtSetInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
2899 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2900 Length
, FileInformationClass
);
2902 if (PreviousMode
!= KernelMode
)
2906 if (IoStatusBlock
!= NULL
)
2908 ProbeForWrite(IoStatusBlock
,
2909 sizeof(IO_STATUS_BLOCK
),
2915 ProbeForRead(FileInformation
,
2922 Status
= _SEH_GetExceptionCode();
2926 if (!NT_SUCCESS(Status
))
2933 ASSERT(IoStatusBlock
!= NULL
);
2934 ASSERT(FileInformation
!= NULL
);
2937 /* Get the file object from the file handle */
2938 Status
= ObReferenceObjectByHandle(FileHandle
,
2942 (PVOID
*)&FileObject
,
2943 &HandleInformation
);
2944 if (!NT_SUCCESS(Status
)) return Status
;
2946 /* Check information class specific access rights */
2947 switch (FileInformationClass
)
2949 case FileBasicInformation
:
2950 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_ATTRIBUTES
))
2954 case FileDispositionInformation
:
2955 if (!(HandleInformation
.GrantedAccess
& DELETE
))
2959 case FilePositionInformation
:
2960 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2961 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2965 case FileEndOfFileInformation
:
2966 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
))
2976 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2977 ObDereferenceObject(FileObject
);
2978 return STATUS_ACCESS_DENIED
;
2981 DPRINT("FileObject 0x%p\n", FileObject
);
2983 if (FileInformationClass
== FilePositionInformation
)
2985 if (Length
< sizeof(FILE_POSITION_INFORMATION
))
2987 Status
= STATUS_BUFFER_OVERFLOW
;
2993 FileObject
->CurrentByteOffset
= ((PFILE_POSITION_INFORMATION
)FileInformation
)->CurrentByteOffset
;
2994 IoStatusBlock
->Information
= 0;
2995 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2999 Status
= _SEH_GetExceptionCode();
3003 ObDereferenceObject(FileObject
);
3007 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3008 /* Handle IO Completion Port quickly */
3009 if (FileInformationClass
== FileCompletionInformation
)
3012 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
3013 PIO_COMPLETION_CONTEXT Context
;
3015 if (Length
< sizeof(FILE_COMPLETION_INFORMATION
))
3017 Status
= STATUS_INFO_LENGTH_MISMATCH
;
3021 /* Reference the Port */
3022 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3023 IO_COMPLETION_MODIFY_STATE
,
3028 if (NT_SUCCESS(Status
))
3030 /* Allocate the Context */
3031 Context
= ExAllocatePoolWithTag(PagedPool
,
3032 sizeof(IO_COMPLETION_CONTEXT
),
3033 TAG('I', 'o', 'C', 'p'));
3036 Context
->Key
= CompletionInfo
->Key
;
3037 Context
->Port
= Queue
;
3038 FileObject
->CompletionContext
= Context
;
3040 /* Dereference the Port now */
3041 ObDereferenceObject(Queue
);
3045 /* Complete the I/O */
3046 ObDereferenceObject(FileObject
);
3050 /* Check if this is a direct open or not */
3051 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3053 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3057 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3060 /* Check if we should use Sync IO or not */
3061 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3063 /* Use File Object event */
3064 KeClearEvent(&FileObject
->Event
);
3068 /* Use local event */
3069 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3073 /* Allocate the IRP */
3074 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
3076 ObDereferenceObject(FileObject
);
3077 return STATUS_INSUFFICIENT_RESOURCES
;
3080 /* Allocate the System Buffer */
3081 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
3085 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3089 /* Copy the data inside */
3090 if (PreviousMode
!= KernelMode
)
3094 /* no need to probe again */
3095 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3101 Status
= _SEH_GetExceptionCode();
3105 if (!NT_SUCCESS(Status
))
3107 ExFreePoolWithTag(Irp
->AssociatedIrp
.SystemBuffer
,
3109 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3112 ObDereferenceObject(FileObject
);
3118 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3123 /* Set up the IRP */
3124 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3125 Irp
->RequestorMode
= PreviousMode
;
3126 Irp
->UserIosb
= IoStatusBlock
;
3127 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
3128 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3129 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
3130 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3132 /* Set up Stack Data */
3133 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3134 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
3135 StackPtr
->FileObject
= FileObject
;
3137 /* Set the Parameters */
3138 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
3139 StackPtr
->Parameters
.SetFile
.Length
= Length
;
3141 /* Call the Driver */
3142 Status
= IoCallDriver(DeviceObject
, Irp
);
3143 if (Status
== STATUS_PENDING
)
3147 KeWaitForSingleObject(&Event
,
3150 FileObject
->Flags
& FO_ALERTABLE_IO
,
3154 Status
= IoStatusBlock
->Status
;
3158 Status
= _SEH_GetExceptionCode();
3164 KeWaitForSingleObject(&FileObject
->Event
,
3167 FileObject
->Flags
& FO_ALERTABLE_IO
,
3171 Status
= FileObject
->FinalStatus
;
3175 Status
= _SEH_GetExceptionCode();
3181 /* Return the Status */
3190 NtSetQuotaInformationFile(HANDLE FileHandle
,
3191 PIO_STATUS_BLOCK IoStatusBlock
,
3192 PFILE_QUOTA_INFORMATION Buffer
,
3196 return STATUS_NOT_IMPLEMENTED
;
3204 NtUnlockFile(IN HANDLE FileHandle
,
3205 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3206 IN PLARGE_INTEGER ByteOffset
,
3207 IN PLARGE_INTEGER Length
,
3208 OUT PULONG Key OPTIONAL
)
3210 PFILE_OBJECT FileObject
= NULL
;
3211 PLARGE_INTEGER LocalLength
= NULL
;
3213 PIO_STACK_LOCATION StackPtr
;
3214 PDEVICE_OBJECT DeviceObject
;
3216 BOOLEAN LocalEvent
= FALSE
;
3217 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3218 NTSTATUS Status
= STATUS_SUCCESS
;
3219 OBJECT_HANDLE_INFORMATION HandleInformation
;
3221 /* FIXME: instead of this, use SEH */
3222 if (!Length
|| !ByteOffset
) return STATUS_INVALID_PARAMETER
;
3224 /* Get File Object */
3225 Status
= ObReferenceObjectByHandle(FileHandle
,
3229 (PVOID
*)&FileObject
,
3230 &HandleInformation
);
3231 if (!NT_SUCCESS(Status
)) return Status
;
3233 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
3234 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3236 DPRINT1("Invalid access rights\n");
3237 ObDereferenceObject(FileObject
);
3238 return STATUS_ACCESS_DENIED
;
3241 /* Check if this is a direct open or not */
3242 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3244 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3248 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3251 /* Check if we should use Sync IO or not */
3252 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3254 /* Use File Object event */
3255 KeClearEvent(&FileObject
->Event
);
3259 /* Use local event */
3260 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
3264 /* Allocate the IRP */
3265 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
)))
3267 ObDereferenceObject(FileObject
);
3268 return STATUS_INSUFFICIENT_RESOURCES
;
3271 /* Allocate local buffer */
3272 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3273 sizeof(LARGE_INTEGER
),
3278 ObDereferenceObject(FileObject
);
3279 return STATUS_INSUFFICIENT_RESOURCES
;
3281 *LocalLength
= *Length
;
3283 /* Set up the IRP */
3284 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3285 Irp
->RequestorMode
= PreviousMode
;
3286 Irp
->UserIosb
= IoStatusBlock
;
3287 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
3288 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3289 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3291 /* Set up Stack Data */
3292 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3293 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3294 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3295 StackPtr
->FileObject
= FileObject
;
3297 /* Set Parameters */
3298 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3299 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
3300 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
3302 /* Call the Driver */
3303 Status
= IoCallDriver(DeviceObject
, Irp
);
3304 if (Status
== STATUS_PENDING
)
3308 KeWaitForSingleObject(&Event
,
3311 FileObject
->Flags
& FO_ALERTABLE_IO
,
3313 Status
= IoStatusBlock
->Status
;
3317 KeWaitForSingleObject(&FileObject
->Event
,
3320 FileObject
->Flags
& FO_ALERTABLE_IO
,
3322 Status
= FileObject
->FinalStatus
;
3326 /* Return the Status */
3346 NtWriteFile (IN HANDLE FileHandle
,
3347 IN HANDLE Event OPTIONAL
,
3348 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3349 IN PVOID ApcContext OPTIONAL
,
3350 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3353 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
3354 IN PULONG Key OPTIONAL
)
3356 OBJECT_HANDLE_INFORMATION HandleInformation
;
3357 NTSTATUS Status
= STATUS_SUCCESS
;
3358 PFILE_OBJECT FileObject
;
3360 PDEVICE_OBJECT DeviceObject
;
3361 PIO_STACK_LOCATION StackPtr
;
3362 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3363 BOOLEAN LocalEvent
= FALSE
;
3364 PKEVENT EventObject
= NULL
;
3366 DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
3367 "IoStatusBlock 0x%p)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
3370 /* Validate User-Mode Buffers */
3371 if(PreviousMode
!= KernelMode
)
3376 ProbeForWrite(IoStatusBlock
,
3377 sizeof(IO_STATUS_BLOCK
),
3380 ProbeForRead(Buffer
,
3387 Status
= _SEH_GetExceptionCode();
3391 if(!NT_SUCCESS(Status
)) return Status
;
3394 /* Get File Object */
3395 Status
= ObReferenceObjectByHandle(FileHandle
,
3399 (PVOID
*)&FileObject
,
3400 &HandleInformation
);
3401 if (!NT_SUCCESS(Status
)) return Status
;
3403 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3404 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)))
3406 DPRINT1("Invalid access rights\n");
3407 ObDereferenceObject(FileObject
);
3408 return STATUS_ACCESS_DENIED
;
3411 /* Check if we got write Access */
3412 if (HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
)
3414 /* Check the Byte Offset */
3416 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
3417 ByteOffset
->u
.HighPart
== -1))
3419 /* a valid ByteOffset is required if asynch. op. */
3420 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3422 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3423 ObDereferenceObject(FileObject
);
3424 return STATUS_INVALID_PARAMETER
;
3427 /* Use the Current Byte OFfset */
3428 ByteOffset
= &FileObject
->CurrentByteOffset
;
3431 else if (HandleInformation
.GrantedAccess
& FILE_APPEND_DATA
)
3433 /* a valid ByteOffset is required if asynch. op. */
3434 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3436 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3437 ObDereferenceObject(FileObject
);
3438 return STATUS_INVALID_PARAMETER
;
3441 /* Give the drivers somethign to understand */
3442 ByteOffset
->u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3443 ByteOffset
->u
.HighPart
= 0xffffffff;
3446 /* Check if we got an event */
3450 Status
= ObReferenceObjectByHandle(Event
,
3454 (PVOID
*)&EventObject
,
3456 if (!NT_SUCCESS(Status
))
3458 ObDereferenceObject(FileObject
);
3461 KeClearEvent(EventObject
);
3464 /* Check if this is a direct open or not */
3465 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3467 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3471 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3474 /* Check if we should use Sync IO or not */
3475 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3477 /* Use File Object event */
3478 KeClearEvent(&FileObject
->Event
);
3488 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
3497 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3502 Status
= _SEH_GetExceptionCode();
3506 /* Cleanup on failure */
3507 if (!NT_SUCCESS(Status
))
3511 ObDereferenceObject(&EventObject
);
3513 ObDereferenceObject(FileObject
);
3517 /* Set up IRP Data */
3518 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3519 Irp
->RequestorMode
= PreviousMode
;
3520 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3521 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3522 Irp
->Flags
|= IRP_WRITE_OPERATION
;
3525 * Vfat doesn't handle non cached files correctly.
3527 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3530 /* Setup Stack Data */
3531 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3532 StackPtr
->FileObject
= FileObject
;
3533 StackPtr
->Parameters
.Write
.Key
= Key
? *Key
: 0;
3534 if (FileObject
->Flags
& FO_WRITE_THROUGH
) StackPtr
->Flags
= SL_WRITE_THROUGH
;
3536 /* Call the Driver */
3537 Status
= IoCallDriver(DeviceObject
, Irp
);
3538 if (Status
== STATUS_PENDING
)
3542 KeWaitForSingleObject(&FileObject
->Event
,
3545 FileObject
->Flags
& FO_ALERTABLE_IO
,
3547 Status
= FileObject
->FinalStatus
;
3551 /* Return the Status */
3569 NtWriteFileGather(IN HANDLE FileHandle
,
3570 IN HANDLE Event OPTIONAL
,
3571 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3572 IN PVOID UserApcContext OPTIONAL
,
3573 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3574 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3575 IN ULONG BufferLength
,
3576 IN PLARGE_INTEGER ByteOffset
,
3577 IN PULONG Key OPTIONAL
)
3580 return(STATUS_NOT_IMPLEMENTED
);