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: David Welch (welch@mcmail.com)
10 /* INCLUDES *****************************************************************/
14 #include <internal/debug.h>
16 /* GLOBALS *******************************************************************/
18 #define TAG_SYSB TAG('S', 'Y', 'S', 'B')
19 #define TAG_LOCK TAG('F','l','c','k')
20 #define TAG_FILE_NAME TAG('F', 'N', 'A', 'M')
22 extern GENERIC_MAPPING IopFileMapping
;
24 /* INTERNAL FUNCTIONS ********************************************************/
29 IopLockFileCompletionRoutine(IN PDEVICE_OBJECT DeviceObject
,
34 return STATUS_SUCCESS
;
35 // FIXME: Should I call IoFreeIrp and return STATUS_MORE_PROCESSING_REQUIRED?
52 IopCreateFile(PVOID ObjectBody
,
55 POBJECT_ATTRIBUTES ObjectAttributes
)
57 PDEVICE_OBJECT DeviceObject
;
58 PFILE_OBJECT FileObject
= (PFILE_OBJECT
) ObjectBody
;
59 POBJECT_TYPE ParentObjectType
;
62 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
69 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
70 for the cache manager, so return STATUS_SUCCESS */
71 DPRINT("Parent object was NULL\n");
72 return(STATUS_SUCCESS
);
75 ParentObjectType
= BODY_TO_HEADER(Parent
)->ObjectType
;
77 if (ParentObjectType
!= IoDeviceObjectType
&&
78 ParentObjectType
!= IoFileObjectType
)
80 DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n",
81 &BODY_TO_HEADER(Parent
)->Name
,
82 BODY_TO_HEADER(Parent
)->ObjectType
->TypeName
.Buffer
,
84 return(STATUS_UNSUCCESSFUL
);
87 Status
= ObReferenceObjectByPointer(Parent
,
88 STANDARD_RIGHTS_REQUIRED
,
91 if (!NT_SUCCESS(Status
))
93 CPRINT("Failed to reference parent object %x\n", Parent
);
97 if (ParentObjectType
== IoDeviceObjectType
)
99 /* Parent is a devce object */
100 DeviceObject
= IoGetAttachedDevice((PDEVICE_OBJECT
)Parent
);
101 DPRINT("DeviceObject %x\n", DeviceObject
);
103 if (RemainingPath
== NULL
)
105 FileObject
->Flags
= FileObject
->Flags
| FO_DIRECT_DEVICE_OPEN
;
106 FileObject
->FileName
.Buffer
= 0;
107 FileObject
->FileName
.Length
= FileObject
->FileName
.MaximumLength
= 0;
111 if ((DeviceObject
->DeviceType
!= FILE_DEVICE_FILE_SYSTEM
)
112 && (DeviceObject
->DeviceType
!= FILE_DEVICE_DISK
)
113 && (DeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
)
114 && (DeviceObject
->DeviceType
!= FILE_DEVICE_TAPE
)
115 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
)
116 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
117 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
119 CPRINT("Device was wrong type\n");
120 return(STATUS_UNSUCCESSFUL
);
123 if (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
124 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
125 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
127 if (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
129 DPRINT("Mount the logical volume\n");
130 Status
= IoMountVolume(DeviceObject
, FALSE
);
131 DPRINT("Status %x\n", Status
);
132 if (!NT_SUCCESS(Status
))
134 CPRINT("Failed to mount logical volume (Status %x)\n",
139 DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
140 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
142 RtlpCreateUnicodeString(&(FileObject
->FileName
),
143 RemainingPath
, NonPagedPool
);
148 /* Parent is a file object */
149 if (RemainingPath
== NULL
)
151 CPRINT("Device is unnamed\n");
152 return STATUS_UNSUCCESSFUL
;
155 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
156 DPRINT("DeviceObject %x\n", DeviceObject
);
158 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
160 RtlpCreateUnicodeString(&(FileObject
->FileName
),
161 RemainingPath
, NonPagedPool
);
164 DPRINT("FileObject->FileName %wZ\n",
165 &FileObject
->FileName
);
166 FileObject
->DeviceObject
= DeviceObject
;
167 DPRINT("FileObject %x DeviceObject %x\n",
170 FileObject
->Vpb
= DeviceObject
->Vpb
;
171 FileObject
->Type
= IO_TYPE_FILE
;
173 return(STATUS_SUCCESS
);
178 IopDeleteFile(PVOID ObjectBody
)
180 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
182 PIO_STACK_LOCATION StackPtr
;
185 PDEVICE_OBJECT DeviceObject
;
187 DPRINT("IopDeleteFile()\n");
189 if (FileObject
->DeviceObject
)
191 /* Check if this is a direct open or not */
192 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
194 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
198 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
201 /* Clear and set up Events */
202 KeClearEvent(&FileObject
->Event
);
203 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
205 /* Allocate an IRP */
206 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
209 Irp
->UserEvent
= &Event
;
210 Irp
->UserIosb
= &Irp
->IoStatus
;
211 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
212 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
213 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
215 /* Set up Stack Pointer Data */
216 StackPtr
= IoGetNextIrpStackLocation(Irp
);
217 StackPtr
->MajorFunction
= IRP_MJ_CLOSE
;
218 StackPtr
->DeviceObject
= DeviceObject
;
219 StackPtr
->FileObject
= FileObject
;
221 /* Call the FS Driver */
222 Status
= IoCallDriver(DeviceObject
, Irp
);
224 /* Wait for completion */
225 if (Status
== STATUS_PENDING
)
227 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
233 /* Clear the file name */
234 if (FileObject
->FileName
.Buffer
)
236 ExFreePool(FileObject
->FileName
.Buffer
);
237 FileObject
->FileName
.Buffer
= NULL
;
240 /* Free the completion context */
241 if (FileObject
->CompletionContext
)
243 ObDereferenceObject(FileObject
->CompletionContext
->Port
);
244 ExFreePool(FileObject
->CompletionContext
);
250 IopSetDefaultSecurityDescriptor(SECURITY_INFORMATION SecurityInformation
,
251 PSECURITY_DESCRIPTOR SecurityDescriptor
,
259 DPRINT("IopSetDefaultSecurityDescriptor() called\n");
261 if (SecurityInformation
== 0)
263 return STATUS_ACCESS_DENIED
;
266 SidSize
= RtlLengthSid(SeWorldSid
);
267 SdSize
= sizeof(SECURITY_DESCRIPTOR
) + (2 * SidSize
);
269 if (*BufferLength
< SdSize
)
271 *BufferLength
= SdSize
;
272 return STATUS_BUFFER_TOO_SMALL
;
275 *BufferLength
= SdSize
;
277 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
278 SECURITY_DESCRIPTOR_REVISION
);
279 if (!NT_SUCCESS(Status
))
284 SecurityDescriptor
->Control
|= SE_SELF_RELATIVE
;
285 Current
= (ULONG_PTR
)SecurityDescriptor
+ sizeof(SECURITY_DESCRIPTOR
);
287 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
289 RtlCopyMemory((PVOID
)Current
,
292 SecurityDescriptor
->Owner
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)SecurityDescriptor
);
296 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
298 RtlCopyMemory((PVOID
)Current
,
301 SecurityDescriptor
->Group
= (PSID
)((ULONG_PTR
)Current
- (ULONG_PTR
)SecurityDescriptor
);
305 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
307 SecurityDescriptor
->Control
|= SE_DACL_PRESENT
;
310 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
312 SecurityDescriptor
->Control
|= SE_SACL_PRESENT
;
315 return STATUS_SUCCESS
;
320 IopSecurityFile(PVOID ObjectBody
,
321 SECURITY_OPERATION_CODE OperationCode
,
322 SECURITY_INFORMATION SecurityInformation
,
323 PSECURITY_DESCRIPTOR SecurityDescriptor
,
326 IO_STATUS_BLOCK IoStatusBlock
;
327 PIO_STACK_LOCATION StackPtr
;
328 PFILE_OBJECT FileObject
;
332 DPRINT("IopSecurityFile() called\n");
334 FileObject
= (PFILE_OBJECT
)ObjectBody
;
336 switch (OperationCode
)
338 case SetSecurityDescriptor
:
339 DPRINT("Set security descriptor\n");
340 KeResetEvent(&FileObject
->Event
);
341 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_SET_SECURITY
,
342 FileObject
->DeviceObject
,
349 StackPtr
= IoGetNextIrpStackLocation(Irp
);
350 StackPtr
->FileObject
= FileObject
;
352 StackPtr
->Parameters
.SetSecurity
.SecurityInformation
= SecurityInformation
;
353 StackPtr
->Parameters
.SetSecurity
.SecurityDescriptor
= SecurityDescriptor
;
355 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
356 if (Status
== STATUS_PENDING
)
358 KeWaitForSingleObject(&FileObject
->Event
,
363 Status
= IoStatusBlock
.Status
;
366 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
368 Status
= STATUS_SUCCESS
;
372 case QuerySecurityDescriptor
:
373 DPRINT("Query security descriptor\n");
374 KeResetEvent(&FileObject
->Event
);
375 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_SECURITY
,
376 FileObject
->DeviceObject
,
383 Irp
->UserBuffer
= SecurityDescriptor
;
385 StackPtr
= IoGetNextIrpStackLocation(Irp
);
386 StackPtr
->FileObject
= FileObject
;
388 StackPtr
->Parameters
.QuerySecurity
.SecurityInformation
= SecurityInformation
;
389 StackPtr
->Parameters
.QuerySecurity
.Length
= *BufferLength
;
391 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
392 if (Status
== STATUS_PENDING
)
394 KeWaitForSingleObject(&FileObject
->Event
,
399 Status
= IoStatusBlock
.Status
;
402 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
404 Status
= IopSetDefaultSecurityDescriptor(SecurityInformation
,
410 /* FIXME: Is this correct?? */
411 *BufferLength
= IoStatusBlock
.Information
;
415 case DeleteSecurityDescriptor
:
416 DPRINT("Delete security descriptor\n");
417 return STATUS_SUCCESS
;
419 case AssignSecurityDescriptor
:
420 DPRINT("Assign security descriptor\n");
421 return STATUS_SUCCESS
;
424 return STATUS_UNSUCCESSFUL
;
429 IopQueryNameFile(PVOID ObjectBody
,
430 POBJECT_NAME_INFORMATION ObjectNameInfo
,
434 POBJECT_NAME_INFORMATION LocalInfo
;
435 PFILE_NAME_INFORMATION FileNameInfo
;
436 PFILE_OBJECT FileObject
;
437 ULONG LocalReturnLength
;
440 DPRINT ("IopQueryNameFile() called\n");
442 FileObject
= (PFILE_OBJECT
)ObjectBody
;
444 LocalInfo
= ExAllocatePool (NonPagedPool
,
445 sizeof(OBJECT_NAME_INFORMATION
) +
446 MAX_PATH
* sizeof(WCHAR
));
447 if (LocalInfo
== NULL
)
448 return STATUS_INSUFFICIENT_RESOURCES
;
450 Status
= ObQueryNameString (FileObject
->DeviceObject
->Vpb
->RealDevice
,
452 MAX_PATH
* sizeof(WCHAR
),
454 if (!NT_SUCCESS (Status
))
456 ExFreePool (LocalInfo
);
459 DPRINT ("Device path: %wZ\n", &LocalInfo
->Name
);
461 Status
= RtlAppendUnicodeStringToString (&ObjectNameInfo
->Name
,
464 ExFreePool (LocalInfo
);
466 FileNameInfo
= ExAllocatePool (NonPagedPool
,
467 MAX_PATH
* sizeof(WCHAR
) + sizeof(ULONG
));
468 if (FileNameInfo
== NULL
)
469 return STATUS_INSUFFICIENT_RESOURCES
;
471 Status
= IoQueryFileInformation (FileObject
,
473 MAX_PATH
* sizeof(WCHAR
) + sizeof(ULONG
),
476 if (Status
!= STATUS_SUCCESS
)
478 ExFreePool (FileNameInfo
);
482 Status
= RtlAppendUnicodeToString (&ObjectNameInfo
->Name
,
483 FileNameInfo
->FileName
);
485 DPRINT ("Total path: %wZ\n", &ObjectNameInfo
->Name
);
487 ExFreePool (FileNameInfo
);
494 IopCloseFile(PVOID ObjectBody
,
497 PFILE_OBJECT FileObject
= (PFILE_OBJECT
)ObjectBody
;
500 PIO_STACK_LOCATION StackPtr
;
502 PDEVICE_OBJECT DeviceObject
;
504 DPRINT("IopCloseFile()\n");
506 if (HandleCount
> 1 || FileObject
->DeviceObject
== NULL
) return;
508 /* Check if this is a direct open or not */
509 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
511 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
515 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
518 /* Clear and set up Events */
519 KeClearEvent(&FileObject
->Event
);
520 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
522 /* Allocate an IRP */
523 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
526 Irp
->UserEvent
= &Event
;
527 Irp
->UserIosb
= &Irp
->IoStatus
;
528 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
529 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
530 Irp
->Flags
= IRP_CLOSE_OPERATION
| IRP_SYNCHRONOUS_API
;
532 /* Set up Stack Pointer Data */
533 StackPtr
= IoGetNextIrpStackLocation(Irp
);
534 StackPtr
->MajorFunction
= IRP_MJ_CLEANUP
;
535 StackPtr
->FileObject
= FileObject
;
537 /* Call the FS Driver */
538 Status
= IoCallDriver(DeviceObject
, Irp
);
540 /* Wait for completion */
541 if (Status
== STATUS_PENDING
)
543 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
548 /* FUNCTIONS *****************************************************************/
555 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass
,
557 IN BOOLEAN SetOperation
)
560 return STATUS_NOT_IMPLEMENTED
;
568 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer
,
569 IN ULONG QuotaLength
,
570 OUT PULONG ErrorOffset
)
573 return STATUS_NOT_IMPLEMENTED
;
581 * Either causes a new file or directory to be created, or it
582 * opens an existing file, device, directory or volume, giving
583 * the caller a handle for the file object. This handle can be
584 * used by subsequent calls to manipulate data within the file
585 * or the file object's state of attributes.
589 * Points to a variable which receives the file handle
593 * Desired access to the file;
596 * Structure describing the file;
598 * IoStatusBlock (OUT)
599 * Receives information about the operation on return;
601 * AllocationSize [OPTIONAL]
602 * Initial size of the file in bytes;
605 * Attributes to create the file with;
608 * Type of shared access the caller would like to the
612 * Specifies what to do, depending on whether the
613 * file already exists;
616 * Options for creating a new file;
618 * EaBuffer [OPTIONAL]
625 * Type of file (normal, named pipe, mailslot) to create;
627 * ExtraCreateParameters [OPTIONAL]
628 * Additional creation data for named pipe and mailsots;
637 * Prototype taken from Bo Branten's ntifs.h v15.
638 * Description taken from old NtCreateFile's which is
639 * now a wrapper of this call.
647 IoCreateFile(OUT PHANDLE FileHandle
,
648 IN ACCESS_MASK DesiredAccess
,
649 IN POBJECT_ATTRIBUTES ObjectAttributes
,
650 OUT PIO_STATUS_BLOCK IoStatusBlock
,
651 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
652 IN ULONG FileAttributes
,
653 IN ULONG ShareAccess
,
654 IN ULONG CreateDisposition
,
655 IN ULONG CreateOptions
,
656 IN PVOID EaBuffer OPTIONAL
,
658 IN CREATE_FILE_TYPE CreateFileType
,
659 IN PVOID ExtraCreateParameters OPTIONAL
,
662 PFILE_OBJECT FileObject
= NULL
;
663 PDEVICE_OBJECT DeviceObject
;
665 PIO_STACK_LOCATION StackLoc
;
666 IO_SECURITY_CONTEXT SecurityContext
;
667 KPROCESSOR_MODE AccessMode
;
669 IO_STATUS_BLOCK LocalIoStatusBlock
;
670 LARGE_INTEGER SafeAllocationSize
;
671 PVOID SystemEaBuffer
= NULL
;
672 NTSTATUS Status
= STATUS_SUCCESS
;
674 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
675 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
676 FileHandle
,DesiredAccess
,ObjectAttributes
,
677 ObjectAttributes
->ObjectName
->Buffer
);
679 ASSERT_IRQL(PASSIVE_LEVEL
);
681 if (IoStatusBlock
== NULL
|| FileHandle
== NULL
)
682 return STATUS_ACCESS_VIOLATION
;
686 if(Options
& IO_NO_PARAMETER_CHECKING
)
687 AccessMode
= KernelMode
;
689 AccessMode
= ExGetPreviousMode();
691 if(AccessMode
!= KernelMode
)
695 ProbeForWrite(FileHandle
,
698 ProbeForWrite(IoStatusBlock
,
699 sizeof(IO_STATUS_BLOCK
),
701 if(AllocationSize
!= NULL
)
703 ProbeForRead(AllocationSize
,
704 sizeof(LARGE_INTEGER
),
706 SafeAllocationSize
= *AllocationSize
;
709 SafeAllocationSize
.QuadPart
= 0;
711 if(EaBuffer
!= NULL
&& EaLength
> 0)
713 ProbeForRead(EaBuffer
,
717 /* marshal EaBuffer */
718 SystemEaBuffer
= ExAllocatePool(NonPagedPool
,
720 if(SystemEaBuffer
== NULL
)
722 Status
= STATUS_INSUFFICIENT_RESOURCES
;
726 RtlCopyMemory(SystemEaBuffer
,
733 Status
= _SEH_GetExceptionCode();
737 if(!NT_SUCCESS(Status
))
744 if(AllocationSize
!= NULL
)
745 SafeAllocationSize
= *AllocationSize
;
747 SafeAllocationSize
.QuadPart
= 0;
749 if(EaBuffer
!= NULL
&& EaLength
> 0)
751 SystemEaBuffer
= EaBuffer
;
755 if(Options
& IO_CHECK_CREATE_PARAMETERS
)
757 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
760 if (CreateDisposition
== FILE_OPEN
||
761 CreateDisposition
== FILE_OPEN_IF
)
763 Status
= ObOpenObjectByName(ObjectAttributes
,
770 if (NT_SUCCESS(Status
))
772 Status
= ObReferenceObjectByHandle(LocalHandle
,
776 (PVOID
*)&DeviceObject
,
778 ZwClose(LocalHandle
);
779 if (!NT_SUCCESS(Status
))
783 if (BODY_TO_HEADER(DeviceObject
)->ObjectType
!= IoDeviceObjectType
)
785 ObDereferenceObject (DeviceObject
);
786 return STATUS_OBJECT_NAME_COLLISION
;
788 FileObject
= IoCreateStreamFileObject(NULL
, DeviceObject
);
789 ObDereferenceObject (DeviceObject
);
794 if (FileObject
== NULL
)
796 Status
= ObCreateObject(AccessMode
,
804 (PVOID
*)&FileObject
);
805 if (!NT_SUCCESS(Status
))
807 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
811 RtlMapGenericMask(&DesiredAccess
,
812 BODY_TO_HEADER(FileObject
)->ObjectType
->Mapping
);
814 Status
= ObInsertObject ((PVOID
)FileObject
,
820 if (!NT_SUCCESS(Status
))
822 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
823 ObDereferenceObject (FileObject
);
827 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
829 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
831 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
833 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
836 if (CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
837 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
839 SecurityContext
.SecurityQos
= NULL
; /* ?? */
840 SecurityContext
.AccessState
= NULL
; /* ?? */
841 SecurityContext
.DesiredAccess
= DesiredAccess
;
842 SecurityContext
.FullCreateOptions
= 0; /* ?? */
844 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
845 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
847 DPRINT("FileObject %x\n", FileObject
);
848 DPRINT("FileObject->DeviceObject %x\n", FileObject
->DeviceObject
);
850 * Create a new IRP to hand to
851 * the FS driver: this may fail
852 * due to resource shortage.
854 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
857 ZwClose(LocalHandle
);
858 return STATUS_UNSUCCESSFUL
;
861 //trigger FileObject/Event dereferencing
862 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
863 Irp
->RequestorMode
= AccessMode
;
864 Irp
->UserIosb
= &LocalIoStatusBlock
;
865 Irp
->AssociatedIrp
.SystemBuffer
= SystemEaBuffer
;
866 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
867 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
868 Irp
->UserEvent
= &FileObject
->Event
;
869 Irp
->Overlay
.AllocationSize
= SafeAllocationSize
;
872 * Get the stack location for the new
873 * IRP and prepare it.
875 StackLoc
= IoGetNextIrpStackLocation(Irp
);
876 StackLoc
->MinorFunction
= 0;
877 StackLoc
->Flags
= (UCHAR
)Options
;
878 StackLoc
->Control
= 0;
879 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
880 StackLoc
->FileObject
= FileObject
;
882 switch (CreateFileType
)
885 case CreateFileTypeNone
:
886 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
887 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
888 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
889 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
890 StackLoc
->Parameters
.Create
.FileAttributes
= (USHORT
)FileAttributes
;
891 StackLoc
->Parameters
.Create
.ShareAccess
= (USHORT
)ShareAccess
;
892 StackLoc
->Parameters
.Create
.EaLength
= SystemEaBuffer
!= NULL
? EaLength
: 0;
895 case CreateFileTypeNamedPipe
:
896 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
897 StackLoc
->Parameters
.CreatePipe
.SecurityContext
= &SecurityContext
;
898 StackLoc
->Parameters
.CreatePipe
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
899 StackLoc
->Parameters
.CreatePipe
.Options
|= (CreateDisposition
<< 24);
900 StackLoc
->Parameters
.CreatePipe
.ShareAccess
= (USHORT
)ShareAccess
;
901 StackLoc
->Parameters
.CreatePipe
.Parameters
= ExtraCreateParameters
;
904 case CreateFileTypeMailslot
:
905 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
906 StackLoc
->Parameters
.CreateMailslot
.SecurityContext
= &SecurityContext
;
907 StackLoc
->Parameters
.CreateMailslot
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
908 StackLoc
->Parameters
.CreateMailslot
.Options
|= (CreateDisposition
<< 24);
909 StackLoc
->Parameters
.CreateMailslot
.ShareAccess
= (USHORT
)ShareAccess
;
910 StackLoc
->Parameters
.CreateMailslot
.Parameters
= ExtraCreateParameters
;
915 * Now call the driver and
916 * possibly wait if it can
917 * not complete the request
920 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
921 DPRINT("Status :%x\n", Status
);
923 if (Status
== STATUS_PENDING
)
925 KeWaitForSingleObject(&FileObject
->Event
,
930 Status
= LocalIoStatusBlock
.Status
;
932 if (!NT_SUCCESS(Status
))
934 DPRINT("Failing create request with status %x\n", Status
);
935 FileObject
->DeviceObject
= NULL
;
936 FileObject
->Vpb
= NULL
;
938 ZwClose(LocalHandle
);
944 *FileHandle
= LocalHandle
;
945 *IoStatusBlock
= LocalIoStatusBlock
;
949 Status
= _SEH_GetExceptionCode();
954 /* cleanup EABuffer if captured */
955 if(AccessMode
!= KernelMode
&& SystemEaBuffer
!= NULL
)
957 ExFreePool(SystemEaBuffer
);
960 ASSERT_IRQL(PASSIVE_LEVEL
);
962 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle
));
972 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle
,
973 IN ACCESS_MASK DesiredAccess
,
974 IN POBJECT_ATTRIBUTES ObjectAttributes
,
975 OUT PIO_STATUS_BLOCK IoStatusBlock
,
976 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
977 IN ULONG FileAttributes
,
978 IN ULONG ShareAccess
,
979 IN ULONG Disposition
,
980 IN ULONG CreateOptions
,
981 IN PVOID EaBuffer OPTIONAL
,
983 IN CREATE_FILE_TYPE CreateFileType
,
984 IN PVOID ExtraCreateParameters OPTIONAL
,
986 IN PVOID DeviceObject
)
989 return STATUS_NOT_IMPLEMENTED
;
994 * IoCreateStreamFileObject@8
1015 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
1016 PDEVICE_OBJECT DeviceObject
)
1018 PFILE_OBJECT CreatedFileObject
;
1021 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
1022 FileObject
, DeviceObject
);
1024 ASSERT_IRQL(PASSIVE_LEVEL
);
1026 Status
= ObCreateObject(KernelMode
,
1031 sizeof(FILE_OBJECT
),
1034 (PVOID
*)&CreatedFileObject
);
1035 if (!NT_SUCCESS(Status
))
1037 DPRINT("Could not create FileObject\n");
1041 if (FileObject
!= NULL
)
1043 DeviceObject
= FileObject
->DeviceObject
;
1045 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1047 DPRINT("DeviceObject %x\n", DeviceObject
);
1049 if (DeviceObject
->Vpb
&&
1050 DeviceObject
->Vpb
->DeviceObject
)
1052 CreatedFileObject
->DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
1056 CreatedFileObject
->DeviceObject
= DeviceObject
;
1058 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
1059 CreatedFileObject
->Type
= IO_TYPE_FILE
;
1060 CreatedFileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
1062 // shouldn't we initialize the lock event, and several other things here too?
1063 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
1064 KeInitializeEvent(&CreatedFileObject
->Lock
, SynchronizationEvent
, TRUE
);
1066 return CreatedFileObject
;
1074 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL
,
1075 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
1076 OUT PHANDLE FileObjectHandle OPTIONAL
)
1086 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL
,
1087 IN PDEVICE_OBJECT DeviceObject OPTIONAL
)
1098 IoGetFileObjectGenericMapping(VOID
)
1100 return &IopFileMapping
;
1108 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject
)
1110 /* Return the flag status */
1111 return (FileObject
->Flags
& FO_REMOTE_ORIGIN
);
1119 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject
,
1120 OUT POBJECT_NAME_INFORMATION
*ObjectNameInformation
)
1123 return STATUS_NOT_IMPLEMENTED
;
1131 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1132 IN FILE_INFORMATION_CLASS FileInformationClass
,
1134 OUT PVOID FileInformation
,
1135 OUT PULONG ReturnedLength
)
1137 IO_STATUS_BLOCK IoStatusBlock
;
1139 PDEVICE_OBJECT DeviceObject
;
1140 PIO_STACK_LOCATION StackPtr
;
1141 BOOLEAN LocalEvent
= FALSE
;
1145 ASSERT(FileInformation
!= NULL
);
1147 Status
= ObReferenceObjectByPointer(FileObject
,
1148 FILE_READ_ATTRIBUTES
,
1151 if (!NT_SUCCESS(Status
)) return(Status
);
1153 DPRINT("FileObject %x\n", FileObject
);
1155 /* Get the Device Object */
1156 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1158 /* Check if we should use Sync IO or not */
1159 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1161 /* Use File Object event */
1162 KeClearEvent(&FileObject
->Event
);
1166 /* Use local event */
1167 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1171 /* Allocate the IRP */
1172 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1175 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1176 Irp
->RequestorMode
= KernelMode
;
1177 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1178 Irp
->UserIosb
= &IoStatusBlock
;
1179 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1180 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1181 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1183 /* Set the Stack Data */
1184 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1185 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1186 StackPtr
->FileObject
= FileObject
;
1188 /* Set Parameters */
1189 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1190 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1192 /* Call the Driver */
1193 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
1195 if (Status
== STATUS_PENDING
)
1199 KeWaitForSingleObject(&Event
,
1202 FileObject
->Flags
& FO_ALERTABLE_IO
,
1204 Status
= IoStatusBlock
.Status
;
1208 KeWaitForSingleObject(&FileObject
->Event
,
1211 FileObject
->Flags
& FO_ALERTABLE_IO
,
1213 Status
= FileObject
->FinalStatus
;
1218 /* Return the Length and Status. ReturnedLength is NOT optional */
1219 *ReturnedLength
= IoStatusBlock
.Information
;
1228 IoSetFileOrigin(IN PFILE_OBJECT FileObject
,
1232 return STATUS_NOT_IMPLEMENTED
;
1236 * @name NtCancelIoFile
1238 * Cancel all pending I/O operations in the current thread for specified
1242 * Handle to file object to cancel requests for. No specific
1243 * access rights are needed.
1244 * @param IoStatusBlock
1245 * Pointer to status block which is filled with final completition
1246 * status on successful return.
1254 NtCancelIoFile(IN HANDLE FileHandle
,
1255 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1258 PFILE_OBJECT FileObject
;
1260 PLIST_ENTRY IrpEntry
;
1263 BOOLEAN OurIrpsInList
= FALSE
;
1264 LARGE_INTEGER Interval
;
1266 if ((ULONG_PTR
)IoStatusBlock
>= MmUserProbeAddress
&&
1267 KeGetPreviousMode() == UserMode
)
1268 return STATUS_ACCESS_VIOLATION
;
1270 Status
= ObReferenceObjectByHandle(FileHandle
, 0, IoFileObjectType
,
1271 KeGetPreviousMode(), (PVOID
*)&FileObject
,
1273 if (!NT_SUCCESS(Status
))
1276 /* IRP cancellations are synchronized at APC_LEVEL. */
1277 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1280 * Walk the list of active IRPs and cancel the ones that belong to
1284 Thread
= PsGetCurrentThread();
1285 for (IrpEntry
= Thread
->IrpList
.Flink
;
1286 IrpEntry
!= &Thread
->IrpList
;
1287 IrpEntry
= IrpEntry
->Flink
)
1289 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1290 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1293 /* Don't break here, we want to cancel all IRPs for the file object. */
1294 OurIrpsInList
= TRUE
;
1298 KfLowerIrql(OldIrql
);
1300 while (OurIrpsInList
)
1302 OurIrpsInList
= FALSE
;
1304 /* Wait a short while and then look if all our IRPs were completed. */
1305 Interval
.QuadPart
= -1000000; /* 100 milliseconds */
1306 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1308 OldIrql
= KfRaiseIrql(APC_LEVEL
);
1311 * Look in the list if all IRPs for the specified file object
1312 * are completed (or cancelled). If someone sends a new IRP
1313 * for our file object while we're here we can happily loop
1317 for (IrpEntry
= Thread
->IrpList
.Flink
;
1318 IrpEntry
!= &Thread
->IrpList
;
1319 IrpEntry
= IrpEntry
->Flink
)
1321 Irp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
1322 if (Irp
->Tail
.Overlay
.OriginalFileObject
== FileObject
)
1324 OurIrpsInList
= TRUE
;
1329 KfLowerIrql(OldIrql
);
1334 IoStatusBlock
->Status
= STATUS_SUCCESS
;
1335 IoStatusBlock
->Information
= 0;
1336 Status
= STATUS_SUCCESS
;
1340 Status
= STATUS_UNSUCCESSFUL
;
1344 ObDereferenceObject(FileObject
);
1354 * Entry point to call IoCreateFile with
1355 * default parameters.
1365 * Code originally in NtCreateFile moved in IoCreateFile.
1371 NtCreateFile(PHANDLE FileHandle
,
1372 ACCESS_MASK DesiredAccess
,
1373 POBJECT_ATTRIBUTES ObjectAttributes
,
1374 PIO_STATUS_BLOCK IoStatusBlock
,
1375 PLARGE_INTEGER AllocateSize
,
1376 ULONG FileAttributes
,
1378 ULONG CreateDisposition
,
1379 ULONG CreateOptions
,
1383 /* Call the I/O Function */
1384 return IoCreateFile(FileHandle
,
1402 NtCreateMailslotFile(OUT PHANDLE FileHandle
,
1403 IN ACCESS_MASK DesiredAccess
,
1404 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1405 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1406 IN ULONG CreateOptions
,
1407 IN ULONG MailslotQuota
,
1408 IN ULONG MaxMessageSize
,
1409 IN PLARGE_INTEGER TimeOut
)
1411 MAILSLOT_CREATE_PARAMETERS Buffer
;
1413 DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, "
1414 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1415 FileHandle
,DesiredAccess
,ObjectAttributes
,
1416 ObjectAttributes
->ObjectName
->Buffer
);
1418 ASSERT_IRQL(PASSIVE_LEVEL
);
1420 if (TimeOut
!= NULL
)
1422 Buffer
.ReadTimeout
.QuadPart
= TimeOut
->QuadPart
;
1423 Buffer
.TimeoutSpecified
= TRUE
;
1427 Buffer
.TimeoutSpecified
= FALSE
;
1429 Buffer
.MailslotQuota
= MailslotQuota
;
1430 Buffer
.MaximumMessageSize
= MaxMessageSize
;
1432 return IoCreateFile(FileHandle
,
1437 FILE_ATTRIBUTE_NORMAL
,
1438 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1443 CreateFileTypeMailslot
,
1450 NtCreateNamedPipeFile(PHANDLE FileHandle
,
1451 ACCESS_MASK DesiredAccess
,
1452 POBJECT_ATTRIBUTES ObjectAttributes
,
1453 PIO_STATUS_BLOCK IoStatusBlock
,
1455 ULONG CreateDisposition
,
1456 ULONG CreateOptions
,
1457 ULONG NamedPipeType
,
1459 ULONG CompletionMode
,
1460 ULONG MaximumInstances
,
1462 ULONG OutboundQuota
,
1463 PLARGE_INTEGER DefaultTimeout
)
1465 NAMED_PIPE_CREATE_PARAMETERS Buffer
;
1467 DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, "
1468 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
1469 FileHandle
,DesiredAccess
,ObjectAttributes
,
1470 ObjectAttributes
->ObjectName
->Buffer
);
1472 ASSERT_IRQL(PASSIVE_LEVEL
);
1474 if (DefaultTimeout
!= NULL
)
1476 Buffer
.DefaultTimeout
.QuadPart
= DefaultTimeout
->QuadPart
;
1477 Buffer
.TimeoutSpecified
= TRUE
;
1481 Buffer
.TimeoutSpecified
= FALSE
;
1483 Buffer
.NamedPipeType
= NamedPipeType
;
1484 Buffer
.ReadMode
= ReadMode
;
1485 Buffer
.CompletionMode
= CompletionMode
;
1486 Buffer
.MaximumInstances
= MaximumInstances
;
1487 Buffer
.InboundQuota
= InboundQuota
;
1488 Buffer
.OutboundQuota
= OutboundQuota
;
1490 return IoCreateFile(FileHandle
,
1495 FILE_ATTRIBUTE_NORMAL
,
1501 CreateFileTypeNamedPipe
,
1524 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
1527 return(STATUS_NOT_IMPLEMENTED
);
1532 NtFlushWriteBuffer(VOID
)
1534 KeFlushWriteBuffer();
1535 return STATUS_SUCCESS
;
1539 * FUNCTION: Flushes cached file data to disk
1541 * FileHandle = Points to the file
1542 * IoStatusBlock = Caller must supply storage to receive the result of
1543 * the flush buffers operation. The information field is
1544 * set to number of bytes flushed to disk.
1546 * REMARKS: This function maps to the win32 FlushFileBuffers
1550 NtFlushBuffersFile(IN HANDLE FileHandle
,
1551 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1553 PFILE_OBJECT FileObject
= NULL
;
1555 PIO_STACK_LOCATION StackPtr
;
1557 PDEVICE_OBJECT DeviceObject
;
1559 BOOLEAN LocalEvent
= FALSE
;
1560 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1562 /* Get the File Object */
1563 Status
= ObReferenceObjectByHandle(FileHandle
,
1567 (PVOID
*)&FileObject
,
1569 if (Status
!= STATUS_SUCCESS
) return(Status
);
1571 /* Check if this is a direct open or not */
1572 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1574 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1578 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1581 /* Check if we should use Sync IO or not */
1582 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1584 /* Use File Object event */
1585 KeClearEvent(&FileObject
->Event
);
1589 /* Use local event */
1590 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1594 /* Allocate the IRP */
1595 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
)))
1597 ObDereferenceObject(FileObject
);
1598 return STATUS_INSUFFICIENT_RESOURCES
;
1601 /* Set up the IRP */
1602 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1603 Irp
->RequestorMode
= PreviousMode
;
1604 Irp
->UserIosb
= IoStatusBlock
;
1605 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1606 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1607 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1609 /* Set up Stack Data */
1610 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1611 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1612 StackPtr
->FileObject
= FileObject
;
1614 /* Call the Driver */
1615 Status
= IoCallDriver(DeviceObject
, Irp
);
1616 if (Status
== STATUS_PENDING
)
1620 KeWaitForSingleObject(&Event
,
1623 FileObject
->Flags
& FO_ALERTABLE_IO
,
1625 Status
= IoStatusBlock
->Status
;
1629 KeWaitForSingleObject(&FileObject
->Event
,
1632 FileObject
->Flags
& FO_ALERTABLE_IO
,
1634 Status
= FileObject
->FinalStatus
;
1638 /* Return the Status */
1647 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1648 IN HANDLE Event OPTIONAL
,
1649 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1650 IN PVOID ApcContext OPTIONAL
,
1651 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1653 IN ULONG BufferSize
,
1654 IN ULONG CompletionFilter
,
1655 IN BOOLEAN WatchTree
)
1658 PDEVICE_OBJECT DeviceObject
;
1659 PFILE_OBJECT FileObject
;
1660 PIO_STACK_LOCATION IoStack
;
1661 KPROCESSOR_MODE PreviousMode
;
1662 NTSTATUS Status
= STATUS_SUCCESS
;
1664 DPRINT("NtNotifyChangeDirectoryFile()\n");
1668 PreviousMode
= ExGetPreviousMode();
1670 if(PreviousMode
!= KernelMode
)
1674 ProbeForWrite(IoStatusBlock
,
1675 sizeof(IO_STATUS_BLOCK
),
1679 ProbeForWrite(Buffer
,
1686 Status
= _SEH_GetExceptionCode();
1690 if(!NT_SUCCESS(Status
))
1696 Status
= ObReferenceObjectByHandle(FileHandle
,
1697 FILE_LIST_DIRECTORY
,
1700 (PVOID
*)&FileObject
,
1702 if (Status
!= STATUS_SUCCESS
) return(Status
);
1705 DeviceObject
= FileObject
->DeviceObject
;
1708 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1711 ObDereferenceObject(FileObject
);
1712 return STATUS_UNSUCCESSFUL
;
1717 Event
= &FileObject
->Event
;
1720 /* Trigger FileObject/Event dereferencing */
1721 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1722 Irp
->RequestorMode
= PreviousMode
;
1723 Irp
->UserIosb
= IoStatusBlock
;
1724 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1725 Irp
->UserEvent
= Event
;
1726 KeResetEvent( Event
);
1727 Irp
->UserBuffer
= Buffer
;
1728 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1729 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1731 IoStack
= IoGetNextIrpStackLocation(Irp
);
1733 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1734 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1736 IoStack
->Control
= 0;
1737 IoStack
->DeviceObject
= DeviceObject
;
1738 IoStack
->FileObject
= FileObject
;
1742 IoStack
->Flags
= SL_WATCH_TREE
;
1745 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1746 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1748 Status
= IoCallDriver(FileObject
->DeviceObject
,Irp
);
1750 /* FIXME: Should we wait here or not for synchronously opened files? */
1760 NtLockFile(IN HANDLE FileHandle
,
1761 IN HANDLE EventHandle OPTIONAL
,
1762 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1763 IN PVOID ApcContext OPTIONAL
,
1764 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1765 IN PLARGE_INTEGER ByteOffset
,
1766 IN PLARGE_INTEGER Length
,
1768 IN BOOLEAN FailImmediatedly
,
1769 IN BOOLEAN ExclusiveLock
1772 PFILE_OBJECT FileObject
= NULL
;
1773 PLARGE_INTEGER LocalLength
= NULL
;
1774 PKEVENT Event
= NULL
;
1776 PIO_STACK_LOCATION StackPtr
;
1777 PDEVICE_OBJECT DeviceObject
;
1778 KPROCESSOR_MODE PreviousMode
;
1781 // FIXME: instead of this, use SEH when available?
1782 if (!Length
|| !ByteOffset
)
1784 Status
= STATUS_INVALID_PARAMETER
;
1788 PreviousMode
= ExGetPreviousMode();
1790 Status
= ObReferenceObjectByHandle(FileHandle
,
1794 (PVOID
*)&FileObject
,
1796 if (!NT_SUCCESS(Status
))
1801 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1803 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,
1807 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1811 if (EventHandle
!= NULL
&& !FailImmediatedly
)
1813 Status
= ObReferenceObjectByHandle(EventHandle
,
1819 if (!NT_SUCCESS(Status
))
1826 Event
= &FileObject
->Event
;
1827 KeResetEvent(Event
);
1830 /* Trigger FileObject/Event dereferencing */
1831 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1833 Irp
->RequestorMode
= PreviousMode
;
1834 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1835 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1837 Irp
->UserEvent
= Event
;
1838 Irp
->UserIosb
= IoStatusBlock
;
1839 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1841 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1842 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1843 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1844 StackPtr
->FileObject
= FileObject
;
1847 StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1849 if (FailImmediatedly
)
1850 StackPtr
->Flags
|= SL_FAIL_IMMEDIATELY
;
1852 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1853 sizeof(LARGE_INTEGER
),
1857 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1861 *LocalLength
= *Length
;
1863 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1864 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
1865 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
1867 IoSetCompletionRoutine(Irp
,
1868 IopLockFileCompletionRoutine
,
1874 /* Can't touch FileObject after IoCallDriver since it might be freed */
1875 Status
= IofCallDriver(DeviceObject
, Irp
);
1876 if (Status
== STATUS_PENDING
&& (FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
1878 Status
= KeWaitForSingleObject(Event
,
1881 FileObject
->Flags
& FO_ALERTABLE_IO
,
1884 if (Status
!= STATUS_WAIT_0
)
1886 DPRINT1("NtLockFile -> KeWaitForSingleObject failed!\n");
1888 * FIXME: Should do some special processing here if alertable wait
1889 * was interupted by user apc or a thread alert (STATUS_ALERTED, STATUS_USER_APC)
1891 return Status
; /* Set status to something else? */
1894 Status
= IoStatusBlock
->Status
;
1901 ExFreePool(LocalLength
);
1907 ObDereferenceObject(Event
);
1910 ObDereferenceObject(FileObject
);
1920 * Opens an existing file (simpler than NtCreateFile).
1924 * Variable that receives the file handle on return;
1927 * Access desired by the caller to the file;
1930 * Structue describing the file to be opened;
1932 * IoStatusBlock (OUT)
1933 * Receives details about the result of the
1937 * Type of shared access the caller requires;
1940 * Options for the file open.
1952 NtOpenFile(PHANDLE FileHandle
,
1953 ACCESS_MASK DesiredAccess
,
1954 POBJECT_ATTRIBUTES ObjectAttributes
,
1955 PIO_STATUS_BLOCK IoStatusBlock
,
1959 /* Call the I/O Function */
1960 return IoCreateFile(FileHandle
,
1978 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
1979 OUT PFILE_BASIC_INFORMATION FileInformation
)
1981 IO_STATUS_BLOCK IoStatusBlock
;
1986 Status
= ZwOpenFile (&FileHandle
,
1987 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
1990 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1991 FILE_SYNCHRONOUS_IO_NONALERT
);
1992 if (!NT_SUCCESS (Status
))
1994 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
1998 /* Get file attributes */
1999 Status
= ZwQueryInformationFile (FileHandle
,
2002 sizeof(FILE_BASIC_INFORMATION
),
2003 FileBasicInformation
);
2004 ZwClose (FileHandle
);
2005 if (!NT_SUCCESS (Status
))
2007 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2016 * FUNCTION: Queries a directory file.
2018 * FileHandle = Handle to a directory file
2019 * EventHandle = Handle to the event signaled on completion
2020 * ApcRoutine = Asynchroneous procedure callback, called on completion
2021 * ApcContext = Argument to the apc.
2022 * IoStatusBlock = Caller supplies storage for extended status information.
2023 * FileInformation = Caller supplies storage for the resulting information.
2025 * FileNameInformation FILE_NAMES_INFORMATION
2026 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2027 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2028 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2030 * Length = Size of the storage supplied
2031 * FileInformationClass = Indicates the type of information requested.
2032 * ReturnSingleEntry = Specify true if caller only requests the first
2034 * FileName = Initial directory name to query, that may contain wild
2036 * RestartScan = Number of times the action should be repeated
2037 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2038 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2039 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2043 NtQueryDirectoryFile(IN HANDLE FileHandle
,
2044 IN HANDLE PEvent OPTIONAL
,
2045 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2046 IN PVOID ApcContext OPTIONAL
,
2047 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2048 OUT PVOID FileInformation
,
2050 IN FILE_INFORMATION_CLASS FileInformationClass
,
2051 IN BOOLEAN ReturnSingleEntry
,
2052 IN PUNICODE_STRING FileName OPTIONAL
,
2053 IN BOOLEAN RestartScan
)
2056 PDEVICE_OBJECT DeviceObject
;
2057 PFILE_OBJECT FileObject
;
2058 PIO_STACK_LOCATION StackPtr
;
2059 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2060 NTSTATUS Status
= STATUS_SUCCESS
;
2061 BOOLEAN LocalEvent
= FALSE
;
2062 PKEVENT Event
= NULL
;
2064 DPRINT("NtQueryDirectoryFile()\n");
2067 /* Validate User-Mode Buffers */
2068 if(PreviousMode
!= KernelMode
)
2072 ProbeForWrite(IoStatusBlock
,
2073 sizeof(IO_STATUS_BLOCK
),
2075 ProbeForWrite(FileInformation
,
2081 Status
= _SEH_GetExceptionCode();
2085 if(!NT_SUCCESS(Status
)) return Status
;
2088 /* Get File Object */
2089 Status
= ObReferenceObjectByHandle(FileHandle
,
2090 FILE_LIST_DIRECTORY
,
2093 (PVOID
*)&FileObject
,
2095 if (Status
!= STATUS_SUCCESS
) return(Status
);
2097 /* Get Event Object */
2100 Status
= ObReferenceObjectByHandle(PEvent
,
2106 if (Status
!= STATUS_SUCCESS
) return(Status
);
2107 KeClearEvent(Event
);
2110 /* Check if this is a direct open or not */
2111 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2113 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2117 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2120 /* Check if we should use Sync IO or not */
2121 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2123 /* Use File Object event */
2124 KeClearEvent(&FileObject
->Event
);
2131 /* Allocate the IRP */
2132 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
)))
2134 ObDereferenceObject(FileObject
);
2135 return STATUS_INSUFFICIENT_RESOURCES
;
2138 /* Set up the IRP */
2139 Irp
->RequestorMode
= PreviousMode
;
2140 Irp
->UserIosb
= IoStatusBlock
;
2141 Irp
->UserEvent
= Event
;
2142 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2143 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2144 Irp
->UserBuffer
= FileInformation
;
2145 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2146 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2148 /* Set up Stack Data */
2149 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2150 StackPtr
->FileObject
= FileObject
;
2151 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2152 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2154 /* Set Parameters */
2155 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
= FileInformationClass
;
2156 StackPtr
->Parameters
.QueryDirectory
.FileName
= FileName
;
2157 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2158 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2159 StackPtr
->Flags
= 0;
2160 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2161 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2163 /* Call the Driver */
2164 Status
= IoCallDriver(DeviceObject
, Irp
);
2165 if (Status
== STATUS_PENDING
)
2169 KeWaitForSingleObject(&FileObject
->Event
,
2172 FileObject
->Flags
& FO_ALERTABLE_IO
,
2174 Status
= FileObject
->FinalStatus
;
2178 /* Return the Status */
2186 NtQueryEaFile(IN HANDLE FileHandle
,
2187 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2190 IN BOOLEAN ReturnSingleEntry
,
2191 IN PVOID EaList OPTIONAL
,
2192 IN ULONG EaListLength
,
2193 IN PULONG EaIndex OPTIONAL
,
2194 IN BOOLEAN RestartScan
)
2197 return STATUS_NOT_IMPLEMENTED
;
2202 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes
,
2203 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
)
2205 IO_STATUS_BLOCK IoStatusBlock
;
2210 Status
= ZwOpenFile (&FileHandle
,
2211 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
2214 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2215 FILE_SYNCHRONOUS_IO_NONALERT
);
2216 if (!NT_SUCCESS (Status
))
2218 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status
);
2222 /* Get file attributes */
2223 Status
= ZwQueryInformationFile (FileHandle
,
2226 sizeof(FILE_NETWORK_OPEN_INFORMATION
),
2227 FileNetworkOpenInformation
);
2228 ZwClose (FileHandle
);
2229 if (!NT_SUCCESS (Status
))
2231 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status
);
2241 NtQueryInformationFile(HANDLE FileHandle
,
2242 PIO_STATUS_BLOCK IoStatusBlock
,
2243 PVOID FileInformation
,
2245 FILE_INFORMATION_CLASS FileInformationClass
)
2247 OBJECT_HANDLE_INFORMATION HandleInformation
;
2248 PFILE_OBJECT FileObject
;
2251 PDEVICE_OBJECT DeviceObject
;
2252 PIO_STACK_LOCATION StackPtr
;
2253 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2255 BOOLEAN LocalEvent
= FALSE
;
2256 BOOLEAN Failed
= FALSE
;
2258 ASSERT(IoStatusBlock
!= NULL
);
2259 ASSERT(FileInformation
!= NULL
);
2261 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2262 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2263 Length
, FileInformationClass
);
2265 /* Reference the Handle */
2266 Status
= ObReferenceObjectByHandle(FileHandle
,
2270 (PVOID
*)&FileObject
,
2271 &HandleInformation
);
2272 if (!NT_SUCCESS(Status
)) return Status
;
2274 /* Check information class specific access rights */
2275 switch (FileInformationClass
)
2277 case FileBasicInformation
:
2278 if (!(HandleInformation
.GrantedAccess
& FILE_READ_ATTRIBUTES
))
2282 case FilePositionInformation
:
2283 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2284 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2288 case FileAlignmentInformation
:
2289 if (!(FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
))
2299 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2300 ObDereferenceObject(FileObject
);
2301 return STATUS_ACCESS_DENIED
;
2304 DPRINT("FileObject %x\n", FileObject
);
2306 /* Check if this is a direct open or not */
2307 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2309 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2313 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2316 /* Check if we should use Sync IO or not */
2317 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2319 /* Use File Object event */
2320 KeClearEvent(&FileObject
->Event
);
2324 /* Use local event */
2325 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
2329 /* Allocate the IRP */
2330 if (!(Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
)))
2332 ObDereferenceObject(FileObject
);
2333 return STATUS_INSUFFICIENT_RESOURCES
;
2336 /* Allocate the System Buffer */
2337 if (!(Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2342 ObDereferenceObject(FileObject
);
2343 return STATUS_INSUFFICIENT_RESOURCES
;
2346 /* Set up the IRP */
2347 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2348 Irp
->RequestorMode
= PreviousMode
;
2349 Irp
->UserIosb
= IoStatusBlock
;
2350 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
2351 Irp
->UserBuffer
= FileInformation
;
2352 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2353 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
2354 Irp
->Flags
|= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2356 /* Set up Stack Data */
2357 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2358 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2359 StackPtr
->FileObject
= FileObject
;
2361 /* Set the Parameters */
2362 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2363 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2365 /* Call the Driver */
2366 Status
= IoCallDriver(DeviceObject
, Irp
);
2367 if (Status
== STATUS_PENDING
)
2371 KeWaitForSingleObject(&Event
,
2374 FileObject
->Flags
& FO_ALERTABLE_IO
,
2376 Status
= IoStatusBlock
->Status
;
2380 KeWaitForSingleObject(&FileObject
->Event
,
2383 FileObject
->Flags
& FO_ALERTABLE_IO
,
2385 Status
= FileObject
->FinalStatus
;
2389 /* Return the Status */
2398 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2399 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2402 IN BOOLEAN ReturnSingleEntry
,
2403 IN PVOID SidList OPTIONAL
,
2404 IN ULONG SidListLength
,
2405 IN PSID StartSid OPTIONAL
,
2406 IN BOOLEAN RestartScan
)
2409 return STATUS_NOT_IMPLEMENTED
;
2428 NtReadFile(IN HANDLE FileHandle
,
2429 IN HANDLE Event OPTIONAL
,
2430 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2431 IN PVOID ApcContext OPTIONAL
,
2432 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2435 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2436 IN PULONG Key OPTIONAL
)
2438 NTSTATUS Status
= STATUS_SUCCESS
;
2439 PFILE_OBJECT FileObject
;
2441 PDEVICE_OBJECT DeviceObject
;
2442 PIO_STACK_LOCATION StackPtr
;
2443 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2444 BOOLEAN LocalEvent
= FALSE
;
2445 PKEVENT EventObject
= NULL
;
2447 DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2448 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2452 /* Validate User-Mode Buffers */
2453 if(PreviousMode
!= KernelMode
)
2457 ProbeForWrite(IoStatusBlock
,
2458 sizeof(IO_STATUS_BLOCK
),
2461 ProbeForWrite(Buffer
,
2468 Status
= _SEH_GetExceptionCode();
2472 if(!NT_SUCCESS(Status
)) return Status
;
2475 /* Get File Object */
2476 Status
= ObReferenceObjectByHandle(FileHandle
,
2480 (PVOID
*)&FileObject
,
2482 if (!NT_SUCCESS(Status
)) return Status
;
2484 /* Check the Byte Offset */
2486 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
2487 ByteOffset
->u
.HighPart
== 0xffffffff))
2489 /* a valid ByteOffset is required if asynch. op. */
2490 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2492 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2493 ObDereferenceObject(FileObject
);
2494 return STATUS_INVALID_PARAMETER
;
2497 /* Use the Current Byte OFfset */
2498 ByteOffset
= &FileObject
->CurrentByteOffset
;
2501 /* Check for event */
2505 Status
= ObReferenceObjectByHandle(Event
,
2509 (PVOID
*)&EventObject
,
2511 if (!NT_SUCCESS(Status
))
2513 ObDereferenceObject(FileObject
);
2516 KeClearEvent(EventObject
);
2519 /* Check if this is a direct open or not */
2520 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2522 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2526 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2529 /* Check if we should use Sync IO or not */
2530 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2532 /* Use File Object event */
2533 KeClearEvent(&FileObject
->Event
);
2540 /* Create the IRP */
2543 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2553 Status
= _SEH_GetExceptionCode();
2557 /* Cleanup if IRP Allocation Failed */
2558 if (!NT_SUCCESS(Status
) || !Irp
)
2560 if (Event
) ObDereferenceObject(EventObject
);
2561 ObDereferenceObject(FileObject
);
2566 return NT_SUCCESS(Status
) ? STATUS_INSUFFICIENT_RESOURCES
: Status
;
2569 /* Set up IRP Data */
2570 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2571 Irp
->RequestorMode
= PreviousMode
;
2572 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2573 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2574 Irp
->Flags
|= IRP_READ_OPERATION
;
2575 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2577 /* Setup Stack Data */
2578 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2579 StackPtr
->FileObject
= FileObject
;
2580 StackPtr
->Parameters
.Read
.Key
= Key
? *Key
: 0;
2582 /* Call the Driver */
2583 Status
= IoCallDriver(DeviceObject
, Irp
);
2584 if (Status
== STATUS_PENDING
)
2588 KeWaitForSingleObject(&FileObject
->Event
,
2591 FileObject
->Flags
& FO_ALERTABLE_IO
,
2593 Status
= FileObject
->FinalStatus
;
2597 /* Return the Status */
2615 NtReadFileScatter(IN HANDLE FileHandle
,
2616 IN HANDLE Event OPTIONAL
,
2617 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2618 IN PVOID UserApcContext OPTIONAL
,
2619 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2620 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2621 IN ULONG BufferLength
,
2622 IN PLARGE_INTEGER ByteOffset
,
2623 IN PULONG Key OPTIONAL
)
2626 return(STATUS_NOT_IMPLEMENTED
);
2634 NtSetEaFile(IN HANDLE FileHandle
,
2635 IN PIO_STATUS_BLOCK IoStatusBlock
,
2637 IN ULONG EaBufferSize
)
2640 return STATUS_NOT_IMPLEMENTED
;
2647 NtSetInformationFile(HANDLE FileHandle
,
2648 PIO_STATUS_BLOCK IoStatusBlock
,
2649 PVOID FileInformation
,
2651 FILE_INFORMATION_CLASS FileInformationClass
)
2653 OBJECT_HANDLE_INFORMATION HandleInformation
;
2654 PIO_STACK_LOCATION StackPtr
;
2655 PFILE_OBJECT FileObject
;
2656 PDEVICE_OBJECT DeviceObject
;
2660 KPROCESSOR_MODE PreviousMode
;
2661 BOOLEAN Failed
= FALSE
;
2663 ASSERT(IoStatusBlock
!= NULL
);
2664 ASSERT(FileInformation
!= NULL
);
2666 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2667 "Class %d)\n", FileHandle
, IoStatusBlock
, FileInformation
,
2668 Length
, FileInformationClass
);
2670 PreviousMode
= ExGetPreviousMode();
2672 /* Get the file object from the file handle */
2673 Status
= ObReferenceObjectByHandle(FileHandle
,
2677 (PVOID
*)&FileObject
,
2678 &HandleInformation
);
2679 if (!NT_SUCCESS(Status
))
2684 /* Check information class specific access rights */
2685 switch (FileInformationClass
)
2687 case FileBasicInformation
:
2688 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_ATTRIBUTES
))
2692 case FileDispositionInformation
:
2693 if (!(HandleInformation
.GrantedAccess
& DELETE
))
2697 case FilePositionInformation
:
2698 if (!(HandleInformation
.GrantedAccess
& (FILE_READ_DATA
| FILE_WRITE_DATA
)) ||
2699 !(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2703 case FileEndOfFileInformation
:
2704 if (!(HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
))
2714 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2715 ObDereferenceObject(FileObject
);
2716 return STATUS_ACCESS_DENIED
;
2719 DPRINT("FileObject %x\n", FileObject
);
2721 /* io completion port? */
2722 if (FileInformationClass
== FileCompletionInformation
)
2726 if (Length
< sizeof(FILE_COMPLETION_INFORMATION
))
2728 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2732 Status
= ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION
)FileInformation
)->IoCompletionHandle
,
2733 IO_COMPLETION_MODIFY_STATE
,//???
2738 if (NT_SUCCESS(Status
))
2740 /* FIXME: maybe use lookaside list */
2741 FileObject
->CompletionContext
= ExAllocatePool(NonPagedPool
, sizeof(IO_COMPLETION_CONTEXT
));
2742 FileObject
->CompletionContext
->Key
= ((PFILE_COMPLETION_INFORMATION
)FileInformation
)->CompletionKey
;
2743 FileObject
->CompletionContext
->Port
= Queue
;
2745 ObDereferenceObject(Queue
);
2749 ObDereferenceObject(FileObject
);
2753 DeviceObject
= FileObject
->DeviceObject
;
2755 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,
2759 ObDereferenceObject(FileObject
);
2760 return STATUS_INSUFFICIENT_RESOURCES
;
2763 SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2766 if (SystemBuffer
== NULL
)
2769 ObDereferenceObject(FileObject
);
2770 return STATUS_INSUFFICIENT_RESOURCES
;
2773 MmSafeCopyFromUser(SystemBuffer
,
2777 /* Trigger FileObject/Event dereferencing */
2778 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2779 Irp
->RequestorMode
= PreviousMode
;
2780 Irp
->AssociatedIrp
.SystemBuffer
= SystemBuffer
;
2781 Irp
->UserIosb
= IoStatusBlock
;
2782 Irp
->UserEvent
= &FileObject
->Event
;
2783 KeResetEvent(&FileObject
->Event
);
2784 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2786 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2787 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2788 StackPtr
->MinorFunction
= 0;
2789 StackPtr
->Flags
= 0;
2790 StackPtr
->Control
= 0;
2791 StackPtr
->DeviceObject
= DeviceObject
;
2792 StackPtr
->FileObject
= FileObject
;
2794 StackPtr
->Parameters
.SetFile
.FileInformationClass
=
2795 FileInformationClass
;
2796 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2799 * Pass the IRP to the FSD (and wait for
2802 DPRINT("FileObject->DeviceObject %x\n", FileObject
->DeviceObject
);
2803 Status
= IoCallDriver(FileObject
->DeviceObject
,
2805 if (Status
== STATUS_PENDING
&& (FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
2807 KeWaitForSingleObject(&FileObject
->Event
,
2810 FileObject
->Flags
& FO_ALERTABLE_IO
,
2812 Status
= IoStatusBlock
->Status
;
2815 ExFreePool(SystemBuffer
);
2825 NtSetQuotaInformationFile(HANDLE FileHandle
,
2826 PIO_STATUS_BLOCK IoStatusBlock
,
2827 PFILE_USER_QUOTA_INFORMATION Buffer
,
2831 return STATUS_NOT_IMPLEMENTED
;
2839 NtUnlockFile(IN HANDLE FileHandle
,
2840 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2841 IN PLARGE_INTEGER ByteOffset
,
2842 IN PLARGE_INTEGER Length
,
2843 OUT PULONG Key OPTIONAL
)
2845 PFILE_OBJECT FileObject
= NULL
;
2846 PLARGE_INTEGER LocalLength
= NULL
;
2848 PIO_STACK_LOCATION StackPtr
;
2849 PDEVICE_OBJECT DeviceObject
;
2850 KPROCESSOR_MODE PreviousMode
;
2853 // FIXME: instead of this, use SEH when available
2854 if (!Length
|| !ByteOffset
)
2856 Status
= STATUS_INVALID_PARAMETER
;
2860 PreviousMode
= ExGetPreviousMode();
2863 * BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and mode=UserMode
2864 * It should ONLY fail if we desire an access that conflict with granted access!
2866 Status
= ObReferenceObjectByHandle(FileHandle
,
2867 0, //FILE_READ_DATA,//BUGBUG: have to use something...but shouldn't have to!
2870 (PVOID
*)&FileObject
,
2872 if (!NT_SUCCESS(Status
))
2877 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2879 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,
2883 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2887 /* Trigger FileObject/Event dereferencing */
2888 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2889 Irp
->RequestorMode
= PreviousMode
;
2890 Irp
->UserIosb
= IoStatusBlock
;
2891 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2893 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2894 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2895 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2896 StackPtr
->DeviceObject
= DeviceObject
;
2897 StackPtr
->FileObject
= FileObject
;
2899 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2900 sizeof(LARGE_INTEGER
),
2904 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2908 *LocalLength
= *Length
;
2910 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2911 StackPtr
->Parameters
.LockControl
.ByteOffset
= *ByteOffset
;
2912 StackPtr
->Parameters
.LockControl
.Key
= Key
? *Key
: 0;
2914 /* Allways synchronous */
2915 Status
= IofCallDriver(DeviceObject
, Irp
);
2917 ExFreePool(LocalLength
);
2923 ExFreePool(LocalLength
);
2929 ObDereferenceObject(FileObject
);
2950 NtWriteFile (IN HANDLE FileHandle
,
2951 IN HANDLE Event OPTIONAL
,
2952 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2953 IN PVOID ApcContext OPTIONAL
,
2954 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2957 IN PLARGE_INTEGER ByteOffset OPTIONAL
, /* NOT optional for asynch. operations! */
2958 IN PULONG Key OPTIONAL
)
2960 OBJECT_HANDLE_INFORMATION HandleInformation
;
2961 NTSTATUS Status
= STATUS_SUCCESS
;
2962 PFILE_OBJECT FileObject
;
2964 PDEVICE_OBJECT DeviceObject
;
2965 PIO_STACK_LOCATION StackPtr
;
2966 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2967 BOOLEAN LocalEvent
= FALSE
;
2968 PKEVENT EventObject
= NULL
;
2970 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2971 "IoStatusBlock %x)\n", FileHandle
, Buffer
, Length
, ByteOffset
,
2974 /* Validate User-Mode Buffers */
2975 if(PreviousMode
!= KernelMode
)
2979 ProbeForWrite(IoStatusBlock
,
2980 sizeof(IO_STATUS_BLOCK
),
2983 ProbeForRead(Buffer
,
2990 Status
= _SEH_GetExceptionCode();
2994 if(!NT_SUCCESS(Status
)) return Status
;
2997 /* Get File Object */
2998 Status
= ObReferenceObjectByHandle(FileHandle
,
3002 (PVOID
*)&FileObject
,
3003 &HandleInformation
);
3004 if (!NT_SUCCESS(Status
)) return Status
;
3006 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3007 if (!(HandleInformation
.GrantedAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)))
3009 DPRINT1("Invalid access rights\n");
3010 ObDereferenceObject(FileObject
);
3011 return STATUS_ACCESS_DENIED
;
3014 /* Check if we got write Access */
3015 if (HandleInformation
.GrantedAccess
& FILE_WRITE_DATA
)
3017 /* Check the Byte Offset */
3019 (ByteOffset
->u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
&&
3020 ByteOffset
->u
.HighPart
== 0xffffffff))
3022 /* a valid ByteOffset is required if asynch. op. */
3023 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3025 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3026 ObDereferenceObject(FileObject
);
3027 return STATUS_INVALID_PARAMETER
;
3030 /* Use the Current Byte OFfset */
3031 ByteOffset
= &FileObject
->CurrentByteOffset
;
3034 else if (HandleInformation
.GrantedAccess
& FILE_APPEND_DATA
)
3036 /* a valid ByteOffset is required if asynch. op. */
3037 if (!(FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
3039 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3040 ObDereferenceObject(FileObject
);
3041 return STATUS_INVALID_PARAMETER
;
3044 /* Give the drivers somethign to understand */
3045 ByteOffset
->u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3046 ByteOffset
->u
.HighPart
= 0xffffffff;
3049 /* Check if we got an event */
3053 Status
= ObReferenceObjectByHandle(Event
,
3057 (PVOID
*)&EventObject
,
3059 if (!NT_SUCCESS(Status
))
3061 ObDereferenceObject(FileObject
);
3064 KeClearEvent(EventObject
);
3067 /* Check if this is a direct open or not */
3068 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3070 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3074 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3077 /* Check if we should use Sync IO or not */
3078 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3080 /* Use File Object event */
3081 KeClearEvent(&FileObject
->Event
);
3091 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
3092 FileObject
->DeviceObject
,
3101 Status
= _SEH_GetExceptionCode();
3105 /* Cleanup on failure */
3106 if (!NT_SUCCESS(Status
) || !Irp
)
3110 ObDereferenceObject(&EventObject
);
3112 ObDereferenceObject(FileObject
);
3113 if (Irp
) IoFreeIrp(Irp
);
3114 return NT_SUCCESS(Status
) ? STATUS_INSUFFICIENT_RESOURCES
: Status
;
3117 /* Set up IRP Data */
3118 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3119 Irp
->RequestorMode
= PreviousMode
;
3120 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3121 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3122 Irp
->Flags
|= IRP_WRITE_OPERATION
;
3123 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3125 /* Setup Stack Data */
3126 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3127 StackPtr
->FileObject
= FileObject
;
3128 StackPtr
->Parameters
.Write
.Key
= Key
? *Key
: 0;
3129 if (FileObject
->Flags
& FO_WRITE_THROUGH
) StackPtr
->Flags
= SL_WRITE_THROUGH
;
3131 /* Call the Driver */
3132 Status
= IoCallDriver(DeviceObject
, Irp
);
3133 if (Status
== STATUS_PENDING
)
3137 KeWaitForSingleObject(&FileObject
->Event
,
3140 FileObject
->Flags
& FO_ALERTABLE_IO
,
3142 Status
= FileObject
->FinalStatus
;
3146 /* Return the Status */
3164 NtWriteFileGather(IN HANDLE FileHandle
,
3165 IN HANDLE Event OPTIONAL
,
3166 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3167 IN PVOID UserApcContext OPTIONAL
,
3168 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3169 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3170 IN ULONG BufferLength
,
3171 IN PLARGE_INTEGER ByteOffset
,
3172 IN PULONG Key OPTIONAL
)
3175 return(STATUS_NOT_IMPLEMENTED
);