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 write */
2565 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2566 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2567 &CapturedByteOffset
,
2575 /* Only accept the result if we got a straightforward status */
2577 (KernelIosb
.Status
== STATUS_SUCCESS
||
2578 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2579 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2581 /* Fast path -- update transfer & operation counts */
2582 IopUpdateOperationCount(IopReadTransfer
);
2583 IopUpdateTransferCount(IopReadTransfer
,
2584 (ULONG
)KernelIosb
.Information
);
2586 /* Enter SEH to write the IOSB back */
2589 /* Write it back to the caller */
2590 *IoStatusBlock
= KernelIosb
;
2592 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2594 /* The caller's IOSB was invalid, so fail */
2595 if (EventObject
) ObDereferenceObject(EventObject
);
2596 IopUnlockFileObject(FileObject
);
2597 ObDereferenceObject(FileObject
);
2598 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2602 /* Signal the completion event */
2605 KeSetEvent(EventObject
, 0, FALSE
);
2606 ObDereferenceObject(EventObject
);
2610 IopUnlockFileObject(FileObject
);
2611 ObDereferenceObject(FileObject
);
2612 return KernelIosb
.Status
;
2616 /* Remember we are sync */
2619 else if (!(ByteOffset
) &&
2620 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2622 /* Otherwise, this was async I/O without a byte offset, so fail */
2623 if (EventObject
) ObDereferenceObject(EventObject
);
2624 ObDereferenceObject(FileObject
);
2625 return STATUS_INVALID_PARAMETER
;
2628 /* Clear the File Object's event */
2629 KeClearEvent(&FileObject
->Event
);
2631 /* Allocate the IRP */
2632 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2633 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2636 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2637 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2638 Irp
->RequestorMode
= PreviousMode
;
2639 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2640 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2641 Irp
->UserIosb
= IoStatusBlock
;
2642 Irp
->UserEvent
= EventObject
;
2643 Irp
->PendingReturned
= FALSE
;
2644 Irp
->Cancel
= FALSE
;
2645 Irp
->CancelRoutine
= NULL
;
2646 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2647 Irp
->MdlAddress
= NULL
;
2649 /* Set the Stack Data */
2650 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2651 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2652 StackPtr
->FileObject
= FileObject
;
2653 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2654 StackPtr
->Parameters
.Read
.Length
= Length
;
2655 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2657 /* Check if this is buffered I/O */
2658 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2660 /* Check if we have a buffer length */
2666 /* Allocate a buffer */
2667 Irp
->AssociatedIrp
.SystemBuffer
=
2668 ExAllocatePoolWithTag(NonPagedPool
,
2672 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2674 /* Allocating failed, clean up and return the exception code */
2675 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2676 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2680 /* Set the buffer and flags */
2681 Irp
->UserBuffer
= Buffer
;
2682 Irp
->Flags
= (IRP_BUFFERED_IO
|
2683 IRP_DEALLOCATE_BUFFER
|
2684 IRP_INPUT_OPERATION
);
2688 /* Not reading anything */
2689 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2692 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2694 /* Check if we have a buffer length */
2699 /* Allocate an MDL */
2700 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2702 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2703 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2705 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2707 /* Allocating failed, clean up and return the exception code */
2708 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2709 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2715 /* No allocation flags */
2720 /* No allocation flags, and use the buffer directly */
2722 Irp
->UserBuffer
= Buffer
;
2725 /* Now set the deferred read flags */
2726 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2728 /* FIXME: VFAT SUCKS */
2729 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2732 /* Perform the call */
2733 return IopPerformSynchronousRequest(DeviceObject
,
2747 NtReadFileScatter(IN HANDLE FileHandle
,
2748 IN HANDLE Event OPTIONAL
,
2749 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2750 IN PVOID UserApcContext OPTIONAL
,
2751 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2752 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2753 IN ULONG BufferLength
,
2754 IN PLARGE_INTEGER ByteOffset
,
2755 IN PULONG Key OPTIONAL
)
2758 return STATUS_NOT_IMPLEMENTED
;
2766 NtSetEaFile(IN HANDLE FileHandle
,
2767 IN PIO_STATUS_BLOCK IoStatusBlock
,
2769 IN ULONG EaBufferSize
)
2772 return STATUS_NOT_IMPLEMENTED
;
2780 NtSetInformationFile(IN HANDLE FileHandle
,
2781 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2782 IN PVOID FileInformation
,
2784 IN FILE_INFORMATION_CLASS FileInformationClass
)
2786 PFILE_OBJECT FileObject
;
2789 PDEVICE_OBJECT DeviceObject
;
2790 PIO_STACK_LOCATION StackPtr
;
2791 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2792 PKEVENT Event
= NULL
;
2793 BOOLEAN LocalEvent
= FALSE
;
2794 PKNORMAL_ROUTINE NormalRoutine
;
2795 PVOID NormalContext
;
2797 IO_STATUS_BLOCK KernelIosb
;
2799 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2800 PIO_COMPLETION_CONTEXT Context
;
2801 PFILE_RENAME_INFORMATION RenameInfo
;
2802 HANDLE TargetHandle
= NULL
;
2804 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2806 /* Check if we're called from user mode */
2807 if (PreviousMode
!= KernelMode
)
2809 /* Validate the information class */
2810 if ((FileInformationClass
>= FileMaximumInformation
) ||
2811 !(IopSetOperationLength
[FileInformationClass
]))
2814 return STATUS_INVALID_INFO_CLASS
;
2817 /* Validate the length */
2818 if (Length
< IopSetOperationLength
[FileInformationClass
])
2820 /* Invalid length */
2821 return STATUS_INFO_LENGTH_MISMATCH
;
2824 /* Enter SEH for probing */
2827 /* Probe the I/O Status block */
2828 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2830 /* Probe the information */
2831 ProbeForRead(FileInformation
,
2833 (Length
== sizeof(BOOLEAN
)) ?
2834 sizeof(BOOLEAN
) : sizeof(ULONG
));
2836 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2838 /* Return the exception code */
2839 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2845 /* Validate the information class */
2846 if ((FileInformationClass
>= FileMaximumInformation
) ||
2847 !(IopSetOperationLength
[FileInformationClass
]))
2850 return STATUS_INVALID_INFO_CLASS
;
2853 /* Validate the length */
2854 if (Length
< IopSetOperationLength
[FileInformationClass
])
2856 /* Invalid length */
2857 return STATUS_INFO_LENGTH_MISMATCH
;
2861 /* Reference the Handle */
2862 Status
= ObReferenceObjectByHandle(FileHandle
,
2863 IopSetOperationAccess
2864 [FileInformationClass
],
2867 (PVOID
*)&FileObject
,
2869 if (!NT_SUCCESS(Status
)) return Status
;
2871 /* Check if this is a direct open or not */
2872 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2874 /* Get the device object */
2875 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2879 /* Get the device object */
2880 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2883 DPRINT("Will call: %p\n", DeviceObject
);
2884 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
2886 /* Check if this is a file that was opened for Synch I/O */
2887 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2890 IopLockFileObject(FileObject
);
2892 /* Check if the caller just wants the position */
2893 if (FileInformationClass
== FilePositionInformation
)
2895 /* Protect write in SEH */
2898 /* Write the offset */
2899 FileObject
->CurrentByteOffset
=
2900 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2903 /* Fill out the I/O Status Block */
2904 IoStatusBlock
->Information
= 0;
2905 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2907 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2909 /* Get the exception code */
2910 Status
= _SEH2_GetExceptionCode();
2914 /* Update transfer count */
2915 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2917 /* Release the file lock, dereference the file and return */
2918 IopUnlockFileObject(FileObject
);
2919 ObDereferenceObject(FileObject
);
2925 /* Use local event */
2926 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2929 ObDereferenceObject(FileObject
);
2930 return STATUS_INSUFFICIENT_RESOURCES
;
2933 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2937 /* Clear the File Object event */
2938 KeClearEvent(&FileObject
->Event
);
2940 /* Allocate the IRP */
2941 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2942 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2945 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2946 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2947 Irp
->RequestorMode
= PreviousMode
;
2948 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2949 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2950 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2951 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2952 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2953 Irp
->MdlAddress
= NULL
;
2954 Irp
->UserBuffer
= FileInformation
;
2956 /* Set the Stack Data */
2957 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2958 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2959 StackPtr
->FileObject
= FileObject
;
2964 /* Allocate a buffer */
2965 Irp
->AssociatedIrp
.SystemBuffer
=
2966 ExAllocatePoolWithTag(NonPagedPool
,
2970 /* Copy the data into it */
2971 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2975 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2977 /* Allocating failed, clean up and return the exception code */
2978 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2979 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2984 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2985 IRP_DEALLOCATE_BUFFER
|
2986 IRP_DEFER_IO_COMPLETION
);
2988 /* Set the Parameters */
2989 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2990 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2993 IopQueueIrpToThread(Irp
);
2995 /* Update operation counts */
2996 IopUpdateOperationCount(IopOtherTransfer
);
2998 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2999 /* Handle IO Completion Port quickly */
3000 if (FileInformationClass
== FileCompletionInformation
)
3002 /* Check if the file object already has a completion port */
3003 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3004 (FileObject
->CompletionContext
))
3007 Status
= STATUS_INVALID_PARAMETER
;
3011 /* Reference the Port */
3012 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3013 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3014 IO_COMPLETION_MODIFY_STATE
,
3019 if (NT_SUCCESS(Status
))
3021 /* Allocate the Context */
3022 Context
= ExAllocatePoolWithTag(PagedPool
,
3023 sizeof(IO_COMPLETION_CONTEXT
),
3028 Context
->Key
= CompletionInfo
->Key
;
3029 Context
->Port
= Queue
;
3030 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3036 * Someone else set the completion port in the
3037 * meanwhile, so dereference the port and fail.
3039 ExFreePoolWithTag(Context
, IOC_TAG
);
3040 ObDereferenceObject(Queue
);
3041 Status
= STATUS_INVALID_PARAMETER
;
3046 /* Dereference the Port now */
3047 ObDereferenceObject(Queue
);
3048 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3053 /* Set the IRP Status */
3054 Irp
->IoStatus
.Status
= Status
;
3055 Irp
->IoStatus
.Information
= 0;
3057 else if (FileInformationClass
== FileRenameInformation
||
3058 FileInformationClass
== FileLinkInformation
||
3059 FileInformationClass
== FileMoveClusterInformation
)
3061 /* Get associated information */
3062 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3067 * -> sizes are valid
3069 if (RenameInfo
->FileNameLength
!= 0 &&
3070 !(RenameInfo
->FileNameLength
& 1) &&
3071 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3073 /* Properly set information received */
3074 if (FileInformationClass
== FileMoveClusterInformation
)
3076 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3080 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3083 /* If we got fully path OR relative target, attempt a parent directory open */
3084 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3086 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3087 if (!NT_SUCCESS(Status
))
3089 Irp
->IoStatus
.Status
= Status
;
3093 /* Call the Driver */
3094 Status
= IoCallDriver(DeviceObject
, Irp
);
3099 /* Call the Driver */
3100 Status
= IoCallDriver(DeviceObject
, Irp
);
3105 Status
= STATUS_INVALID_PARAMETER
;
3106 Irp
->IoStatus
.Status
= Status
;
3111 /* Call the Driver */
3112 Status
= IoCallDriver(DeviceObject
, Irp
);
3115 /* Check if we're waiting for the IRP to complete */
3116 if (Status
== STATUS_PENDING
)
3118 /* Check if this was async I/O */
3121 /* Then to a non-alertable wait */
3122 Status
= KeWaitForSingleObject(Event
,
3127 if (Status
== STATUS_USER_APC
)
3129 /* Abort the request */
3130 IopAbortInterruptedIrp(Event
, Irp
);
3133 /* Set the final status */
3134 Status
= KernelIosb
.Status
;
3136 /* Enter SEH to write the IOSB back */
3139 /* Write it back to the caller */
3140 *IoStatusBlock
= KernelIosb
;
3142 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3144 /* Get the exception code */
3145 Status
= _SEH2_GetExceptionCode();
3149 /* Free the event */
3150 ExFreePoolWithTag(Event
, TAG_IO
);
3154 /* Wait for the IRP */
3155 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3158 (FileObject
->Flags
&
3159 FO_ALERTABLE_IO
) != 0,
3161 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3163 /* Abort the request */
3164 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3167 /* Set the final status */
3168 Status
= FileObject
->FinalStatus
;
3170 /* Release the file lock */
3171 IopUnlockFileObject(FileObject
);
3176 /* Free the event if we had one */
3179 /* Clear it in the IRP for completion */
3180 Irp
->UserEvent
= NULL
;
3181 ExFreePoolWithTag(Event
, TAG_IO
);
3184 /* Set the caller IOSB */
3185 Irp
->UserIosb
= IoStatusBlock
;
3187 /* The IRP wasn't completed, complete it ourselves */
3188 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3189 IopCompleteRequest(&Irp
->Tail
.Apc
,
3192 (PVOID
*)&FileObject
,
3194 KeLowerIrql(OldIrql
);
3196 /* Release the file object if we had locked it*/
3197 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3200 if (TargetHandle
!= NULL
)
3202 ObCloseHandle(TargetHandle
, KernelMode
);
3205 /* Return the Status */
3214 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3215 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3217 IN ULONG BufferLength
)
3220 return STATUS_NOT_IMPLEMENTED
;
3228 NtUnlockFile(IN HANDLE FileHandle
,
3229 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3230 IN PLARGE_INTEGER ByteOffset
,
3231 IN PLARGE_INTEGER Length
,
3232 IN ULONG Key OPTIONAL
)
3234 PFILE_OBJECT FileObject
;
3235 PLARGE_INTEGER LocalLength
= NULL
;
3237 PIO_STACK_LOCATION StackPtr
;
3238 PDEVICE_OBJECT DeviceObject
;
3239 PKEVENT Event
= NULL
;
3240 BOOLEAN LocalEvent
= FALSE
;
3241 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3242 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3244 OBJECT_HANDLE_INFORMATION HandleInformation
;
3245 IO_STATUS_BLOCK KernelIosb
;
3246 PFAST_IO_DISPATCH FastIoDispatch
;
3248 CapturedByteOffset
.QuadPart
= 0;
3249 CapturedLength
.QuadPart
= 0;
3250 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3252 /* Get File Object */
3253 Status
= ObReferenceObjectByHandle(FileHandle
,
3257 (PVOID
*)&FileObject
,
3258 &HandleInformation
);
3259 if (!NT_SUCCESS(Status
)) return Status
;
3261 /* Check if we're called from user mode */
3262 if (PreviousMode
!= KernelMode
)
3264 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3265 if (!(HandleInformation
.GrantedAccess
&
3266 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3268 ObDereferenceObject(FileObject
);
3269 return STATUS_ACCESS_DENIED
;
3272 /* Enter SEH for probing */
3275 /* Probe the I/O Status block */
3276 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3278 /* Probe and capture the large integers */
3279 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3280 CapturedLength
= ProbeForReadLargeInteger(Length
);
3282 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3284 /* Dereference the object and return exception code */
3285 ObDereferenceObject(FileObject
);
3286 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3292 /* Otherwise, capture them directly */
3293 CapturedByteOffset
= *ByteOffset
;
3294 CapturedLength
= *Length
;
3297 /* Check if this is a direct open or not */
3298 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3300 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3304 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3307 /* Try to do it the FastIO way if possible */
3308 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3309 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3311 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3312 &CapturedByteOffset
,
3314 PsGetCurrentProcess(),
3319 /* Write the IOSB back */
3322 *IoStatusBlock
= KernelIosb
;
3324 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3326 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3330 /* We're done with FastIO! */
3331 ObDereferenceObject(FileObject
);
3332 return KernelIosb
.Status
;
3336 /* Check if we should use Sync IO or not */
3337 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3340 IopLockFileObject(FileObject
);
3344 /* Use local event */
3345 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3348 ObDereferenceObject(FileObject
);
3349 return STATUS_INSUFFICIENT_RESOURCES
;
3351 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3355 /* Clear File Object event */
3356 KeClearEvent(&FileObject
->Event
);
3358 /* Allocate the IRP */
3359 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3360 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3362 /* Set up the IRP */
3363 Irp
->RequestorMode
= PreviousMode
;
3364 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3365 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3366 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3367 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3368 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3369 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3371 /* Set up Stack Data */
3372 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3373 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3374 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3375 StackPtr
->FileObject
= FileObject
;
3380 /* Allocate a buffer */
3381 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3382 sizeof(LARGE_INTEGER
),
3385 /* Set the length */
3386 *LocalLength
= CapturedLength
;
3387 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3388 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3390 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3392 /* Allocating failed, clean up and return the exception code */
3393 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3394 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3396 /* Return the exception code */
3397 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3401 /* Set Parameters */
3402 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3403 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3405 /* Call the Driver */
3406 Status
= IopPerformSynchronousRequest(DeviceObject
,
3414 /* Check if this was async I/O */
3417 /* It was, finalize this request */
3418 Status
= IopFinalizeAsynchronousIo(Status
,
3435 NtWriteFile(IN HANDLE FileHandle
,
3436 IN HANDLE Event OPTIONAL
,
3437 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3438 IN PVOID ApcContext OPTIONAL
,
3439 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3442 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3443 IN PULONG Key OPTIONAL
)
3446 PFILE_OBJECT FileObject
;
3448 PDEVICE_OBJECT DeviceObject
;
3449 PIO_STACK_LOCATION StackPtr
;
3450 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3451 PKEVENT EventObject
= NULL
;
3452 LARGE_INTEGER CapturedByteOffset
;
3453 ULONG CapturedKey
= 0;
3454 BOOLEAN Synchronous
= FALSE
;
3456 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3457 PFAST_IO_DISPATCH FastIoDispatch
;
3458 IO_STATUS_BLOCK KernelIosb
;
3462 CapturedByteOffset
.QuadPart
= 0;
3463 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3465 /* Get File Object */
3466 Status
= ObReferenceObjectByHandle(FileHandle
,
3470 (PVOID
*)&FileObject
,
3472 if (!NT_SUCCESS(Status
)) return Status
;
3474 /* Validate User-Mode Buffers */
3475 if (PreviousMode
!= KernelMode
)
3480 * Check if the handle has either FILE_WRITE_DATA or
3481 * FILE_APPEND_DATA granted. However, if this is a named pipe,
3482 * make sure we don't ask for FILE_APPEND_DATA as it interferes
3483 * with the FILE_CREATE_PIPE_INSTANCE access right!
3485 if (!(ObjectHandleInfo
.GrantedAccess
&
3486 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
3487 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
3490 ObDereferenceObject(FileObject
);
3491 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
3494 /* Probe the status block */
3495 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3497 /* Probe the read buffer */
3498 ProbeForRead(Buffer
, Length
, 1);
3500 /* Check if we got a byte offset */
3503 /* Capture and probe it */
3504 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3507 /* Capture and probe the key */
3508 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3510 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3512 /* Release the file object and return the exception code */
3513 ObDereferenceObject(FileObject
);
3514 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3520 /* Kernel mode: capture directly */
3521 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3522 if (Key
) CapturedKey
= *Key
;
3525 /* Check if this is an append operation */
3526 if ((ObjectHandleInfo
.GrantedAccess
&
3527 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3529 /* Give the drivers something to understand */
3530 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3531 CapturedByteOffset
.u
.HighPart
= -1;
3534 /* Check for event */
3538 Status
= ObReferenceObjectByHandle(Event
,
3542 (PVOID
*)&EventObject
,
3544 if (!NT_SUCCESS(Status
))
3547 ObDereferenceObject(FileObject
);
3551 /* Otherwise reset the event */
3552 KeClearEvent(EventObject
);
3555 /* Get the device object */
3556 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3558 /* Check if we should use Sync IO or not */
3559 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3561 /* Lock the file object */
3562 IopLockFileObject(FileObject
);
3564 /* Check if we don't have a byte offset available */
3565 if (!(ByteOffset
) ||
3566 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3567 (CapturedByteOffset
.u
.HighPart
== -1)))
3569 /* Use the Current Byte Offset instead */
3570 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3573 /* If the file is cached, try fast I/O */
3574 if (FileObject
->PrivateCacheMap
)
3576 /* Perform fast read */
3577 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3578 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3579 &CapturedByteOffset
,
3587 /* Only accept the result if it was successful */
3589 KernelIosb
.Status
== STATUS_SUCCESS
)
3591 /* Fast path -- update transfer & operation counts */
3592 IopUpdateOperationCount(IopWriteTransfer
);
3593 IopUpdateTransferCount(IopWriteTransfer
,
3594 (ULONG
)KernelIosb
.Information
);
3596 /* Enter SEH to write the IOSB back */
3599 /* Write it back to the caller */
3600 *IoStatusBlock
= KernelIosb
;
3602 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3604 /* The caller's IOSB was invalid, so fail */
3605 if (EventObject
) ObDereferenceObject(EventObject
);
3606 IopUnlockFileObject(FileObject
);
3607 ObDereferenceObject(FileObject
);
3608 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3612 /* Signal the completion event */
3615 KeSetEvent(EventObject
, 0, FALSE
);
3616 ObDereferenceObject(EventObject
);
3620 IopUnlockFileObject(FileObject
);
3621 ObDereferenceObject(FileObject
);
3622 return KernelIosb
.Status
;
3626 /* Remember we are sync */
3629 else if (!(ByteOffset
) &&
3630 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3632 /* Otherwise, this was async I/O without a byte offset, so fail */
3633 if (EventObject
) ObDereferenceObject(EventObject
);
3634 ObDereferenceObject(FileObject
);
3635 return STATUS_INVALID_PARAMETER
;
3638 /* Clear the File Object's event */
3639 KeClearEvent(&FileObject
->Event
);
3641 /* Allocate the IRP */
3642 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3643 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3646 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3647 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3648 Irp
->RequestorMode
= PreviousMode
;
3649 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3650 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3651 Irp
->UserIosb
= IoStatusBlock
;
3652 Irp
->UserEvent
= EventObject
;
3653 Irp
->PendingReturned
= FALSE
;
3654 Irp
->Cancel
= FALSE
;
3655 Irp
->CancelRoutine
= NULL
;
3656 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3657 Irp
->MdlAddress
= NULL
;
3659 /* Set the Stack Data */
3660 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3661 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3662 StackPtr
->FileObject
= FileObject
;
3663 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3664 SL_WRITE_THROUGH
: 0;
3665 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3666 StackPtr
->Parameters
.Write
.Length
= Length
;
3667 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3669 /* Check if this is buffered I/O */
3670 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3672 /* Check if we have a buffer length */
3678 /* Allocate a buffer */
3679 Irp
->AssociatedIrp
.SystemBuffer
=
3680 ExAllocatePoolWithTag(NonPagedPool
,
3684 /* Copy the data into it */
3685 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3687 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3689 /* Allocating failed, clean up and return the exception code */
3690 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3691 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3696 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3700 /* Not writing anything */
3701 Irp
->Flags
= IRP_BUFFERED_IO
;
3704 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3706 /* Check if we have a buffer length */
3711 /* Allocate an MDL */
3712 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3714 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3715 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3717 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3719 /* Allocating failed, clean up and return the exception code */
3720 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3721 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3726 /* No allocation flags */
3731 /* No allocation flags, and use the buffer directly */
3733 Irp
->UserBuffer
= Buffer
;
3736 /* Now set the deferred read flags */
3737 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3739 /* FIXME: VFAT SUCKS */
3740 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3743 /* Perform the call */
3744 return IopPerformSynchronousRequest(DeviceObject
,
3755 NtWriteFileGather(IN HANDLE FileHandle
,
3756 IN HANDLE Event OPTIONAL
,
3757 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3758 IN PVOID UserApcContext OPTIONAL
,
3759 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3760 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3761 IN ULONG BufferLength
,
3762 IN PLARGE_INTEGER ByteOffset
,
3763 IN PULONG Key OPTIONAL
)
3766 return STATUS_NOT_IMPLEMENTED
;
3774 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3775 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3776 OUT PVOID FsInformation
,
3778 IN FS_INFORMATION_CLASS FsInformationClass
)
3780 PFILE_OBJECT FileObject
;
3782 PIO_STACK_LOCATION StackPtr
;
3783 PDEVICE_OBJECT DeviceObject
;
3784 PKEVENT Event
= NULL
;
3785 BOOLEAN LocalEvent
= FALSE
;
3786 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3788 IO_STATUS_BLOCK KernelIosb
;
3790 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3792 /* Check if we're called from user mode */
3793 if (PreviousMode
!= KernelMode
)
3795 /* Validate the information class */
3796 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3797 !(IopQueryFsOperationLength
[FsInformationClass
]))
3800 return STATUS_INVALID_INFO_CLASS
;
3803 /* Validate the length */
3804 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3806 /* Invalid length */
3807 return STATUS_INFO_LENGTH_MISMATCH
;
3810 /* Enter SEH for probing */
3813 /* Probe the I/O Status block */
3814 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3816 /* Probe the information */
3817 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3819 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3821 /* Return the exception code */
3822 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3827 /* Get File Object */
3828 Status
= ObReferenceObjectByHandle(FileHandle
,
3829 IopQueryFsOperationAccess
3830 [FsInformationClass
],
3833 (PVOID
*)&FileObject
,
3835 if (!NT_SUCCESS(Status
)) return Status
;
3837 /* Check if we should use Sync IO or not */
3838 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3841 IopLockFileObject(FileObject
);
3845 /* Use local event */
3846 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3849 ObDereferenceObject(FileObject
);
3850 return STATUS_INSUFFICIENT_RESOURCES
;
3852 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3856 /* Get the device object */
3857 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3859 /* Clear File Object event */
3860 KeClearEvent(&FileObject
->Event
);
3862 /* Allocate the IRP */
3863 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3864 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3866 /* Set up the IRP */
3867 Irp
->RequestorMode
= PreviousMode
;
3868 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3869 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3870 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3871 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3872 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3873 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3874 Irp
->UserBuffer
= FsInformation
;
3875 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3876 Irp
->MdlAddress
= NULL
;
3878 /* Set up Stack Data */
3879 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3880 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3881 StackPtr
->FileObject
= FileObject
;
3886 /* Allocate a buffer */
3887 Irp
->AssociatedIrp
.SystemBuffer
=
3888 ExAllocatePoolWithTag(NonPagedPool
,
3892 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3894 /* Allocating failed, clean up and return the exception code */
3895 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3896 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3900 /* Set the flags for this buffered + deferred I/O */
3901 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3902 IRP_DEALLOCATE_BUFFER
|
3903 IRP_INPUT_OPERATION
|
3904 IRP_DEFER_IO_COMPLETION
);
3906 /* Set Parameters */
3907 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3908 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3910 /* Call the Driver */
3911 Status
= IopPerformSynchronousRequest(DeviceObject
,
3919 /* Check if this was async I/O */
3922 /* It was, finalize this request */
3923 Status
= IopFinalizeAsynchronousIo(Status
,
3940 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3941 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3942 IN PVOID FsInformation
,
3944 IN FS_INFORMATION_CLASS FsInformationClass
)
3946 PFILE_OBJECT FileObject
;
3948 PIO_STACK_LOCATION StackPtr
;
3949 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3950 PKEVENT Event
= NULL
;
3951 BOOLEAN LocalEvent
= FALSE
;
3952 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3954 IO_STATUS_BLOCK KernelIosb
;
3955 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3957 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3959 /* Check if we're called from user mode */
3960 if (PreviousMode
!= KernelMode
)
3962 /* Validate the information class */
3963 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3964 !(IopSetFsOperationLength
[FsInformationClass
]))
3967 return STATUS_INVALID_INFO_CLASS
;
3970 /* Validate the length */
3971 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3973 /* Invalid length */
3974 return STATUS_INFO_LENGTH_MISMATCH
;
3977 /* Enter SEH for probing */
3980 /* Probe the I/O Status block */
3981 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3983 /* Probe the information */
3984 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3986 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3988 /* Return the exception code */
3989 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3994 /* Get File Object */
3995 Status
= ObReferenceObjectByHandle(FileHandle
,
3996 IopSetFsOperationAccess
3997 [FsInformationClass
],
4000 (PVOID
*)&FileObject
,
4002 if (!NT_SUCCESS(Status
)) return Status
;
4004 /* Get target device for notification */
4005 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4006 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4008 /* Check if we should use Sync IO or not */
4009 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4012 IopLockFileObject(FileObject
);
4016 /* Use local event */
4017 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4020 ObDereferenceObject(FileObject
);
4021 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4022 return STATUS_INSUFFICIENT_RESOURCES
;
4024 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4028 /* Get the device object */
4029 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4031 /* Clear File Object event */
4032 KeClearEvent(&FileObject
->Event
);
4034 /* Allocate the IRP */
4035 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4038 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4039 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4042 /* Set up the IRP */
4043 Irp
->RequestorMode
= PreviousMode
;
4044 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4045 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4046 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4047 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4048 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4049 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4050 Irp
->UserBuffer
= FsInformation
;
4051 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4052 Irp
->MdlAddress
= NULL
;
4054 /* Set up Stack Data */
4055 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4056 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
4057 StackPtr
->FileObject
= FileObject
;
4062 /* Allocate a buffer */
4063 Irp
->AssociatedIrp
.SystemBuffer
=
4064 ExAllocatePoolWithTag(NonPagedPool
,
4068 /* Copy the data into it */
4069 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
4071 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4073 /* Allocating failed, clean up and return the exception code */
4074 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4075 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4076 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4080 /* Set the flags for this buffered + deferred I/O */
4081 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4083 /* Set Parameters */
4084 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
4085 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
4087 /* Call the Driver */
4088 Status
= IopPerformSynchronousRequest(DeviceObject
,
4096 /* Check if this was async I/O */
4099 /* It was, finalize this request */
4100 Status
= IopFinalizeAsynchronousIo(Status
,
4108 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
4110 /* Time to report change */
4111 NotificationStructure
.Version
= 1;
4112 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
4113 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
4114 NotificationStructure
.FileObject
= NULL
;
4115 NotificationStructure
.NameBufferOffset
= - 1;
4116 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
4128 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
4131 return STATUS_NOT_IMPLEMENTED
;
4139 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
4142 return STATUS_NOT_IMPLEMENTED
;