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 requet 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 requet 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 if (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
;
2619 /* Remember we are sync */
2622 else if (!(ByteOffset
) &&
2623 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2625 /* Otherwise, this was async I/O without a byte offset, so fail */
2626 if (EventObject
) ObDereferenceObject(EventObject
);
2627 ObDereferenceObject(FileObject
);
2628 return STATUS_INVALID_PARAMETER
;
2631 /* Clear the File Object's event */
2632 KeClearEvent(&FileObject
->Event
);
2634 /* Allocate the IRP */
2635 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2636 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2639 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2640 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2641 Irp
->RequestorMode
= PreviousMode
;
2642 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2643 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2644 Irp
->UserIosb
= IoStatusBlock
;
2645 Irp
->UserEvent
= EventObject
;
2646 Irp
->PendingReturned
= FALSE
;
2647 Irp
->Cancel
= FALSE
;
2648 Irp
->CancelRoutine
= NULL
;
2649 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2650 Irp
->MdlAddress
= NULL
;
2652 /* Set the Stack Data */
2653 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2654 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2655 StackPtr
->FileObject
= FileObject
;
2656 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2657 StackPtr
->Parameters
.Read
.Length
= Length
;
2658 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2660 /* Check if this is buffered I/O */
2661 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2663 /* Check if we have a buffer length */
2669 /* Allocate a buffer */
2670 Irp
->AssociatedIrp
.SystemBuffer
=
2671 ExAllocatePoolWithTag(NonPagedPool
,
2675 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2677 /* Allocating failed, clean up and return the exception code */
2678 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2679 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2683 /* Set the buffer and flags */
2684 Irp
->UserBuffer
= Buffer
;
2685 Irp
->Flags
= (IRP_BUFFERED_IO
|
2686 IRP_DEALLOCATE_BUFFER
|
2687 IRP_INPUT_OPERATION
);
2691 /* Not reading anything */
2692 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2695 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2697 /* Check if we have a buffer length */
2702 /* Allocate an MDL */
2703 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2705 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2706 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2708 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2710 /* Allocating failed, clean up and return the exception code */
2711 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2712 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2718 /* No allocation flags */
2723 /* No allocation flags, and use the buffer directly */
2725 Irp
->UserBuffer
= Buffer
;
2728 /* Now set the deferred read flags */
2729 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2731 /* FIXME: VFAT SUCKS */
2732 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2735 /* Perform the call */
2736 return IopPerformSynchronousRequest(DeviceObject
,
2750 NtReadFileScatter(IN HANDLE FileHandle
,
2751 IN HANDLE Event OPTIONAL
,
2752 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2753 IN PVOID UserApcContext OPTIONAL
,
2754 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2755 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2756 IN ULONG BufferLength
,
2757 IN PLARGE_INTEGER ByteOffset
,
2758 IN PULONG Key OPTIONAL
)
2761 return STATUS_NOT_IMPLEMENTED
;
2769 NtSetEaFile(IN HANDLE FileHandle
,
2770 IN PIO_STATUS_BLOCK IoStatusBlock
,
2772 IN ULONG EaBufferSize
)
2775 return STATUS_NOT_IMPLEMENTED
;
2783 NtSetInformationFile(IN HANDLE FileHandle
,
2784 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2785 IN PVOID FileInformation
,
2787 IN FILE_INFORMATION_CLASS FileInformationClass
)
2789 PFILE_OBJECT FileObject
;
2792 PDEVICE_OBJECT DeviceObject
;
2793 PIO_STACK_LOCATION StackPtr
;
2794 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2795 PKEVENT Event
= NULL
;
2796 BOOLEAN LocalEvent
= FALSE
;
2797 PKNORMAL_ROUTINE NormalRoutine
;
2798 PVOID NormalContext
;
2800 IO_STATUS_BLOCK KernelIosb
;
2802 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2803 PIO_COMPLETION_CONTEXT Context
;
2804 PFILE_RENAME_INFORMATION RenameInfo
;
2805 HANDLE TargetHandle
= NULL
;
2807 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2809 /* Check if we're called from user mode */
2810 if (PreviousMode
!= KernelMode
)
2812 /* Validate the information class */
2813 if ((FileInformationClass
>= FileMaximumInformation
) ||
2814 !(IopSetOperationLength
[FileInformationClass
]))
2817 return STATUS_INVALID_INFO_CLASS
;
2820 /* Validate the length */
2821 if (Length
< IopSetOperationLength
[FileInformationClass
])
2823 /* Invalid length */
2824 return STATUS_INFO_LENGTH_MISMATCH
;
2827 /* Enter SEH for probing */
2830 /* Probe the I/O Status block */
2831 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2833 /* Probe the information */
2834 ProbeForRead(FileInformation
,
2836 (Length
== sizeof(BOOLEAN
)) ?
2837 sizeof(BOOLEAN
) : sizeof(ULONG
));
2839 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2841 /* Return the exception code */
2842 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2848 /* Validate the information class */
2849 if ((FileInformationClass
>= FileMaximumInformation
) ||
2850 !(IopSetOperationLength
[FileInformationClass
]))
2853 return STATUS_INVALID_INFO_CLASS
;
2856 /* Validate the length */
2857 if (Length
< IopSetOperationLength
[FileInformationClass
])
2859 /* Invalid length */
2860 return STATUS_INFO_LENGTH_MISMATCH
;
2864 /* Reference the Handle */
2865 Status
= ObReferenceObjectByHandle(FileHandle
,
2866 IopSetOperationAccess
2867 [FileInformationClass
],
2870 (PVOID
*)&FileObject
,
2872 if (!NT_SUCCESS(Status
)) return Status
;
2874 /* Check if this is a direct open or not */
2875 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2877 /* Get the device object */
2878 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2882 /* Get the device object */
2883 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2886 DPRINT("Will call: %p\n", DeviceObject
);
2887 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
2889 /* Check if this is a file that was opened for Synch I/O */
2890 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2893 IopLockFileObject(FileObject
);
2895 /* Check if the caller just wants the position */
2896 if (FileInformationClass
== FilePositionInformation
)
2898 /* Protect write in SEH */
2901 /* Write the offset */
2902 FileObject
->CurrentByteOffset
=
2903 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2906 /* Fill out the I/O Status Block */
2907 IoStatusBlock
->Information
= 0;
2908 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2910 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2912 /* Get the exception code */
2913 Status
= _SEH2_GetExceptionCode();
2917 /* Update transfer count */
2918 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2920 /* Release the file lock, dereference the file and return */
2921 IopUnlockFileObject(FileObject
);
2922 ObDereferenceObject(FileObject
);
2928 /* Use local event */
2929 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2932 ObDereferenceObject(FileObject
);
2933 return STATUS_INSUFFICIENT_RESOURCES
;
2936 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2940 /* Clear the File Object event */
2941 KeClearEvent(&FileObject
->Event
);
2943 /* Allocate the IRP */
2944 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2945 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2948 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2949 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2950 Irp
->RequestorMode
= PreviousMode
;
2951 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2952 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2953 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2954 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2955 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2956 Irp
->MdlAddress
= NULL
;
2957 Irp
->UserBuffer
= FileInformation
;
2959 /* Set the Stack Data */
2960 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2961 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2962 StackPtr
->FileObject
= FileObject
;
2967 /* Allocate a buffer */
2968 Irp
->AssociatedIrp
.SystemBuffer
=
2969 ExAllocatePoolWithTag(NonPagedPool
,
2973 /* Copy the data into it */
2974 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2978 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2980 /* Allocating failed, clean up and return the exception code */
2981 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2982 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2987 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2988 IRP_DEALLOCATE_BUFFER
|
2989 IRP_DEFER_IO_COMPLETION
);
2991 /* Set the Parameters */
2992 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2993 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2996 IopQueueIrpToThread(Irp
);
2998 /* Update operation counts */
2999 IopUpdateOperationCount(IopOtherTransfer
);
3001 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3002 /* Handle IO Completion Port quickly */
3003 if (FileInformationClass
== FileCompletionInformation
)
3005 /* Check if the file object already has a completion port */
3006 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3007 (FileObject
->CompletionContext
))
3010 Status
= STATUS_INVALID_PARAMETER
;
3014 /* Reference the Port */
3015 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3016 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3017 IO_COMPLETION_MODIFY_STATE
,
3022 if (NT_SUCCESS(Status
))
3024 /* Allocate the Context */
3025 Context
= ExAllocatePoolWithTag(PagedPool
,
3026 sizeof(IO_COMPLETION_CONTEXT
),
3031 Context
->Key
= CompletionInfo
->Key
;
3032 Context
->Port
= Queue
;
3033 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3039 * Someone else set the completion port in the
3040 * meanwhile, so dereference the port and fail.
3042 ExFreePoolWithTag(Context
, IOC_TAG
);
3043 ObDereferenceObject(Queue
);
3044 Status
= STATUS_INVALID_PARAMETER
;
3049 /* Dereference the Port now */
3050 ObDereferenceObject(Queue
);
3051 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3056 /* Set the IRP Status */
3057 Irp
->IoStatus
.Status
= Status
;
3058 Irp
->IoStatus
.Information
= 0;
3060 else if (FileInformationClass
== FileRenameInformation
||
3061 FileInformationClass
== FileLinkInformation
||
3062 FileInformationClass
== FileMoveClusterInformation
)
3064 /* Get associated information */
3065 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3070 * -> sizes are valid
3072 if (RenameInfo
->FileNameLength
!= 0 &&
3073 !(RenameInfo
->FileNameLength
& 1) &&
3074 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3076 /* Properly set information received */
3077 if (FileInformationClass
== FileMoveClusterInformation
)
3079 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3083 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3086 /* If we got fully path OR relative target, attempt a parent directory open */
3087 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3089 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3090 if (!NT_SUCCESS(Status
))
3092 Irp
->IoStatus
.Status
= Status
;
3096 /* Call the Driver */
3097 Status
= IoCallDriver(DeviceObject
, Irp
);
3102 /* Call the Driver */
3103 Status
= IoCallDriver(DeviceObject
, Irp
);
3108 Status
= STATUS_INVALID_PARAMETER
;
3109 Irp
->IoStatus
.Status
= Status
;
3114 /* Call the Driver */
3115 Status
= IoCallDriver(DeviceObject
, Irp
);
3118 /* Check if we're waiting for the IRP to complete */
3119 if (Status
== STATUS_PENDING
)
3121 /* Check if this was async I/O */
3124 /* Then to a non-alertable wait */
3125 Status
= KeWaitForSingleObject(Event
,
3130 if (Status
== STATUS_USER_APC
)
3132 /* Abort the request */
3133 IopAbortInterruptedIrp(Event
, Irp
);
3136 /* Set the final status */
3137 Status
= KernelIosb
.Status
;
3139 /* Enter SEH to write the IOSB back */
3142 /* Write it back to the caller */
3143 *IoStatusBlock
= KernelIosb
;
3145 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3147 /* Get the exception code */
3148 Status
= _SEH2_GetExceptionCode();
3152 /* Free the event */
3153 ExFreePoolWithTag(Event
, TAG_IO
);
3157 /* Wait for the IRP */
3158 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3161 (FileObject
->Flags
&
3162 FO_ALERTABLE_IO
) != 0,
3164 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3166 /* Abort the request */
3167 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3170 /* Set the final status */
3171 Status
= FileObject
->FinalStatus
;
3173 /* Release the file lock */
3174 IopUnlockFileObject(FileObject
);
3179 /* Free the event if we had one */
3182 /* Clear it in the IRP for completion */
3183 Irp
->UserEvent
= NULL
;
3184 ExFreePoolWithTag(Event
, TAG_IO
);
3187 /* Set the caller IOSB */
3188 Irp
->UserIosb
= IoStatusBlock
;
3190 /* The IRP wasn't completed, complete it ourselves */
3191 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3192 IopCompleteRequest(&Irp
->Tail
.Apc
,
3195 (PVOID
*)&FileObject
,
3197 KeLowerIrql(OldIrql
);
3199 /* Release the file object if we had locked it*/
3200 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3203 if (TargetHandle
!= NULL
)
3205 ObCloseHandle(TargetHandle
, KernelMode
);
3208 /* Return the Status */
3217 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3218 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3220 IN ULONG BufferLength
)
3223 return STATUS_NOT_IMPLEMENTED
;
3231 NtUnlockFile(IN HANDLE FileHandle
,
3232 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3233 IN PLARGE_INTEGER ByteOffset
,
3234 IN PLARGE_INTEGER Length
,
3235 IN ULONG Key OPTIONAL
)
3237 PFILE_OBJECT FileObject
;
3238 PLARGE_INTEGER LocalLength
= NULL
;
3240 PIO_STACK_LOCATION StackPtr
;
3241 PDEVICE_OBJECT DeviceObject
;
3242 PKEVENT Event
= NULL
;
3243 BOOLEAN LocalEvent
= FALSE
;
3244 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3245 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3247 OBJECT_HANDLE_INFORMATION HandleInformation
;
3248 IO_STATUS_BLOCK KernelIosb
;
3249 PFAST_IO_DISPATCH FastIoDispatch
;
3251 CapturedByteOffset
.QuadPart
= 0;
3252 CapturedLength
.QuadPart
= 0;
3253 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3255 /* Get File Object */
3256 Status
= ObReferenceObjectByHandle(FileHandle
,
3260 (PVOID
*)&FileObject
,
3261 &HandleInformation
);
3262 if (!NT_SUCCESS(Status
)) return Status
;
3264 /* Check if we're called from user mode */
3265 if (PreviousMode
!= KernelMode
)
3267 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3268 if (!(HandleInformation
.GrantedAccess
&
3269 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3271 ObDereferenceObject(FileObject
);
3272 return STATUS_ACCESS_DENIED
;
3275 /* Enter SEH for probing */
3278 /* Probe the I/O Status block */
3279 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3281 /* Probe and capture the large integers */
3282 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3283 CapturedLength
= ProbeForReadLargeInteger(Length
);
3285 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3287 /* Dereference the object and return exception code */
3288 ObDereferenceObject(FileObject
);
3289 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3295 /* Otherwise, capture them directly */
3296 CapturedByteOffset
= *ByteOffset
;
3297 CapturedLength
= *Length
;
3300 /* Check if this is a direct open or not */
3301 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3303 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3307 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3310 /* Try to do it the FastIO way if possible */
3311 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3312 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3314 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3315 &CapturedByteOffset
,
3317 PsGetCurrentProcess(),
3322 /* Write the IOSB back */
3325 *IoStatusBlock
= KernelIosb
;
3327 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3329 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3333 /* We're done with FastIO! */
3334 ObDereferenceObject(FileObject
);
3335 return KernelIosb
.Status
;
3339 /* Check if we should use Sync IO or not */
3340 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3343 IopLockFileObject(FileObject
);
3347 /* Use local event */
3348 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3351 ObDereferenceObject(FileObject
);
3352 return STATUS_INSUFFICIENT_RESOURCES
;
3354 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3358 /* Clear File Object event */
3359 KeClearEvent(&FileObject
->Event
);
3361 /* Allocate the IRP */
3362 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3363 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3365 /* Set up the IRP */
3366 Irp
->RequestorMode
= PreviousMode
;
3367 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3368 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3369 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3370 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3371 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3372 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3374 /* Set up Stack Data */
3375 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3376 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3377 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3378 StackPtr
->FileObject
= FileObject
;
3383 /* Allocate a buffer */
3384 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3385 sizeof(LARGE_INTEGER
),
3388 /* Set the length */
3389 *LocalLength
= CapturedLength
;
3390 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3391 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3393 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3395 /* Allocating failed, clean up and return the exception code */
3396 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3397 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3399 /* Return the exception code */
3400 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3404 /* Set Parameters */
3405 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3406 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3408 /* Call the Driver */
3409 Status
= IopPerformSynchronousRequest(DeviceObject
,
3417 /* Check if this was async I/O */
3420 /* It was, finalize this request */
3421 Status
= IopFinalizeAsynchronousIo(Status
,
3438 NtWriteFile(IN HANDLE FileHandle
,
3439 IN HANDLE Event OPTIONAL
,
3440 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3441 IN PVOID ApcContext OPTIONAL
,
3442 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3445 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3446 IN PULONG Key OPTIONAL
)
3449 PFILE_OBJECT FileObject
;
3451 PDEVICE_OBJECT DeviceObject
;
3452 PIO_STACK_LOCATION StackPtr
;
3453 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3454 PKEVENT EventObject
= NULL
;
3455 LARGE_INTEGER CapturedByteOffset
;
3456 ULONG CapturedKey
= 0;
3457 BOOLEAN Synchronous
= FALSE
;
3459 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3460 PFAST_IO_DISPATCH FastIoDispatch
;
3461 IO_STATUS_BLOCK KernelIosb
;
3465 CapturedByteOffset
.QuadPart
= 0;
3466 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3468 /* Get File Object */
3469 Status
= ObReferenceObjectByHandle(FileHandle
,
3473 (PVOID
*)&FileObject
,
3475 if (!NT_SUCCESS(Status
)) return Status
;
3477 /* Validate User-Mode Buffers */
3478 if (PreviousMode
!= KernelMode
)
3483 * Check if the handle has either FILE_WRITE_DATA or
3484 * FILE_APPEND_DATA granted. However, if this is a named pipe,
3485 * make sure we don't ask for FILE_APPEND_DATA as it interferes
3486 * with the FILE_CREATE_PIPE_INSTANCE access right!
3488 if (!(ObjectHandleInfo
.GrantedAccess
&
3489 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
3490 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
3493 ObDereferenceObject(FileObject
);
3494 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
3497 /* Probe the status block */
3498 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3500 /* Probe the read buffer */
3501 ProbeForRead(Buffer
, Length
, 1);
3503 /* Check if we got a byte offset */
3506 /* Capture and probe it */
3507 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3510 /* Capture and probe the key */
3511 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3513 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3515 /* Release the file object and return the exception code */
3516 ObDereferenceObject(FileObject
);
3517 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3523 /* Kernel mode: capture directly */
3524 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3525 if (Key
) CapturedKey
= *Key
;
3528 /* Check if this is an append operation */
3529 if ((ObjectHandleInfo
.GrantedAccess
&
3530 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3532 /* Give the drivers something to understand */
3533 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3534 CapturedByteOffset
.u
.HighPart
= -1;
3537 /* Check for event */
3541 Status
= ObReferenceObjectByHandle(Event
,
3545 (PVOID
*)&EventObject
,
3547 if (!NT_SUCCESS(Status
))
3550 ObDereferenceObject(FileObject
);
3554 /* Otherwise reset the event */
3555 KeClearEvent(EventObject
);
3558 /* Get the device object */
3559 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3561 /* Check if we should use Sync IO or not */
3562 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3564 /* Lock the file object */
3565 IopLockFileObject(FileObject
);
3567 /* Check if we don't have a byte offset available */
3568 if (!(ByteOffset
) ||
3569 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3570 (CapturedByteOffset
.u
.HighPart
== -1)))
3572 /* Use the Current Byte Offset instead */
3573 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3576 /* If the file is cached, try fast I/O */
3577 if (FileObject
->PrivateCacheMap
)
3579 /* Perform fast write */
3580 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3581 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoWrite
!= NULL
)
3583 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3584 &CapturedByteOffset
,
3592 /* Only accept the result if it was successful */
3594 KernelIosb
.Status
== STATUS_SUCCESS
)
3596 /* Fast path -- update transfer & operation counts */
3597 IopUpdateOperationCount(IopWriteTransfer
);
3598 IopUpdateTransferCount(IopWriteTransfer
,
3599 (ULONG
)KernelIosb
.Information
);
3601 /* Enter SEH to write the IOSB back */
3604 /* Write it back to the caller */
3605 *IoStatusBlock
= KernelIosb
;
3607 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3609 /* The caller's IOSB was invalid, so fail */
3610 if (EventObject
) ObDereferenceObject(EventObject
);
3611 IopUnlockFileObject(FileObject
);
3612 ObDereferenceObject(FileObject
);
3613 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3617 /* Signal the completion event */
3620 KeSetEvent(EventObject
, 0, FALSE
);
3621 ObDereferenceObject(EventObject
);
3625 IopUnlockFileObject(FileObject
);
3626 ObDereferenceObject(FileObject
);
3627 return KernelIosb
.Status
;
3632 /* Remember we are sync */
3635 else if (!(ByteOffset
) &&
3636 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3638 /* Otherwise, this was async I/O without a byte offset, so fail */
3639 if (EventObject
) ObDereferenceObject(EventObject
);
3640 ObDereferenceObject(FileObject
);
3641 return STATUS_INVALID_PARAMETER
;
3644 /* Clear the File Object's event */
3645 KeClearEvent(&FileObject
->Event
);
3647 /* Allocate the IRP */
3648 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3649 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3652 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3653 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3654 Irp
->RequestorMode
= PreviousMode
;
3655 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3656 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3657 Irp
->UserIosb
= IoStatusBlock
;
3658 Irp
->UserEvent
= EventObject
;
3659 Irp
->PendingReturned
= FALSE
;
3660 Irp
->Cancel
= FALSE
;
3661 Irp
->CancelRoutine
= NULL
;
3662 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3663 Irp
->MdlAddress
= NULL
;
3665 /* Set the Stack Data */
3666 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3667 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3668 StackPtr
->FileObject
= FileObject
;
3669 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3670 SL_WRITE_THROUGH
: 0;
3671 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3672 StackPtr
->Parameters
.Write
.Length
= Length
;
3673 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3675 /* Check if this is buffered I/O */
3676 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3678 /* Check if we have a buffer length */
3684 /* Allocate a buffer */
3685 Irp
->AssociatedIrp
.SystemBuffer
=
3686 ExAllocatePoolWithTag(NonPagedPool
,
3690 /* Copy the data into it */
3691 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3693 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3695 /* Allocating failed, clean up and return the exception code */
3696 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3697 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3702 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3706 /* Not writing anything */
3707 Irp
->Flags
= IRP_BUFFERED_IO
;
3710 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3712 /* Check if we have a buffer length */
3717 /* Allocate an MDL */
3718 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3720 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3721 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3723 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3725 /* Allocating failed, clean up and return the exception code */
3726 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3727 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3732 /* No allocation flags */
3737 /* No allocation flags, and use the buffer directly */
3739 Irp
->UserBuffer
= Buffer
;
3742 /* Now set the deferred read flags */
3743 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3745 /* FIXME: VFAT SUCKS */
3746 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3749 /* Perform the call */
3750 return IopPerformSynchronousRequest(DeviceObject
,
3761 NtWriteFileGather(IN HANDLE FileHandle
,
3762 IN HANDLE Event OPTIONAL
,
3763 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3764 IN PVOID UserApcContext OPTIONAL
,
3765 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3766 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3767 IN ULONG BufferLength
,
3768 IN PLARGE_INTEGER ByteOffset
,
3769 IN PULONG Key OPTIONAL
)
3772 return STATUS_NOT_IMPLEMENTED
;
3780 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3781 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3782 OUT PVOID FsInformation
,
3784 IN FS_INFORMATION_CLASS FsInformationClass
)
3786 PFILE_OBJECT FileObject
;
3788 PIO_STACK_LOCATION StackPtr
;
3789 PDEVICE_OBJECT DeviceObject
;
3790 PKEVENT Event
= NULL
;
3791 BOOLEAN LocalEvent
= FALSE
;
3792 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3794 IO_STATUS_BLOCK KernelIosb
;
3796 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3798 /* Check if we're called from user mode */
3799 if (PreviousMode
!= KernelMode
)
3801 /* Validate the information class */
3802 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3803 !(IopQueryFsOperationLength
[FsInformationClass
]))
3806 return STATUS_INVALID_INFO_CLASS
;
3809 /* Validate the length */
3810 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3812 /* Invalid length */
3813 return STATUS_INFO_LENGTH_MISMATCH
;
3816 /* Enter SEH for probing */
3819 /* Probe the I/O Status block */
3820 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3822 /* Probe the information */
3823 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3825 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3827 /* Return the exception code */
3828 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3833 /* Get File Object */
3834 Status
= ObReferenceObjectByHandle(FileHandle
,
3835 IopQueryFsOperationAccess
3836 [FsInformationClass
],
3839 (PVOID
*)&FileObject
,
3841 if (!NT_SUCCESS(Status
)) return Status
;
3843 /* Check if we should use Sync IO or not */
3844 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3847 IopLockFileObject(FileObject
);
3851 /* Use local event */
3852 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3855 ObDereferenceObject(FileObject
);
3856 return STATUS_INSUFFICIENT_RESOURCES
;
3858 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3862 /* Get the device object */
3863 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3865 /* Clear File Object event */
3866 KeClearEvent(&FileObject
->Event
);
3868 /* Allocate the IRP */
3869 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3870 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3872 /* Set up the IRP */
3873 Irp
->RequestorMode
= PreviousMode
;
3874 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3875 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3876 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3877 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3878 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3879 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3880 Irp
->UserBuffer
= FsInformation
;
3881 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3882 Irp
->MdlAddress
= NULL
;
3884 /* Set up Stack Data */
3885 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3886 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3887 StackPtr
->FileObject
= FileObject
;
3892 /* Allocate a buffer */
3893 Irp
->AssociatedIrp
.SystemBuffer
=
3894 ExAllocatePoolWithTag(NonPagedPool
,
3898 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3900 /* Allocating failed, clean up and return the exception code */
3901 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3902 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3906 /* Set the flags for this buffered + deferred I/O */
3907 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3908 IRP_DEALLOCATE_BUFFER
|
3909 IRP_INPUT_OPERATION
|
3910 IRP_DEFER_IO_COMPLETION
);
3912 /* Set Parameters */
3913 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3914 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3916 /* Call the Driver */
3917 Status
= IopPerformSynchronousRequest(DeviceObject
,
3925 /* Check if this was async I/O */
3928 /* It was, finalize this request */
3929 Status
= IopFinalizeAsynchronousIo(Status
,
3946 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3947 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3948 IN PVOID FsInformation
,
3950 IN FS_INFORMATION_CLASS FsInformationClass
)
3952 PFILE_OBJECT FileObject
;
3954 PIO_STACK_LOCATION StackPtr
;
3955 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3956 PKEVENT Event
= NULL
;
3957 BOOLEAN LocalEvent
= FALSE
;
3958 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3960 IO_STATUS_BLOCK KernelIosb
;
3961 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3963 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3965 /* Check if we're called from user mode */
3966 if (PreviousMode
!= KernelMode
)
3968 /* Validate the information class */
3969 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3970 !(IopSetFsOperationLength
[FsInformationClass
]))
3973 return STATUS_INVALID_INFO_CLASS
;
3976 /* Validate the length */
3977 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3979 /* Invalid length */
3980 return STATUS_INFO_LENGTH_MISMATCH
;
3983 /* Enter SEH for probing */
3986 /* Probe the I/O Status block */
3987 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3989 /* Probe the information */
3990 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3992 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3994 /* Return the exception code */
3995 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4000 /* Get File Object */
4001 Status
= ObReferenceObjectByHandle(FileHandle
,
4002 IopSetFsOperationAccess
4003 [FsInformationClass
],
4006 (PVOID
*)&FileObject
,
4008 if (!NT_SUCCESS(Status
)) return Status
;
4010 /* Get target device for notification */
4011 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4012 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4014 /* Check if we should use Sync IO or not */
4015 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4018 IopLockFileObject(FileObject
);
4022 /* Use local event */
4023 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4026 ObDereferenceObject(FileObject
);
4027 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4028 return STATUS_INSUFFICIENT_RESOURCES
;
4030 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4034 /* Get the device object */
4035 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4037 /* Clear File Object event */
4038 KeClearEvent(&FileObject
->Event
);
4040 /* Allocate the IRP */
4041 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4044 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4045 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4048 /* Set up the IRP */
4049 Irp
->RequestorMode
= PreviousMode
;
4050 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4051 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4052 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4053 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4054 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4055 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4056 Irp
->UserBuffer
= FsInformation
;
4057 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4058 Irp
->MdlAddress
= NULL
;
4060 /* Set up Stack Data */
4061 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4062 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
4063 StackPtr
->FileObject
= FileObject
;
4068 /* Allocate a buffer */
4069 Irp
->AssociatedIrp
.SystemBuffer
=
4070 ExAllocatePoolWithTag(NonPagedPool
,
4074 /* Copy the data into it */
4075 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
4077 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4079 /* Allocating failed, clean up and return the exception code */
4080 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4081 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4082 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4086 /* Set the flags for this buffered + deferred I/O */
4087 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4089 /* Set Parameters */
4090 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
4091 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
4093 /* Call the Driver */
4094 Status
= IopPerformSynchronousRequest(DeviceObject
,
4102 /* Check if this was async I/O */
4105 /* It was, finalize this request */
4106 Status
= IopFinalizeAsynchronousIo(Status
,
4114 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
4116 /* Time to report change */
4117 NotificationStructure
.Version
= 1;
4118 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
4119 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
4120 NotificationStructure
.FileObject
= NULL
;
4121 NotificationStructure
.NameBufferOffset
= - 1;
4122 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
4134 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
4137 return STATUS_NOT_IMPLEMENTED
;
4145 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
4148 return STATUS_NOT_IMPLEMENTED
;