2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/iofunc.c
5 * PURPOSE: Generic I/O Functions that build IRPs for various operations
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Filip Navara (navaraf@reactos.org)
9 * Pierre Schweitzer (pierre@reactos.org)
12 /* INCLUDES *****************************************************************/
18 #include "internal/io_i.h"
20 /* PRIVATE FUNCTIONS *********************************************************/
24 IopCleanupAfterException(IN PFILE_OBJECT FileObject
,
26 IN PKEVENT Event OPTIONAL
,
27 IN PKEVENT LocalEvent OPTIONAL
)
30 IOTRACE(IO_API_DEBUG
, "IRP: %p. FO: %p \n", Irp
, FileObject
);
34 /* Check if we had a buffer */
35 if (Irp
->AssociatedIrp
.SystemBuffer
)
38 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
42 if (Irp
->MdlAddress
) IoFreeMdl(Irp
->MdlAddress
);
48 /* Check if we had a file lock */
49 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
52 IopUnlockFileObject(FileObject
);
55 /* Check if we had an event */
56 if (Event
) ObDereferenceObject(Event
);
58 /* Check if we had a local event */
59 if (LocalEvent
) ExFreePool(LocalEvent
);
61 /* Derefenrce the FO */
62 ObDereferenceObject(FileObject
);
67 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus
,
70 IN KPROCESSOR_MODE PreviousMode
,
71 IN PIO_STATUS_BLOCK KernelIosb
,
72 OUT PIO_STATUS_BLOCK IoStatusBlock
)
74 NTSTATUS FinalStatus
= SynchStatus
;
76 IOTRACE(IO_API_DEBUG
, "IRP: %p. Status: %lx \n", Irp
, SynchStatus
);
78 /* Make sure the IRP was completed, but returned pending */
79 if (FinalStatus
== STATUS_PENDING
)
81 /* Wait for the IRP */
82 FinalStatus
= KeWaitForSingleObject(Event
,
87 if (FinalStatus
== STATUS_USER_APC
)
89 /* Abort the request */
90 IopAbortInterruptedIrp(Event
, Irp
);
93 /* Set the final status */
94 FinalStatus
= KernelIosb
->Status
;
97 /* Wrap potential user-mode write in SEH */
100 *IoStatusBlock
= *KernelIosb
;
102 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
104 /* Get the exception code */
105 FinalStatus
= _SEH2_GetExceptionCode();
109 /* Free the event and return status */
116 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject
,
118 IN PFILE_OBJECT FileObject
,
120 IN KPROCESSOR_MODE PreviousMode
,
122 IN IOP_TRANSFER_TYPE TransferType
)
125 PKNORMAL_ROUTINE NormalRoutine
;
126 PVOID NormalContext
= NULL
;
129 IOTRACE(IO_API_DEBUG
, "IRP: %p. DO: %p. FO: %p \n",
130 Irp
, DeviceObject
, FileObject
);
133 IopQueueIrpToThread(Irp
);
135 /* Update operation counts */
136 IopUpdateOperationCount(TransferType
);
138 /* Call the driver */
139 Status
= IoCallDriver(DeviceObject
, Irp
);
141 /* Check if we're optimizing this case */
144 /* We are! Check if the IRP wasn't completed */
145 if (Status
!= STATUS_PENDING
)
147 /* Complete it ourselves */
148 ASSERT(!Irp
->PendingReturned
);
149 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
150 IopCompleteRequest(&Irp
->Tail
.Apc
,
155 KeLowerIrql(OldIrql
);
159 /* Check if this was synch I/O */
162 /* Make sure the IRP was completed, but returned pending */
163 if (Status
== STATUS_PENDING
)
165 /* Wait for the IRP */
166 Status
= KeWaitForSingleObject(&FileObject
->Event
,
170 FO_ALERTABLE_IO
) != 0,
172 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
174 /* Abort the request */
175 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
178 /* Set the final status */
179 Status
= FileObject
->FinalStatus
;
182 /* Release the file lock */
183 IopUnlockFileObject(FileObject
);
192 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
193 IN HANDLE Event OPTIONAL
,
194 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
195 IN PVOID UserApcContext OPTIONAL
,
196 OUT PIO_STATUS_BLOCK IoStatusBlock
,
197 IN ULONG IoControlCode
,
198 IN PVOID InputBuffer
,
199 IN ULONG InputBufferLength OPTIONAL
,
200 OUT PVOID OutputBuffer
,
201 IN ULONG OutputBufferLength OPTIONAL
,
202 IN BOOLEAN IsDevIoCtl
)
205 PFILE_OBJECT FileObject
;
206 PDEVICE_OBJECT DeviceObject
;
208 PIO_STACK_LOCATION StackPtr
;
209 PKEVENT EventObject
= NULL
;
210 BOOLEAN LockedForSynch
= FALSE
;
212 OBJECT_HANDLE_INFORMATION HandleInformation
;
213 ACCESS_MASK DesiredAccess
;
214 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
220 IOTRACE(IO_CTL_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
221 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
223 /* Get the access type */
224 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
226 /* Check if we came from user mode */
227 if (PreviousMode
!= KernelMode
)
231 /* Probe the status block */
232 ProbeForWriteIoStatusBlock(IoStatusBlock
);
234 /* Check if this is buffered I/O */
235 if (AccessType
== METHOD_BUFFERED
)
237 /* Check if we have an output buffer */
240 /* Probe the output buffer */
241 ProbeForWrite(OutputBuffer
,
247 /* Make sure the caller can't fake this as we depend on this */
248 OutputBufferLength
= 0;
252 /* Check if we we have an input buffer I/O */
253 if (AccessType
!= METHOD_NEITHER
)
255 /* Check if we have an input buffer */
258 /* Probe the input buffer */
259 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
263 /* Make sure the caller can't fake this as we depend on this */
264 InputBufferLength
= 0;
268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
270 /* Return the exception code */
271 _SEH2_YIELD(return _SEH2_GetExceptionCode());
276 /* Don't check for access rights right now, KernelMode can do anything */
277 Status
= ObReferenceObjectByHandle(DeviceHandle
,
283 if (!NT_SUCCESS(Status
)) return Status
;
285 /* Can't use an I/O completion port and an APC in the same time */
286 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
289 ObDereferenceObject(FileObject
);
290 return STATUS_INVALID_PARAMETER
;
293 /* Check if we from user mode */
294 if (PreviousMode
!= KernelMode
)
296 /* Get the access mask */
297 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
299 /* Check if we can open it */
300 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
301 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
303 /* Dereference the file object and fail */
304 ObDereferenceObject(FileObject
);
305 return STATUS_ACCESS_DENIED
;
309 /* Check for an event */
313 Status
= ObReferenceObjectByHandle(Event
,
317 (PVOID
*)&EventObject
,
319 if (!NT_SUCCESS(Status
))
321 /* Dereference the file object and fail */
322 ObDereferenceObject(FileObject
);
327 KeClearEvent(EventObject
);
330 /* Check if this is a file that was opened for Synch I/O */
331 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
334 IopLockFileObject(FileObject
);
336 /* Remember to unlock later */
337 LockedForSynch
= TRUE
;
340 /* Check if this is a direct open or not */
341 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
343 /* It's a direct open, get the attached device */
344 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
348 /* Otherwise get the related device */
349 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
352 /* If this is a device I/O, try to do it with FastIO path */
355 PFAST_IO_DISPATCH FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
357 /* Check whether FSD is FastIO aware and provide an appropriate routine */
358 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoDeviceControl
!= NULL
)
360 IO_STATUS_BLOCK KernelIosb
;
362 /* If we have an output buffer coming from usermode */
363 if (PreviousMode
!= KernelMode
&& OutputBuffer
!= NULL
)
365 /* Probe it according to its usage */
368 if (AccessType
== METHOD_IN_DIRECT
)
370 ProbeForRead(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
372 else if (AccessType
== METHOD_OUT_DIRECT
)
374 ProbeForWrite(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
377 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
379 /* Cleanup after exception and return */
380 IopCleanupAfterException(FileObject
, NULL
, EventObject
, NULL
);
382 /* Return the exception code */
383 _SEH2_YIELD(return _SEH2_GetExceptionCode());
388 /* If we are dismounting a volume, increase the dismount count */
389 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
391 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
395 if (FastIoDispatch
->FastIoDeviceControl(FileObject
,
405 IO_COMPLETION_CONTEXT CompletionInfo
= { NULL
, NULL
};
407 /* Write the IOSB back */
410 *IoStatusBlock
= KernelIosb
;
413 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
415 KernelIosb
.Status
= _SEH2_GetExceptionCode();
419 /* Backup our complete context in case it exists */
420 if (FileObject
->CompletionContext
)
422 CompletionInfo
= *(FileObject
->CompletionContext
);
425 /* If we had an event, signal it */
428 KeSetEvent(EventObject
, IO_NO_INCREMENT
, FALSE
);
429 ObDereferenceObject(EventObject
);
432 /* If FO was locked, unlock it */
435 IopUnlockFileObject(FileObject
);
438 /* Set completion if required */
439 if (CompletionInfo
.Port
!= NULL
&& UserApcContext
!= NULL
)
441 if (!NT_SUCCESS(IoSetIoCompletion(CompletionInfo
.Port
,
445 KernelIosb
.Information
,
448 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
452 /* We're done with FastIO! */
453 ObDereferenceObject(FileObject
);
454 return KernelIosb
.Status
;
459 /* Clear the event */
460 KeClearEvent(&FileObject
->Event
);
463 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
464 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
467 Irp
->UserIosb
= IoStatusBlock
;
468 Irp
->UserEvent
= EventObject
;
469 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
470 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
472 Irp
->CancelRoutine
= NULL
;
473 Irp
->PendingReturned
= FALSE
;
474 Irp
->RequestorMode
= PreviousMode
;
475 Irp
->MdlAddress
= NULL
;
476 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
478 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
479 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
480 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
482 /* Set stack location settings */
483 StackPtr
= IoGetNextIrpStackLocation(Irp
);
484 StackPtr
->FileObject
= FileObject
;
485 StackPtr
->MajorFunction
= IsDevIoCtl
?
486 IRP_MJ_DEVICE_CONTROL
:
487 IRP_MJ_FILE_SYSTEM_CONTROL
;
488 StackPtr
->MinorFunction
= 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
489 StackPtr
->Control
= 0;
491 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
493 /* Set the IOCTL Data */
494 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
495 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
496 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
499 PoolType
= IsDevIoCtl
? NonPagedPoolCacheAligned
: NonPagedPool
;
501 /* Handle the Methods */
505 case METHOD_BUFFERED
:
507 /* Enter SEH for allocations */
510 /* Select the right Buffer Length */
511 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
512 InputBufferLength
: OutputBufferLength
;
514 /* Make sure there is one */
517 /* Allocate the System Buffer */
518 Irp
->AssociatedIrp
.SystemBuffer
=
519 ExAllocatePoolWithQuotaTag(PoolType
,
523 /* Check if we got a buffer */
526 /* Copy into the System Buffer */
527 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
532 /* Write the flags */
533 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
534 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
536 /* Save the Buffer */
537 Irp
->UserBuffer
= OutputBuffer
;
541 /* Clear the Flags and Buffer */
542 Irp
->UserBuffer
= NULL
;
545 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
547 /* Cleanup after exception and return */
548 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
549 _SEH2_YIELD(return _SEH2_GetExceptionCode());
555 case METHOD_IN_DIRECT
:
556 case METHOD_OUT_DIRECT
:
561 /* Check if we got an input buffer */
562 if ((InputBufferLength
) && (InputBuffer
))
564 /* Allocate the System Buffer */
565 Irp
->AssociatedIrp
.SystemBuffer
=
566 ExAllocatePoolWithQuotaTag(PoolType
,
570 /* Copy into the System Buffer */
571 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
575 /* Write the flags */
576 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
579 /* Check if we got an output buffer */
582 /* Allocate the System Buffer */
583 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
588 if (!Irp
->MdlAddress
)
590 /* Raise exception we'll catch */
591 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
595 MmProbeAndLockPages(Irp
->MdlAddress
,
597 (AccessType
== METHOD_IN_DIRECT
) ?
598 IoReadAccess
: IoWriteAccess
);
601 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
603 /* Cleanup after exception and return */
604 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
605 _SEH2_YIELD(return _SEH2_GetExceptionCode());
612 /* Just save the Buffer */
613 Irp
->UserBuffer
= OutputBuffer
;
614 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
617 /* Use deferred completion for FS I/O */
620 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
623 /* If we are dismounting a volume, increaase the dismount count */
624 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
626 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
629 /* Perform the call */
630 return IopPerformSynchronousRequest(DeviceObject
,
641 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
642 IN ULONG InformationClass
,
644 OUT PVOID Information
,
645 OUT PULONG ReturnedLength
,
648 IO_STATUS_BLOCK IoStatusBlock
;
650 PDEVICE_OBJECT DeviceObject
;
651 PIO_STACK_LOCATION StackPtr
;
652 BOOLEAN LocalEvent
= FALSE
;
656 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
657 FileObject
, InformationClass
, File
);
659 /* Reference the object */
660 ObReferenceObject(FileObject
);
662 /* Check if this is a file that was opened for Synch I/O */
663 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
666 IopLockFileObject(FileObject
);
668 /* Use File Object event */
669 KeClearEvent(&FileObject
->Event
);
673 /* Use local event */
674 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
678 /* Get the Device Object */
679 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
681 /* Allocate the IRP */
682 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
683 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
686 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
687 Irp
->RequestorMode
= KernelMode
;
688 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
689 Irp
->UserIosb
= &IoStatusBlock
;
690 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
691 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
692 Irp
->Flags
|= IRP_BUFFERED_IO
;
693 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
694 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
696 /* Set the Stack Data */
697 StackPtr
= IoGetNextIrpStackLocation(Irp
);
698 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
699 IRP_MJ_QUERY_VOLUME_INFORMATION
;
700 StackPtr
->FileObject
= FileObject
;
702 /* Check which type this is */
706 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
707 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
712 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
713 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
717 IopQueueIrpToThread(Irp
);
719 /* Call the Driver */
720 Status
= IoCallDriver(DeviceObject
, Irp
);
722 /* Check if this was synch I/O */
725 /* Check if the request is pending */
726 if (Status
== STATUS_PENDING
)
728 /* Wait on the file object */
729 Status
= KeWaitForSingleObject(&FileObject
->Event
,
733 FO_ALERTABLE_IO
) != 0,
735 if (Status
== STATUS_ALERTED
)
737 /* Abort the operation */
738 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
741 /* Get the final status */
742 Status
= FileObject
->FinalStatus
;
745 /* Release the file lock */
746 IopUnlockFileObject(FileObject
);
748 else if (Status
== STATUS_PENDING
)
750 /* Wait on the local event and get the final status */
751 KeWaitForSingleObject(&Event
,
756 Status
= IoStatusBlock
.Status
;
759 /* Return the Length and Status. ReturnedLength is NOT optional */
760 *ReturnedLength
= (ULONG
)IoStatusBlock
.Information
;
766 IopGetFileInformation(IN PFILE_OBJECT FileObject
,
768 IN FILE_INFORMATION_CLASS FileInfoClass
,
770 OUT PULONG ReturnedLength
)
775 PIO_STACK_LOCATION Stack
;
776 PDEVICE_OBJECT DeviceObject
;
777 IO_STATUS_BLOCK IoStatusBlock
;
781 /* Allocate an IRP */
782 ObReferenceObject(FileObject
);
783 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
784 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
787 ObDereferenceObject(FileObject
);
788 return STATUS_INSUFFICIENT_RESOURCES
;
792 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
795 Irp
->UserIosb
= &IoStatusBlock
;
796 Irp
->UserEvent
= &Event
;
797 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
798 Irp
->RequestorMode
= KernelMode
;
799 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
800 Irp
->Flags
= IRP_SYNCHRONOUS_API
| IRP_BUFFERED_IO
| IRP_OB_QUERY_NAME
;
801 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
802 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
804 Stack
= IoGetNextIrpStackLocation(Irp
);
805 Stack
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
806 Stack
->FileObject
= FileObject
;
807 Stack
->Parameters
.QueryFile
.FileInformationClass
= FileInfoClass
;
808 Stack
->Parameters
.QueryFile
.Length
= Length
;
812 IopQueueIrpToThread(Irp
);
814 /* Call the driver */
815 Status
= IoCallDriver(DeviceObject
, Irp
);
816 if (Status
== STATUS_PENDING
)
818 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
819 Status
= IoStatusBlock
.Status
;
822 *ReturnedLength
= IoStatusBlock
.Information
;
828 IopGetBasicInformationFile(IN PFILE_OBJECT FileObject
,
829 OUT PFILE_BASIC_INFORMATION BasicInfo
)
831 ULONG ReturnedLength
;
832 PDEVICE_OBJECT DeviceObject
;
833 IO_STATUS_BLOCK IoStatusBlock
;
837 /* Try to do it the fast way if possible */
838 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
839 if (DeviceObject
->DriverObject
->FastIoDispatch
!= NULL
&&
840 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
&&
841 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo(FileObject
,
842 ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) != 0),
847 return IoStatusBlock
.Status
;
850 /* In case it failed, fall back to IRP-based method */
851 return IopGetFileInformation(FileObject
, sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
, BasicInfo
, &ReturnedLength
);
856 IopOpenLinkOrRenameTarget(OUT PHANDLE Handle
,
858 IN PFILE_RENAME_INFORMATION RenameInfo
,
859 IN PFILE_OBJECT FileObject
)
863 UNICODE_STRING FileName
;
864 PIO_STACK_LOCATION Stack
;
865 PFILE_OBJECT TargetFileObject
;
866 IO_STATUS_BLOCK IoStatusBlock
;
867 FILE_BASIC_INFORMATION BasicInfo
;
868 OBJECT_ATTRIBUTES ObjectAttributes
;
869 OBJECT_HANDLE_INFORMATION HandleInformation
;
870 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
874 /* First, establish whether our target is a directory */
875 if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
877 Status
= IopGetBasicInformationFile(FileObject
, &BasicInfo
);
878 if (!NT_SUCCESS(Status
))
883 if (BasicInfo
.FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
884 DesiredAccess
= FILE_ADD_SUBDIRECTORY
;
888 /* Setup the string to the target */
889 FileName
.Buffer
= RenameInfo
->FileName
;
890 FileName
.Length
= RenameInfo
->FileNameLength
;
891 FileName
.MaximumLength
= RenameInfo
->FileNameLength
;
893 InitializeObjectAttributes(&ObjectAttributes
,
895 (FileObject
->Flags
& FO_OPENED_CASE_SENSITIVE
? 0 : OBJ_CASE_INSENSITIVE
) | OBJ_KERNEL_HANDLE
,
896 RenameInfo
->RootDirectory
,
899 /* And open its parent directory */
900 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
902 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
904 /* Commented out - we don't support FO extension yet
905 * FIXME: Corrected last arg when it's supported
907 Status
= IoCreateFileSpecifyDeviceObjectHint(&TargetHandle
,
908 DesiredAccess
| SYNCHRONIZE
,
913 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
915 FILE_OPEN_FOR_BACKUP_INTENT
,
920 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
,
921 FileObject
->DeviceObject
);
925 return STATUS_NOT_IMPLEMENTED
;
930 Status
= IoCreateFile(&TargetHandle
,
931 DesiredAccess
| SYNCHRONIZE
,
936 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
938 FILE_OPEN_FOR_BACKUP_INTENT
,
943 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
);
946 if (!NT_SUCCESS(Status
))
951 /* Once open, continue only if:
952 * Target exists and we're allowed to overwrite it
954 Stack
= IoGetNextIrpStackLocation(Irp
);
955 if (Stack
->Parameters
.SetFile
.FileInformationClass
== FileLinkInformation
&&
956 !RenameInfo
->ReplaceIfExists
&&
957 IoStatusBlock
.Information
== FILE_EXISTS
)
959 ObCloseHandle(TargetHandle
, KernelMode
);
960 return STATUS_OBJECT_NAME_COLLISION
;
963 /* Now, we'll get the associated device of the target, to check for same device location
964 * So, get the FO first
966 Status
= ObReferenceObjectByHandle(TargetHandle
,
970 (PVOID
*)&TargetFileObject
,
972 if (!NT_SUCCESS(Status
))
974 ObCloseHandle(TargetHandle
, KernelMode
);
978 /* We can dereference, we have the handle */
979 ObDereferenceObject(TargetFileObject
);
980 /* If we're not on the same device, error out **/
981 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
983 ObCloseHandle(TargetHandle
, KernelMode
);
984 return STATUS_NOT_SAME_DEVICE
;
987 /* Return parent directory file object and handle */
988 Stack
->Parameters
.SetFile
.FileObject
= TargetFileObject
;
989 *Handle
= TargetHandle
;
991 return STATUS_SUCCESS
;
996 IopGetFileMode(IN PFILE_OBJECT FileObject
)
1000 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
1001 Mode
|= FILE_WRITE_THROUGH
;
1003 if (FileObject
->Flags
& FO_SEQUENTIAL_ONLY
)
1004 Mode
|= FILE_SEQUENTIAL_ONLY
;
1006 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
1007 Mode
|= FILE_NO_INTERMEDIATE_BUFFERING
;
1009 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1011 if (FileObject
->Flags
& FO_ALERTABLE_IO
)
1012 Mode
|= FILE_SYNCHRONOUS_IO_ALERT
;
1014 Mode
|= FILE_SYNCHRONOUS_IO_NONALERT
;
1017 if (FileObject
->Flags
& FO_DELETE_ON_CLOSE
)
1018 Mode
|= FILE_DELETE_ON_CLOSE
;
1023 /* PUBLIC FUNCTIONS **********************************************************/
1030 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
1032 IN PLARGE_INTEGER Offset
,
1034 IN PIO_STATUS_BLOCK StatusBlock
)
1037 PIO_STACK_LOCATION StackPtr
;
1038 PDEVICE_OBJECT DeviceObject
;
1039 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1040 FileObject
, Mdl
, Offset
);
1042 /* Get the Device Object */
1043 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1046 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1047 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1050 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1052 /* Create the IRP Settings */
1053 Irp
->MdlAddress
= Mdl
;
1054 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1055 Irp
->UserIosb
= StatusBlock
;
1056 Irp
->UserEvent
= Event
;
1057 Irp
->RequestorMode
= KernelMode
;
1058 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
1059 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1060 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1062 /* Set the Stack Settings */
1063 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
1064 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
1065 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
1066 StackPtr
->FileObject
= FileObject
;
1068 /* Call the Driver */
1069 return IoCallDriver(DeviceObject
, Irp
);
1077 IoPageRead(IN PFILE_OBJECT FileObject
,
1079 IN PLARGE_INTEGER Offset
,
1081 IN PIO_STATUS_BLOCK StatusBlock
)
1084 PIO_STACK_LOCATION StackPtr
;
1085 PDEVICE_OBJECT DeviceObject
;
1086 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1087 FileObject
, Mdl
, Offset
);
1089 /* Get the Device Object */
1090 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1093 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1094 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1097 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1099 /* Create the IRP Settings */
1100 Irp
->MdlAddress
= Mdl
;
1101 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1102 Irp
->UserIosb
= StatusBlock
;
1103 Irp
->UserEvent
= Event
;
1104 Irp
->RequestorMode
= KernelMode
;
1105 Irp
->Flags
= IRP_PAGING_IO
|
1107 IRP_SYNCHRONOUS_PAGING_IO
|
1108 IRP_INPUT_OPERATION
;
1109 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1110 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1112 /* Set the Stack Settings */
1113 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
1114 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
1115 StackPtr
->MajorFunction
= IRP_MJ_READ
;
1116 StackPtr
->FileObject
= FileObject
;
1118 /* Call the Driver */
1119 return IoCallDriver(DeviceObject
, Irp
);
1127 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1128 IN FILE_INFORMATION_CLASS FileInformationClass
,
1130 OUT PVOID FileInformation
,
1131 OUT PULONG ReturnedLength
)
1133 /* Call the shared routine */
1134 return IopQueryDeviceInformation(FileObject
,
1135 FileInformationClass
,
1147 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
1148 IN FS_INFORMATION_CLASS FsInformationClass
,
1150 OUT PVOID FsInformation
,
1151 OUT PULONG ReturnedLength
)
1153 /* Call the shared routine */
1154 return IopQueryDeviceInformation(FileObject
,
1167 IoSetInformation(IN PFILE_OBJECT FileObject
,
1168 IN FILE_INFORMATION_CLASS FileInformationClass
,
1170 IN PVOID FileInformation
)
1172 IO_STATUS_BLOCK IoStatusBlock
;
1174 PDEVICE_OBJECT DeviceObject
;
1175 PIO_STACK_LOCATION StackPtr
;
1176 BOOLEAN LocalEvent
= FALSE
;
1180 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
1181 FileObject
, FileInformationClass
, Length
);
1183 /* Reference the object */
1184 ObReferenceObject(FileObject
);
1186 /* Check if this is a file that was opened for Synch I/O */
1187 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1190 IopLockFileObject(FileObject
);
1192 /* Use File Object event */
1193 KeClearEvent(&FileObject
->Event
);
1197 /* Use local event */
1198 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1202 /* Get the Device Object */
1203 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1205 /* Allocate the IRP */
1206 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1207 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1210 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1211 Irp
->RequestorMode
= KernelMode
;
1212 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1213 Irp
->UserIosb
= &IoStatusBlock
;
1214 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1215 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1216 Irp
->Flags
|= IRP_BUFFERED_IO
;
1217 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1218 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1220 /* Set the Stack Data */
1221 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1222 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
1223 StackPtr
->FileObject
= FileObject
;
1225 /* Set Parameters */
1226 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
1227 StackPtr
->Parameters
.SetFile
.Length
= Length
;
1230 IopQueueIrpToThread(Irp
);
1232 /* Call the Driver */
1233 Status
= IoCallDriver(DeviceObject
, Irp
);
1235 /* Check if this was synch I/O */
1238 /* Check if the request is pending */
1239 if (Status
== STATUS_PENDING
)
1241 /* Wait on the file object */
1242 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1245 (FileObject
->Flags
&
1246 FO_ALERTABLE_IO
) != 0,
1248 if (Status
== STATUS_ALERTED
)
1250 /* Abort the operation */
1251 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1254 /* Get the final status */
1255 Status
= FileObject
->FinalStatus
;
1258 /* Release the file lock */
1259 IopUnlockFileObject(FileObject
);
1261 else if (Status
== STATUS_PENDING
)
1263 /* Wait on the local event and get the final status */
1264 KeWaitForSingleObject(&Event
,
1269 Status
= IoStatusBlock
.Status
;
1272 /* Return the status */
1276 /* NATIVE SERVICES ***********************************************************/
1283 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1284 IN HANDLE Event OPTIONAL
,
1285 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1286 IN PVOID UserApcContext OPTIONAL
,
1287 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1288 IN ULONG IoControlCode
,
1289 IN PVOID InputBuffer
,
1290 IN ULONG InputBufferLength OPTIONAL
,
1291 OUT PVOID OutputBuffer
,
1292 IN ULONG OutputBufferLength OPTIONAL
)
1294 /* Call the Generic Function */
1295 return IopDeviceFsIoControl(DeviceHandle
,
1313 NtFsControlFile(IN HANDLE DeviceHandle
,
1314 IN HANDLE Event OPTIONAL
,
1315 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1316 IN PVOID UserApcContext OPTIONAL
,
1317 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1318 IN ULONG IoControlCode
,
1319 IN PVOID InputBuffer
,
1320 IN ULONG InputBufferLength OPTIONAL
,
1321 OUT PVOID OutputBuffer
,
1322 IN ULONG OutputBufferLength OPTIONAL
)
1324 /* Call the Generic Function */
1325 return IopDeviceFsIoControl(DeviceHandle
,
1340 NtFlushBuffersFile(IN HANDLE FileHandle
,
1341 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1343 PFILE_OBJECT FileObject
;
1345 PIO_STACK_LOCATION StackPtr
;
1347 PDEVICE_OBJECT DeviceObject
;
1348 PKEVENT Event
= NULL
;
1349 BOOLEAN LocalEvent
= FALSE
;
1350 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1351 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1352 IO_STATUS_BLOCK KernelIosb
;
1354 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1356 if (PreviousMode
!= KernelMode
)
1358 /* Protect probes */
1361 /* Probe the I/O Status block */
1362 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1364 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1366 /* Return the exception code */
1367 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1372 /* Get the File Object */
1373 Status
= ObReferenceObjectByHandle(FileHandle
,
1377 (PVOID
*)&FileObject
,
1379 if (!NT_SUCCESS(Status
)) return Status
;
1382 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1383 * granted. However, if this is a named pipe, make sure we don't ask for
1384 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1387 if (!(ObjectHandleInfo
.GrantedAccess
&
1388 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1392 ObDereferenceObject(FileObject
);
1393 return STATUS_ACCESS_DENIED
;
1396 /* Check if we should use Sync IO or not */
1397 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1400 IopLockFileObject(FileObject
);
1404 /* Use local event */
1405 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1409 ObDereferenceObject(FileObject
);
1410 return STATUS_INSUFFICIENT_RESOURCES
;
1412 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1416 /* Get the Device Object */
1417 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1419 /* Clear the event */
1420 KeClearEvent(&FileObject
->Event
);
1422 /* Allocate the IRP */
1423 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1424 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1426 /* Set up the IRP */
1427 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1428 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1429 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1430 Irp
->RequestorMode
= PreviousMode
;
1431 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1432 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1433 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1435 /* Set up Stack Data */
1436 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1437 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1438 StackPtr
->FileObject
= FileObject
;
1440 /* Call the Driver */
1441 Status
= IopPerformSynchronousRequest(DeviceObject
,
1449 /* Check if this was async I/O */
1452 /* It was, finalize this request */
1453 Status
= IopFinalizeAsynchronousIo(Status
,
1461 /* Return the Status */
1470 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1471 IN HANDLE EventHandle OPTIONAL
,
1472 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1473 IN PVOID ApcContext OPTIONAL
,
1474 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1476 IN ULONG BufferSize
,
1477 IN ULONG CompletionFilter
,
1478 IN BOOLEAN WatchTree
)
1481 PKEVENT Event
= NULL
;
1482 PDEVICE_OBJECT DeviceObject
;
1483 PFILE_OBJECT FileObject
;
1484 PIO_STACK_LOCATION IoStack
;
1485 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1487 BOOLEAN LockedForSync
= FALSE
;
1489 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1491 /* Check if we're called from user mode */
1492 if (PreviousMode
!= KernelMode
)
1494 /* Enter SEH for probing */
1497 /* Probe the I/O STatus block */
1498 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1500 /* Probe the buffer */
1501 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1503 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1505 /* Return the exception code */
1506 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1510 /* Check if CompletionFilter is valid */
1511 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1513 return STATUS_INVALID_PARAMETER
;
1517 /* Get File Object */
1518 Status
= ObReferenceObjectByHandle(FileHandle
,
1519 FILE_LIST_DIRECTORY
,
1522 (PVOID
*)&FileObject
,
1524 if (!NT_SUCCESS(Status
)) return Status
;
1526 /* Check if we have an event handle */
1530 Status
= ObReferenceObjectByHandle(EventHandle
,
1536 if (Status
!= STATUS_SUCCESS
)
1538 ObDereferenceObject(FileObject
);
1541 KeClearEvent(Event
);
1544 /* Check if we should use Sync IO or not */
1545 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1548 IopLockFileObject(FileObject
);
1549 LockedForSync
= TRUE
;
1552 /* Clear File Object event */
1553 KeClearEvent(&FileObject
->Event
);
1555 /* Get the device object */
1556 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1558 /* Allocate the IRP */
1559 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1560 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1562 /* Set up the IRP */
1563 Irp
->RequestorMode
= PreviousMode
;
1564 Irp
->UserIosb
= IoStatusBlock
;
1565 Irp
->UserEvent
= Event
;
1566 Irp
->UserBuffer
= Buffer
;
1567 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1568 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1569 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1570 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1572 /* Set up Stack Data */
1573 IoStack
= IoGetNextIrpStackLocation(Irp
);
1574 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1575 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1576 IoStack
->FileObject
= FileObject
;
1578 /* Set parameters */
1579 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1580 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1581 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1583 /* Perform the call */
1584 return IopPerformSynchronousRequest(DeviceObject
,
1598 NtLockFile(IN HANDLE FileHandle
,
1599 IN HANDLE EventHandle OPTIONAL
,
1600 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1601 IN PVOID ApcContext OPTIONAL
,
1602 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1603 IN PLARGE_INTEGER ByteOffset
,
1604 IN PLARGE_INTEGER Length
,
1606 IN BOOLEAN FailImmediately
,
1607 IN BOOLEAN ExclusiveLock
)
1609 PFILE_OBJECT FileObject
;
1610 PLARGE_INTEGER LocalLength
= NULL
;
1612 PIO_STACK_LOCATION StackPtr
;
1613 PDEVICE_OBJECT DeviceObject
;
1614 PKEVENT Event
= NULL
;
1615 BOOLEAN LockedForSync
= FALSE
;
1616 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1617 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1619 OBJECT_HANDLE_INFORMATION HandleInformation
;
1620 PFAST_IO_DISPATCH FastIoDispatch
;
1622 CapturedByteOffset
.QuadPart
= 0;
1623 CapturedLength
.QuadPart
= 0;
1624 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1626 /* Get File Object */
1627 Status
= ObReferenceObjectByHandle(FileHandle
,
1631 (PVOID
*)&FileObject
,
1632 &HandleInformation
);
1633 if (!NT_SUCCESS(Status
)) return Status
;
1635 /* Check if we're called from user mode */
1636 if (PreviousMode
!= KernelMode
)
1638 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1639 if (!(HandleInformation
.GrantedAccess
&
1640 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1642 ObDereferenceObject(FileObject
);
1643 return STATUS_ACCESS_DENIED
;
1646 /* Enter SEH for probing */
1649 /* Probe the I/O STatus block */
1650 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1652 /* Probe and capture the large integers */
1653 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1654 CapturedLength
= ProbeForReadLargeInteger(Length
);
1656 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1658 /* Dereference the object and return exception code */
1659 ObDereferenceObject(FileObject
);
1660 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1666 /* Otherwise, capture them directly */
1667 CapturedByteOffset
= *ByteOffset
;
1668 CapturedLength
= *Length
;
1671 /* Check if we have an event handle */
1675 Status
= ObReferenceObjectByHandle(EventHandle
,
1681 if (Status
!= STATUS_SUCCESS
) return Status
;
1682 KeClearEvent(Event
);
1685 /* Get the device object */
1686 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1688 /* Try to do it the FastIO way if possible */
1689 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1690 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoLock
!= NULL
)
1692 IO_STATUS_BLOCK KernelIosb
;
1694 if (FastIoDispatch
->FastIoLock(FileObject
,
1695 &CapturedByteOffset
,
1697 PsGetCurrentProcess(),
1704 /* Write the IOSB back */
1707 *IoStatusBlock
= KernelIosb
;
1709 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1711 KernelIosb
.Status
= _SEH2_GetExceptionCode();
1715 /* If we had an event, signal it */
1718 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1719 ObDereferenceObject(Event
);
1722 /* Set completion if required */
1723 if (FileObject
->CompletionContext
!= NULL
&& ApcContext
!= NULL
)
1725 if (!NT_SUCCESS(IoSetIoCompletion(FileObject
->CompletionContext
->Port
,
1726 FileObject
->CompletionContext
->Key
,
1729 KernelIosb
.Information
,
1732 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1736 FileObject
->LockOperation
= TRUE
;
1738 /* We're done with FastIO! */
1739 ObDereferenceObject(FileObject
);
1740 return KernelIosb
.Status
;
1744 /* Check if we should use Sync IO or not */
1745 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1748 IopLockFileObject(FileObject
);
1749 LockedForSync
= TRUE
;
1752 /* Clear File Object event */
1753 KeClearEvent(&FileObject
->Event
);
1754 FileObject
->LockOperation
= TRUE
;
1756 /* Allocate the IRP */
1757 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1758 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1760 /* Set up the IRP */
1761 Irp
->RequestorMode
= PreviousMode
;
1762 Irp
->UserIosb
= IoStatusBlock
;
1763 Irp
->UserEvent
= Event
;
1764 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1765 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1766 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1767 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1769 /* Set up Stack Data */
1770 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1771 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1772 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1773 StackPtr
->FileObject
= FileObject
;
1775 /* Allocate local buffer */
1776 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1777 sizeof(LARGE_INTEGER
),
1781 /* Allocating failed, clean up and return failure */
1782 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1783 return STATUS_INSUFFICIENT_RESOURCES
;
1786 /* Set the length */
1787 *LocalLength
= CapturedLength
;
1788 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1789 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1791 /* Set Parameters */
1792 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1793 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1796 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1797 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1799 /* Perform the call */
1800 return IopPerformSynchronousRequest(DeviceObject
,
1814 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1815 IN HANDLE EventHandle OPTIONAL
,
1816 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1817 IN PVOID ApcContext OPTIONAL
,
1818 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1819 OUT PVOID FileInformation
,
1821 IN FILE_INFORMATION_CLASS FileInformationClass
,
1822 IN BOOLEAN ReturnSingleEntry
,
1823 IN PUNICODE_STRING FileName OPTIONAL
,
1824 IN BOOLEAN RestartScan
)
1827 PDEVICE_OBJECT DeviceObject
;
1828 PFILE_OBJECT FileObject
;
1829 PIO_STACK_LOCATION StackPtr
;
1830 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1832 BOOLEAN LockedForSynch
= FALSE
;
1833 PKEVENT Event
= NULL
;
1834 volatile PVOID AuxBuffer
= NULL
;
1836 UNICODE_STRING CapturedFileName
;
1837 PUNICODE_STRING SearchPattern
;
1839 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1841 /* Check if we came from user mode */
1842 if (PreviousMode
!= KernelMode
)
1844 /* Enter SEH for probing */
1847 /* Probe the I/O Status Block */
1848 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1850 /* Probe the file information */
1851 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1853 /* Check if we have a file name */
1857 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1858 if (CapturedFileName
.Length
)
1860 /* Probe its buffer */
1861 ProbeForRead(CapturedFileName
.Buffer
,
1862 CapturedFileName
.Length
,
1866 /* Allocate the auxiliary buffer */
1867 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1868 CapturedFileName
.Length
+
1869 sizeof(UNICODE_STRING
),
1871 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1872 sizeof(UNICODE_STRING
)),
1873 CapturedFileName
.Buffer
,
1874 CapturedFileName
.Length
);
1876 /* Setup the search pattern */
1877 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1878 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1879 sizeof(UNICODE_STRING
));
1880 SearchPattern
->Length
= CapturedFileName
.Length
;
1881 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1884 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1886 /* Free buffer and return the exception code */
1887 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1888 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1893 /* Get File Object */
1894 Status
= ObReferenceObjectByHandle(FileHandle
,
1895 FILE_LIST_DIRECTORY
,
1898 (PVOID
*)&FileObject
,
1900 if (!NT_SUCCESS(Status
))
1903 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1907 /* Are there two associated completion routines? */
1908 if (FileObject
->CompletionContext
!= NULL
&& ApcRoutine
!= NULL
)
1910 ObDereferenceObject(FileObject
);
1911 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1912 return STATUS_INVALID_PARAMETER
;
1915 /* Check if we have an even handle */
1918 /* Get its pointer */
1919 Status
= ObReferenceObjectByHandle(EventHandle
,
1925 if (!NT_SUCCESS(Status
))
1928 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1929 ObDereferenceObject(FileObject
);
1934 KeClearEvent(Event
);
1937 /* Check if this is a file that was opened for Synch I/O */
1938 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1941 IopLockFileObject(FileObject
);
1943 /* Remember to unlock later */
1944 LockedForSynch
= TRUE
;
1947 /* Get the device object */
1948 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1950 /* Clear the File Object's event */
1951 KeClearEvent(&FileObject
->Event
);
1953 /* Allocate the IRP */
1954 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1955 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1957 /* Set up the IRP */
1958 Irp
->RequestorMode
= PreviousMode
;
1959 Irp
->UserIosb
= IoStatusBlock
;
1960 Irp
->UserEvent
= Event
;
1961 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1962 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1963 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1964 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1965 Irp
->MdlAddress
= NULL
;
1966 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1967 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1969 /* Check if this is buffered I/O */
1970 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1972 /* Allocate a buffer */
1973 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1976 if (!Irp
->AssociatedIrp
.SystemBuffer
)
1978 /* Allocating failed, clean up and return the exception code */
1979 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1980 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1982 /* Return the exception code */
1983 return STATUS_INSUFFICIENT_RESOURCES
;
1986 /* Set the buffer and flags */
1987 Irp
->UserBuffer
= FileInformation
;
1988 Irp
->Flags
= (IRP_BUFFERED_IO
|
1989 IRP_DEALLOCATE_BUFFER
|
1990 IRP_INPUT_OPERATION
);
1992 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1996 /* Allocate an MDL */
1997 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1998 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1999 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2001 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2003 /* Allocating failed, clean up and return the exception code */
2004 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2005 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2011 /* No allocation flags, and use the buffer directly */
2012 Irp
->UserBuffer
= FileInformation
;
2015 /* Set up Stack Data */
2016 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2017 StackPtr
->FileObject
= FileObject
;
2018 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2019 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2021 /* Set Parameters */
2022 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
2023 FileInformationClass
;
2024 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
2025 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2026 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2027 StackPtr
->Flags
= 0;
2028 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2029 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2031 /* Set deferred I/O */
2032 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
2034 /* Perform the call */
2035 return IopPerformSynchronousRequest(DeviceObject
,
2049 NtQueryEaFile(IN HANDLE FileHandle
,
2050 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2053 IN BOOLEAN ReturnSingleEntry
,
2054 IN PVOID EaList OPTIONAL
,
2055 IN ULONG EaListLength
,
2056 IN PULONG EaIndex OPTIONAL
,
2057 IN BOOLEAN RestartScan
)
2060 return STATUS_NOT_IMPLEMENTED
;
2068 NtQueryInformationFile(IN HANDLE FileHandle
,
2069 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2070 IN PVOID FileInformation
,
2072 IN FILE_INFORMATION_CLASS FileInformationClass
)
2074 OBJECT_HANDLE_INFORMATION HandleInformation
;
2075 PFILE_OBJECT FileObject
;
2078 PDEVICE_OBJECT DeviceObject
;
2079 PIO_STACK_LOCATION StackPtr
;
2080 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2081 PKEVENT Event
= NULL
;
2082 BOOLEAN LocalEvent
= FALSE
;
2083 PKNORMAL_ROUTINE NormalRoutine
;
2084 PVOID NormalContext
;
2086 IO_STATUS_BLOCK KernelIosb
;
2087 BOOLEAN CallDriver
= TRUE
;
2088 PFILE_ACCESS_INFORMATION AccessBuffer
;
2089 PFILE_MODE_INFORMATION ModeBuffer
;
2090 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer
;
2091 PFILE_ALL_INFORMATION AllBuffer
;
2092 PFAST_IO_DISPATCH FastIoDispatch
;
2094 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2096 /* Check if we're called from user mode */
2097 if (PreviousMode
!= KernelMode
)
2099 /* Validate the information class */
2100 if ((FileInformationClass
>= FileMaximumInformation
) ||
2101 !(IopQueryOperationLength
[FileInformationClass
]))
2104 return STATUS_INVALID_INFO_CLASS
;
2107 /* Validate the length */
2108 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2110 /* Invalid length */
2111 return STATUS_INFO_LENGTH_MISMATCH
;
2114 /* Enter SEH for probing */
2117 /* Probe the I/O Status block */
2118 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2120 /* Probe the information */
2121 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2123 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2125 /* Return the exception code */
2126 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2133 /* Validate the information class */
2134 if ((FileInformationClass
>= FileMaximumInformation
) ||
2135 !(IopQueryOperationLength
[FileInformationClass
]))
2138 return STATUS_INVALID_INFO_CLASS
;
2141 /* Validate the length */
2142 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2144 /* Invalid length */
2145 return STATUS_INFO_LENGTH_MISMATCH
;
2150 /* Reference the Handle */
2151 Status
= ObReferenceObjectByHandle(FileHandle
,
2152 IopQueryOperationAccess
2153 [FileInformationClass
],
2156 (PVOID
*)&FileObject
,
2157 &HandleInformation
);
2158 if (!NT_SUCCESS(Status
)) return Status
;
2160 /* Check if this is a direct open or not */
2161 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2163 /* Get the device object */
2164 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2168 /* Get the device object */
2169 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2172 /* Check if this is a file that was opened for Synch I/O */
2173 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2176 IopLockFileObject(FileObject
);
2178 /* Check if the caller just wants the position */
2179 if (FileInformationClass
== FilePositionInformation
)
2181 /* Protect write in SEH */
2184 /* Write the offset */
2185 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2186 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2188 /* Fill out the I/O Status Block */
2189 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2190 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2192 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2194 /* Get the exception code */
2195 Status
= _SEH2_GetExceptionCode();
2199 /* Release the file lock, dereference the file and return */
2200 IopUnlockFileObject(FileObject
);
2201 ObDereferenceObject(FileObject
);
2207 /* Use local event */
2208 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2211 ObDereferenceObject(FileObject
);
2212 return STATUS_INSUFFICIENT_RESOURCES
;
2214 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2218 /* Check if FastIO is possible for the two available information classes */
2219 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2220 if (FastIoDispatch
!= NULL
&&
2221 ((FileInformationClass
== FileBasicInformation
&& FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
) ||
2222 (FileInformationClass
== FileStandardInformation
&& FastIoDispatch
->FastIoQueryStandardInfo
!= NULL
)))
2224 BOOLEAN Success
= FALSE
;
2226 if (FileInformationClass
== FileBasicInformation
)
2228 Success
= FastIoDispatch
->FastIoQueryBasicInfo(FileObject
, TRUE
,
2235 Success
= FastIoDispatch
->FastIoQueryStandardInfo(FileObject
, TRUE
,
2241 /* If call succeed */
2244 /* Write the IOSB back */
2247 *IoStatusBlock
= KernelIosb
;
2249 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2251 KernelIosb
.Status
= _SEH2_GetExceptionCode();
2255 /* Free the event if we had one */
2258 ExFreePoolWithTag(Event
, TAG_IO
);
2261 /* If FO was locked, unlock it */
2262 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2264 IopUnlockFileObject(FileObject
);
2267 /* We're done with FastIO! */
2268 ObDereferenceObject(FileObject
);
2269 return KernelIosb
.Status
;
2273 /* Clear the File Object event */
2274 KeClearEvent(&FileObject
->Event
);
2276 /* Allocate the IRP */
2277 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2278 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2281 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2282 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2283 Irp
->RequestorMode
= PreviousMode
;
2284 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2285 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2286 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2287 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2288 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2289 Irp
->MdlAddress
= NULL
;
2290 Irp
->UserBuffer
= FileInformation
;
2292 /* Set the Stack Data */
2293 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2294 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2295 StackPtr
->FileObject
= FileObject
;
2300 /* Allocate a buffer */
2301 Irp
->AssociatedIrp
.SystemBuffer
=
2302 ExAllocatePoolWithTag(NonPagedPool
,
2306 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2308 /* Allocating failed, clean up and return the exception code */
2309 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2310 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2315 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2316 IRP_DEALLOCATE_BUFFER
|
2317 IRP_INPUT_OPERATION
|
2318 IRP_DEFER_IO_COMPLETION
);
2320 /* Set the Parameters */
2321 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2322 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2325 IopQueueIrpToThread(Irp
);
2327 /* Update operation counts */
2328 IopUpdateOperationCount(IopOtherTransfer
);
2330 /* Fill in file information before calling the driver.
2331 See 'File System Internals' page 485.*/
2332 if (FileInformationClass
== FileAccessInformation
)
2334 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2335 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2336 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2339 else if (FileInformationClass
== FileModeInformation
)
2341 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2342 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2343 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2346 else if (FileInformationClass
== FileAlignmentInformation
)
2348 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2349 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2350 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2353 else if (FileInformationClass
== FileAllInformation
)
2355 AllBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2356 AllBuffer
->AccessInformation
.AccessFlags
= HandleInformation
.GrantedAccess
;
2357 AllBuffer
->ModeInformation
.Mode
= IopGetFileMode(FileObject
);
2358 AllBuffer
->AlignmentInformation
.AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2359 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
) +
2360 sizeof(FILE_MODE_INFORMATION
) +
2361 sizeof(FILE_ALIGNMENT_INFORMATION
);
2364 /* Call the Driver */
2367 Status
= IoCallDriver(DeviceObject
, Irp
);
2371 Status
= STATUS_SUCCESS
;
2372 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2375 if (Status
== STATUS_PENDING
)
2377 /* Check if this was async I/O */
2380 /* Then to a non-alertable wait */
2381 Status
= KeWaitForSingleObject(Event
,
2386 if (Status
== STATUS_USER_APC
)
2388 /* Abort the request */
2389 IopAbortInterruptedIrp(Event
, Irp
);
2392 /* Set the final status */
2393 Status
= KernelIosb
.Status
;
2395 /* Enter SEH to write the IOSB back */
2398 /* Write it back to the caller */
2399 *IoStatusBlock
= KernelIosb
;
2401 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2403 /* Get the exception code */
2404 Status
= _SEH2_GetExceptionCode();
2408 /* Free the event */
2409 ExFreePoolWithTag(Event
, TAG_IO
);
2413 /* Wait for the IRP */
2414 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2417 (FileObject
->Flags
&
2418 FO_ALERTABLE_IO
) != 0,
2420 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2422 /* Abort the request */
2423 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2426 /* Set the final status */
2427 Status
= FileObject
->FinalStatus
;
2429 /* Release the file lock */
2430 IopUnlockFileObject(FileObject
);
2435 /* Free the event if we had one */
2438 /* Clear it in the IRP for completion */
2439 Irp
->UserEvent
= NULL
;
2440 ExFreePoolWithTag(Event
, TAG_IO
);
2443 /* Set the caller IOSB */
2444 Irp
->UserIosb
= IoStatusBlock
;
2446 /* The IRP wasn't completed, complete it ourselves */
2447 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2448 IopCompleteRequest(&Irp
->Tail
.Apc
,
2451 (PVOID
*)&FileObject
,
2453 KeLowerIrql(OldIrql
);
2455 /* Release the file object if we had locked it*/
2456 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2459 /* Return the Status */
2468 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2469 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2472 IN BOOLEAN ReturnSingleEntry
,
2473 IN PVOID SidList OPTIONAL
,
2474 IN ULONG SidListLength
,
2475 IN PSID StartSid OPTIONAL
,
2476 IN BOOLEAN RestartScan
)
2479 return STATUS_NOT_IMPLEMENTED
;
2487 NtReadFile(IN HANDLE FileHandle
,
2488 IN HANDLE Event OPTIONAL
,
2489 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2490 IN PVOID ApcContext OPTIONAL
,
2491 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2494 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2495 IN PULONG Key OPTIONAL
)
2498 PFILE_OBJECT FileObject
;
2500 PDEVICE_OBJECT DeviceObject
;
2501 PIO_STACK_LOCATION StackPtr
;
2502 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2503 PKEVENT EventObject
= NULL
;
2504 LARGE_INTEGER CapturedByteOffset
;
2505 ULONG CapturedKey
= 0;
2506 BOOLEAN Synchronous
= FALSE
;
2508 PFAST_IO_DISPATCH FastIoDispatch
;
2509 IO_STATUS_BLOCK KernelIosb
;
2513 CapturedByteOffset
.QuadPart
= 0;
2514 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2516 /* Validate User-Mode Buffers */
2517 if (PreviousMode
!= KernelMode
)
2521 /* Probe the status block */
2522 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2524 /* Probe the read buffer */
2525 ProbeForWrite(Buffer
, Length
, 1);
2527 /* Check if we got a byte offset */
2530 /* Capture and probe it */
2531 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2534 /* Capture and probe the key */
2535 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2537 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2539 /* Return the exception code */
2540 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2546 /* Kernel mode: capture directly */
2547 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2548 if (Key
) CapturedKey
= *Key
;
2551 /* Get File Object */
2552 Status
= ObReferenceObjectByHandle(FileHandle
,
2556 (PVOID
*)&FileObject
,
2558 if (!NT_SUCCESS(Status
)) return Status
;
2560 /* Check for event */
2564 Status
= ObReferenceObjectByHandle(Event
,
2568 (PVOID
*)&EventObject
,
2570 if (!NT_SUCCESS(Status
))
2573 ObDereferenceObject(FileObject
);
2577 /* Otherwise reset the event */
2578 KeClearEvent(EventObject
);
2581 /* Get the device object */
2582 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2584 /* Check if we should use Sync IO or not */
2585 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2587 /* Lock the file object */
2588 IopLockFileObject(FileObject
);
2590 /* Check if we don't have a byte offset available */
2591 if (!(ByteOffset
) ||
2592 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2593 (CapturedByteOffset
.u
.HighPart
== -1)))
2595 /* Use the Current Byte Offset instead */
2596 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2599 /* If the file is cached, try fast I/O */
2600 if (FileObject
->PrivateCacheMap
)
2602 /* Perform fast read */
2603 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2604 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoRead
!= NULL
);
2606 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2607 &CapturedByteOffset
,
2615 /* Only accept the result if we got a straightforward status */
2617 (KernelIosb
.Status
== STATUS_SUCCESS
||
2618 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2619 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2621 /* Fast path -- update transfer & operation counts */
2622 IopUpdateOperationCount(IopReadTransfer
);
2623 IopUpdateTransferCount(IopReadTransfer
,
2624 (ULONG
)KernelIosb
.Information
);
2626 /* Enter SEH to write the IOSB back */
2629 /* Write it back to the caller */
2630 *IoStatusBlock
= KernelIosb
;
2632 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2634 /* The caller's IOSB was invalid, so fail */
2635 if (EventObject
) ObDereferenceObject(EventObject
);
2636 IopUnlockFileObject(FileObject
);
2637 ObDereferenceObject(FileObject
);
2638 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2642 /* Signal the completion event */
2645 KeSetEvent(EventObject
, 0, FALSE
);
2646 ObDereferenceObject(EventObject
);
2650 IopUnlockFileObject(FileObject
);
2651 ObDereferenceObject(FileObject
);
2652 return KernelIosb
.Status
;
2656 /* Remember we are sync */
2659 else if (!(ByteOffset
) &&
2660 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2662 /* Otherwise, this was async I/O without a byte offset, so fail */
2663 if (EventObject
) ObDereferenceObject(EventObject
);
2664 ObDereferenceObject(FileObject
);
2665 return STATUS_INVALID_PARAMETER
;
2668 /* Clear the File Object's event */
2669 KeClearEvent(&FileObject
->Event
);
2671 /* Allocate the IRP */
2672 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2673 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2676 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2677 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2678 Irp
->RequestorMode
= PreviousMode
;
2679 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2680 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2681 Irp
->UserIosb
= IoStatusBlock
;
2682 Irp
->UserEvent
= EventObject
;
2683 Irp
->PendingReturned
= FALSE
;
2684 Irp
->Cancel
= FALSE
;
2685 Irp
->CancelRoutine
= NULL
;
2686 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2687 Irp
->MdlAddress
= NULL
;
2689 /* Set the Stack Data */
2690 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2691 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2692 StackPtr
->FileObject
= FileObject
;
2693 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2694 StackPtr
->Parameters
.Read
.Length
= Length
;
2695 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2697 /* Check if this is buffered I/O */
2698 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2700 /* Check if we have a buffer length */
2706 /* Allocate a buffer */
2707 Irp
->AssociatedIrp
.SystemBuffer
=
2708 ExAllocatePoolWithTag(NonPagedPool
,
2712 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2714 /* Allocating failed, clean up and return the exception code */
2715 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2716 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2720 /* Set the buffer and flags */
2721 Irp
->UserBuffer
= Buffer
;
2722 Irp
->Flags
= (IRP_BUFFERED_IO
|
2723 IRP_DEALLOCATE_BUFFER
|
2724 IRP_INPUT_OPERATION
);
2728 /* Not reading anything */
2729 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2732 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2734 /* Check if we have a buffer length */
2739 /* Allocate an MDL */
2740 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2742 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2743 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2745 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2747 /* Allocating failed, clean up and return the exception code */
2748 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2749 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2755 /* No allocation flags */
2760 /* No allocation flags, and use the buffer directly */
2762 Irp
->UserBuffer
= Buffer
;
2765 /* Now set the deferred read flags */
2766 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2768 /* FIXME: VFAT SUCKS */
2769 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2772 /* Perform the call */
2773 return IopPerformSynchronousRequest(DeviceObject
,
2787 NtReadFileScatter(IN HANDLE FileHandle
,
2788 IN HANDLE Event OPTIONAL
,
2789 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2790 IN PVOID UserApcContext OPTIONAL
,
2791 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2792 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2793 IN ULONG BufferLength
,
2794 IN PLARGE_INTEGER ByteOffset
,
2795 IN PULONG Key OPTIONAL
)
2798 return STATUS_NOT_IMPLEMENTED
;
2806 NtSetEaFile(IN HANDLE FileHandle
,
2807 IN PIO_STATUS_BLOCK IoStatusBlock
,
2809 IN ULONG EaBufferSize
)
2812 return STATUS_NOT_IMPLEMENTED
;
2820 NtSetInformationFile(IN HANDLE FileHandle
,
2821 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2822 IN PVOID FileInformation
,
2824 IN FILE_INFORMATION_CLASS FileInformationClass
)
2826 PFILE_OBJECT FileObject
;
2829 PDEVICE_OBJECT DeviceObject
;
2830 PIO_STACK_LOCATION StackPtr
;
2831 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2832 PKEVENT Event
= NULL
;
2833 BOOLEAN LocalEvent
= FALSE
;
2834 PKNORMAL_ROUTINE NormalRoutine
;
2835 PVOID NormalContext
;
2837 IO_STATUS_BLOCK KernelIosb
;
2839 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2840 PIO_COMPLETION_CONTEXT Context
;
2841 PFILE_RENAME_INFORMATION RenameInfo
;
2842 HANDLE TargetHandle
= NULL
;
2844 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2846 /* Check if we're called from user mode */
2847 if (PreviousMode
!= KernelMode
)
2849 /* Validate the information class */
2850 if ((FileInformationClass
>= FileMaximumInformation
) ||
2851 !(IopSetOperationLength
[FileInformationClass
]))
2854 return STATUS_INVALID_INFO_CLASS
;
2857 /* Validate the length */
2858 if (Length
< IopSetOperationLength
[FileInformationClass
])
2860 /* Invalid length */
2861 return STATUS_INFO_LENGTH_MISMATCH
;
2864 /* Enter SEH for probing */
2867 /* Probe the I/O Status block */
2868 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2870 /* Probe the information */
2871 ProbeForRead(FileInformation
,
2873 (Length
== sizeof(BOOLEAN
)) ?
2874 sizeof(BOOLEAN
) : sizeof(ULONG
));
2876 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2878 /* Return the exception code */
2879 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2885 /* Validate the information class */
2886 if ((FileInformationClass
>= FileMaximumInformation
) ||
2887 !(IopSetOperationLength
[FileInformationClass
]))
2890 return STATUS_INVALID_INFO_CLASS
;
2893 /* Validate the length */
2894 if (Length
< IopSetOperationLength
[FileInformationClass
])
2896 /* Invalid length */
2897 return STATUS_INFO_LENGTH_MISMATCH
;
2901 /* Reference the Handle */
2902 Status
= ObReferenceObjectByHandle(FileHandle
,
2903 IopSetOperationAccess
2904 [FileInformationClass
],
2907 (PVOID
*)&FileObject
,
2909 if (!NT_SUCCESS(Status
)) return Status
;
2911 /* Check if this is a direct open or not */
2912 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2914 /* Get the device object */
2915 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2919 /* Get the device object */
2920 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2923 DPRINT("Will call: %p\n", DeviceObject
);
2924 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
2926 /* Check if this is a file that was opened for Synch I/O */
2927 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2930 IopLockFileObject(FileObject
);
2932 /* Check if the caller just wants the position */
2933 if (FileInformationClass
== FilePositionInformation
)
2935 /* Protect write in SEH */
2938 /* Write the offset */
2939 FileObject
->CurrentByteOffset
=
2940 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2943 /* Fill out the I/O Status Block */
2944 IoStatusBlock
->Information
= 0;
2945 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2947 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2949 /* Get the exception code */
2950 Status
= _SEH2_GetExceptionCode();
2954 /* Update transfer count */
2955 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2957 /* Release the file lock, dereference the file and return */
2958 IopUnlockFileObject(FileObject
);
2959 ObDereferenceObject(FileObject
);
2965 /* Use local event */
2966 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2969 ObDereferenceObject(FileObject
);
2970 return STATUS_INSUFFICIENT_RESOURCES
;
2973 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2977 /* Clear the File Object event */
2978 KeClearEvent(&FileObject
->Event
);
2980 /* Allocate the IRP */
2981 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2982 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2985 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2986 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2987 Irp
->RequestorMode
= PreviousMode
;
2988 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2989 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2990 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2991 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2992 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2993 Irp
->MdlAddress
= NULL
;
2994 Irp
->UserBuffer
= FileInformation
;
2996 /* Set the Stack Data */
2997 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2998 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2999 StackPtr
->FileObject
= FileObject
;
3004 /* Allocate a buffer */
3005 Irp
->AssociatedIrp
.SystemBuffer
=
3006 ExAllocatePoolWithTag(NonPagedPool
,
3010 /* Copy the data into it */
3011 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3015 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3017 /* Allocating failed, clean up and return the exception code */
3018 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3019 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3024 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3025 IRP_DEALLOCATE_BUFFER
|
3026 IRP_DEFER_IO_COMPLETION
);
3028 /* Set the Parameters */
3029 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
3030 StackPtr
->Parameters
.SetFile
.Length
= Length
;
3033 IopQueueIrpToThread(Irp
);
3035 /* Update operation counts */
3036 IopUpdateOperationCount(IopOtherTransfer
);
3038 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3039 /* Handle IO Completion Port quickly */
3040 if (FileInformationClass
== FileCompletionInformation
)
3042 /* Check if the file object already has a completion port */
3043 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3044 (FileObject
->CompletionContext
))
3047 Status
= STATUS_INVALID_PARAMETER
;
3051 /* Reference the Port */
3052 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3053 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3054 IO_COMPLETION_MODIFY_STATE
,
3059 if (NT_SUCCESS(Status
))
3061 /* Allocate the Context */
3062 Context
= ExAllocatePoolWithTag(PagedPool
,
3063 sizeof(IO_COMPLETION_CONTEXT
),
3068 Context
->Key
= CompletionInfo
->Key
;
3069 Context
->Port
= Queue
;
3070 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3076 * Someone else set the completion port in the
3077 * meanwhile, so dereference the port and fail.
3079 ExFreePoolWithTag(Context
, IOC_TAG
);
3080 ObDereferenceObject(Queue
);
3081 Status
= STATUS_INVALID_PARAMETER
;
3086 /* Dereference the Port now */
3087 ObDereferenceObject(Queue
);
3088 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3093 /* Set the IRP Status */
3094 Irp
->IoStatus
.Status
= Status
;
3095 Irp
->IoStatus
.Information
= 0;
3097 else if (FileInformationClass
== FileRenameInformation
||
3098 FileInformationClass
== FileLinkInformation
||
3099 FileInformationClass
== FileMoveClusterInformation
)
3101 /* Get associated information */
3102 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3107 * -> sizes are valid
3109 if (RenameInfo
->FileNameLength
!= 0 &&
3110 !(RenameInfo
->FileNameLength
& 1) &&
3111 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3113 /* Properly set information received */
3114 if (FileInformationClass
== FileMoveClusterInformation
)
3116 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3120 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3123 /* If we got fully path OR relative target, attempt a parent directory open */
3124 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3126 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3127 if (!NT_SUCCESS(Status
))
3129 Irp
->IoStatus
.Status
= Status
;
3133 /* Call the Driver */
3134 Status
= IoCallDriver(DeviceObject
, Irp
);
3139 /* Call the Driver */
3140 Status
= IoCallDriver(DeviceObject
, Irp
);
3145 Status
= STATUS_INVALID_PARAMETER
;
3146 Irp
->IoStatus
.Status
= Status
;
3151 /* Call the Driver */
3152 Status
= IoCallDriver(DeviceObject
, Irp
);
3155 /* Check if we're waiting for the IRP to complete */
3156 if (Status
== STATUS_PENDING
)
3158 /* Check if this was async I/O */
3161 /* Then to a non-alertable wait */
3162 Status
= KeWaitForSingleObject(Event
,
3167 if (Status
== STATUS_USER_APC
)
3169 /* Abort the request */
3170 IopAbortInterruptedIrp(Event
, Irp
);
3173 /* Set the final status */
3174 Status
= KernelIosb
.Status
;
3176 /* Enter SEH to write the IOSB back */
3179 /* Write it back to the caller */
3180 *IoStatusBlock
= KernelIosb
;
3182 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3184 /* Get the exception code */
3185 Status
= _SEH2_GetExceptionCode();
3189 /* Free the event */
3190 ExFreePoolWithTag(Event
, TAG_IO
);
3194 /* Wait for the IRP */
3195 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3198 (FileObject
->Flags
&
3199 FO_ALERTABLE_IO
) != 0,
3201 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3203 /* Abort the request */
3204 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3207 /* Set the final status */
3208 Status
= FileObject
->FinalStatus
;
3210 /* Release the file lock */
3211 IopUnlockFileObject(FileObject
);
3216 /* Free the event if we had one */
3219 /* Clear it in the IRP for completion */
3220 Irp
->UserEvent
= NULL
;
3221 ExFreePoolWithTag(Event
, TAG_IO
);
3224 /* Set the caller IOSB */
3225 Irp
->UserIosb
= IoStatusBlock
;
3227 /* The IRP wasn't completed, complete it ourselves */
3228 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3229 IopCompleteRequest(&Irp
->Tail
.Apc
,
3232 (PVOID
*)&FileObject
,
3234 KeLowerIrql(OldIrql
);
3236 /* Release the file object if we had locked it*/
3237 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3240 if (TargetHandle
!= NULL
)
3242 ObCloseHandle(TargetHandle
, KernelMode
);
3245 /* Return the Status */
3254 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3255 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3257 IN ULONG BufferLength
)
3260 return STATUS_NOT_IMPLEMENTED
;
3268 NtUnlockFile(IN HANDLE FileHandle
,
3269 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3270 IN PLARGE_INTEGER ByteOffset
,
3271 IN PLARGE_INTEGER Length
,
3272 IN ULONG Key OPTIONAL
)
3274 PFILE_OBJECT FileObject
;
3275 PLARGE_INTEGER LocalLength
= NULL
;
3277 PIO_STACK_LOCATION StackPtr
;
3278 PDEVICE_OBJECT DeviceObject
;
3279 PKEVENT Event
= NULL
;
3280 BOOLEAN LocalEvent
= FALSE
;
3281 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3282 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3284 OBJECT_HANDLE_INFORMATION HandleInformation
;
3285 IO_STATUS_BLOCK KernelIosb
;
3286 PFAST_IO_DISPATCH FastIoDispatch
;
3288 CapturedByteOffset
.QuadPart
= 0;
3289 CapturedLength
.QuadPart
= 0;
3290 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3292 /* Get File Object */
3293 Status
= ObReferenceObjectByHandle(FileHandle
,
3297 (PVOID
*)&FileObject
,
3298 &HandleInformation
);
3299 if (!NT_SUCCESS(Status
)) return Status
;
3301 /* Check if we're called from user mode */
3302 if (PreviousMode
!= KernelMode
)
3304 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3305 if (!(HandleInformation
.GrantedAccess
&
3306 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3308 ObDereferenceObject(FileObject
);
3309 return STATUS_ACCESS_DENIED
;
3312 /* Enter SEH for probing */
3315 /* Probe the I/O Status block */
3316 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3318 /* Probe and capture the large integers */
3319 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3320 CapturedLength
= ProbeForReadLargeInteger(Length
);
3322 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3324 /* Dereference the object and return exception code */
3325 ObDereferenceObject(FileObject
);
3326 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3332 /* Otherwise, capture them directly */
3333 CapturedByteOffset
= *ByteOffset
;
3334 CapturedLength
= *Length
;
3337 /* Check if this is a direct open or not */
3338 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3340 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3344 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3347 /* Try to do it the FastIO way if possible */
3348 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3349 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3351 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3352 &CapturedByteOffset
,
3354 PsGetCurrentProcess(),
3359 /* Write the IOSB back */
3362 *IoStatusBlock
= KernelIosb
;
3364 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3366 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3370 /* We're done with FastIO! */
3371 ObDereferenceObject(FileObject
);
3372 return KernelIosb
.Status
;
3376 /* Check if we should use Sync IO or not */
3377 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3380 IopLockFileObject(FileObject
);
3384 /* Use local event */
3385 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3388 ObDereferenceObject(FileObject
);
3389 return STATUS_INSUFFICIENT_RESOURCES
;
3391 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3395 /* Clear File Object event */
3396 KeClearEvent(&FileObject
->Event
);
3398 /* Allocate the IRP */
3399 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3400 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3402 /* Set up the IRP */
3403 Irp
->RequestorMode
= PreviousMode
;
3404 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3405 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3406 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3407 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3408 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3409 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3411 /* Set up Stack Data */
3412 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3413 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3414 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3415 StackPtr
->FileObject
= FileObject
;
3420 /* Allocate a buffer */
3421 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3422 sizeof(LARGE_INTEGER
),
3425 /* Set the length */
3426 *LocalLength
= CapturedLength
;
3427 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3428 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3430 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3432 /* Allocating failed, clean up and return the exception code */
3433 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3434 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3436 /* Return the exception code */
3437 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3441 /* Set Parameters */
3442 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3443 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3445 /* Call the Driver */
3446 Status
= IopPerformSynchronousRequest(DeviceObject
,
3454 /* Check if this was async I/O */
3457 /* It was, finalize this request */
3458 Status
= IopFinalizeAsynchronousIo(Status
,
3475 NtWriteFile(IN HANDLE FileHandle
,
3476 IN HANDLE Event OPTIONAL
,
3477 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3478 IN PVOID ApcContext OPTIONAL
,
3479 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3482 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3483 IN PULONG Key OPTIONAL
)
3486 PFILE_OBJECT FileObject
;
3488 PDEVICE_OBJECT DeviceObject
;
3489 PIO_STACK_LOCATION StackPtr
;
3490 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3491 PKEVENT EventObject
= NULL
;
3492 LARGE_INTEGER CapturedByteOffset
;
3493 ULONG CapturedKey
= 0;
3494 BOOLEAN Synchronous
= FALSE
;
3496 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3497 PFAST_IO_DISPATCH FastIoDispatch
;
3498 IO_STATUS_BLOCK KernelIosb
;
3502 CapturedByteOffset
.QuadPart
= 0;
3503 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3505 /* Get File Object for write */
3506 Status
= ObReferenceFileObjectForWrite(FileHandle
,
3510 if (!NT_SUCCESS(Status
)) return Status
;
3512 /* Validate User-Mode Buffers */
3513 if (PreviousMode
!= KernelMode
)
3517 /* Probe the status block */
3518 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3520 /* Probe the read buffer */
3521 ProbeForRead(Buffer
, Length
, 1);
3523 /* Check if we got a byte offset */
3526 /* Capture and probe it */
3527 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3530 /* Capture and probe the key */
3531 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3533 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3535 /* Release the file object and return the exception code */
3536 ObDereferenceObject(FileObject
);
3537 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3543 /* Kernel mode: capture directly */
3544 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3545 if (Key
) CapturedKey
= *Key
;
3548 /* Check if this is an append operation */
3549 if ((ObjectHandleInfo
.GrantedAccess
&
3550 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3552 /* Give the drivers something to understand */
3553 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3554 CapturedByteOffset
.u
.HighPart
= -1;
3557 /* Check for event */
3561 Status
= ObReferenceObjectByHandle(Event
,
3565 (PVOID
*)&EventObject
,
3567 if (!NT_SUCCESS(Status
))
3570 ObDereferenceObject(FileObject
);
3574 /* Otherwise reset the event */
3575 KeClearEvent(EventObject
);
3578 /* Get the device object */
3579 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3581 /* Check if we should use Sync IO or not */
3582 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3584 /* Lock the file object */
3585 IopLockFileObject(FileObject
);
3587 /* Check if we don't have a byte offset available */
3588 if (!(ByteOffset
) ||
3589 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3590 (CapturedByteOffset
.u
.HighPart
== -1)))
3592 /* Use the Current Byte Offset instead */
3593 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3596 /* If the file is cached, try fast I/O */
3597 if (FileObject
->PrivateCacheMap
)
3599 /* Perform fast write */
3600 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3601 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoWrite
!= NULL
);
3603 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3604 &CapturedByteOffset
,
3612 /* Only accept the result if it was successful */
3614 KernelIosb
.Status
== STATUS_SUCCESS
)
3616 /* Fast path -- update transfer & operation counts */
3617 IopUpdateOperationCount(IopWriteTransfer
);
3618 IopUpdateTransferCount(IopWriteTransfer
,
3619 (ULONG
)KernelIosb
.Information
);
3621 /* Enter SEH to write the IOSB back */
3624 /* Write it back to the caller */
3625 *IoStatusBlock
= KernelIosb
;
3627 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3629 /* The caller's IOSB was invalid, so fail */
3630 if (EventObject
) ObDereferenceObject(EventObject
);
3631 IopUnlockFileObject(FileObject
);
3632 ObDereferenceObject(FileObject
);
3633 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3637 /* Signal the completion event */
3640 KeSetEvent(EventObject
, 0, FALSE
);
3641 ObDereferenceObject(EventObject
);
3645 IopUnlockFileObject(FileObject
);
3646 ObDereferenceObject(FileObject
);
3647 return KernelIosb
.Status
;
3651 /* Remember we are sync */
3654 else if (!(ByteOffset
) &&
3655 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3657 /* Otherwise, this was async I/O without a byte offset, so fail */
3658 if (EventObject
) ObDereferenceObject(EventObject
);
3659 ObDereferenceObject(FileObject
);
3660 return STATUS_INVALID_PARAMETER
;
3663 /* Clear the File Object's event */
3664 KeClearEvent(&FileObject
->Event
);
3666 /* Allocate the IRP */
3667 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3668 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3671 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3672 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3673 Irp
->RequestorMode
= PreviousMode
;
3674 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3675 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3676 Irp
->UserIosb
= IoStatusBlock
;
3677 Irp
->UserEvent
= EventObject
;
3678 Irp
->PendingReturned
= FALSE
;
3679 Irp
->Cancel
= FALSE
;
3680 Irp
->CancelRoutine
= NULL
;
3681 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3682 Irp
->MdlAddress
= NULL
;
3684 /* Set the Stack Data */
3685 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3686 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3687 StackPtr
->FileObject
= FileObject
;
3688 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3689 SL_WRITE_THROUGH
: 0;
3690 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3691 StackPtr
->Parameters
.Write
.Length
= Length
;
3692 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3694 /* Check if this is buffered I/O */
3695 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3697 /* Check if we have a buffer length */
3703 /* Allocate a buffer */
3704 Irp
->AssociatedIrp
.SystemBuffer
=
3705 ExAllocatePoolWithTag(NonPagedPool
,
3709 /* Copy the data into it */
3710 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3712 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3714 /* Allocating failed, clean up and return the exception code */
3715 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3716 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3721 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3725 /* Not writing anything */
3726 Irp
->Flags
= IRP_BUFFERED_IO
;
3729 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3731 /* Check if we have a buffer length */
3736 /* Allocate an MDL */
3737 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3739 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3740 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3742 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3744 /* Allocating failed, clean up and return the exception code */
3745 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3746 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3751 /* No allocation flags */
3756 /* No allocation flags, and use the buffer directly */
3758 Irp
->UserBuffer
= Buffer
;
3761 /* Now set the deferred read flags */
3762 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3764 /* FIXME: VFAT SUCKS */
3765 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3768 /* Perform the call */
3769 return IopPerformSynchronousRequest(DeviceObject
,
3780 NtWriteFileGather(IN HANDLE FileHandle
,
3781 IN HANDLE Event OPTIONAL
,
3782 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3783 IN PVOID UserApcContext OPTIONAL
,
3784 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3785 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3786 IN ULONG BufferLength
,
3787 IN PLARGE_INTEGER ByteOffset
,
3788 IN PULONG Key OPTIONAL
)
3791 return STATUS_NOT_IMPLEMENTED
;
3799 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3800 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3801 OUT PVOID FsInformation
,
3803 IN FS_INFORMATION_CLASS FsInformationClass
)
3805 PFILE_OBJECT FileObject
;
3807 PIO_STACK_LOCATION StackPtr
;
3808 PDEVICE_OBJECT DeviceObject
;
3809 PKEVENT Event
= NULL
;
3810 BOOLEAN LocalEvent
= FALSE
;
3811 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3813 IO_STATUS_BLOCK KernelIosb
;
3815 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3817 /* Check if we're called from user mode */
3818 if (PreviousMode
!= KernelMode
)
3820 /* Validate the information class */
3821 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3822 !(IopQueryFsOperationLength
[FsInformationClass
]))
3825 return STATUS_INVALID_INFO_CLASS
;
3828 /* Validate the length */
3829 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3831 /* Invalid length */
3832 return STATUS_INFO_LENGTH_MISMATCH
;
3835 /* Enter SEH for probing */
3838 /* Probe the I/O Status block */
3839 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3841 /* Probe the information */
3842 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3844 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3846 /* Return the exception code */
3847 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3852 /* Get File Object */
3853 Status
= ObReferenceObjectByHandle(FileHandle
,
3854 IopQueryFsOperationAccess
3855 [FsInformationClass
],
3858 (PVOID
*)&FileObject
,
3860 if (!NT_SUCCESS(Status
)) return Status
;
3862 /* Check if we should use Sync IO or not */
3863 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3866 IopLockFileObject(FileObject
);
3870 /* Use local event */
3871 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3874 ObDereferenceObject(FileObject
);
3875 return STATUS_INSUFFICIENT_RESOURCES
;
3877 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3881 /* Get the device object */
3882 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3884 /* Clear File Object event */
3885 KeClearEvent(&FileObject
->Event
);
3887 /* Allocate the IRP */
3888 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3889 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3891 /* Set up the IRP */
3892 Irp
->RequestorMode
= PreviousMode
;
3893 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3894 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3895 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3896 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3897 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3898 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3899 Irp
->UserBuffer
= FsInformation
;
3900 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3901 Irp
->MdlAddress
= NULL
;
3903 /* Set up Stack Data */
3904 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3905 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3906 StackPtr
->FileObject
= FileObject
;
3911 /* Allocate a buffer */
3912 Irp
->AssociatedIrp
.SystemBuffer
=
3913 ExAllocatePoolWithTag(NonPagedPool
,
3917 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3919 /* Allocating failed, clean up and return the exception code */
3920 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3921 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3925 /* Set the flags for this buffered + deferred I/O */
3926 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3927 IRP_DEALLOCATE_BUFFER
|
3928 IRP_INPUT_OPERATION
|
3929 IRP_DEFER_IO_COMPLETION
);
3931 /* Set Parameters */
3932 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3933 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3935 /* Call the Driver */
3936 Status
= IopPerformSynchronousRequest(DeviceObject
,
3944 /* Check if this was async I/O */
3947 /* It was, finalize this request */
3948 Status
= IopFinalizeAsynchronousIo(Status
,
3965 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3966 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3967 IN PVOID FsInformation
,
3969 IN FS_INFORMATION_CLASS FsInformationClass
)
3971 PFILE_OBJECT FileObject
;
3973 PIO_STACK_LOCATION StackPtr
;
3974 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3975 PKEVENT Event
= NULL
;
3976 BOOLEAN LocalEvent
= FALSE
;
3977 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3979 IO_STATUS_BLOCK KernelIosb
;
3980 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3982 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3984 /* Check if we're called from user mode */
3985 if (PreviousMode
!= KernelMode
)
3987 /* Validate the information class */
3988 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3989 !(IopSetFsOperationLength
[FsInformationClass
]))
3992 return STATUS_INVALID_INFO_CLASS
;
3995 /* Validate the length */
3996 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3998 /* Invalid length */
3999 return STATUS_INFO_LENGTH_MISMATCH
;
4002 /* Enter SEH for probing */
4005 /* Probe the I/O Status block */
4006 ProbeForWriteIoStatusBlock(IoStatusBlock
);
4008 /* Probe the information */
4009 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
4011 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4013 /* Return the exception code */
4014 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4019 /* Get File Object */
4020 Status
= ObReferenceObjectByHandle(FileHandle
,
4021 IopSetFsOperationAccess
4022 [FsInformationClass
],
4025 (PVOID
*)&FileObject
,
4027 if (!NT_SUCCESS(Status
)) return Status
;
4029 /* Get target device for notification */
4030 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4031 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4033 /* Check if we should use Sync IO or not */
4034 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4037 IopLockFileObject(FileObject
);
4041 /* Use local event */
4042 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4045 ObDereferenceObject(FileObject
);
4046 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4047 return STATUS_INSUFFICIENT_RESOURCES
;
4049 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4053 /* Get the device object */
4054 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4056 /* Clear File Object event */
4057 KeClearEvent(&FileObject
->Event
);
4059 /* Allocate the IRP */
4060 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4063 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4064 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4067 /* Set up the IRP */
4068 Irp
->RequestorMode
= PreviousMode
;
4069 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4070 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4071 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4072 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4073 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4074 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4075 Irp
->UserBuffer
= FsInformation
;
4076 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4077 Irp
->MdlAddress
= NULL
;
4079 /* Set up Stack Data */
4080 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4081 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
4082 StackPtr
->FileObject
= FileObject
;
4087 /* Allocate a buffer */
4088 Irp
->AssociatedIrp
.SystemBuffer
=
4089 ExAllocatePoolWithTag(NonPagedPool
,
4093 /* Copy the data into it */
4094 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
4096 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4098 /* Allocating failed, clean up and return the exception code */
4099 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4100 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4101 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4105 /* Set the flags for this buffered + deferred I/O */
4106 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4108 /* Set Parameters */
4109 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
4110 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
4112 /* Call the Driver */
4113 Status
= IopPerformSynchronousRequest(DeviceObject
,
4121 /* Check if this was async I/O */
4124 /* It was, finalize this request */
4125 Status
= IopFinalizeAsynchronousIo(Status
,
4133 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
4135 /* Time to report change */
4136 NotificationStructure
.Version
= 1;
4137 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
4138 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
4139 NotificationStructure
.FileObject
= NULL
;
4140 NotificationStructure
.NameBufferOffset
= - 1;
4141 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
4153 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
4156 return STATUS_NOT_IMPLEMENTED
;
4164 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
4167 return STATUS_NOT_IMPLEMENTED
;