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 /* PRIVATE FUNCTIONS *********************************************************/
24 IopCleanupAfterException(IN PFILE_OBJECT FileObject
,
26 IN PKEVENT Event OPTIONAL
,
27 IN PKEVENT LocalEvent OPTIONAL
)
30 IOTRACE(IO_API_DEBUG
, "IRP: %p. FO: %p \n", Irp
, FileObject
);
32 /* Check if we had a buffer */
33 if (Irp
->AssociatedIrp
.SystemBuffer
)
36 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
40 if (Irp
->MdlAddress
) IoFreeMdl(Irp
->MdlAddress
);
45 /* Check if we had a file lock */
46 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
49 IopUnlockFileObject(FileObject
);
52 /* Check if we had an event */
53 if (Event
) ObDereferenceObject(Event
);
55 /* Check if we had a local event */
56 if (LocalEvent
) ExFreePool(LocalEvent
);
58 /* Derefenrce the FO */
59 ObDereferenceObject(FileObject
);
64 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus
,
67 IN KPROCESSOR_MODE PreviousMode
,
68 IN PIO_STATUS_BLOCK KernelIosb
,
69 OUT PIO_STATUS_BLOCK IoStatusBlock
)
71 NTSTATUS FinalStatus
= SynchStatus
;
73 IOTRACE(IO_API_DEBUG
, "IRP: %p. Status: %lx \n", Irp
, SynchStatus
);
75 /* Make sure the IRP was completed, but returned pending */
76 if (FinalStatus
== STATUS_PENDING
)
78 /* Wait for the IRP */
79 FinalStatus
= KeWaitForSingleObject(Event
,
84 if (FinalStatus
== STATUS_USER_APC
)
86 /* Abort the request */
87 IopAbortInterruptedIrp(Event
, Irp
);
90 /* Set the final status */
91 FinalStatus
= KernelIosb
->Status
;
94 /* Wrap potential user-mode write in SEH */
97 *IoStatusBlock
= *KernelIosb
;
99 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
101 /* Get the exception code */
102 FinalStatus
= _SEH2_GetExceptionCode();
106 /* Free the event and return status */
113 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject
,
115 IN PFILE_OBJECT FileObject
,
117 IN KPROCESSOR_MODE PreviousMode
,
119 IN IOP_TRANSFER_TYPE TransferType
)
122 PKNORMAL_ROUTINE NormalRoutine
;
123 PVOID NormalContext
= NULL
;
126 IOTRACE(IO_API_DEBUG
, "IRP: %p. DO: %p. FO: %p \n",
127 Irp
, DeviceObject
, FileObject
);
130 IopQueueIrpToThread(Irp
);
132 /* Update operation counts */
133 IopUpdateOperationCount(TransferType
);
135 /* Call the driver */
136 Status
= IoCallDriver(DeviceObject
, Irp
);
138 /* Check if we're optimizing this case */
141 /* We are! Check if the IRP wasn't completed */
142 if (Status
!= STATUS_PENDING
)
144 /* Complete it ourselves */
145 ASSERT(!Irp
->PendingReturned
);
146 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
147 IopCompleteRequest(&Irp
->Tail
.Apc
,
152 KeLowerIrql(OldIrql
);
156 /* Check if this was synch I/O */
159 /* Make sure the IRP was completed, but returned pending */
160 if (Status
== STATUS_PENDING
)
162 /* Wait for the IRP */
163 Status
= KeWaitForSingleObject(&FileObject
->Event
,
167 FO_ALERTABLE_IO
) != 0,
169 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
171 /* Abort the request */
172 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
175 /* Set the final status */
176 Status
= FileObject
->FinalStatus
;
179 /* Release the file lock */
180 IopUnlockFileObject(FileObject
);
189 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
190 IN HANDLE Event OPTIONAL
,
191 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
192 IN PVOID UserApcContext OPTIONAL
,
193 OUT PIO_STATUS_BLOCK IoStatusBlock
,
194 IN ULONG IoControlCode
,
195 IN PVOID InputBuffer
,
196 IN ULONG InputBufferLength OPTIONAL
,
197 OUT PVOID OutputBuffer
,
198 IN ULONG OutputBufferLength OPTIONAL
,
199 IN BOOLEAN IsDevIoCtl
)
202 PFILE_OBJECT FileObject
;
203 PDEVICE_OBJECT DeviceObject
;
205 PIO_STACK_LOCATION StackPtr
;
206 PKEVENT EventObject
= NULL
;
207 BOOLEAN LockedForSynch
= FALSE
;
209 OBJECT_HANDLE_INFORMATION HandleInformation
;
210 ACCESS_MASK DesiredAccess
;
211 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
213 IOTRACE(IO_CTL_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
214 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
216 /* Get the access type */
217 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
219 /* Check if we came from user mode */
220 if (PreviousMode
!= KernelMode
)
224 /* Probe the status block */
225 ProbeForWriteIoStatusBlock(IoStatusBlock
);
227 /* Check if this is buffered I/O */
228 if (AccessType
== METHOD_BUFFERED
)
230 /* Check if we have an output buffer */
233 /* Probe the output buffer */
234 ProbeForWrite(OutputBuffer
,
240 /* Make sure the caller can't fake this as we depend on this */
241 OutputBufferLength
= 0;
245 /* Check if we we have an input buffer I/O */
246 if (AccessType
!= METHOD_NEITHER
)
248 /* Check if we have an input buffer */
251 /* Probe the input buffer */
252 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
256 /* Make sure the caller can't fake this as we depend on this */
257 InputBufferLength
= 0;
261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
263 /* Return the exception code */
264 _SEH2_YIELD(return _SEH2_GetExceptionCode());
269 /* Don't check for access rights right now, KernelMode can do anything */
270 Status
= ObReferenceObjectByHandle(DeviceHandle
,
276 if (!NT_SUCCESS(Status
)) return Status
;
278 /* Can't use an I/O completion port and an APC in the same time */
279 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
282 ObDereferenceObject(FileObject
);
283 return STATUS_INVALID_PARAMETER
;
286 /* Check if we from user mode */
287 if (PreviousMode
!= KernelMode
)
289 /* Get the access mask */
290 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
292 /* Check if we can open it */
293 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
294 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
296 /* Dereference the file object and fail */
297 ObDereferenceObject(FileObject
);
298 return STATUS_ACCESS_DENIED
;
302 /* Check for an event */
306 Status
= ObReferenceObjectByHandle(Event
,
310 (PVOID
*)&EventObject
,
312 if (!NT_SUCCESS(Status
))
314 /* Dereference the file object and fail */
315 ObDereferenceObject(FileObject
);
320 KeClearEvent(EventObject
);
323 /* Check if this is a file that was opened for Synch I/O */
324 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
327 IopLockFileObject(FileObject
);
329 /* Remember to unlock later */
330 LockedForSynch
= TRUE
;
333 /* Check if this is a direct open or not */
334 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
336 /* It's a direct open, get the attached device */
337 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
341 /* Otherwise get the related device */
342 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
345 /* If that's FS I/O, try to do it with FastIO path */
348 PFAST_IO_DISPATCH FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
350 /* Check whether FSD is FastIO aware and provide an appropriate routine */
351 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoDeviceControl
!= NULL
)
353 IO_STATUS_BLOCK KernelIosb
;
355 /* If we have an output buffer coming from usermode */
356 if (PreviousMode
!= KernelMode
&& OutputBuffer
!= NULL
)
358 /* Probe it according to its usage */
361 if (AccessType
== METHOD_IN_DIRECT
)
363 ProbeForRead(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
365 else if (AccessType
== METHOD_OUT_DIRECT
)
367 ProbeForWrite(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
370 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
372 /* Cleanup after exception and return */
373 IopCleanupAfterException(FileObject
, NULL
, EventObject
, NULL
);
375 /* Return the exception code */
376 _SEH2_YIELD(return _SEH2_GetExceptionCode());
381 /* If we're to dismount a volume, increaase the dismount count */
382 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
384 InterlockedExchangeAdd((PLONG
)&SharedUserData
->DismountCount
, 1);
388 if (FastIoDispatch
->FastIoDeviceControl(FileObject
,
398 IO_COMPLETION_CONTEXT CompletionInfo
= { NULL
, NULL
};
400 /* Write the IOSB back */
403 *IoStatusBlock
= KernelIosb
;
406 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
408 KernelIosb
.Status
= _SEH2_GetExceptionCode();
412 /* Backup our complete context in case it exists */
413 if (FileObject
->CompletionContext
)
415 CompletionInfo
= *(FileObject
->CompletionContext
);
418 /* If we had an event, signal it */
421 KeSetEvent(EventObject
, IO_NO_INCREMENT
, FALSE
);
422 ObDereferenceObject(EventObject
);
425 /* If FO was locked, unlock it */
428 IopUnlockFileObject(FileObject
);
431 /* Set completion if required */
432 if (CompletionInfo
.Port
!= NULL
&& UserApcContext
!= NULL
)
434 if (!NT_SUCCESS(IoSetIoCompletion(CompletionInfo
.Port
,
438 KernelIosb
.Information
,
441 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
445 /* We're done with FastIO! */
446 ObDereferenceObject(FileObject
);
447 return KernelIosb
.Status
;
452 /* Clear the event */
453 KeClearEvent(&FileObject
->Event
);
456 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
457 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
460 Irp
->UserIosb
= IoStatusBlock
;
461 Irp
->UserEvent
= EventObject
;
462 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
463 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
465 Irp
->CancelRoutine
= NULL
;
466 Irp
->PendingReturned
= FALSE
;
467 Irp
->RequestorMode
= PreviousMode
;
468 Irp
->MdlAddress
= NULL
;
469 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
471 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
472 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
473 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
475 /* Set stack location settings */
476 StackPtr
= IoGetNextIrpStackLocation(Irp
);
477 StackPtr
->FileObject
= FileObject
;
478 StackPtr
->MajorFunction
= IsDevIoCtl
?
479 IRP_MJ_DEVICE_CONTROL
:
480 IRP_MJ_FILE_SYSTEM_CONTROL
;
481 StackPtr
->MinorFunction
= 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
482 StackPtr
->Control
= 0;
484 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
486 /* Set the IOCTL Data */
487 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
488 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
489 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
492 /* Handle the Methods */
496 case METHOD_BUFFERED
:
498 /* Enter SEH for allocations */
501 /* Select the right Buffer Length */
502 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
503 InputBufferLength
: OutputBufferLength
;
505 /* Make sure there is one */
508 /* Allocate the System Buffer */
509 Irp
->AssociatedIrp
.SystemBuffer
=
510 ExAllocatePoolWithTag(NonPagedPool
,
514 /* Check if we got a buffer */
517 /* Copy into the System Buffer */
518 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
523 /* Write the flags */
524 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
525 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
527 /* Save the Buffer */
528 Irp
->UserBuffer
= OutputBuffer
;
532 /* Clear the Flags and Buffer */
533 Irp
->UserBuffer
= NULL
;
536 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
538 /* Cleanup after exception and return */
539 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
540 _SEH2_YIELD(return _SEH2_GetExceptionCode());
546 case METHOD_IN_DIRECT
:
547 case METHOD_OUT_DIRECT
:
552 /* Check if we got an input buffer */
553 if ((InputBufferLength
) && (InputBuffer
))
555 /* Allocate the System Buffer */
556 Irp
->AssociatedIrp
.SystemBuffer
=
557 ExAllocatePoolWithTag(NonPagedPool
,
561 /* Copy into the System Buffer */
562 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
566 /* Write the flags */
567 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
570 /* Check if we got an output buffer */
573 /* Allocate the System Buffer */
574 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
579 if (!Irp
->MdlAddress
)
581 /* Raise exception we'll catch */
582 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
586 MmProbeAndLockPages(Irp
->MdlAddress
,
588 (AccessType
== METHOD_IN_DIRECT
) ?
589 IoReadAccess
: IoWriteAccess
);
592 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
594 /* Cleanup after exception and return */
595 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
596 _SEH2_YIELD(return _SEH2_GetExceptionCode());
603 /* Just save the Buffer */
604 Irp
->UserBuffer
= OutputBuffer
;
605 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
608 /* Use deferred completion for FS I/O */
609 Irp
->Flags
|= (!IsDevIoCtl
) ? IRP_DEFER_IO_COMPLETION
: 0;
611 /* Perform the call */
612 return IopPerformSynchronousRequest(DeviceObject
,
623 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
624 IN ULONG InformationClass
,
626 OUT PVOID Information
,
627 OUT PULONG ReturnedLength
,
630 IO_STATUS_BLOCK IoStatusBlock
;
632 PDEVICE_OBJECT DeviceObject
;
633 PIO_STACK_LOCATION StackPtr
;
634 BOOLEAN LocalEvent
= FALSE
;
638 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
639 FileObject
, InformationClass
, File
);
641 /* Reference the object */
642 ObReferenceObject(FileObject
);
644 /* Check if this is a file that was opened for Synch I/O */
645 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
648 IopLockFileObject(FileObject
);
650 /* Use File Object event */
651 KeClearEvent(&FileObject
->Event
);
655 /* Use local event */
656 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
660 /* Get the Device Object */
661 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
663 /* Allocate the IRP */
664 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
665 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
668 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
669 Irp
->RequestorMode
= KernelMode
;
670 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
671 Irp
->UserIosb
= &IoStatusBlock
;
672 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
673 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
674 Irp
->Flags
|= IRP_BUFFERED_IO
;
675 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
676 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
678 /* Set the Stack Data */
679 StackPtr
= IoGetNextIrpStackLocation(Irp
);
680 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
681 IRP_MJ_QUERY_VOLUME_INFORMATION
;
682 StackPtr
->FileObject
= FileObject
;
684 /* Check which type this is */
688 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
689 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
694 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
695 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
699 IopQueueIrpToThread(Irp
);
701 /* Call the Driver */
702 Status
= IoCallDriver(DeviceObject
, Irp
);
704 /* Check if this was synch I/O */
707 /* Check if the request is pending */
708 if (Status
== STATUS_PENDING
)
710 /* Wait on the file object */
711 Status
= KeWaitForSingleObject(&FileObject
->Event
,
715 FO_ALERTABLE_IO
) != 0,
717 if (Status
== STATUS_ALERTED
)
719 /* Abort the operation */
720 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
723 /* Get the final status */
724 Status
= FileObject
->FinalStatus
;
727 /* Release the file lock */
728 IopUnlockFileObject(FileObject
);
730 else if (Status
== STATUS_PENDING
)
732 /* Wait on the local event and get the final status */
733 KeWaitForSingleObject(&Event
,
738 Status
= IoStatusBlock
.Status
;
741 /* Return the Length and Status. ReturnedLength is NOT optional */
742 *ReturnedLength
= (ULONG
)IoStatusBlock
.Information
;
748 IopGetFileInformation(IN PFILE_OBJECT FileObject
,
750 IN FILE_INFORMATION_CLASS FileInfoClass
,
752 OUT PULONG ReturnedLength
)
757 PIO_STACK_LOCATION Stack
;
758 PDEVICE_OBJECT DeviceObject
;
759 IO_STATUS_BLOCK IoStatusBlock
;
763 /* Allocate an IRP */
764 ObReferenceObject(FileObject
);
765 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
766 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
769 ObDereferenceObject(FileObject
);
770 return STATUS_INSUFFICIENT_RESOURCES
;
774 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
777 Irp
->UserIosb
= &IoStatusBlock
;
778 Irp
->UserEvent
= &Event
;
779 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
780 Irp
->RequestorMode
= KernelMode
;
781 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
782 Irp
->Flags
= IRP_SYNCHRONOUS_API
| IRP_BUFFERED_IO
| IRP_OB_QUERY_NAME
;
783 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
784 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
786 Stack
= IoGetNextIrpStackLocation(Irp
);
787 Stack
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
788 Stack
->FileObject
= FileObject
;
789 Stack
->Parameters
.QueryFile
.FileInformationClass
= FileInfoClass
;
790 Stack
->Parameters
.QueryFile
.Length
= Length
;
794 IopQueueIrpToThread(Irp
);
796 /* Call the driver */
797 Status
= IoCallDriver(DeviceObject
, Irp
);
798 if (Status
== STATUS_PENDING
)
800 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
801 Status
= IoStatusBlock
.Status
;
804 *ReturnedLength
= IoStatusBlock
.Information
;
810 IopGetBasicInformationFile(IN PFILE_OBJECT FileObject
,
811 OUT PFILE_BASIC_INFORMATION BasicInfo
)
813 ULONG ReturnedLength
;
814 PDEVICE_OBJECT DeviceObject
;
815 IO_STATUS_BLOCK IoStatusBlock
;
819 /* Try to do it the fast way if possible */
820 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
821 if (DeviceObject
->DriverObject
->FastIoDispatch
!= NULL
&&
822 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
&&
823 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo(FileObject
,
824 ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) != 0),
829 return IoStatusBlock
.Status
;
832 /* In case it failed, fall back to IRP-based method */
833 return IopGetFileInformation(FileObject
, sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
, BasicInfo
, &ReturnedLength
);
838 IopOpenLinkOrRenameTarget(OUT PHANDLE Handle
,
840 IN PFILE_RENAME_INFORMATION RenameInfo
,
841 IN PFILE_OBJECT FileObject
)
845 UNICODE_STRING FileName
;
846 PIO_STACK_LOCATION Stack
;
847 PFILE_OBJECT TargetFileObject
;
848 IO_STATUS_BLOCK IoStatusBlock
;
849 FILE_BASIC_INFORMATION BasicInfo
;
850 OBJECT_ATTRIBUTES ObjectAttributes
;
851 OBJECT_HANDLE_INFORMATION HandleInformation
;
852 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
856 /* First, establish whether our target is a directory */
857 if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
859 Status
= IopGetBasicInformationFile(FileObject
, &BasicInfo
);
860 if (!NT_SUCCESS(Status
))
865 if (BasicInfo
.FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
866 DesiredAccess
= FILE_ADD_SUBDIRECTORY
;
870 /* Setup the string to the target */
871 FileName
.Buffer
= RenameInfo
->FileName
;
872 FileName
.Length
= RenameInfo
->FileNameLength
;
873 FileName
.MaximumLength
= RenameInfo
->FileNameLength
;
875 InitializeObjectAttributes(&ObjectAttributes
,
877 (FileObject
->Flags
& FO_OPENED_CASE_SENSITIVE
? 0 : OBJ_CASE_INSENSITIVE
) | OBJ_KERNEL_HANDLE
,
878 RenameInfo
->RootDirectory
,
881 /* And open its parent directory */
882 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
884 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
886 /* Commented out - we don't support FO extension yet
887 * FIXME: Corrected last arg when it's supported
889 Status
= IoCreateFileSpecifyDeviceObjectHint(&TargetHandle
,
890 DesiredAccess
| SYNCHRONIZE
,
895 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
897 FILE_OPEN_FOR_BACKUP_INTENT
,
902 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
,
903 FileObject
->DeviceObject
);
907 return STATUS_NOT_IMPLEMENTED
;
912 Status
= IoCreateFile(&TargetHandle
,
913 DesiredAccess
| SYNCHRONIZE
,
918 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
920 FILE_OPEN_FOR_BACKUP_INTENT
,
925 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
);
928 if (!NT_SUCCESS(Status
))
933 /* Once open, continue only if:
934 * Target exists and we're allowed to overwrite it
936 Stack
= IoGetNextIrpStackLocation(Irp
);
937 if (Stack
->Parameters
.SetFile
.FileInformationClass
== FileLinkInformation
&&
938 !RenameInfo
->ReplaceIfExists
&&
939 IoStatusBlock
.Information
== FILE_EXISTS
)
941 ObCloseHandle(TargetHandle
, KernelMode
);
942 return STATUS_OBJECT_NAME_COLLISION
;
945 /* Now, we'll get the associated device of the target, to check for same device location
946 * So, get the FO first
948 Status
= ObReferenceObjectByHandle(TargetHandle
,
952 (PVOID
*)&TargetFileObject
,
954 if (!NT_SUCCESS(Status
))
956 ObCloseHandle(TargetHandle
, KernelMode
);
960 /* We can dereference, we have the handle */
961 ObDereferenceObject(TargetFileObject
);
962 /* If we're not on the same device, error out **/
963 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
965 ObCloseHandle(TargetHandle
, KernelMode
);
966 return STATUS_NOT_SAME_DEVICE
;
969 /* Return parent directory file object and handle */
970 Stack
->Parameters
.SetFile
.FileObject
= TargetFileObject
;
971 *Handle
= TargetHandle
;
973 return STATUS_SUCCESS
;
978 IopGetFileMode(IN PFILE_OBJECT FileObject
)
982 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
983 Mode
|= FILE_WRITE_THROUGH
;
985 if (FileObject
->Flags
& FO_SEQUENTIAL_ONLY
)
986 Mode
|= FILE_SEQUENTIAL_ONLY
;
988 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
989 Mode
|= FILE_NO_INTERMEDIATE_BUFFERING
;
991 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
993 if (FileObject
->Flags
& FO_ALERTABLE_IO
)
994 Mode
|= FILE_SYNCHRONOUS_IO_ALERT
;
996 Mode
|= FILE_SYNCHRONOUS_IO_NONALERT
;
999 if (FileObject
->Flags
& FO_DELETE_ON_CLOSE
)
1000 Mode
|= FILE_DELETE_ON_CLOSE
;
1005 /* PUBLIC FUNCTIONS **********************************************************/
1012 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
1014 IN PLARGE_INTEGER Offset
,
1016 IN PIO_STATUS_BLOCK StatusBlock
)
1019 PIO_STACK_LOCATION StackPtr
;
1020 PDEVICE_OBJECT DeviceObject
;
1021 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1022 FileObject
, Mdl
, Offset
);
1024 /* Get the Device Object */
1025 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1028 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1029 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1032 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1034 /* Create the IRP Settings */
1035 Irp
->MdlAddress
= Mdl
;
1036 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1037 Irp
->UserIosb
= StatusBlock
;
1038 Irp
->UserEvent
= Event
;
1039 Irp
->RequestorMode
= KernelMode
;
1040 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
1041 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1042 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1044 /* Set the Stack Settings */
1045 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
1046 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
1047 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
1048 StackPtr
->FileObject
= FileObject
;
1050 /* Call the Driver */
1051 return IoCallDriver(DeviceObject
, Irp
);
1059 IoPageRead(IN PFILE_OBJECT FileObject
,
1061 IN PLARGE_INTEGER Offset
,
1063 IN PIO_STATUS_BLOCK StatusBlock
)
1066 PIO_STACK_LOCATION StackPtr
;
1067 PDEVICE_OBJECT DeviceObject
;
1068 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1069 FileObject
, Mdl
, Offset
);
1071 /* Get the Device Object */
1072 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1075 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1076 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1079 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1081 /* Create the IRP Settings */
1082 Irp
->MdlAddress
= Mdl
;
1083 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1084 Irp
->UserIosb
= StatusBlock
;
1085 Irp
->UserEvent
= Event
;
1086 Irp
->RequestorMode
= KernelMode
;
1087 Irp
->Flags
= IRP_PAGING_IO
|
1089 IRP_SYNCHRONOUS_PAGING_IO
|
1090 IRP_INPUT_OPERATION
;
1091 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1092 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1094 /* Set the Stack Settings */
1095 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
1096 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
1097 StackPtr
->MajorFunction
= IRP_MJ_READ
;
1098 StackPtr
->FileObject
= FileObject
;
1100 /* Call the Driver */
1101 return IoCallDriver(DeviceObject
, Irp
);
1109 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1110 IN FILE_INFORMATION_CLASS FileInformationClass
,
1112 OUT PVOID FileInformation
,
1113 OUT PULONG ReturnedLength
)
1115 /* Call the shared routine */
1116 return IopQueryDeviceInformation(FileObject
,
1117 FileInformationClass
,
1129 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
1130 IN FS_INFORMATION_CLASS FsInformationClass
,
1132 OUT PVOID FsInformation
,
1133 OUT PULONG ReturnedLength
)
1135 /* Call the shared routine */
1136 return IopQueryDeviceInformation(FileObject
,
1149 IoSetInformation(IN PFILE_OBJECT FileObject
,
1150 IN FILE_INFORMATION_CLASS FileInformationClass
,
1152 IN PVOID FileInformation
)
1154 IO_STATUS_BLOCK IoStatusBlock
;
1156 PDEVICE_OBJECT DeviceObject
;
1157 PIO_STACK_LOCATION StackPtr
;
1158 BOOLEAN LocalEvent
= FALSE
;
1162 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
1163 FileObject
, FileInformationClass
, Length
);
1165 /* Reference the object */
1166 ObReferenceObject(FileObject
);
1168 /* Check if this is a file that was opened for Synch I/O */
1169 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1172 IopLockFileObject(FileObject
);
1174 /* Use File Object event */
1175 KeClearEvent(&FileObject
->Event
);
1179 /* Use local event */
1180 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1184 /* Get the Device Object */
1185 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1187 /* Allocate the IRP */
1188 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1189 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1192 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1193 Irp
->RequestorMode
= KernelMode
;
1194 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1195 Irp
->UserIosb
= &IoStatusBlock
;
1196 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1197 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1198 Irp
->Flags
|= IRP_BUFFERED_IO
;
1199 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1200 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1202 /* Set the Stack Data */
1203 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1204 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
1205 StackPtr
->FileObject
= FileObject
;
1207 /* Set Parameters */
1208 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
1209 StackPtr
->Parameters
.SetFile
.Length
= Length
;
1212 IopQueueIrpToThread(Irp
);
1214 /* Call the Driver */
1215 Status
= IoCallDriver(DeviceObject
, Irp
);
1217 /* Check if this was synch I/O */
1220 /* Check if the request is pending */
1221 if (Status
== STATUS_PENDING
)
1223 /* Wait on the file object */
1224 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1227 (FileObject
->Flags
&
1228 FO_ALERTABLE_IO
) != 0,
1230 if (Status
== STATUS_ALERTED
)
1232 /* Abort the operation */
1233 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1236 /* Get the final status */
1237 Status
= FileObject
->FinalStatus
;
1240 /* Release the file lock */
1241 IopUnlockFileObject(FileObject
);
1243 else if (Status
== STATUS_PENDING
)
1245 /* Wait on the local event and get the final status */
1246 KeWaitForSingleObject(&Event
,
1251 Status
= IoStatusBlock
.Status
;
1254 /* Return the status */
1258 /* NATIVE SERVICES ***********************************************************/
1265 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1266 IN HANDLE Event OPTIONAL
,
1267 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1268 IN PVOID UserApcContext OPTIONAL
,
1269 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1270 IN ULONG IoControlCode
,
1271 IN PVOID InputBuffer
,
1272 IN ULONG InputBufferLength OPTIONAL
,
1273 OUT PVOID OutputBuffer
,
1274 IN ULONG OutputBufferLength OPTIONAL
)
1276 /* Call the Generic Function */
1277 return IopDeviceFsIoControl(DeviceHandle
,
1295 NtFsControlFile(IN HANDLE DeviceHandle
,
1296 IN HANDLE Event OPTIONAL
,
1297 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1298 IN PVOID UserApcContext OPTIONAL
,
1299 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1300 IN ULONG IoControlCode
,
1301 IN PVOID InputBuffer
,
1302 IN ULONG InputBufferLength OPTIONAL
,
1303 OUT PVOID OutputBuffer
,
1304 IN ULONG OutputBufferLength OPTIONAL
)
1306 /* Call the Generic Function */
1307 return IopDeviceFsIoControl(DeviceHandle
,
1322 NtFlushBuffersFile(IN HANDLE FileHandle
,
1323 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1325 PFILE_OBJECT FileObject
;
1327 PIO_STACK_LOCATION StackPtr
;
1329 PDEVICE_OBJECT DeviceObject
;
1330 PKEVENT Event
= NULL
;
1331 BOOLEAN LocalEvent
= FALSE
;
1332 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1333 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1334 IO_STATUS_BLOCK KernelIosb
;
1336 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1338 if (PreviousMode
!= KernelMode
)
1340 /* Protect probes */
1343 /* Probe the I/O Status block */
1344 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1346 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1348 /* Return the exception code */
1349 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1354 /* Get the File Object */
1355 Status
= ObReferenceObjectByHandle(FileHandle
,
1359 (PVOID
*)&FileObject
,
1361 if (!NT_SUCCESS(Status
)) return Status
;
1364 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1365 * granted. However, if this is a named pipe, make sure we don't ask for
1366 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1369 if (!(ObjectHandleInfo
.GrantedAccess
&
1370 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1374 ObDereferenceObject(FileObject
);
1375 return STATUS_ACCESS_DENIED
;
1378 /* Check if we should use Sync IO or not */
1379 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1382 IopLockFileObject(FileObject
);
1386 /* Use local event */
1387 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1391 ObDereferenceObject(FileObject
);
1392 return STATUS_INSUFFICIENT_RESOURCES
;
1394 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1398 /* Get the Device Object */
1399 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1401 /* Clear the event */
1402 KeClearEvent(&FileObject
->Event
);
1404 /* Allocate the IRP */
1405 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1406 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1408 /* Set up the IRP */
1409 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1410 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1411 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1412 Irp
->RequestorMode
= PreviousMode
;
1413 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1414 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1415 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1417 /* Set up Stack Data */
1418 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1419 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1420 StackPtr
->FileObject
= FileObject
;
1422 /* Call the Driver */
1423 Status
= IopPerformSynchronousRequest(DeviceObject
,
1431 /* Check if this was async I/O */
1434 /* It was, finalize this request */
1435 Status
= IopFinalizeAsynchronousIo(Status
,
1443 /* Return the Status */
1452 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1453 IN HANDLE EventHandle OPTIONAL
,
1454 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1455 IN PVOID ApcContext OPTIONAL
,
1456 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1458 IN ULONG BufferSize
,
1459 IN ULONG CompletionFilter
,
1460 IN BOOLEAN WatchTree
)
1463 PKEVENT Event
= NULL
;
1464 PDEVICE_OBJECT DeviceObject
;
1465 PFILE_OBJECT FileObject
;
1466 PIO_STACK_LOCATION IoStack
;
1467 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1469 BOOLEAN LockedForSync
= FALSE
;
1471 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1473 /* Check if we're called from user mode */
1474 if (PreviousMode
!= KernelMode
)
1476 /* Enter SEH for probing */
1479 /* Probe the I/O STatus block */
1480 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1482 /* Probe the buffer */
1483 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1485 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1487 /* Return the exception code */
1488 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1492 /* Check if CompletionFilter is valid */
1493 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1495 return STATUS_INVALID_PARAMETER
;
1499 /* Get File Object */
1500 Status
= ObReferenceObjectByHandle(FileHandle
,
1501 FILE_LIST_DIRECTORY
,
1504 (PVOID
*)&FileObject
,
1506 if (!NT_SUCCESS(Status
)) return Status
;
1508 /* Check if we have an event handle */
1512 Status
= ObReferenceObjectByHandle(EventHandle
,
1518 if (Status
!= STATUS_SUCCESS
)
1520 ObDereferenceObject(FileObject
);
1523 KeClearEvent(Event
);
1526 /* Check if we should use Sync IO or not */
1527 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1530 IopLockFileObject(FileObject
);
1531 LockedForSync
= TRUE
;
1534 /* Clear File Object event */
1535 KeClearEvent(&FileObject
->Event
);
1537 /* Get the device object */
1538 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1540 /* Allocate the IRP */
1541 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1542 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1544 /* Set up the IRP */
1545 Irp
->RequestorMode
= PreviousMode
;
1546 Irp
->UserIosb
= IoStatusBlock
;
1547 Irp
->UserEvent
= Event
;
1548 Irp
->UserBuffer
= Buffer
;
1549 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1550 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1551 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1552 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1554 /* Set up Stack Data */
1555 IoStack
= IoGetNextIrpStackLocation(Irp
);
1556 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1557 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1558 IoStack
->FileObject
= FileObject
;
1560 /* Set parameters */
1561 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1562 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1563 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1565 /* Perform the call */
1566 return IopPerformSynchronousRequest(DeviceObject
,
1580 NtLockFile(IN HANDLE FileHandle
,
1581 IN HANDLE EventHandle OPTIONAL
,
1582 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1583 IN PVOID ApcContext OPTIONAL
,
1584 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1585 IN PLARGE_INTEGER ByteOffset
,
1586 IN PLARGE_INTEGER Length
,
1588 IN BOOLEAN FailImmediately
,
1589 IN BOOLEAN ExclusiveLock
)
1591 PFILE_OBJECT FileObject
;
1592 PLARGE_INTEGER LocalLength
= NULL
;
1594 PIO_STACK_LOCATION StackPtr
;
1595 PDEVICE_OBJECT DeviceObject
;
1596 PKEVENT Event
= NULL
;
1597 BOOLEAN LockedForSync
= FALSE
;
1598 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1599 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1601 OBJECT_HANDLE_INFORMATION HandleInformation
;
1602 PFAST_IO_DISPATCH FastIoDispatch
;
1604 CapturedByteOffset
.QuadPart
= 0;
1605 CapturedLength
.QuadPart
= 0;
1606 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1608 /* Get File Object */
1609 Status
= ObReferenceObjectByHandle(FileHandle
,
1613 (PVOID
*)&FileObject
,
1614 &HandleInformation
);
1615 if (!NT_SUCCESS(Status
)) return Status
;
1617 /* Check if we're called from user mode */
1618 if (PreviousMode
!= KernelMode
)
1620 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1621 if (!(HandleInformation
.GrantedAccess
&
1622 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1624 ObDereferenceObject(FileObject
);
1625 return STATUS_ACCESS_DENIED
;
1628 /* Enter SEH for probing */
1631 /* Probe the I/O STatus block */
1632 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1634 /* Probe and capture the large integers */
1635 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1636 CapturedLength
= ProbeForReadLargeInteger(Length
);
1638 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1640 /* Dereference the object and return exception code */
1641 ObDereferenceObject(FileObject
);
1642 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1648 /* Otherwise, capture them directly */
1649 CapturedByteOffset
= *ByteOffset
;
1650 CapturedLength
= *Length
;
1653 /* Check if we have an event handle */
1657 Status
= ObReferenceObjectByHandle(EventHandle
,
1663 if (Status
!= STATUS_SUCCESS
) return Status
;
1664 KeClearEvent(Event
);
1667 /* Get the device object */
1668 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1670 /* Try to do it the FastIO way if possible */
1671 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1672 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoLock
!= NULL
)
1674 IO_STATUS_BLOCK KernelIosb
;
1676 if (FastIoDispatch
->FastIoLock(FileObject
,
1677 &CapturedByteOffset
,
1679 PsGetCurrentProcess(),
1686 /* Write the IOSB back */
1689 *IoStatusBlock
= KernelIosb
;
1691 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1693 KernelIosb
.Status
= _SEH2_GetExceptionCode();
1697 /* If we had an event, signal it */
1700 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1701 ObDereferenceObject(Event
);
1704 /* Set completion if required */
1705 if (FileObject
->CompletionContext
!= NULL
&& ApcContext
!= NULL
)
1707 if (!NT_SUCCESS(IoSetIoCompletion(FileObject
->CompletionContext
->Port
,
1708 FileObject
->CompletionContext
->Key
,
1711 KernelIosb
.Information
,
1714 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1718 FileObject
->LockOperation
= TRUE
;
1720 /* We're done with FastIO! */
1721 ObDereferenceObject(FileObject
);
1722 return KernelIosb
.Status
;
1726 /* Check if we should use Sync IO or not */
1727 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1730 IopLockFileObject(FileObject
);
1731 LockedForSync
= TRUE
;
1734 /* Clear File Object event */
1735 KeClearEvent(&FileObject
->Event
);
1736 FileObject
->LockOperation
= TRUE
;
1738 /* Allocate the IRP */
1739 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1740 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1742 /* Set up the IRP */
1743 Irp
->RequestorMode
= PreviousMode
;
1744 Irp
->UserIosb
= IoStatusBlock
;
1745 Irp
->UserEvent
= Event
;
1746 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1747 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1748 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1749 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1751 /* Set up Stack Data */
1752 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1753 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1754 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1755 StackPtr
->FileObject
= FileObject
;
1757 /* Allocate local buffer */
1758 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1759 sizeof(LARGE_INTEGER
),
1763 /* Allocating failed, clean up and return failure */
1764 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1765 return STATUS_INSUFFICIENT_RESOURCES
;
1768 /* Set the length */
1769 *LocalLength
= CapturedLength
;
1770 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1771 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1773 /* Set Parameters */
1774 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1775 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1778 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1779 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1781 /* Perform the call */
1782 return IopPerformSynchronousRequest(DeviceObject
,
1796 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1797 IN HANDLE EventHandle OPTIONAL
,
1798 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1799 IN PVOID ApcContext OPTIONAL
,
1800 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1801 OUT PVOID FileInformation
,
1803 IN FILE_INFORMATION_CLASS FileInformationClass
,
1804 IN BOOLEAN ReturnSingleEntry
,
1805 IN PUNICODE_STRING FileName OPTIONAL
,
1806 IN BOOLEAN RestartScan
)
1809 PDEVICE_OBJECT DeviceObject
;
1810 PFILE_OBJECT FileObject
;
1811 PIO_STACK_LOCATION StackPtr
;
1812 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1814 BOOLEAN LockedForSynch
= FALSE
;
1815 PKEVENT Event
= NULL
;
1816 volatile PVOID AuxBuffer
= NULL
;
1818 UNICODE_STRING CapturedFileName
;
1819 PUNICODE_STRING SearchPattern
;
1821 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1823 /* Check if we came from user mode */
1824 if (PreviousMode
!= KernelMode
)
1826 /* Enter SEH for probing */
1829 /* Probe the I/O Status Block */
1830 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1832 /* Probe the file information */
1833 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1835 /* Check if we have a file name */
1839 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1840 if (CapturedFileName
.Length
)
1842 /* Probe its buffer */
1843 ProbeForRead(CapturedFileName
.Buffer
,
1844 CapturedFileName
.Length
,
1848 /* Allocate the auxiliary buffer */
1849 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1850 CapturedFileName
.Length
+
1851 sizeof(UNICODE_STRING
),
1853 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1854 sizeof(UNICODE_STRING
)),
1855 CapturedFileName
.Buffer
,
1856 CapturedFileName
.Length
);
1858 /* Setup the search pattern */
1859 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1860 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1861 sizeof(UNICODE_STRING
));
1862 SearchPattern
->Length
= CapturedFileName
.Length
;
1863 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1866 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1868 /* Free buffer and return the exception code */
1869 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1870 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1875 /* Get File Object */
1876 Status
= ObReferenceObjectByHandle(FileHandle
,
1877 FILE_LIST_DIRECTORY
,
1880 (PVOID
*)&FileObject
,
1882 if (!NT_SUCCESS(Status
))
1885 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1889 /* Check if we have an even handle */
1892 /* Get its pointer */
1893 Status
= ObReferenceObjectByHandle(EventHandle
,
1899 if (!NT_SUCCESS(Status
))
1902 ObDereferenceObject(FileObject
);
1907 KeClearEvent(Event
);
1910 /* Check if this is a file that was opened for Synch I/O */
1911 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1914 IopLockFileObject(FileObject
);
1916 /* Remember to unlock later */
1917 LockedForSynch
= TRUE
;
1920 /* Get the device object */
1921 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1923 /* Clear the File Object's event */
1924 KeClearEvent(&FileObject
->Event
);
1926 /* Allocate the IRP */
1927 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1928 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1930 /* Set up the IRP */
1931 Irp
->RequestorMode
= PreviousMode
;
1932 Irp
->UserIosb
= IoStatusBlock
;
1933 Irp
->UserEvent
= Event
;
1934 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1935 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1936 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1937 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1938 Irp
->MdlAddress
= NULL
;
1939 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1940 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1942 /* Check if this is buffered I/O */
1943 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1945 /* Allocate a buffer */
1946 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1949 if (!Irp
->AssociatedIrp
.SystemBuffer
)
1951 /* Allocating failed, clean up and return the exception code */
1952 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1953 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1955 /* Return the exception code */
1956 return STATUS_INSUFFICIENT_RESOURCES
;
1959 /* Set the buffer and flags */
1960 Irp
->UserBuffer
= FileInformation
;
1961 Irp
->Flags
= (IRP_BUFFERED_IO
|
1962 IRP_DEALLOCATE_BUFFER
|
1963 IRP_INPUT_OPERATION
);
1965 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1969 /* Allocate an MDL */
1970 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1971 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1972 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1974 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1976 /* Allocating failed, clean up and return the exception code */
1977 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1978 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1984 /* No allocation flags, and use the buffer directly */
1985 Irp
->UserBuffer
= FileInformation
;
1988 /* Set up Stack Data */
1989 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1990 StackPtr
->FileObject
= FileObject
;
1991 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1992 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1994 /* Set Parameters */
1995 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1996 FileInformationClass
;
1997 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1998 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1999 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2000 StackPtr
->Flags
= 0;
2001 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2002 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2004 /* Set deferred I/O */
2005 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
2007 /* Perform the call */
2008 return IopPerformSynchronousRequest(DeviceObject
,
2022 NtQueryEaFile(IN HANDLE FileHandle
,
2023 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2026 IN BOOLEAN ReturnSingleEntry
,
2027 IN PVOID EaList OPTIONAL
,
2028 IN ULONG EaListLength
,
2029 IN PULONG EaIndex OPTIONAL
,
2030 IN BOOLEAN RestartScan
)
2033 return STATUS_NOT_IMPLEMENTED
;
2041 NtQueryInformationFile(IN HANDLE FileHandle
,
2042 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2043 IN PVOID FileInformation
,
2045 IN FILE_INFORMATION_CLASS FileInformationClass
)
2047 OBJECT_HANDLE_INFORMATION HandleInformation
;
2048 PFILE_OBJECT FileObject
;
2051 PDEVICE_OBJECT DeviceObject
;
2052 PIO_STACK_LOCATION StackPtr
;
2053 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2054 PKEVENT Event
= NULL
;
2055 BOOLEAN LocalEvent
= FALSE
;
2056 PKNORMAL_ROUTINE NormalRoutine
;
2057 PVOID NormalContext
;
2059 IO_STATUS_BLOCK KernelIosb
;
2060 BOOLEAN CallDriver
= TRUE
;
2061 PFILE_ACCESS_INFORMATION AccessBuffer
;
2062 PFILE_MODE_INFORMATION ModeBuffer
;
2063 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer
;
2064 PFILE_ALL_INFORMATION AllBuffer
;
2065 PFAST_IO_DISPATCH FastIoDispatch
;
2067 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2069 /* Check if we're called from user mode */
2070 if (PreviousMode
!= KernelMode
)
2072 /* Validate the information class */
2073 if ((FileInformationClass
>= FileMaximumInformation
) ||
2074 !(IopQueryOperationLength
[FileInformationClass
]))
2077 return STATUS_INVALID_INFO_CLASS
;
2080 /* Validate the length */
2081 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2083 /* Invalid length */
2084 return STATUS_INFO_LENGTH_MISMATCH
;
2087 /* Enter SEH for probing */
2090 /* Probe the I/O Status block */
2091 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2093 /* Probe the information */
2094 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2096 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2098 /* Return the exception code */
2099 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2105 /* Validate the information class */
2106 if ((FileInformationClass
>= FileMaximumInformation
) ||
2107 !(IopQueryOperationLength
[FileInformationClass
]))
2110 return STATUS_INVALID_INFO_CLASS
;
2113 /* Validate the length */
2114 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2116 /* Invalid length */
2117 return STATUS_INFO_LENGTH_MISMATCH
;
2121 /* Reference the Handle */
2122 Status
= ObReferenceObjectByHandle(FileHandle
,
2123 IopQueryOperationAccess
2124 [FileInformationClass
],
2127 (PVOID
*)&FileObject
,
2128 &HandleInformation
);
2129 if (!NT_SUCCESS(Status
)) return Status
;
2131 /* Check if this is a direct open or not */
2132 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2134 /* Get the device object */
2135 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2139 /* Get the device object */
2140 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2143 /* Check if this is a file that was opened for Synch I/O */
2144 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2147 IopLockFileObject(FileObject
);
2149 /* Check if the caller just wants the position */
2150 if (FileInformationClass
== FilePositionInformation
)
2152 /* Protect write in SEH */
2155 /* Write the offset */
2156 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2157 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2159 /* Fill out the I/O Status Block */
2160 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2161 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2163 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2165 /* Get the exception code */
2166 Status
= _SEH2_GetExceptionCode();
2170 /* Release the file lock, dereference the file and return */
2171 IopUnlockFileObject(FileObject
);
2172 ObDereferenceObject(FileObject
);
2178 /* Use local event */
2179 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2182 ObDereferenceObject(FileObject
);
2183 return STATUS_INSUFFICIENT_RESOURCES
;
2185 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2189 /* Check if FastIO is possible for the two available information classes */
2190 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2191 if (FastIoDispatch
!= NULL
&&
2192 ((FileInformationClass
== FileBasicInformation
&& FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
) ||
2193 (FileInformationClass
== FileStandardInformation
&& FastIoDispatch
->FastIoQueryStandardInfo
!= NULL
)))
2195 BOOLEAN Success
= FALSE
;
2197 if (FileInformationClass
== FileBasicInformation
)
2199 Success
= FastIoDispatch
->FastIoQueryBasicInfo(FileObject
, TRUE
,
2206 Success
= FastIoDispatch
->FastIoQueryStandardInfo(FileObject
, TRUE
,
2212 /* If call succeed */
2215 /* Write the IOSB back */
2218 *IoStatusBlock
= KernelIosb
;
2220 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2222 KernelIosb
.Status
= _SEH2_GetExceptionCode();
2227 IopUnlockFileObject(FileObject
);
2229 /* We're done with FastIO! */
2230 ObDereferenceObject(FileObject
);
2231 return KernelIosb
.Status
;
2235 /* Clear the File Object event */
2236 KeClearEvent(&FileObject
->Event
);
2238 /* Allocate the IRP */
2239 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2240 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2243 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2244 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2245 Irp
->RequestorMode
= PreviousMode
;
2246 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2247 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2248 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2249 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2250 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2251 Irp
->MdlAddress
= NULL
;
2252 Irp
->UserBuffer
= FileInformation
;
2254 /* Set the Stack Data */
2255 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2256 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2257 StackPtr
->FileObject
= FileObject
;
2262 /* Allocate a buffer */
2263 Irp
->AssociatedIrp
.SystemBuffer
=
2264 ExAllocatePoolWithTag(NonPagedPool
,
2268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2270 /* Allocating failed, clean up and return the exception code */
2271 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2272 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2277 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2278 IRP_DEALLOCATE_BUFFER
|
2279 IRP_INPUT_OPERATION
|
2280 IRP_DEFER_IO_COMPLETION
);
2282 /* Set the Parameters */
2283 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2284 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2287 IopQueueIrpToThread(Irp
);
2289 /* Update operation counts */
2290 IopUpdateOperationCount(IopOtherTransfer
);
2292 /* Fill in file information before calling the driver.
2293 See 'File System Internals' page 485.*/
2294 if (FileInformationClass
== FileAccessInformation
)
2296 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2297 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2298 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2301 else if (FileInformationClass
== FileModeInformation
)
2303 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2304 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2305 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2308 else if (FileInformationClass
== FileAlignmentInformation
)
2310 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2311 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2312 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2315 else if (FileInformationClass
== FileAllInformation
)
2317 AllBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2318 AllBuffer
->AccessInformation
.AccessFlags
= HandleInformation
.GrantedAccess
;
2319 AllBuffer
->ModeInformation
.Mode
= IopGetFileMode(FileObject
);
2320 AllBuffer
->AlignmentInformation
.AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2321 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
) +
2322 sizeof(FILE_MODE_INFORMATION
) +
2323 sizeof(FILE_ALIGNMENT_INFORMATION
);
2326 /* Call the Driver */
2329 Status
= IoCallDriver(DeviceObject
, Irp
);
2333 Status
= STATUS_SUCCESS
;
2334 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2337 if (Status
== STATUS_PENDING
)
2339 /* Check if this was async I/O */
2342 /* Then to a non-alertable wait */
2343 Status
= KeWaitForSingleObject(Event
,
2348 if (Status
== STATUS_USER_APC
)
2350 /* Abort the request */
2351 IopAbortInterruptedIrp(Event
, Irp
);
2354 /* Set the final status */
2355 Status
= KernelIosb
.Status
;
2357 /* Enter SEH to write the IOSB back */
2360 /* Write it back to the caller */
2361 *IoStatusBlock
= KernelIosb
;
2363 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2365 /* Get the exception code */
2366 Status
= _SEH2_GetExceptionCode();
2370 /* Free the event */
2371 ExFreePoolWithTag(Event
, TAG_IO
);
2375 /* Wait for the IRP */
2376 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2379 (FileObject
->Flags
&
2380 FO_ALERTABLE_IO
) != 0,
2382 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2384 /* Abort the request */
2385 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2388 /* Set the final status */
2389 Status
= FileObject
->FinalStatus
;
2391 /* Release the file lock */
2392 IopUnlockFileObject(FileObject
);
2397 /* Free the event if we had one */
2400 /* Clear it in the IRP for completion */
2401 Irp
->UserEvent
= NULL
;
2402 ExFreePoolWithTag(Event
, TAG_IO
);
2405 /* Set the caller IOSB */
2406 Irp
->UserIosb
= IoStatusBlock
;
2408 /* The IRP wasn't completed, complete it ourselves */
2409 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2410 IopCompleteRequest(&Irp
->Tail
.Apc
,
2413 (PVOID
*)&FileObject
,
2415 KeLowerIrql(OldIrql
);
2417 /* Release the file object if we had locked it*/
2418 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2421 /* Return the Status */
2430 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2431 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2434 IN BOOLEAN ReturnSingleEntry
,
2435 IN PVOID SidList OPTIONAL
,
2436 IN ULONG SidListLength
,
2437 IN PSID StartSid OPTIONAL
,
2438 IN BOOLEAN RestartScan
)
2441 return STATUS_NOT_IMPLEMENTED
;
2449 NtReadFile(IN HANDLE FileHandle
,
2450 IN HANDLE Event OPTIONAL
,
2451 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2452 IN PVOID ApcContext OPTIONAL
,
2453 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2456 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2457 IN PULONG Key OPTIONAL
)
2460 PFILE_OBJECT FileObject
;
2462 PDEVICE_OBJECT DeviceObject
;
2463 PIO_STACK_LOCATION StackPtr
;
2464 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2465 PKEVENT EventObject
= NULL
;
2466 LARGE_INTEGER CapturedByteOffset
;
2467 ULONG CapturedKey
= 0;
2468 BOOLEAN Synchronous
= FALSE
;
2470 PFAST_IO_DISPATCH FastIoDispatch
;
2471 IO_STATUS_BLOCK KernelIosb
;
2475 CapturedByteOffset
.QuadPart
= 0;
2476 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2478 /* Validate User-Mode Buffers */
2479 if (PreviousMode
!= KernelMode
)
2483 /* Probe the status block */
2484 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2486 /* Probe the read buffer */
2487 ProbeForWrite(Buffer
, Length
, 1);
2489 /* Check if we got a byte offset */
2492 /* Capture and probe it */
2493 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2496 /* Capture and probe the key */
2497 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2499 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2501 /* Return the exception code */
2502 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2508 /* Kernel mode: capture directly */
2509 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2510 if (Key
) CapturedKey
= *Key
;
2513 /* Get File Object */
2514 Status
= ObReferenceObjectByHandle(FileHandle
,
2518 (PVOID
*)&FileObject
,
2520 if (!NT_SUCCESS(Status
)) return Status
;
2522 /* Check for event */
2526 Status
= ObReferenceObjectByHandle(Event
,
2530 (PVOID
*)&EventObject
,
2532 if (!NT_SUCCESS(Status
))
2535 ObDereferenceObject(FileObject
);
2539 /* Otherwise reset the event */
2540 KeClearEvent(EventObject
);
2543 /* Get the device object */
2544 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2546 /* Check if we should use Sync IO or not */
2547 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2549 /* Lock the file object */
2550 IopLockFileObject(FileObject
);
2552 /* Check if we don't have a byte offset available */
2553 if (!(ByteOffset
) ||
2554 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2555 (CapturedByteOffset
.u
.HighPart
== -1)))
2557 /* Use the Current Byte Offset instead */
2558 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2561 /* If the file is cached, try fast I/O */
2562 if (FileObject
->PrivateCacheMap
)
2564 /* Perform fast read */
2565 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2566 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoRead
!= NULL
);
2568 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2569 &CapturedByteOffset
,
2577 /* Only accept the result if we got a straightforward status */
2579 (KernelIosb
.Status
== STATUS_SUCCESS
||
2580 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2581 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2583 /* Fast path -- update transfer & operation counts */
2584 IopUpdateOperationCount(IopReadTransfer
);
2585 IopUpdateTransferCount(IopReadTransfer
,
2586 (ULONG
)KernelIosb
.Information
);
2588 /* Enter SEH to write the IOSB back */
2591 /* Write it back to the caller */
2592 *IoStatusBlock
= KernelIosb
;
2594 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2596 /* The caller's IOSB was invalid, so fail */
2597 if (EventObject
) ObDereferenceObject(EventObject
);
2598 IopUnlockFileObject(FileObject
);
2599 ObDereferenceObject(FileObject
);
2600 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2604 /* Signal the completion event */
2607 KeSetEvent(EventObject
, 0, FALSE
);
2608 ObDereferenceObject(EventObject
);
2612 IopUnlockFileObject(FileObject
);
2613 ObDereferenceObject(FileObject
);
2614 return KernelIosb
.Status
;
2618 /* Remember we are sync */
2621 else if (!(ByteOffset
) &&
2622 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2624 /* Otherwise, this was async I/O without a byte offset, so fail */
2625 if (EventObject
) ObDereferenceObject(EventObject
);
2626 ObDereferenceObject(FileObject
);
2627 return STATUS_INVALID_PARAMETER
;
2630 /* Clear the File Object's event */
2631 KeClearEvent(&FileObject
->Event
);
2633 /* Allocate the IRP */
2634 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2635 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2638 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2639 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2640 Irp
->RequestorMode
= PreviousMode
;
2641 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2642 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2643 Irp
->UserIosb
= IoStatusBlock
;
2644 Irp
->UserEvent
= EventObject
;
2645 Irp
->PendingReturned
= FALSE
;
2646 Irp
->Cancel
= FALSE
;
2647 Irp
->CancelRoutine
= NULL
;
2648 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2649 Irp
->MdlAddress
= NULL
;
2651 /* Set the Stack Data */
2652 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2653 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2654 StackPtr
->FileObject
= FileObject
;
2655 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2656 StackPtr
->Parameters
.Read
.Length
= Length
;
2657 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2659 /* Check if this is buffered I/O */
2660 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2662 /* Check if we have a buffer length */
2668 /* Allocate a buffer */
2669 Irp
->AssociatedIrp
.SystemBuffer
=
2670 ExAllocatePoolWithTag(NonPagedPool
,
2674 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2676 /* Allocating failed, clean up and return the exception code */
2677 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2678 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2682 /* Set the buffer and flags */
2683 Irp
->UserBuffer
= Buffer
;
2684 Irp
->Flags
= (IRP_BUFFERED_IO
|
2685 IRP_DEALLOCATE_BUFFER
|
2686 IRP_INPUT_OPERATION
);
2690 /* Not reading anything */
2691 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2694 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2696 /* Check if we have a buffer length */
2701 /* Allocate an MDL */
2702 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2704 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2705 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2707 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2709 /* Allocating failed, clean up and return the exception code */
2710 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2711 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2717 /* No allocation flags */
2722 /* No allocation flags, and use the buffer directly */
2724 Irp
->UserBuffer
= Buffer
;
2727 /* Now set the deferred read flags */
2728 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2730 /* FIXME: VFAT SUCKS */
2731 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2734 /* Perform the call */
2735 return IopPerformSynchronousRequest(DeviceObject
,
2749 NtReadFileScatter(IN HANDLE FileHandle
,
2750 IN HANDLE Event OPTIONAL
,
2751 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2752 IN PVOID UserApcContext OPTIONAL
,
2753 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2754 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2755 IN ULONG BufferLength
,
2756 IN PLARGE_INTEGER ByteOffset
,
2757 IN PULONG Key OPTIONAL
)
2760 return STATUS_NOT_IMPLEMENTED
;
2768 NtSetEaFile(IN HANDLE FileHandle
,
2769 IN PIO_STATUS_BLOCK IoStatusBlock
,
2771 IN ULONG EaBufferSize
)
2774 return STATUS_NOT_IMPLEMENTED
;
2782 NtSetInformationFile(IN HANDLE FileHandle
,
2783 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2784 IN PVOID FileInformation
,
2786 IN FILE_INFORMATION_CLASS FileInformationClass
)
2788 PFILE_OBJECT FileObject
;
2791 PDEVICE_OBJECT DeviceObject
;
2792 PIO_STACK_LOCATION StackPtr
;
2793 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2794 PKEVENT Event
= NULL
;
2795 BOOLEAN LocalEvent
= FALSE
;
2796 PKNORMAL_ROUTINE NormalRoutine
;
2797 PVOID NormalContext
;
2799 IO_STATUS_BLOCK KernelIosb
;
2801 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2802 PIO_COMPLETION_CONTEXT Context
;
2803 PFILE_RENAME_INFORMATION RenameInfo
;
2804 HANDLE TargetHandle
= NULL
;
2806 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2808 /* Check if we're called from user mode */
2809 if (PreviousMode
!= KernelMode
)
2811 /* Validate the information class */
2812 if ((FileInformationClass
>= FileMaximumInformation
) ||
2813 !(IopSetOperationLength
[FileInformationClass
]))
2816 return STATUS_INVALID_INFO_CLASS
;
2819 /* Validate the length */
2820 if (Length
< IopSetOperationLength
[FileInformationClass
])
2822 /* Invalid length */
2823 return STATUS_INFO_LENGTH_MISMATCH
;
2826 /* Enter SEH for probing */
2829 /* Probe the I/O Status block */
2830 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2832 /* Probe the information */
2833 ProbeForRead(FileInformation
,
2835 (Length
== sizeof(BOOLEAN
)) ?
2836 sizeof(BOOLEAN
) : sizeof(ULONG
));
2838 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2840 /* Return the exception code */
2841 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2847 /* Validate the information class */
2848 if ((FileInformationClass
>= FileMaximumInformation
) ||
2849 !(IopSetOperationLength
[FileInformationClass
]))
2852 return STATUS_INVALID_INFO_CLASS
;
2855 /* Validate the length */
2856 if (Length
< IopSetOperationLength
[FileInformationClass
])
2858 /* Invalid length */
2859 return STATUS_INFO_LENGTH_MISMATCH
;
2863 /* Reference the Handle */
2864 Status
= ObReferenceObjectByHandle(FileHandle
,
2865 IopSetOperationAccess
2866 [FileInformationClass
],
2869 (PVOID
*)&FileObject
,
2871 if (!NT_SUCCESS(Status
)) return Status
;
2873 /* Check if this is a direct open or not */
2874 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2876 /* Get the device object */
2877 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2881 /* Get the device object */
2882 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2885 DPRINT("Will call: %p\n", DeviceObject
);
2886 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
2888 /* Check if this is a file that was opened for Synch I/O */
2889 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2892 IopLockFileObject(FileObject
);
2894 /* Check if the caller just wants the position */
2895 if (FileInformationClass
== FilePositionInformation
)
2897 /* Protect write in SEH */
2900 /* Write the offset */
2901 FileObject
->CurrentByteOffset
=
2902 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2905 /* Fill out the I/O Status Block */
2906 IoStatusBlock
->Information
= 0;
2907 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2909 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2911 /* Get the exception code */
2912 Status
= _SEH2_GetExceptionCode();
2916 /* Update transfer count */
2917 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2919 /* Release the file lock, dereference the file and return */
2920 IopUnlockFileObject(FileObject
);
2921 ObDereferenceObject(FileObject
);
2927 /* Use local event */
2928 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2931 ObDereferenceObject(FileObject
);
2932 return STATUS_INSUFFICIENT_RESOURCES
;
2935 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2939 /* Clear the File Object event */
2940 KeClearEvent(&FileObject
->Event
);
2942 /* Allocate the IRP */
2943 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2944 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2947 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2948 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2949 Irp
->RequestorMode
= PreviousMode
;
2950 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2951 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2952 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2953 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2954 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2955 Irp
->MdlAddress
= NULL
;
2956 Irp
->UserBuffer
= FileInformation
;
2958 /* Set the Stack Data */
2959 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2960 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2961 StackPtr
->FileObject
= FileObject
;
2966 /* Allocate a buffer */
2967 Irp
->AssociatedIrp
.SystemBuffer
=
2968 ExAllocatePoolWithTag(NonPagedPool
,
2972 /* Copy the data into it */
2973 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2977 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2979 /* Allocating failed, clean up and return the exception code */
2980 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2981 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2986 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2987 IRP_DEALLOCATE_BUFFER
|
2988 IRP_DEFER_IO_COMPLETION
);
2990 /* Set the Parameters */
2991 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2992 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2995 IopQueueIrpToThread(Irp
);
2997 /* Update operation counts */
2998 IopUpdateOperationCount(IopOtherTransfer
);
3000 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3001 /* Handle IO Completion Port quickly */
3002 if (FileInformationClass
== FileCompletionInformation
)
3004 /* Check if the file object already has a completion port */
3005 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3006 (FileObject
->CompletionContext
))
3009 Status
= STATUS_INVALID_PARAMETER
;
3013 /* Reference the Port */
3014 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3015 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3016 IO_COMPLETION_MODIFY_STATE
,
3021 if (NT_SUCCESS(Status
))
3023 /* Allocate the Context */
3024 Context
= ExAllocatePoolWithTag(PagedPool
,
3025 sizeof(IO_COMPLETION_CONTEXT
),
3030 Context
->Key
= CompletionInfo
->Key
;
3031 Context
->Port
= Queue
;
3032 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3038 * Someone else set the completion port in the
3039 * meanwhile, so dereference the port and fail.
3041 ExFreePoolWithTag(Context
, IOC_TAG
);
3042 ObDereferenceObject(Queue
);
3043 Status
= STATUS_INVALID_PARAMETER
;
3048 /* Dereference the Port now */
3049 ObDereferenceObject(Queue
);
3050 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3055 /* Set the IRP Status */
3056 Irp
->IoStatus
.Status
= Status
;
3057 Irp
->IoStatus
.Information
= 0;
3059 else if (FileInformationClass
== FileRenameInformation
||
3060 FileInformationClass
== FileLinkInformation
||
3061 FileInformationClass
== FileMoveClusterInformation
)
3063 /* Get associated information */
3064 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3069 * -> sizes are valid
3071 if (RenameInfo
->FileNameLength
!= 0 &&
3072 !(RenameInfo
->FileNameLength
& 1) &&
3073 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3075 /* Properly set information received */
3076 if (FileInformationClass
== FileMoveClusterInformation
)
3078 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3082 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3085 /* If we got fully path OR relative target, attempt a parent directory open */
3086 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3088 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3089 if (!NT_SUCCESS(Status
))
3091 Irp
->IoStatus
.Status
= Status
;
3095 /* Call the Driver */
3096 Status
= IoCallDriver(DeviceObject
, Irp
);
3101 /* Call the Driver */
3102 Status
= IoCallDriver(DeviceObject
, Irp
);
3107 Status
= STATUS_INVALID_PARAMETER
;
3108 Irp
->IoStatus
.Status
= Status
;
3113 /* Call the Driver */
3114 Status
= IoCallDriver(DeviceObject
, Irp
);
3117 /* Check if we're waiting for the IRP to complete */
3118 if (Status
== STATUS_PENDING
)
3120 /* Check if this was async I/O */
3123 /* Then to a non-alertable wait */
3124 Status
= KeWaitForSingleObject(Event
,
3129 if (Status
== STATUS_USER_APC
)
3131 /* Abort the request */
3132 IopAbortInterruptedIrp(Event
, Irp
);
3135 /* Set the final status */
3136 Status
= KernelIosb
.Status
;
3138 /* Enter SEH to write the IOSB back */
3141 /* Write it back to the caller */
3142 *IoStatusBlock
= KernelIosb
;
3144 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3146 /* Get the exception code */
3147 Status
= _SEH2_GetExceptionCode();
3151 /* Free the event */
3152 ExFreePoolWithTag(Event
, TAG_IO
);
3156 /* Wait for the IRP */
3157 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3160 (FileObject
->Flags
&
3161 FO_ALERTABLE_IO
) != 0,
3163 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3165 /* Abort the request */
3166 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3169 /* Set the final status */
3170 Status
= FileObject
->FinalStatus
;
3172 /* Release the file lock */
3173 IopUnlockFileObject(FileObject
);
3178 /* Free the event if we had one */
3181 /* Clear it in the IRP for completion */
3182 Irp
->UserEvent
= NULL
;
3183 ExFreePoolWithTag(Event
, TAG_IO
);
3186 /* Set the caller IOSB */
3187 Irp
->UserIosb
= IoStatusBlock
;
3189 /* The IRP wasn't completed, complete it ourselves */
3190 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3191 IopCompleteRequest(&Irp
->Tail
.Apc
,
3194 (PVOID
*)&FileObject
,
3196 KeLowerIrql(OldIrql
);
3198 /* Release the file object if we had locked it*/
3199 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3202 if (TargetHandle
!= NULL
)
3204 ObCloseHandle(TargetHandle
, KernelMode
);
3207 /* Return the Status */
3216 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3217 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3219 IN ULONG BufferLength
)
3222 return STATUS_NOT_IMPLEMENTED
;
3230 NtUnlockFile(IN HANDLE FileHandle
,
3231 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3232 IN PLARGE_INTEGER ByteOffset
,
3233 IN PLARGE_INTEGER Length
,
3234 IN ULONG Key OPTIONAL
)
3236 PFILE_OBJECT FileObject
;
3237 PLARGE_INTEGER LocalLength
= NULL
;
3239 PIO_STACK_LOCATION StackPtr
;
3240 PDEVICE_OBJECT DeviceObject
;
3241 PKEVENT Event
= NULL
;
3242 BOOLEAN LocalEvent
= FALSE
;
3243 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3244 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3246 OBJECT_HANDLE_INFORMATION HandleInformation
;
3247 IO_STATUS_BLOCK KernelIosb
;
3248 PFAST_IO_DISPATCH FastIoDispatch
;
3250 CapturedByteOffset
.QuadPart
= 0;
3251 CapturedLength
.QuadPart
= 0;
3252 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3254 /* Get File Object */
3255 Status
= ObReferenceObjectByHandle(FileHandle
,
3259 (PVOID
*)&FileObject
,
3260 &HandleInformation
);
3261 if (!NT_SUCCESS(Status
)) return Status
;
3263 /* Check if we're called from user mode */
3264 if (PreviousMode
!= KernelMode
)
3266 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3267 if (!(HandleInformation
.GrantedAccess
&
3268 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3270 ObDereferenceObject(FileObject
);
3271 return STATUS_ACCESS_DENIED
;
3274 /* Enter SEH for probing */
3277 /* Probe the I/O Status block */
3278 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3280 /* Probe and capture the large integers */
3281 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3282 CapturedLength
= ProbeForReadLargeInteger(Length
);
3284 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3286 /* Dereference the object and return exception code */
3287 ObDereferenceObject(FileObject
);
3288 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3294 /* Otherwise, capture them directly */
3295 CapturedByteOffset
= *ByteOffset
;
3296 CapturedLength
= *Length
;
3299 /* Check if this is a direct open or not */
3300 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3302 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3306 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3309 /* Try to do it the FastIO way if possible */
3310 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3311 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3313 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3314 &CapturedByteOffset
,
3316 PsGetCurrentProcess(),
3321 /* Write the IOSB back */
3324 *IoStatusBlock
= KernelIosb
;
3326 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3328 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3332 /* We're done with FastIO! */
3333 ObDereferenceObject(FileObject
);
3334 return KernelIosb
.Status
;
3338 /* Check if we should use Sync IO or not */
3339 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3342 IopLockFileObject(FileObject
);
3346 /* Use local event */
3347 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3350 ObDereferenceObject(FileObject
);
3351 return STATUS_INSUFFICIENT_RESOURCES
;
3353 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3357 /* Clear File Object event */
3358 KeClearEvent(&FileObject
->Event
);
3360 /* Allocate the IRP */
3361 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3362 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3364 /* Set up the IRP */
3365 Irp
->RequestorMode
= PreviousMode
;
3366 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3367 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3368 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3369 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3370 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3371 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3373 /* Set up Stack Data */
3374 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3375 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3376 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3377 StackPtr
->FileObject
= FileObject
;
3382 /* Allocate a buffer */
3383 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3384 sizeof(LARGE_INTEGER
),
3387 /* Set the length */
3388 *LocalLength
= CapturedLength
;
3389 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3390 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3392 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3394 /* Allocating failed, clean up and return the exception code */
3395 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3396 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3398 /* Return the exception code */
3399 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3403 /* Set Parameters */
3404 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3405 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3407 /* Call the Driver */
3408 Status
= IopPerformSynchronousRequest(DeviceObject
,
3416 /* Check if this was async I/O */
3419 /* It was, finalize this request */
3420 Status
= IopFinalizeAsynchronousIo(Status
,
3437 NtWriteFile(IN HANDLE FileHandle
,
3438 IN HANDLE Event OPTIONAL
,
3439 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3440 IN PVOID ApcContext OPTIONAL
,
3441 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3444 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3445 IN PULONG Key OPTIONAL
)
3448 PFILE_OBJECT FileObject
;
3450 PDEVICE_OBJECT DeviceObject
;
3451 PIO_STACK_LOCATION StackPtr
;
3452 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3453 PKEVENT EventObject
= NULL
;
3454 LARGE_INTEGER CapturedByteOffset
;
3455 ULONG CapturedKey
= 0;
3456 BOOLEAN Synchronous
= FALSE
;
3458 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3459 PFAST_IO_DISPATCH FastIoDispatch
;
3460 IO_STATUS_BLOCK KernelIosb
;
3464 CapturedByteOffset
.QuadPart
= 0;
3465 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3467 /* Get File Object */
3468 Status
= ObReferenceObjectByHandle(FileHandle
,
3472 (PVOID
*)&FileObject
,
3474 if (!NT_SUCCESS(Status
)) return Status
;
3476 /* Validate User-Mode Buffers */
3477 if (PreviousMode
!= KernelMode
)
3482 * Check if the handle has either FILE_WRITE_DATA or
3483 * FILE_APPEND_DATA granted. However, if this is a named pipe,
3484 * make sure we don't ask for FILE_APPEND_DATA as it interferes
3485 * with the FILE_CREATE_PIPE_INSTANCE access right!
3487 if (!(ObjectHandleInfo
.GrantedAccess
&
3488 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
3489 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
3492 ObDereferenceObject(FileObject
);
3493 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
3496 /* Probe the status block */
3497 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3499 /* Probe the read buffer */
3500 ProbeForRead(Buffer
, Length
, 1);
3502 /* Check if we got a byte offset */
3505 /* Capture and probe it */
3506 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3509 /* Capture and probe the key */
3510 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3512 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3514 /* Release the file object and return the exception code */
3515 ObDereferenceObject(FileObject
);
3516 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3522 /* Kernel mode: capture directly */
3523 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3524 if (Key
) CapturedKey
= *Key
;
3527 /* Check if this is an append operation */
3528 if ((ObjectHandleInfo
.GrantedAccess
&
3529 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3531 /* Give the drivers something to understand */
3532 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3533 CapturedByteOffset
.u
.HighPart
= -1;
3536 /* Check for event */
3540 Status
= ObReferenceObjectByHandle(Event
,
3544 (PVOID
*)&EventObject
,
3546 if (!NT_SUCCESS(Status
))
3549 ObDereferenceObject(FileObject
);
3553 /* Otherwise reset the event */
3554 KeClearEvent(EventObject
);
3557 /* Get the device object */
3558 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3560 /* Check if we should use Sync IO or not */
3561 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3563 /* Lock the file object */
3564 IopLockFileObject(FileObject
);
3566 /* Check if we don't have a byte offset available */
3567 if (!(ByteOffset
) ||
3568 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3569 (CapturedByteOffset
.u
.HighPart
== -1)))
3571 /* Use the Current Byte Offset instead */
3572 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3575 /* If the file is cached, try fast I/O */
3576 if (FileObject
->PrivateCacheMap
)
3578 /* Perform fast write */
3579 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3580 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoWrite
!= NULL
);
3582 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3583 &CapturedByteOffset
,
3591 /* Only accept the result if it was successful */
3593 KernelIosb
.Status
== STATUS_SUCCESS
)
3595 /* Fast path -- update transfer & operation counts */
3596 IopUpdateOperationCount(IopWriteTransfer
);
3597 IopUpdateTransferCount(IopWriteTransfer
,
3598 (ULONG
)KernelIosb
.Information
);
3600 /* Enter SEH to write the IOSB back */
3603 /* Write it back to the caller */
3604 *IoStatusBlock
= KernelIosb
;
3606 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3608 /* The caller's IOSB was invalid, so fail */
3609 if (EventObject
) ObDereferenceObject(EventObject
);
3610 IopUnlockFileObject(FileObject
);
3611 ObDereferenceObject(FileObject
);
3612 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3616 /* Signal the completion event */
3619 KeSetEvent(EventObject
, 0, FALSE
);
3620 ObDereferenceObject(EventObject
);
3624 IopUnlockFileObject(FileObject
);
3625 ObDereferenceObject(FileObject
);
3626 return KernelIosb
.Status
;
3630 /* Remember we are sync */
3633 else if (!(ByteOffset
) &&
3634 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3636 /* Otherwise, this was async I/O without a byte offset, so fail */
3637 if (EventObject
) ObDereferenceObject(EventObject
);
3638 ObDereferenceObject(FileObject
);
3639 return STATUS_INVALID_PARAMETER
;
3642 /* Clear the File Object's event */
3643 KeClearEvent(&FileObject
->Event
);
3645 /* Allocate the IRP */
3646 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3647 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3650 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3651 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3652 Irp
->RequestorMode
= PreviousMode
;
3653 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3654 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3655 Irp
->UserIosb
= IoStatusBlock
;
3656 Irp
->UserEvent
= EventObject
;
3657 Irp
->PendingReturned
= FALSE
;
3658 Irp
->Cancel
= FALSE
;
3659 Irp
->CancelRoutine
= NULL
;
3660 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3661 Irp
->MdlAddress
= NULL
;
3663 /* Set the Stack Data */
3664 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3665 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3666 StackPtr
->FileObject
= FileObject
;
3667 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3668 SL_WRITE_THROUGH
: 0;
3669 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3670 StackPtr
->Parameters
.Write
.Length
= Length
;
3671 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3673 /* Check if this is buffered I/O */
3674 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3676 /* Check if we have a buffer length */
3682 /* Allocate a buffer */
3683 Irp
->AssociatedIrp
.SystemBuffer
=
3684 ExAllocatePoolWithTag(NonPagedPool
,
3688 /* Copy the data into it */
3689 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3691 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3693 /* Allocating failed, clean up and return the exception code */
3694 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3695 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3700 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3704 /* Not writing anything */
3705 Irp
->Flags
= IRP_BUFFERED_IO
;
3708 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3710 /* Check if we have a buffer length */
3715 /* Allocate an MDL */
3716 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3718 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3719 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3721 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3723 /* Allocating failed, clean up and return the exception code */
3724 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3725 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3730 /* No allocation flags */
3735 /* No allocation flags, and use the buffer directly */
3737 Irp
->UserBuffer
= Buffer
;
3740 /* Now set the deferred read flags */
3741 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3743 /* FIXME: VFAT SUCKS */
3744 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3747 /* Perform the call */
3748 return IopPerformSynchronousRequest(DeviceObject
,
3759 NtWriteFileGather(IN HANDLE FileHandle
,
3760 IN HANDLE Event OPTIONAL
,
3761 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3762 IN PVOID UserApcContext OPTIONAL
,
3763 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3764 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3765 IN ULONG BufferLength
,
3766 IN PLARGE_INTEGER ByteOffset
,
3767 IN PULONG Key OPTIONAL
)
3770 return STATUS_NOT_IMPLEMENTED
;
3778 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3779 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3780 OUT PVOID FsInformation
,
3782 IN FS_INFORMATION_CLASS FsInformationClass
)
3784 PFILE_OBJECT FileObject
;
3786 PIO_STACK_LOCATION StackPtr
;
3787 PDEVICE_OBJECT DeviceObject
;
3788 PKEVENT Event
= NULL
;
3789 BOOLEAN LocalEvent
= FALSE
;
3790 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3792 IO_STATUS_BLOCK KernelIosb
;
3794 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3796 /* Check if we're called from user mode */
3797 if (PreviousMode
!= KernelMode
)
3799 /* Validate the information class */
3800 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3801 !(IopQueryFsOperationLength
[FsInformationClass
]))
3804 return STATUS_INVALID_INFO_CLASS
;
3807 /* Validate the length */
3808 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3810 /* Invalid length */
3811 return STATUS_INFO_LENGTH_MISMATCH
;
3814 /* Enter SEH for probing */
3817 /* Probe the I/O Status block */
3818 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3820 /* Probe the information */
3821 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3823 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3825 /* Return the exception code */
3826 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3831 /* Get File Object */
3832 Status
= ObReferenceObjectByHandle(FileHandle
,
3833 IopQueryFsOperationAccess
3834 [FsInformationClass
],
3837 (PVOID
*)&FileObject
,
3839 if (!NT_SUCCESS(Status
)) return Status
;
3841 /* Check if we should use Sync IO or not */
3842 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3845 IopLockFileObject(FileObject
);
3849 /* Use local event */
3850 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3853 ObDereferenceObject(FileObject
);
3854 return STATUS_INSUFFICIENT_RESOURCES
;
3856 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3860 /* Get the device object */
3861 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3863 /* Clear File Object event */
3864 KeClearEvent(&FileObject
->Event
);
3866 /* Allocate the IRP */
3867 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3868 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3870 /* Set up the IRP */
3871 Irp
->RequestorMode
= PreviousMode
;
3872 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3873 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3874 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3875 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3876 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3877 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3878 Irp
->UserBuffer
= FsInformation
;
3879 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3880 Irp
->MdlAddress
= NULL
;
3882 /* Set up Stack Data */
3883 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3884 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3885 StackPtr
->FileObject
= FileObject
;
3890 /* Allocate a buffer */
3891 Irp
->AssociatedIrp
.SystemBuffer
=
3892 ExAllocatePoolWithTag(NonPagedPool
,
3896 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3898 /* Allocating failed, clean up and return the exception code */
3899 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3900 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3904 /* Set the flags for this buffered + deferred I/O */
3905 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3906 IRP_DEALLOCATE_BUFFER
|
3907 IRP_INPUT_OPERATION
|
3908 IRP_DEFER_IO_COMPLETION
);
3910 /* Set Parameters */
3911 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3912 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3914 /* Call the Driver */
3915 Status
= IopPerformSynchronousRequest(DeviceObject
,
3923 /* Check if this was async I/O */
3926 /* It was, finalize this request */
3927 Status
= IopFinalizeAsynchronousIo(Status
,
3944 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3945 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3946 IN PVOID FsInformation
,
3948 IN FS_INFORMATION_CLASS FsInformationClass
)
3950 PFILE_OBJECT FileObject
;
3952 PIO_STACK_LOCATION StackPtr
;
3953 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3954 PKEVENT Event
= NULL
;
3955 BOOLEAN LocalEvent
= FALSE
;
3956 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3958 IO_STATUS_BLOCK KernelIosb
;
3959 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3961 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3963 /* Check if we're called from user mode */
3964 if (PreviousMode
!= KernelMode
)
3966 /* Validate the information class */
3967 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3968 !(IopSetFsOperationLength
[FsInformationClass
]))
3971 return STATUS_INVALID_INFO_CLASS
;
3974 /* Validate the length */
3975 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3977 /* Invalid length */
3978 return STATUS_INFO_LENGTH_MISMATCH
;
3981 /* Enter SEH for probing */
3984 /* Probe the I/O Status block */
3985 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3987 /* Probe the information */
3988 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3990 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3992 /* Return the exception code */
3993 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3998 /* Get File Object */
3999 Status
= ObReferenceObjectByHandle(FileHandle
,
4000 IopSetFsOperationAccess
4001 [FsInformationClass
],
4004 (PVOID
*)&FileObject
,
4006 if (!NT_SUCCESS(Status
)) return Status
;
4008 /* Get target device for notification */
4009 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4010 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4012 /* Check if we should use Sync IO or not */
4013 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4016 IopLockFileObject(FileObject
);
4020 /* Use local event */
4021 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4024 ObDereferenceObject(FileObject
);
4025 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4026 return STATUS_INSUFFICIENT_RESOURCES
;
4028 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4032 /* Get the device object */
4033 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4035 /* Clear File Object event */
4036 KeClearEvent(&FileObject
->Event
);
4038 /* Allocate the IRP */
4039 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4042 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4043 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4046 /* Set up the IRP */
4047 Irp
->RequestorMode
= PreviousMode
;
4048 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4049 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4050 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4051 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4052 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4053 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4054 Irp
->UserBuffer
= FsInformation
;
4055 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4056 Irp
->MdlAddress
= NULL
;
4058 /* Set up Stack Data */
4059 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4060 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
4061 StackPtr
->FileObject
= FileObject
;
4066 /* Allocate a buffer */
4067 Irp
->AssociatedIrp
.SystemBuffer
=
4068 ExAllocatePoolWithTag(NonPagedPool
,
4072 /* Copy the data into it */
4073 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
4075 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4077 /* Allocating failed, clean up and return the exception code */
4078 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4079 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4080 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4084 /* Set the flags for this buffered + deferred I/O */
4085 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4087 /* Set Parameters */
4088 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
4089 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
4091 /* Call the Driver */
4092 Status
= IopPerformSynchronousRequest(DeviceObject
,
4100 /* Check if this was async I/O */
4103 /* It was, finalize this request */
4104 Status
= IopFinalizeAsynchronousIo(Status
,
4112 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
4114 /* Time to report change */
4115 NotificationStructure
.Version
= 1;
4116 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
4117 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
4118 NotificationStructure
.FileObject
= NULL
;
4119 NotificationStructure
.NameBufferOffset
= - 1;
4120 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
4132 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
4135 return STATUS_NOT_IMPLEMENTED
;
4143 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
4146 return STATUS_NOT_IMPLEMENTED
;