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 at 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 /* Can't use an I/O completion port and an APC at the same time */
1679 if ((FileObject
->CompletionContext
) && (ApcRoutine
))
1682 ObDereferenceObject(FileObject
);
1683 return STATUS_INVALID_PARAMETER
;
1686 /* Check if we have an event handle */
1690 Status
= ObReferenceObjectByHandle(EventHandle
,
1696 if (Status
!= STATUS_SUCCESS
)
1698 ObDereferenceObject(FileObject
);
1701 KeClearEvent(Event
);
1704 /* Check if we should use Sync IO or not */
1705 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1708 Status
= IopLockFileObject(FileObject
, PreviousMode
);
1709 if (Status
!= STATUS_SUCCESS
)
1711 if (Event
) ObDereferenceObject(Event
);
1712 ObDereferenceObject(FileObject
);
1715 LockedForSync
= TRUE
;
1718 /* Clear File Object event */
1719 KeClearEvent(&FileObject
->Event
);
1721 /* Get the device object */
1722 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1724 /* Allocate the IRP */
1725 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1726 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1728 /* Set up the IRP */
1729 Irp
->RequestorMode
= PreviousMode
;
1730 Irp
->UserIosb
= IoStatusBlock
;
1731 Irp
->UserEvent
= Event
;
1732 Irp
->UserBuffer
= Buffer
;
1733 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1734 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1735 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1736 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1738 /* Set up Stack Data */
1739 IoStack
= IoGetNextIrpStackLocation(Irp
);
1740 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1741 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1742 IoStack
->FileObject
= FileObject
;
1744 /* Set parameters */
1745 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1746 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1747 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1749 /* Perform the call */
1750 return IopPerformSynchronousRequest(DeviceObject
,
1764 NtLockFile(IN HANDLE FileHandle
,
1765 IN HANDLE EventHandle OPTIONAL
,
1766 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1767 IN PVOID ApcContext OPTIONAL
,
1768 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1769 IN PLARGE_INTEGER ByteOffset
,
1770 IN PLARGE_INTEGER Length
,
1772 IN BOOLEAN FailImmediately
,
1773 IN BOOLEAN ExclusiveLock
)
1775 PFILE_OBJECT FileObject
;
1776 PLARGE_INTEGER LocalLength
= NULL
;
1778 PIO_STACK_LOCATION StackPtr
;
1779 PDEVICE_OBJECT DeviceObject
;
1780 PKEVENT Event
= NULL
;
1781 BOOLEAN LockedForSync
= FALSE
;
1782 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1783 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1785 OBJECT_HANDLE_INFORMATION HandleInformation
;
1786 PFAST_IO_DISPATCH FastIoDispatch
;
1788 CapturedByteOffset
.QuadPart
= 0;
1789 CapturedLength
.QuadPart
= 0;
1790 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1792 /* Get File Object */
1793 Status
= ObReferenceObjectByHandle(FileHandle
,
1797 (PVOID
*)&FileObject
,
1798 &HandleInformation
);
1799 if (!NT_SUCCESS(Status
)) return Status
;
1801 /* Check if we're called from user mode */
1802 if (PreviousMode
!= KernelMode
)
1804 /* Can't use an I/O completion port and an APC at the same time */
1805 if ((FileObject
->CompletionContext
) && (ApcRoutine
))
1808 ObDereferenceObject(FileObject
);
1809 return STATUS_INVALID_PARAMETER
;
1812 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1813 if (!(HandleInformation
.GrantedAccess
&
1814 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1816 ObDereferenceObject(FileObject
);
1817 return STATUS_ACCESS_DENIED
;
1820 /* Enter SEH for probing */
1823 /* Probe the I/O STatus block */
1824 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1826 /* Probe and capture the large integers */
1827 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1828 CapturedLength
= ProbeForReadLargeInteger(Length
);
1830 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1832 /* Dereference the object and return exception code */
1833 ObDereferenceObject(FileObject
);
1834 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1840 /* Otherwise, capture them directly */
1841 CapturedByteOffset
= *ByteOffset
;
1842 CapturedLength
= *Length
;
1845 /* Check if we have an event handle */
1849 Status
= ObReferenceObjectByHandle(EventHandle
,
1855 if (Status
!= STATUS_SUCCESS
) return Status
;
1856 KeClearEvent(Event
);
1859 /* Get the device object */
1860 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1862 /* Try to do it the FastIO way if possible */
1863 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1864 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoLock
!= NULL
)
1866 IO_STATUS_BLOCK KernelIosb
;
1868 if (FastIoDispatch
->FastIoLock(FileObject
,
1869 &CapturedByteOffset
,
1871 PsGetCurrentProcess(),
1878 /* Write the IOSB back */
1881 *IoStatusBlock
= KernelIosb
;
1883 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1885 KernelIosb
.Status
= _SEH2_GetExceptionCode();
1889 /* If we had an event, signal it */
1892 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1893 ObDereferenceObject(Event
);
1896 /* Set completion if required */
1897 if (FileObject
->CompletionContext
!= NULL
&& ApcContext
!= NULL
)
1899 if (!NT_SUCCESS(IoSetIoCompletion(FileObject
->CompletionContext
->Port
,
1900 FileObject
->CompletionContext
->Key
,
1903 KernelIosb
.Information
,
1906 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1910 FileObject
->LockOperation
= TRUE
;
1912 /* We're done with FastIO! */
1913 ObDereferenceObject(FileObject
);
1914 return KernelIosb
.Status
;
1918 /* Check if we should use Sync IO or not */
1919 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1922 Status
= IopLockFileObject(FileObject
, PreviousMode
);
1923 if (Status
!= STATUS_SUCCESS
)
1925 if (Event
) ObDereferenceObject(Event
);
1926 ObDereferenceObject(FileObject
);
1929 LockedForSync
= TRUE
;
1932 /* Clear File Object event */
1933 KeClearEvent(&FileObject
->Event
);
1934 FileObject
->LockOperation
= TRUE
;
1936 /* Allocate the IRP */
1937 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1938 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1940 /* Set up the IRP */
1941 Irp
->RequestorMode
= PreviousMode
;
1942 Irp
->UserIosb
= IoStatusBlock
;
1943 Irp
->UserEvent
= Event
;
1944 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1945 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1946 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1947 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1949 /* Set up Stack Data */
1950 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1951 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1952 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1953 StackPtr
->FileObject
= FileObject
;
1955 /* Allocate local buffer */
1956 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1957 sizeof(LARGE_INTEGER
),
1961 /* Allocating failed, clean up and return failure */
1962 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1963 return STATUS_INSUFFICIENT_RESOURCES
;
1966 /* Set the length */
1967 *LocalLength
= CapturedLength
;
1968 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1969 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1971 /* Set Parameters */
1972 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1973 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1976 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1977 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1979 /* Perform the call */
1980 return IopPerformSynchronousRequest(DeviceObject
,
1994 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1995 IN HANDLE EventHandle OPTIONAL
,
1996 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1997 IN PVOID ApcContext OPTIONAL
,
1998 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1999 OUT PVOID FileInformation
,
2001 IN FILE_INFORMATION_CLASS FileInformationClass
,
2002 IN BOOLEAN ReturnSingleEntry
,
2003 IN PUNICODE_STRING FileName OPTIONAL
,
2004 IN BOOLEAN RestartScan
)
2007 PDEVICE_OBJECT DeviceObject
;
2008 PFILE_OBJECT FileObject
;
2009 PIO_STACK_LOCATION StackPtr
;
2010 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2012 BOOLEAN LockedForSynch
= FALSE
;
2013 PKEVENT Event
= NULL
;
2014 volatile PVOID AuxBuffer
= NULL
;
2016 UNICODE_STRING CapturedFileName
;
2017 PUNICODE_STRING SearchPattern
;
2019 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2021 /* Check if we came from user mode */
2022 if (PreviousMode
!= KernelMode
)
2024 /* Enter SEH for probing */
2027 /* Probe the I/O Status Block */
2028 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2030 /* Probe the file information */
2031 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2033 /* Check if we have a file name */
2037 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
2038 if (CapturedFileName
.Length
)
2040 /* Probe its buffer */
2041 ProbeForRead(CapturedFileName
.Buffer
,
2042 CapturedFileName
.Length
,
2046 /* Allocate the auxiliary buffer */
2047 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2048 CapturedFileName
.Length
+
2049 sizeof(UNICODE_STRING
),
2051 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
2052 sizeof(UNICODE_STRING
)),
2053 CapturedFileName
.Buffer
,
2054 CapturedFileName
.Length
);
2056 /* Setup the search pattern */
2057 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
2058 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
2059 sizeof(UNICODE_STRING
));
2060 SearchPattern
->Length
= CapturedFileName
.Length
;
2061 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
2064 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2066 /* Free buffer and return the exception code */
2067 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2068 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2073 /* Check input parameters */
2075 switch (FileInformationClass
)
2077 #define CHECK_LENGTH(class, struct) \
2079 if (Length < sizeof(struct)) \
2080 return STATUS_INFO_LENGTH_MISMATCH; \
2082 CHECK_LENGTH(FileDirectoryInformation
, FILE_DIRECTORY_INFORMATION
);
2083 CHECK_LENGTH(FileFullDirectoryInformation
, FILE_FULL_DIR_INFORMATION
);
2084 CHECK_LENGTH(FileIdFullDirectoryInformation
, FILE_ID_FULL_DIR_INFORMATION
);
2085 CHECK_LENGTH(FileNamesInformation
, FILE_NAMES_INFORMATION
);
2086 CHECK_LENGTH(FileBothDirectoryInformation
, FILE_BOTH_DIR_INFORMATION
);
2087 CHECK_LENGTH(FileIdBothDirectoryInformation
, FILE_ID_BOTH_DIR_INFORMATION
);
2093 /* Get File Object */
2094 Status
= ObReferenceObjectByHandle(FileHandle
,
2095 FILE_LIST_DIRECTORY
,
2098 (PVOID
*)&FileObject
,
2100 if (!NT_SUCCESS(Status
))
2103 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2107 /* Are there two associated completion routines? */
2108 if (FileObject
->CompletionContext
!= NULL
&& ApcRoutine
!= NULL
)
2110 ObDereferenceObject(FileObject
);
2111 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2112 return STATUS_INVALID_PARAMETER
;
2115 /* Check if we have an even handle */
2118 /* Get its pointer */
2119 Status
= ObReferenceObjectByHandle(EventHandle
,
2125 if (!NT_SUCCESS(Status
))
2128 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2129 ObDereferenceObject(FileObject
);
2134 KeClearEvent(Event
);
2137 /* Check if this is a file that was opened for Synch I/O */
2138 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2141 Status
= IopLockFileObject(FileObject
, PreviousMode
);
2142 if (Status
!= STATUS_SUCCESS
)
2144 if (Event
) ObDereferenceObject(Event
);
2145 ObDereferenceObject(FileObject
);
2146 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2150 /* Remember to unlock later */
2151 LockedForSynch
= TRUE
;
2154 /* Get the device object */
2155 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2157 /* Clear the File Object's event */
2158 KeClearEvent(&FileObject
->Event
);
2160 /* Allocate the IRP */
2161 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2162 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
2164 /* Set up the IRP */
2165 Irp
->RequestorMode
= PreviousMode
;
2166 Irp
->UserIosb
= IoStatusBlock
;
2167 Irp
->UserEvent
= Event
;
2168 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2169 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2170 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2171 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2172 Irp
->MdlAddress
= NULL
;
2173 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
2174 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2176 /* Check if this is buffered I/O */
2177 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2179 /* Allocate a buffer */
2180 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2183 if (!Irp
->AssociatedIrp
.SystemBuffer
)
2185 /* Allocating failed, clean up and return the exception code */
2186 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2187 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2189 /* Return the exception code */
2190 return STATUS_INSUFFICIENT_RESOURCES
;
2193 /* Set the buffer and flags */
2194 Irp
->UserBuffer
= FileInformation
;
2195 Irp
->Flags
= (IRP_BUFFERED_IO
|
2196 IRP_DEALLOCATE_BUFFER
|
2197 IRP_INPUT_OPERATION
);
2199 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2203 /* Allocate an MDL */
2204 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
2205 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2206 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2208 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2210 /* Allocating failed, clean up and return the exception code */
2211 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2212 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2218 /* No allocation flags, and use the buffer directly */
2219 Irp
->UserBuffer
= FileInformation
;
2222 /* Set up Stack Data */
2223 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2224 StackPtr
->FileObject
= FileObject
;
2225 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2226 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2228 /* Set Parameters */
2229 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
2230 FileInformationClass
;
2231 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
2232 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2233 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2234 StackPtr
->Flags
= 0;
2235 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2236 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2238 /* Set deferred I/O */
2239 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
2241 /* Perform the call */
2242 return IopPerformSynchronousRequest(DeviceObject
,
2256 NtQueryEaFile(IN HANDLE FileHandle
,
2257 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2260 IN BOOLEAN ReturnSingleEntry
,
2261 IN PVOID EaList OPTIONAL
,
2262 IN ULONG EaListLength
,
2263 IN PULONG EaIndex OPTIONAL
,
2264 IN BOOLEAN RestartScan
)
2267 return STATUS_NOT_IMPLEMENTED
;
2275 NtQueryInformationFile(IN HANDLE FileHandle
,
2276 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2277 IN PVOID FileInformation
,
2279 IN FILE_INFORMATION_CLASS FileInformationClass
)
2281 OBJECT_HANDLE_INFORMATION HandleInformation
;
2282 PFILE_OBJECT FileObject
;
2285 PDEVICE_OBJECT DeviceObject
;
2286 PIO_STACK_LOCATION StackPtr
;
2287 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2288 PKEVENT Event
= NULL
;
2289 BOOLEAN LocalEvent
= FALSE
;
2290 PKNORMAL_ROUTINE NormalRoutine
;
2291 PVOID NormalContext
;
2293 IO_STATUS_BLOCK KernelIosb
;
2294 BOOLEAN CallDriver
= TRUE
;
2295 PFILE_ACCESS_INFORMATION AccessBuffer
;
2296 PFILE_MODE_INFORMATION ModeBuffer
;
2297 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer
;
2298 PFILE_ALL_INFORMATION AllBuffer
;
2299 PFAST_IO_DISPATCH FastIoDispatch
;
2301 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2303 /* Check if we're called from user mode */
2304 if (PreviousMode
!= KernelMode
)
2306 /* Validate the information class */
2307 if ((FileInformationClass
< 0) ||
2308 (FileInformationClass
>= FileMaximumInformation
) ||
2309 !(IopQueryOperationLength
[FileInformationClass
]))
2312 return STATUS_INVALID_INFO_CLASS
;
2315 /* Validate the length */
2316 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2318 /* Invalid length */
2319 return STATUS_INFO_LENGTH_MISMATCH
;
2322 /* Enter SEH for probing */
2325 /* Probe the I/O Status block */
2326 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2328 /* Probe the information */
2329 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2331 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2333 /* Return the exception code */
2334 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2341 /* Validate the information class */
2342 if ((FileInformationClass
< 0) ||
2343 (FileInformationClass
>= FileMaximumInformation
) ||
2344 !(IopQueryOperationLength
[FileInformationClass
]))
2347 return STATUS_INVALID_INFO_CLASS
;
2350 /* Validate the length */
2351 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2353 /* Invalid length */
2354 return STATUS_INFO_LENGTH_MISMATCH
;
2359 /* Reference the Handle */
2360 Status
= ObReferenceObjectByHandle(FileHandle
,
2361 IopQueryOperationAccess
2362 [FileInformationClass
],
2365 (PVOID
*)&FileObject
,
2366 &HandleInformation
);
2367 if (!NT_SUCCESS(Status
)) return Status
;
2369 /* Check if this is a direct open or not */
2370 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2372 /* Get the device object */
2373 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2377 /* Get the device object */
2378 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2381 /* Check if this is a file that was opened for Synch I/O */
2382 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2385 Status
= IopLockFileObject(FileObject
, PreviousMode
);
2386 if (Status
!= STATUS_SUCCESS
)
2388 ObDereferenceObject(FileObject
);
2392 /* Check if the caller just wants the position */
2393 if (FileInformationClass
== FilePositionInformation
)
2395 /* Protect write in SEH */
2398 /* Write the offset */
2399 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2400 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2402 /* Fill out the I/O Status Block */
2403 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2404 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2406 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2408 /* Get the exception code */
2409 Status
= _SEH2_GetExceptionCode();
2413 /* Release the file lock, dereference the file and return */
2414 IopUnlockFileObject(FileObject
);
2415 ObDereferenceObject(FileObject
);
2421 /* Use local event */
2422 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2425 ObDereferenceObject(FileObject
);
2426 return STATUS_INSUFFICIENT_RESOURCES
;
2428 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2432 /* Check if FastIO is possible for the two available information classes */
2433 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2434 if (FastIoDispatch
!= NULL
&&
2435 ((FileInformationClass
== FileBasicInformation
&& FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
) ||
2436 (FileInformationClass
== FileStandardInformation
&& FastIoDispatch
->FastIoQueryStandardInfo
!= NULL
)))
2438 BOOLEAN Success
= FALSE
;
2440 if (FileInformationClass
== FileBasicInformation
)
2442 Success
= FastIoDispatch
->FastIoQueryBasicInfo(FileObject
, TRUE
,
2449 Success
= FastIoDispatch
->FastIoQueryStandardInfo(FileObject
, TRUE
,
2455 /* If call succeed */
2458 /* Write the IOSB back */
2461 *IoStatusBlock
= KernelIosb
;
2463 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2465 KernelIosb
.Status
= _SEH2_GetExceptionCode();
2469 /* Free the event if we had one */
2472 ExFreePoolWithTag(Event
, TAG_IO
);
2475 /* If FO was locked, unlock it */
2476 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2478 IopUnlockFileObject(FileObject
);
2481 /* We're done with FastIO! */
2482 ObDereferenceObject(FileObject
);
2483 return KernelIosb
.Status
;
2487 /* Clear the File Object event */
2488 KeClearEvent(&FileObject
->Event
);
2490 /* Allocate the IRP */
2491 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2492 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2495 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2496 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2497 Irp
->RequestorMode
= PreviousMode
;
2498 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2499 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2500 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2501 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2502 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2503 Irp
->MdlAddress
= NULL
;
2504 Irp
->UserBuffer
= FileInformation
;
2506 /* Set the Stack Data */
2507 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2508 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2509 StackPtr
->FileObject
= FileObject
;
2514 /* Allocate a buffer */
2515 Irp
->AssociatedIrp
.SystemBuffer
=
2516 ExAllocatePoolWithTag(NonPagedPool
,
2520 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2522 /* Allocating failed, clean up and return the exception code */
2523 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2524 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2529 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2530 IRP_DEALLOCATE_BUFFER
|
2531 IRP_INPUT_OPERATION
|
2532 IRP_DEFER_IO_COMPLETION
);
2534 /* Set the Parameters */
2535 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2536 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2539 IopQueueIrpToThread(Irp
);
2541 /* Update operation counts */
2542 IopUpdateOperationCount(IopOtherTransfer
);
2544 /* Fill in file information before calling the driver.
2545 See 'File System Internals' page 485.*/
2546 if (FileInformationClass
== FileAccessInformation
)
2548 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2549 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2550 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2553 else if (FileInformationClass
== FileModeInformation
)
2555 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2556 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2557 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2560 else if (FileInformationClass
== FileAlignmentInformation
)
2562 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2563 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2564 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2567 else if (FileInformationClass
== FileAllInformation
)
2569 AllBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2570 AllBuffer
->AccessInformation
.AccessFlags
= HandleInformation
.GrantedAccess
;
2571 AllBuffer
->ModeInformation
.Mode
= IopGetFileMode(FileObject
);
2572 AllBuffer
->AlignmentInformation
.AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2573 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
) +
2574 sizeof(FILE_MODE_INFORMATION
) +
2575 sizeof(FILE_ALIGNMENT_INFORMATION
);
2578 /* Call the Driver */
2581 Status
= IoCallDriver(DeviceObject
, Irp
);
2585 Status
= STATUS_SUCCESS
;
2586 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2589 if (Status
== STATUS_PENDING
)
2591 /* Check if this was async I/O */
2594 /* Then to a non-alertable wait */
2595 Status
= KeWaitForSingleObject(Event
,
2600 if (Status
== STATUS_USER_APC
)
2602 /* Abort the request */
2603 IopAbortInterruptedIrp(Event
, Irp
);
2606 /* Set the final status */
2607 Status
= KernelIosb
.Status
;
2609 /* Enter SEH to write the IOSB back */
2612 /* Write it back to the caller */
2613 *IoStatusBlock
= KernelIosb
;
2615 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2617 /* Get the exception code */
2618 Status
= _SEH2_GetExceptionCode();
2622 /* Free the event */
2623 ExFreePoolWithTag(Event
, TAG_IO
);
2627 /* Wait for the IRP */
2628 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2631 (FileObject
->Flags
&
2632 FO_ALERTABLE_IO
) != 0,
2634 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2636 /* Abort the request */
2637 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2640 /* Set the final status */
2641 Status
= FileObject
->FinalStatus
;
2643 /* Release the file lock */
2644 IopUnlockFileObject(FileObject
);
2649 /* Free the event if we had one */
2652 /* Clear it in the IRP for completion */
2653 Irp
->UserEvent
= NULL
;
2654 ExFreePoolWithTag(Event
, TAG_IO
);
2657 /* Set the caller IOSB */
2658 Irp
->UserIosb
= IoStatusBlock
;
2660 /* The IRP wasn't completed, complete it ourselves */
2661 NormalRoutine
= NULL
;
2662 NormalContext
= NULL
;
2663 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2664 IopCompleteRequest(&Irp
->Tail
.Apc
,
2667 (PVOID
*)&FileObject
,
2669 KeLowerIrql(OldIrql
);
2671 /* Release the file object if we had locked it*/
2672 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2675 /* Return the Status */
2684 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2685 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2688 IN BOOLEAN ReturnSingleEntry
,
2689 IN PVOID SidList OPTIONAL
,
2690 IN ULONG SidListLength
,
2691 IN PSID StartSid OPTIONAL
,
2692 IN BOOLEAN RestartScan
)
2695 return STATUS_NOT_IMPLEMENTED
;
2703 NtReadFile(IN HANDLE FileHandle
,
2704 IN HANDLE Event OPTIONAL
,
2705 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2706 IN PVOID ApcContext OPTIONAL
,
2707 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2710 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2711 IN PULONG Key OPTIONAL
)
2714 PFILE_OBJECT FileObject
;
2716 PDEVICE_OBJECT DeviceObject
;
2717 PIO_STACK_LOCATION StackPtr
;
2718 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2719 PKEVENT EventObject
= NULL
;
2720 LARGE_INTEGER CapturedByteOffset
;
2721 ULONG CapturedKey
= 0;
2722 BOOLEAN Synchronous
= FALSE
;
2724 PFAST_IO_DISPATCH FastIoDispatch
;
2725 IO_STATUS_BLOCK KernelIosb
;
2729 CapturedByteOffset
.QuadPart
= 0;
2730 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2732 /* Get File Object */
2733 Status
= ObReferenceObjectByHandle(FileHandle
,
2737 (PVOID
*)&FileObject
,
2739 if (!NT_SUCCESS(Status
)) return Status
;
2741 /* Get the device object */
2742 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2744 /* Validate User-Mode Buffers */
2745 if (PreviousMode
!= KernelMode
)
2749 /* Probe the status block */
2750 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2752 /* Probe the read buffer */
2753 ProbeForWrite(Buffer
, Length
, 1);
2755 /* Check if we got a byte offset */
2758 /* Capture and probe it */
2759 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2762 /* Can't use an I/O completion port and an APC at the same time */
2763 if ((FileObject
->CompletionContext
) && (ApcRoutine
))
2766 ObDereferenceObject(FileObject
);
2767 return STATUS_INVALID_PARAMETER
;
2770 /* Perform additional checks for non-cached file access */
2771 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
2773 /* Fail if Length is not sector size aligned
2774 * Perform a quick check for 2^ sector sizes
2775 * If it fails, try a more standard way
2777 if ((DeviceObject
->SectorSize
!= 0) &&
2778 ((DeviceObject
->SectorSize
- 1) & Length
) != 0)
2780 if (Length
% DeviceObject
->SectorSize
!= 0)
2782 /* Release the file object and and fail */
2783 ObDereferenceObject(FileObject
);
2784 return STATUS_INVALID_PARAMETER
;
2788 /* Fail if buffer doesn't match alignment requirements */
2789 if (((ULONG_PTR
)Buffer
& DeviceObject
->AlignmentRequirement
) != 0)
2791 /* Release the file object and and fail */
2792 ObDereferenceObject(FileObject
);
2793 return STATUS_INVALID_PARAMETER
;
2798 /* Fail if ByteOffset is not sector size aligned */
2799 if ((DeviceObject
->SectorSize
!= 0) &&
2800 (CapturedByteOffset
.QuadPart
% DeviceObject
->SectorSize
!= 0))
2802 /* Release the file object and and fail */
2803 ObDereferenceObject(FileObject
);
2804 return STATUS_INVALID_PARAMETER
;
2809 /* Capture and probe the key */
2810 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2812 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2814 /* Release the file object and return the exception code */
2815 ObDereferenceObject(FileObject
);
2816 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2822 /* Kernel mode: capture directly */
2823 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2824 if (Key
) CapturedKey
= *Key
;
2827 /* Check for invalid offset */
2828 if ((CapturedByteOffset
.QuadPart
< 0) && (CapturedByteOffset
.QuadPart
!= -2))
2830 /* -2 is FILE_USE_FILE_POINTER_POSITION */
2831 ObDereferenceObject(FileObject
);
2832 return STATUS_INVALID_PARAMETER
;
2835 /* Check for event */
2839 Status
= ObReferenceObjectByHandle(Event
,
2843 (PVOID
*)&EventObject
,
2845 if (!NT_SUCCESS(Status
))
2848 ObDereferenceObject(FileObject
);
2852 /* Otherwise reset the event */
2853 KeClearEvent(EventObject
);
2856 /* Check if we should use Sync IO or not */
2857 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2859 /* Lock the file object */
2860 Status
= IopLockFileObject(FileObject
, PreviousMode
);
2861 if (Status
!= STATUS_SUCCESS
)
2863 if (EventObject
) ObDereferenceObject(EventObject
);
2864 ObDereferenceObject(FileObject
);
2868 /* Check if we don't have a byte offset available */
2869 if (!(ByteOffset
) ||
2870 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2871 (CapturedByteOffset
.u
.HighPart
== -1)))
2873 /* Use the Current Byte Offset instead */
2874 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2877 /* If the file is cached, try fast I/O */
2878 if (FileObject
->PrivateCacheMap
)
2880 /* Perform fast read */
2881 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2882 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoRead
!= NULL
);
2884 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2885 &CapturedByteOffset
,
2893 /* Only accept the result if we got a straightforward status */
2895 (KernelIosb
.Status
== STATUS_SUCCESS
||
2896 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2897 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2899 /* Fast path -- update transfer & operation counts */
2900 IopUpdateOperationCount(IopReadTransfer
);
2901 IopUpdateTransferCount(IopReadTransfer
,
2902 (ULONG
)KernelIosb
.Information
);
2904 /* Enter SEH to write the IOSB back */
2907 /* Write it back to the caller */
2908 *IoStatusBlock
= KernelIosb
;
2910 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2912 /* The caller's IOSB was invalid, so fail */
2913 if (EventObject
) ObDereferenceObject(EventObject
);
2914 IopUnlockFileObject(FileObject
);
2915 ObDereferenceObject(FileObject
);
2916 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2920 /* Signal the completion event */
2923 KeSetEvent(EventObject
, 0, FALSE
);
2924 ObDereferenceObject(EventObject
);
2928 IopUnlockFileObject(FileObject
);
2929 ObDereferenceObject(FileObject
);
2930 return KernelIosb
.Status
;
2934 /* Remember we are sync */
2937 else if (!(ByteOffset
) &&
2938 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2940 /* Otherwise, this was async I/O without a byte offset, so fail */
2941 if (EventObject
) ObDereferenceObject(EventObject
);
2942 ObDereferenceObject(FileObject
);
2943 return STATUS_INVALID_PARAMETER
;
2946 /* Clear the File Object's event */
2947 KeClearEvent(&FileObject
->Event
);
2949 /* Allocate the IRP */
2950 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2951 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2954 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2955 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2956 Irp
->RequestorMode
= PreviousMode
;
2957 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2958 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2959 Irp
->UserIosb
= IoStatusBlock
;
2960 Irp
->UserEvent
= EventObject
;
2961 Irp
->PendingReturned
= FALSE
;
2962 Irp
->Cancel
= FALSE
;
2963 Irp
->CancelRoutine
= NULL
;
2964 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2965 Irp
->MdlAddress
= NULL
;
2967 /* Set the Stack Data */
2968 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2969 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2970 StackPtr
->FileObject
= FileObject
;
2971 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2972 StackPtr
->Parameters
.Read
.Length
= Length
;
2973 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2975 /* Check if this is buffered I/O */
2976 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2978 /* Check if we have a buffer length */
2984 /* Allocate a buffer */
2985 Irp
->AssociatedIrp
.SystemBuffer
=
2986 ExAllocatePoolWithTag(NonPagedPool
,
2990 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2992 /* Allocating failed, clean up and return the exception code */
2993 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2994 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2998 /* Set the buffer and flags */
2999 Irp
->UserBuffer
= Buffer
;
3000 Irp
->Flags
= (IRP_BUFFERED_IO
|
3001 IRP_DEALLOCATE_BUFFER
|
3002 IRP_INPUT_OPERATION
);
3006 /* Not reading anything */
3007 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
3010 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3012 /* Check if we have a buffer length */
3017 /* Allocate an MDL */
3018 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3020 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3021 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
3023 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3025 /* Allocating failed, clean up and return the exception code */
3026 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3027 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3033 /* No allocation flags */
3038 /* No allocation flags, and use the buffer directly */
3040 Irp
->UserBuffer
= Buffer
;
3043 /* Now set the deferred read flags */
3044 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3046 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3048 /* Perform the call */
3049 return IopPerformSynchronousRequest(DeviceObject
,
3063 NtReadFileScatter(IN HANDLE FileHandle
,
3064 IN HANDLE Event OPTIONAL
,
3065 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3066 IN PVOID UserApcContext OPTIONAL
,
3067 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3068 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3069 IN ULONG BufferLength
,
3070 IN PLARGE_INTEGER ByteOffset
,
3071 IN PULONG Key OPTIONAL
)
3074 return STATUS_NOT_IMPLEMENTED
;
3082 NtSetEaFile(IN HANDLE FileHandle
,
3083 IN PIO_STATUS_BLOCK IoStatusBlock
,
3085 IN ULONG EaBufferSize
)
3088 return STATUS_NOT_IMPLEMENTED
;
3096 NtSetInformationFile(IN HANDLE FileHandle
,
3097 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3098 IN PVOID FileInformation
,
3100 IN FILE_INFORMATION_CLASS FileInformationClass
)
3102 PFILE_OBJECT FileObject
;
3105 PDEVICE_OBJECT DeviceObject
;
3106 PIO_STACK_LOCATION StackPtr
;
3107 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
3108 PKEVENT Event
= NULL
;
3109 BOOLEAN LocalEvent
= FALSE
;
3110 PKNORMAL_ROUTINE NormalRoutine
;
3111 PVOID NormalContext
;
3113 IO_STATUS_BLOCK KernelIosb
;
3115 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
3116 PIO_COMPLETION_CONTEXT Context
;
3117 PFILE_RENAME_INFORMATION RenameInfo
;
3118 HANDLE TargetHandle
= NULL
;
3120 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3122 /* Check if we're called from user mode */
3123 if (PreviousMode
!= KernelMode
)
3125 /* Validate the information class */
3126 if ((FileInformationClass
< 0) ||
3127 (FileInformationClass
>= FileMaximumInformation
) ||
3128 !(IopSetOperationLength
[FileInformationClass
]))
3131 return STATUS_INVALID_INFO_CLASS
;
3134 /* Validate the length */
3135 if (Length
< IopSetOperationLength
[FileInformationClass
])
3137 /* Invalid length */
3138 return STATUS_INFO_LENGTH_MISMATCH
;
3141 /* Enter SEH for probing */
3144 /* Probe the I/O Status block */
3145 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3147 /* Probe the information */
3148 ProbeForRead(FileInformation
,
3150 (Length
== sizeof(BOOLEAN
)) ?
3151 sizeof(BOOLEAN
) : sizeof(ULONG
));
3153 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3155 /* Return the exception code */
3156 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3162 /* Validate the information class */
3163 if ((FileInformationClass
< 0) ||
3164 (FileInformationClass
>= FileMaximumInformation
) ||
3165 !(IopSetOperationLength
[FileInformationClass
]))
3168 return STATUS_INVALID_INFO_CLASS
;
3171 /* Validate the length */
3172 if (Length
< IopSetOperationLength
[FileInformationClass
])
3174 /* Invalid length */
3175 return STATUS_INFO_LENGTH_MISMATCH
;
3179 /* Reference the Handle */
3180 Status
= ObReferenceObjectByHandle(FileHandle
,
3181 IopSetOperationAccess
3182 [FileInformationClass
],
3185 (PVOID
*)&FileObject
,
3187 if (!NT_SUCCESS(Status
)) return Status
;
3189 /* Check if this is a direct open or not */
3190 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3192 /* Get the device object */
3193 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3197 /* Get the device object */
3198 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3201 DPRINT("Will call: %p\n", DeviceObject
);
3202 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
3204 /* Check if this is a file that was opened for Synch I/O */
3205 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3208 Status
= IopLockFileObject(FileObject
, PreviousMode
);
3209 if (Status
!= STATUS_SUCCESS
)
3211 ObDereferenceObject(FileObject
);
3215 /* Check if the caller just wants the position */
3216 if (FileInformationClass
== FilePositionInformation
)
3218 /* Protect write in SEH */
3221 /* Write the offset */
3222 FileObject
->CurrentByteOffset
=
3223 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
3226 /* Fill out the I/O Status Block */
3227 IoStatusBlock
->Information
= 0;
3228 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
3230 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3232 /* Get the exception code */
3233 Status
= _SEH2_GetExceptionCode();
3237 /* Update transfer count */
3238 IopUpdateTransferCount(IopOtherTransfer
, Length
);
3240 /* Release the file lock, dereference the file and return */
3241 IopUnlockFileObject(FileObject
);
3242 ObDereferenceObject(FileObject
);
3248 /* Use local event */
3249 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3252 ObDereferenceObject(FileObject
);
3253 return STATUS_INSUFFICIENT_RESOURCES
;
3256 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3260 /* Clear the File Object event */
3261 KeClearEvent(&FileObject
->Event
);
3263 /* Allocate the IRP */
3264 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
3265 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3268 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3269 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3270 Irp
->RequestorMode
= PreviousMode
;
3271 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3272 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3273 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3274 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3275 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3276 Irp
->MdlAddress
= NULL
;
3277 Irp
->UserBuffer
= FileInformation
;
3279 /* Set the Stack Data */
3280 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3281 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
3282 StackPtr
->FileObject
= FileObject
;
3287 /* Allocate a buffer */
3288 Irp
->AssociatedIrp
.SystemBuffer
=
3289 ExAllocatePoolWithTag(NonPagedPool
,
3293 /* Copy the data into it */
3294 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3300 /* Allocating failed, clean up and return the exception code */
3301 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3302 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3307 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3308 IRP_DEALLOCATE_BUFFER
|
3309 IRP_DEFER_IO_COMPLETION
);
3311 /* Set the Parameters */
3312 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
3313 StackPtr
->Parameters
.SetFile
.Length
= Length
;
3316 IopQueueIrpToThread(Irp
);
3318 /* Update operation counts */
3319 IopUpdateOperationCount(IopOtherTransfer
);
3321 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3322 /* Handle IO Completion Port quickly */
3323 if (FileInformationClass
== FileCompletionInformation
)
3325 /* Check if the file object already has a completion port */
3326 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3327 (FileObject
->CompletionContext
))
3330 Status
= STATUS_INVALID_PARAMETER
;
3334 /* Reference the Port */
3335 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3336 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3337 IO_COMPLETION_MODIFY_STATE
,
3342 if (NT_SUCCESS(Status
))
3344 /* Allocate the Context */
3345 Context
= ExAllocatePoolWithTag(PagedPool
,
3346 sizeof(IO_COMPLETION_CONTEXT
),
3351 Context
->Key
= CompletionInfo
->Key
;
3352 Context
->Port
= Queue
;
3353 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3359 * Someone else set the completion port in the
3360 * meanwhile, so dereference the port and fail.
3362 ExFreePoolWithTag(Context
, IOC_TAG
);
3363 ObDereferenceObject(Queue
);
3364 Status
= STATUS_INVALID_PARAMETER
;
3369 /* Dereference the Port now */
3370 ObDereferenceObject(Queue
);
3371 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3376 /* Set the IRP Status */
3377 Irp
->IoStatus
.Status
= Status
;
3378 Irp
->IoStatus
.Information
= 0;
3380 else if (FileInformationClass
== FileRenameInformation
||
3381 FileInformationClass
== FileLinkInformation
||
3382 FileInformationClass
== FileMoveClusterInformation
)
3384 /* Get associated information */
3385 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3390 * -> sizes are valid
3392 if (RenameInfo
->FileNameLength
!= 0 &&
3393 !(RenameInfo
->FileNameLength
& 1) &&
3394 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3396 /* Properly set information received */
3397 if (FileInformationClass
== FileMoveClusterInformation
)
3399 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3403 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3406 /* If we got fully path OR relative target, attempt a parent directory open */
3407 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3409 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3410 if (!NT_SUCCESS(Status
))
3412 Irp
->IoStatus
.Status
= Status
;
3416 /* Call the Driver */
3417 Status
= IoCallDriver(DeviceObject
, Irp
);
3422 /* Call the Driver */
3423 Status
= IoCallDriver(DeviceObject
, Irp
);
3428 Status
= STATUS_INVALID_PARAMETER
;
3429 Irp
->IoStatus
.Status
= Status
;
3434 /* Call the Driver */
3435 Status
= IoCallDriver(DeviceObject
, Irp
);
3438 /* Check if we're waiting for the IRP to complete */
3439 if (Status
== STATUS_PENDING
)
3441 /* Check if this was async I/O */
3444 /* Then to a non-alertable wait */
3445 Status
= KeWaitForSingleObject(Event
,
3450 if (Status
== STATUS_USER_APC
)
3452 /* Abort the request */
3453 IopAbortInterruptedIrp(Event
, Irp
);
3456 /* Set the final status */
3457 Status
= KernelIosb
.Status
;
3459 /* Enter SEH to write the IOSB back */
3462 /* Write it back to the caller */
3463 *IoStatusBlock
= KernelIosb
;
3465 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3467 /* Get the exception code */
3468 Status
= _SEH2_GetExceptionCode();
3472 /* Free the event */
3473 ExFreePoolWithTag(Event
, TAG_IO
);
3477 /* Wait for the IRP */
3478 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3481 (FileObject
->Flags
&
3482 FO_ALERTABLE_IO
) != 0,
3484 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3486 /* Abort the request */
3487 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3490 /* Set the final status */
3491 Status
= FileObject
->FinalStatus
;
3493 /* Release the file lock */
3494 IopUnlockFileObject(FileObject
);
3499 /* Free the event if we had one */
3502 /* Clear it in the IRP for completion */
3503 Irp
->UserEvent
= NULL
;
3504 ExFreePoolWithTag(Event
, TAG_IO
);
3507 /* Set the caller IOSB */
3508 Irp
->UserIosb
= IoStatusBlock
;
3510 /* The IRP wasn't completed, complete it ourselves */
3511 NormalRoutine
= NULL
;
3512 NormalContext
= NULL
;
3513 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3514 IopCompleteRequest(&Irp
->Tail
.Apc
,
3517 (PVOID
*)&FileObject
,
3519 KeLowerIrql(OldIrql
);
3521 /* Release the file object if we had locked it*/
3522 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3525 if (TargetHandle
!= NULL
)
3527 ObCloseHandle(TargetHandle
, KernelMode
);
3530 /* Return the Status */
3539 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3540 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3542 IN ULONG BufferLength
)
3545 return STATUS_NOT_IMPLEMENTED
;
3553 NtUnlockFile(IN HANDLE FileHandle
,
3554 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3555 IN PLARGE_INTEGER ByteOffset
,
3556 IN PLARGE_INTEGER Length
,
3557 IN ULONG Key OPTIONAL
)
3559 PFILE_OBJECT FileObject
;
3560 PLARGE_INTEGER LocalLength
= NULL
;
3562 PIO_STACK_LOCATION StackPtr
;
3563 PDEVICE_OBJECT DeviceObject
;
3564 PKEVENT Event
= NULL
;
3565 BOOLEAN LocalEvent
= FALSE
;
3566 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3567 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3569 OBJECT_HANDLE_INFORMATION HandleInformation
;
3570 IO_STATUS_BLOCK KernelIosb
;
3571 PFAST_IO_DISPATCH FastIoDispatch
;
3573 CapturedByteOffset
.QuadPart
= 0;
3574 CapturedLength
.QuadPart
= 0;
3575 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3577 /* Get File Object */
3578 Status
= ObReferenceObjectByHandle(FileHandle
,
3582 (PVOID
*)&FileObject
,
3583 &HandleInformation
);
3584 if (!NT_SUCCESS(Status
)) return Status
;
3586 /* Check if we're called from user mode */
3587 if (PreviousMode
!= KernelMode
)
3589 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3590 if (!(HandleInformation
.GrantedAccess
&
3591 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3593 ObDereferenceObject(FileObject
);
3594 return STATUS_ACCESS_DENIED
;
3597 /* Enter SEH for probing */
3600 /* Probe the I/O Status block */
3601 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3603 /* Probe and capture the large integers */
3604 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3605 CapturedLength
= ProbeForReadLargeInteger(Length
);
3607 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3609 /* Dereference the object and return exception code */
3610 ObDereferenceObject(FileObject
);
3611 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3617 /* Otherwise, capture them directly */
3618 CapturedByteOffset
= *ByteOffset
;
3619 CapturedLength
= *Length
;
3622 /* Check if this is a direct open or not */
3623 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3625 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3629 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3632 /* Try to do it the FastIO way if possible */
3633 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3634 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3636 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3637 &CapturedByteOffset
,
3639 PsGetCurrentProcess(),
3644 /* Write the IOSB back */
3647 *IoStatusBlock
= KernelIosb
;
3649 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3651 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3655 /* We're done with FastIO! */
3656 ObDereferenceObject(FileObject
);
3657 return KernelIosb
.Status
;
3661 /* Check if we should use Sync IO or not */
3662 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3665 Status
= IopLockFileObject(FileObject
, PreviousMode
);
3666 if (Status
!= STATUS_SUCCESS
)
3668 ObDereferenceObject(FileObject
);
3674 /* Use local event */
3675 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3678 ObDereferenceObject(FileObject
);
3679 return STATUS_INSUFFICIENT_RESOURCES
;
3681 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3685 /* Clear File Object event */
3686 KeClearEvent(&FileObject
->Event
);
3688 /* Allocate the IRP */
3689 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3690 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3692 /* Set up the IRP */
3693 Irp
->RequestorMode
= PreviousMode
;
3694 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3695 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3696 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3697 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3698 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3699 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3701 /* Set up Stack Data */
3702 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3703 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3704 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3705 StackPtr
->FileObject
= FileObject
;
3710 /* Allocate a buffer */
3711 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3712 sizeof(LARGE_INTEGER
),
3715 /* Set the length */
3716 *LocalLength
= CapturedLength
;
3717 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3718 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3720 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3722 /* Allocating failed, clean up and return the exception code */
3723 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3724 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3726 /* Return the exception code */
3727 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3731 /* Set Parameters */
3732 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3733 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3735 /* Call the Driver */
3736 Status
= IopPerformSynchronousRequest(DeviceObject
,
3744 /* Check if this was async I/O */
3747 /* It was, finalize this request */
3748 Status
= IopFinalizeAsynchronousIo(Status
,
3765 NtWriteFile(IN HANDLE FileHandle
,
3766 IN HANDLE Event OPTIONAL
,
3767 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3768 IN PVOID ApcContext OPTIONAL
,
3769 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3772 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3773 IN PULONG Key OPTIONAL
)
3776 PFILE_OBJECT FileObject
;
3778 PDEVICE_OBJECT DeviceObject
;
3779 PIO_STACK_LOCATION StackPtr
;
3780 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3781 PKEVENT EventObject
= NULL
;
3782 LARGE_INTEGER CapturedByteOffset
;
3783 ULONG CapturedKey
= 0;
3784 BOOLEAN Synchronous
= FALSE
;
3786 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3787 PFAST_IO_DISPATCH FastIoDispatch
;
3788 IO_STATUS_BLOCK KernelIosb
;
3792 CapturedByteOffset
.QuadPart
= 0;
3793 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3795 /* Get File Object for write */
3796 Status
= ObReferenceFileObjectForWrite(FileHandle
,
3800 if (!NT_SUCCESS(Status
)) return Status
;
3802 /* Get the device object */
3803 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3805 /* Validate User-Mode Buffers */
3806 if (PreviousMode
!= KernelMode
)
3810 /* Probe the status block */
3811 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3813 /* Probe the read buffer */
3814 ProbeForRead(Buffer
, Length
, 1);
3816 /* Check if we got a byte offset */
3819 /* Capture and probe it */
3820 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3823 /* Can't use an I/O completion port and an APC at the same time */
3824 if ((FileObject
->CompletionContext
) && (ApcRoutine
))
3827 ObDereferenceObject(FileObject
);
3828 return STATUS_INVALID_PARAMETER
;
3831 /* Perform additional checks for non-cached file access */
3832 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
3834 /* Fail if Length is not sector size aligned
3835 * Perform a quick check for 2^ sector sizes
3836 * If it fails, try a more standard way
3838 if ((DeviceObject
->SectorSize
!= 0) &&
3839 ((DeviceObject
->SectorSize
- 1) & Length
) != 0)
3841 if (Length
% DeviceObject
->SectorSize
!= 0)
3843 /* Release the file object and and fail */
3844 ObDereferenceObject(FileObject
);
3845 return STATUS_INVALID_PARAMETER
;
3849 /* Fail if buffer doesn't match alignment requirements */
3850 if (((ULONG_PTR
)Buffer
& DeviceObject
->AlignmentRequirement
) != 0)
3852 /* Release the file object and and fail */
3853 ObDereferenceObject(FileObject
);
3854 return STATUS_INVALID_PARAMETER
;
3859 /* Fail if ByteOffset is not sector size aligned */
3860 if ((DeviceObject
->SectorSize
!= 0) &&
3861 (CapturedByteOffset
.QuadPart
% DeviceObject
->SectorSize
!= 0))
3863 /* Only if that's not specific values for synchronous IO */
3864 if ((CapturedByteOffset
.QuadPart
!= FILE_WRITE_TO_END_OF_FILE
) &&
3865 (CapturedByteOffset
.QuadPart
!= FILE_USE_FILE_POINTER_POSITION
||
3866 !BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
)))
3868 /* Release the file object and and fail */
3869 ObDereferenceObject(FileObject
);
3870 return STATUS_INVALID_PARAMETER
;
3876 /* Capture and probe the key */
3877 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3879 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3881 /* Release the file object and return the exception code */
3882 ObDereferenceObject(FileObject
);
3883 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3889 /* Kernel mode: capture directly */
3890 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3891 if (Key
) CapturedKey
= *Key
;
3894 /* Check for invalid offset */
3895 if (CapturedByteOffset
.QuadPart
< -2)
3897 /* -1 is FILE_WRITE_TO_END_OF_FILE */
3898 /* -2 is FILE_USE_FILE_POINTER_POSITION */
3899 ObDereferenceObject(FileObject
);
3900 return STATUS_INVALID_PARAMETER
;
3903 /* Check if this is an append operation */
3904 if ((ObjectHandleInfo
.GrantedAccess
&
3905 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3907 /* Give the drivers something to understand */
3908 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3909 CapturedByteOffset
.u
.HighPart
= -1;
3912 /* Check for event */
3916 Status
= ObReferenceObjectByHandle(Event
,
3920 (PVOID
*)&EventObject
,
3922 if (!NT_SUCCESS(Status
))
3925 ObDereferenceObject(FileObject
);
3929 /* Otherwise reset the event */
3930 KeClearEvent(EventObject
);
3933 /* Check if we should use Sync IO or not */
3934 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3936 /* Lock the file object */
3937 Status
= IopLockFileObject(FileObject
, PreviousMode
);
3938 if (Status
!= STATUS_SUCCESS
)
3940 if (EventObject
) ObDereferenceObject(EventObject
);
3941 ObDereferenceObject(FileObject
);
3945 /* Check if we don't have a byte offset available */
3946 if (!(ByteOffset
) ||
3947 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3948 (CapturedByteOffset
.u
.HighPart
== -1)))
3950 /* Use the Current Byte Offset instead */
3951 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3954 /* If the file is cached, try fast I/O */
3955 if (FileObject
->PrivateCacheMap
)
3957 /* Perform fast write */
3958 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3959 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoWrite
!= NULL
);
3961 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3962 &CapturedByteOffset
,
3970 /* Only accept the result if it was successful */
3972 KernelIosb
.Status
== STATUS_SUCCESS
)
3974 /* Fast path -- update transfer & operation counts */
3975 IopUpdateOperationCount(IopWriteTransfer
);
3976 IopUpdateTransferCount(IopWriteTransfer
,
3977 (ULONG
)KernelIosb
.Information
);
3979 /* Enter SEH to write the IOSB back */
3982 /* Write it back to the caller */
3983 *IoStatusBlock
= KernelIosb
;
3985 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3987 /* The caller's IOSB was invalid, so fail */
3988 if (EventObject
) ObDereferenceObject(EventObject
);
3989 IopUnlockFileObject(FileObject
);
3990 ObDereferenceObject(FileObject
);
3991 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3995 /* Signal the completion event */
3998 KeSetEvent(EventObject
, 0, FALSE
);
3999 ObDereferenceObject(EventObject
);
4003 IopUnlockFileObject(FileObject
);
4004 ObDereferenceObject(FileObject
);
4005 return KernelIosb
.Status
;
4009 /* Remember we are sync */
4012 else if (!(ByteOffset
) &&
4013 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
4015 /* Otherwise, this was async I/O without a byte offset, so fail */
4016 if (EventObject
) ObDereferenceObject(EventObject
);
4017 ObDereferenceObject(FileObject
);
4018 return STATUS_INVALID_PARAMETER
;
4021 /* Clear the File Object's event */
4022 KeClearEvent(&FileObject
->Event
);
4024 /* Allocate the IRP */
4025 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4026 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
4029 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4030 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4031 Irp
->RequestorMode
= PreviousMode
;
4032 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
4033 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
4034 Irp
->UserIosb
= IoStatusBlock
;
4035 Irp
->UserEvent
= EventObject
;
4036 Irp
->PendingReturned
= FALSE
;
4037 Irp
->Cancel
= FALSE
;
4038 Irp
->CancelRoutine
= NULL
;
4039 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4040 Irp
->MdlAddress
= NULL
;
4042 /* Set the Stack Data */
4043 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4044 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
4045 StackPtr
->FileObject
= FileObject
;
4046 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
4047 SL_WRITE_THROUGH
: 0;
4048 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
4049 StackPtr
->Parameters
.Write
.Length
= Length
;
4050 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
4052 /* Check if this is buffered I/O */
4053 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
4055 /* Check if we have a buffer length */
4061 /* Allocate a buffer */
4062 Irp
->AssociatedIrp
.SystemBuffer
=
4063 ExAllocatePoolWithTag(NonPagedPool
,
4067 /* Copy the data into it */
4068 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
4070 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4072 /* Allocating failed, clean up and return the exception code */
4073 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
4074 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4079 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4083 /* Not writing anything */
4084 Irp
->Flags
= IRP_BUFFERED_IO
;
4087 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
4089 /* Check if we have a buffer length */
4094 /* Allocate an MDL */
4095 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
4097 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
4098 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
4100 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4102 /* Allocating failed, clean up and return the exception code */
4103 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
4104 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4109 /* No allocation flags */
4114 /* No allocation flags, and use the buffer directly */
4116 Irp
->UserBuffer
= Buffer
;
4119 /* Now set the deferred read flags */
4120 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
4122 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
4124 /* Perform the call */
4125 return IopPerformSynchronousRequest(DeviceObject
,
4136 NtWriteFileGather(IN HANDLE FileHandle
,
4137 IN HANDLE Event OPTIONAL
,
4138 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
4139 IN PVOID UserApcContext OPTIONAL
,
4140 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
4141 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
4142 IN ULONG BufferLength
,
4143 IN PLARGE_INTEGER ByteOffset
,
4144 IN PULONG Key OPTIONAL
)
4147 return STATUS_NOT_IMPLEMENTED
;
4155 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
4156 OUT PIO_STATUS_BLOCK IoStatusBlock
,
4157 OUT PVOID FsInformation
,
4159 IN FS_INFORMATION_CLASS FsInformationClass
)
4161 PFILE_OBJECT FileObject
;
4163 PIO_STACK_LOCATION StackPtr
;
4164 PDEVICE_OBJECT DeviceObject
;
4165 PKEVENT Event
= NULL
;
4166 BOOLEAN LocalEvent
= FALSE
;
4167 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
4169 IO_STATUS_BLOCK KernelIosb
;
4171 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
4173 /* Check if we're called from user mode */
4174 if (PreviousMode
!= KernelMode
)
4176 /* Validate the information class */
4177 if ((FsInformationClass
< 0) ||
4178 (FsInformationClass
>= FileFsMaximumInformation
) ||
4179 !(IopQueryFsOperationLength
[FsInformationClass
]))
4182 return STATUS_INVALID_INFO_CLASS
;
4185 /* Validate the length */
4186 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
4188 /* Invalid length */
4189 return STATUS_INFO_LENGTH_MISMATCH
;
4192 /* Enter SEH for probing */
4195 /* Probe the I/O Status block */
4196 ProbeForWriteIoStatusBlock(IoStatusBlock
);
4198 /* Probe the information */
4199 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
4201 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4203 /* Return the exception code */
4204 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4209 /* Get File Object */
4210 Status
= ObReferenceObjectByHandle(FileHandle
,
4211 IopQueryFsOperationAccess
4212 [FsInformationClass
],
4215 (PVOID
*)&FileObject
,
4217 if (!NT_SUCCESS(Status
)) return Status
;
4219 /* Only allow direct device open for FileFsDeviceInformation */
4220 if (BooleanFlagOn(FileObject
->Flags
, FO_DIRECT_DEVICE_OPEN
) &&
4221 FsInformationClass
!= FileFsDeviceInformation
)
4223 ObDereferenceObject(FileObject
);
4224 return STATUS_INVALID_DEVICE_REQUEST
;
4227 /* Check if we should use Sync IO or not */
4228 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4231 Status
= IopLockFileObject(FileObject
, PreviousMode
);
4232 if (Status
!= STATUS_SUCCESS
)
4234 ObDereferenceObject(FileObject
);
4240 * Quick path for FileFsDeviceInformation - the kernel has enough
4241 * info to reply instead of the driver, excepted for network file systems
4243 if (FsInformationClass
== FileFsDeviceInformation
&&
4244 (BooleanFlagOn(FileObject
->Flags
, FO_DIRECT_DEVICE_OPEN
) || FileObject
->DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK_FILE_SYSTEM
))
4246 PFILE_FS_DEVICE_INFORMATION FsDeviceInfo
= FsInformation
;
4247 DeviceObject
= FileObject
->DeviceObject
;
4251 FsDeviceInfo
->DeviceType
= DeviceObject
->DeviceType
;
4253 /* Complete characteristcs with mount status if relevant */
4254 FsDeviceInfo
->Characteristics
= DeviceObject
->Characteristics
;
4255 if (IopGetMountFlag(DeviceObject
))
4257 SetFlag(FsDeviceInfo
->Characteristics
, FILE_DEVICE_IS_MOUNTED
);
4260 IoStatusBlock
->Information
= sizeof(FILE_FS_DEVICE_INFORMATION
);
4261 IoStatusBlock
->Status
= STATUS_SUCCESS
;
4263 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4265 /* Check if we had a file lock */
4266 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
4269 IopUnlockFileObject(FileObject
);
4272 /* Dereference the FO */
4273 ObDereferenceObject(FileObject
);
4275 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4279 /* Check if we had a file lock */
4280 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
4283 IopUnlockFileObject(FileObject
);
4286 /* Dereference the FO */
4287 ObDereferenceObject(FileObject
);
4289 return STATUS_SUCCESS
;
4291 /* This is to be handled by the kernel, not by FSD */
4292 else if (FsInformationClass
== FileFsDriverPathInformation
)
4294 _SEH2_VOLATILE PFILE_FS_DRIVER_PATH_INFORMATION DriverPathInfo
= NULL
;
4298 /* Allocate our local structure */
4299 DriverPathInfo
= ExAllocatePoolWithQuotaTag(NonPagedPool
, Length
, TAG_IO
);
4301 /* And copy back caller data */
4302 RtlCopyMemory(DriverPathInfo
, FsInformation
, Length
);
4304 /* Is the driver in the IO path? */
4305 Status
= IopGetDriverPathInformation(FileObject
,
4306 (PFILE_FS_DRIVER_PATH_INFORMATION
)DriverPathInfo
,
4308 /* We failed, don't continue execution */
4309 if (!NT_SUCCESS(Status
))
4311 RtlRaiseStatus(Status
);
4314 /* We succeed, copy back info */
4315 ((PFILE_FS_DRIVER_PATH_INFORMATION
)FsInformation
)->DriverInPath
= DriverPathInfo
->DriverInPath
;
4318 IoStatusBlock
->Information
= sizeof(FILE_FS_DRIVER_PATH_INFORMATION
);
4319 IoStatusBlock
->Status
= STATUS_SUCCESS
;
4321 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4323 Status
= _SEH2_GetExceptionCode();
4328 if (DriverPathInfo
!= NULL
)
4330 ExFreePoolWithTag(DriverPathInfo
, TAG_IO
);
4333 /* Check if we had a file lock */
4334 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
4337 IopUnlockFileObject(FileObject
);
4340 /* Dereference the FO */
4341 ObDereferenceObject(FileObject
);
4346 if (!BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
4348 /* Use local event */
4349 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4352 ObDereferenceObject(FileObject
);
4353 return STATUS_INSUFFICIENT_RESOURCES
;
4355 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4359 /* Get the device object */
4360 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4362 /* Clear File Object event */
4363 KeClearEvent(&FileObject
->Event
);
4365 /* Allocate the IRP */
4366 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4367 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4369 /* Set up the IRP */
4370 Irp
->RequestorMode
= PreviousMode
;
4371 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4372 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4373 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4374 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4375 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4376 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4377 Irp
->UserBuffer
= FsInformation
;
4378 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4379 Irp
->MdlAddress
= NULL
;
4381 /* Set up Stack Data */
4382 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4383 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
4384 StackPtr
->FileObject
= FileObject
;
4389 /* Allocate a buffer */
4390 Irp
->AssociatedIrp
.SystemBuffer
=
4391 ExAllocatePoolWithTag(NonPagedPool
,
4395 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4397 /* Allocating failed, clean up and return the exception code */
4398 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4399 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4403 /* Set the flags for this buffered + deferred I/O */
4404 Irp
->Flags
|= (IRP_BUFFERED_IO
|
4405 IRP_DEALLOCATE_BUFFER
|
4406 IRP_INPUT_OPERATION
|
4407 IRP_DEFER_IO_COMPLETION
);
4409 /* Set Parameters */
4410 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
4411 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
4413 /* Call the Driver */
4414 Status
= IopPerformSynchronousRequest(DeviceObject
,
4422 /* Check if this was async I/O */
4425 /* It was, finalize this request */
4426 Status
= IopFinalizeAsynchronousIo(Status
,
4443 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
4444 OUT PIO_STATUS_BLOCK IoStatusBlock
,
4445 IN PVOID FsInformation
,
4447 IN FS_INFORMATION_CLASS FsInformationClass
)
4449 PFILE_OBJECT FileObject
;
4451 PIO_STACK_LOCATION StackPtr
;
4452 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
4453 PKEVENT Event
= NULL
;
4454 BOOLEAN LocalEvent
= FALSE
;
4455 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
4457 IO_STATUS_BLOCK KernelIosb
;
4458 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
4460 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
4462 /* Check if we're called from user mode */
4463 if (PreviousMode
!= KernelMode
)
4465 /* Validate the information class */
4466 if ((FsInformationClass
< 0) ||
4467 (FsInformationClass
>= FileFsMaximumInformation
) ||
4468 !(IopSetFsOperationLength
[FsInformationClass
]))
4471 return STATUS_INVALID_INFO_CLASS
;
4474 /* Validate the length */
4475 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
4477 /* Invalid length */
4478 return STATUS_INFO_LENGTH_MISMATCH
;
4481 /* Enter SEH for probing */
4484 /* Probe the I/O Status block */
4485 ProbeForWriteIoStatusBlock(IoStatusBlock
);
4487 /* Probe the information */
4488 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
4490 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4492 /* Return the exception code */
4493 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4498 /* Get File Object */
4499 Status
= ObReferenceObjectByHandle(FileHandle
,
4500 IopSetFsOperationAccess
4501 [FsInformationClass
],
4504 (PVOID
*)&FileObject
,
4506 if (!NT_SUCCESS(Status
)) return Status
;
4508 /* Get target device for notification */
4509 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4510 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4512 /* Check if we should use Sync IO or not */
4513 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4516 Status
= IopLockFileObject(FileObject
, PreviousMode
);
4517 if (Status
!= STATUS_SUCCESS
)
4519 ObDereferenceObject(FileObject
);
4520 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4526 /* Use local event */
4527 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4530 ObDereferenceObject(FileObject
);
4531 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4532 return STATUS_INSUFFICIENT_RESOURCES
;
4534 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4538 /* Get the device object */
4539 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4541 /* Clear File Object event */
4542 KeClearEvent(&FileObject
->Event
);
4544 /* Allocate the IRP */
4545 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4548 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4549 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4552 /* Set up the IRP */
4553 Irp
->RequestorMode
= PreviousMode
;
4554 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4555 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4556 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4557 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4558 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4559 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4560 Irp
->UserBuffer
= FsInformation
;
4561 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4562 Irp
->MdlAddress
= NULL
;
4564 /* Set up Stack Data */
4565 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4566 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
4567 StackPtr
->FileObject
= FileObject
;
4572 /* Allocate a buffer */
4573 Irp
->AssociatedIrp
.SystemBuffer
=
4574 ExAllocatePoolWithTag(NonPagedPool
,
4578 /* Copy the data into it */
4579 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
4581 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4583 /* Allocating failed, clean up and return the exception code */
4584 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4585 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4586 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4590 /* Set the flags for this buffered + deferred I/O */
4591 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4593 /* Set Parameters */
4594 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
4595 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
4597 /* Call the Driver */
4598 Status
= IopPerformSynchronousRequest(DeviceObject
,
4606 /* Check if this was async I/O */
4609 /* It was, finalize this request */
4610 Status
= IopFinalizeAsynchronousIo(Status
,
4618 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
4620 /* Time to report change */
4621 NotificationStructure
.Version
= 1;
4622 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
4623 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
4624 NotificationStructure
.FileObject
= NULL
;
4625 NotificationStructure
.NameBufferOffset
= - 1;
4626 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
4638 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
4641 return STATUS_NOT_IMPLEMENTED
;
4649 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
4652 return STATUS_NOT_IMPLEMENTED
;