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 NormalRoutine
= NULL
;
152 NormalContext
= NULL
;
153 ASSERT(!Irp
->PendingReturned
);
154 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
155 IopCompleteRequest(&Irp
->Tail
.Apc
,
160 KeLowerIrql(OldIrql
);
164 /* Check if this was synch I/O */
167 /* Make sure the IRP was completed, but returned pending */
168 if (Status
== STATUS_PENDING
)
170 /* Wait for the IRP */
171 Status
= KeWaitForSingleObject(&FileObject
->Event
,
175 FO_ALERTABLE_IO
) != 0,
177 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
179 /* Abort the request */
180 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
183 /* Set the final status */
184 Status
= FileObject
->FinalStatus
;
187 /* Release the file lock */
188 IopUnlockFileObject(FileObject
);
197 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
198 IN HANDLE Event OPTIONAL
,
199 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
200 IN PVOID UserApcContext OPTIONAL
,
201 OUT PIO_STATUS_BLOCK IoStatusBlock
,
202 IN ULONG IoControlCode
,
203 IN PVOID InputBuffer
,
204 IN ULONG InputBufferLength OPTIONAL
,
205 OUT PVOID OutputBuffer
,
206 IN ULONG OutputBufferLength OPTIONAL
,
207 IN BOOLEAN IsDevIoCtl
)
210 PFILE_OBJECT FileObject
;
211 PDEVICE_OBJECT DeviceObject
;
213 PIO_STACK_LOCATION StackPtr
;
214 PKEVENT EventObject
= NULL
;
215 BOOLEAN LockedForSynch
= FALSE
;
217 OBJECT_HANDLE_INFORMATION HandleInformation
;
218 ACCESS_MASK DesiredAccess
;
219 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
225 IOTRACE(IO_CTL_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx\n",
226 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
228 /* Get the access type */
229 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
231 /* Check if we came from user mode */
232 if (PreviousMode
!= KernelMode
)
236 /* Probe the status block */
237 ProbeForWriteIoStatusBlock(IoStatusBlock
);
239 /* Check if this is buffered I/O */
240 if (AccessType
== METHOD_BUFFERED
)
242 /* Check if we have an output buffer */
245 /* Probe the output buffer */
246 ProbeForWrite(OutputBuffer
,
252 /* Make sure the caller can't fake this as we depend on this */
253 OutputBufferLength
= 0;
257 /* Check if we we have an input buffer I/O */
258 if (AccessType
!= METHOD_NEITHER
)
260 /* Check if we have an input buffer */
263 /* Probe the input buffer */
264 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
268 /* Make sure the caller can't fake this as we depend on this */
269 InputBufferLength
= 0;
273 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
275 /* Return the exception code */
276 _SEH2_YIELD(return _SEH2_GetExceptionCode());
281 /* Don't check for access rights right now, KernelMode can do anything */
282 Status
= ObReferenceObjectByHandle(DeviceHandle
,
288 if (!NT_SUCCESS(Status
)) return Status
;
290 /* Can't use an I/O completion port and an APC in the same time */
291 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
294 ObDereferenceObject(FileObject
);
295 return STATUS_INVALID_PARAMETER
;
298 /* Check if we from user mode */
299 if (PreviousMode
!= KernelMode
)
301 /* Get the access mask */
302 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
304 /* Check if we can open it */
305 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
306 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
308 /* Dereference the file object and fail */
309 ObDereferenceObject(FileObject
);
310 return STATUS_ACCESS_DENIED
;
314 /* Check for an event */
318 Status
= ObReferenceObjectByHandle(Event
,
322 (PVOID
*)&EventObject
,
324 if (!NT_SUCCESS(Status
))
326 /* Dereference the file object and fail */
327 ObDereferenceObject(FileObject
);
332 KeClearEvent(EventObject
);
335 /* Check if this is a file that was opened for Synch I/O */
336 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
339 Status
= IopLockFileObject(FileObject
, PreviousMode
);
340 if (Status
!= STATUS_SUCCESS
)
342 if (EventObject
) ObDereferenceObject(EventObject
);
343 ObDereferenceObject(FileObject
);
347 /* Remember to unlock later */
348 LockedForSynch
= TRUE
;
351 /* Check if this is a direct open or not */
352 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
354 /* It's a direct open, get the attached device */
355 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
359 /* Otherwise get the related device */
360 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
363 /* If this is a device I/O, try to do it with FastIO path */
366 PFAST_IO_DISPATCH FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
368 /* Check whether FSD is FastIO aware and provide an appropriate routine */
369 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoDeviceControl
!= NULL
)
371 IO_STATUS_BLOCK KernelIosb
;
373 /* If we have an output buffer coming from usermode */
374 if (PreviousMode
!= KernelMode
&& OutputBuffer
!= NULL
)
376 /* Probe it according to its usage */
379 if (AccessType
== METHOD_IN_DIRECT
)
381 ProbeForRead(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
383 else if (AccessType
== METHOD_OUT_DIRECT
)
385 ProbeForWrite(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
388 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
390 /* Cleanup after exception and return */
391 IopCleanupAfterException(FileObject
, NULL
, EventObject
, NULL
);
393 /* Return the exception code */
394 _SEH2_YIELD(return _SEH2_GetExceptionCode());
399 /* If we are dismounting a volume, increase the dismount count */
400 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
402 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
406 if (FastIoDispatch
->FastIoDeviceControl(FileObject
,
416 IO_COMPLETION_CONTEXT CompletionInfo
= { NULL
, NULL
};
418 /* Write the IOSB back */
421 *IoStatusBlock
= KernelIosb
;
424 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
426 KernelIosb
.Status
= _SEH2_GetExceptionCode();
430 /* Backup our complete context in case it exists */
431 if (FileObject
->CompletionContext
)
433 CompletionInfo
= *(FileObject
->CompletionContext
);
436 /* If we had an event, signal it */
439 KeSetEvent(EventObject
, IO_NO_INCREMENT
, FALSE
);
440 ObDereferenceObject(EventObject
);
443 /* If FO was locked, unlock it */
446 IopUnlockFileObject(FileObject
);
449 /* Set completion if required */
450 if (CompletionInfo
.Port
!= NULL
&& UserApcContext
!= NULL
)
452 if (!NT_SUCCESS(IoSetIoCompletion(CompletionInfo
.Port
,
456 KernelIosb
.Information
,
459 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
463 /* We're done with FastIO! */
464 ObDereferenceObject(FileObject
);
465 return KernelIosb
.Status
;
470 /* Clear the event */
471 KeClearEvent(&FileObject
->Event
);
474 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
475 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
478 Irp
->UserIosb
= IoStatusBlock
;
479 Irp
->UserEvent
= EventObject
;
480 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
481 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
483 Irp
->CancelRoutine
= NULL
;
484 Irp
->PendingReturned
= FALSE
;
485 Irp
->RequestorMode
= PreviousMode
;
486 Irp
->MdlAddress
= NULL
;
487 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
489 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
490 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
491 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
493 /* Set stack location settings */
494 StackPtr
= IoGetNextIrpStackLocation(Irp
);
495 StackPtr
->FileObject
= FileObject
;
496 StackPtr
->MajorFunction
= IsDevIoCtl
?
497 IRP_MJ_DEVICE_CONTROL
:
498 IRP_MJ_FILE_SYSTEM_CONTROL
;
499 StackPtr
->MinorFunction
= 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
500 StackPtr
->Control
= 0;
502 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
504 /* Set the IOCTL Data */
505 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
506 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
507 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
510 PoolType
= IsDevIoCtl
? NonPagedPoolCacheAligned
: NonPagedPool
;
512 /* Handle the Methods */
516 case METHOD_BUFFERED
:
518 /* Enter SEH for allocations */
521 /* Select the right Buffer Length */
522 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
523 InputBufferLength
: OutputBufferLength
;
525 /* Make sure there is one */
528 /* Allocate the System Buffer */
529 Irp
->AssociatedIrp
.SystemBuffer
=
530 ExAllocatePoolWithQuotaTag(PoolType
,
534 /* Check if we got a buffer */
537 /* Copy into the System Buffer */
538 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
543 /* Write the flags */
544 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
545 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
547 /* Save the Buffer */
548 Irp
->UserBuffer
= OutputBuffer
;
552 /* Clear the Flags and Buffer */
553 Irp
->UserBuffer
= NULL
;
556 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
558 /* Cleanup after exception and return */
559 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
560 _SEH2_YIELD(return _SEH2_GetExceptionCode());
566 case METHOD_IN_DIRECT
:
567 case METHOD_OUT_DIRECT
:
572 /* Check if we got an input buffer */
573 if ((InputBufferLength
) && (InputBuffer
))
575 /* Allocate the System Buffer */
576 Irp
->AssociatedIrp
.SystemBuffer
=
577 ExAllocatePoolWithQuotaTag(PoolType
,
581 /* Copy into the System Buffer */
582 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
586 /* Write the flags */
587 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
590 /* Check if we got an output buffer */
591 if (OutputBufferLength
)
593 /* Allocate the System Buffer */
594 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
599 if (!Irp
->MdlAddress
)
601 /* Raise exception we'll catch */
602 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
606 MmProbeAndLockPages(Irp
->MdlAddress
,
608 (AccessType
== METHOD_IN_DIRECT
) ?
609 IoReadAccess
: IoWriteAccess
);
612 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
614 /* Cleanup after exception and return */
615 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
616 _SEH2_YIELD(return _SEH2_GetExceptionCode());
623 /* Just save the Buffer */
624 Irp
->UserBuffer
= OutputBuffer
;
625 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
628 /* Use deferred completion for FS I/O */
631 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
634 /* If we are dismounting a volume, increaase the dismount count */
635 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
637 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
640 /* Perform the call */
641 return IopPerformSynchronousRequest(DeviceObject
,
652 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
653 IN ULONG InformationClass
,
655 OUT PVOID Information
,
656 OUT PULONG ReturnedLength
,
659 IO_STATUS_BLOCK IoStatusBlock
;
661 PDEVICE_OBJECT DeviceObject
;
662 PIO_STACK_LOCATION StackPtr
;
663 BOOLEAN LocalEvent
= FALSE
;
667 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx\n",
668 FileObject
, InformationClass
, File
);
670 /* Reference the object */
671 ObReferenceObject(FileObject
);
673 /* Check if this is a file that was opened for Synch I/O */
674 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
677 (void)IopLockFileObject(FileObject
, KernelMode
);
679 /* Use File Object event */
680 KeClearEvent(&FileObject
->Event
);
684 /* Use local event */
685 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
689 /* Get the Device Object */
690 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
692 /* Allocate the IRP */
693 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
694 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
697 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
698 Irp
->RequestorMode
= KernelMode
;
699 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
700 Irp
->UserIosb
= &IoStatusBlock
;
701 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
702 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
703 Irp
->Flags
|= IRP_BUFFERED_IO
;
704 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
705 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
707 /* Set the Stack Data */
708 StackPtr
= IoGetNextIrpStackLocation(Irp
);
709 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
710 IRP_MJ_QUERY_VOLUME_INFORMATION
;
711 StackPtr
->FileObject
= FileObject
;
713 /* Check which type this is */
717 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
718 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
723 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
724 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
728 IopQueueIrpToThread(Irp
);
730 /* Call the Driver */
731 Status
= IoCallDriver(DeviceObject
, Irp
);
733 /* Check if this was synch I/O */
736 /* Check if the request is pending */
737 if (Status
== STATUS_PENDING
)
739 /* Wait on the file object */
740 Status
= KeWaitForSingleObject(&FileObject
->Event
,
744 FO_ALERTABLE_IO
) != 0,
746 if (Status
== STATUS_ALERTED
)
748 /* Abort the operation */
749 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
752 /* Get the final status */
753 Status
= FileObject
->FinalStatus
;
756 /* Release the file lock */
757 IopUnlockFileObject(FileObject
);
759 else if (Status
== STATUS_PENDING
)
761 /* Wait on the local event and get the final status */
762 KeWaitForSingleObject(&Event
,
767 Status
= IoStatusBlock
.Status
;
770 /* Return the Length and Status. ReturnedLength is NOT optional */
771 *ReturnedLength
= (ULONG
)IoStatusBlock
.Information
;
777 IopGetFileInformation(IN PFILE_OBJECT FileObject
,
779 IN FILE_INFORMATION_CLASS FileInfoClass
,
781 OUT PULONG ReturnedLength
)
786 PIO_STACK_LOCATION Stack
;
787 PDEVICE_OBJECT DeviceObject
;
788 IO_STATUS_BLOCK IoStatusBlock
;
792 /* Allocate an IRP */
793 ObReferenceObject(FileObject
);
794 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
795 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
798 ObDereferenceObject(FileObject
);
799 return STATUS_INSUFFICIENT_RESOURCES
;
803 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
806 Irp
->UserIosb
= &IoStatusBlock
;
807 Irp
->UserEvent
= &Event
;
808 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
809 Irp
->RequestorMode
= KernelMode
;
810 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
811 Irp
->Flags
= IRP_SYNCHRONOUS_API
| IRP_BUFFERED_IO
| IRP_OB_QUERY_NAME
;
812 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
813 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
815 Stack
= IoGetNextIrpStackLocation(Irp
);
816 Stack
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
817 Stack
->FileObject
= FileObject
;
818 Stack
->Parameters
.QueryFile
.FileInformationClass
= FileInfoClass
;
819 Stack
->Parameters
.QueryFile
.Length
= Length
;
823 IopQueueIrpToThread(Irp
);
825 /* Call the driver */
826 Status
= IoCallDriver(DeviceObject
, Irp
);
827 if (Status
== STATUS_PENDING
)
829 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
830 Status
= IoStatusBlock
.Status
;
833 *ReturnedLength
= IoStatusBlock
.Information
;
839 IopGetBasicInformationFile(IN PFILE_OBJECT FileObject
,
840 OUT PFILE_BASIC_INFORMATION BasicInfo
)
842 ULONG ReturnedLength
;
843 PDEVICE_OBJECT DeviceObject
;
844 IO_STATUS_BLOCK IoStatusBlock
;
848 /* Try to do it the fast way if possible */
849 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
850 if (DeviceObject
->DriverObject
->FastIoDispatch
!= NULL
&&
851 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
&&
852 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo(FileObject
,
853 ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) != 0),
858 return IoStatusBlock
.Status
;
861 /* In case it failed, fall back to IRP-based method */
862 return IopGetFileInformation(FileObject
, sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
, BasicInfo
, &ReturnedLength
);
867 IopOpenLinkOrRenameTarget(OUT PHANDLE Handle
,
869 IN PFILE_RENAME_INFORMATION RenameInfo
,
870 IN PFILE_OBJECT FileObject
)
874 UNICODE_STRING FileName
;
875 PIO_STACK_LOCATION Stack
;
876 PFILE_OBJECT TargetFileObject
;
877 IO_STATUS_BLOCK IoStatusBlock
;
878 FILE_BASIC_INFORMATION BasicInfo
;
879 OBJECT_ATTRIBUTES ObjectAttributes
;
880 OBJECT_HANDLE_INFORMATION HandleInformation
;
881 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
885 /* First, establish whether our target is a directory */
886 if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
888 Status
= IopGetBasicInformationFile(FileObject
, &BasicInfo
);
889 if (!NT_SUCCESS(Status
))
894 if (BasicInfo
.FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
895 DesiredAccess
= FILE_ADD_SUBDIRECTORY
;
899 /* Setup the string to the target */
900 FileName
.Buffer
= RenameInfo
->FileName
;
901 FileName
.Length
= RenameInfo
->FileNameLength
;
902 FileName
.MaximumLength
= RenameInfo
->FileNameLength
;
904 InitializeObjectAttributes(&ObjectAttributes
,
906 (FileObject
->Flags
& FO_OPENED_CASE_SENSITIVE
? 0 : OBJ_CASE_INSENSITIVE
) | OBJ_KERNEL_HANDLE
,
907 RenameInfo
->RootDirectory
,
910 /* And open its parent directory
911 * Use hint if specified
913 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
915 PFILE_OBJECT_EXTENSION FileObjectExtension
;
917 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
919 FileObjectExtension
= FileObject
->FileObjectExtension
;
920 Status
= IoCreateFileSpecifyDeviceObjectHint(&TargetHandle
,
921 DesiredAccess
| SYNCHRONIZE
,
926 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
928 FILE_OPEN_FOR_BACKUP_INTENT
,
933 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
,
934 FileObjectExtension
->TopDeviceObjectHint
);
938 Status
= IoCreateFile(&TargetHandle
,
939 DesiredAccess
| SYNCHRONIZE
,
944 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
946 FILE_OPEN_FOR_BACKUP_INTENT
,
951 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
);
954 if (!NT_SUCCESS(Status
))
959 /* Once open, continue only if:
960 * Target exists and we're allowed to overwrite it
962 Stack
= IoGetNextIrpStackLocation(Irp
);
963 if (Stack
->Parameters
.SetFile
.FileInformationClass
== FileLinkInformation
&&
964 !RenameInfo
->ReplaceIfExists
&&
965 IoStatusBlock
.Information
== FILE_EXISTS
)
967 ObCloseHandle(TargetHandle
, KernelMode
);
968 return STATUS_OBJECT_NAME_COLLISION
;
971 /* Now, we'll get the associated device of the target, to check for same device location
972 * So, get the FO first
974 Status
= ObReferenceObjectByHandle(TargetHandle
,
978 (PVOID
*)&TargetFileObject
,
980 if (!NT_SUCCESS(Status
))
982 ObCloseHandle(TargetHandle
, KernelMode
);
986 /* We can dereference, we have the handle */
987 ObDereferenceObject(TargetFileObject
);
988 /* If we're not on the same device, error out **/
989 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
991 ObCloseHandle(TargetHandle
, KernelMode
);
992 return STATUS_NOT_SAME_DEVICE
;
995 /* Return parent directory file object and handle */
996 Stack
->Parameters
.SetFile
.FileObject
= TargetFileObject
;
997 *Handle
= TargetHandle
;
999 return STATUS_SUCCESS
;
1004 IopGetFileMode(IN PFILE_OBJECT FileObject
)
1008 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
1009 Mode
|= FILE_WRITE_THROUGH
;
1011 if (FileObject
->Flags
& FO_SEQUENTIAL_ONLY
)
1012 Mode
|= FILE_SEQUENTIAL_ONLY
;
1014 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
1015 Mode
|= FILE_NO_INTERMEDIATE_BUFFERING
;
1017 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1019 if (FileObject
->Flags
& FO_ALERTABLE_IO
)
1020 Mode
|= FILE_SYNCHRONOUS_IO_ALERT
;
1022 Mode
|= FILE_SYNCHRONOUS_IO_NONALERT
;
1025 if (FileObject
->Flags
& FO_DELETE_ON_CLOSE
)
1026 Mode
|= FILE_DELETE_ON_CLOSE
;
1033 IopGetMountFlag(IN PDEVICE_OBJECT DeviceObject
)
1039 /* Assume not mounted */
1042 /* Check whether we have the mount flag */
1043 IoAcquireVpbSpinLock(&OldIrql
);
1045 Vpb
= DeviceObject
->Vpb
;
1047 BooleanFlagOn(Vpb
->Flags
, VPB_MOUNTED
))
1052 IoReleaseVpbSpinLock(OldIrql
);
1059 IopVerifyDriverObjectOnStack(IN PDEVICE_OBJECT DeviceObject
,
1060 IN PDRIVER_OBJECT DriverObject
)
1062 PDEVICE_OBJECT StackDO
;
1064 /* Browse our whole device stack, trying to find the appropriate driver */
1065 StackDO
= IopGetDeviceAttachmentBase(DeviceObject
);
1066 while (StackDO
!= NULL
)
1068 /* We've found the driver, return success */
1069 if (StackDO
->DriverObject
== DriverObject
)
1074 /* Move to the next */
1075 StackDO
= StackDO
->AttachedDevice
;
1078 /* We only reach there if driver was not found */
1084 IopGetDriverPathInformation(IN PFILE_OBJECT FileObject
,
1085 IN PFILE_FS_DRIVER_PATH_INFORMATION DriverPathInfo
,
1090 UNICODE_STRING DriverName
;
1091 PDRIVER_OBJECT DriverObject
;
1093 /* Make sure the structure is consistent (ie, driver name fits into the buffer) */
1094 if (Length
- FIELD_OFFSET(FILE_FS_DRIVER_PATH_INFORMATION
, DriverName
) < DriverPathInfo
->DriverNameLength
)
1096 return STATUS_INVALID_PARAMETER
;
1099 /* Setup the whole driver name */
1100 DriverName
.Length
= DriverPathInfo
->DriverNameLength
;
1101 DriverName
.MaximumLength
= DriverPathInfo
->DriverNameLength
;
1102 DriverName
.Buffer
= &DriverPathInfo
->DriverName
[0];
1104 /* Ask Ob for such driver */
1105 Status
= ObReferenceObjectByName(&DriverName
,
1106 OBJ_CASE_INSENSITIVE
,
1112 (PVOID
*)&DriverObject
);
1113 /* No such driver, bail out */
1114 if (!NT_SUCCESS(Status
))
1119 /* Lock the devices database, we'll browse it */
1120 OldIrql
= KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock
);
1121 /* If we have a VPB, browse the stack from the volume */
1122 if (FileObject
->Vpb
!= NULL
&& FileObject
->Vpb
->DeviceObject
!= NULL
)
1124 DriverPathInfo
->DriverInPath
= IopVerifyDriverObjectOnStack(FileObject
->Vpb
->DeviceObject
, DriverObject
);
1126 /* Otherwise, do it from the normal device */
1129 DriverPathInfo
->DriverInPath
= IopVerifyDriverObjectOnStack(FileObject
->DeviceObject
, DriverObject
);
1131 KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock
, OldIrql
);
1133 /* No longer needed */
1134 ObDereferenceObject(DriverObject
);
1136 return STATUS_SUCCESS
;
1139 /* PUBLIC FUNCTIONS **********************************************************/
1146 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
1148 IN PLARGE_INTEGER Offset
,
1150 IN PIO_STATUS_BLOCK StatusBlock
)
1153 PIO_STACK_LOCATION StackPtr
;
1154 PDEVICE_OBJECT DeviceObject
;
1155 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p\n",
1156 FileObject
, Mdl
, Offset
);
1158 /* Is the write originating from Cc? */
1159 if (FileObject
->SectionObjectPointer
!= NULL
&&
1160 FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
1163 CcDataPages
+= BYTES_TO_PAGES(MmGetMdlByteCount(Mdl
));
1166 /* Get the Device Object */
1167 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1170 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1171 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1174 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1176 /* Create the IRP Settings */
1177 Irp
->MdlAddress
= Mdl
;
1178 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1179 Irp
->UserIosb
= StatusBlock
;
1180 Irp
->UserEvent
= Event
;
1181 Irp
->RequestorMode
= KernelMode
;
1182 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
1183 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1184 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1186 /* Set the Stack Settings */
1187 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
1188 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
1189 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
1190 StackPtr
->FileObject
= FileObject
;
1192 /* Call the Driver */
1193 return IoCallDriver(DeviceObject
, Irp
);
1201 IoPageRead(IN PFILE_OBJECT FileObject
,
1203 IN PLARGE_INTEGER Offset
,
1205 IN PIO_STATUS_BLOCK StatusBlock
)
1208 PIO_STACK_LOCATION StackPtr
;
1209 PDEVICE_OBJECT DeviceObject
;
1210 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p\n",
1211 FileObject
, Mdl
, Offset
);
1213 /* Get the Device Object */
1214 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1217 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1218 /* If allocation failed, try to see whether we can use
1223 /* We will use it only for paging file */
1224 if (MmIsFileObjectAPagingFile(FileObject
))
1226 InterlockedExchangeAdd(&IoPageReadIrpAllocationFailure
, 1);
1227 Irp
= IopAllocateReserveIrp(DeviceObject
->StackSize
);
1231 InterlockedExchangeAdd(&IoPageReadNonPagefileIrpAllocationFailure
, 1);
1234 /* If allocation failed (not a paging file or too big stack size)
1239 return STATUS_INSUFFICIENT_RESOURCES
;
1244 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1246 /* Create the IRP Settings */
1247 Irp
->MdlAddress
= Mdl
;
1248 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1249 Irp
->UserIosb
= StatusBlock
;
1250 Irp
->UserEvent
= Event
;
1251 Irp
->RequestorMode
= KernelMode
;
1252 Irp
->Flags
= IRP_PAGING_IO
|
1254 IRP_SYNCHRONOUS_PAGING_IO
|
1255 IRP_INPUT_OPERATION
;
1256 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1257 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1259 /* Set the Stack Settings */
1260 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
1261 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
1262 StackPtr
->MajorFunction
= IRP_MJ_READ
;
1263 StackPtr
->FileObject
= FileObject
;
1265 /* Call the Driver */
1266 return IoCallDriver(DeviceObject
, Irp
);
1274 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1275 IN FILE_INFORMATION_CLASS FileInformationClass
,
1277 OUT PVOID FileInformation
,
1278 OUT PULONG ReturnedLength
)
1280 /* Call the shared routine */
1281 return IopQueryDeviceInformation(FileObject
,
1282 FileInformationClass
,
1294 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
1295 IN FS_INFORMATION_CLASS FsInformationClass
,
1297 OUT PVOID FsInformation
,
1298 OUT PULONG ReturnedLength
)
1300 /* Call the shared routine */
1301 return IopQueryDeviceInformation(FileObject
,
1314 IoSetInformation(IN PFILE_OBJECT FileObject
,
1315 IN FILE_INFORMATION_CLASS FileInformationClass
,
1317 IN PVOID FileInformation
)
1319 IO_STATUS_BLOCK IoStatusBlock
;
1321 PDEVICE_OBJECT DeviceObject
;
1322 PIO_STACK_LOCATION StackPtr
;
1323 BOOLEAN LocalEvent
= FALSE
;
1327 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx\n",
1328 FileObject
, FileInformationClass
, Length
);
1330 /* Reference the object */
1331 ObReferenceObject(FileObject
);
1333 /* Check if this is a file that was opened for Synch I/O */
1334 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1337 (void)IopLockFileObject(FileObject
, KernelMode
);
1339 /* Use File Object event */
1340 KeClearEvent(&FileObject
->Event
);
1344 /* Use local event */
1345 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1349 /* Get the Device Object */
1350 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1352 /* Allocate the IRP */
1353 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1354 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1357 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1358 Irp
->RequestorMode
= KernelMode
;
1359 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1360 Irp
->UserIosb
= &IoStatusBlock
;
1361 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1362 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1363 Irp
->Flags
|= IRP_BUFFERED_IO
;
1364 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1365 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1367 /* Set the Stack Data */
1368 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1369 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
1370 StackPtr
->FileObject
= FileObject
;
1372 /* Set Parameters */
1373 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
1374 StackPtr
->Parameters
.SetFile
.Length
= Length
;
1377 IopQueueIrpToThread(Irp
);
1379 /* Call the Driver */
1380 Status
= IoCallDriver(DeviceObject
, Irp
);
1382 /* Check if this was synch I/O */
1385 /* Check if the request is pending */
1386 if (Status
== STATUS_PENDING
)
1388 /* Wait on the file object */
1389 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1392 (FileObject
->Flags
&
1393 FO_ALERTABLE_IO
) != 0,
1395 if (Status
== STATUS_ALERTED
)
1397 /* Abort the operation */
1398 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1401 /* Get the final status */
1402 Status
= FileObject
->FinalStatus
;
1405 /* Release the file lock */
1406 IopUnlockFileObject(FileObject
);
1408 else if (Status
== STATUS_PENDING
)
1410 /* Wait on the local event and get the final status */
1411 KeWaitForSingleObject(&Event
,
1416 Status
= IoStatusBlock
.Status
;
1419 /* Return the status */
1423 /* NATIVE SERVICES ***********************************************************/
1430 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1431 IN HANDLE Event OPTIONAL
,
1432 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1433 IN PVOID UserApcContext OPTIONAL
,
1434 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1435 IN ULONG IoControlCode
,
1436 IN PVOID InputBuffer
,
1437 IN ULONG InputBufferLength OPTIONAL
,
1438 OUT PVOID OutputBuffer
,
1439 IN ULONG OutputBufferLength OPTIONAL
)
1441 /* Call the Generic Function */
1442 return IopDeviceFsIoControl(DeviceHandle
,
1460 NtFsControlFile(IN HANDLE DeviceHandle
,
1461 IN HANDLE Event OPTIONAL
,
1462 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1463 IN PVOID UserApcContext OPTIONAL
,
1464 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1465 IN ULONG IoControlCode
,
1466 IN PVOID InputBuffer
,
1467 IN ULONG InputBufferLength OPTIONAL
,
1468 OUT PVOID OutputBuffer
,
1469 IN ULONG OutputBufferLength OPTIONAL
)
1471 /* Call the Generic Function */
1472 return IopDeviceFsIoControl(DeviceHandle
,
1487 NtFlushBuffersFile(IN HANDLE FileHandle
,
1488 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1490 PFILE_OBJECT FileObject
;
1492 PIO_STACK_LOCATION StackPtr
;
1494 PDEVICE_OBJECT DeviceObject
;
1495 PKEVENT Event
= NULL
;
1496 BOOLEAN LocalEvent
= FALSE
;
1497 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1498 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1499 IO_STATUS_BLOCK KernelIosb
;
1501 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1503 if (PreviousMode
!= KernelMode
)
1505 /* Protect probes */
1508 /* Probe the I/O Status block */
1509 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1511 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1513 /* Return the exception code */
1514 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1519 /* Get the File Object */
1520 Status
= ObReferenceObjectByHandle(FileHandle
,
1524 (PVOID
*)&FileObject
,
1526 if (!NT_SUCCESS(Status
)) return Status
;
1529 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1530 * granted. However, if this is a named pipe, make sure we don't ask for
1531 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1534 if (!(ObjectHandleInfo
.GrantedAccess
&
1535 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1539 ObDereferenceObject(FileObject
);
1540 return STATUS_ACCESS_DENIED
;
1543 /* Check if we should use Sync IO or not */
1544 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1547 Status
= IopLockFileObject(FileObject
, PreviousMode
);
1548 if (Status
!= STATUS_SUCCESS
)
1550 ObDereferenceObject(FileObject
);
1556 /* Use local event */
1557 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1561 ObDereferenceObject(FileObject
);
1562 return STATUS_INSUFFICIENT_RESOURCES
;
1564 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1568 /* Get the Device Object */
1569 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1571 /* Clear the event */
1572 KeClearEvent(&FileObject
->Event
);
1574 /* Allocate the IRP */
1575 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1576 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1578 /* Set up the IRP */
1579 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1580 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1581 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1582 Irp
->RequestorMode
= PreviousMode
;
1583 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1584 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1585 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1587 /* Set up Stack Data */
1588 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1589 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1590 StackPtr
->FileObject
= FileObject
;
1592 /* Call the Driver */
1593 Status
= IopPerformSynchronousRequest(DeviceObject
,
1601 /* Check if this was async I/O */
1604 /* It was, finalize this request */
1605 Status
= IopFinalizeAsynchronousIo(Status
,
1613 /* Return the Status */
1622 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1623 IN HANDLE EventHandle OPTIONAL
,
1624 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1625 IN PVOID ApcContext OPTIONAL
,
1626 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1628 IN ULONG BufferSize
,
1629 IN ULONG CompletionFilter
,
1630 IN BOOLEAN WatchTree
)
1633 PKEVENT Event
= NULL
;
1634 PDEVICE_OBJECT DeviceObject
;
1635 PFILE_OBJECT FileObject
;
1636 PIO_STACK_LOCATION IoStack
;
1637 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1639 BOOLEAN LockedForSync
= FALSE
;
1641 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1643 /* Check if we're called from user mode */
1644 if (PreviousMode
!= KernelMode
)
1646 /* Enter SEH for probing */
1649 /* Probe the I/O STatus block */
1650 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1652 /* Probe the buffer */
1653 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1655 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1657 /* Return the exception code */
1658 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1662 /* Check if CompletionFilter is valid */
1663 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1665 return STATUS_INVALID_PARAMETER
;
1669 /* Get File Object */
1670 Status
= ObReferenceObjectByHandle(FileHandle
,
1671 FILE_LIST_DIRECTORY
,
1674 (PVOID
*)&FileObject
,
1676 if (!NT_SUCCESS(Status
)) return Status
;
1678 /* Check if we have an event handle */
1682 Status
= ObReferenceObjectByHandle(EventHandle
,
1688 if (Status
!= STATUS_SUCCESS
)
1690 ObDereferenceObject(FileObject
);
1693 KeClearEvent(Event
);
1696 /* Check if we should use Sync IO or not */
1697 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1700 Status
= IopLockFileObject(FileObject
, PreviousMode
);
1701 if (Status
!= STATUS_SUCCESS
)
1703 if (Event
) ObDereferenceObject(Event
);
1704 ObDereferenceObject(FileObject
);
1707 LockedForSync
= TRUE
;
1710 /* Clear File Object event */
1711 KeClearEvent(&FileObject
->Event
);
1713 /* Get the device object */
1714 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1716 /* Allocate the IRP */
1717 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1718 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1720 /* Set up the IRP */
1721 Irp
->RequestorMode
= PreviousMode
;
1722 Irp
->UserIosb
= IoStatusBlock
;
1723 Irp
->UserEvent
= Event
;
1724 Irp
->UserBuffer
= Buffer
;
1725 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1726 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1727 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1728 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1730 /* Set up Stack Data */
1731 IoStack
= IoGetNextIrpStackLocation(Irp
);
1732 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1733 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1734 IoStack
->FileObject
= FileObject
;
1736 /* Set parameters */
1737 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1738 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1739 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1741 /* Perform the call */
1742 return IopPerformSynchronousRequest(DeviceObject
,
1756 NtLockFile(IN HANDLE FileHandle
,
1757 IN HANDLE EventHandle OPTIONAL
,
1758 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1759 IN PVOID ApcContext OPTIONAL
,
1760 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1761 IN PLARGE_INTEGER ByteOffset
,
1762 IN PLARGE_INTEGER Length
,
1764 IN BOOLEAN FailImmediately
,
1765 IN BOOLEAN ExclusiveLock
)
1767 PFILE_OBJECT FileObject
;
1768 PLARGE_INTEGER LocalLength
= NULL
;
1770 PIO_STACK_LOCATION StackPtr
;
1771 PDEVICE_OBJECT DeviceObject
;
1772 PKEVENT Event
= NULL
;
1773 BOOLEAN LockedForSync
= FALSE
;
1774 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1775 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1777 OBJECT_HANDLE_INFORMATION HandleInformation
;
1778 PFAST_IO_DISPATCH FastIoDispatch
;
1780 CapturedByteOffset
.QuadPart
= 0;
1781 CapturedLength
.QuadPart
= 0;
1782 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1784 /* Get File Object */
1785 Status
= ObReferenceObjectByHandle(FileHandle
,
1789 (PVOID
*)&FileObject
,
1790 &HandleInformation
);
1791 if (!NT_SUCCESS(Status
)) return Status
;
1793 /* Check if we're called from user mode */
1794 if (PreviousMode
!= KernelMode
)
1796 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1797 if (!(HandleInformation
.GrantedAccess
&
1798 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1800 ObDereferenceObject(FileObject
);
1801 return STATUS_ACCESS_DENIED
;
1804 /* Enter SEH for probing */
1807 /* Probe the I/O STatus block */
1808 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1810 /* Probe and capture the large integers */
1811 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1812 CapturedLength
= ProbeForReadLargeInteger(Length
);
1814 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1816 /* Dereference the object and return exception code */
1817 ObDereferenceObject(FileObject
);
1818 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1824 /* Otherwise, capture them directly */
1825 CapturedByteOffset
= *ByteOffset
;
1826 CapturedLength
= *Length
;
1829 /* Check if we have an event handle */
1833 Status
= ObReferenceObjectByHandle(EventHandle
,
1839 if (Status
!= STATUS_SUCCESS
) return Status
;
1840 KeClearEvent(Event
);
1843 /* Get the device object */
1844 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1846 /* Try to do it the FastIO way if possible */
1847 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1848 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoLock
!= NULL
)
1850 IO_STATUS_BLOCK KernelIosb
;
1852 if (FastIoDispatch
->FastIoLock(FileObject
,
1853 &CapturedByteOffset
,
1855 PsGetCurrentProcess(),
1862 /* Write the IOSB back */
1865 *IoStatusBlock
= KernelIosb
;
1867 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1869 KernelIosb
.Status
= _SEH2_GetExceptionCode();
1873 /* If we had an event, signal it */
1876 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1877 ObDereferenceObject(Event
);
1880 /* Set completion if required */
1881 if (FileObject
->CompletionContext
!= NULL
&& ApcContext
!= NULL
)
1883 if (!NT_SUCCESS(IoSetIoCompletion(FileObject
->CompletionContext
->Port
,
1884 FileObject
->CompletionContext
->Key
,
1887 KernelIosb
.Information
,
1890 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1894 FileObject
->LockOperation
= TRUE
;
1896 /* We're done with FastIO! */
1897 ObDereferenceObject(FileObject
);
1898 return KernelIosb
.Status
;
1902 /* Check if we should use Sync IO or not */
1903 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1906 Status
= IopLockFileObject(FileObject
, PreviousMode
);
1907 if (Status
!= STATUS_SUCCESS
)
1909 if (Event
) ObDereferenceObject(Event
);
1910 ObDereferenceObject(FileObject
);
1913 LockedForSync
= TRUE
;
1916 /* Clear File Object event */
1917 KeClearEvent(&FileObject
->Event
);
1918 FileObject
->LockOperation
= TRUE
;
1920 /* Allocate the IRP */
1921 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1922 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1924 /* Set up the IRP */
1925 Irp
->RequestorMode
= PreviousMode
;
1926 Irp
->UserIosb
= IoStatusBlock
;
1927 Irp
->UserEvent
= Event
;
1928 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1929 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1930 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1931 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1933 /* Set up Stack Data */
1934 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1935 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1936 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1937 StackPtr
->FileObject
= FileObject
;
1939 /* Allocate local buffer */
1940 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1941 sizeof(LARGE_INTEGER
),
1945 /* Allocating failed, clean up and return failure */
1946 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1947 return STATUS_INSUFFICIENT_RESOURCES
;
1950 /* Set the length */
1951 *LocalLength
= CapturedLength
;
1952 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1953 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1955 /* Set Parameters */
1956 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1957 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1960 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1961 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1963 /* Perform the call */
1964 return IopPerformSynchronousRequest(DeviceObject
,
1978 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1979 IN HANDLE EventHandle OPTIONAL
,
1980 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1981 IN PVOID ApcContext OPTIONAL
,
1982 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1983 OUT PVOID FileInformation
,
1985 IN FILE_INFORMATION_CLASS FileInformationClass
,
1986 IN BOOLEAN ReturnSingleEntry
,
1987 IN PUNICODE_STRING FileName OPTIONAL
,
1988 IN BOOLEAN RestartScan
)
1991 PDEVICE_OBJECT DeviceObject
;
1992 PFILE_OBJECT FileObject
;
1993 PIO_STACK_LOCATION StackPtr
;
1994 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1996 BOOLEAN LockedForSynch
= FALSE
;
1997 PKEVENT Event
= NULL
;
1998 volatile PVOID AuxBuffer
= NULL
;
2000 UNICODE_STRING CapturedFileName
;
2001 PUNICODE_STRING SearchPattern
;
2003 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2005 /* Check if we came from user mode */
2006 if (PreviousMode
!= KernelMode
)
2008 /* Enter SEH for probing */
2011 /* Probe the I/O Status Block */
2012 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2014 /* Probe the file information */
2015 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2017 /* Check if we have a file name */
2021 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
2022 if (CapturedFileName
.Length
)
2024 /* Probe its buffer */
2025 ProbeForRead(CapturedFileName
.Buffer
,
2026 CapturedFileName
.Length
,
2030 /* Allocate the auxiliary buffer */
2031 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2032 CapturedFileName
.Length
+
2033 sizeof(UNICODE_STRING
),
2035 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
2036 sizeof(UNICODE_STRING
)),
2037 CapturedFileName
.Buffer
,
2038 CapturedFileName
.Length
);
2040 /* Setup the search pattern */
2041 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
2042 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
2043 sizeof(UNICODE_STRING
));
2044 SearchPattern
->Length
= CapturedFileName
.Length
;
2045 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
2048 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2050 /* Free buffer and return the exception code */
2051 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2052 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2057 /* Check input parameters */
2059 switch (FileInformationClass
)
2061 #define CHECK_LENGTH(class, struct) \
2063 if (Length < sizeof(struct)) \
2064 return STATUS_INFO_LENGTH_MISMATCH; \
2066 CHECK_LENGTH(FileDirectoryInformation
, FILE_DIRECTORY_INFORMATION
);
2067 CHECK_LENGTH(FileFullDirectoryInformation
, FILE_FULL_DIR_INFORMATION
);
2068 CHECK_LENGTH(FileIdFullDirectoryInformation
, FILE_ID_FULL_DIR_INFORMATION
);
2069 CHECK_LENGTH(FileNamesInformation
, FILE_NAMES_INFORMATION
);
2070 CHECK_LENGTH(FileBothDirectoryInformation
, FILE_BOTH_DIR_INFORMATION
);
2071 CHECK_LENGTH(FileIdBothDirectoryInformation
, FILE_ID_BOTH_DIR_INFORMATION
);
2077 /* Get File Object */
2078 Status
= ObReferenceObjectByHandle(FileHandle
,
2079 FILE_LIST_DIRECTORY
,
2082 (PVOID
*)&FileObject
,
2084 if (!NT_SUCCESS(Status
))
2087 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2091 /* Are there two associated completion routines? */
2092 if (FileObject
->CompletionContext
!= NULL
&& ApcRoutine
!= NULL
)
2094 ObDereferenceObject(FileObject
);
2095 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2096 return STATUS_INVALID_PARAMETER
;
2099 /* Check if we have an even handle */
2102 /* Get its pointer */
2103 Status
= ObReferenceObjectByHandle(EventHandle
,
2109 if (!NT_SUCCESS(Status
))
2112 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2113 ObDereferenceObject(FileObject
);
2118 KeClearEvent(Event
);
2121 /* Check if this is a file that was opened for Synch I/O */
2122 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2125 Status
= IopLockFileObject(FileObject
, PreviousMode
);
2126 if (Status
!= STATUS_SUCCESS
)
2128 if (Event
) ObDereferenceObject(Event
);
2129 ObDereferenceObject(FileObject
);
2130 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2134 /* Remember to unlock later */
2135 LockedForSynch
= TRUE
;
2138 /* Get the device object */
2139 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2141 /* Clear the File Object's event */
2142 KeClearEvent(&FileObject
->Event
);
2144 /* Allocate the IRP */
2145 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2146 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
2148 /* Set up the IRP */
2149 Irp
->RequestorMode
= PreviousMode
;
2150 Irp
->UserIosb
= IoStatusBlock
;
2151 Irp
->UserEvent
= Event
;
2152 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2153 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2154 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2155 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2156 Irp
->MdlAddress
= NULL
;
2157 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
2158 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2160 /* Check if this is buffered I/O */
2161 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2163 /* Allocate a buffer */
2164 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2167 if (!Irp
->AssociatedIrp
.SystemBuffer
)
2169 /* Allocating failed, clean up and return the exception code */
2170 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2171 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2173 /* Return the exception code */
2174 return STATUS_INSUFFICIENT_RESOURCES
;
2177 /* Set the buffer and flags */
2178 Irp
->UserBuffer
= FileInformation
;
2179 Irp
->Flags
= (IRP_BUFFERED_IO
|
2180 IRP_DEALLOCATE_BUFFER
|
2181 IRP_INPUT_OPERATION
);
2183 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2187 /* Allocate an MDL */
2188 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
2189 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2190 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2192 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2194 /* Allocating failed, clean up and return the exception code */
2195 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2196 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2202 /* No allocation flags, and use the buffer directly */
2203 Irp
->UserBuffer
= FileInformation
;
2206 /* Set up Stack Data */
2207 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2208 StackPtr
->FileObject
= FileObject
;
2209 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2210 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2212 /* Set Parameters */
2213 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
2214 FileInformationClass
;
2215 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
2216 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2217 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2218 StackPtr
->Flags
= 0;
2219 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2220 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2222 /* Set deferred I/O */
2223 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
2225 /* Perform the call */
2226 return IopPerformSynchronousRequest(DeviceObject
,
2240 NtQueryEaFile(IN HANDLE FileHandle
,
2241 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2244 IN BOOLEAN ReturnSingleEntry
,
2245 IN PVOID EaList OPTIONAL
,
2246 IN ULONG EaListLength
,
2247 IN PULONG EaIndex OPTIONAL
,
2248 IN BOOLEAN RestartScan
)
2251 return STATUS_NOT_IMPLEMENTED
;
2259 NtQueryInformationFile(IN HANDLE FileHandle
,
2260 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2261 IN PVOID FileInformation
,
2263 IN FILE_INFORMATION_CLASS FileInformationClass
)
2265 OBJECT_HANDLE_INFORMATION HandleInformation
;
2266 PFILE_OBJECT FileObject
;
2269 PDEVICE_OBJECT DeviceObject
;
2270 PIO_STACK_LOCATION StackPtr
;
2271 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2272 PKEVENT Event
= NULL
;
2273 BOOLEAN LocalEvent
= FALSE
;
2274 PKNORMAL_ROUTINE NormalRoutine
;
2275 PVOID NormalContext
;
2277 IO_STATUS_BLOCK KernelIosb
;
2278 BOOLEAN CallDriver
= TRUE
;
2279 PFILE_ACCESS_INFORMATION AccessBuffer
;
2280 PFILE_MODE_INFORMATION ModeBuffer
;
2281 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer
;
2282 PFILE_ALL_INFORMATION AllBuffer
;
2283 PFAST_IO_DISPATCH FastIoDispatch
;
2285 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2287 /* Check if we're called from user mode */
2288 if (PreviousMode
!= KernelMode
)
2290 /* Validate the information class */
2291 if ((FileInformationClass
< 0) ||
2292 (FileInformationClass
>= FileMaximumInformation
) ||
2293 !(IopQueryOperationLength
[FileInformationClass
]))
2296 return STATUS_INVALID_INFO_CLASS
;
2299 /* Validate the length */
2300 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2302 /* Invalid length */
2303 return STATUS_INFO_LENGTH_MISMATCH
;
2306 /* Enter SEH for probing */
2309 /* Probe the I/O Status block */
2310 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2312 /* Probe the information */
2313 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2317 /* Return the exception code */
2318 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2325 /* Validate the information class */
2326 if ((FileInformationClass
< 0) ||
2327 (FileInformationClass
>= FileMaximumInformation
) ||
2328 !(IopQueryOperationLength
[FileInformationClass
]))
2331 return STATUS_INVALID_INFO_CLASS
;
2334 /* Validate the length */
2335 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2337 /* Invalid length */
2338 return STATUS_INFO_LENGTH_MISMATCH
;
2343 /* Reference the Handle */
2344 Status
= ObReferenceObjectByHandle(FileHandle
,
2345 IopQueryOperationAccess
2346 [FileInformationClass
],
2349 (PVOID
*)&FileObject
,
2350 &HandleInformation
);
2351 if (!NT_SUCCESS(Status
)) return Status
;
2353 /* Check if this is a direct open or not */
2354 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2356 /* Get the device object */
2357 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2361 /* Get the device object */
2362 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2365 /* Check if this is a file that was opened for Synch I/O */
2366 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2369 Status
= IopLockFileObject(FileObject
, PreviousMode
);
2370 if (Status
!= STATUS_SUCCESS
)
2372 ObDereferenceObject(FileObject
);
2376 /* Check if the caller just wants the position */
2377 if (FileInformationClass
== FilePositionInformation
)
2379 /* Protect write in SEH */
2382 /* Write the offset */
2383 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2384 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2386 /* Fill out the I/O Status Block */
2387 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2388 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2390 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2392 /* Get the exception code */
2393 Status
= _SEH2_GetExceptionCode();
2397 /* Release the file lock, dereference the file and return */
2398 IopUnlockFileObject(FileObject
);
2399 ObDereferenceObject(FileObject
);
2405 /* Use local event */
2406 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2409 ObDereferenceObject(FileObject
);
2410 return STATUS_INSUFFICIENT_RESOURCES
;
2412 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2416 /* Check if FastIO is possible for the two available information classes */
2417 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2418 if (FastIoDispatch
!= NULL
&&
2419 ((FileInformationClass
== FileBasicInformation
&& FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
) ||
2420 (FileInformationClass
== FileStandardInformation
&& FastIoDispatch
->FastIoQueryStandardInfo
!= NULL
)))
2422 BOOLEAN Success
= FALSE
;
2424 if (FileInformationClass
== FileBasicInformation
)
2426 Success
= FastIoDispatch
->FastIoQueryBasicInfo(FileObject
, TRUE
,
2433 Success
= FastIoDispatch
->FastIoQueryStandardInfo(FileObject
, TRUE
,
2439 /* If call succeed */
2442 /* Write the IOSB back */
2445 *IoStatusBlock
= KernelIosb
;
2447 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2449 KernelIosb
.Status
= _SEH2_GetExceptionCode();
2453 /* Free the event if we had one */
2456 ExFreePoolWithTag(Event
, TAG_IO
);
2459 /* If FO was locked, unlock it */
2460 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2462 IopUnlockFileObject(FileObject
);
2465 /* We're done with FastIO! */
2466 ObDereferenceObject(FileObject
);
2467 return KernelIosb
.Status
;
2471 /* Clear the File Object event */
2472 KeClearEvent(&FileObject
->Event
);
2474 /* Allocate the IRP */
2475 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2476 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2479 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2480 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2481 Irp
->RequestorMode
= PreviousMode
;
2482 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2483 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2484 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2485 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2486 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2487 Irp
->MdlAddress
= NULL
;
2488 Irp
->UserBuffer
= FileInformation
;
2490 /* Set the Stack Data */
2491 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2492 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2493 StackPtr
->FileObject
= FileObject
;
2498 /* Allocate a buffer */
2499 Irp
->AssociatedIrp
.SystemBuffer
=
2500 ExAllocatePoolWithTag(NonPagedPool
,
2504 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2506 /* Allocating failed, clean up and return the exception code */
2507 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2508 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2513 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2514 IRP_DEALLOCATE_BUFFER
|
2515 IRP_INPUT_OPERATION
|
2516 IRP_DEFER_IO_COMPLETION
);
2518 /* Set the Parameters */
2519 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2520 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2523 IopQueueIrpToThread(Irp
);
2525 /* Update operation counts */
2526 IopUpdateOperationCount(IopOtherTransfer
);
2528 /* Fill in file information before calling the driver.
2529 See 'File System Internals' page 485.*/
2530 if (FileInformationClass
== FileAccessInformation
)
2532 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2533 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2534 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2537 else if (FileInformationClass
== FileModeInformation
)
2539 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2540 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2541 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2544 else if (FileInformationClass
== FileAlignmentInformation
)
2546 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2547 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2548 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2551 else if (FileInformationClass
== FileAllInformation
)
2553 AllBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2554 AllBuffer
->AccessInformation
.AccessFlags
= HandleInformation
.GrantedAccess
;
2555 AllBuffer
->ModeInformation
.Mode
= IopGetFileMode(FileObject
);
2556 AllBuffer
->AlignmentInformation
.AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2557 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
) +
2558 sizeof(FILE_MODE_INFORMATION
) +
2559 sizeof(FILE_ALIGNMENT_INFORMATION
);
2562 /* Call the Driver */
2565 Status
= IoCallDriver(DeviceObject
, Irp
);
2569 Status
= STATUS_SUCCESS
;
2570 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2573 if (Status
== STATUS_PENDING
)
2575 /* Check if this was async I/O */
2578 /* Then to a non-alertable wait */
2579 Status
= KeWaitForSingleObject(Event
,
2584 if (Status
== STATUS_USER_APC
)
2586 /* Abort the request */
2587 IopAbortInterruptedIrp(Event
, Irp
);
2590 /* Set the final status */
2591 Status
= KernelIosb
.Status
;
2593 /* Enter SEH to write the IOSB back */
2596 /* Write it back to the caller */
2597 *IoStatusBlock
= KernelIosb
;
2599 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2601 /* Get the exception code */
2602 Status
= _SEH2_GetExceptionCode();
2606 /* Free the event */
2607 ExFreePoolWithTag(Event
, TAG_IO
);
2611 /* Wait for the IRP */
2612 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2615 (FileObject
->Flags
&
2616 FO_ALERTABLE_IO
) != 0,
2618 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2620 /* Abort the request */
2621 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2624 /* Set the final status */
2625 Status
= FileObject
->FinalStatus
;
2627 /* Release the file lock */
2628 IopUnlockFileObject(FileObject
);
2633 /* Free the event if we had one */
2636 /* Clear it in the IRP for completion */
2637 Irp
->UserEvent
= NULL
;
2638 ExFreePoolWithTag(Event
, TAG_IO
);
2641 /* Set the caller IOSB */
2642 Irp
->UserIosb
= IoStatusBlock
;
2644 /* The IRP wasn't completed, complete it ourselves */
2645 NormalRoutine
= NULL
;
2646 NormalContext
= NULL
;
2647 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2648 IopCompleteRequest(&Irp
->Tail
.Apc
,
2651 (PVOID
*)&FileObject
,
2653 KeLowerIrql(OldIrql
);
2655 /* Release the file object if we had locked it*/
2656 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2659 /* Return the Status */
2668 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2669 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2672 IN BOOLEAN ReturnSingleEntry
,
2673 IN PVOID SidList OPTIONAL
,
2674 IN ULONG SidListLength
,
2675 IN PSID StartSid OPTIONAL
,
2676 IN BOOLEAN RestartScan
)
2679 return STATUS_NOT_IMPLEMENTED
;
2687 NtReadFile(IN HANDLE FileHandle
,
2688 IN HANDLE Event OPTIONAL
,
2689 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2690 IN PVOID ApcContext OPTIONAL
,
2691 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2694 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2695 IN PULONG Key OPTIONAL
)
2698 PFILE_OBJECT FileObject
;
2700 PDEVICE_OBJECT DeviceObject
;
2701 PIO_STACK_LOCATION StackPtr
;
2702 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2703 PKEVENT EventObject
= NULL
;
2704 LARGE_INTEGER CapturedByteOffset
;
2705 ULONG CapturedKey
= 0;
2706 BOOLEAN Synchronous
= FALSE
;
2708 PFAST_IO_DISPATCH FastIoDispatch
;
2709 IO_STATUS_BLOCK KernelIosb
;
2713 CapturedByteOffset
.QuadPart
= 0;
2714 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2716 /* Get File Object */
2717 Status
= ObReferenceObjectByHandle(FileHandle
,
2721 (PVOID
*)&FileObject
,
2723 if (!NT_SUCCESS(Status
)) return Status
;
2725 /* Get the device object */
2726 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2728 /* Validate User-Mode Buffers */
2729 if (PreviousMode
!= KernelMode
)
2733 /* Probe the status block */
2734 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2736 /* Probe the read buffer */
2737 ProbeForWrite(Buffer
, Length
, 1);
2739 /* Check if we got a byte offset */
2742 /* Capture and probe it */
2743 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2746 /* Perform additional checks for non-cached file access */
2747 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
2749 /* Fail if Length is not sector size aligned
2750 * Perform a quick check for 2^ sector sizes
2751 * If it fails, try a more standard way
2753 if ((DeviceObject
->SectorSize
!= 0) &&
2754 ((DeviceObject
->SectorSize
- 1) & Length
) != 0)
2756 if (Length
% DeviceObject
->SectorSize
!= 0)
2758 /* Release the file object and and fail */
2759 ObDereferenceObject(FileObject
);
2760 return STATUS_INVALID_PARAMETER
;
2764 /* Fail if buffer doesn't match alignment requirements */
2765 if (((ULONG_PTR
)Buffer
& DeviceObject
->AlignmentRequirement
) != 0)
2767 /* Release the file object and and fail */
2768 ObDereferenceObject(FileObject
);
2769 return STATUS_INVALID_PARAMETER
;
2774 /* Fail if ByteOffset is not sector size aligned */
2775 if ((DeviceObject
->SectorSize
!= 0) &&
2776 (CapturedByteOffset
.QuadPart
% DeviceObject
->SectorSize
!= 0))
2778 /* Release the file object and and fail */
2779 ObDereferenceObject(FileObject
);
2780 return STATUS_INVALID_PARAMETER
;
2785 /* Capture and probe the key */
2786 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2788 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2790 /* Release the file object and return the exception code */
2791 ObDereferenceObject(FileObject
);
2792 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2798 /* Kernel mode: capture directly */
2799 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2800 if (Key
) CapturedKey
= *Key
;
2803 /* Check for invalid offset */
2804 if ((CapturedByteOffset
.QuadPart
< 0) && (CapturedByteOffset
.QuadPart
!= -2))
2806 /* -2 is FILE_USE_FILE_POINTER_POSITION */
2807 ObDereferenceObject(FileObject
);
2808 return STATUS_INVALID_PARAMETER
;
2811 /* Check for event */
2815 Status
= ObReferenceObjectByHandle(Event
,
2819 (PVOID
*)&EventObject
,
2821 if (!NT_SUCCESS(Status
))
2824 ObDereferenceObject(FileObject
);
2828 /* Otherwise reset the event */
2829 KeClearEvent(EventObject
);
2832 /* Check if we should use Sync IO or not */
2833 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2835 /* Lock the file object */
2836 Status
= IopLockFileObject(FileObject
, PreviousMode
);
2837 if (Status
!= STATUS_SUCCESS
)
2839 if (EventObject
) ObDereferenceObject(EventObject
);
2840 ObDereferenceObject(FileObject
);
2844 /* Check if we don't have a byte offset available */
2845 if (!(ByteOffset
) ||
2846 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2847 (CapturedByteOffset
.u
.HighPart
== -1)))
2849 /* Use the Current Byte Offset instead */
2850 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2853 /* If the file is cached, try fast I/O */
2854 if (FileObject
->PrivateCacheMap
)
2856 /* Perform fast read */
2857 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2858 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoRead
!= NULL
);
2860 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2861 &CapturedByteOffset
,
2869 /* Only accept the result if we got a straightforward status */
2871 (KernelIosb
.Status
== STATUS_SUCCESS
||
2872 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2873 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2875 /* Fast path -- update transfer & operation counts */
2876 IopUpdateOperationCount(IopReadTransfer
);
2877 IopUpdateTransferCount(IopReadTransfer
,
2878 (ULONG
)KernelIosb
.Information
);
2880 /* Enter SEH to write the IOSB back */
2883 /* Write it back to the caller */
2884 *IoStatusBlock
= KernelIosb
;
2886 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2888 /* The caller's IOSB was invalid, so fail */
2889 if (EventObject
) ObDereferenceObject(EventObject
);
2890 IopUnlockFileObject(FileObject
);
2891 ObDereferenceObject(FileObject
);
2892 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2896 /* Signal the completion event */
2899 KeSetEvent(EventObject
, 0, FALSE
);
2900 ObDereferenceObject(EventObject
);
2904 IopUnlockFileObject(FileObject
);
2905 ObDereferenceObject(FileObject
);
2906 return KernelIosb
.Status
;
2910 /* Remember we are sync */
2913 else if (!(ByteOffset
) &&
2914 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2916 /* Otherwise, this was async I/O without a byte offset, so fail */
2917 if (EventObject
) ObDereferenceObject(EventObject
);
2918 ObDereferenceObject(FileObject
);
2919 return STATUS_INVALID_PARAMETER
;
2922 /* Clear the File Object's event */
2923 KeClearEvent(&FileObject
->Event
);
2925 /* Allocate the IRP */
2926 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2927 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2930 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2931 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2932 Irp
->RequestorMode
= PreviousMode
;
2933 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2934 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2935 Irp
->UserIosb
= IoStatusBlock
;
2936 Irp
->UserEvent
= EventObject
;
2937 Irp
->PendingReturned
= FALSE
;
2938 Irp
->Cancel
= FALSE
;
2939 Irp
->CancelRoutine
= NULL
;
2940 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2941 Irp
->MdlAddress
= NULL
;
2943 /* Set the Stack Data */
2944 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2945 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2946 StackPtr
->FileObject
= FileObject
;
2947 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2948 StackPtr
->Parameters
.Read
.Length
= Length
;
2949 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2951 /* Check if this is buffered I/O */
2952 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2954 /* Check if we have a buffer length */
2960 /* Allocate a buffer */
2961 Irp
->AssociatedIrp
.SystemBuffer
=
2962 ExAllocatePoolWithTag(NonPagedPool
,
2966 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2968 /* Allocating failed, clean up and return the exception code */
2969 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2970 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2974 /* Set the buffer and flags */
2975 Irp
->UserBuffer
= Buffer
;
2976 Irp
->Flags
= (IRP_BUFFERED_IO
|
2977 IRP_DEALLOCATE_BUFFER
|
2978 IRP_INPUT_OPERATION
);
2982 /* Not reading anything */
2983 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2986 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2988 /* Check if we have a buffer length */
2993 /* Allocate an MDL */
2994 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2996 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2997 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2999 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3001 /* Allocating failed, clean up and return the exception code */
3002 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3003 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3009 /* No allocation flags */
3014 /* No allocation flags, and use the buffer directly */
3016 Irp
->UserBuffer
= Buffer
;
3019 /* Now set the deferred read flags */
3020 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3022 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3024 /* Perform the call */
3025 return IopPerformSynchronousRequest(DeviceObject
,
3039 NtReadFileScatter(IN HANDLE FileHandle
,
3040 IN HANDLE Event OPTIONAL
,
3041 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3042 IN PVOID UserApcContext OPTIONAL
,
3043 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3044 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3045 IN ULONG BufferLength
,
3046 IN PLARGE_INTEGER ByteOffset
,
3047 IN PULONG Key OPTIONAL
)
3050 return STATUS_NOT_IMPLEMENTED
;
3058 NtSetEaFile(IN HANDLE FileHandle
,
3059 IN PIO_STATUS_BLOCK IoStatusBlock
,
3061 IN ULONG EaBufferSize
)
3064 return STATUS_NOT_IMPLEMENTED
;
3072 NtSetInformationFile(IN HANDLE FileHandle
,
3073 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3074 IN PVOID FileInformation
,
3076 IN FILE_INFORMATION_CLASS FileInformationClass
)
3078 PFILE_OBJECT FileObject
;
3081 PDEVICE_OBJECT DeviceObject
;
3082 PIO_STACK_LOCATION StackPtr
;
3083 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3084 PKEVENT Event
= NULL
;
3085 BOOLEAN LocalEvent
= FALSE
;
3086 PKNORMAL_ROUTINE NormalRoutine
;
3087 PVOID NormalContext
;
3089 IO_STATUS_BLOCK KernelIosb
;
3091 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
3092 PIO_COMPLETION_CONTEXT Context
;
3093 PFILE_RENAME_INFORMATION RenameInfo
;
3094 HANDLE TargetHandle
= NULL
;
3096 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3098 /* Check if we're called from user mode */
3099 if (PreviousMode
!= KernelMode
)
3101 /* Validate the information class */
3102 if ((FileInformationClass
< 0) ||
3103 (FileInformationClass
>= FileMaximumInformation
) ||
3104 !(IopSetOperationLength
[FileInformationClass
]))
3107 return STATUS_INVALID_INFO_CLASS
;
3110 /* Validate the length */
3111 if (Length
< IopSetOperationLength
[FileInformationClass
])
3113 /* Invalid length */
3114 return STATUS_INFO_LENGTH_MISMATCH
;
3117 /* Enter SEH for probing */
3120 /* Probe the I/O Status block */
3121 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3123 /* Probe the information */
3124 ProbeForRead(FileInformation
,
3126 (Length
== sizeof(BOOLEAN
)) ?
3127 sizeof(BOOLEAN
) : sizeof(ULONG
));
3129 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3131 /* Return the exception code */
3132 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3138 /* Validate the information class */
3139 if ((FileInformationClass
< 0) ||
3140 (FileInformationClass
>= FileMaximumInformation
) ||
3141 !(IopSetOperationLength
[FileInformationClass
]))
3144 return STATUS_INVALID_INFO_CLASS
;
3147 /* Validate the length */
3148 if (Length
< IopSetOperationLength
[FileInformationClass
])
3150 /* Invalid length */
3151 return STATUS_INFO_LENGTH_MISMATCH
;
3155 /* Reference the Handle */
3156 Status
= ObReferenceObjectByHandle(FileHandle
,
3157 IopSetOperationAccess
3158 [FileInformationClass
],
3161 (PVOID
*)&FileObject
,
3163 if (!NT_SUCCESS(Status
)) return Status
;
3165 /* Check if this is a direct open or not */
3166 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3168 /* Get the device object */
3169 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3173 /* Get the device object */
3174 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3177 DPRINT("Will call: %p\n", DeviceObject
);
3178 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
3180 /* Check if this is a file that was opened for Synch I/O */
3181 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3184 Status
= IopLockFileObject(FileObject
, PreviousMode
);
3185 if (Status
!= STATUS_SUCCESS
)
3187 ObDereferenceObject(FileObject
);
3191 /* Check if the caller just wants the position */
3192 if (FileInformationClass
== FilePositionInformation
)
3194 /* Protect write in SEH */
3197 /* Write the offset */
3198 FileObject
->CurrentByteOffset
=
3199 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
3202 /* Fill out the I/O Status Block */
3203 IoStatusBlock
->Information
= 0;
3204 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
3206 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3208 /* Get the exception code */
3209 Status
= _SEH2_GetExceptionCode();
3213 /* Update transfer count */
3214 IopUpdateTransferCount(IopOtherTransfer
, Length
);
3216 /* Release the file lock, dereference the file and return */
3217 IopUnlockFileObject(FileObject
);
3218 ObDereferenceObject(FileObject
);
3224 /* Use local event */
3225 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3228 ObDereferenceObject(FileObject
);
3229 return STATUS_INSUFFICIENT_RESOURCES
;
3232 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3236 /* Clear the File Object event */
3237 KeClearEvent(&FileObject
->Event
);
3239 /* Allocate the IRP */
3240 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
3241 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3244 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3245 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3246 Irp
->RequestorMode
= PreviousMode
;
3247 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3248 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3249 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3250 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3251 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3252 Irp
->MdlAddress
= NULL
;
3253 Irp
->UserBuffer
= FileInformation
;
3255 /* Set the Stack Data */
3256 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3257 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
3258 StackPtr
->FileObject
= FileObject
;
3263 /* Allocate a buffer */
3264 Irp
->AssociatedIrp
.SystemBuffer
=
3265 ExAllocatePoolWithTag(NonPagedPool
,
3269 /* Copy the data into it */
3270 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3274 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3276 /* Allocating failed, clean up and return the exception code */
3277 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3278 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3283 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3284 IRP_DEALLOCATE_BUFFER
|
3285 IRP_DEFER_IO_COMPLETION
);
3287 /* Set the Parameters */
3288 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
3289 StackPtr
->Parameters
.SetFile
.Length
= Length
;
3292 IopQueueIrpToThread(Irp
);
3294 /* Update operation counts */
3295 IopUpdateOperationCount(IopOtherTransfer
);
3297 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3298 /* Handle IO Completion Port quickly */
3299 if (FileInformationClass
== FileCompletionInformation
)
3301 /* Check if the file object already has a completion port */
3302 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3303 (FileObject
->CompletionContext
))
3306 Status
= STATUS_INVALID_PARAMETER
;
3310 /* Reference the Port */
3311 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3312 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3313 IO_COMPLETION_MODIFY_STATE
,
3318 if (NT_SUCCESS(Status
))
3320 /* Allocate the Context */
3321 Context
= ExAllocatePoolWithTag(PagedPool
,
3322 sizeof(IO_COMPLETION_CONTEXT
),
3327 Context
->Key
= CompletionInfo
->Key
;
3328 Context
->Port
= Queue
;
3329 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3335 * Someone else set the completion port in the
3336 * meanwhile, so dereference the port and fail.
3338 ExFreePoolWithTag(Context
, IOC_TAG
);
3339 ObDereferenceObject(Queue
);
3340 Status
= STATUS_INVALID_PARAMETER
;
3345 /* Dereference the Port now */
3346 ObDereferenceObject(Queue
);
3347 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3352 /* Set the IRP Status */
3353 Irp
->IoStatus
.Status
= Status
;
3354 Irp
->IoStatus
.Information
= 0;
3356 else if (FileInformationClass
== FileRenameInformation
||
3357 FileInformationClass
== FileLinkInformation
||
3358 FileInformationClass
== FileMoveClusterInformation
)
3360 /* Get associated information */
3361 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3366 * -> sizes are valid
3368 if (RenameInfo
->FileNameLength
!= 0 &&
3369 !(RenameInfo
->FileNameLength
& 1) &&
3370 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3372 /* Properly set information received */
3373 if (FileInformationClass
== FileMoveClusterInformation
)
3375 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3379 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3382 /* If we got fully path OR relative target, attempt a parent directory open */
3383 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3385 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3386 if (!NT_SUCCESS(Status
))
3388 Irp
->IoStatus
.Status
= Status
;
3392 /* Call the Driver */
3393 Status
= IoCallDriver(DeviceObject
, Irp
);
3398 /* Call the Driver */
3399 Status
= IoCallDriver(DeviceObject
, Irp
);
3404 Status
= STATUS_INVALID_PARAMETER
;
3405 Irp
->IoStatus
.Status
= Status
;
3410 /* Call the Driver */
3411 Status
= IoCallDriver(DeviceObject
, Irp
);
3414 /* Check if we're waiting for the IRP to complete */
3415 if (Status
== STATUS_PENDING
)
3417 /* Check if this was async I/O */
3420 /* Then to a non-alertable wait */
3421 Status
= KeWaitForSingleObject(Event
,
3426 if (Status
== STATUS_USER_APC
)
3428 /* Abort the request */
3429 IopAbortInterruptedIrp(Event
, Irp
);
3432 /* Set the final status */
3433 Status
= KernelIosb
.Status
;
3435 /* Enter SEH to write the IOSB back */
3438 /* Write it back to the caller */
3439 *IoStatusBlock
= KernelIosb
;
3441 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3443 /* Get the exception code */
3444 Status
= _SEH2_GetExceptionCode();
3448 /* Free the event */
3449 ExFreePoolWithTag(Event
, TAG_IO
);
3453 /* Wait for the IRP */
3454 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3457 (FileObject
->Flags
&
3458 FO_ALERTABLE_IO
) != 0,
3460 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3462 /* Abort the request */
3463 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3466 /* Set the final status */
3467 Status
= FileObject
->FinalStatus
;
3469 /* Release the file lock */
3470 IopUnlockFileObject(FileObject
);
3475 /* Free the event if we had one */
3478 /* Clear it in the IRP for completion */
3479 Irp
->UserEvent
= NULL
;
3480 ExFreePoolWithTag(Event
, TAG_IO
);
3483 /* Set the caller IOSB */
3484 Irp
->UserIosb
= IoStatusBlock
;
3486 /* The IRP wasn't completed, complete it ourselves */
3487 NormalRoutine
= NULL
;
3488 NormalContext
= NULL
;
3489 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3490 IopCompleteRequest(&Irp
->Tail
.Apc
,
3493 (PVOID
*)&FileObject
,
3495 KeLowerIrql(OldIrql
);
3497 /* Release the file object if we had locked it*/
3498 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3501 if (TargetHandle
!= NULL
)
3503 ObCloseHandle(TargetHandle
, KernelMode
);
3506 /* Return the Status */
3515 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3516 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3518 IN ULONG BufferLength
)
3521 return STATUS_NOT_IMPLEMENTED
;
3529 NtUnlockFile(IN HANDLE FileHandle
,
3530 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3531 IN PLARGE_INTEGER ByteOffset
,
3532 IN PLARGE_INTEGER Length
,
3533 IN ULONG Key OPTIONAL
)
3535 PFILE_OBJECT FileObject
;
3536 PLARGE_INTEGER LocalLength
= NULL
;
3538 PIO_STACK_LOCATION StackPtr
;
3539 PDEVICE_OBJECT DeviceObject
;
3540 PKEVENT Event
= NULL
;
3541 BOOLEAN LocalEvent
= FALSE
;
3542 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3543 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3545 OBJECT_HANDLE_INFORMATION HandleInformation
;
3546 IO_STATUS_BLOCK KernelIosb
;
3547 PFAST_IO_DISPATCH FastIoDispatch
;
3549 CapturedByteOffset
.QuadPart
= 0;
3550 CapturedLength
.QuadPart
= 0;
3551 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3553 /* Get File Object */
3554 Status
= ObReferenceObjectByHandle(FileHandle
,
3558 (PVOID
*)&FileObject
,
3559 &HandleInformation
);
3560 if (!NT_SUCCESS(Status
)) return Status
;
3562 /* Check if we're called from user mode */
3563 if (PreviousMode
!= KernelMode
)
3565 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3566 if (!(HandleInformation
.GrantedAccess
&
3567 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3569 ObDereferenceObject(FileObject
);
3570 return STATUS_ACCESS_DENIED
;
3573 /* Enter SEH for probing */
3576 /* Probe the I/O Status block */
3577 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3579 /* Probe and capture the large integers */
3580 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3581 CapturedLength
= ProbeForReadLargeInteger(Length
);
3583 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3585 /* Dereference the object and return exception code */
3586 ObDereferenceObject(FileObject
);
3587 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3593 /* Otherwise, capture them directly */
3594 CapturedByteOffset
= *ByteOffset
;
3595 CapturedLength
= *Length
;
3598 /* Check if this is a direct open or not */
3599 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3601 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3605 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3608 /* Try to do it the FastIO way if possible */
3609 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3610 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3612 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3613 &CapturedByteOffset
,
3615 PsGetCurrentProcess(),
3620 /* Write the IOSB back */
3623 *IoStatusBlock
= KernelIosb
;
3625 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3627 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3631 /* We're done with FastIO! */
3632 ObDereferenceObject(FileObject
);
3633 return KernelIosb
.Status
;
3637 /* Check if we should use Sync IO or not */
3638 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3641 Status
= IopLockFileObject(FileObject
, PreviousMode
);
3642 if (Status
!= STATUS_SUCCESS
)
3644 ObDereferenceObject(FileObject
);
3650 /* Use local event */
3651 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3654 ObDereferenceObject(FileObject
);
3655 return STATUS_INSUFFICIENT_RESOURCES
;
3657 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3661 /* Clear File Object event */
3662 KeClearEvent(&FileObject
->Event
);
3664 /* Allocate the IRP */
3665 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3666 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3668 /* Set up the IRP */
3669 Irp
->RequestorMode
= PreviousMode
;
3670 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3671 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3672 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3673 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3674 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3675 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3677 /* Set up Stack Data */
3678 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3679 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3680 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3681 StackPtr
->FileObject
= FileObject
;
3686 /* Allocate a buffer */
3687 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3688 sizeof(LARGE_INTEGER
),
3691 /* Set the length */
3692 *LocalLength
= CapturedLength
;
3693 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3694 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3696 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3698 /* Allocating failed, clean up and return the exception code */
3699 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3700 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3702 /* Return the exception code */
3703 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3707 /* Set Parameters */
3708 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3709 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3711 /* Call the Driver */
3712 Status
= IopPerformSynchronousRequest(DeviceObject
,
3720 /* Check if this was async I/O */
3723 /* It was, finalize this request */
3724 Status
= IopFinalizeAsynchronousIo(Status
,
3741 NtWriteFile(IN HANDLE FileHandle
,
3742 IN HANDLE Event OPTIONAL
,
3743 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3744 IN PVOID ApcContext OPTIONAL
,
3745 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3748 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3749 IN PULONG Key OPTIONAL
)
3752 PFILE_OBJECT FileObject
;
3754 PDEVICE_OBJECT DeviceObject
;
3755 PIO_STACK_LOCATION StackPtr
;
3756 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3757 PKEVENT EventObject
= NULL
;
3758 LARGE_INTEGER CapturedByteOffset
;
3759 ULONG CapturedKey
= 0;
3760 BOOLEAN Synchronous
= FALSE
;
3762 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3763 PFAST_IO_DISPATCH FastIoDispatch
;
3764 IO_STATUS_BLOCK KernelIosb
;
3768 CapturedByteOffset
.QuadPart
= 0;
3769 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3771 /* Get File Object for write */
3772 Status
= ObReferenceFileObjectForWrite(FileHandle
,
3776 if (!NT_SUCCESS(Status
)) return Status
;
3778 /* Get the device object */
3779 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3781 /* Validate User-Mode Buffers */
3782 if (PreviousMode
!= KernelMode
)
3786 /* Probe the status block */
3787 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3789 /* Probe the read buffer */
3790 ProbeForRead(Buffer
, Length
, 1);
3792 /* Check if we got a byte offset */
3795 /* Capture and probe it */
3796 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3799 /* Perform additional checks for non-cached file access */
3800 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
3802 /* Fail if Length is not sector size aligned
3803 * Perform a quick check for 2^ sector sizes
3804 * If it fails, try a more standard way
3806 if ((DeviceObject
->SectorSize
!= 0) &&
3807 ((DeviceObject
->SectorSize
- 1) & Length
) != 0)
3809 if (Length
% DeviceObject
->SectorSize
!= 0)
3811 /* Release the file object and and fail */
3812 ObDereferenceObject(FileObject
);
3813 return STATUS_INVALID_PARAMETER
;
3817 /* Fail if buffer doesn't match alignment requirements */
3818 if (((ULONG_PTR
)Buffer
& DeviceObject
->AlignmentRequirement
) != 0)
3820 /* Release the file object and and fail */
3821 ObDereferenceObject(FileObject
);
3822 return STATUS_INVALID_PARAMETER
;
3827 /* Fail if ByteOffset is not sector size aligned */
3828 if ((DeviceObject
->SectorSize
!= 0) &&
3829 (CapturedByteOffset
.QuadPart
% DeviceObject
->SectorSize
!= 0))
3831 /* Only if that's not specific values for synchronous IO */
3832 if ((CapturedByteOffset
.QuadPart
!= FILE_WRITE_TO_END_OF_FILE
) &&
3833 (CapturedByteOffset
.QuadPart
!= FILE_USE_FILE_POINTER_POSITION
||
3834 !BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
)))
3836 /* Release the file object and and fail */
3837 ObDereferenceObject(FileObject
);
3838 return STATUS_INVALID_PARAMETER
;
3844 /* Capture and probe the key */
3845 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3847 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3849 /* Release the file object and return the exception code */
3850 ObDereferenceObject(FileObject
);
3851 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3857 /* Kernel mode: capture directly */
3858 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3859 if (Key
) CapturedKey
= *Key
;
3862 /* Check for invalid offset */
3863 if (CapturedByteOffset
.QuadPart
< -2)
3865 /* -1 is FILE_WRITE_TO_END_OF_FILE */
3866 /* -2 is FILE_USE_FILE_POINTER_POSITION */
3867 ObDereferenceObject(FileObject
);
3868 return STATUS_INVALID_PARAMETER
;
3871 /* Check if this is an append operation */
3872 if ((ObjectHandleInfo
.GrantedAccess
&
3873 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3875 /* Give the drivers something to understand */
3876 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3877 CapturedByteOffset
.u
.HighPart
= -1;
3880 /* Check for event */
3884 Status
= ObReferenceObjectByHandle(Event
,
3888 (PVOID
*)&EventObject
,
3890 if (!NT_SUCCESS(Status
))
3893 ObDereferenceObject(FileObject
);
3897 /* Otherwise reset the event */
3898 KeClearEvent(EventObject
);
3901 /* Check if we should use Sync IO or not */
3902 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3904 /* Lock the file object */
3905 Status
= IopLockFileObject(FileObject
, PreviousMode
);
3906 if (Status
!= STATUS_SUCCESS
)
3908 if (EventObject
) ObDereferenceObject(EventObject
);
3909 ObDereferenceObject(FileObject
);
3913 /* Check if we don't have a byte offset available */
3914 if (!(ByteOffset
) ||
3915 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3916 (CapturedByteOffset
.u
.HighPart
== -1)))
3918 /* Use the Current Byte Offset instead */
3919 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3922 /* If the file is cached, try fast I/O */
3923 if (FileObject
->PrivateCacheMap
)
3925 /* Perform fast write */
3926 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3927 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoWrite
!= NULL
);
3929 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3930 &CapturedByteOffset
,
3938 /* Only accept the result if it was successful */
3940 KernelIosb
.Status
== STATUS_SUCCESS
)
3942 /* Fast path -- update transfer & operation counts */
3943 IopUpdateOperationCount(IopWriteTransfer
);
3944 IopUpdateTransferCount(IopWriteTransfer
,
3945 (ULONG
)KernelIosb
.Information
);
3947 /* Enter SEH to write the IOSB back */
3950 /* Write it back to the caller */
3951 *IoStatusBlock
= KernelIosb
;
3953 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3955 /* The caller's IOSB was invalid, so fail */
3956 if (EventObject
) ObDereferenceObject(EventObject
);
3957 IopUnlockFileObject(FileObject
);
3958 ObDereferenceObject(FileObject
);
3959 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3963 /* Signal the completion event */
3966 KeSetEvent(EventObject
, 0, FALSE
);
3967 ObDereferenceObject(EventObject
);
3971 IopUnlockFileObject(FileObject
);
3972 ObDereferenceObject(FileObject
);
3973 return KernelIosb
.Status
;
3977 /* Remember we are sync */
3980 else if (!(ByteOffset
) &&
3981 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3983 /* Otherwise, this was async I/O without a byte offset, so fail */
3984 if (EventObject
) ObDereferenceObject(EventObject
);
3985 ObDereferenceObject(FileObject
);
3986 return STATUS_INVALID_PARAMETER
;
3989 /* Clear the File Object's event */
3990 KeClearEvent(&FileObject
->Event
);
3992 /* Allocate the IRP */
3993 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3994 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3997 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3998 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3999 Irp
->RequestorMode
= PreviousMode
;
4000 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
4001 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
4002 Irp
->UserIosb
= IoStatusBlock
;
4003 Irp
->UserEvent
= EventObject
;
4004 Irp
->PendingReturned
= FALSE
;
4005 Irp
->Cancel
= FALSE
;
4006 Irp
->CancelRoutine
= NULL
;
4007 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4008 Irp
->MdlAddress
= NULL
;
4010 /* Set the Stack Data */
4011 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4012 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
4013 StackPtr
->FileObject
= FileObject
;
4014 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
4015 SL_WRITE_THROUGH
: 0;
4016 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
4017 StackPtr
->Parameters
.Write
.Length
= Length
;
4018 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
4020 /* Check if this is buffered I/O */
4021 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
4023 /* Check if we have a buffer length */
4029 /* Allocate a buffer */
4030 Irp
->AssociatedIrp
.SystemBuffer
=
4031 ExAllocatePoolWithTag(NonPagedPool
,
4035 /* Copy the data into it */
4036 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
4038 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4040 /* Allocating failed, clean up and return the exception code */
4041 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
4042 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4047 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4051 /* Not writing anything */
4052 Irp
->Flags
= IRP_BUFFERED_IO
;
4055 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
4057 /* Check if we have a buffer length */
4062 /* Allocate an MDL */
4063 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
4065 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
4066 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
4068 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4070 /* Allocating failed, clean up and return the exception code */
4071 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
4072 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4077 /* No allocation flags */
4082 /* No allocation flags, and use the buffer directly */
4084 Irp
->UserBuffer
= Buffer
;
4087 /* Now set the deferred read flags */
4088 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
4090 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
4092 /* Perform the call */
4093 return IopPerformSynchronousRequest(DeviceObject
,
4104 NtWriteFileGather(IN HANDLE FileHandle
,
4105 IN HANDLE Event OPTIONAL
,
4106 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
4107 IN PVOID UserApcContext OPTIONAL
,
4108 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
4109 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
4110 IN ULONG BufferLength
,
4111 IN PLARGE_INTEGER ByteOffset
,
4112 IN PULONG Key OPTIONAL
)
4115 return STATUS_NOT_IMPLEMENTED
;
4123 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
4124 OUT PIO_STATUS_BLOCK IoStatusBlock
,
4125 OUT PVOID FsInformation
,
4127 IN FS_INFORMATION_CLASS FsInformationClass
)
4129 PFILE_OBJECT FileObject
;
4131 PIO_STACK_LOCATION StackPtr
;
4132 PDEVICE_OBJECT DeviceObject
;
4133 PKEVENT Event
= NULL
;
4134 BOOLEAN LocalEvent
= FALSE
;
4135 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
4137 IO_STATUS_BLOCK KernelIosb
;
4139 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
4141 /* Check if we're called from user mode */
4142 if (PreviousMode
!= KernelMode
)
4144 /* Validate the information class */
4145 if ((FsInformationClass
< 0) ||
4146 (FsInformationClass
>= FileFsMaximumInformation
) ||
4147 !(IopQueryFsOperationLength
[FsInformationClass
]))
4150 return STATUS_INVALID_INFO_CLASS
;
4153 /* Validate the length */
4154 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
4156 /* Invalid length */
4157 return STATUS_INFO_LENGTH_MISMATCH
;
4160 /* Enter SEH for probing */
4163 /* Probe the I/O Status block */
4164 ProbeForWriteIoStatusBlock(IoStatusBlock
);
4166 /* Probe the information */
4167 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
4169 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4171 /* Return the exception code */
4172 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4177 /* Get File Object */
4178 Status
= ObReferenceObjectByHandle(FileHandle
,
4179 IopQueryFsOperationAccess
4180 [FsInformationClass
],
4183 (PVOID
*)&FileObject
,
4185 if (!NT_SUCCESS(Status
)) return Status
;
4187 /* Only allow direct device open for FileFsDeviceInformation */
4188 if (BooleanFlagOn(FileObject
->Flags
, FO_DIRECT_DEVICE_OPEN
) &&
4189 FsInformationClass
!= FileFsDeviceInformation
)
4191 ObDereferenceObject(FileObject
);
4192 return STATUS_INVALID_DEVICE_REQUEST
;
4195 /* Check if we should use Sync IO or not */
4196 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4199 Status
= IopLockFileObject(FileObject
, PreviousMode
);
4200 if (Status
!= STATUS_SUCCESS
)
4202 ObDereferenceObject(FileObject
);
4208 * Quick path for FileFsDeviceInformation - the kernel has enough
4209 * info to reply instead of the driver, excepted for network file systems
4211 if (FsInformationClass
== FileFsDeviceInformation
&&
4212 (BooleanFlagOn(FileObject
->Flags
, FO_DIRECT_DEVICE_OPEN
) || FileObject
->DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK_FILE_SYSTEM
))
4214 PFILE_FS_DEVICE_INFORMATION FsDeviceInfo
= FsInformation
;
4215 DeviceObject
= FileObject
->DeviceObject
;
4219 FsDeviceInfo
->DeviceType
= DeviceObject
->DeviceType
;
4221 /* Complete characteristcs with mount status if relevant */
4222 FsDeviceInfo
->Characteristics
= DeviceObject
->Characteristics
;
4223 if (IopGetMountFlag(DeviceObject
))
4225 SetFlag(FsDeviceInfo
->Characteristics
, FILE_DEVICE_IS_MOUNTED
);
4228 IoStatusBlock
->Information
= sizeof(FILE_FS_DEVICE_INFORMATION
);
4229 IoStatusBlock
->Status
= STATUS_SUCCESS
;
4231 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4233 /* Check if we had a file lock */
4234 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
4237 IopUnlockFileObject(FileObject
);
4240 /* Dereference the FO */
4241 ObDereferenceObject(FileObject
);
4243 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4247 /* Check if we had a file lock */
4248 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
4251 IopUnlockFileObject(FileObject
);
4254 /* Dereference the FO */
4255 ObDereferenceObject(FileObject
);
4257 return STATUS_SUCCESS
;
4259 /* This is to be handled by the kernel, not by FSD */
4260 else if (FsInformationClass
== FileFsDriverPathInformation
)
4262 _SEH2_VOLATILE PFILE_FS_DRIVER_PATH_INFORMATION DriverPathInfo
= NULL
;
4266 /* Allocate our local structure */
4267 DriverPathInfo
= ExAllocatePoolWithQuotaTag(NonPagedPool
, Length
, TAG_IO
);
4269 /* And copy back caller data */
4270 RtlCopyMemory(DriverPathInfo
, FsInformation
, Length
);
4272 /* Is the driver in the IO path? */
4273 Status
= IopGetDriverPathInformation(FileObject
,
4274 (PFILE_FS_DRIVER_PATH_INFORMATION
)DriverPathInfo
,
4276 /* We failed, don't continue execution */
4277 if (!NT_SUCCESS(Status
))
4279 RtlRaiseStatus(Status
);
4282 /* We succeed, copy back info */
4283 ((PFILE_FS_DRIVER_PATH_INFORMATION
)FsInformation
)->DriverInPath
= DriverPathInfo
->DriverInPath
;
4286 IoStatusBlock
->Information
= sizeof(FILE_FS_DRIVER_PATH_INFORMATION
);
4287 IoStatusBlock
->Status
= STATUS_SUCCESS
;
4289 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4291 Status
= _SEH2_GetExceptionCode();
4296 if (DriverPathInfo
!= NULL
)
4298 ExFreePoolWithTag(DriverPathInfo
, TAG_IO
);
4301 /* Check if we had a file lock */
4302 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
4305 IopUnlockFileObject(FileObject
);
4308 /* Dereference the FO */
4309 ObDereferenceObject(FileObject
);
4314 if (!BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
4316 /* Use local event */
4317 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4320 ObDereferenceObject(FileObject
);
4321 return STATUS_INSUFFICIENT_RESOURCES
;
4323 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4327 /* Get the device object */
4328 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4330 /* Clear File Object event */
4331 KeClearEvent(&FileObject
->Event
);
4333 /* Allocate the IRP */
4334 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4335 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4337 /* Set up the IRP */
4338 Irp
->RequestorMode
= PreviousMode
;
4339 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4340 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4341 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4342 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4343 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4344 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4345 Irp
->UserBuffer
= FsInformation
;
4346 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4347 Irp
->MdlAddress
= NULL
;
4349 /* Set up Stack Data */
4350 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4351 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
4352 StackPtr
->FileObject
= FileObject
;
4357 /* Allocate a buffer */
4358 Irp
->AssociatedIrp
.SystemBuffer
=
4359 ExAllocatePoolWithTag(NonPagedPool
,
4363 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4365 /* Allocating failed, clean up and return the exception code */
4366 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4367 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4371 /* Set the flags for this buffered + deferred I/O */
4372 Irp
->Flags
|= (IRP_BUFFERED_IO
|
4373 IRP_DEALLOCATE_BUFFER
|
4374 IRP_INPUT_OPERATION
|
4375 IRP_DEFER_IO_COMPLETION
);
4377 /* Set Parameters */
4378 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
4379 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
4381 /* Call the Driver */
4382 Status
= IopPerformSynchronousRequest(DeviceObject
,
4390 /* Check if this was async I/O */
4393 /* It was, finalize this request */
4394 Status
= IopFinalizeAsynchronousIo(Status
,
4411 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
4412 OUT PIO_STATUS_BLOCK IoStatusBlock
,
4413 IN PVOID FsInformation
,
4415 IN FS_INFORMATION_CLASS FsInformationClass
)
4417 PFILE_OBJECT FileObject
;
4419 PIO_STACK_LOCATION StackPtr
;
4420 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
4421 PKEVENT Event
= NULL
;
4422 BOOLEAN LocalEvent
= FALSE
;
4423 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
4425 IO_STATUS_BLOCK KernelIosb
;
4426 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
4428 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
4430 /* Check if we're called from user mode */
4431 if (PreviousMode
!= KernelMode
)
4433 /* Validate the information class */
4434 if ((FsInformationClass
< 0) ||
4435 (FsInformationClass
>= FileFsMaximumInformation
) ||
4436 !(IopSetFsOperationLength
[FsInformationClass
]))
4439 return STATUS_INVALID_INFO_CLASS
;
4442 /* Validate the length */
4443 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
4445 /* Invalid length */
4446 return STATUS_INFO_LENGTH_MISMATCH
;
4449 /* Enter SEH for probing */
4452 /* Probe the I/O Status block */
4453 ProbeForWriteIoStatusBlock(IoStatusBlock
);
4455 /* Probe the information */
4456 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
4458 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4460 /* Return the exception code */
4461 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4466 /* Get File Object */
4467 Status
= ObReferenceObjectByHandle(FileHandle
,
4468 IopSetFsOperationAccess
4469 [FsInformationClass
],
4472 (PVOID
*)&FileObject
,
4474 if (!NT_SUCCESS(Status
)) return Status
;
4476 /* Get target device for notification */
4477 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4478 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4480 /* Check if we should use Sync IO or not */
4481 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4484 Status
= IopLockFileObject(FileObject
, PreviousMode
);
4485 if (Status
!= STATUS_SUCCESS
)
4487 ObDereferenceObject(FileObject
);
4488 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4494 /* Use local event */
4495 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4498 ObDereferenceObject(FileObject
);
4499 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4500 return STATUS_INSUFFICIENT_RESOURCES
;
4502 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4506 /* Get the device object */
4507 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4509 /* Clear File Object event */
4510 KeClearEvent(&FileObject
->Event
);
4512 /* Allocate the IRP */
4513 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4516 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4517 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4520 /* Set up the IRP */
4521 Irp
->RequestorMode
= PreviousMode
;
4522 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4523 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4524 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4525 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4526 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4527 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4528 Irp
->UserBuffer
= FsInformation
;
4529 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4530 Irp
->MdlAddress
= NULL
;
4532 /* Set up Stack Data */
4533 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4534 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
4535 StackPtr
->FileObject
= FileObject
;
4540 /* Allocate a buffer */
4541 Irp
->AssociatedIrp
.SystemBuffer
=
4542 ExAllocatePoolWithTag(NonPagedPool
,
4546 /* Copy the data into it */
4547 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
4549 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4551 /* Allocating failed, clean up and return the exception code */
4552 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4553 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4554 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4558 /* Set the flags for this buffered + deferred I/O */
4559 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4561 /* Set Parameters */
4562 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
4563 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
4565 /* Call the Driver */
4566 Status
= IopPerformSynchronousRequest(DeviceObject
,
4574 /* Check if this was async I/O */
4577 /* It was, finalize this request */
4578 Status
= IopFinalizeAsynchronousIo(Status
,
4586 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
4588 /* Time to report change */
4589 NotificationStructure
.Version
= 1;
4590 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
4591 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
4592 NotificationStructure
.FileObject
= NULL
;
4593 NotificationStructure
.NameBufferOffset
= - 1;
4594 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
4606 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
4609 return STATUS_NOT_IMPLEMENTED
;
4617 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
4620 return STATUS_NOT_IMPLEMENTED
;