2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/iofunc.c
5 * PURPOSE: Generic I/O Functions that build IRPs for various operations
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Filip Navara (navaraf@reactos.org)
9 * Pierre Schweitzer (pierre@reactos.org)
12 /* INCLUDES *****************************************************************/
18 #include "internal/io_i.h"
20 volatile LONG IoPageReadIrpAllocationFailure
= 0;
21 volatile LONG IoPageReadNonPagefileIrpAllocationFailure
= 0;
23 /* PRIVATE FUNCTIONS *********************************************************/
27 IopCleanupAfterException(IN PFILE_OBJECT FileObject
,
29 IN PKEVENT Event OPTIONAL
,
30 IN PKEVENT LocalEvent OPTIONAL
)
33 IOTRACE(IO_API_DEBUG
, "IRP: %p. FO: %p \n", Irp
, FileObject
);
37 /* Check if we had a buffer */
38 if (Irp
->AssociatedIrp
.SystemBuffer
)
41 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
45 if (Irp
->MdlAddress
) IoFreeMdl(Irp
->MdlAddress
);
51 /* Check if we had a file lock */
52 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
55 IopUnlockFileObject(FileObject
);
58 /* Check if we had an event */
59 if (Event
) ObDereferenceObject(Event
);
61 /* Check if we had a local event */
62 if (LocalEvent
) ExFreePool(LocalEvent
);
64 /* Derefenrce the FO */
65 ObDereferenceObject(FileObject
);
70 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus
,
73 IN KPROCESSOR_MODE PreviousMode
,
74 IN PIO_STATUS_BLOCK KernelIosb
,
75 OUT PIO_STATUS_BLOCK IoStatusBlock
)
77 NTSTATUS FinalStatus
= SynchStatus
;
79 IOTRACE(IO_API_DEBUG
, "IRP: %p. Status: %lx \n", Irp
, SynchStatus
);
81 /* Make sure the IRP was completed, but returned pending */
82 if (FinalStatus
== STATUS_PENDING
)
84 /* Wait for the IRP */
85 FinalStatus
= KeWaitForSingleObject(Event
,
90 if (FinalStatus
== STATUS_USER_APC
)
92 /* Abort the request */
93 IopAbortInterruptedIrp(Event
, Irp
);
96 /* Set the final status */
97 FinalStatus
= KernelIosb
->Status
;
100 /* Wrap potential user-mode write in SEH */
103 *IoStatusBlock
= *KernelIosb
;
105 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
107 /* Get the exception code */
108 FinalStatus
= _SEH2_GetExceptionCode();
112 /* Free the event and return status */
119 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject
,
121 IN PFILE_OBJECT FileObject
,
123 IN KPROCESSOR_MODE PreviousMode
,
125 IN IOP_TRANSFER_TYPE TransferType
)
128 PKNORMAL_ROUTINE NormalRoutine
;
129 PVOID NormalContext
= NULL
;
132 IOTRACE(IO_API_DEBUG
, "IRP: %p. DO: %p. FO: %p \n",
133 Irp
, DeviceObject
, FileObject
);
136 IopQueueIrpToThread(Irp
);
138 /* Update operation counts */
139 IopUpdateOperationCount(TransferType
);
141 /* Call the driver */
142 Status
= IoCallDriver(DeviceObject
, Irp
);
144 /* Check if we're optimizing this case */
147 /* We are! Check if the IRP wasn't completed */
148 if (Status
!= STATUS_PENDING
)
150 /* Complete it ourselves */
151 ASSERT(!Irp
->PendingReturned
);
152 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
153 IopCompleteRequest(&Irp
->Tail
.Apc
,
158 KeLowerIrql(OldIrql
);
162 /* Check if this was synch I/O */
165 /* Make sure the IRP was completed, but returned pending */
166 if (Status
== STATUS_PENDING
)
168 /* Wait for the IRP */
169 Status
= KeWaitForSingleObject(&FileObject
->Event
,
173 FO_ALERTABLE_IO
) != 0,
175 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
177 /* Abort the request */
178 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
181 /* Set the final status */
182 Status
= FileObject
->FinalStatus
;
185 /* Release the file lock */
186 IopUnlockFileObject(FileObject
);
195 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
196 IN HANDLE Event OPTIONAL
,
197 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
198 IN PVOID UserApcContext OPTIONAL
,
199 OUT PIO_STATUS_BLOCK IoStatusBlock
,
200 IN ULONG IoControlCode
,
201 IN PVOID InputBuffer
,
202 IN ULONG InputBufferLength OPTIONAL
,
203 OUT PVOID OutputBuffer
,
204 IN ULONG OutputBufferLength OPTIONAL
,
205 IN BOOLEAN IsDevIoCtl
)
208 PFILE_OBJECT FileObject
;
209 PDEVICE_OBJECT DeviceObject
;
211 PIO_STACK_LOCATION StackPtr
;
212 PKEVENT EventObject
= NULL
;
213 BOOLEAN LockedForSynch
= FALSE
;
215 OBJECT_HANDLE_INFORMATION HandleInformation
;
216 ACCESS_MASK DesiredAccess
;
217 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
223 IOTRACE(IO_CTL_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
224 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
226 /* Get the access type */
227 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
229 /* Check if we came from user mode */
230 if (PreviousMode
!= KernelMode
)
234 /* Probe the status block */
235 ProbeForWriteIoStatusBlock(IoStatusBlock
);
237 /* Check if this is buffered I/O */
238 if (AccessType
== METHOD_BUFFERED
)
240 /* Check if we have an output buffer */
243 /* Probe the output buffer */
244 ProbeForWrite(OutputBuffer
,
250 /* Make sure the caller can't fake this as we depend on this */
251 OutputBufferLength
= 0;
255 /* Check if we we have an input buffer I/O */
256 if (AccessType
!= METHOD_NEITHER
)
258 /* Check if we have an input buffer */
261 /* Probe the input buffer */
262 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
266 /* Make sure the caller can't fake this as we depend on this */
267 InputBufferLength
= 0;
271 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
273 /* Return the exception code */
274 _SEH2_YIELD(return _SEH2_GetExceptionCode());
279 /* Don't check for access rights right now, KernelMode can do anything */
280 Status
= ObReferenceObjectByHandle(DeviceHandle
,
286 if (!NT_SUCCESS(Status
)) return Status
;
288 /* Can't use an I/O completion port and an APC in the same time */
289 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
292 ObDereferenceObject(FileObject
);
293 return STATUS_INVALID_PARAMETER
;
296 /* Check if we from user mode */
297 if (PreviousMode
!= KernelMode
)
299 /* Get the access mask */
300 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
302 /* Check if we can open it */
303 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
304 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
306 /* Dereference the file object and fail */
307 ObDereferenceObject(FileObject
);
308 return STATUS_ACCESS_DENIED
;
312 /* Check for an event */
316 Status
= ObReferenceObjectByHandle(Event
,
320 (PVOID
*)&EventObject
,
322 if (!NT_SUCCESS(Status
))
324 /* Dereference the file object and fail */
325 ObDereferenceObject(FileObject
);
330 KeClearEvent(EventObject
);
333 /* Check if this is a file that was opened for Synch I/O */
334 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
337 IopLockFileObject(FileObject
);
339 /* Remember to unlock later */
340 LockedForSynch
= TRUE
;
343 /* Check if this is a direct open or not */
344 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
346 /* It's a direct open, get the attached device */
347 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
351 /* Otherwise get the related device */
352 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
355 /* If this is a device I/O, try to do it with FastIO path */
358 PFAST_IO_DISPATCH FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
360 /* Check whether FSD is FastIO aware and provide an appropriate routine */
361 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoDeviceControl
!= NULL
)
363 IO_STATUS_BLOCK KernelIosb
;
365 /* If we have an output buffer coming from usermode */
366 if (PreviousMode
!= KernelMode
&& OutputBuffer
!= NULL
)
368 /* Probe it according to its usage */
371 if (AccessType
== METHOD_IN_DIRECT
)
373 ProbeForRead(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
375 else if (AccessType
== METHOD_OUT_DIRECT
)
377 ProbeForWrite(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
380 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
382 /* Cleanup after exception and return */
383 IopCleanupAfterException(FileObject
, NULL
, EventObject
, NULL
);
385 /* Return the exception code */
386 _SEH2_YIELD(return _SEH2_GetExceptionCode());
391 /* If we are dismounting a volume, increase the dismount count */
392 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
394 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
398 if (FastIoDispatch
->FastIoDeviceControl(FileObject
,
408 IO_COMPLETION_CONTEXT CompletionInfo
= { NULL
, NULL
};
410 /* Write the IOSB back */
413 *IoStatusBlock
= KernelIosb
;
416 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
418 KernelIosb
.Status
= _SEH2_GetExceptionCode();
422 /* Backup our complete context in case it exists */
423 if (FileObject
->CompletionContext
)
425 CompletionInfo
= *(FileObject
->CompletionContext
);
428 /* If we had an event, signal it */
431 KeSetEvent(EventObject
, IO_NO_INCREMENT
, FALSE
);
432 ObDereferenceObject(EventObject
);
435 /* If FO was locked, unlock it */
438 IopUnlockFileObject(FileObject
);
441 /* Set completion if required */
442 if (CompletionInfo
.Port
!= NULL
&& UserApcContext
!= NULL
)
444 if (!NT_SUCCESS(IoSetIoCompletion(CompletionInfo
.Port
,
448 KernelIosb
.Information
,
451 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
455 /* We're done with FastIO! */
456 ObDereferenceObject(FileObject
);
457 return KernelIosb
.Status
;
462 /* Clear the event */
463 KeClearEvent(&FileObject
->Event
);
466 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
467 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
470 Irp
->UserIosb
= IoStatusBlock
;
471 Irp
->UserEvent
= EventObject
;
472 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
473 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
475 Irp
->CancelRoutine
= NULL
;
476 Irp
->PendingReturned
= FALSE
;
477 Irp
->RequestorMode
= PreviousMode
;
478 Irp
->MdlAddress
= NULL
;
479 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
481 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
482 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
483 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
485 /* Set stack location settings */
486 StackPtr
= IoGetNextIrpStackLocation(Irp
);
487 StackPtr
->FileObject
= FileObject
;
488 StackPtr
->MajorFunction
= IsDevIoCtl
?
489 IRP_MJ_DEVICE_CONTROL
:
490 IRP_MJ_FILE_SYSTEM_CONTROL
;
491 StackPtr
->MinorFunction
= 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
492 StackPtr
->Control
= 0;
494 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
496 /* Set the IOCTL Data */
497 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
498 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
499 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
502 PoolType
= IsDevIoCtl
? NonPagedPoolCacheAligned
: NonPagedPool
;
504 /* Handle the Methods */
508 case METHOD_BUFFERED
:
510 /* Enter SEH for allocations */
513 /* Select the right Buffer Length */
514 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
515 InputBufferLength
: OutputBufferLength
;
517 /* Make sure there is one */
520 /* Allocate the System Buffer */
521 Irp
->AssociatedIrp
.SystemBuffer
=
522 ExAllocatePoolWithQuotaTag(PoolType
,
526 /* Check if we got a buffer */
529 /* Copy into the System Buffer */
530 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
535 /* Write the flags */
536 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
537 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
539 /* Save the Buffer */
540 Irp
->UserBuffer
= OutputBuffer
;
544 /* Clear the Flags and Buffer */
545 Irp
->UserBuffer
= NULL
;
548 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
550 /* Cleanup after exception and return */
551 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
552 _SEH2_YIELD(return _SEH2_GetExceptionCode());
558 case METHOD_IN_DIRECT
:
559 case METHOD_OUT_DIRECT
:
564 /* Check if we got an input buffer */
565 if ((InputBufferLength
) && (InputBuffer
))
567 /* Allocate the System Buffer */
568 Irp
->AssociatedIrp
.SystemBuffer
=
569 ExAllocatePoolWithQuotaTag(PoolType
,
573 /* Copy into the System Buffer */
574 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
578 /* Write the flags */
579 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
582 /* Check if we got an output buffer */
585 /* Allocate the System Buffer */
586 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
591 if (!Irp
->MdlAddress
)
593 /* Raise exception we'll catch */
594 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
598 MmProbeAndLockPages(Irp
->MdlAddress
,
600 (AccessType
== METHOD_IN_DIRECT
) ?
601 IoReadAccess
: IoWriteAccess
);
604 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
606 /* Cleanup after exception and return */
607 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
608 _SEH2_YIELD(return _SEH2_GetExceptionCode());
615 /* Just save the Buffer */
616 Irp
->UserBuffer
= OutputBuffer
;
617 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
620 /* Use deferred completion for FS I/O */
623 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
626 /* If we are dismounting a volume, increaase the dismount count */
627 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
629 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
632 /* Perform the call */
633 return IopPerformSynchronousRequest(DeviceObject
,
644 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
645 IN ULONG InformationClass
,
647 OUT PVOID Information
,
648 OUT PULONG ReturnedLength
,
651 IO_STATUS_BLOCK IoStatusBlock
;
653 PDEVICE_OBJECT DeviceObject
;
654 PIO_STACK_LOCATION StackPtr
;
655 BOOLEAN LocalEvent
= FALSE
;
659 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
660 FileObject
, InformationClass
, File
);
662 /* Reference the object */
663 ObReferenceObject(FileObject
);
665 /* Check if this is a file that was opened for Synch I/O */
666 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
669 IopLockFileObject(FileObject
);
671 /* Use File Object event */
672 KeClearEvent(&FileObject
->Event
);
676 /* Use local event */
677 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
681 /* Get the Device Object */
682 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
684 /* Allocate the IRP */
685 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
686 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
689 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
690 Irp
->RequestorMode
= KernelMode
;
691 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
692 Irp
->UserIosb
= &IoStatusBlock
;
693 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
694 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
695 Irp
->Flags
|= IRP_BUFFERED_IO
;
696 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
697 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
699 /* Set the Stack Data */
700 StackPtr
= IoGetNextIrpStackLocation(Irp
);
701 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
702 IRP_MJ_QUERY_VOLUME_INFORMATION
;
703 StackPtr
->FileObject
= FileObject
;
705 /* Check which type this is */
709 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
710 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
715 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
716 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
720 IopQueueIrpToThread(Irp
);
722 /* Call the Driver */
723 Status
= IoCallDriver(DeviceObject
, Irp
);
725 /* Check if this was synch I/O */
728 /* Check if the request is pending */
729 if (Status
== STATUS_PENDING
)
731 /* Wait on the file object */
732 Status
= KeWaitForSingleObject(&FileObject
->Event
,
736 FO_ALERTABLE_IO
) != 0,
738 if (Status
== STATUS_ALERTED
)
740 /* Abort the operation */
741 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
744 /* Get the final status */
745 Status
= FileObject
->FinalStatus
;
748 /* Release the file lock */
749 IopUnlockFileObject(FileObject
);
751 else if (Status
== STATUS_PENDING
)
753 /* Wait on the local event and get the final status */
754 KeWaitForSingleObject(&Event
,
759 Status
= IoStatusBlock
.Status
;
762 /* Return the Length and Status. ReturnedLength is NOT optional */
763 *ReturnedLength
= (ULONG
)IoStatusBlock
.Information
;
769 IopGetFileInformation(IN PFILE_OBJECT FileObject
,
771 IN FILE_INFORMATION_CLASS FileInfoClass
,
773 OUT PULONG ReturnedLength
)
778 PIO_STACK_LOCATION Stack
;
779 PDEVICE_OBJECT DeviceObject
;
780 IO_STATUS_BLOCK IoStatusBlock
;
784 /* Allocate an IRP */
785 ObReferenceObject(FileObject
);
786 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
787 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
790 ObDereferenceObject(FileObject
);
791 return STATUS_INSUFFICIENT_RESOURCES
;
795 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
798 Irp
->UserIosb
= &IoStatusBlock
;
799 Irp
->UserEvent
= &Event
;
800 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
801 Irp
->RequestorMode
= KernelMode
;
802 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
803 Irp
->Flags
= IRP_SYNCHRONOUS_API
| IRP_BUFFERED_IO
| IRP_OB_QUERY_NAME
;
804 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
805 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
807 Stack
= IoGetNextIrpStackLocation(Irp
);
808 Stack
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
809 Stack
->FileObject
= FileObject
;
810 Stack
->Parameters
.QueryFile
.FileInformationClass
= FileInfoClass
;
811 Stack
->Parameters
.QueryFile
.Length
= Length
;
815 IopQueueIrpToThread(Irp
);
817 /* Call the driver */
818 Status
= IoCallDriver(DeviceObject
, Irp
);
819 if (Status
== STATUS_PENDING
)
821 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
822 Status
= IoStatusBlock
.Status
;
825 *ReturnedLength
= IoStatusBlock
.Information
;
831 IopGetBasicInformationFile(IN PFILE_OBJECT FileObject
,
832 OUT PFILE_BASIC_INFORMATION BasicInfo
)
834 ULONG ReturnedLength
;
835 PDEVICE_OBJECT DeviceObject
;
836 IO_STATUS_BLOCK IoStatusBlock
;
840 /* Try to do it the fast way if possible */
841 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
842 if (DeviceObject
->DriverObject
->FastIoDispatch
!= NULL
&&
843 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
&&
844 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo(FileObject
,
845 ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) != 0),
850 return IoStatusBlock
.Status
;
853 /* In case it failed, fall back to IRP-based method */
854 return IopGetFileInformation(FileObject
, sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
, BasicInfo
, &ReturnedLength
);
859 IopOpenLinkOrRenameTarget(OUT PHANDLE Handle
,
861 IN PFILE_RENAME_INFORMATION RenameInfo
,
862 IN PFILE_OBJECT FileObject
)
866 UNICODE_STRING FileName
;
867 PIO_STACK_LOCATION Stack
;
868 PFILE_OBJECT TargetFileObject
;
869 IO_STATUS_BLOCK IoStatusBlock
;
870 FILE_BASIC_INFORMATION BasicInfo
;
871 OBJECT_ATTRIBUTES ObjectAttributes
;
872 OBJECT_HANDLE_INFORMATION HandleInformation
;
873 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
877 /* First, establish whether our target is a directory */
878 if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
880 Status
= IopGetBasicInformationFile(FileObject
, &BasicInfo
);
881 if (!NT_SUCCESS(Status
))
886 if (BasicInfo
.FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
887 DesiredAccess
= FILE_ADD_SUBDIRECTORY
;
891 /* Setup the string to the target */
892 FileName
.Buffer
= RenameInfo
->FileName
;
893 FileName
.Length
= RenameInfo
->FileNameLength
;
894 FileName
.MaximumLength
= RenameInfo
->FileNameLength
;
896 InitializeObjectAttributes(&ObjectAttributes
,
898 (FileObject
->Flags
& FO_OPENED_CASE_SENSITIVE
? 0 : OBJ_CASE_INSENSITIVE
) | OBJ_KERNEL_HANDLE
,
899 RenameInfo
->RootDirectory
,
902 /* And open its parent directory */
903 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
905 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
907 /* Commented out - we don't support FO extension yet
908 * FIXME: Corrected last arg when it's supported
910 Status
= IoCreateFileSpecifyDeviceObjectHint(&TargetHandle
,
911 DesiredAccess
| SYNCHRONIZE
,
916 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
918 FILE_OPEN_FOR_BACKUP_INTENT
,
923 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
,
924 FileObject
->DeviceObject
);
928 return STATUS_NOT_IMPLEMENTED
;
933 Status
= IoCreateFile(&TargetHandle
,
934 DesiredAccess
| SYNCHRONIZE
,
939 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
941 FILE_OPEN_FOR_BACKUP_INTENT
,
946 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
);
949 if (!NT_SUCCESS(Status
))
954 /* Once open, continue only if:
955 * Target exists and we're allowed to overwrite it
957 Stack
= IoGetNextIrpStackLocation(Irp
);
958 if (Stack
->Parameters
.SetFile
.FileInformationClass
== FileLinkInformation
&&
959 !RenameInfo
->ReplaceIfExists
&&
960 IoStatusBlock
.Information
== FILE_EXISTS
)
962 ObCloseHandle(TargetHandle
, KernelMode
);
963 return STATUS_OBJECT_NAME_COLLISION
;
966 /* Now, we'll get the associated device of the target, to check for same device location
967 * So, get the FO first
969 Status
= ObReferenceObjectByHandle(TargetHandle
,
973 (PVOID
*)&TargetFileObject
,
975 if (!NT_SUCCESS(Status
))
977 ObCloseHandle(TargetHandle
, KernelMode
);
981 /* We can dereference, we have the handle */
982 ObDereferenceObject(TargetFileObject
);
983 /* If we're not on the same device, error out **/
984 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
986 ObCloseHandle(TargetHandle
, KernelMode
);
987 return STATUS_NOT_SAME_DEVICE
;
990 /* Return parent directory file object and handle */
991 Stack
->Parameters
.SetFile
.FileObject
= TargetFileObject
;
992 *Handle
= TargetHandle
;
994 return STATUS_SUCCESS
;
999 IopGetFileMode(IN PFILE_OBJECT FileObject
)
1003 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
1004 Mode
|= FILE_WRITE_THROUGH
;
1006 if (FileObject
->Flags
& FO_SEQUENTIAL_ONLY
)
1007 Mode
|= FILE_SEQUENTIAL_ONLY
;
1009 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
1010 Mode
|= FILE_NO_INTERMEDIATE_BUFFERING
;
1012 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1014 if (FileObject
->Flags
& FO_ALERTABLE_IO
)
1015 Mode
|= FILE_SYNCHRONOUS_IO_ALERT
;
1017 Mode
|= FILE_SYNCHRONOUS_IO_NONALERT
;
1020 if (FileObject
->Flags
& FO_DELETE_ON_CLOSE
)
1021 Mode
|= FILE_DELETE_ON_CLOSE
;
1026 /* PUBLIC FUNCTIONS **********************************************************/
1033 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
1035 IN PLARGE_INTEGER Offset
,
1037 IN PIO_STATUS_BLOCK StatusBlock
)
1040 PIO_STACK_LOCATION StackPtr
;
1041 PDEVICE_OBJECT DeviceObject
;
1042 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1043 FileObject
, Mdl
, Offset
);
1045 /* Is the write originating from Cc? */
1046 if (FileObject
->SectionObjectPointer
!= NULL
&&
1047 FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
1050 CcDataPages
+= BYTES_TO_PAGES(MmGetMdlByteCount(Mdl
));
1053 /* Get the Device Object */
1054 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1057 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1058 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1061 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1063 /* Create the IRP Settings */
1064 Irp
->MdlAddress
= Mdl
;
1065 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1066 Irp
->UserIosb
= StatusBlock
;
1067 Irp
->UserEvent
= Event
;
1068 Irp
->RequestorMode
= KernelMode
;
1069 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
1070 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1071 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1073 /* Set the Stack Settings */
1074 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
1075 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
1076 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
1077 StackPtr
->FileObject
= FileObject
;
1079 /* Call the Driver */
1080 return IoCallDriver(DeviceObject
, Irp
);
1088 IoPageRead(IN PFILE_OBJECT FileObject
,
1090 IN PLARGE_INTEGER Offset
,
1092 IN PIO_STATUS_BLOCK StatusBlock
)
1095 PIO_STACK_LOCATION StackPtr
;
1096 PDEVICE_OBJECT DeviceObject
;
1097 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1098 FileObject
, Mdl
, Offset
);
1100 /* Get the Device Object */
1101 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1104 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1105 /* If allocation failed, try to see whether we can use
1110 /* We will use it only for paging file */
1111 if (MmIsFileObjectAPagingFile(FileObject
))
1113 InterlockedExchangeAdd(&IoPageReadIrpAllocationFailure
, 1);
1114 Irp
= IopAllocateReserveIrp(DeviceObject
->StackSize
);
1118 InterlockedExchangeAdd(&IoPageReadNonPagefileIrpAllocationFailure
, 1);
1121 /* If allocation failed (not a paging file or too big stack size)
1126 return STATUS_INSUFFICIENT_RESOURCES
;
1131 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1133 /* Create the IRP Settings */
1134 Irp
->MdlAddress
= Mdl
;
1135 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1136 Irp
->UserIosb
= StatusBlock
;
1137 Irp
->UserEvent
= Event
;
1138 Irp
->RequestorMode
= KernelMode
;
1139 Irp
->Flags
= IRP_PAGING_IO
|
1141 IRP_SYNCHRONOUS_PAGING_IO
|
1142 IRP_INPUT_OPERATION
;
1143 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1144 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1146 /* Set the Stack Settings */
1147 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
1148 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
1149 StackPtr
->MajorFunction
= IRP_MJ_READ
;
1150 StackPtr
->FileObject
= FileObject
;
1152 /* Call the Driver */
1153 return IoCallDriver(DeviceObject
, Irp
);
1161 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1162 IN FILE_INFORMATION_CLASS FileInformationClass
,
1164 OUT PVOID FileInformation
,
1165 OUT PULONG ReturnedLength
)
1167 /* Call the shared routine */
1168 return IopQueryDeviceInformation(FileObject
,
1169 FileInformationClass
,
1181 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
1182 IN FS_INFORMATION_CLASS FsInformationClass
,
1184 OUT PVOID FsInformation
,
1185 OUT PULONG ReturnedLength
)
1187 /* Call the shared routine */
1188 return IopQueryDeviceInformation(FileObject
,
1201 IoSetInformation(IN PFILE_OBJECT FileObject
,
1202 IN FILE_INFORMATION_CLASS FileInformationClass
,
1204 IN PVOID FileInformation
)
1206 IO_STATUS_BLOCK IoStatusBlock
;
1208 PDEVICE_OBJECT DeviceObject
;
1209 PIO_STACK_LOCATION StackPtr
;
1210 BOOLEAN LocalEvent
= FALSE
;
1214 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
1215 FileObject
, FileInformationClass
, Length
);
1217 /* Reference the object */
1218 ObReferenceObject(FileObject
);
1220 /* Check if this is a file that was opened for Synch I/O */
1221 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1224 IopLockFileObject(FileObject
);
1226 /* Use File Object event */
1227 KeClearEvent(&FileObject
->Event
);
1231 /* Use local event */
1232 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1236 /* Get the Device Object */
1237 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1239 /* Allocate the IRP */
1240 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1241 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1244 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1245 Irp
->RequestorMode
= KernelMode
;
1246 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1247 Irp
->UserIosb
= &IoStatusBlock
;
1248 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1249 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1250 Irp
->Flags
|= IRP_BUFFERED_IO
;
1251 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1252 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1254 /* Set the Stack Data */
1255 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1256 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
1257 StackPtr
->FileObject
= FileObject
;
1259 /* Set Parameters */
1260 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
1261 StackPtr
->Parameters
.SetFile
.Length
= Length
;
1264 IopQueueIrpToThread(Irp
);
1266 /* Call the Driver */
1267 Status
= IoCallDriver(DeviceObject
, Irp
);
1269 /* Check if this was synch I/O */
1272 /* Check if the request is pending */
1273 if (Status
== STATUS_PENDING
)
1275 /* Wait on the file object */
1276 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1279 (FileObject
->Flags
&
1280 FO_ALERTABLE_IO
) != 0,
1282 if (Status
== STATUS_ALERTED
)
1284 /* Abort the operation */
1285 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1288 /* Get the final status */
1289 Status
= FileObject
->FinalStatus
;
1292 /* Release the file lock */
1293 IopUnlockFileObject(FileObject
);
1295 else if (Status
== STATUS_PENDING
)
1297 /* Wait on the local event and get the final status */
1298 KeWaitForSingleObject(&Event
,
1303 Status
= IoStatusBlock
.Status
;
1306 /* Return the status */
1310 /* NATIVE SERVICES ***********************************************************/
1317 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1318 IN HANDLE Event OPTIONAL
,
1319 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1320 IN PVOID UserApcContext OPTIONAL
,
1321 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1322 IN ULONG IoControlCode
,
1323 IN PVOID InputBuffer
,
1324 IN ULONG InputBufferLength OPTIONAL
,
1325 OUT PVOID OutputBuffer
,
1326 IN ULONG OutputBufferLength OPTIONAL
)
1328 /* Call the Generic Function */
1329 return IopDeviceFsIoControl(DeviceHandle
,
1347 NtFsControlFile(IN HANDLE DeviceHandle
,
1348 IN HANDLE Event OPTIONAL
,
1349 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1350 IN PVOID UserApcContext OPTIONAL
,
1351 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1352 IN ULONG IoControlCode
,
1353 IN PVOID InputBuffer
,
1354 IN ULONG InputBufferLength OPTIONAL
,
1355 OUT PVOID OutputBuffer
,
1356 IN ULONG OutputBufferLength OPTIONAL
)
1358 /* Call the Generic Function */
1359 return IopDeviceFsIoControl(DeviceHandle
,
1374 NtFlushBuffersFile(IN HANDLE FileHandle
,
1375 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1377 PFILE_OBJECT FileObject
;
1379 PIO_STACK_LOCATION StackPtr
;
1381 PDEVICE_OBJECT DeviceObject
;
1382 PKEVENT Event
= NULL
;
1383 BOOLEAN LocalEvent
= FALSE
;
1384 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1385 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1386 IO_STATUS_BLOCK KernelIosb
;
1388 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1390 if (PreviousMode
!= KernelMode
)
1392 /* Protect probes */
1395 /* Probe the I/O Status block */
1396 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1398 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1400 /* Return the exception code */
1401 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1406 /* Get the File Object */
1407 Status
= ObReferenceObjectByHandle(FileHandle
,
1411 (PVOID
*)&FileObject
,
1413 if (!NT_SUCCESS(Status
)) return Status
;
1416 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1417 * granted. However, if this is a named pipe, make sure we don't ask for
1418 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1421 if (!(ObjectHandleInfo
.GrantedAccess
&
1422 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1426 ObDereferenceObject(FileObject
);
1427 return STATUS_ACCESS_DENIED
;
1430 /* Check if we should use Sync IO or not */
1431 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1434 IopLockFileObject(FileObject
);
1438 /* Use local event */
1439 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1443 ObDereferenceObject(FileObject
);
1444 return STATUS_INSUFFICIENT_RESOURCES
;
1446 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1450 /* Get the Device Object */
1451 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1453 /* Clear the event */
1454 KeClearEvent(&FileObject
->Event
);
1456 /* Allocate the IRP */
1457 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1458 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1460 /* Set up the IRP */
1461 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1462 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1463 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1464 Irp
->RequestorMode
= PreviousMode
;
1465 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1466 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1467 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1469 /* Set up Stack Data */
1470 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1471 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1472 StackPtr
->FileObject
= FileObject
;
1474 /* Call the Driver */
1475 Status
= IopPerformSynchronousRequest(DeviceObject
,
1483 /* Check if this was async I/O */
1486 /* It was, finalize this request */
1487 Status
= IopFinalizeAsynchronousIo(Status
,
1495 /* Return the Status */
1504 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1505 IN HANDLE EventHandle OPTIONAL
,
1506 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1507 IN PVOID ApcContext OPTIONAL
,
1508 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1510 IN ULONG BufferSize
,
1511 IN ULONG CompletionFilter
,
1512 IN BOOLEAN WatchTree
)
1515 PKEVENT Event
= NULL
;
1516 PDEVICE_OBJECT DeviceObject
;
1517 PFILE_OBJECT FileObject
;
1518 PIO_STACK_LOCATION IoStack
;
1519 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1521 BOOLEAN LockedForSync
= FALSE
;
1523 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1525 /* Check if we're called from user mode */
1526 if (PreviousMode
!= KernelMode
)
1528 /* Enter SEH for probing */
1531 /* Probe the I/O STatus block */
1532 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1534 /* Probe the buffer */
1535 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1537 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1539 /* Return the exception code */
1540 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1544 /* Check if CompletionFilter is valid */
1545 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1547 return STATUS_INVALID_PARAMETER
;
1551 /* Get File Object */
1552 Status
= ObReferenceObjectByHandle(FileHandle
,
1553 FILE_LIST_DIRECTORY
,
1556 (PVOID
*)&FileObject
,
1558 if (!NT_SUCCESS(Status
)) return Status
;
1560 /* Check if we have an event handle */
1564 Status
= ObReferenceObjectByHandle(EventHandle
,
1570 if (Status
!= STATUS_SUCCESS
)
1572 ObDereferenceObject(FileObject
);
1575 KeClearEvent(Event
);
1578 /* Check if we should use Sync IO or not */
1579 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1582 IopLockFileObject(FileObject
);
1583 LockedForSync
= TRUE
;
1586 /* Clear File Object event */
1587 KeClearEvent(&FileObject
->Event
);
1589 /* Get the device object */
1590 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1592 /* Allocate the IRP */
1593 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1594 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1596 /* Set up the IRP */
1597 Irp
->RequestorMode
= PreviousMode
;
1598 Irp
->UserIosb
= IoStatusBlock
;
1599 Irp
->UserEvent
= Event
;
1600 Irp
->UserBuffer
= Buffer
;
1601 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1602 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1603 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1604 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1606 /* Set up Stack Data */
1607 IoStack
= IoGetNextIrpStackLocation(Irp
);
1608 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1609 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1610 IoStack
->FileObject
= FileObject
;
1612 /* Set parameters */
1613 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1614 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1615 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1617 /* Perform the call */
1618 return IopPerformSynchronousRequest(DeviceObject
,
1632 NtLockFile(IN HANDLE FileHandle
,
1633 IN HANDLE EventHandle OPTIONAL
,
1634 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1635 IN PVOID ApcContext OPTIONAL
,
1636 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1637 IN PLARGE_INTEGER ByteOffset
,
1638 IN PLARGE_INTEGER Length
,
1640 IN BOOLEAN FailImmediately
,
1641 IN BOOLEAN ExclusiveLock
)
1643 PFILE_OBJECT FileObject
;
1644 PLARGE_INTEGER LocalLength
= NULL
;
1646 PIO_STACK_LOCATION StackPtr
;
1647 PDEVICE_OBJECT DeviceObject
;
1648 PKEVENT Event
= NULL
;
1649 BOOLEAN LockedForSync
= FALSE
;
1650 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1651 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1653 OBJECT_HANDLE_INFORMATION HandleInformation
;
1654 PFAST_IO_DISPATCH FastIoDispatch
;
1656 CapturedByteOffset
.QuadPart
= 0;
1657 CapturedLength
.QuadPart
= 0;
1658 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1660 /* Get File Object */
1661 Status
= ObReferenceObjectByHandle(FileHandle
,
1665 (PVOID
*)&FileObject
,
1666 &HandleInformation
);
1667 if (!NT_SUCCESS(Status
)) return Status
;
1669 /* Check if we're called from user mode */
1670 if (PreviousMode
!= KernelMode
)
1672 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1673 if (!(HandleInformation
.GrantedAccess
&
1674 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1676 ObDereferenceObject(FileObject
);
1677 return STATUS_ACCESS_DENIED
;
1680 /* Enter SEH for probing */
1683 /* Probe the I/O STatus block */
1684 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1686 /* Probe and capture the large integers */
1687 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1688 CapturedLength
= ProbeForReadLargeInteger(Length
);
1690 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1692 /* Dereference the object and return exception code */
1693 ObDereferenceObject(FileObject
);
1694 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1700 /* Otherwise, capture them directly */
1701 CapturedByteOffset
= *ByteOffset
;
1702 CapturedLength
= *Length
;
1705 /* Check if we have an event handle */
1709 Status
= ObReferenceObjectByHandle(EventHandle
,
1715 if (Status
!= STATUS_SUCCESS
) return Status
;
1716 KeClearEvent(Event
);
1719 /* Get the device object */
1720 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1722 /* Try to do it the FastIO way if possible */
1723 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1724 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoLock
!= NULL
)
1726 IO_STATUS_BLOCK KernelIosb
;
1728 if (FastIoDispatch
->FastIoLock(FileObject
,
1729 &CapturedByteOffset
,
1731 PsGetCurrentProcess(),
1738 /* Write the IOSB back */
1741 *IoStatusBlock
= KernelIosb
;
1743 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1745 KernelIosb
.Status
= _SEH2_GetExceptionCode();
1749 /* If we had an event, signal it */
1752 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1753 ObDereferenceObject(Event
);
1756 /* Set completion if required */
1757 if (FileObject
->CompletionContext
!= NULL
&& ApcContext
!= NULL
)
1759 if (!NT_SUCCESS(IoSetIoCompletion(FileObject
->CompletionContext
->Port
,
1760 FileObject
->CompletionContext
->Key
,
1763 KernelIosb
.Information
,
1766 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1770 FileObject
->LockOperation
= TRUE
;
1772 /* We're done with FastIO! */
1773 ObDereferenceObject(FileObject
);
1774 return KernelIosb
.Status
;
1778 /* Check if we should use Sync IO or not */
1779 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1782 IopLockFileObject(FileObject
);
1783 LockedForSync
= TRUE
;
1786 /* Clear File Object event */
1787 KeClearEvent(&FileObject
->Event
);
1788 FileObject
->LockOperation
= TRUE
;
1790 /* Allocate the IRP */
1791 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1792 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1794 /* Set up the IRP */
1795 Irp
->RequestorMode
= PreviousMode
;
1796 Irp
->UserIosb
= IoStatusBlock
;
1797 Irp
->UserEvent
= Event
;
1798 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1799 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1800 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1801 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1803 /* Set up Stack Data */
1804 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1805 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1806 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1807 StackPtr
->FileObject
= FileObject
;
1809 /* Allocate local buffer */
1810 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1811 sizeof(LARGE_INTEGER
),
1815 /* Allocating failed, clean up and return failure */
1816 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1817 return STATUS_INSUFFICIENT_RESOURCES
;
1820 /* Set the length */
1821 *LocalLength
= CapturedLength
;
1822 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1823 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1825 /* Set Parameters */
1826 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1827 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1830 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1831 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1833 /* Perform the call */
1834 return IopPerformSynchronousRequest(DeviceObject
,
1848 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1849 IN HANDLE EventHandle OPTIONAL
,
1850 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1851 IN PVOID ApcContext OPTIONAL
,
1852 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1853 OUT PVOID FileInformation
,
1855 IN FILE_INFORMATION_CLASS FileInformationClass
,
1856 IN BOOLEAN ReturnSingleEntry
,
1857 IN PUNICODE_STRING FileName OPTIONAL
,
1858 IN BOOLEAN RestartScan
)
1861 PDEVICE_OBJECT DeviceObject
;
1862 PFILE_OBJECT FileObject
;
1863 PIO_STACK_LOCATION StackPtr
;
1864 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1866 BOOLEAN LockedForSynch
= FALSE
;
1867 PKEVENT Event
= NULL
;
1868 volatile PVOID AuxBuffer
= NULL
;
1870 UNICODE_STRING CapturedFileName
;
1871 PUNICODE_STRING SearchPattern
;
1873 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1875 /* Check if we came from user mode */
1876 if (PreviousMode
!= KernelMode
)
1878 /* Enter SEH for probing */
1881 /* Probe the I/O Status Block */
1882 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1884 /* Probe the file information */
1885 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1887 /* Check if we have a file name */
1891 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1892 if (CapturedFileName
.Length
)
1894 /* Probe its buffer */
1895 ProbeForRead(CapturedFileName
.Buffer
,
1896 CapturedFileName
.Length
,
1900 /* Allocate the auxiliary buffer */
1901 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1902 CapturedFileName
.Length
+
1903 sizeof(UNICODE_STRING
),
1905 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1906 sizeof(UNICODE_STRING
)),
1907 CapturedFileName
.Buffer
,
1908 CapturedFileName
.Length
);
1910 /* Setup the search pattern */
1911 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1912 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1913 sizeof(UNICODE_STRING
));
1914 SearchPattern
->Length
= CapturedFileName
.Length
;
1915 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1918 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1920 /* Free buffer and return the exception code */
1921 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1922 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1927 /* Get File Object */
1928 Status
= ObReferenceObjectByHandle(FileHandle
,
1929 FILE_LIST_DIRECTORY
,
1932 (PVOID
*)&FileObject
,
1934 if (!NT_SUCCESS(Status
))
1937 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1941 /* Are there two associated completion routines? */
1942 if (FileObject
->CompletionContext
!= NULL
&& ApcRoutine
!= NULL
)
1944 ObDereferenceObject(FileObject
);
1945 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1946 return STATUS_INVALID_PARAMETER
;
1949 /* Check if we have an even handle */
1952 /* Get its pointer */
1953 Status
= ObReferenceObjectByHandle(EventHandle
,
1959 if (!NT_SUCCESS(Status
))
1962 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1963 ObDereferenceObject(FileObject
);
1968 KeClearEvent(Event
);
1971 /* Check if this is a file that was opened for Synch I/O */
1972 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1975 IopLockFileObject(FileObject
);
1977 /* Remember to unlock later */
1978 LockedForSynch
= TRUE
;
1981 /* Get the device object */
1982 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1984 /* Clear the File Object's event */
1985 KeClearEvent(&FileObject
->Event
);
1987 /* Allocate the IRP */
1988 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1989 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1991 /* Set up the IRP */
1992 Irp
->RequestorMode
= PreviousMode
;
1993 Irp
->UserIosb
= IoStatusBlock
;
1994 Irp
->UserEvent
= Event
;
1995 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1996 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1997 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1998 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1999 Irp
->MdlAddress
= NULL
;
2000 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
2001 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2003 /* Check if this is buffered I/O */
2004 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2006 /* Allocate a buffer */
2007 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2010 if (!Irp
->AssociatedIrp
.SystemBuffer
)
2012 /* Allocating failed, clean up and return the exception code */
2013 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2014 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2016 /* Return the exception code */
2017 return STATUS_INSUFFICIENT_RESOURCES
;
2020 /* Set the buffer and flags */
2021 Irp
->UserBuffer
= FileInformation
;
2022 Irp
->Flags
= (IRP_BUFFERED_IO
|
2023 IRP_DEALLOCATE_BUFFER
|
2024 IRP_INPUT_OPERATION
);
2026 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2030 /* Allocate an MDL */
2031 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
2032 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2033 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2035 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2037 /* Allocating failed, clean up and return the exception code */
2038 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2039 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2045 /* No allocation flags, and use the buffer directly */
2046 Irp
->UserBuffer
= FileInformation
;
2049 /* Set up Stack Data */
2050 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2051 StackPtr
->FileObject
= FileObject
;
2052 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2053 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2055 /* Set Parameters */
2056 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
2057 FileInformationClass
;
2058 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
2059 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2060 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2061 StackPtr
->Flags
= 0;
2062 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2063 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2065 /* Set deferred I/O */
2066 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
2068 /* Perform the call */
2069 return IopPerformSynchronousRequest(DeviceObject
,
2083 NtQueryEaFile(IN HANDLE FileHandle
,
2084 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2087 IN BOOLEAN ReturnSingleEntry
,
2088 IN PVOID EaList OPTIONAL
,
2089 IN ULONG EaListLength
,
2090 IN PULONG EaIndex OPTIONAL
,
2091 IN BOOLEAN RestartScan
)
2094 return STATUS_NOT_IMPLEMENTED
;
2102 NtQueryInformationFile(IN HANDLE FileHandle
,
2103 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2104 IN PVOID FileInformation
,
2106 IN FILE_INFORMATION_CLASS FileInformationClass
)
2108 OBJECT_HANDLE_INFORMATION HandleInformation
;
2109 PFILE_OBJECT FileObject
;
2112 PDEVICE_OBJECT DeviceObject
;
2113 PIO_STACK_LOCATION StackPtr
;
2114 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2115 PKEVENT Event
= NULL
;
2116 BOOLEAN LocalEvent
= FALSE
;
2117 PKNORMAL_ROUTINE NormalRoutine
;
2118 PVOID NormalContext
;
2120 IO_STATUS_BLOCK KernelIosb
;
2121 BOOLEAN CallDriver
= TRUE
;
2122 PFILE_ACCESS_INFORMATION AccessBuffer
;
2123 PFILE_MODE_INFORMATION ModeBuffer
;
2124 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer
;
2125 PFILE_ALL_INFORMATION AllBuffer
;
2126 PFAST_IO_DISPATCH FastIoDispatch
;
2128 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2130 /* Check if we're called from user mode */
2131 if (PreviousMode
!= KernelMode
)
2133 /* Validate the information class */
2134 if ((FileInformationClass
>= FileMaximumInformation
) ||
2135 !(IopQueryOperationLength
[FileInformationClass
]))
2138 return STATUS_INVALID_INFO_CLASS
;
2141 /* Validate the length */
2142 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2144 /* Invalid length */
2145 return STATUS_INFO_LENGTH_MISMATCH
;
2148 /* Enter SEH for probing */
2151 /* Probe the I/O Status block */
2152 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2154 /* Probe the information */
2155 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2159 /* Return the exception code */
2160 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2167 /* Validate the information class */
2168 if ((FileInformationClass
>= FileMaximumInformation
) ||
2169 !(IopQueryOperationLength
[FileInformationClass
]))
2172 return STATUS_INVALID_INFO_CLASS
;
2175 /* Validate the length */
2176 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2178 /* Invalid length */
2179 return STATUS_INFO_LENGTH_MISMATCH
;
2184 /* Reference the Handle */
2185 Status
= ObReferenceObjectByHandle(FileHandle
,
2186 IopQueryOperationAccess
2187 [FileInformationClass
],
2190 (PVOID
*)&FileObject
,
2191 &HandleInformation
);
2192 if (!NT_SUCCESS(Status
)) return Status
;
2194 /* Check if this is a direct open or not */
2195 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2197 /* Get the device object */
2198 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2202 /* Get the device object */
2203 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2206 /* Check if this is a file that was opened for Synch I/O */
2207 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2210 IopLockFileObject(FileObject
);
2212 /* Check if the caller just wants the position */
2213 if (FileInformationClass
== FilePositionInformation
)
2215 /* Protect write in SEH */
2218 /* Write the offset */
2219 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2220 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2222 /* Fill out the I/O Status Block */
2223 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2224 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2226 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2228 /* Get the exception code */
2229 Status
= _SEH2_GetExceptionCode();
2233 /* Release the file lock, dereference the file and return */
2234 IopUnlockFileObject(FileObject
);
2235 ObDereferenceObject(FileObject
);
2241 /* Use local event */
2242 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2245 ObDereferenceObject(FileObject
);
2246 return STATUS_INSUFFICIENT_RESOURCES
;
2248 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2252 /* Check if FastIO is possible for the two available information classes */
2253 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2254 if (FastIoDispatch
!= NULL
&&
2255 ((FileInformationClass
== FileBasicInformation
&& FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
) ||
2256 (FileInformationClass
== FileStandardInformation
&& FastIoDispatch
->FastIoQueryStandardInfo
!= NULL
)))
2258 BOOLEAN Success
= FALSE
;
2260 if (FileInformationClass
== FileBasicInformation
)
2262 Success
= FastIoDispatch
->FastIoQueryBasicInfo(FileObject
, TRUE
,
2269 Success
= FastIoDispatch
->FastIoQueryStandardInfo(FileObject
, TRUE
,
2275 /* If call succeed */
2278 /* Write the IOSB back */
2281 *IoStatusBlock
= KernelIosb
;
2283 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2285 KernelIosb
.Status
= _SEH2_GetExceptionCode();
2289 /* Free the event if we had one */
2292 ExFreePoolWithTag(Event
, TAG_IO
);
2295 /* If FO was locked, unlock it */
2296 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2298 IopUnlockFileObject(FileObject
);
2301 /* We're done with FastIO! */
2302 ObDereferenceObject(FileObject
);
2303 return KernelIosb
.Status
;
2307 /* Clear the File Object event */
2308 KeClearEvent(&FileObject
->Event
);
2310 /* Allocate the IRP */
2311 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2312 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2315 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2316 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2317 Irp
->RequestorMode
= PreviousMode
;
2318 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2319 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2320 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2321 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2322 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2323 Irp
->MdlAddress
= NULL
;
2324 Irp
->UserBuffer
= FileInformation
;
2326 /* Set the Stack Data */
2327 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2328 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2329 StackPtr
->FileObject
= FileObject
;
2334 /* Allocate a buffer */
2335 Irp
->AssociatedIrp
.SystemBuffer
=
2336 ExAllocatePoolWithTag(NonPagedPool
,
2340 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2342 /* Allocating failed, clean up and return the exception code */
2343 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2344 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2349 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2350 IRP_DEALLOCATE_BUFFER
|
2351 IRP_INPUT_OPERATION
|
2352 IRP_DEFER_IO_COMPLETION
);
2354 /* Set the Parameters */
2355 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2356 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2359 IopQueueIrpToThread(Irp
);
2361 /* Update operation counts */
2362 IopUpdateOperationCount(IopOtherTransfer
);
2364 /* Fill in file information before calling the driver.
2365 See 'File System Internals' page 485.*/
2366 if (FileInformationClass
== FileAccessInformation
)
2368 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2369 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2370 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2373 else if (FileInformationClass
== FileModeInformation
)
2375 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2376 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2377 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2380 else if (FileInformationClass
== FileAlignmentInformation
)
2382 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2383 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2384 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2387 else if (FileInformationClass
== FileAllInformation
)
2389 AllBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2390 AllBuffer
->AccessInformation
.AccessFlags
= HandleInformation
.GrantedAccess
;
2391 AllBuffer
->ModeInformation
.Mode
= IopGetFileMode(FileObject
);
2392 AllBuffer
->AlignmentInformation
.AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2393 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
) +
2394 sizeof(FILE_MODE_INFORMATION
) +
2395 sizeof(FILE_ALIGNMENT_INFORMATION
);
2398 /* Call the Driver */
2401 Status
= IoCallDriver(DeviceObject
, Irp
);
2405 Status
= STATUS_SUCCESS
;
2406 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2409 if (Status
== STATUS_PENDING
)
2411 /* Check if this was async I/O */
2414 /* Then to a non-alertable wait */
2415 Status
= KeWaitForSingleObject(Event
,
2420 if (Status
== STATUS_USER_APC
)
2422 /* Abort the request */
2423 IopAbortInterruptedIrp(Event
, Irp
);
2426 /* Set the final status */
2427 Status
= KernelIosb
.Status
;
2429 /* Enter SEH to write the IOSB back */
2432 /* Write it back to the caller */
2433 *IoStatusBlock
= KernelIosb
;
2435 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2437 /* Get the exception code */
2438 Status
= _SEH2_GetExceptionCode();
2442 /* Free the event */
2443 ExFreePoolWithTag(Event
, TAG_IO
);
2447 /* Wait for the IRP */
2448 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2451 (FileObject
->Flags
&
2452 FO_ALERTABLE_IO
) != 0,
2454 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2456 /* Abort the request */
2457 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2460 /* Set the final status */
2461 Status
= FileObject
->FinalStatus
;
2463 /* Release the file lock */
2464 IopUnlockFileObject(FileObject
);
2469 /* Free the event if we had one */
2472 /* Clear it in the IRP for completion */
2473 Irp
->UserEvent
= NULL
;
2474 ExFreePoolWithTag(Event
, TAG_IO
);
2477 /* Set the caller IOSB */
2478 Irp
->UserIosb
= IoStatusBlock
;
2480 /* The IRP wasn't completed, complete it ourselves */
2481 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2482 IopCompleteRequest(&Irp
->Tail
.Apc
,
2485 (PVOID
*)&FileObject
,
2487 KeLowerIrql(OldIrql
);
2489 /* Release the file object if we had locked it*/
2490 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2493 /* Return the Status */
2502 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2503 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2506 IN BOOLEAN ReturnSingleEntry
,
2507 IN PVOID SidList OPTIONAL
,
2508 IN ULONG SidListLength
,
2509 IN PSID StartSid OPTIONAL
,
2510 IN BOOLEAN RestartScan
)
2513 return STATUS_NOT_IMPLEMENTED
;
2521 NtReadFile(IN HANDLE FileHandle
,
2522 IN HANDLE Event OPTIONAL
,
2523 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2524 IN PVOID ApcContext OPTIONAL
,
2525 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2528 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2529 IN PULONG Key OPTIONAL
)
2532 PFILE_OBJECT FileObject
;
2534 PDEVICE_OBJECT DeviceObject
;
2535 PIO_STACK_LOCATION StackPtr
;
2536 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2537 PKEVENT EventObject
= NULL
;
2538 LARGE_INTEGER CapturedByteOffset
;
2539 ULONG CapturedKey
= 0;
2540 BOOLEAN Synchronous
= FALSE
;
2542 PFAST_IO_DISPATCH FastIoDispatch
;
2543 IO_STATUS_BLOCK KernelIosb
;
2547 CapturedByteOffset
.QuadPart
= 0;
2548 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2550 /* Validate User-Mode Buffers */
2551 if (PreviousMode
!= KernelMode
)
2555 /* Probe the status block */
2556 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2558 /* Probe the read buffer */
2559 ProbeForWrite(Buffer
, Length
, 1);
2561 /* Check if we got a byte offset */
2564 /* Capture and probe it */
2565 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2568 /* Capture and probe the key */
2569 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2571 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2573 /* Return the exception code */
2574 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2580 /* Kernel mode: capture directly */
2581 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2582 if (Key
) CapturedKey
= *Key
;
2585 /* Get File Object */
2586 Status
= ObReferenceObjectByHandle(FileHandle
,
2590 (PVOID
*)&FileObject
,
2592 if (!NT_SUCCESS(Status
)) return Status
;
2594 /* Check for event */
2598 Status
= ObReferenceObjectByHandle(Event
,
2602 (PVOID
*)&EventObject
,
2604 if (!NT_SUCCESS(Status
))
2607 ObDereferenceObject(FileObject
);
2611 /* Otherwise reset the event */
2612 KeClearEvent(EventObject
);
2615 /* Get the device object */
2616 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2618 /* Check if we should use Sync IO or not */
2619 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2621 /* Lock the file object */
2622 IopLockFileObject(FileObject
);
2624 /* Check if we don't have a byte offset available */
2625 if (!(ByteOffset
) ||
2626 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2627 (CapturedByteOffset
.u
.HighPart
== -1)))
2629 /* Use the Current Byte Offset instead */
2630 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2633 /* If the file is cached, try fast I/O */
2634 if (FileObject
->PrivateCacheMap
)
2636 /* Perform fast read */
2637 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2638 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoRead
!= NULL
);
2640 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2641 &CapturedByteOffset
,
2649 /* Only accept the result if we got a straightforward status */
2651 (KernelIosb
.Status
== STATUS_SUCCESS
||
2652 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2653 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2655 /* Fast path -- update transfer & operation counts */
2656 IopUpdateOperationCount(IopReadTransfer
);
2657 IopUpdateTransferCount(IopReadTransfer
,
2658 (ULONG
)KernelIosb
.Information
);
2660 /* Enter SEH to write the IOSB back */
2663 /* Write it back to the caller */
2664 *IoStatusBlock
= KernelIosb
;
2666 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2668 /* The caller's IOSB was invalid, so fail */
2669 if (EventObject
) ObDereferenceObject(EventObject
);
2670 IopUnlockFileObject(FileObject
);
2671 ObDereferenceObject(FileObject
);
2672 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2676 /* Signal the completion event */
2679 KeSetEvent(EventObject
, 0, FALSE
);
2680 ObDereferenceObject(EventObject
);
2684 IopUnlockFileObject(FileObject
);
2685 ObDereferenceObject(FileObject
);
2686 return KernelIosb
.Status
;
2690 /* Remember we are sync */
2693 else if (!(ByteOffset
) &&
2694 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2696 /* Otherwise, this was async I/O without a byte offset, so fail */
2697 if (EventObject
) ObDereferenceObject(EventObject
);
2698 ObDereferenceObject(FileObject
);
2699 return STATUS_INVALID_PARAMETER
;
2702 /* Clear the File Object's event */
2703 KeClearEvent(&FileObject
->Event
);
2705 /* Allocate the IRP */
2706 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2707 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2710 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2711 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2712 Irp
->RequestorMode
= PreviousMode
;
2713 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2714 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2715 Irp
->UserIosb
= IoStatusBlock
;
2716 Irp
->UserEvent
= EventObject
;
2717 Irp
->PendingReturned
= FALSE
;
2718 Irp
->Cancel
= FALSE
;
2719 Irp
->CancelRoutine
= NULL
;
2720 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2721 Irp
->MdlAddress
= NULL
;
2723 /* Set the Stack Data */
2724 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2725 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2726 StackPtr
->FileObject
= FileObject
;
2727 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2728 StackPtr
->Parameters
.Read
.Length
= Length
;
2729 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2731 /* Check if this is buffered I/O */
2732 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2734 /* Check if we have a buffer length */
2740 /* Allocate a buffer */
2741 Irp
->AssociatedIrp
.SystemBuffer
=
2742 ExAllocatePoolWithTag(NonPagedPool
,
2746 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2748 /* Allocating failed, clean up and return the exception code */
2749 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2750 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2754 /* Set the buffer and flags */
2755 Irp
->UserBuffer
= Buffer
;
2756 Irp
->Flags
= (IRP_BUFFERED_IO
|
2757 IRP_DEALLOCATE_BUFFER
|
2758 IRP_INPUT_OPERATION
);
2762 /* Not reading anything */
2763 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2766 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2768 /* Check if we have a buffer length */
2773 /* Allocate an MDL */
2774 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2776 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2777 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2779 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2781 /* Allocating failed, clean up and return the exception code */
2782 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2783 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2789 /* No allocation flags */
2794 /* No allocation flags, and use the buffer directly */
2796 Irp
->UserBuffer
= Buffer
;
2799 /* Now set the deferred read flags */
2800 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2802 /* FIXME: VFAT SUCKS */
2803 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2806 /* Perform the call */
2807 return IopPerformSynchronousRequest(DeviceObject
,
2821 NtReadFileScatter(IN HANDLE FileHandle
,
2822 IN HANDLE Event OPTIONAL
,
2823 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2824 IN PVOID UserApcContext OPTIONAL
,
2825 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2826 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2827 IN ULONG BufferLength
,
2828 IN PLARGE_INTEGER ByteOffset
,
2829 IN PULONG Key OPTIONAL
)
2832 return STATUS_NOT_IMPLEMENTED
;
2840 NtSetEaFile(IN HANDLE FileHandle
,
2841 IN PIO_STATUS_BLOCK IoStatusBlock
,
2843 IN ULONG EaBufferSize
)
2846 return STATUS_NOT_IMPLEMENTED
;
2854 NtSetInformationFile(IN HANDLE FileHandle
,
2855 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2856 IN PVOID FileInformation
,
2858 IN FILE_INFORMATION_CLASS FileInformationClass
)
2860 PFILE_OBJECT FileObject
;
2863 PDEVICE_OBJECT DeviceObject
;
2864 PIO_STACK_LOCATION StackPtr
;
2865 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2866 PKEVENT Event
= NULL
;
2867 BOOLEAN LocalEvent
= FALSE
;
2868 PKNORMAL_ROUTINE NormalRoutine
;
2869 PVOID NormalContext
;
2871 IO_STATUS_BLOCK KernelIosb
;
2873 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2874 PIO_COMPLETION_CONTEXT Context
;
2875 PFILE_RENAME_INFORMATION RenameInfo
;
2876 HANDLE TargetHandle
= NULL
;
2878 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2880 /* Check if we're called from user mode */
2881 if (PreviousMode
!= KernelMode
)
2883 /* Validate the information class */
2884 if ((FileInformationClass
>= FileMaximumInformation
) ||
2885 !(IopSetOperationLength
[FileInformationClass
]))
2888 return STATUS_INVALID_INFO_CLASS
;
2891 /* Validate the length */
2892 if (Length
< IopSetOperationLength
[FileInformationClass
])
2894 /* Invalid length */
2895 return STATUS_INFO_LENGTH_MISMATCH
;
2898 /* Enter SEH for probing */
2901 /* Probe the I/O Status block */
2902 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2904 /* Probe the information */
2905 ProbeForRead(FileInformation
,
2907 (Length
== sizeof(BOOLEAN
)) ?
2908 sizeof(BOOLEAN
) : sizeof(ULONG
));
2910 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2912 /* Return the exception code */
2913 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2919 /* Validate the information class */
2920 if ((FileInformationClass
>= FileMaximumInformation
) ||
2921 !(IopSetOperationLength
[FileInformationClass
]))
2924 return STATUS_INVALID_INFO_CLASS
;
2927 /* Validate the length */
2928 if (Length
< IopSetOperationLength
[FileInformationClass
])
2930 /* Invalid length */
2931 return STATUS_INFO_LENGTH_MISMATCH
;
2935 /* Reference the Handle */
2936 Status
= ObReferenceObjectByHandle(FileHandle
,
2937 IopSetOperationAccess
2938 [FileInformationClass
],
2941 (PVOID
*)&FileObject
,
2943 if (!NT_SUCCESS(Status
)) return Status
;
2945 /* Check if this is a direct open or not */
2946 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2948 /* Get the device object */
2949 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2953 /* Get the device object */
2954 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2957 DPRINT("Will call: %p\n", DeviceObject
);
2958 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
2960 /* Check if this is a file that was opened for Synch I/O */
2961 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2964 IopLockFileObject(FileObject
);
2966 /* Check if the caller just wants the position */
2967 if (FileInformationClass
== FilePositionInformation
)
2969 /* Protect write in SEH */
2972 /* Write the offset */
2973 FileObject
->CurrentByteOffset
=
2974 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2977 /* Fill out the I/O Status Block */
2978 IoStatusBlock
->Information
= 0;
2979 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2981 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2983 /* Get the exception code */
2984 Status
= _SEH2_GetExceptionCode();
2988 /* Update transfer count */
2989 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2991 /* Release the file lock, dereference the file and return */
2992 IopUnlockFileObject(FileObject
);
2993 ObDereferenceObject(FileObject
);
2999 /* Use local event */
3000 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3003 ObDereferenceObject(FileObject
);
3004 return STATUS_INSUFFICIENT_RESOURCES
;
3007 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3011 /* Clear the File Object event */
3012 KeClearEvent(&FileObject
->Event
);
3014 /* Allocate the IRP */
3015 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
3016 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3019 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3020 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3021 Irp
->RequestorMode
= PreviousMode
;
3022 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3023 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3024 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3025 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3026 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3027 Irp
->MdlAddress
= NULL
;
3028 Irp
->UserBuffer
= FileInformation
;
3030 /* Set the Stack Data */
3031 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3032 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
3033 StackPtr
->FileObject
= FileObject
;
3038 /* Allocate a buffer */
3039 Irp
->AssociatedIrp
.SystemBuffer
=
3040 ExAllocatePoolWithTag(NonPagedPool
,
3044 /* Copy the data into it */
3045 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3049 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3051 /* Allocating failed, clean up and return the exception code */
3052 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3053 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3058 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3059 IRP_DEALLOCATE_BUFFER
|
3060 IRP_DEFER_IO_COMPLETION
);
3062 /* Set the Parameters */
3063 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
3064 StackPtr
->Parameters
.SetFile
.Length
= Length
;
3067 IopQueueIrpToThread(Irp
);
3069 /* Update operation counts */
3070 IopUpdateOperationCount(IopOtherTransfer
);
3072 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3073 /* Handle IO Completion Port quickly */
3074 if (FileInformationClass
== FileCompletionInformation
)
3076 /* Check if the file object already has a completion port */
3077 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3078 (FileObject
->CompletionContext
))
3081 Status
= STATUS_INVALID_PARAMETER
;
3085 /* Reference the Port */
3086 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3087 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3088 IO_COMPLETION_MODIFY_STATE
,
3093 if (NT_SUCCESS(Status
))
3095 /* Allocate the Context */
3096 Context
= ExAllocatePoolWithTag(PagedPool
,
3097 sizeof(IO_COMPLETION_CONTEXT
),
3102 Context
->Key
= CompletionInfo
->Key
;
3103 Context
->Port
= Queue
;
3104 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3110 * Someone else set the completion port in the
3111 * meanwhile, so dereference the port and fail.
3113 ExFreePoolWithTag(Context
, IOC_TAG
);
3114 ObDereferenceObject(Queue
);
3115 Status
= STATUS_INVALID_PARAMETER
;
3120 /* Dereference the Port now */
3121 ObDereferenceObject(Queue
);
3122 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3127 /* Set the IRP Status */
3128 Irp
->IoStatus
.Status
= Status
;
3129 Irp
->IoStatus
.Information
= 0;
3131 else if (FileInformationClass
== FileRenameInformation
||
3132 FileInformationClass
== FileLinkInformation
||
3133 FileInformationClass
== FileMoveClusterInformation
)
3135 /* Get associated information */
3136 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3141 * -> sizes are valid
3143 if (RenameInfo
->FileNameLength
!= 0 &&
3144 !(RenameInfo
->FileNameLength
& 1) &&
3145 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3147 /* Properly set information received */
3148 if (FileInformationClass
== FileMoveClusterInformation
)
3150 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3154 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3157 /* If we got fully path OR relative target, attempt a parent directory open */
3158 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3160 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3161 if (!NT_SUCCESS(Status
))
3163 Irp
->IoStatus
.Status
= Status
;
3167 /* Call the Driver */
3168 Status
= IoCallDriver(DeviceObject
, Irp
);
3173 /* Call the Driver */
3174 Status
= IoCallDriver(DeviceObject
, Irp
);
3179 Status
= STATUS_INVALID_PARAMETER
;
3180 Irp
->IoStatus
.Status
= Status
;
3185 /* Call the Driver */
3186 Status
= IoCallDriver(DeviceObject
, Irp
);
3189 /* Check if we're waiting for the IRP to complete */
3190 if (Status
== STATUS_PENDING
)
3192 /* Check if this was async I/O */
3195 /* Then to a non-alertable wait */
3196 Status
= KeWaitForSingleObject(Event
,
3201 if (Status
== STATUS_USER_APC
)
3203 /* Abort the request */
3204 IopAbortInterruptedIrp(Event
, Irp
);
3207 /* Set the final status */
3208 Status
= KernelIosb
.Status
;
3210 /* Enter SEH to write the IOSB back */
3213 /* Write it back to the caller */
3214 *IoStatusBlock
= KernelIosb
;
3216 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3218 /* Get the exception code */
3219 Status
= _SEH2_GetExceptionCode();
3223 /* Free the event */
3224 ExFreePoolWithTag(Event
, TAG_IO
);
3228 /* Wait for the IRP */
3229 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3232 (FileObject
->Flags
&
3233 FO_ALERTABLE_IO
) != 0,
3235 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3237 /* Abort the request */
3238 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3241 /* Set the final status */
3242 Status
= FileObject
->FinalStatus
;
3244 /* Release the file lock */
3245 IopUnlockFileObject(FileObject
);
3250 /* Free the event if we had one */
3253 /* Clear it in the IRP for completion */
3254 Irp
->UserEvent
= NULL
;
3255 ExFreePoolWithTag(Event
, TAG_IO
);
3258 /* Set the caller IOSB */
3259 Irp
->UserIosb
= IoStatusBlock
;
3261 /* The IRP wasn't completed, complete it ourselves */
3262 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3263 IopCompleteRequest(&Irp
->Tail
.Apc
,
3266 (PVOID
*)&FileObject
,
3268 KeLowerIrql(OldIrql
);
3270 /* Release the file object if we had locked it*/
3271 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3274 if (TargetHandle
!= NULL
)
3276 ObCloseHandle(TargetHandle
, KernelMode
);
3279 /* Return the Status */
3288 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3289 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3291 IN ULONG BufferLength
)
3294 return STATUS_NOT_IMPLEMENTED
;
3302 NtUnlockFile(IN HANDLE FileHandle
,
3303 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3304 IN PLARGE_INTEGER ByteOffset
,
3305 IN PLARGE_INTEGER Length
,
3306 IN ULONG Key OPTIONAL
)
3308 PFILE_OBJECT FileObject
;
3309 PLARGE_INTEGER LocalLength
= NULL
;
3311 PIO_STACK_LOCATION StackPtr
;
3312 PDEVICE_OBJECT DeviceObject
;
3313 PKEVENT Event
= NULL
;
3314 BOOLEAN LocalEvent
= FALSE
;
3315 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3316 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3318 OBJECT_HANDLE_INFORMATION HandleInformation
;
3319 IO_STATUS_BLOCK KernelIosb
;
3320 PFAST_IO_DISPATCH FastIoDispatch
;
3322 CapturedByteOffset
.QuadPart
= 0;
3323 CapturedLength
.QuadPart
= 0;
3324 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3326 /* Get File Object */
3327 Status
= ObReferenceObjectByHandle(FileHandle
,
3331 (PVOID
*)&FileObject
,
3332 &HandleInformation
);
3333 if (!NT_SUCCESS(Status
)) return Status
;
3335 /* Check if we're called from user mode */
3336 if (PreviousMode
!= KernelMode
)
3338 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3339 if (!(HandleInformation
.GrantedAccess
&
3340 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3342 ObDereferenceObject(FileObject
);
3343 return STATUS_ACCESS_DENIED
;
3346 /* Enter SEH for probing */
3349 /* Probe the I/O Status block */
3350 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3352 /* Probe and capture the large integers */
3353 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3354 CapturedLength
= ProbeForReadLargeInteger(Length
);
3356 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3358 /* Dereference the object and return exception code */
3359 ObDereferenceObject(FileObject
);
3360 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3366 /* Otherwise, capture them directly */
3367 CapturedByteOffset
= *ByteOffset
;
3368 CapturedLength
= *Length
;
3371 /* Check if this is a direct open or not */
3372 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3374 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3378 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3381 /* Try to do it the FastIO way if possible */
3382 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3383 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3385 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3386 &CapturedByteOffset
,
3388 PsGetCurrentProcess(),
3393 /* Write the IOSB back */
3396 *IoStatusBlock
= KernelIosb
;
3398 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3400 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3404 /* We're done with FastIO! */
3405 ObDereferenceObject(FileObject
);
3406 return KernelIosb
.Status
;
3410 /* Check if we should use Sync IO or not */
3411 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3414 IopLockFileObject(FileObject
);
3418 /* Use local event */
3419 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3422 ObDereferenceObject(FileObject
);
3423 return STATUS_INSUFFICIENT_RESOURCES
;
3425 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3429 /* Clear File Object event */
3430 KeClearEvent(&FileObject
->Event
);
3432 /* Allocate the IRP */
3433 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3434 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3436 /* Set up the IRP */
3437 Irp
->RequestorMode
= PreviousMode
;
3438 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3439 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3440 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3441 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3442 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3443 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3445 /* Set up Stack Data */
3446 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3447 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3448 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3449 StackPtr
->FileObject
= FileObject
;
3454 /* Allocate a buffer */
3455 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3456 sizeof(LARGE_INTEGER
),
3459 /* Set the length */
3460 *LocalLength
= CapturedLength
;
3461 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3462 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3464 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3466 /* Allocating failed, clean up and return the exception code */
3467 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3468 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3470 /* Return the exception code */
3471 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3475 /* Set Parameters */
3476 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3477 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3479 /* Call the Driver */
3480 Status
= IopPerformSynchronousRequest(DeviceObject
,
3488 /* Check if this was async I/O */
3491 /* It was, finalize this request */
3492 Status
= IopFinalizeAsynchronousIo(Status
,
3509 NtWriteFile(IN HANDLE FileHandle
,
3510 IN HANDLE Event OPTIONAL
,
3511 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3512 IN PVOID ApcContext OPTIONAL
,
3513 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3516 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3517 IN PULONG Key OPTIONAL
)
3520 PFILE_OBJECT FileObject
;
3522 PDEVICE_OBJECT DeviceObject
;
3523 PIO_STACK_LOCATION StackPtr
;
3524 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3525 PKEVENT EventObject
= NULL
;
3526 LARGE_INTEGER CapturedByteOffset
;
3527 ULONG CapturedKey
= 0;
3528 BOOLEAN Synchronous
= FALSE
;
3530 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3531 PFAST_IO_DISPATCH FastIoDispatch
;
3532 IO_STATUS_BLOCK KernelIosb
;
3536 CapturedByteOffset
.QuadPart
= 0;
3537 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3539 /* Get File Object for write */
3540 Status
= ObReferenceFileObjectForWrite(FileHandle
,
3544 if (!NT_SUCCESS(Status
)) return Status
;
3546 /* Validate User-Mode Buffers */
3547 if (PreviousMode
!= KernelMode
)
3551 /* Probe the status block */
3552 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3554 /* Probe the read buffer */
3555 ProbeForRead(Buffer
, Length
, 1);
3557 /* Check if we got a byte offset */
3560 /* Capture and probe it */
3561 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3564 /* Capture and probe the key */
3565 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3567 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3569 /* Release the file object and return the exception code */
3570 ObDereferenceObject(FileObject
);
3571 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3577 /* Kernel mode: capture directly */
3578 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3579 if (Key
) CapturedKey
= *Key
;
3582 /* Check if this is an append operation */
3583 if ((ObjectHandleInfo
.GrantedAccess
&
3584 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3586 /* Give the drivers something to understand */
3587 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3588 CapturedByteOffset
.u
.HighPart
= -1;
3591 /* Check for event */
3595 Status
= ObReferenceObjectByHandle(Event
,
3599 (PVOID
*)&EventObject
,
3601 if (!NT_SUCCESS(Status
))
3604 ObDereferenceObject(FileObject
);
3608 /* Otherwise reset the event */
3609 KeClearEvent(EventObject
);
3612 /* Get the device object */
3613 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3615 /* Check if we should use Sync IO or not */
3616 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3618 /* Lock the file object */
3619 IopLockFileObject(FileObject
);
3621 /* Check if we don't have a byte offset available */
3622 if (!(ByteOffset
) ||
3623 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3624 (CapturedByteOffset
.u
.HighPart
== -1)))
3626 /* Use the Current Byte Offset instead */
3627 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3630 /* If the file is cached, try fast I/O */
3631 if (FileObject
->PrivateCacheMap
)
3633 /* Perform fast write */
3634 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3635 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoWrite
!= NULL
);
3637 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3638 &CapturedByteOffset
,
3646 /* Only accept the result if it was successful */
3648 KernelIosb
.Status
== STATUS_SUCCESS
)
3650 /* Fast path -- update transfer & operation counts */
3651 IopUpdateOperationCount(IopWriteTransfer
);
3652 IopUpdateTransferCount(IopWriteTransfer
,
3653 (ULONG
)KernelIosb
.Information
);
3655 /* Enter SEH to write the IOSB back */
3658 /* Write it back to the caller */
3659 *IoStatusBlock
= KernelIosb
;
3661 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3663 /* The caller's IOSB was invalid, so fail */
3664 if (EventObject
) ObDereferenceObject(EventObject
);
3665 IopUnlockFileObject(FileObject
);
3666 ObDereferenceObject(FileObject
);
3667 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3671 /* Signal the completion event */
3674 KeSetEvent(EventObject
, 0, FALSE
);
3675 ObDereferenceObject(EventObject
);
3679 IopUnlockFileObject(FileObject
);
3680 ObDereferenceObject(FileObject
);
3681 return KernelIosb
.Status
;
3685 /* Remember we are sync */
3688 else if (!(ByteOffset
) &&
3689 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3691 /* Otherwise, this was async I/O without a byte offset, so fail */
3692 if (EventObject
) ObDereferenceObject(EventObject
);
3693 ObDereferenceObject(FileObject
);
3694 return STATUS_INVALID_PARAMETER
;
3697 /* Clear the File Object's event */
3698 KeClearEvent(&FileObject
->Event
);
3700 /* Allocate the IRP */
3701 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3702 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3705 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3706 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3707 Irp
->RequestorMode
= PreviousMode
;
3708 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3709 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3710 Irp
->UserIosb
= IoStatusBlock
;
3711 Irp
->UserEvent
= EventObject
;
3712 Irp
->PendingReturned
= FALSE
;
3713 Irp
->Cancel
= FALSE
;
3714 Irp
->CancelRoutine
= NULL
;
3715 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3716 Irp
->MdlAddress
= NULL
;
3718 /* Set the Stack Data */
3719 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3720 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3721 StackPtr
->FileObject
= FileObject
;
3722 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3723 SL_WRITE_THROUGH
: 0;
3724 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3725 StackPtr
->Parameters
.Write
.Length
= Length
;
3726 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3728 /* Check if this is buffered I/O */
3729 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3731 /* Check if we have a buffer length */
3737 /* Allocate a buffer */
3738 Irp
->AssociatedIrp
.SystemBuffer
=
3739 ExAllocatePoolWithTag(NonPagedPool
,
3743 /* Copy the data into it */
3744 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3746 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3748 /* Allocating failed, clean up and return the exception code */
3749 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3750 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3755 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3759 /* Not writing anything */
3760 Irp
->Flags
= IRP_BUFFERED_IO
;
3763 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3765 /* Check if we have a buffer length */
3770 /* Allocate an MDL */
3771 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3773 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3774 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3776 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3778 /* Allocating failed, clean up and return the exception code */
3779 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3780 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3785 /* No allocation flags */
3790 /* No allocation flags, and use the buffer directly */
3792 Irp
->UserBuffer
= Buffer
;
3795 /* Now set the deferred read flags */
3796 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3798 /* FIXME: VFAT SUCKS */
3799 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3802 /* Perform the call */
3803 return IopPerformSynchronousRequest(DeviceObject
,
3814 NtWriteFileGather(IN HANDLE FileHandle
,
3815 IN HANDLE Event OPTIONAL
,
3816 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3817 IN PVOID UserApcContext OPTIONAL
,
3818 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3819 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3820 IN ULONG BufferLength
,
3821 IN PLARGE_INTEGER ByteOffset
,
3822 IN PULONG Key OPTIONAL
)
3825 return STATUS_NOT_IMPLEMENTED
;
3833 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3834 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3835 OUT PVOID FsInformation
,
3837 IN FS_INFORMATION_CLASS FsInformationClass
)
3839 PFILE_OBJECT FileObject
;
3841 PIO_STACK_LOCATION StackPtr
;
3842 PDEVICE_OBJECT DeviceObject
;
3843 PKEVENT Event
= NULL
;
3844 BOOLEAN LocalEvent
= FALSE
;
3845 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3847 IO_STATUS_BLOCK KernelIosb
;
3849 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3851 /* Check if we're called from user mode */
3852 if (PreviousMode
!= KernelMode
)
3854 /* Validate the information class */
3855 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3856 !(IopQueryFsOperationLength
[FsInformationClass
]))
3859 return STATUS_INVALID_INFO_CLASS
;
3862 /* Validate the length */
3863 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3865 /* Invalid length */
3866 return STATUS_INFO_LENGTH_MISMATCH
;
3869 /* Enter SEH for probing */
3872 /* Probe the I/O Status block */
3873 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3875 /* Probe the information */
3876 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3878 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3880 /* Return the exception code */
3881 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3886 /* Get File Object */
3887 Status
= ObReferenceObjectByHandle(FileHandle
,
3888 IopQueryFsOperationAccess
3889 [FsInformationClass
],
3892 (PVOID
*)&FileObject
,
3894 if (!NT_SUCCESS(Status
)) return Status
;
3896 /* Check if we should use Sync IO or not */
3897 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3900 IopLockFileObject(FileObject
);
3904 /* Use local event */
3905 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3908 ObDereferenceObject(FileObject
);
3909 return STATUS_INSUFFICIENT_RESOURCES
;
3911 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3915 /* Get the device object */
3916 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3918 /* Clear File Object event */
3919 KeClearEvent(&FileObject
->Event
);
3921 /* Allocate the IRP */
3922 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3923 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3925 /* Set up the IRP */
3926 Irp
->RequestorMode
= PreviousMode
;
3927 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3928 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3929 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3930 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3931 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3932 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3933 Irp
->UserBuffer
= FsInformation
;
3934 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3935 Irp
->MdlAddress
= NULL
;
3937 /* Set up Stack Data */
3938 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3939 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3940 StackPtr
->FileObject
= FileObject
;
3945 /* Allocate a buffer */
3946 Irp
->AssociatedIrp
.SystemBuffer
=
3947 ExAllocatePoolWithTag(NonPagedPool
,
3951 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3953 /* Allocating failed, clean up and return the exception code */
3954 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3955 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3959 /* Set the flags for this buffered + deferred I/O */
3960 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3961 IRP_DEALLOCATE_BUFFER
|
3962 IRP_INPUT_OPERATION
|
3963 IRP_DEFER_IO_COMPLETION
);
3965 /* Set Parameters */
3966 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3967 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3969 /* Call the Driver */
3970 Status
= IopPerformSynchronousRequest(DeviceObject
,
3978 /* Check if this was async I/O */
3981 /* It was, finalize this request */
3982 Status
= IopFinalizeAsynchronousIo(Status
,
3999 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
4000 OUT PIO_STATUS_BLOCK IoStatusBlock
,
4001 IN PVOID FsInformation
,
4003 IN FS_INFORMATION_CLASS FsInformationClass
)
4005 PFILE_OBJECT FileObject
;
4007 PIO_STACK_LOCATION StackPtr
;
4008 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
4009 PKEVENT Event
= NULL
;
4010 BOOLEAN LocalEvent
= FALSE
;
4011 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
4013 IO_STATUS_BLOCK KernelIosb
;
4014 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
4016 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
4018 /* Check if we're called from user mode */
4019 if (PreviousMode
!= KernelMode
)
4021 /* Validate the information class */
4022 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
4023 !(IopSetFsOperationLength
[FsInformationClass
]))
4026 return STATUS_INVALID_INFO_CLASS
;
4029 /* Validate the length */
4030 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
4032 /* Invalid length */
4033 return STATUS_INFO_LENGTH_MISMATCH
;
4036 /* Enter SEH for probing */
4039 /* Probe the I/O Status block */
4040 ProbeForWriteIoStatusBlock(IoStatusBlock
);
4042 /* Probe the information */
4043 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
4045 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4047 /* Return the exception code */
4048 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4053 /* Get File Object */
4054 Status
= ObReferenceObjectByHandle(FileHandle
,
4055 IopSetFsOperationAccess
4056 [FsInformationClass
],
4059 (PVOID
*)&FileObject
,
4061 if (!NT_SUCCESS(Status
)) return Status
;
4063 /* Get target device for notification */
4064 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4065 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4067 /* Check if we should use Sync IO or not */
4068 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4071 IopLockFileObject(FileObject
);
4075 /* Use local event */
4076 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);