2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/iofunc.c
5 * PURPOSE: Generic I/O Functions that build IRPs for various operations
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Filip Navara (navaraf@reactos.org)
9 * Pierre Schweitzer (pierre@reactos.org)
12 /* INCLUDES *****************************************************************/
18 #include "internal/io_i.h"
20 volatile LONG IoPageReadIrpAllocationFailure
= 0;
21 volatile LONG IoPageReadNonPagefileIrpAllocationFailure
= 0;
23 /* PRIVATE FUNCTIONS *********************************************************/
27 IopCleanupAfterException(IN PFILE_OBJECT FileObject
,
29 IN PKEVENT Event OPTIONAL
,
30 IN PKEVENT LocalEvent OPTIONAL
)
33 IOTRACE(IO_API_DEBUG
, "IRP: %p. FO: %p \n", Irp
, FileObject
);
37 /* Check if we had a buffer */
38 if (Irp
->AssociatedIrp
.SystemBuffer
)
41 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
45 if (Irp
->MdlAddress
) IoFreeMdl(Irp
->MdlAddress
);
51 /* Check if we had a file lock */
52 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
55 IopUnlockFileObject(FileObject
);
58 /* Check if we had an event */
59 if (Event
) ObDereferenceObject(Event
);
61 /* Check if we had a local event */
62 if (LocalEvent
) ExFreePool(LocalEvent
);
64 /* Derefenrce the FO */
65 ObDereferenceObject(FileObject
);
70 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus
,
73 IN KPROCESSOR_MODE PreviousMode
,
74 IN PIO_STATUS_BLOCK KernelIosb
,
75 OUT PIO_STATUS_BLOCK IoStatusBlock
)
77 NTSTATUS FinalStatus
= SynchStatus
;
79 IOTRACE(IO_API_DEBUG
, "IRP: %p. Status: %lx \n", Irp
, SynchStatus
);
81 /* Make sure the IRP was completed, but returned pending */
82 if (FinalStatus
== STATUS_PENDING
)
84 /* Wait for the IRP */
85 FinalStatus
= KeWaitForSingleObject(Event
,
90 if (FinalStatus
== STATUS_USER_APC
)
92 /* Abort the request */
93 IopAbortInterruptedIrp(Event
, Irp
);
96 /* Set the final status */
97 FinalStatus
= KernelIosb
->Status
;
100 /* Wrap potential user-mode write in SEH */
103 *IoStatusBlock
= *KernelIosb
;
105 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
107 /* Get the exception code */
108 FinalStatus
= _SEH2_GetExceptionCode();
112 /* Free the event and return status */
119 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject
,
121 IN PFILE_OBJECT FileObject
,
123 IN KPROCESSOR_MODE PreviousMode
,
125 IN IOP_TRANSFER_TYPE TransferType
)
128 PKNORMAL_ROUTINE NormalRoutine
;
129 PVOID NormalContext
= NULL
;
132 IOTRACE(IO_API_DEBUG
, "IRP: %p. DO: %p. FO: %p \n",
133 Irp
, DeviceObject
, FileObject
);
136 IopQueueIrpToThread(Irp
);
138 /* Update operation counts */
139 IopUpdateOperationCount(TransferType
);
141 /* Call the driver */
142 Status
= IoCallDriver(DeviceObject
, Irp
);
144 /* Check if we're optimizing this case */
147 /* We are! Check if the IRP wasn't completed */
148 if (Status
!= STATUS_PENDING
)
150 /* Complete it ourselves */
151 ASSERT(!Irp
->PendingReturned
);
152 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
153 IopCompleteRequest(&Irp
->Tail
.Apc
,
158 KeLowerIrql(OldIrql
);
162 /* Check if this was synch I/O */
165 /* Make sure the IRP was completed, but returned pending */
166 if (Status
== STATUS_PENDING
)
168 /* Wait for the IRP */
169 Status
= KeWaitForSingleObject(&FileObject
->Event
,
173 FO_ALERTABLE_IO
) != 0,
175 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
177 /* Abort the request */
178 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
181 /* Set the final status */
182 Status
= FileObject
->FinalStatus
;
185 /* Release the file lock */
186 IopUnlockFileObject(FileObject
);
195 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
196 IN HANDLE Event OPTIONAL
,
197 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
198 IN PVOID UserApcContext OPTIONAL
,
199 OUT PIO_STATUS_BLOCK IoStatusBlock
,
200 IN ULONG IoControlCode
,
201 IN PVOID InputBuffer
,
202 IN ULONG InputBufferLength OPTIONAL
,
203 OUT PVOID OutputBuffer
,
204 IN ULONG OutputBufferLength OPTIONAL
,
205 IN BOOLEAN IsDevIoCtl
)
208 PFILE_OBJECT FileObject
;
209 PDEVICE_OBJECT DeviceObject
;
211 PIO_STACK_LOCATION StackPtr
;
212 PKEVENT EventObject
= NULL
;
213 BOOLEAN LockedForSynch
= FALSE
;
215 OBJECT_HANDLE_INFORMATION HandleInformation
;
216 ACCESS_MASK DesiredAccess
;
217 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
223 IOTRACE(IO_CTL_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
224 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
226 /* Get the access type */
227 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
229 /* Check if we came from user mode */
230 if (PreviousMode
!= KernelMode
)
234 /* Probe the status block */
235 ProbeForWriteIoStatusBlock(IoStatusBlock
);
237 /* Check if this is buffered I/O */
238 if (AccessType
== METHOD_BUFFERED
)
240 /* Check if we have an output buffer */
243 /* Probe the output buffer */
244 ProbeForWrite(OutputBuffer
,
250 /* Make sure the caller can't fake this as we depend on this */
251 OutputBufferLength
= 0;
255 /* Check if we we have an input buffer I/O */
256 if (AccessType
!= METHOD_NEITHER
)
258 /* Check if we have an input buffer */
261 /* Probe the input buffer */
262 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
266 /* Make sure the caller can't fake this as we depend on this */
267 InputBufferLength
= 0;
271 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
273 /* Return the exception code */
274 _SEH2_YIELD(return _SEH2_GetExceptionCode());
279 /* Don't check for access rights right now, KernelMode can do anything */
280 Status
= ObReferenceObjectByHandle(DeviceHandle
,
286 if (!NT_SUCCESS(Status
)) return Status
;
288 /* Can't use an I/O completion port and an APC in the same time */
289 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
292 ObDereferenceObject(FileObject
);
293 return STATUS_INVALID_PARAMETER
;
296 /* Check if we from user mode */
297 if (PreviousMode
!= KernelMode
)
299 /* Get the access mask */
300 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
302 /* Check if we can open it */
303 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
304 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
306 /* Dereference the file object and fail */
307 ObDereferenceObject(FileObject
);
308 return STATUS_ACCESS_DENIED
;
312 /* Check for an event */
316 Status
= ObReferenceObjectByHandle(Event
,
320 (PVOID
*)&EventObject
,
322 if (!NT_SUCCESS(Status
))
324 /* Dereference the file object and fail */
325 ObDereferenceObject(FileObject
);
330 KeClearEvent(EventObject
);
333 /* Check if this is a file that was opened for Synch I/O */
334 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
337 Status
= IopLockFileObject(FileObject
, PreviousMode
);
338 if (Status
!= STATUS_SUCCESS
)
340 if (EventObject
) ObDereferenceObject(EventObject
);
341 ObDereferenceObject(FileObject
);
345 /* Remember to unlock later */
346 LockedForSynch
= TRUE
;
349 /* Check if this is a direct open or not */
350 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
352 /* It's a direct open, get the attached device */
353 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
357 /* Otherwise get the related device */
358 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
361 /* If this is a device I/O, try to do it with FastIO path */
364 PFAST_IO_DISPATCH FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
366 /* Check whether FSD is FastIO aware and provide an appropriate routine */
367 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoDeviceControl
!= NULL
)
369 IO_STATUS_BLOCK KernelIosb
;
371 /* If we have an output buffer coming from usermode */
372 if (PreviousMode
!= KernelMode
&& OutputBuffer
!= NULL
)
374 /* Probe it according to its usage */
377 if (AccessType
== METHOD_IN_DIRECT
)
379 ProbeForRead(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
381 else if (AccessType
== METHOD_OUT_DIRECT
)
383 ProbeForWrite(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
386 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
388 /* Cleanup after exception and return */
389 IopCleanupAfterException(FileObject
, NULL
, EventObject
, NULL
);
391 /* Return the exception code */
392 _SEH2_YIELD(return _SEH2_GetExceptionCode());
397 /* If we are dismounting a volume, increase the dismount count */
398 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
400 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
404 if (FastIoDispatch
->FastIoDeviceControl(FileObject
,
414 IO_COMPLETION_CONTEXT CompletionInfo
= { NULL
, NULL
};
416 /* Write the IOSB back */
419 *IoStatusBlock
= KernelIosb
;
422 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
424 KernelIosb
.Status
= _SEH2_GetExceptionCode();
428 /* Backup our complete context in case it exists */
429 if (FileObject
->CompletionContext
)
431 CompletionInfo
= *(FileObject
->CompletionContext
);
434 /* If we had an event, signal it */
437 KeSetEvent(EventObject
, IO_NO_INCREMENT
, FALSE
);
438 ObDereferenceObject(EventObject
);
441 /* If FO was locked, unlock it */
444 IopUnlockFileObject(FileObject
);
447 /* Set completion if required */
448 if (CompletionInfo
.Port
!= NULL
&& UserApcContext
!= NULL
)
450 if (!NT_SUCCESS(IoSetIoCompletion(CompletionInfo
.Port
,
454 KernelIosb
.Information
,
457 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
461 /* We're done with FastIO! */
462 ObDereferenceObject(FileObject
);
463 return KernelIosb
.Status
;
468 /* Clear the event */
469 KeClearEvent(&FileObject
->Event
);
472 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
473 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
476 Irp
->UserIosb
= IoStatusBlock
;
477 Irp
->UserEvent
= EventObject
;
478 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
479 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
481 Irp
->CancelRoutine
= NULL
;
482 Irp
->PendingReturned
= FALSE
;
483 Irp
->RequestorMode
= PreviousMode
;
484 Irp
->MdlAddress
= NULL
;
485 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
487 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
488 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
489 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
491 /* Set stack location settings */
492 StackPtr
= IoGetNextIrpStackLocation(Irp
);
493 StackPtr
->FileObject
= FileObject
;
494 StackPtr
->MajorFunction
= IsDevIoCtl
?
495 IRP_MJ_DEVICE_CONTROL
:
496 IRP_MJ_FILE_SYSTEM_CONTROL
;
497 StackPtr
->MinorFunction
= 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
498 StackPtr
->Control
= 0;
500 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
502 /* Set the IOCTL Data */
503 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
504 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
505 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
508 PoolType
= IsDevIoCtl
? NonPagedPoolCacheAligned
: NonPagedPool
;
510 /* Handle the Methods */
514 case METHOD_BUFFERED
:
516 /* Enter SEH for allocations */
519 /* Select the right Buffer Length */
520 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
521 InputBufferLength
: OutputBufferLength
;
523 /* Make sure there is one */
526 /* Allocate the System Buffer */
527 Irp
->AssociatedIrp
.SystemBuffer
=
528 ExAllocatePoolWithQuotaTag(PoolType
,
532 /* Check if we got a buffer */
535 /* Copy into the System Buffer */
536 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
541 /* Write the flags */
542 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
543 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
545 /* Save the Buffer */
546 Irp
->UserBuffer
= OutputBuffer
;
550 /* Clear the Flags and Buffer */
551 Irp
->UserBuffer
= NULL
;
554 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
556 /* Cleanup after exception and return */
557 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
558 _SEH2_YIELD(return _SEH2_GetExceptionCode());
564 case METHOD_IN_DIRECT
:
565 case METHOD_OUT_DIRECT
:
570 /* Check if we got an input buffer */
571 if ((InputBufferLength
) && (InputBuffer
))
573 /* Allocate the System Buffer */
574 Irp
->AssociatedIrp
.SystemBuffer
=
575 ExAllocatePoolWithQuotaTag(PoolType
,
579 /* Copy into the System Buffer */
580 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
584 /* Write the flags */
585 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
588 /* Check if we got an output buffer */
589 if (OutputBufferLength
)
591 /* Allocate the System Buffer */
592 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
597 if (!Irp
->MdlAddress
)
599 /* Raise exception we'll catch */
600 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
604 MmProbeAndLockPages(Irp
->MdlAddress
,
606 (AccessType
== METHOD_IN_DIRECT
) ?
607 IoReadAccess
: IoWriteAccess
);
610 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
612 /* Cleanup after exception and return */
613 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
614 _SEH2_YIELD(return _SEH2_GetExceptionCode());
621 /* Just save the Buffer */
622 Irp
->UserBuffer
= OutputBuffer
;
623 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
626 /* Use deferred completion for FS I/O */
629 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
632 /* If we are dismounting a volume, increaase the dismount count */
633 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
635 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
638 /* Perform the call */
639 return IopPerformSynchronousRequest(DeviceObject
,
650 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
651 IN ULONG InformationClass
,
653 OUT PVOID Information
,
654 OUT PULONG ReturnedLength
,
657 IO_STATUS_BLOCK IoStatusBlock
;
659 PDEVICE_OBJECT DeviceObject
;
660 PIO_STACK_LOCATION StackPtr
;
661 BOOLEAN LocalEvent
= FALSE
;
665 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
666 FileObject
, InformationClass
, File
);
668 /* Reference the object */
669 ObReferenceObject(FileObject
);
671 /* Check if this is a file that was opened for Synch I/O */
672 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
675 (void)IopLockFileObject(FileObject
, KernelMode
);
677 /* Use File Object event */
678 KeClearEvent(&FileObject
->Event
);
682 /* Use local event */
683 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
687 /* Get the Device Object */
688 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
690 /* Allocate the IRP */
691 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
692 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
695 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
696 Irp
->RequestorMode
= KernelMode
;
697 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
698 Irp
->UserIosb
= &IoStatusBlock
;
699 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
700 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
701 Irp
->Flags
|= IRP_BUFFERED_IO
;
702 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
703 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
705 /* Set the Stack Data */
706 StackPtr
= IoGetNextIrpStackLocation(Irp
);
707 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
708 IRP_MJ_QUERY_VOLUME_INFORMATION
;
709 StackPtr
->FileObject
= FileObject
;
711 /* Check which type this is */
715 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
716 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
721 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
722 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
726 IopQueueIrpToThread(Irp
);
728 /* Call the Driver */
729 Status
= IoCallDriver(DeviceObject
, Irp
);
731 /* Check if this was synch I/O */
734 /* Check if the request is pending */
735 if (Status
== STATUS_PENDING
)
737 /* Wait on the file object */
738 Status
= KeWaitForSingleObject(&FileObject
->Event
,
742 FO_ALERTABLE_IO
) != 0,
744 if (Status
== STATUS_ALERTED
)
746 /* Abort the operation */
747 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
750 /* Get the final status */
751 Status
= FileObject
->FinalStatus
;
754 /* Release the file lock */
755 IopUnlockFileObject(FileObject
);
757 else if (Status
== STATUS_PENDING
)
759 /* Wait on the local event and get the final status */
760 KeWaitForSingleObject(&Event
,
765 Status
= IoStatusBlock
.Status
;
768 /* Return the Length and Status. ReturnedLength is NOT optional */
769 *ReturnedLength
= (ULONG
)IoStatusBlock
.Information
;
775 IopGetFileInformation(IN PFILE_OBJECT FileObject
,
777 IN FILE_INFORMATION_CLASS FileInfoClass
,
779 OUT PULONG ReturnedLength
)
784 PIO_STACK_LOCATION Stack
;
785 PDEVICE_OBJECT DeviceObject
;
786 IO_STATUS_BLOCK IoStatusBlock
;
790 /* Allocate an IRP */
791 ObReferenceObject(FileObject
);
792 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
793 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
796 ObDereferenceObject(FileObject
);
797 return STATUS_INSUFFICIENT_RESOURCES
;
801 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
804 Irp
->UserIosb
= &IoStatusBlock
;
805 Irp
->UserEvent
= &Event
;
806 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
807 Irp
->RequestorMode
= KernelMode
;
808 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
809 Irp
->Flags
= IRP_SYNCHRONOUS_API
| IRP_BUFFERED_IO
| IRP_OB_QUERY_NAME
;
810 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
811 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
813 Stack
= IoGetNextIrpStackLocation(Irp
);
814 Stack
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
815 Stack
->FileObject
= FileObject
;
816 Stack
->Parameters
.QueryFile
.FileInformationClass
= FileInfoClass
;
817 Stack
->Parameters
.QueryFile
.Length
= Length
;
821 IopQueueIrpToThread(Irp
);
823 /* Call the driver */
824 Status
= IoCallDriver(DeviceObject
, Irp
);
825 if (Status
== STATUS_PENDING
)
827 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
828 Status
= IoStatusBlock
.Status
;
831 *ReturnedLength
= IoStatusBlock
.Information
;
837 IopGetBasicInformationFile(IN PFILE_OBJECT FileObject
,
838 OUT PFILE_BASIC_INFORMATION BasicInfo
)
840 ULONG ReturnedLength
;
841 PDEVICE_OBJECT DeviceObject
;
842 IO_STATUS_BLOCK IoStatusBlock
;
846 /* Try to do it the fast way if possible */
847 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
848 if (DeviceObject
->DriverObject
->FastIoDispatch
!= NULL
&&
849 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
&&
850 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo(FileObject
,
851 ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) != 0),
856 return IoStatusBlock
.Status
;
859 /* In case it failed, fall back to IRP-based method */
860 return IopGetFileInformation(FileObject
, sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
, BasicInfo
, &ReturnedLength
);
865 IopOpenLinkOrRenameTarget(OUT PHANDLE Handle
,
867 IN PFILE_RENAME_INFORMATION RenameInfo
,
868 IN PFILE_OBJECT FileObject
)
872 UNICODE_STRING FileName
;
873 PIO_STACK_LOCATION Stack
;
874 PFILE_OBJECT TargetFileObject
;
875 IO_STATUS_BLOCK IoStatusBlock
;
876 FILE_BASIC_INFORMATION BasicInfo
;
877 OBJECT_ATTRIBUTES ObjectAttributes
;
878 OBJECT_HANDLE_INFORMATION HandleInformation
;
879 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
883 /* First, establish whether our target is a directory */
884 if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
886 Status
= IopGetBasicInformationFile(FileObject
, &BasicInfo
);
887 if (!NT_SUCCESS(Status
))
892 if (BasicInfo
.FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
893 DesiredAccess
= FILE_ADD_SUBDIRECTORY
;
897 /* Setup the string to the target */
898 FileName
.Buffer
= RenameInfo
->FileName
;
899 FileName
.Length
= RenameInfo
->FileNameLength
;
900 FileName
.MaximumLength
= RenameInfo
->FileNameLength
;
902 InitializeObjectAttributes(&ObjectAttributes
,
904 (FileObject
->Flags
& FO_OPENED_CASE_SENSITIVE
? 0 : OBJ_CASE_INSENSITIVE
) | OBJ_KERNEL_HANDLE
,
905 RenameInfo
->RootDirectory
,
908 /* And open its parent directory
909 * Use hint if specified
911 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
913 PFILE_OBJECT_EXTENSION FileObjectExtension
;
915 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
917 FileObjectExtension
= FileObject
->FileObjectExtension
;
918 Status
= IoCreateFileSpecifyDeviceObjectHint(&TargetHandle
,
919 DesiredAccess
| SYNCHRONIZE
,
924 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
926 FILE_OPEN_FOR_BACKUP_INTENT
,
931 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
,
932 FileObjectExtension
->TopDeviceObjectHint
);
936 Status
= IoCreateFile(&TargetHandle
,
937 DesiredAccess
| SYNCHRONIZE
,
942 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
944 FILE_OPEN_FOR_BACKUP_INTENT
,
949 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
);
952 if (!NT_SUCCESS(Status
))
957 /* Once open, continue only if:
958 * Target exists and we're allowed to overwrite it
960 Stack
= IoGetNextIrpStackLocation(Irp
);
961 if (Stack
->Parameters
.SetFile
.FileInformationClass
== FileLinkInformation
&&
962 !RenameInfo
->ReplaceIfExists
&&
963 IoStatusBlock
.Information
== FILE_EXISTS
)
965 ObCloseHandle(TargetHandle
, KernelMode
);
966 return STATUS_OBJECT_NAME_COLLISION
;
969 /* Now, we'll get the associated device of the target, to check for same device location
970 * So, get the FO first
972 Status
= ObReferenceObjectByHandle(TargetHandle
,
976 (PVOID
*)&TargetFileObject
,
978 if (!NT_SUCCESS(Status
))
980 ObCloseHandle(TargetHandle
, KernelMode
);
984 /* We can dereference, we have the handle */
985 ObDereferenceObject(TargetFileObject
);
986 /* If we're not on the same device, error out **/
987 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
989 ObCloseHandle(TargetHandle
, KernelMode
);
990 return STATUS_NOT_SAME_DEVICE
;
993 /* Return parent directory file object and handle */
994 Stack
->Parameters
.SetFile
.FileObject
= TargetFileObject
;
995 *Handle
= TargetHandle
;
997 return STATUS_SUCCESS
;
1002 IopGetFileMode(IN PFILE_OBJECT FileObject
)
1006 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
1007 Mode
|= FILE_WRITE_THROUGH
;
1009 if (FileObject
->Flags
& FO_SEQUENTIAL_ONLY
)
1010 Mode
|= FILE_SEQUENTIAL_ONLY
;
1012 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
1013 Mode
|= FILE_NO_INTERMEDIATE_BUFFERING
;
1015 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1017 if (FileObject
->Flags
& FO_ALERTABLE_IO
)
1018 Mode
|= FILE_SYNCHRONOUS_IO_ALERT
;
1020 Mode
|= FILE_SYNCHRONOUS_IO_NONALERT
;
1023 if (FileObject
->Flags
& FO_DELETE_ON_CLOSE
)
1024 Mode
|= FILE_DELETE_ON_CLOSE
;
1029 /* PUBLIC FUNCTIONS **********************************************************/
1036 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
1038 IN PLARGE_INTEGER Offset
,
1040 IN PIO_STATUS_BLOCK StatusBlock
)
1043 PIO_STACK_LOCATION StackPtr
;
1044 PDEVICE_OBJECT DeviceObject
;
1045 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1046 FileObject
, Mdl
, Offset
);
1048 /* Is the write originating from Cc? */
1049 if (FileObject
->SectionObjectPointer
!= NULL
&&
1050 FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
1053 CcDataPages
+= BYTES_TO_PAGES(MmGetMdlByteCount(Mdl
));
1056 /* Get the Device Object */
1057 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1060 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1061 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1064 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1066 /* Create the IRP Settings */
1067 Irp
->MdlAddress
= Mdl
;
1068 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1069 Irp
->UserIosb
= StatusBlock
;
1070 Irp
->UserEvent
= Event
;
1071 Irp
->RequestorMode
= KernelMode
;
1072 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
1073 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1074 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1076 /* Set the Stack Settings */
1077 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
1078 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
1079 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
1080 StackPtr
->FileObject
= FileObject
;
1082 /* Call the Driver */
1083 return IoCallDriver(DeviceObject
, Irp
);
1091 IoPageRead(IN PFILE_OBJECT FileObject
,
1093 IN PLARGE_INTEGER Offset
,
1095 IN PIO_STATUS_BLOCK StatusBlock
)
1098 PIO_STACK_LOCATION StackPtr
;
1099 PDEVICE_OBJECT DeviceObject
;
1100 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1101 FileObject
, Mdl
, Offset
);
1103 /* Get the Device Object */
1104 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1107 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1108 /* If allocation failed, try to see whether we can use
1113 /* We will use it only for paging file */
1114 if (MmIsFileObjectAPagingFile(FileObject
))
1116 InterlockedExchangeAdd(&IoPageReadIrpAllocationFailure
, 1);
1117 Irp
= IopAllocateReserveIrp(DeviceObject
->StackSize
);
1121 InterlockedExchangeAdd(&IoPageReadNonPagefileIrpAllocationFailure
, 1);
1124 /* If allocation failed (not a paging file or too big stack size)
1129 return STATUS_INSUFFICIENT_RESOURCES
;
1134 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1136 /* Create the IRP Settings */
1137 Irp
->MdlAddress
= Mdl
;
1138 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1139 Irp
->UserIosb
= StatusBlock
;
1140 Irp
->UserEvent
= Event
;
1141 Irp
->RequestorMode
= KernelMode
;
1142 Irp
->Flags
= IRP_PAGING_IO
|
1144 IRP_SYNCHRONOUS_PAGING_IO
|
1145 IRP_INPUT_OPERATION
;
1146 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1147 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1149 /* Set the Stack Settings */
1150 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
1151 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
1152 StackPtr
->MajorFunction
= IRP_MJ_READ
;
1153 StackPtr
->FileObject
= FileObject
;
1155 /* Call the Driver */
1156 return IoCallDriver(DeviceObject
, Irp
);
1164 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1165 IN FILE_INFORMATION_CLASS FileInformationClass
,
1167 OUT PVOID FileInformation
,
1168 OUT PULONG ReturnedLength
)
1170 /* Call the shared routine */
1171 return IopQueryDeviceInformation(FileObject
,
1172 FileInformationClass
,
1184 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
1185 IN FS_INFORMATION_CLASS FsInformationClass
,
1187 OUT PVOID FsInformation
,
1188 OUT PULONG ReturnedLength
)
1190 /* Call the shared routine */
1191 return IopQueryDeviceInformation(FileObject
,
1204 IoSetInformation(IN PFILE_OBJECT FileObject
,
1205 IN FILE_INFORMATION_CLASS FileInformationClass
,
1207 IN PVOID FileInformation
)
1209 IO_STATUS_BLOCK IoStatusBlock
;
1211 PDEVICE_OBJECT DeviceObject
;
1212 PIO_STACK_LOCATION StackPtr
;
1213 BOOLEAN LocalEvent
= FALSE
;
1217 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
1218 FileObject
, FileInformationClass
, Length
);
1220 /* Reference the object */
1221 ObReferenceObject(FileObject
);
1223 /* Check if this is a file that was opened for Synch I/O */
1224 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1227 (void)IopLockFileObject(FileObject
, KernelMode
);
1229 /* Use File Object event */
1230 KeClearEvent(&FileObject
->Event
);
1234 /* Use local event */
1235 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1239 /* Get the Device Object */
1240 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1242 /* Allocate the IRP */
1243 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1244 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1247 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1248 Irp
->RequestorMode
= KernelMode
;
1249 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1250 Irp
->UserIosb
= &IoStatusBlock
;
1251 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1252 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1253 Irp
->Flags
|= IRP_BUFFERED_IO
;
1254 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1255 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1257 /* Set the Stack Data */
1258 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1259 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
1260 StackPtr
->FileObject
= FileObject
;
1262 /* Set Parameters */
1263 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
1264 StackPtr
->Parameters
.SetFile
.Length
= Length
;
1267 IopQueueIrpToThread(Irp
);
1269 /* Call the Driver */
1270 Status
= IoCallDriver(DeviceObject
, Irp
);
1272 /* Check if this was synch I/O */
1275 /* Check if the request is pending */
1276 if (Status
== STATUS_PENDING
)
1278 /* Wait on the file object */
1279 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1282 (FileObject
->Flags
&
1283 FO_ALERTABLE_IO
) != 0,
1285 if (Status
== STATUS_ALERTED
)
1287 /* Abort the operation */
1288 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1291 /* Get the final status */
1292 Status
= FileObject
->FinalStatus
;
1295 /* Release the file lock */
1296 IopUnlockFileObject(FileObject
);
1298 else if (Status
== STATUS_PENDING
)
1300 /* Wait on the local event and get the final status */
1301 KeWaitForSingleObject(&Event
,
1306 Status
= IoStatusBlock
.Status
;
1309 /* Return the status */
1313 /* NATIVE SERVICES ***********************************************************/
1320 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1321 IN HANDLE Event OPTIONAL
,
1322 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1323 IN PVOID UserApcContext OPTIONAL
,
1324 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1325 IN ULONG IoControlCode
,
1326 IN PVOID InputBuffer
,
1327 IN ULONG InputBufferLength OPTIONAL
,
1328 OUT PVOID OutputBuffer
,
1329 IN ULONG OutputBufferLength OPTIONAL
)
1331 /* Call the Generic Function */
1332 return IopDeviceFsIoControl(DeviceHandle
,
1350 NtFsControlFile(IN HANDLE DeviceHandle
,
1351 IN HANDLE Event OPTIONAL
,
1352 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1353 IN PVOID UserApcContext OPTIONAL
,
1354 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1355 IN ULONG IoControlCode
,
1356 IN PVOID InputBuffer
,
1357 IN ULONG InputBufferLength OPTIONAL
,
1358 OUT PVOID OutputBuffer
,
1359 IN ULONG OutputBufferLength OPTIONAL
)
1361 /* Call the Generic Function */
1362 return IopDeviceFsIoControl(DeviceHandle
,
1377 NtFlushBuffersFile(IN HANDLE FileHandle
,
1378 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1380 PFILE_OBJECT FileObject
;
1382 PIO_STACK_LOCATION StackPtr
;
1384 PDEVICE_OBJECT DeviceObject
;
1385 PKEVENT Event
= NULL
;
1386 BOOLEAN LocalEvent
= FALSE
;
1387 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1388 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1389 IO_STATUS_BLOCK KernelIosb
;
1391 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1393 if (PreviousMode
!= KernelMode
)
1395 /* Protect probes */
1398 /* Probe the I/O Status block */
1399 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1401 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1403 /* Return the exception code */
1404 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1409 /* Get the File Object */
1410 Status
= ObReferenceObjectByHandle(FileHandle
,
1414 (PVOID
*)&FileObject
,
1416 if (!NT_SUCCESS(Status
)) return Status
;
1419 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1420 * granted. However, if this is a named pipe, make sure we don't ask for
1421 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1424 if (!(ObjectHandleInfo
.GrantedAccess
&
1425 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1429 ObDereferenceObject(FileObject
);
1430 return STATUS_ACCESS_DENIED
;
1433 /* Check if we should use Sync IO or not */
1434 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1437 Status
= IopLockFileObject(FileObject
, PreviousMode
);
1438 if (Status
!= STATUS_SUCCESS
)
1440 ObDereferenceObject(FileObject
);
1446 /* Use local event */
1447 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1451 ObDereferenceObject(FileObject
);
1452 return STATUS_INSUFFICIENT_RESOURCES
;
1454 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1458 /* Get the Device Object */
1459 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1461 /* Clear the event */
1462 KeClearEvent(&FileObject
->Event
);
1464 /* Allocate the IRP */
1465 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1466 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1468 /* Set up the IRP */
1469 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1470 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1471 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1472 Irp
->RequestorMode
= PreviousMode
;
1473 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1474 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1475 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1477 /* Set up Stack Data */
1478 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1479 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1480 StackPtr
->FileObject
= FileObject
;
1482 /* Call the Driver */
1483 Status
= IopPerformSynchronousRequest(DeviceObject
,
1491 /* Check if this was async I/O */
1494 /* It was, finalize this request */
1495 Status
= IopFinalizeAsynchronousIo(Status
,
1503 /* Return the Status */
1512 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1513 IN HANDLE EventHandle OPTIONAL
,
1514 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1515 IN PVOID ApcContext OPTIONAL
,
1516 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1518 IN ULONG BufferSize
,
1519 IN ULONG CompletionFilter
,
1520 IN BOOLEAN WatchTree
)
1523 PKEVENT Event
= NULL
;
1524 PDEVICE_OBJECT DeviceObject
;
1525 PFILE_OBJECT FileObject
;
1526 PIO_STACK_LOCATION IoStack
;
1527 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1529 BOOLEAN LockedForSync
= FALSE
;
1531 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1533 /* Check if we're called from user mode */
1534 if (PreviousMode
!= KernelMode
)
1536 /* Enter SEH for probing */
1539 /* Probe the I/O STatus block */
1540 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1542 /* Probe the buffer */
1543 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1545 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1547 /* Return the exception code */
1548 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1552 /* Check if CompletionFilter is valid */
1553 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1555 return STATUS_INVALID_PARAMETER
;
1559 /* Get File Object */
1560 Status
= ObReferenceObjectByHandle(FileHandle
,
1561 FILE_LIST_DIRECTORY
,
1564 (PVOID
*)&FileObject
,
1566 if (!NT_SUCCESS(Status
)) return Status
;
1568 /* Check if we have an event handle */
1572 Status
= ObReferenceObjectByHandle(EventHandle
,
1578 if (Status
!= STATUS_SUCCESS
)
1580 ObDereferenceObject(FileObject
);
1583 KeClearEvent(Event
);
1586 /* Check if we should use Sync IO or not */
1587 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1590 Status
= IopLockFileObject(FileObject
, PreviousMode
);
1591 if (Status
!= STATUS_SUCCESS
)
1593 if (Event
) ObDereferenceObject(Event
);
1594 ObDereferenceObject(FileObject
);
1597 LockedForSync
= TRUE
;
1600 /* Clear File Object event */
1601 KeClearEvent(&FileObject
->Event
);
1603 /* Get the device object */
1604 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1606 /* Allocate the IRP */
1607 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1608 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1610 /* Set up the IRP */
1611 Irp
->RequestorMode
= PreviousMode
;
1612 Irp
->UserIosb
= IoStatusBlock
;
1613 Irp
->UserEvent
= Event
;
1614 Irp
->UserBuffer
= Buffer
;
1615 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1616 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1617 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1618 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1620 /* Set up Stack Data */
1621 IoStack
= IoGetNextIrpStackLocation(Irp
);
1622 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1623 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1624 IoStack
->FileObject
= FileObject
;
1626 /* Set parameters */
1627 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1628 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1629 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1631 /* Perform the call */
1632 return IopPerformSynchronousRequest(DeviceObject
,
1646 NtLockFile(IN HANDLE FileHandle
,
1647 IN HANDLE EventHandle OPTIONAL
,
1648 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1649 IN PVOID ApcContext OPTIONAL
,
1650 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1651 IN PLARGE_INTEGER ByteOffset
,
1652 IN PLARGE_INTEGER Length
,
1654 IN BOOLEAN FailImmediately
,
1655 IN BOOLEAN ExclusiveLock
)
1657 PFILE_OBJECT FileObject
;
1658 PLARGE_INTEGER LocalLength
= NULL
;
1660 PIO_STACK_LOCATION StackPtr
;
1661 PDEVICE_OBJECT DeviceObject
;
1662 PKEVENT Event
= NULL
;
1663 BOOLEAN LockedForSync
= FALSE
;
1664 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1665 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1667 OBJECT_HANDLE_INFORMATION HandleInformation
;
1668 PFAST_IO_DISPATCH FastIoDispatch
;
1670 CapturedByteOffset
.QuadPart
= 0;
1671 CapturedLength
.QuadPart
= 0;
1672 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1674 /* Get File Object */
1675 Status
= ObReferenceObjectByHandle(FileHandle
,
1679 (PVOID
*)&FileObject
,
1680 &HandleInformation
);
1681 if (!NT_SUCCESS(Status
)) return Status
;
1683 /* Check if we're called from user mode */
1684 if (PreviousMode
!= KernelMode
)
1686 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1687 if (!(HandleInformation
.GrantedAccess
&
1688 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1690 ObDereferenceObject(FileObject
);
1691 return STATUS_ACCESS_DENIED
;
1694 /* Enter SEH for probing */
1697 /* Probe the I/O STatus block */
1698 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1700 /* Probe and capture the large integers */
1701 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1702 CapturedLength
= ProbeForReadLargeInteger(Length
);
1704 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1706 /* Dereference the object and return exception code */
1707 ObDereferenceObject(FileObject
);
1708 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1714 /* Otherwise, capture them directly */
1715 CapturedByteOffset
= *ByteOffset
;
1716 CapturedLength
= *Length
;
1719 /* Check if we have an event handle */
1723 Status
= ObReferenceObjectByHandle(EventHandle
,
1729 if (Status
!= STATUS_SUCCESS
) return Status
;
1730 KeClearEvent(Event
);
1733 /* Get the device object */
1734 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1736 /* Try to do it the FastIO way if possible */
1737 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1738 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoLock
!= NULL
)
1740 IO_STATUS_BLOCK KernelIosb
;
1742 if (FastIoDispatch
->FastIoLock(FileObject
,
1743 &CapturedByteOffset
,
1745 PsGetCurrentProcess(),
1752 /* Write the IOSB back */
1755 *IoStatusBlock
= KernelIosb
;
1757 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1759 KernelIosb
.Status
= _SEH2_GetExceptionCode();
1763 /* If we had an event, signal it */
1766 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1767 ObDereferenceObject(Event
);
1770 /* Set completion if required */
1771 if (FileObject
->CompletionContext
!= NULL
&& ApcContext
!= NULL
)
1773 if (!NT_SUCCESS(IoSetIoCompletion(FileObject
->CompletionContext
->Port
,
1774 FileObject
->CompletionContext
->Key
,
1777 KernelIosb
.Information
,
1780 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1784 FileObject
->LockOperation
= TRUE
;
1786 /* We're done with FastIO! */
1787 ObDereferenceObject(FileObject
);
1788 return KernelIosb
.Status
;
1792 /* Check if we should use Sync IO or not */
1793 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1796 Status
= IopLockFileObject(FileObject
, PreviousMode
);
1797 if (Status
!= STATUS_SUCCESS
)
1799 if (Event
) ObDereferenceObject(Event
);
1800 ObDereferenceObject(FileObject
);
1803 LockedForSync
= TRUE
;
1806 /* Clear File Object event */
1807 KeClearEvent(&FileObject
->Event
);
1808 FileObject
->LockOperation
= TRUE
;
1810 /* Allocate the IRP */
1811 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1812 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1814 /* Set up the IRP */
1815 Irp
->RequestorMode
= PreviousMode
;
1816 Irp
->UserIosb
= IoStatusBlock
;
1817 Irp
->UserEvent
= Event
;
1818 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1819 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1820 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1821 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1823 /* Set up Stack Data */
1824 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1825 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1826 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1827 StackPtr
->FileObject
= FileObject
;
1829 /* Allocate local buffer */
1830 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1831 sizeof(LARGE_INTEGER
),
1835 /* Allocating failed, clean up and return failure */
1836 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1837 return STATUS_INSUFFICIENT_RESOURCES
;
1840 /* Set the length */
1841 *LocalLength
= CapturedLength
;
1842 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1843 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1845 /* Set Parameters */
1846 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1847 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1850 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1851 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1853 /* Perform the call */
1854 return IopPerformSynchronousRequest(DeviceObject
,
1868 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1869 IN HANDLE EventHandle OPTIONAL
,
1870 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1871 IN PVOID ApcContext OPTIONAL
,
1872 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1873 OUT PVOID FileInformation
,
1875 IN FILE_INFORMATION_CLASS FileInformationClass
,
1876 IN BOOLEAN ReturnSingleEntry
,
1877 IN PUNICODE_STRING FileName OPTIONAL
,
1878 IN BOOLEAN RestartScan
)
1881 PDEVICE_OBJECT DeviceObject
;
1882 PFILE_OBJECT FileObject
;
1883 PIO_STACK_LOCATION StackPtr
;
1884 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1886 BOOLEAN LockedForSynch
= FALSE
;
1887 PKEVENT Event
= NULL
;
1888 volatile PVOID AuxBuffer
= NULL
;
1890 UNICODE_STRING CapturedFileName
;
1891 PUNICODE_STRING SearchPattern
;
1893 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1895 /* Check if we came from user mode */
1896 if (PreviousMode
!= KernelMode
)
1898 /* Enter SEH for probing */
1901 /* Probe the I/O Status Block */
1902 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1904 /* Probe the file information */
1905 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1907 /* Check if we have a file name */
1911 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1912 if (CapturedFileName
.Length
)
1914 /* Probe its buffer */
1915 ProbeForRead(CapturedFileName
.Buffer
,
1916 CapturedFileName
.Length
,
1920 /* Allocate the auxiliary buffer */
1921 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1922 CapturedFileName
.Length
+
1923 sizeof(UNICODE_STRING
),
1925 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1926 sizeof(UNICODE_STRING
)),
1927 CapturedFileName
.Buffer
,
1928 CapturedFileName
.Length
);
1930 /* Setup the search pattern */
1931 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1932 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1933 sizeof(UNICODE_STRING
));
1934 SearchPattern
->Length
= CapturedFileName
.Length
;
1935 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1938 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1940 /* Free buffer and return the exception code */
1941 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1942 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1947 /* Get File Object */
1948 Status
= ObReferenceObjectByHandle(FileHandle
,
1949 FILE_LIST_DIRECTORY
,
1952 (PVOID
*)&FileObject
,
1954 if (!NT_SUCCESS(Status
))
1957 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1961 /* Are there two associated completion routines? */
1962 if (FileObject
->CompletionContext
!= NULL
&& ApcRoutine
!= NULL
)
1964 ObDereferenceObject(FileObject
);
1965 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1966 return STATUS_INVALID_PARAMETER
;
1969 /* Check if we have an even handle */
1972 /* Get its pointer */
1973 Status
= ObReferenceObjectByHandle(EventHandle
,
1979 if (!NT_SUCCESS(Status
))
1982 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1983 ObDereferenceObject(FileObject
);
1988 KeClearEvent(Event
);
1991 /* Check if this is a file that was opened for Synch I/O */
1992 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1995 Status
= IopLockFileObject(FileObject
, PreviousMode
);
1996 if (Status
!= STATUS_SUCCESS
)
1998 if (Event
) ObDereferenceObject(Event
);
1999 ObDereferenceObject(FileObject
);
2000 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2004 /* Remember to unlock later */
2005 LockedForSynch
= TRUE
;
2008 /* Get the device object */
2009 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2011 /* Clear the File Object's event */
2012 KeClearEvent(&FileObject
->Event
);
2014 /* Allocate the IRP */
2015 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2016 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
2018 /* Set up the IRP */
2019 Irp
->RequestorMode
= PreviousMode
;
2020 Irp
->UserIosb
= IoStatusBlock
;
2021 Irp
->UserEvent
= Event
;
2022 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2023 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2024 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2025 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2026 Irp
->MdlAddress
= NULL
;
2027 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
2028 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2030 /* Check if this is buffered I/O */
2031 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2033 /* Allocate a buffer */
2034 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
2037 if (!Irp
->AssociatedIrp
.SystemBuffer
)
2039 /* Allocating failed, clean up and return the exception code */
2040 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2041 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
2043 /* Return the exception code */
2044 return STATUS_INSUFFICIENT_RESOURCES
;
2047 /* Set the buffer and flags */
2048 Irp
->UserBuffer
= FileInformation
;
2049 Irp
->Flags
= (IRP_BUFFERED_IO
|
2050 IRP_DEALLOCATE_BUFFER
|
2051 IRP_INPUT_OPERATION
);
2053 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2057 /* Allocate an MDL */
2058 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
2059 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2060 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2062 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2064 /* Allocating failed, clean up and return the exception code */
2065 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2066 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2072 /* No allocation flags, and use the buffer directly */
2073 Irp
->UserBuffer
= FileInformation
;
2076 /* Set up Stack Data */
2077 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2078 StackPtr
->FileObject
= FileObject
;
2079 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2080 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2082 /* Set Parameters */
2083 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
2084 FileInformationClass
;
2085 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
2086 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2087 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2088 StackPtr
->Flags
= 0;
2089 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2090 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2092 /* Set deferred I/O */
2093 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
2095 /* Perform the call */
2096 return IopPerformSynchronousRequest(DeviceObject
,
2110 NtQueryEaFile(IN HANDLE FileHandle
,
2111 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2114 IN BOOLEAN ReturnSingleEntry
,
2115 IN PVOID EaList OPTIONAL
,
2116 IN ULONG EaListLength
,
2117 IN PULONG EaIndex OPTIONAL
,
2118 IN BOOLEAN RestartScan
)
2121 return STATUS_NOT_IMPLEMENTED
;
2129 NtQueryInformationFile(IN HANDLE FileHandle
,
2130 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2131 IN PVOID FileInformation
,
2133 IN FILE_INFORMATION_CLASS FileInformationClass
)
2135 OBJECT_HANDLE_INFORMATION HandleInformation
;
2136 PFILE_OBJECT FileObject
;
2139 PDEVICE_OBJECT DeviceObject
;
2140 PIO_STACK_LOCATION StackPtr
;
2141 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2142 PKEVENT Event
= NULL
;
2143 BOOLEAN LocalEvent
= FALSE
;
2144 PKNORMAL_ROUTINE NormalRoutine
;
2145 PVOID NormalContext
;
2147 IO_STATUS_BLOCK KernelIosb
;
2148 BOOLEAN CallDriver
= TRUE
;
2149 PFILE_ACCESS_INFORMATION AccessBuffer
;
2150 PFILE_MODE_INFORMATION ModeBuffer
;
2151 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer
;
2152 PFILE_ALL_INFORMATION AllBuffer
;
2153 PFAST_IO_DISPATCH FastIoDispatch
;
2155 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2157 /* Check if we're called from user mode */
2158 if (PreviousMode
!= KernelMode
)
2160 /* Validate the information class */
2161 if ((FileInformationClass
>= FileMaximumInformation
) ||
2162 !(IopQueryOperationLength
[FileInformationClass
]))
2165 return STATUS_INVALID_INFO_CLASS
;
2168 /* Validate the length */
2169 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2171 /* Invalid length */
2172 return STATUS_INFO_LENGTH_MISMATCH
;
2175 /* Enter SEH for probing */
2178 /* Probe the I/O Status block */
2179 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2181 /* Probe the information */
2182 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2184 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2186 /* Return the exception code */
2187 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2194 /* Validate the information class */
2195 if ((FileInformationClass
>= FileMaximumInformation
) ||
2196 !(IopQueryOperationLength
[FileInformationClass
]))
2199 return STATUS_INVALID_INFO_CLASS
;
2202 /* Validate the length */
2203 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2205 /* Invalid length */
2206 return STATUS_INFO_LENGTH_MISMATCH
;
2211 /* Reference the Handle */
2212 Status
= ObReferenceObjectByHandle(FileHandle
,
2213 IopQueryOperationAccess
2214 [FileInformationClass
],
2217 (PVOID
*)&FileObject
,
2218 &HandleInformation
);
2219 if (!NT_SUCCESS(Status
)) return Status
;
2221 /* Check if this is a direct open or not */
2222 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2224 /* Get the device object */
2225 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2229 /* Get the device object */
2230 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2233 /* Check if this is a file that was opened for Synch I/O */
2234 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2237 Status
= IopLockFileObject(FileObject
, PreviousMode
);
2238 if (Status
!= STATUS_SUCCESS
)
2240 ObDereferenceObject(FileObject
);
2244 /* Check if the caller just wants the position */
2245 if (FileInformationClass
== FilePositionInformation
)
2247 /* Protect write in SEH */
2250 /* Write the offset */
2251 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2252 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2254 /* Fill out the I/O Status Block */
2255 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2256 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2258 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2260 /* Get the exception code */
2261 Status
= _SEH2_GetExceptionCode();
2265 /* Release the file lock, dereference the file and return */
2266 IopUnlockFileObject(FileObject
);
2267 ObDereferenceObject(FileObject
);
2273 /* Use local event */
2274 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2277 ObDereferenceObject(FileObject
);
2278 return STATUS_INSUFFICIENT_RESOURCES
;
2280 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2284 /* Check if FastIO is possible for the two available information classes */
2285 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2286 if (FastIoDispatch
!= NULL
&&
2287 ((FileInformationClass
== FileBasicInformation
&& FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
) ||
2288 (FileInformationClass
== FileStandardInformation
&& FastIoDispatch
->FastIoQueryStandardInfo
!= NULL
)))
2290 BOOLEAN Success
= FALSE
;
2292 if (FileInformationClass
== FileBasicInformation
)
2294 Success
= FastIoDispatch
->FastIoQueryBasicInfo(FileObject
, TRUE
,
2301 Success
= FastIoDispatch
->FastIoQueryStandardInfo(FileObject
, TRUE
,
2307 /* If call succeed */
2310 /* Write the IOSB back */
2313 *IoStatusBlock
= KernelIosb
;
2315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2317 KernelIosb
.Status
= _SEH2_GetExceptionCode();
2321 /* Free the event if we had one */
2324 ExFreePoolWithTag(Event
, TAG_IO
);
2327 /* If FO was locked, unlock it */
2328 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2330 IopUnlockFileObject(FileObject
);
2333 /* We're done with FastIO! */
2334 ObDereferenceObject(FileObject
);
2335 return KernelIosb
.Status
;
2339 /* Clear the File Object event */
2340 KeClearEvent(&FileObject
->Event
);
2342 /* Allocate the IRP */
2343 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2344 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2347 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2348 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2349 Irp
->RequestorMode
= PreviousMode
;
2350 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2351 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2352 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2353 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2354 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2355 Irp
->MdlAddress
= NULL
;
2356 Irp
->UserBuffer
= FileInformation
;
2358 /* Set the Stack Data */
2359 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2360 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2361 StackPtr
->FileObject
= FileObject
;
2366 /* Allocate a buffer */
2367 Irp
->AssociatedIrp
.SystemBuffer
=
2368 ExAllocatePoolWithTag(NonPagedPool
,
2372 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2374 /* Allocating failed, clean up and return the exception code */
2375 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2376 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2381 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2382 IRP_DEALLOCATE_BUFFER
|
2383 IRP_INPUT_OPERATION
|
2384 IRP_DEFER_IO_COMPLETION
);
2386 /* Set the Parameters */
2387 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2388 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2391 IopQueueIrpToThread(Irp
);
2393 /* Update operation counts */
2394 IopUpdateOperationCount(IopOtherTransfer
);
2396 /* Fill in file information before calling the driver.
2397 See 'File System Internals' page 485.*/
2398 if (FileInformationClass
== FileAccessInformation
)
2400 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2401 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2402 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2405 else if (FileInformationClass
== FileModeInformation
)
2407 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2408 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2409 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2412 else if (FileInformationClass
== FileAlignmentInformation
)
2414 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2415 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2416 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2419 else if (FileInformationClass
== FileAllInformation
)
2421 AllBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2422 AllBuffer
->AccessInformation
.AccessFlags
= HandleInformation
.GrantedAccess
;
2423 AllBuffer
->ModeInformation
.Mode
= IopGetFileMode(FileObject
);
2424 AllBuffer
->AlignmentInformation
.AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2425 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
) +
2426 sizeof(FILE_MODE_INFORMATION
) +
2427 sizeof(FILE_ALIGNMENT_INFORMATION
);
2430 /* Call the Driver */
2433 Status
= IoCallDriver(DeviceObject
, Irp
);
2437 Status
= STATUS_SUCCESS
;
2438 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2441 if (Status
== STATUS_PENDING
)
2443 /* Check if this was async I/O */
2446 /* Then to a non-alertable wait */
2447 Status
= KeWaitForSingleObject(Event
,
2452 if (Status
== STATUS_USER_APC
)
2454 /* Abort the request */
2455 IopAbortInterruptedIrp(Event
, Irp
);
2458 /* Set the final status */
2459 Status
= KernelIosb
.Status
;
2461 /* Enter SEH to write the IOSB back */
2464 /* Write it back to the caller */
2465 *IoStatusBlock
= KernelIosb
;
2467 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2469 /* Get the exception code */
2470 Status
= _SEH2_GetExceptionCode();
2474 /* Free the event */
2475 ExFreePoolWithTag(Event
, TAG_IO
);
2479 /* Wait for the IRP */
2480 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2483 (FileObject
->Flags
&
2484 FO_ALERTABLE_IO
) != 0,
2486 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2488 /* Abort the request */
2489 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2492 /* Set the final status */
2493 Status
= FileObject
->FinalStatus
;
2495 /* Release the file lock */
2496 IopUnlockFileObject(FileObject
);
2501 /* Free the event if we had one */
2504 /* Clear it in the IRP for completion */
2505 Irp
->UserEvent
= NULL
;
2506 ExFreePoolWithTag(Event
, TAG_IO
);
2509 /* Set the caller IOSB */
2510 Irp
->UserIosb
= IoStatusBlock
;
2512 /* The IRP wasn't completed, complete it ourselves */
2513 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2514 IopCompleteRequest(&Irp
->Tail
.Apc
,
2517 (PVOID
*)&FileObject
,
2519 KeLowerIrql(OldIrql
);
2521 /* Release the file object if we had locked it*/
2522 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2525 /* Return the Status */
2534 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2535 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2538 IN BOOLEAN ReturnSingleEntry
,
2539 IN PVOID SidList OPTIONAL
,
2540 IN ULONG SidListLength
,
2541 IN PSID StartSid OPTIONAL
,
2542 IN BOOLEAN RestartScan
)
2545 return STATUS_NOT_IMPLEMENTED
;
2553 NtReadFile(IN HANDLE FileHandle
,
2554 IN HANDLE Event OPTIONAL
,
2555 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2556 IN PVOID ApcContext OPTIONAL
,
2557 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2560 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2561 IN PULONG Key OPTIONAL
)
2564 PFILE_OBJECT FileObject
;
2566 PDEVICE_OBJECT DeviceObject
;
2567 PIO_STACK_LOCATION StackPtr
;
2568 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2569 PKEVENT EventObject
= NULL
;
2570 LARGE_INTEGER CapturedByteOffset
;
2571 ULONG CapturedKey
= 0;
2572 BOOLEAN Synchronous
= FALSE
;
2574 PFAST_IO_DISPATCH FastIoDispatch
;
2575 IO_STATUS_BLOCK KernelIosb
;
2579 CapturedByteOffset
.QuadPart
= 0;
2580 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2582 /* Get File Object */
2583 Status
= ObReferenceObjectByHandle(FileHandle
,
2587 (PVOID
*)&FileObject
,
2589 if (!NT_SUCCESS(Status
)) return Status
;
2591 /* Get the device object */
2592 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2594 /* Validate User-Mode Buffers */
2595 if (PreviousMode
!= KernelMode
)
2599 /* Probe the status block */
2600 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2602 /* Probe the read buffer */
2603 ProbeForWrite(Buffer
, Length
, 1);
2605 /* Check if we got a byte offset */
2608 /* Capture and probe it */
2609 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2612 /* Perform additional checks for non-cached file access */
2613 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
2615 /* Fail if Length is not sector size aligned */
2616 if ((DeviceObject
->SectorSize
!= 0) &&
2617 (Length
% DeviceObject
->SectorSize
!= 0))
2619 /* Release the file object and and fail */
2620 ObDereferenceObject(FileObject
);
2621 return STATUS_INVALID_PARAMETER
;
2626 /* Fail if ByteOffset is not sector size aligned */
2627 if ((DeviceObject
->SectorSize
!= 0) &&
2628 (ByteOffset
->QuadPart
% DeviceObject
->SectorSize
!= 0))
2630 /* Release the file object and and fail */
2631 ObDereferenceObject(FileObject
);
2632 return STATUS_INVALID_PARAMETER
;
2637 /* Capture and probe the key */
2638 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2640 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2642 /* Release the file object and return the exception code */
2643 ObDereferenceObject(FileObject
);
2644 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2650 /* Kernel mode: capture directly */
2651 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2652 if (Key
) CapturedKey
= *Key
;
2655 /* Check for event */
2659 Status
= ObReferenceObjectByHandle(Event
,
2663 (PVOID
*)&EventObject
,
2665 if (!NT_SUCCESS(Status
))
2668 ObDereferenceObject(FileObject
);
2672 /* Otherwise reset the event */
2673 KeClearEvent(EventObject
);
2676 /* Check if we should use Sync IO or not */
2677 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2679 /* Lock the file object */
2680 Status
= IopLockFileObject(FileObject
, PreviousMode
);
2681 if (Status
!= STATUS_SUCCESS
)
2683 if (EventObject
) ObDereferenceObject(EventObject
);
2684 ObDereferenceObject(FileObject
);
2688 /* Check if we don't have a byte offset available */
2689 if (!(ByteOffset
) ||
2690 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2691 (CapturedByteOffset
.u
.HighPart
== -1)))
2693 /* Use the Current Byte Offset instead */
2694 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2697 /* If the file is cached, try fast I/O */
2698 if (FileObject
->PrivateCacheMap
)
2700 /* Perform fast read */
2701 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2702 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoRead
!= NULL
);
2704 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2705 &CapturedByteOffset
,
2713 /* Only accept the result if we got a straightforward status */
2715 (KernelIosb
.Status
== STATUS_SUCCESS
||
2716 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2717 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2719 /* Fast path -- update transfer & operation counts */
2720 IopUpdateOperationCount(IopReadTransfer
);
2721 IopUpdateTransferCount(IopReadTransfer
,
2722 (ULONG
)KernelIosb
.Information
);
2724 /* Enter SEH to write the IOSB back */
2727 /* Write it back to the caller */
2728 *IoStatusBlock
= KernelIosb
;
2730 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2732 /* The caller's IOSB was invalid, so fail */
2733 if (EventObject
) ObDereferenceObject(EventObject
);
2734 IopUnlockFileObject(FileObject
);
2735 ObDereferenceObject(FileObject
);
2736 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2740 /* Signal the completion event */
2743 KeSetEvent(EventObject
, 0, FALSE
);
2744 ObDereferenceObject(EventObject
);
2748 IopUnlockFileObject(FileObject
);
2749 ObDereferenceObject(FileObject
);
2750 return KernelIosb
.Status
;
2754 /* Remember we are sync */
2757 else if (!(ByteOffset
) &&
2758 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2760 /* Otherwise, this was async I/O without a byte offset, so fail */
2761 if (EventObject
) ObDereferenceObject(EventObject
);
2762 ObDereferenceObject(FileObject
);
2763 return STATUS_INVALID_PARAMETER
;
2766 /* Clear the File Object's event */
2767 KeClearEvent(&FileObject
->Event
);
2769 /* Allocate the IRP */
2770 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2771 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2774 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2775 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2776 Irp
->RequestorMode
= PreviousMode
;
2777 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2778 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2779 Irp
->UserIosb
= IoStatusBlock
;
2780 Irp
->UserEvent
= EventObject
;
2781 Irp
->PendingReturned
= FALSE
;
2782 Irp
->Cancel
= FALSE
;
2783 Irp
->CancelRoutine
= NULL
;
2784 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2785 Irp
->MdlAddress
= NULL
;
2787 /* Set the Stack Data */
2788 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2789 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2790 StackPtr
->FileObject
= FileObject
;
2791 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2792 StackPtr
->Parameters
.Read
.Length
= Length
;
2793 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2795 /* Check if this is buffered I/O */
2796 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2798 /* Check if we have a buffer length */
2804 /* Allocate a buffer */
2805 Irp
->AssociatedIrp
.SystemBuffer
=
2806 ExAllocatePoolWithTag(NonPagedPool
,
2810 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2812 /* Allocating failed, clean up and return the exception code */
2813 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2814 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2818 /* Set the buffer and flags */
2819 Irp
->UserBuffer
= Buffer
;
2820 Irp
->Flags
= (IRP_BUFFERED_IO
|
2821 IRP_DEALLOCATE_BUFFER
|
2822 IRP_INPUT_OPERATION
);
2826 /* Not reading anything */
2827 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2830 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2832 /* Check if we have a buffer length */
2837 /* Allocate an MDL */
2838 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2840 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2841 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2843 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2845 /* Allocating failed, clean up and return the exception code */
2846 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2847 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2853 /* No allocation flags */
2858 /* No allocation flags, and use the buffer directly */
2860 Irp
->UserBuffer
= Buffer
;
2863 /* Now set the deferred read flags */
2864 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2866 /* FIXME: VFAT SUCKS */
2867 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2870 /* Perform the call */
2871 return IopPerformSynchronousRequest(DeviceObject
,
2885 NtReadFileScatter(IN HANDLE FileHandle
,
2886 IN HANDLE Event OPTIONAL
,
2887 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2888 IN PVOID UserApcContext OPTIONAL
,
2889 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2890 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2891 IN ULONG BufferLength
,
2892 IN PLARGE_INTEGER ByteOffset
,
2893 IN PULONG Key OPTIONAL
)
2896 return STATUS_NOT_IMPLEMENTED
;
2904 NtSetEaFile(IN HANDLE FileHandle
,
2905 IN PIO_STATUS_BLOCK IoStatusBlock
,
2907 IN ULONG EaBufferSize
)
2910 return STATUS_NOT_IMPLEMENTED
;
2918 NtSetInformationFile(IN HANDLE FileHandle
,
2919 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2920 IN PVOID FileInformation
,
2922 IN FILE_INFORMATION_CLASS FileInformationClass
)
2924 PFILE_OBJECT FileObject
;
2927 PDEVICE_OBJECT DeviceObject
;
2928 PIO_STACK_LOCATION StackPtr
;
2929 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2930 PKEVENT Event
= NULL
;
2931 BOOLEAN LocalEvent
= FALSE
;
2932 PKNORMAL_ROUTINE NormalRoutine
;
2933 PVOID NormalContext
;
2935 IO_STATUS_BLOCK KernelIosb
;
2937 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2938 PIO_COMPLETION_CONTEXT Context
;
2939 PFILE_RENAME_INFORMATION RenameInfo
;
2940 HANDLE TargetHandle
= NULL
;
2942 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2944 /* Check if we're called from user mode */
2945 if (PreviousMode
!= KernelMode
)
2947 /* Validate the information class */
2948 if ((FileInformationClass
>= FileMaximumInformation
) ||
2949 !(IopSetOperationLength
[FileInformationClass
]))
2952 return STATUS_INVALID_INFO_CLASS
;
2955 /* Validate the length */
2956 if (Length
< IopSetOperationLength
[FileInformationClass
])
2958 /* Invalid length */
2959 return STATUS_INFO_LENGTH_MISMATCH
;
2962 /* Enter SEH for probing */
2965 /* Probe the I/O Status block */
2966 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2968 /* Probe the information */
2969 ProbeForRead(FileInformation
,
2971 (Length
== sizeof(BOOLEAN
)) ?
2972 sizeof(BOOLEAN
) : sizeof(ULONG
));
2974 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2976 /* Return the exception code */
2977 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2983 /* Validate the information class */
2984 if ((FileInformationClass
>= FileMaximumInformation
) ||
2985 !(IopSetOperationLength
[FileInformationClass
]))
2988 return STATUS_INVALID_INFO_CLASS
;
2991 /* Validate the length */
2992 if (Length
< IopSetOperationLength
[FileInformationClass
])
2994 /* Invalid length */
2995 return STATUS_INFO_LENGTH_MISMATCH
;
2999 /* Reference the Handle */
3000 Status
= ObReferenceObjectByHandle(FileHandle
,
3001 IopSetOperationAccess
3002 [FileInformationClass
],
3005 (PVOID
*)&FileObject
,
3007 if (!NT_SUCCESS(Status
)) return Status
;
3009 /* Check if this is a direct open or not */
3010 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3012 /* Get the device object */
3013 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3017 /* Get the device object */
3018 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3021 DPRINT("Will call: %p\n", DeviceObject
);
3022 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
3024 /* Check if this is a file that was opened for Synch I/O */
3025 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3028 Status
= IopLockFileObject(FileObject
, PreviousMode
);
3029 if (Status
!= STATUS_SUCCESS
)
3031 ObDereferenceObject(FileObject
);
3035 /* Check if the caller just wants the position */
3036 if (FileInformationClass
== FilePositionInformation
)
3038 /* Protect write in SEH */
3041 /* Write the offset */
3042 FileObject
->CurrentByteOffset
=
3043 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
3046 /* Fill out the I/O Status Block */
3047 IoStatusBlock
->Information
= 0;
3048 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
3050 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3052 /* Get the exception code */
3053 Status
= _SEH2_GetExceptionCode();
3057 /* Update transfer count */
3058 IopUpdateTransferCount(IopOtherTransfer
, Length
);
3060 /* Release the file lock, dereference the file and return */
3061 IopUnlockFileObject(FileObject
);
3062 ObDereferenceObject(FileObject
);
3068 /* Use local event */
3069 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3072 ObDereferenceObject(FileObject
);
3073 return STATUS_INSUFFICIENT_RESOURCES
;
3076 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3080 /* Clear the File Object event */
3081 KeClearEvent(&FileObject
->Event
);
3083 /* Allocate the IRP */
3084 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
3085 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3088 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3089 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3090 Irp
->RequestorMode
= PreviousMode
;
3091 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3092 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3093 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3094 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3095 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3096 Irp
->MdlAddress
= NULL
;
3097 Irp
->UserBuffer
= FileInformation
;
3099 /* Set the Stack Data */
3100 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3101 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
3102 StackPtr
->FileObject
= FileObject
;
3107 /* Allocate a buffer */
3108 Irp
->AssociatedIrp
.SystemBuffer
=
3109 ExAllocatePoolWithTag(NonPagedPool
,
3113 /* Copy the data into it */
3114 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3118 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3120 /* Allocating failed, clean up and return the exception code */
3121 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3122 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3127 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3128 IRP_DEALLOCATE_BUFFER
|
3129 IRP_DEFER_IO_COMPLETION
);
3131 /* Set the Parameters */
3132 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
3133 StackPtr
->Parameters
.SetFile
.Length
= Length
;
3136 IopQueueIrpToThread(Irp
);
3138 /* Update operation counts */
3139 IopUpdateOperationCount(IopOtherTransfer
);
3141 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3142 /* Handle IO Completion Port quickly */
3143 if (FileInformationClass
== FileCompletionInformation
)
3145 /* Check if the file object already has a completion port */
3146 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3147 (FileObject
->CompletionContext
))
3150 Status
= STATUS_INVALID_PARAMETER
;
3154 /* Reference the Port */
3155 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3156 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3157 IO_COMPLETION_MODIFY_STATE
,
3162 if (NT_SUCCESS(Status
))
3164 /* Allocate the Context */
3165 Context
= ExAllocatePoolWithTag(PagedPool
,
3166 sizeof(IO_COMPLETION_CONTEXT
),
3171 Context
->Key
= CompletionInfo
->Key
;
3172 Context
->Port
= Queue
;
3173 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3179 * Someone else set the completion port in the
3180 * meanwhile, so dereference the port and fail.
3182 ExFreePoolWithTag(Context
, IOC_TAG
);
3183 ObDereferenceObject(Queue
);
3184 Status
= STATUS_INVALID_PARAMETER
;
3189 /* Dereference the Port now */
3190 ObDereferenceObject(Queue
);
3191 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3196 /* Set the IRP Status */
3197 Irp
->IoStatus
.Status
= Status
;
3198 Irp
->IoStatus
.Information
= 0;
3200 else if (FileInformationClass
== FileRenameInformation
||
3201 FileInformationClass
== FileLinkInformation
||
3202 FileInformationClass
== FileMoveClusterInformation
)
3204 /* Get associated information */
3205 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3210 * -> sizes are valid
3212 if (RenameInfo
->FileNameLength
!= 0 &&
3213 !(RenameInfo
->FileNameLength
& 1) &&
3214 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3216 /* Properly set information received */
3217 if (FileInformationClass
== FileMoveClusterInformation
)
3219 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3223 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3226 /* If we got fully path OR relative target, attempt a parent directory open */
3227 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3229 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3230 if (!NT_SUCCESS(Status
))
3232 Irp
->IoStatus
.Status
= Status
;
3236 /* Call the Driver */
3237 Status
= IoCallDriver(DeviceObject
, Irp
);
3242 /* Call the Driver */
3243 Status
= IoCallDriver(DeviceObject
, Irp
);
3248 Status
= STATUS_INVALID_PARAMETER
;
3249 Irp
->IoStatus
.Status
= Status
;
3254 /* Call the Driver */
3255 Status
= IoCallDriver(DeviceObject
, Irp
);
3258 /* Check if we're waiting for the IRP to complete */
3259 if (Status
== STATUS_PENDING
)
3261 /* Check if this was async I/O */
3264 /* Then to a non-alertable wait */
3265 Status
= KeWaitForSingleObject(Event
,
3270 if (Status
== STATUS_USER_APC
)
3272 /* Abort the request */
3273 IopAbortInterruptedIrp(Event
, Irp
);
3276 /* Set the final status */
3277 Status
= KernelIosb
.Status
;
3279 /* Enter SEH to write the IOSB back */
3282 /* Write it back to the caller */
3283 *IoStatusBlock
= KernelIosb
;
3285 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3287 /* Get the exception code */
3288 Status
= _SEH2_GetExceptionCode();
3292 /* Free the event */
3293 ExFreePoolWithTag(Event
, TAG_IO
);
3297 /* Wait for the IRP */
3298 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3301 (FileObject
->Flags
&
3302 FO_ALERTABLE_IO
) != 0,
3304 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3306 /* Abort the request */
3307 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3310 /* Set the final status */
3311 Status
= FileObject
->FinalStatus
;
3313 /* Release the file lock */
3314 IopUnlockFileObject(FileObject
);
3319 /* Free the event if we had one */
3322 /* Clear it in the IRP for completion */
3323 Irp
->UserEvent
= NULL
;
3324 ExFreePoolWithTag(Event
, TAG_IO
);
3327 /* Set the caller IOSB */
3328 Irp
->UserIosb
= IoStatusBlock
;
3330 /* The IRP wasn't completed, complete it ourselves */
3331 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3332 IopCompleteRequest(&Irp
->Tail
.Apc
,
3335 (PVOID
*)&FileObject
,
3337 KeLowerIrql(OldIrql
);
3339 /* Release the file object if we had locked it*/
3340 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3343 if (TargetHandle
!= NULL
)
3345 ObCloseHandle(TargetHandle
, KernelMode
);
3348 /* Return the Status */
3357 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3358 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3360 IN ULONG BufferLength
)
3363 return STATUS_NOT_IMPLEMENTED
;
3371 NtUnlockFile(IN HANDLE FileHandle
,
3372 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3373 IN PLARGE_INTEGER ByteOffset
,
3374 IN PLARGE_INTEGER Length
,
3375 IN ULONG Key OPTIONAL
)
3377 PFILE_OBJECT FileObject
;
3378 PLARGE_INTEGER LocalLength
= NULL
;
3380 PIO_STACK_LOCATION StackPtr
;
3381 PDEVICE_OBJECT DeviceObject
;
3382 PKEVENT Event
= NULL
;
3383 BOOLEAN LocalEvent
= FALSE
;
3384 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3385 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3387 OBJECT_HANDLE_INFORMATION HandleInformation
;
3388 IO_STATUS_BLOCK KernelIosb
;
3389 PFAST_IO_DISPATCH FastIoDispatch
;
3391 CapturedByteOffset
.QuadPart
= 0;
3392 CapturedLength
.QuadPart
= 0;
3393 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3395 /* Get File Object */
3396 Status
= ObReferenceObjectByHandle(FileHandle
,
3400 (PVOID
*)&FileObject
,
3401 &HandleInformation
);
3402 if (!NT_SUCCESS(Status
)) return Status
;
3404 /* Check if we're called from user mode */
3405 if (PreviousMode
!= KernelMode
)
3407 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3408 if (!(HandleInformation
.GrantedAccess
&
3409 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3411 ObDereferenceObject(FileObject
);
3412 return STATUS_ACCESS_DENIED
;
3415 /* Enter SEH for probing */
3418 /* Probe the I/O Status block */
3419 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3421 /* Probe and capture the large integers */
3422 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3423 CapturedLength
= ProbeForReadLargeInteger(Length
);
3425 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3427 /* Dereference the object and return exception code */
3428 ObDereferenceObject(FileObject
);
3429 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3435 /* Otherwise, capture them directly */
3436 CapturedByteOffset
= *ByteOffset
;
3437 CapturedLength
= *Length
;
3440 /* Check if this is a direct open or not */
3441 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3443 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3447 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3450 /* Try to do it the FastIO way if possible */
3451 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3452 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3454 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3455 &CapturedByteOffset
,
3457 PsGetCurrentProcess(),
3462 /* Write the IOSB back */
3465 *IoStatusBlock
= KernelIosb
;
3467 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3469 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3473 /* We're done with FastIO! */
3474 ObDereferenceObject(FileObject
);
3475 return KernelIosb
.Status
;
3479 /* Check if we should use Sync IO or not */
3480 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3483 Status
= IopLockFileObject(FileObject
, PreviousMode
);
3484 if (Status
!= STATUS_SUCCESS
)
3486 ObDereferenceObject(FileObject
);
3492 /* Use local event */
3493 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3496 ObDereferenceObject(FileObject
);
3497 return STATUS_INSUFFICIENT_RESOURCES
;
3499 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3503 /* Clear File Object event */
3504 KeClearEvent(&FileObject
->Event
);
3506 /* Allocate the IRP */
3507 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3508 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3510 /* Set up the IRP */
3511 Irp
->RequestorMode
= PreviousMode
;
3512 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3513 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3514 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3515 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3516 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3517 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3519 /* Set up Stack Data */
3520 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3521 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3522 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3523 StackPtr
->FileObject
= FileObject
;
3528 /* Allocate a buffer */
3529 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3530 sizeof(LARGE_INTEGER
),
3533 /* Set the length */
3534 *LocalLength
= CapturedLength
;
3535 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3536 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3538 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3540 /* Allocating failed, clean up and return the exception code */
3541 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3542 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3544 /* Return the exception code */
3545 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3549 /* Set Parameters */
3550 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3551 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3553 /* Call the Driver */
3554 Status
= IopPerformSynchronousRequest(DeviceObject
,
3562 /* Check if this was async I/O */
3565 /* It was, finalize this request */
3566 Status
= IopFinalizeAsynchronousIo(Status
,
3583 NtWriteFile(IN HANDLE FileHandle
,
3584 IN HANDLE Event OPTIONAL
,
3585 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3586 IN PVOID ApcContext OPTIONAL
,
3587 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3590 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3591 IN PULONG Key OPTIONAL
)
3594 PFILE_OBJECT FileObject
;
3596 PDEVICE_OBJECT DeviceObject
;
3597 PIO_STACK_LOCATION StackPtr
;
3598 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3599 PKEVENT EventObject
= NULL
;
3600 LARGE_INTEGER CapturedByteOffset
;
3601 ULONG CapturedKey
= 0;
3602 BOOLEAN Synchronous
= FALSE
;
3604 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3605 PFAST_IO_DISPATCH FastIoDispatch
;
3606 IO_STATUS_BLOCK KernelIosb
;
3610 CapturedByteOffset
.QuadPart
= 0;
3611 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3613 /* Get File Object for write */
3614 Status
= ObReferenceFileObjectForWrite(FileHandle
,
3618 if (!NT_SUCCESS(Status
)) return Status
;
3620 /* Get the device object */
3621 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3623 /* Validate User-Mode Buffers */
3624 if (PreviousMode
!= KernelMode
)
3628 /* Probe the status block */
3629 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3631 /* Probe the read buffer */
3632 ProbeForRead(Buffer
, Length
, 1);
3634 /* Check if we got a byte offset */
3637 /* Capture and probe it */
3638 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3641 /* Perform additional checks for non-cached file access */
3642 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
3644 /* Fail if Length is not sector size aligned */
3645 if ((DeviceObject
->SectorSize
!= 0) &&
3646 (Length
% DeviceObject
->SectorSize
!= 0))
3648 /* Release the file object and and fail */
3649 ObDereferenceObject(FileObject
);
3650 return STATUS_INVALID_PARAMETER
;
3655 /* Fail if ByteOffset is not sector size aligned */
3656 if ((DeviceObject
->SectorSize
!= 0) &&
3657 (ByteOffset
->QuadPart
% DeviceObject
->SectorSize
!= 0))
3659 /* Release the file object and and fail */
3660 ObDereferenceObject(FileObject
);
3661 return STATUS_INVALID_PARAMETER
;
3666 /* Capture and probe the key */
3667 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3669 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3671 /* Release the file object and return the exception code */
3672 ObDereferenceObject(FileObject
);
3673 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3679 /* Kernel mode: capture directly */
3680 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3681 if (Key
) CapturedKey
= *Key
;
3684 /* Check if this is an append operation */
3685 if ((ObjectHandleInfo
.GrantedAccess
&
3686 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3688 /* Give the drivers something to understand */
3689 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3690 CapturedByteOffset
.u
.HighPart
= -1;
3693 /* Check for event */
3697 Status
= ObReferenceObjectByHandle(Event
,
3701 (PVOID
*)&EventObject
,
3703 if (!NT_SUCCESS(Status
))
3706 ObDereferenceObject(FileObject
);
3710 /* Otherwise reset the event */
3711 KeClearEvent(EventObject
);
3714 /* Check if we should use Sync IO or not */
3715 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3717 /* Lock the file object */
3718 Status
= IopLockFileObject(FileObject
, PreviousMode
);
3719 if (Status
!= STATUS_SUCCESS
)
3721 if (EventObject
) ObDereferenceObject(EventObject
);
3722 ObDereferenceObject(FileObject
);
3726 /* Check if we don't have a byte offset available */
3727 if (!(ByteOffset
) ||
3728 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3729 (CapturedByteOffset
.u
.HighPart
== -1)))
3731 /* Use the Current Byte Offset instead */
3732 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3735 /* If the file is cached, try fast I/O */
3736 if (FileObject
->PrivateCacheMap
)
3738 /* Perform fast write */
3739 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3740 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoWrite
!= NULL
);
3742 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3743 &CapturedByteOffset
,
3751 /* Only accept the result if it was successful */
3753 KernelIosb
.Status
== STATUS_SUCCESS
)
3755 /* Fast path -- update transfer & operation counts */
3756 IopUpdateOperationCount(IopWriteTransfer
);
3757 IopUpdateTransferCount(IopWriteTransfer
,
3758 (ULONG
)KernelIosb
.Information
);
3760 /* Enter SEH to write the IOSB back */
3763 /* Write it back to the caller */
3764 *IoStatusBlock
= KernelIosb
;
3766 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3768 /* The caller's IOSB was invalid, so fail */
3769 if (EventObject
) ObDereferenceObject(EventObject
);
3770 IopUnlockFileObject(FileObject
);
3771 ObDereferenceObject(FileObject
);
3772 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3776 /* Signal the completion event */
3779 KeSetEvent(EventObject
, 0, FALSE
);
3780 ObDereferenceObject(EventObject
);
3784 IopUnlockFileObject(FileObject
);
3785 ObDereferenceObject(FileObject
);
3786 return KernelIosb
.Status
;
3790 /* Remember we are sync */
3793 else if (!(ByteOffset
) &&
3794 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3796 /* Otherwise, this was async I/O without a byte offset, so fail */
3797 if (EventObject
) ObDereferenceObject(EventObject
);
3798 ObDereferenceObject(FileObject
);
3799 return STATUS_INVALID_PARAMETER
;
3802 /* Clear the File Object's event */
3803 KeClearEvent(&FileObject
->Event
);
3805 /* Allocate the IRP */
3806 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3807 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3810 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3811 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3812 Irp
->RequestorMode
= PreviousMode
;
3813 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3814 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3815 Irp
->UserIosb
= IoStatusBlock
;
3816 Irp
->UserEvent
= EventObject
;
3817 Irp
->PendingReturned
= FALSE
;
3818 Irp
->Cancel
= FALSE
;
3819 Irp
->CancelRoutine
= NULL
;
3820 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3821 Irp
->MdlAddress
= NULL
;
3823 /* Set the Stack Data */
3824 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3825 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3826 StackPtr
->FileObject
= FileObject
;
3827 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3828 SL_WRITE_THROUGH
: 0;
3829 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3830 StackPtr
->Parameters
.Write
.Length
= Length
;
3831 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3833 /* Check if this is buffered I/O */
3834 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3836 /* Check if we have a buffer length */
3842 /* Allocate a buffer */
3843 Irp
->AssociatedIrp
.SystemBuffer
=
3844 ExAllocatePoolWithTag(NonPagedPool
,
3848 /* Copy the data into it */
3849 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3851 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3853 /* Allocating failed, clean up and return the exception code */
3854 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3855 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3860 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3864 /* Not writing anything */
3865 Irp
->Flags
= IRP_BUFFERED_IO
;
3868 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3870 /* Check if we have a buffer length */
3875 /* Allocate an MDL */
3876 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3878 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3879 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3881 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3883 /* Allocating failed, clean up and return the exception code */
3884 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3885 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3890 /* No allocation flags */
3895 /* No allocation flags, and use the buffer directly */
3897 Irp
->UserBuffer
= Buffer
;
3900 /* Now set the deferred read flags */
3901 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3903 /* FIXME: VFAT SUCKS */
3904 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3907 /* Perform the call */
3908 return IopPerformSynchronousRequest(DeviceObject
,
3919 NtWriteFileGather(IN HANDLE FileHandle
,
3920 IN HANDLE Event OPTIONAL
,
3921 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3922 IN PVOID UserApcContext OPTIONAL
,
3923 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3924 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3925 IN ULONG BufferLength
,
3926 IN PLARGE_INTEGER ByteOffset
,
3927 IN PULONG Key OPTIONAL
)
3930 return STATUS_NOT_IMPLEMENTED
;
3938 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3939 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3940 OUT PVOID FsInformation
,
3942 IN FS_INFORMATION_CLASS FsInformationClass
)
3944 PFILE_OBJECT FileObject
;
3946 PIO_STACK_LOCATION StackPtr
;
3947 PDEVICE_OBJECT DeviceObject
;
3948 PKEVENT Event
= NULL
;
3949 BOOLEAN LocalEvent
= FALSE
;
3950 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3952 IO_STATUS_BLOCK KernelIosb
;
3954 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3956 /* Check if we're called from user mode */
3957 if (PreviousMode
!= KernelMode
)
3959 /* Validate the information class */
3960 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3961 !(IopQueryFsOperationLength
[FsInformationClass
]))
3964 return STATUS_INVALID_INFO_CLASS
;
3967 /* Validate the length */
3968 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3970 /* Invalid length */
3971 return STATUS_INFO_LENGTH_MISMATCH
;
3974 /* Enter SEH for probing */
3977 /* Probe the I/O Status block */
3978 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3980 /* Probe the information */
3981 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3983 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3985 /* Return the exception code */
3986 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3991 /* Get File Object */
3992 Status
= ObReferenceObjectByHandle(FileHandle
,
3993 IopQueryFsOperationAccess
3994 [FsInformationClass
],
3997 (PVOID
*)&FileObject
,
3999 if (!NT_SUCCESS(Status
)) return Status
;
4001 /* Check if we should use Sync IO or not */
4002 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4005 Status
= IopLockFileObject(FileObject
, PreviousMode
);
4006 if (Status
!= STATUS_SUCCESS
)
4008 ObDereferenceObject(FileObject
);
4014 /* Use local event */
4015 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4018 ObDereferenceObject(FileObject
);
4019 return STATUS_INSUFFICIENT_RESOURCES
;
4021 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4025 /* Get the device object */
4026 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4028 /* Clear File Object event */
4029 KeClearEvent(&FileObject
->Event
);
4031 /* Allocate the IRP */
4032 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4033 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4035 /* Set up the IRP */
4036 Irp
->RequestorMode
= PreviousMode
;
4037 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4038 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4039 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4040 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4041 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4042 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4043 Irp
->UserBuffer
= FsInformation
;
4044 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4045 Irp
->MdlAddress
= NULL
;
4047 /* Set up Stack Data */
4048 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4049 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
4050 StackPtr
->FileObject
= FileObject
;
4055 /* Allocate a buffer */
4056 Irp
->AssociatedIrp
.SystemBuffer
=
4057 ExAllocatePoolWithTag(NonPagedPool
,
4061 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4063 /* Allocating failed, clean up and return the exception code */
4064 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4065 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4069 /* Set the flags for this buffered + deferred I/O */
4070 Irp
->Flags
|= (IRP_BUFFERED_IO
|
4071 IRP_DEALLOCATE_BUFFER
|
4072 IRP_INPUT_OPERATION
|
4073 IRP_DEFER_IO_COMPLETION
);
4075 /* Set Parameters */
4076 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
4077 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
4079 /* Call the Driver */
4080 Status
= IopPerformSynchronousRequest(DeviceObject
,
4088 /* Check if this was async I/O */
4091 /* It was, finalize this request */
4092 Status
= IopFinalizeAsynchronousIo(Status
,
4109 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
4110 OUT PIO_STATUS_BLOCK IoStatusBlock
,
4111 IN PVOID FsInformation
,
4113 IN FS_INFORMATION_CLASS FsInformationClass
)
4115 PFILE_OBJECT FileObject
;
4117 PIO_STACK_LOCATION StackPtr
;
4118 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
4119 PKEVENT Event
= NULL
;
4120 BOOLEAN LocalEvent
= FALSE
;
4121 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
4123 IO_STATUS_BLOCK KernelIosb
;
4124 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
4126 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
4128 /* Check if we're called from user mode */
4129 if (PreviousMode
!= KernelMode
)
4131 /* Validate the information class */
4132 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
4133 !(IopSetFsOperationLength
[FsInformationClass
]))
4136 return STATUS_INVALID_INFO_CLASS
;
4139 /* Validate the length */
4140 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
4142 /* Invalid length */
4143 return STATUS_INFO_LENGTH_MISMATCH
;
4146 /* Enter SEH for probing */
4149 /* Probe the I/O Status block */
4150 ProbeForWriteIoStatusBlock(IoStatusBlock
);
4152 /* Probe the information */
4153 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
4155 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4157 /* Return the exception code */
4158 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4163 /* Get File Object */
4164 Status
= ObReferenceObjectByHandle(FileHandle
,
4165 IopSetFsOperationAccess
4166 [FsInformationClass
],
4169 (PVOID
*)&FileObject
,
4171 if (!NT_SUCCESS(Status
)) return Status
;
4173 /* Get target device for notification */
4174 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4175 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4177 /* Check if we should use Sync IO or not */
4178 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4181 Status
= IopLockFileObject(FileObject
, PreviousMode
);
4182 if (Status
!= STATUS_SUCCESS
)
4184 ObDereferenceObject(FileObject
);
4185 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4191 /* Use local event */
4192 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4195 ObDereferenceObject(FileObject
);
4196 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4197 return STATUS_INSUFFICIENT_RESOURCES
;
4199 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4203 /* Get the device object */
4204 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4206 /* Clear File Object event */
4207 KeClearEvent(&FileObject
->Event
);
4209 /* Allocate the IRP */
4210 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4213 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4214 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4217 /* Set up the IRP */
4218 Irp
->RequestorMode
= PreviousMode
;
4219 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4220 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4221 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4222 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4223 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4224 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4225 Irp
->UserBuffer
= FsInformation
;
4226 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4227 Irp
->MdlAddress
= NULL
;
4229 /* Set up Stack Data */
4230 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4231 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
4232 StackPtr
->FileObject
= FileObject
;
4237 /* Allocate a buffer */
4238 Irp
->AssociatedIrp
.SystemBuffer
=
4239 ExAllocatePoolWithTag(NonPagedPool
,
4243 /* Copy the data into it */
4244 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
4246 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4248 /* Allocating failed, clean up and return the exception code */
4249 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4250 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4251 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4255 /* Set the flags for this buffered + deferred I/O */
4256 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4258 /* Set Parameters */
4259 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
4260 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
4262 /* Call the Driver */
4263 Status
= IopPerformSynchronousRequest(DeviceObject
,
4271 /* Check if this was async I/O */
4274 /* It was, finalize this request */
4275 Status
= IopFinalizeAsynchronousIo(Status
,
4283 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
4285 /* Time to report change */
4286 NotificationStructure
.Version
= 1;
4287 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
4288 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
4289 NotificationStructure
.FileObject
= NULL
;
4290 NotificationStructure
.NameBufferOffset
= - 1;
4291 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
4303 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
4306 return STATUS_NOT_IMPLEMENTED
;
4314 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
4317 return STATUS_NOT_IMPLEMENTED
;