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();
219 IOTRACE(IO_CTL_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
220 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
222 /* Get the access type */
223 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
225 /* Check if we came from user mode */
226 if (PreviousMode
!= KernelMode
)
230 /* Probe the status block */
231 ProbeForWriteIoStatusBlock(IoStatusBlock
);
233 /* Check if this is buffered I/O */
234 if (AccessType
== METHOD_BUFFERED
)
236 /* Check if we have an output buffer */
239 /* Probe the output buffer */
240 ProbeForWrite(OutputBuffer
,
246 /* Make sure the caller can't fake this as we depend on this */
247 OutputBufferLength
= 0;
251 /* Check if we we have an input buffer I/O */
252 if (AccessType
!= METHOD_NEITHER
)
254 /* Check if we have an input buffer */
257 /* Probe the input buffer */
258 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
262 /* Make sure the caller can't fake this as we depend on this */
263 InputBufferLength
= 0;
267 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
269 /* Return the exception code */
270 _SEH2_YIELD(return _SEH2_GetExceptionCode());
275 /* Don't check for access rights right now, KernelMode can do anything */
276 Status
= ObReferenceObjectByHandle(DeviceHandle
,
282 if (!NT_SUCCESS(Status
)) return Status
;
284 /* Can't use an I/O completion port and an APC in the same time */
285 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
288 ObDereferenceObject(FileObject
);
289 return STATUS_INVALID_PARAMETER
;
292 /* Check if we from user mode */
293 if (PreviousMode
!= KernelMode
)
295 /* Get the access mask */
296 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
298 /* Check if we can open it */
299 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
300 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
302 /* Dereference the file object and fail */
303 ObDereferenceObject(FileObject
);
304 return STATUS_ACCESS_DENIED
;
308 /* Check for an event */
312 Status
= ObReferenceObjectByHandle(Event
,
316 (PVOID
*)&EventObject
,
318 if (!NT_SUCCESS(Status
))
320 /* Dereference the file object and fail */
321 ObDereferenceObject(FileObject
);
326 KeClearEvent(EventObject
);
329 /* Check if this is a file that was opened for Synch I/O */
330 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
333 IopLockFileObject(FileObject
);
335 /* Remember to unlock later */
336 LockedForSynch
= TRUE
;
339 /* Check if this is a direct open or not */
340 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
342 /* It's a direct open, get the attached device */
343 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
347 /* Otherwise get the related device */
348 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
351 /* If this is a device I/O, try to do it with FastIO path */
354 PFAST_IO_DISPATCH FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
356 /* Check whether FSD is FastIO aware and provide an appropriate routine */
357 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoDeviceControl
!= NULL
)
359 IO_STATUS_BLOCK KernelIosb
;
361 /* If we have an output buffer coming from usermode */
362 if (PreviousMode
!= KernelMode
&& OutputBuffer
!= NULL
)
364 /* Probe it according to its usage */
367 if (AccessType
== METHOD_IN_DIRECT
)
369 ProbeForRead(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
371 else if (AccessType
== METHOD_OUT_DIRECT
)
373 ProbeForWrite(OutputBuffer
, OutputBufferLength
, sizeof(CHAR
));
376 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
378 /* Cleanup after exception and return */
379 IopCleanupAfterException(FileObject
, NULL
, EventObject
, NULL
);
381 /* Return the exception code */
382 _SEH2_YIELD(return _SEH2_GetExceptionCode());
387 /* If we are dismounting a volume, increase the dismount count */
388 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
390 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
394 if (FastIoDispatch
->FastIoDeviceControl(FileObject
,
404 IO_COMPLETION_CONTEXT CompletionInfo
= { NULL
, NULL
};
406 /* Write the IOSB back */
409 *IoStatusBlock
= KernelIosb
;
412 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
414 KernelIosb
.Status
= _SEH2_GetExceptionCode();
418 /* Backup our complete context in case it exists */
419 if (FileObject
->CompletionContext
)
421 CompletionInfo
= *(FileObject
->CompletionContext
);
424 /* If we had an event, signal it */
427 KeSetEvent(EventObject
, IO_NO_INCREMENT
, FALSE
);
428 ObDereferenceObject(EventObject
);
431 /* If FO was locked, unlock it */
434 IopUnlockFileObject(FileObject
);
437 /* Set completion if required */
438 if (CompletionInfo
.Port
!= NULL
&& UserApcContext
!= NULL
)
440 if (!NT_SUCCESS(IoSetIoCompletion(CompletionInfo
.Port
,
444 KernelIosb
.Information
,
447 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
451 /* We're done with FastIO! */
452 ObDereferenceObject(FileObject
);
453 return KernelIosb
.Status
;
458 /* Clear the event */
459 KeClearEvent(&FileObject
->Event
);
462 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
463 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
466 Irp
->UserIosb
= IoStatusBlock
;
467 Irp
->UserEvent
= EventObject
;
468 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
469 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
471 Irp
->CancelRoutine
= NULL
;
472 Irp
->PendingReturned
= FALSE
;
473 Irp
->RequestorMode
= PreviousMode
;
474 Irp
->MdlAddress
= NULL
;
475 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
477 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
478 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
479 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
481 /* Set stack location settings */
482 StackPtr
= IoGetNextIrpStackLocation(Irp
);
483 StackPtr
->FileObject
= FileObject
;
484 StackPtr
->MajorFunction
= IsDevIoCtl
?
485 IRP_MJ_DEVICE_CONTROL
:
486 IRP_MJ_FILE_SYSTEM_CONTROL
;
487 StackPtr
->MinorFunction
= 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
488 StackPtr
->Control
= 0;
490 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
492 /* Set the IOCTL Data */
493 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
494 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
495 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
498 /* Handle the Methods */
502 case METHOD_BUFFERED
:
504 /* Enter SEH for allocations */
507 /* Select the right Buffer Length */
508 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
509 InputBufferLength
: OutputBufferLength
;
511 /* Make sure there is one */
514 /* Allocate the System Buffer */
515 Irp
->AssociatedIrp
.SystemBuffer
=
516 ExAllocatePoolWithTag(NonPagedPool
,
520 /* Check if we got a buffer */
523 /* Copy into the System Buffer */
524 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
529 /* Write the flags */
530 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
531 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
533 /* Save the Buffer */
534 Irp
->UserBuffer
= OutputBuffer
;
538 /* Clear the Flags and Buffer */
539 Irp
->UserBuffer
= NULL
;
542 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
544 /* Cleanup after exception and return */
545 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
546 _SEH2_YIELD(return _SEH2_GetExceptionCode());
552 case METHOD_IN_DIRECT
:
553 case METHOD_OUT_DIRECT
:
558 /* Check if we got an input buffer */
559 if ((InputBufferLength
) && (InputBuffer
))
561 /* Allocate the System Buffer */
562 Irp
->AssociatedIrp
.SystemBuffer
=
563 ExAllocatePoolWithTag(NonPagedPool
,
567 /* Copy into the System Buffer */
568 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
572 /* Write the flags */
573 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
576 /* Check if we got an output buffer */
579 /* Allocate the System Buffer */
580 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
585 if (!Irp
->MdlAddress
)
587 /* Raise exception we'll catch */
588 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
592 MmProbeAndLockPages(Irp
->MdlAddress
,
594 (AccessType
== METHOD_IN_DIRECT
) ?
595 IoReadAccess
: IoWriteAccess
);
598 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
600 /* Cleanup after exception and return */
601 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
602 _SEH2_YIELD(return _SEH2_GetExceptionCode());
609 /* Just save the Buffer */
610 Irp
->UserBuffer
= OutputBuffer
;
611 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
614 /* Use deferred completion for FS I/O */
617 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
620 /* If we are dismounting a volume, increaase the dismount count */
621 if (IoControlCode
== FSCTL_DISMOUNT_VOLUME
)
623 InterlockedIncrement((PLONG
)&SharedUserData
->DismountCount
);
626 /* Perform the call */
627 return IopPerformSynchronousRequest(DeviceObject
,
638 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
639 IN ULONG InformationClass
,
641 OUT PVOID Information
,
642 OUT PULONG ReturnedLength
,
645 IO_STATUS_BLOCK IoStatusBlock
;
647 PDEVICE_OBJECT DeviceObject
;
648 PIO_STACK_LOCATION StackPtr
;
649 BOOLEAN LocalEvent
= FALSE
;
653 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
654 FileObject
, InformationClass
, File
);
656 /* Reference the object */
657 ObReferenceObject(FileObject
);
659 /* Check if this is a file that was opened for Synch I/O */
660 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
663 IopLockFileObject(FileObject
);
665 /* Use File Object event */
666 KeClearEvent(&FileObject
->Event
);
670 /* Use local event */
671 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
675 /* Get the Device Object */
676 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
678 /* Allocate the IRP */
679 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
680 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
683 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
684 Irp
->RequestorMode
= KernelMode
;
685 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
686 Irp
->UserIosb
= &IoStatusBlock
;
687 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
688 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
689 Irp
->Flags
|= IRP_BUFFERED_IO
;
690 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
691 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
693 /* Set the Stack Data */
694 StackPtr
= IoGetNextIrpStackLocation(Irp
);
695 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
696 IRP_MJ_QUERY_VOLUME_INFORMATION
;
697 StackPtr
->FileObject
= FileObject
;
699 /* Check which type this is */
703 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
704 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
709 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
710 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
714 IopQueueIrpToThread(Irp
);
716 /* Call the Driver */
717 Status
= IoCallDriver(DeviceObject
, Irp
);
719 /* Check if this was synch I/O */
722 /* Check if the request is pending */
723 if (Status
== STATUS_PENDING
)
725 /* Wait on the file object */
726 Status
= KeWaitForSingleObject(&FileObject
->Event
,
730 FO_ALERTABLE_IO
) != 0,
732 if (Status
== STATUS_ALERTED
)
734 /* Abort the operation */
735 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
738 /* Get the final status */
739 Status
= FileObject
->FinalStatus
;
742 /* Release the file lock */
743 IopUnlockFileObject(FileObject
);
745 else if (Status
== STATUS_PENDING
)
747 /* Wait on the local event and get the final status */
748 KeWaitForSingleObject(&Event
,
753 Status
= IoStatusBlock
.Status
;
756 /* Return the Length and Status. ReturnedLength is NOT optional */
757 *ReturnedLength
= (ULONG
)IoStatusBlock
.Information
;
763 IopGetFileInformation(IN PFILE_OBJECT FileObject
,
765 IN FILE_INFORMATION_CLASS FileInfoClass
,
767 OUT PULONG ReturnedLength
)
772 PIO_STACK_LOCATION Stack
;
773 PDEVICE_OBJECT DeviceObject
;
774 IO_STATUS_BLOCK IoStatusBlock
;
778 /* Allocate an IRP */
779 ObReferenceObject(FileObject
);
780 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
781 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
784 ObDereferenceObject(FileObject
);
785 return STATUS_INSUFFICIENT_RESOURCES
;
789 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
792 Irp
->UserIosb
= &IoStatusBlock
;
793 Irp
->UserEvent
= &Event
;
794 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
795 Irp
->RequestorMode
= KernelMode
;
796 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
797 Irp
->Flags
= IRP_SYNCHRONOUS_API
| IRP_BUFFERED_IO
| IRP_OB_QUERY_NAME
;
798 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
799 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
801 Stack
= IoGetNextIrpStackLocation(Irp
);
802 Stack
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
803 Stack
->FileObject
= FileObject
;
804 Stack
->Parameters
.QueryFile
.FileInformationClass
= FileInfoClass
;
805 Stack
->Parameters
.QueryFile
.Length
= Length
;
809 IopQueueIrpToThread(Irp
);
811 /* Call the driver */
812 Status
= IoCallDriver(DeviceObject
, Irp
);
813 if (Status
== STATUS_PENDING
)
815 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
816 Status
= IoStatusBlock
.Status
;
819 *ReturnedLength
= IoStatusBlock
.Information
;
825 IopGetBasicInformationFile(IN PFILE_OBJECT FileObject
,
826 OUT PFILE_BASIC_INFORMATION BasicInfo
)
828 ULONG ReturnedLength
;
829 PDEVICE_OBJECT DeviceObject
;
830 IO_STATUS_BLOCK IoStatusBlock
;
834 /* Try to do it the fast way if possible */
835 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
836 if (DeviceObject
->DriverObject
->FastIoDispatch
!= NULL
&&
837 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
&&
838 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo(FileObject
,
839 ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) != 0),
844 return IoStatusBlock
.Status
;
847 /* In case it failed, fall back to IRP-based method */
848 return IopGetFileInformation(FileObject
, sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
, BasicInfo
, &ReturnedLength
);
853 IopOpenLinkOrRenameTarget(OUT PHANDLE Handle
,
855 IN PFILE_RENAME_INFORMATION RenameInfo
,
856 IN PFILE_OBJECT FileObject
)
860 UNICODE_STRING FileName
;
861 PIO_STACK_LOCATION Stack
;
862 PFILE_OBJECT TargetFileObject
;
863 IO_STATUS_BLOCK IoStatusBlock
;
864 FILE_BASIC_INFORMATION BasicInfo
;
865 OBJECT_ATTRIBUTES ObjectAttributes
;
866 OBJECT_HANDLE_INFORMATION HandleInformation
;
867 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
871 /* First, establish whether our target is a directory */
872 if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
874 Status
= IopGetBasicInformationFile(FileObject
, &BasicInfo
);
875 if (!NT_SUCCESS(Status
))
880 if (BasicInfo
.FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
881 DesiredAccess
= FILE_ADD_SUBDIRECTORY
;
885 /* Setup the string to the target */
886 FileName
.Buffer
= RenameInfo
->FileName
;
887 FileName
.Length
= RenameInfo
->FileNameLength
;
888 FileName
.MaximumLength
= RenameInfo
->FileNameLength
;
890 InitializeObjectAttributes(&ObjectAttributes
,
892 (FileObject
->Flags
& FO_OPENED_CASE_SENSITIVE
? 0 : OBJ_CASE_INSENSITIVE
) | OBJ_KERNEL_HANDLE
,
893 RenameInfo
->RootDirectory
,
896 /* And open its parent directory */
897 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
899 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
901 /* Commented out - we don't support FO extension yet
902 * FIXME: Corrected last arg when it's supported
904 Status
= IoCreateFileSpecifyDeviceObjectHint(&TargetHandle
,
905 DesiredAccess
| SYNCHRONIZE
,
910 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
912 FILE_OPEN_FOR_BACKUP_INTENT
,
917 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
,
918 FileObject
->DeviceObject
);
922 return STATUS_NOT_IMPLEMENTED
;
927 Status
= IoCreateFile(&TargetHandle
,
928 DesiredAccess
| SYNCHRONIZE
,
933 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
935 FILE_OPEN_FOR_BACKUP_INTENT
,
940 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
);
943 if (!NT_SUCCESS(Status
))
948 /* Once open, continue only if:
949 * Target exists and we're allowed to overwrite it
951 Stack
= IoGetNextIrpStackLocation(Irp
);
952 if (Stack
->Parameters
.SetFile
.FileInformationClass
== FileLinkInformation
&&
953 !RenameInfo
->ReplaceIfExists
&&
954 IoStatusBlock
.Information
== FILE_EXISTS
)
956 ObCloseHandle(TargetHandle
, KernelMode
);
957 return STATUS_OBJECT_NAME_COLLISION
;
960 /* Now, we'll get the associated device of the target, to check for same device location
961 * So, get the FO first
963 Status
= ObReferenceObjectByHandle(TargetHandle
,
967 (PVOID
*)&TargetFileObject
,
969 if (!NT_SUCCESS(Status
))
971 ObCloseHandle(TargetHandle
, KernelMode
);
975 /* We can dereference, we have the handle */
976 ObDereferenceObject(TargetFileObject
);
977 /* If we're not on the same device, error out **/
978 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
980 ObCloseHandle(TargetHandle
, KernelMode
);
981 return STATUS_NOT_SAME_DEVICE
;
984 /* Return parent directory file object and handle */
985 Stack
->Parameters
.SetFile
.FileObject
= TargetFileObject
;
986 *Handle
= TargetHandle
;
988 return STATUS_SUCCESS
;
993 IopGetFileMode(IN PFILE_OBJECT FileObject
)
997 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
998 Mode
|= FILE_WRITE_THROUGH
;
1000 if (FileObject
->Flags
& FO_SEQUENTIAL_ONLY
)
1001 Mode
|= FILE_SEQUENTIAL_ONLY
;
1003 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
1004 Mode
|= FILE_NO_INTERMEDIATE_BUFFERING
;
1006 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1008 if (FileObject
->Flags
& FO_ALERTABLE_IO
)
1009 Mode
|= FILE_SYNCHRONOUS_IO_ALERT
;
1011 Mode
|= FILE_SYNCHRONOUS_IO_NONALERT
;
1014 if (FileObject
->Flags
& FO_DELETE_ON_CLOSE
)
1015 Mode
|= FILE_DELETE_ON_CLOSE
;
1020 /* PUBLIC FUNCTIONS **********************************************************/
1027 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
1029 IN PLARGE_INTEGER Offset
,
1031 IN PIO_STATUS_BLOCK StatusBlock
)
1034 PIO_STACK_LOCATION StackPtr
;
1035 PDEVICE_OBJECT DeviceObject
;
1036 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1037 FileObject
, Mdl
, Offset
);
1039 /* Get the Device Object */
1040 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1043 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1044 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1047 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1049 /* Create the IRP Settings */
1050 Irp
->MdlAddress
= Mdl
;
1051 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1052 Irp
->UserIosb
= StatusBlock
;
1053 Irp
->UserEvent
= Event
;
1054 Irp
->RequestorMode
= KernelMode
;
1055 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
1056 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1057 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1059 /* Set the Stack Settings */
1060 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
1061 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
1062 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
1063 StackPtr
->FileObject
= FileObject
;
1065 /* Call the Driver */
1066 return IoCallDriver(DeviceObject
, Irp
);
1074 IoPageRead(IN PFILE_OBJECT FileObject
,
1076 IN PLARGE_INTEGER Offset
,
1078 IN PIO_STATUS_BLOCK StatusBlock
)
1081 PIO_STACK_LOCATION StackPtr
;
1082 PDEVICE_OBJECT DeviceObject
;
1083 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
1084 FileObject
, Mdl
, Offset
);
1086 /* Get the Device Object */
1087 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1090 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1091 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1094 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1096 /* Create the IRP Settings */
1097 Irp
->MdlAddress
= Mdl
;
1098 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
1099 Irp
->UserIosb
= StatusBlock
;
1100 Irp
->UserEvent
= Event
;
1101 Irp
->RequestorMode
= KernelMode
;
1102 Irp
->Flags
= IRP_PAGING_IO
|
1104 IRP_SYNCHRONOUS_PAGING_IO
|
1105 IRP_INPUT_OPERATION
;
1106 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1107 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1109 /* Set the Stack Settings */
1110 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
1111 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
1112 StackPtr
->MajorFunction
= IRP_MJ_READ
;
1113 StackPtr
->FileObject
= FileObject
;
1115 /* Call the Driver */
1116 return IoCallDriver(DeviceObject
, Irp
);
1124 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1125 IN FILE_INFORMATION_CLASS FileInformationClass
,
1127 OUT PVOID FileInformation
,
1128 OUT PULONG ReturnedLength
)
1130 /* Call the shared routine */
1131 return IopQueryDeviceInformation(FileObject
,
1132 FileInformationClass
,
1144 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
1145 IN FS_INFORMATION_CLASS FsInformationClass
,
1147 OUT PVOID FsInformation
,
1148 OUT PULONG ReturnedLength
)
1150 /* Call the shared routine */
1151 return IopQueryDeviceInformation(FileObject
,
1164 IoSetInformation(IN PFILE_OBJECT FileObject
,
1165 IN FILE_INFORMATION_CLASS FileInformationClass
,
1167 IN PVOID FileInformation
)
1169 IO_STATUS_BLOCK IoStatusBlock
;
1171 PDEVICE_OBJECT DeviceObject
;
1172 PIO_STACK_LOCATION StackPtr
;
1173 BOOLEAN LocalEvent
= FALSE
;
1177 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
1178 FileObject
, FileInformationClass
, Length
);
1180 /* Reference the object */
1181 ObReferenceObject(FileObject
);
1183 /* Check if this is a file that was opened for Synch I/O */
1184 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1187 IopLockFileObject(FileObject
);
1189 /* Use File Object event */
1190 KeClearEvent(&FileObject
->Event
);
1194 /* Use local event */
1195 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1199 /* Get the Device Object */
1200 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1202 /* Allocate the IRP */
1203 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1204 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1207 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1208 Irp
->RequestorMode
= KernelMode
;
1209 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1210 Irp
->UserIosb
= &IoStatusBlock
;
1211 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1212 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1213 Irp
->Flags
|= IRP_BUFFERED_IO
;
1214 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1215 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1217 /* Set the Stack Data */
1218 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1219 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
1220 StackPtr
->FileObject
= FileObject
;
1222 /* Set Parameters */
1223 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
1224 StackPtr
->Parameters
.SetFile
.Length
= Length
;
1227 IopQueueIrpToThread(Irp
);
1229 /* Call the Driver */
1230 Status
= IoCallDriver(DeviceObject
, Irp
);
1232 /* Check if this was synch I/O */
1235 /* Check if the request is pending */
1236 if (Status
== STATUS_PENDING
)
1238 /* Wait on the file object */
1239 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1242 (FileObject
->Flags
&
1243 FO_ALERTABLE_IO
) != 0,
1245 if (Status
== STATUS_ALERTED
)
1247 /* Abort the operation */
1248 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1251 /* Get the final status */
1252 Status
= FileObject
->FinalStatus
;
1255 /* Release the file lock */
1256 IopUnlockFileObject(FileObject
);
1258 else if (Status
== STATUS_PENDING
)
1260 /* Wait on the local event and get the final status */
1261 KeWaitForSingleObject(&Event
,
1266 Status
= IoStatusBlock
.Status
;
1269 /* Return the status */
1273 /* NATIVE SERVICES ***********************************************************/
1280 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1281 IN HANDLE Event OPTIONAL
,
1282 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1283 IN PVOID UserApcContext OPTIONAL
,
1284 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1285 IN ULONG IoControlCode
,
1286 IN PVOID InputBuffer
,
1287 IN ULONG InputBufferLength OPTIONAL
,
1288 OUT PVOID OutputBuffer
,
1289 IN ULONG OutputBufferLength OPTIONAL
)
1291 /* Call the Generic Function */
1292 return IopDeviceFsIoControl(DeviceHandle
,
1310 NtFsControlFile(IN HANDLE DeviceHandle
,
1311 IN HANDLE Event OPTIONAL
,
1312 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1313 IN PVOID UserApcContext OPTIONAL
,
1314 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1315 IN ULONG IoControlCode
,
1316 IN PVOID InputBuffer
,
1317 IN ULONG InputBufferLength OPTIONAL
,
1318 OUT PVOID OutputBuffer
,
1319 IN ULONG OutputBufferLength OPTIONAL
)
1321 /* Call the Generic Function */
1322 return IopDeviceFsIoControl(DeviceHandle
,
1337 NtFlushBuffersFile(IN HANDLE FileHandle
,
1338 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1340 PFILE_OBJECT FileObject
;
1342 PIO_STACK_LOCATION StackPtr
;
1344 PDEVICE_OBJECT DeviceObject
;
1345 PKEVENT Event
= NULL
;
1346 BOOLEAN LocalEvent
= FALSE
;
1347 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1348 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1349 IO_STATUS_BLOCK KernelIosb
;
1351 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1353 if (PreviousMode
!= KernelMode
)
1355 /* Protect probes */
1358 /* Probe the I/O Status block */
1359 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1361 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1363 /* Return the exception code */
1364 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1369 /* Get the File Object */
1370 Status
= ObReferenceObjectByHandle(FileHandle
,
1374 (PVOID
*)&FileObject
,
1376 if (!NT_SUCCESS(Status
)) return Status
;
1379 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1380 * granted. However, if this is a named pipe, make sure we don't ask for
1381 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1384 if (!(ObjectHandleInfo
.GrantedAccess
&
1385 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1389 ObDereferenceObject(FileObject
);
1390 return STATUS_ACCESS_DENIED
;
1393 /* Check if we should use Sync IO or not */
1394 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1397 IopLockFileObject(FileObject
);
1401 /* Use local event */
1402 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1406 ObDereferenceObject(FileObject
);
1407 return STATUS_INSUFFICIENT_RESOURCES
;
1409 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1413 /* Get the Device Object */
1414 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1416 /* Clear the event */
1417 KeClearEvent(&FileObject
->Event
);
1419 /* Allocate the IRP */
1420 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1421 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1423 /* Set up the IRP */
1424 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1425 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1426 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1427 Irp
->RequestorMode
= PreviousMode
;
1428 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1429 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1430 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1432 /* Set up Stack Data */
1433 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1434 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1435 StackPtr
->FileObject
= FileObject
;
1437 /* Call the Driver */
1438 Status
= IopPerformSynchronousRequest(DeviceObject
,
1446 /* Check if this was async I/O */
1449 /* It was, finalize this request */
1450 Status
= IopFinalizeAsynchronousIo(Status
,
1458 /* Return the Status */
1467 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1468 IN HANDLE EventHandle OPTIONAL
,
1469 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1470 IN PVOID ApcContext OPTIONAL
,
1471 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1473 IN ULONG BufferSize
,
1474 IN ULONG CompletionFilter
,
1475 IN BOOLEAN WatchTree
)
1478 PKEVENT Event
= NULL
;
1479 PDEVICE_OBJECT DeviceObject
;
1480 PFILE_OBJECT FileObject
;
1481 PIO_STACK_LOCATION IoStack
;
1482 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1484 BOOLEAN LockedForSync
= FALSE
;
1486 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1488 /* Check if we're called from user mode */
1489 if (PreviousMode
!= KernelMode
)
1491 /* Enter SEH for probing */
1494 /* Probe the I/O STatus block */
1495 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1497 /* Probe the buffer */
1498 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1502 /* Return the exception code */
1503 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1507 /* Check if CompletionFilter is valid */
1508 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1510 return STATUS_INVALID_PARAMETER
;
1514 /* Get File Object */
1515 Status
= ObReferenceObjectByHandle(FileHandle
,
1516 FILE_LIST_DIRECTORY
,
1519 (PVOID
*)&FileObject
,
1521 if (!NT_SUCCESS(Status
)) return Status
;
1523 /* Check if we have an event handle */
1527 Status
= ObReferenceObjectByHandle(EventHandle
,
1533 if (Status
!= STATUS_SUCCESS
)
1535 ObDereferenceObject(FileObject
);
1538 KeClearEvent(Event
);
1541 /* Check if we should use Sync IO or not */
1542 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1545 IopLockFileObject(FileObject
);
1546 LockedForSync
= TRUE
;
1549 /* Clear File Object event */
1550 KeClearEvent(&FileObject
->Event
);
1552 /* Get the device object */
1553 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1555 /* Allocate the IRP */
1556 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1557 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1559 /* Set up the IRP */
1560 Irp
->RequestorMode
= PreviousMode
;
1561 Irp
->UserIosb
= IoStatusBlock
;
1562 Irp
->UserEvent
= Event
;
1563 Irp
->UserBuffer
= Buffer
;
1564 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1565 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1566 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1567 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1569 /* Set up Stack Data */
1570 IoStack
= IoGetNextIrpStackLocation(Irp
);
1571 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1572 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1573 IoStack
->FileObject
= FileObject
;
1575 /* Set parameters */
1576 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1577 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1578 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1580 /* Perform the call */
1581 return IopPerformSynchronousRequest(DeviceObject
,
1595 NtLockFile(IN HANDLE FileHandle
,
1596 IN HANDLE EventHandle OPTIONAL
,
1597 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1598 IN PVOID ApcContext OPTIONAL
,
1599 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1600 IN PLARGE_INTEGER ByteOffset
,
1601 IN PLARGE_INTEGER Length
,
1603 IN BOOLEAN FailImmediately
,
1604 IN BOOLEAN ExclusiveLock
)
1606 PFILE_OBJECT FileObject
;
1607 PLARGE_INTEGER LocalLength
= NULL
;
1609 PIO_STACK_LOCATION StackPtr
;
1610 PDEVICE_OBJECT DeviceObject
;
1611 PKEVENT Event
= NULL
;
1612 BOOLEAN LockedForSync
= FALSE
;
1613 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1614 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1616 OBJECT_HANDLE_INFORMATION HandleInformation
;
1617 PFAST_IO_DISPATCH FastIoDispatch
;
1619 CapturedByteOffset
.QuadPart
= 0;
1620 CapturedLength
.QuadPart
= 0;
1621 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1623 /* Get File Object */
1624 Status
= ObReferenceObjectByHandle(FileHandle
,
1628 (PVOID
*)&FileObject
,
1629 &HandleInformation
);
1630 if (!NT_SUCCESS(Status
)) return Status
;
1632 /* Check if we're called from user mode */
1633 if (PreviousMode
!= KernelMode
)
1635 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1636 if (!(HandleInformation
.GrantedAccess
&
1637 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1639 ObDereferenceObject(FileObject
);
1640 return STATUS_ACCESS_DENIED
;
1643 /* Enter SEH for probing */
1646 /* Probe the I/O STatus block */
1647 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1649 /* Probe and capture the large integers */
1650 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1651 CapturedLength
= ProbeForReadLargeInteger(Length
);
1653 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1655 /* Dereference the object and return exception code */
1656 ObDereferenceObject(FileObject
);
1657 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1663 /* Otherwise, capture them directly */
1664 CapturedByteOffset
= *ByteOffset
;
1665 CapturedLength
= *Length
;
1668 /* Check if we have an event handle */
1672 Status
= ObReferenceObjectByHandle(EventHandle
,
1678 if (Status
!= STATUS_SUCCESS
) return Status
;
1679 KeClearEvent(Event
);
1682 /* Get the device object */
1683 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1685 /* Try to do it the FastIO way if possible */
1686 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1687 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoLock
!= NULL
)
1689 IO_STATUS_BLOCK KernelIosb
;
1691 if (FastIoDispatch
->FastIoLock(FileObject
,
1692 &CapturedByteOffset
,
1694 PsGetCurrentProcess(),
1701 /* Write the IOSB back */
1704 *IoStatusBlock
= KernelIosb
;
1706 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1708 KernelIosb
.Status
= _SEH2_GetExceptionCode();
1712 /* If we had an event, signal it */
1715 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
1716 ObDereferenceObject(Event
);
1719 /* Set completion if required */
1720 if (FileObject
->CompletionContext
!= NULL
&& ApcContext
!= NULL
)
1722 if (!NT_SUCCESS(IoSetIoCompletion(FileObject
->CompletionContext
->Port
,
1723 FileObject
->CompletionContext
->Key
,
1726 KernelIosb
.Information
,
1729 KernelIosb
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1733 FileObject
->LockOperation
= TRUE
;
1735 /* We're done with FastIO! */
1736 ObDereferenceObject(FileObject
);
1737 return KernelIosb
.Status
;
1741 /* Check if we should use Sync IO or not */
1742 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1745 IopLockFileObject(FileObject
);
1746 LockedForSync
= TRUE
;
1749 /* Clear File Object event */
1750 KeClearEvent(&FileObject
->Event
);
1751 FileObject
->LockOperation
= TRUE
;
1753 /* Allocate the IRP */
1754 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1755 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1757 /* Set up the IRP */
1758 Irp
->RequestorMode
= PreviousMode
;
1759 Irp
->UserIosb
= IoStatusBlock
;
1760 Irp
->UserEvent
= Event
;
1761 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1762 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1763 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1764 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1766 /* Set up Stack Data */
1767 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1768 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1769 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1770 StackPtr
->FileObject
= FileObject
;
1772 /* Allocate local buffer */
1773 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1774 sizeof(LARGE_INTEGER
),
1778 /* Allocating failed, clean up and return failure */
1779 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1780 return STATUS_INSUFFICIENT_RESOURCES
;
1783 /* Set the length */
1784 *LocalLength
= CapturedLength
;
1785 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1786 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1788 /* Set Parameters */
1789 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1790 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1793 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1794 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1796 /* Perform the call */
1797 return IopPerformSynchronousRequest(DeviceObject
,
1811 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1812 IN HANDLE EventHandle OPTIONAL
,
1813 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1814 IN PVOID ApcContext OPTIONAL
,
1815 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1816 OUT PVOID FileInformation
,
1818 IN FILE_INFORMATION_CLASS FileInformationClass
,
1819 IN BOOLEAN ReturnSingleEntry
,
1820 IN PUNICODE_STRING FileName OPTIONAL
,
1821 IN BOOLEAN RestartScan
)
1824 PDEVICE_OBJECT DeviceObject
;
1825 PFILE_OBJECT FileObject
;
1826 PIO_STACK_LOCATION StackPtr
;
1827 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1829 BOOLEAN LockedForSynch
= FALSE
;
1830 PKEVENT Event
= NULL
;
1831 volatile PVOID AuxBuffer
= NULL
;
1833 UNICODE_STRING CapturedFileName
;
1834 PUNICODE_STRING SearchPattern
;
1836 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1838 /* Check if we came from user mode */
1839 if (PreviousMode
!= KernelMode
)
1841 /* Enter SEH for probing */
1844 /* Probe the I/O Status Block */
1845 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1847 /* Probe the file information */
1848 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1850 /* Check if we have a file name */
1854 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1855 if (CapturedFileName
.Length
)
1857 /* Probe its buffer */
1858 ProbeForRead(CapturedFileName
.Buffer
,
1859 CapturedFileName
.Length
,
1863 /* Allocate the auxiliary buffer */
1864 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1865 CapturedFileName
.Length
+
1866 sizeof(UNICODE_STRING
),
1868 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1869 sizeof(UNICODE_STRING
)),
1870 CapturedFileName
.Buffer
,
1871 CapturedFileName
.Length
);
1873 /* Setup the search pattern */
1874 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1875 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1876 sizeof(UNICODE_STRING
));
1877 SearchPattern
->Length
= CapturedFileName
.Length
;
1878 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1881 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1883 /* Free buffer and return the exception code */
1884 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1885 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1890 /* Get File Object */
1891 Status
= ObReferenceObjectByHandle(FileHandle
,
1892 FILE_LIST_DIRECTORY
,
1895 (PVOID
*)&FileObject
,
1897 if (!NT_SUCCESS(Status
))
1900 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1904 /* Check if we have an even handle */
1907 /* Get its pointer */
1908 Status
= ObReferenceObjectByHandle(EventHandle
,
1914 if (!NT_SUCCESS(Status
))
1917 ObDereferenceObject(FileObject
);
1922 KeClearEvent(Event
);
1925 /* Check if this is a file that was opened for Synch I/O */
1926 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1929 IopLockFileObject(FileObject
);
1931 /* Remember to unlock later */
1932 LockedForSynch
= TRUE
;
1935 /* Get the device object */
1936 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1938 /* Clear the File Object's event */
1939 KeClearEvent(&FileObject
->Event
);
1941 /* Allocate the IRP */
1942 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1943 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1945 /* Set up the IRP */
1946 Irp
->RequestorMode
= PreviousMode
;
1947 Irp
->UserIosb
= IoStatusBlock
;
1948 Irp
->UserEvent
= Event
;
1949 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1950 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1951 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1952 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1953 Irp
->MdlAddress
= NULL
;
1954 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1955 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1957 /* Check if this is buffered I/O */
1958 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1960 /* Allocate a buffer */
1961 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1964 if (!Irp
->AssociatedIrp
.SystemBuffer
)
1966 /* Allocating failed, clean up and return the exception code */
1967 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1968 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1970 /* Return the exception code */
1971 return STATUS_INSUFFICIENT_RESOURCES
;
1974 /* Set the buffer and flags */
1975 Irp
->UserBuffer
= FileInformation
;
1976 Irp
->Flags
= (IRP_BUFFERED_IO
|
1977 IRP_DEALLOCATE_BUFFER
|
1978 IRP_INPUT_OPERATION
);
1980 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1984 /* Allocate an MDL */
1985 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1986 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1987 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1989 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1991 /* Allocating failed, clean up and return the exception code */
1992 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1993 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1999 /* No allocation flags, and use the buffer directly */
2000 Irp
->UserBuffer
= FileInformation
;
2003 /* Set up Stack Data */
2004 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2005 StackPtr
->FileObject
= FileObject
;
2006 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2007 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2009 /* Set Parameters */
2010 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
2011 FileInformationClass
;
2012 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
2013 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2014 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2015 StackPtr
->Flags
= 0;
2016 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2017 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2019 /* Set deferred I/O */
2020 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
2022 /* Perform the call */
2023 return IopPerformSynchronousRequest(DeviceObject
,
2037 NtQueryEaFile(IN HANDLE FileHandle
,
2038 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2041 IN BOOLEAN ReturnSingleEntry
,
2042 IN PVOID EaList OPTIONAL
,
2043 IN ULONG EaListLength
,
2044 IN PULONG EaIndex OPTIONAL
,
2045 IN BOOLEAN RestartScan
)
2048 return STATUS_NOT_IMPLEMENTED
;
2056 NtQueryInformationFile(IN HANDLE FileHandle
,
2057 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2058 IN PVOID FileInformation
,
2060 IN FILE_INFORMATION_CLASS FileInformationClass
)
2062 OBJECT_HANDLE_INFORMATION HandleInformation
;
2063 PFILE_OBJECT FileObject
;
2066 PDEVICE_OBJECT DeviceObject
;
2067 PIO_STACK_LOCATION StackPtr
;
2068 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2069 PKEVENT Event
= NULL
;
2070 BOOLEAN LocalEvent
= FALSE
;
2071 PKNORMAL_ROUTINE NormalRoutine
;
2072 PVOID NormalContext
;
2074 IO_STATUS_BLOCK KernelIosb
;
2075 BOOLEAN CallDriver
= TRUE
;
2076 PFILE_ACCESS_INFORMATION AccessBuffer
;
2077 PFILE_MODE_INFORMATION ModeBuffer
;
2078 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer
;
2079 PFILE_ALL_INFORMATION AllBuffer
;
2080 PFAST_IO_DISPATCH FastIoDispatch
;
2082 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2084 /* Check if we're called from user mode */
2085 if (PreviousMode
!= KernelMode
)
2087 /* Validate the information class */
2088 if ((FileInformationClass
>= FileMaximumInformation
) ||
2089 !(IopQueryOperationLength
[FileInformationClass
]))
2092 return STATUS_INVALID_INFO_CLASS
;
2095 /* Validate the length */
2096 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2098 /* Invalid length */
2099 return STATUS_INFO_LENGTH_MISMATCH
;
2102 /* Enter SEH for probing */
2105 /* Probe the I/O Status block */
2106 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2108 /* Probe the information */
2109 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2111 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2113 /* Return the exception code */
2114 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2120 /* Validate the information class */
2121 if ((FileInformationClass
>= FileMaximumInformation
) ||
2122 !(IopQueryOperationLength
[FileInformationClass
]))
2125 return STATUS_INVALID_INFO_CLASS
;
2128 /* Validate the length */
2129 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2131 /* Invalid length */
2132 return STATUS_INFO_LENGTH_MISMATCH
;
2136 /* Reference the Handle */
2137 Status
= ObReferenceObjectByHandle(FileHandle
,
2138 IopQueryOperationAccess
2139 [FileInformationClass
],
2142 (PVOID
*)&FileObject
,
2143 &HandleInformation
);
2144 if (!NT_SUCCESS(Status
)) return Status
;
2146 /* Check if this is a direct open or not */
2147 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2149 /* Get the device object */
2150 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2154 /* Get the device object */
2155 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2158 /* Check if this is a file that was opened for Synch I/O */
2159 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2162 IopLockFileObject(FileObject
);
2164 /* Check if the caller just wants the position */
2165 if (FileInformationClass
== FilePositionInformation
)
2167 /* Protect write in SEH */
2170 /* Write the offset */
2171 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2172 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2174 /* Fill out the I/O Status Block */
2175 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2176 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2178 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2180 /* Get the exception code */
2181 Status
= _SEH2_GetExceptionCode();
2185 /* Release the file lock, dereference the file and return */
2186 IopUnlockFileObject(FileObject
);
2187 ObDereferenceObject(FileObject
);
2193 /* Use local event */
2194 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2197 ObDereferenceObject(FileObject
);
2198 return STATUS_INSUFFICIENT_RESOURCES
;
2200 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2204 /* Check if FastIO is possible for the two available information classes */
2205 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2206 if (FastIoDispatch
!= NULL
&&
2207 ((FileInformationClass
== FileBasicInformation
&& FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
) ||
2208 (FileInformationClass
== FileStandardInformation
&& FastIoDispatch
->FastIoQueryStandardInfo
!= NULL
)))
2210 BOOLEAN Success
= FALSE
;
2212 if (FileInformationClass
== FileBasicInformation
)
2214 Success
= FastIoDispatch
->FastIoQueryBasicInfo(FileObject
, TRUE
,
2221 Success
= FastIoDispatch
->FastIoQueryStandardInfo(FileObject
, TRUE
,
2227 /* If call succeed */
2230 /* Write the IOSB back */
2233 *IoStatusBlock
= KernelIosb
;
2235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2237 KernelIosb
.Status
= _SEH2_GetExceptionCode();
2242 IopUnlockFileObject(FileObject
);
2244 /* We're done with FastIO! */
2245 ObDereferenceObject(FileObject
);
2246 return KernelIosb
.Status
;
2250 /* Clear the File Object event */
2251 KeClearEvent(&FileObject
->Event
);
2253 /* Allocate the IRP */
2254 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2255 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2258 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2259 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2260 Irp
->RequestorMode
= PreviousMode
;
2261 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2262 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2263 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2264 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2265 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2266 Irp
->MdlAddress
= NULL
;
2267 Irp
->UserBuffer
= FileInformation
;
2269 /* Set the Stack Data */
2270 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2271 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2272 StackPtr
->FileObject
= FileObject
;
2277 /* Allocate a buffer */
2278 Irp
->AssociatedIrp
.SystemBuffer
=
2279 ExAllocatePoolWithTag(NonPagedPool
,
2283 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2285 /* Allocating failed, clean up and return the exception code */
2286 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2287 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2292 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2293 IRP_DEALLOCATE_BUFFER
|
2294 IRP_INPUT_OPERATION
|
2295 IRP_DEFER_IO_COMPLETION
);
2297 /* Set the Parameters */
2298 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2299 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2302 IopQueueIrpToThread(Irp
);
2304 /* Update operation counts */
2305 IopUpdateOperationCount(IopOtherTransfer
);
2307 /* Fill in file information before calling the driver.
2308 See 'File System Internals' page 485.*/
2309 if (FileInformationClass
== FileAccessInformation
)
2311 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2312 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2313 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2316 else if (FileInformationClass
== FileModeInformation
)
2318 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2319 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2320 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2323 else if (FileInformationClass
== FileAlignmentInformation
)
2325 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2326 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2327 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2330 else if (FileInformationClass
== FileAllInformation
)
2332 AllBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2333 AllBuffer
->AccessInformation
.AccessFlags
= HandleInformation
.GrantedAccess
;
2334 AllBuffer
->ModeInformation
.Mode
= IopGetFileMode(FileObject
);
2335 AllBuffer
->AlignmentInformation
.AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2336 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
) +
2337 sizeof(FILE_MODE_INFORMATION
) +
2338 sizeof(FILE_ALIGNMENT_INFORMATION
);
2341 /* Call the Driver */
2344 Status
= IoCallDriver(DeviceObject
, Irp
);
2348 Status
= STATUS_SUCCESS
;
2349 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2352 if (Status
== STATUS_PENDING
)
2354 /* Check if this was async I/O */
2357 /* Then to a non-alertable wait */
2358 Status
= KeWaitForSingleObject(Event
,
2363 if (Status
== STATUS_USER_APC
)
2365 /* Abort the request */
2366 IopAbortInterruptedIrp(Event
, Irp
);
2369 /* Set the final status */
2370 Status
= KernelIosb
.Status
;
2372 /* Enter SEH to write the IOSB back */
2375 /* Write it back to the caller */
2376 *IoStatusBlock
= KernelIosb
;
2378 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2380 /* Get the exception code */
2381 Status
= _SEH2_GetExceptionCode();
2385 /* Free the event */
2386 ExFreePoolWithTag(Event
, TAG_IO
);
2390 /* Wait for the IRP */
2391 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2394 (FileObject
->Flags
&
2395 FO_ALERTABLE_IO
) != 0,
2397 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2399 /* Abort the request */
2400 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2403 /* Set the final status */
2404 Status
= FileObject
->FinalStatus
;
2406 /* Release the file lock */
2407 IopUnlockFileObject(FileObject
);
2412 /* Free the event if we had one */
2415 /* Clear it in the IRP for completion */
2416 Irp
->UserEvent
= NULL
;
2417 ExFreePoolWithTag(Event
, TAG_IO
);
2420 /* Set the caller IOSB */
2421 Irp
->UserIosb
= IoStatusBlock
;
2423 /* The IRP wasn't completed, complete it ourselves */
2424 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2425 IopCompleteRequest(&Irp
->Tail
.Apc
,
2428 (PVOID
*)&FileObject
,
2430 KeLowerIrql(OldIrql
);
2432 /* Release the file object if we had locked it*/
2433 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2436 /* Return the Status */
2445 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2446 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2449 IN BOOLEAN ReturnSingleEntry
,
2450 IN PVOID SidList OPTIONAL
,
2451 IN ULONG SidListLength
,
2452 IN PSID StartSid OPTIONAL
,
2453 IN BOOLEAN RestartScan
)
2456 return STATUS_NOT_IMPLEMENTED
;
2464 NtReadFile(IN HANDLE FileHandle
,
2465 IN HANDLE Event OPTIONAL
,
2466 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2467 IN PVOID ApcContext OPTIONAL
,
2468 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2471 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2472 IN PULONG Key OPTIONAL
)
2475 PFILE_OBJECT FileObject
;
2477 PDEVICE_OBJECT DeviceObject
;
2478 PIO_STACK_LOCATION StackPtr
;
2479 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2480 PKEVENT EventObject
= NULL
;
2481 LARGE_INTEGER CapturedByteOffset
;
2482 ULONG CapturedKey
= 0;
2483 BOOLEAN Synchronous
= FALSE
;
2485 PFAST_IO_DISPATCH FastIoDispatch
;
2486 IO_STATUS_BLOCK KernelIosb
;
2490 CapturedByteOffset
.QuadPart
= 0;
2491 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2493 /* Validate User-Mode Buffers */
2494 if (PreviousMode
!= KernelMode
)
2498 /* Probe the status block */
2499 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2501 /* Probe the read buffer */
2502 ProbeForWrite(Buffer
, Length
, 1);
2504 /* Check if we got a byte offset */
2507 /* Capture and probe it */
2508 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2511 /* Capture and probe the key */
2512 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2514 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2516 /* Return the exception code */
2517 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2523 /* Kernel mode: capture directly */
2524 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2525 if (Key
) CapturedKey
= *Key
;
2528 /* Get File Object */
2529 Status
= ObReferenceObjectByHandle(FileHandle
,
2533 (PVOID
*)&FileObject
,
2535 if (!NT_SUCCESS(Status
)) return Status
;
2537 /* Check for event */
2541 Status
= ObReferenceObjectByHandle(Event
,
2545 (PVOID
*)&EventObject
,
2547 if (!NT_SUCCESS(Status
))
2550 ObDereferenceObject(FileObject
);
2554 /* Otherwise reset the event */
2555 KeClearEvent(EventObject
);
2558 /* Get the device object */
2559 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2561 /* Check if we should use Sync IO or not */
2562 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2564 /* Lock the file object */
2565 IopLockFileObject(FileObject
);
2567 /* Check if we don't have a byte offset available */
2568 if (!(ByteOffset
) ||
2569 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2570 (CapturedByteOffset
.u
.HighPart
== -1)))
2572 /* Use the Current Byte Offset instead */
2573 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2576 /* If the file is cached, try fast I/O */
2577 if (FileObject
->PrivateCacheMap
)
2579 /* Perform fast read */
2580 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2581 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoRead
!= NULL
);
2583 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2584 &CapturedByteOffset
,
2592 /* Only accept the result if we got a straightforward status */
2594 (KernelIosb
.Status
== STATUS_SUCCESS
||
2595 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2596 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2598 /* Fast path -- update transfer & operation counts */
2599 IopUpdateOperationCount(IopReadTransfer
);
2600 IopUpdateTransferCount(IopReadTransfer
,
2601 (ULONG
)KernelIosb
.Information
);
2603 /* Enter SEH to write the IOSB back */
2606 /* Write it back to the caller */
2607 *IoStatusBlock
= KernelIosb
;
2609 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2611 /* The caller's IOSB was invalid, so fail */
2612 if (EventObject
) ObDereferenceObject(EventObject
);
2613 IopUnlockFileObject(FileObject
);
2614 ObDereferenceObject(FileObject
);
2615 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2619 /* Signal the completion event */
2622 KeSetEvent(EventObject
, 0, FALSE
);
2623 ObDereferenceObject(EventObject
);
2627 IopUnlockFileObject(FileObject
);
2628 ObDereferenceObject(FileObject
);
2629 return KernelIosb
.Status
;
2633 /* Remember we are sync */
2636 else if (!(ByteOffset
) &&
2637 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2639 /* Otherwise, this was async I/O without a byte offset, so fail */
2640 if (EventObject
) ObDereferenceObject(EventObject
);
2641 ObDereferenceObject(FileObject
);
2642 return STATUS_INVALID_PARAMETER
;
2645 /* Clear the File Object's event */
2646 KeClearEvent(&FileObject
->Event
);
2648 /* Allocate the IRP */
2649 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2650 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2653 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2654 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2655 Irp
->RequestorMode
= PreviousMode
;
2656 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2657 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2658 Irp
->UserIosb
= IoStatusBlock
;
2659 Irp
->UserEvent
= EventObject
;
2660 Irp
->PendingReturned
= FALSE
;
2661 Irp
->Cancel
= FALSE
;
2662 Irp
->CancelRoutine
= NULL
;
2663 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2664 Irp
->MdlAddress
= NULL
;
2666 /* Set the Stack Data */
2667 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2668 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2669 StackPtr
->FileObject
= FileObject
;
2670 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2671 StackPtr
->Parameters
.Read
.Length
= Length
;
2672 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2674 /* Check if this is buffered I/O */
2675 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2677 /* Check if we have a buffer length */
2683 /* Allocate a buffer */
2684 Irp
->AssociatedIrp
.SystemBuffer
=
2685 ExAllocatePoolWithTag(NonPagedPool
,
2689 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2691 /* Allocating failed, clean up and return the exception code */
2692 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2693 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2697 /* Set the buffer and flags */
2698 Irp
->UserBuffer
= Buffer
;
2699 Irp
->Flags
= (IRP_BUFFERED_IO
|
2700 IRP_DEALLOCATE_BUFFER
|
2701 IRP_INPUT_OPERATION
);
2705 /* Not reading anything */
2706 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2709 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2711 /* Check if we have a buffer length */
2716 /* Allocate an MDL */
2717 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2719 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2720 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2722 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2724 /* Allocating failed, clean up and return the exception code */
2725 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2726 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2732 /* No allocation flags */
2737 /* No allocation flags, and use the buffer directly */
2739 Irp
->UserBuffer
= Buffer
;
2742 /* Now set the deferred read flags */
2743 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2744 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2746 /* Perform the call */
2747 return IopPerformSynchronousRequest(DeviceObject
,
2761 NtReadFileScatter(IN HANDLE FileHandle
,
2762 IN HANDLE Event OPTIONAL
,
2763 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2764 IN PVOID UserApcContext OPTIONAL
,
2765 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2766 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2767 IN ULONG BufferLength
,
2768 IN PLARGE_INTEGER ByteOffset
,
2769 IN PULONG Key OPTIONAL
)
2772 return STATUS_NOT_IMPLEMENTED
;
2780 NtSetEaFile(IN HANDLE FileHandle
,
2781 IN PIO_STATUS_BLOCK IoStatusBlock
,
2783 IN ULONG EaBufferSize
)
2786 return STATUS_NOT_IMPLEMENTED
;
2794 NtSetInformationFile(IN HANDLE FileHandle
,
2795 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2796 IN PVOID FileInformation
,
2798 IN FILE_INFORMATION_CLASS FileInformationClass
)
2800 PFILE_OBJECT FileObject
;
2803 PDEVICE_OBJECT DeviceObject
;
2804 PIO_STACK_LOCATION StackPtr
;
2805 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2806 PKEVENT Event
= NULL
;
2807 BOOLEAN LocalEvent
= FALSE
;
2808 PKNORMAL_ROUTINE NormalRoutine
;
2809 PVOID NormalContext
;
2811 IO_STATUS_BLOCK KernelIosb
;
2813 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2814 PIO_COMPLETION_CONTEXT Context
;
2815 PFILE_RENAME_INFORMATION RenameInfo
;
2816 HANDLE TargetHandle
= NULL
;
2818 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2820 /* Check if we're called from user mode */
2821 if (PreviousMode
!= KernelMode
)
2823 /* Validate the information class */
2824 if ((FileInformationClass
>= FileMaximumInformation
) ||
2825 !(IopSetOperationLength
[FileInformationClass
]))
2828 return STATUS_INVALID_INFO_CLASS
;
2831 /* Validate the length */
2832 if (Length
< IopSetOperationLength
[FileInformationClass
])
2834 /* Invalid length */
2835 return STATUS_INFO_LENGTH_MISMATCH
;
2838 /* Enter SEH for probing */
2841 /* Probe the I/O Status block */
2842 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2844 /* Probe the information */
2845 ProbeForRead(FileInformation
,
2847 (Length
== sizeof(BOOLEAN
)) ?
2848 sizeof(BOOLEAN
) : sizeof(ULONG
));
2850 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2852 /* Return the exception code */
2853 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2859 /* Validate the information class */
2860 if ((FileInformationClass
>= FileMaximumInformation
) ||
2861 !(IopSetOperationLength
[FileInformationClass
]))
2864 return STATUS_INVALID_INFO_CLASS
;
2867 /* Validate the length */
2868 if (Length
< IopSetOperationLength
[FileInformationClass
])
2870 /* Invalid length */
2871 return STATUS_INFO_LENGTH_MISMATCH
;
2875 /* Reference the Handle */
2876 Status
= ObReferenceObjectByHandle(FileHandle
,
2877 IopSetOperationAccess
2878 [FileInformationClass
],
2881 (PVOID
*)&FileObject
,
2883 if (!NT_SUCCESS(Status
)) return Status
;
2885 /* Check if this is a direct open or not */
2886 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2888 /* Get the device object */
2889 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2893 /* Get the device object */
2894 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2897 DPRINT("Will call: %p\n", DeviceObject
);
2898 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
2900 /* Check if this is a file that was opened for Synch I/O */
2901 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2904 IopLockFileObject(FileObject
);
2906 /* Check if the caller just wants the position */
2907 if (FileInformationClass
== FilePositionInformation
)
2909 /* Protect write in SEH */
2912 /* Write the offset */
2913 FileObject
->CurrentByteOffset
=
2914 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2917 /* Fill out the I/O Status Block */
2918 IoStatusBlock
->Information
= 0;
2919 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2921 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2923 /* Get the exception code */
2924 Status
= _SEH2_GetExceptionCode();
2928 /* Update transfer count */
2929 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2931 /* Release the file lock, dereference the file and return */
2932 IopUnlockFileObject(FileObject
);
2933 ObDereferenceObject(FileObject
);
2939 /* Use local event */
2940 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2943 ObDereferenceObject(FileObject
);
2944 return STATUS_INSUFFICIENT_RESOURCES
;
2947 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2951 /* Clear the File Object event */
2952 KeClearEvent(&FileObject
->Event
);
2954 /* Allocate the IRP */
2955 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2956 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2959 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2960 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2961 Irp
->RequestorMode
= PreviousMode
;
2962 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2963 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2964 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2965 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2966 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2967 Irp
->MdlAddress
= NULL
;
2968 Irp
->UserBuffer
= FileInformation
;
2970 /* Set the Stack Data */
2971 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2972 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2973 StackPtr
->FileObject
= FileObject
;
2978 /* Allocate a buffer */
2979 Irp
->AssociatedIrp
.SystemBuffer
=
2980 ExAllocatePoolWithTag(NonPagedPool
,
2984 /* Copy the data into it */
2985 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2989 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2991 /* Allocating failed, clean up and return the exception code */
2992 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2993 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2998 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2999 IRP_DEALLOCATE_BUFFER
|
3000 IRP_DEFER_IO_COMPLETION
);
3002 /* Set the Parameters */
3003 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
3004 StackPtr
->Parameters
.SetFile
.Length
= Length
;
3007 IopQueueIrpToThread(Irp
);
3009 /* Update operation counts */
3010 IopUpdateOperationCount(IopOtherTransfer
);
3012 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3013 /* Handle IO Completion Port quickly */
3014 if (FileInformationClass
== FileCompletionInformation
)
3016 /* Check if the file object already has a completion port */
3017 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3018 (FileObject
->CompletionContext
))
3021 Status
= STATUS_INVALID_PARAMETER
;
3025 /* Reference the Port */
3026 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3027 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3028 IO_COMPLETION_MODIFY_STATE
,
3033 if (NT_SUCCESS(Status
))
3035 /* Allocate the Context */
3036 Context
= ExAllocatePoolWithTag(PagedPool
,
3037 sizeof(IO_COMPLETION_CONTEXT
),
3042 Context
->Key
= CompletionInfo
->Key
;
3043 Context
->Port
= Queue
;
3044 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3050 * Someone else set the completion port in the
3051 * meanwhile, so dereference the port and fail.
3053 ExFreePoolWithTag(Context
, IOC_TAG
);
3054 ObDereferenceObject(Queue
);
3055 Status
= STATUS_INVALID_PARAMETER
;
3060 /* Dereference the Port now */
3061 ObDereferenceObject(Queue
);
3062 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3067 /* Set the IRP Status */
3068 Irp
->IoStatus
.Status
= Status
;
3069 Irp
->IoStatus
.Information
= 0;
3071 else if (FileInformationClass
== FileRenameInformation
||
3072 FileInformationClass
== FileLinkInformation
||
3073 FileInformationClass
== FileMoveClusterInformation
)
3075 /* Get associated information */
3076 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3081 * -> sizes are valid
3083 if (RenameInfo
->FileNameLength
!= 0 &&
3084 !(RenameInfo
->FileNameLength
& 1) &&
3085 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3087 /* Properly set information received */
3088 if (FileInformationClass
== FileMoveClusterInformation
)
3090 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3094 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3097 /* If we got fully path OR relative target, attempt a parent directory open */
3098 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3100 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3101 if (!NT_SUCCESS(Status
))
3103 Irp
->IoStatus
.Status
= Status
;
3107 /* Call the Driver */
3108 Status
= IoCallDriver(DeviceObject
, Irp
);
3113 /* Call the Driver */
3114 Status
= IoCallDriver(DeviceObject
, Irp
);
3119 Status
= STATUS_INVALID_PARAMETER
;
3120 Irp
->IoStatus
.Status
= Status
;
3125 /* Call the Driver */
3126 Status
= IoCallDriver(DeviceObject
, Irp
);
3129 /* Check if we're waiting for the IRP to complete */
3130 if (Status
== STATUS_PENDING
)
3132 /* Check if this was async I/O */
3135 /* Then to a non-alertable wait */
3136 Status
= KeWaitForSingleObject(Event
,
3141 if (Status
== STATUS_USER_APC
)
3143 /* Abort the request */
3144 IopAbortInterruptedIrp(Event
, Irp
);
3147 /* Set the final status */
3148 Status
= KernelIosb
.Status
;
3150 /* Enter SEH to write the IOSB back */
3153 /* Write it back to the caller */
3154 *IoStatusBlock
= KernelIosb
;
3156 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3158 /* Get the exception code */
3159 Status
= _SEH2_GetExceptionCode();
3163 /* Free the event */
3164 ExFreePoolWithTag(Event
, TAG_IO
);
3168 /* Wait for the IRP */
3169 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3172 (FileObject
->Flags
&
3173 FO_ALERTABLE_IO
) != 0,
3175 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3177 /* Abort the request */
3178 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3181 /* Set the final status */
3182 Status
= FileObject
->FinalStatus
;
3184 /* Release the file lock */
3185 IopUnlockFileObject(FileObject
);
3190 /* Free the event if we had one */
3193 /* Clear it in the IRP for completion */
3194 Irp
->UserEvent
= NULL
;
3195 ExFreePoolWithTag(Event
, TAG_IO
);
3198 /* Set the caller IOSB */
3199 Irp
->UserIosb
= IoStatusBlock
;
3201 /* The IRP wasn't completed, complete it ourselves */
3202 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3203 IopCompleteRequest(&Irp
->Tail
.Apc
,
3206 (PVOID
*)&FileObject
,
3208 KeLowerIrql(OldIrql
);
3210 /* Release the file object if we had locked it*/
3211 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3214 if (TargetHandle
!= NULL
)
3216 ObCloseHandle(TargetHandle
, KernelMode
);
3219 /* Return the Status */
3228 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3229 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3231 IN ULONG BufferLength
)
3234 return STATUS_NOT_IMPLEMENTED
;
3242 NtUnlockFile(IN HANDLE FileHandle
,
3243 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3244 IN PLARGE_INTEGER ByteOffset
,
3245 IN PLARGE_INTEGER Length
,
3246 IN ULONG Key OPTIONAL
)
3248 PFILE_OBJECT FileObject
;
3249 PLARGE_INTEGER LocalLength
= NULL
;
3251 PIO_STACK_LOCATION StackPtr
;
3252 PDEVICE_OBJECT DeviceObject
;
3253 PKEVENT Event
= NULL
;
3254 BOOLEAN LocalEvent
= FALSE
;
3255 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3256 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3258 OBJECT_HANDLE_INFORMATION HandleInformation
;
3259 IO_STATUS_BLOCK KernelIosb
;
3260 PFAST_IO_DISPATCH FastIoDispatch
;
3262 CapturedByteOffset
.QuadPart
= 0;
3263 CapturedLength
.QuadPart
= 0;
3264 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3266 /* Get File Object */
3267 Status
= ObReferenceObjectByHandle(FileHandle
,
3271 (PVOID
*)&FileObject
,
3272 &HandleInformation
);
3273 if (!NT_SUCCESS(Status
)) return Status
;
3275 /* Check if we're called from user mode */
3276 if (PreviousMode
!= KernelMode
)
3278 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3279 if (!(HandleInformation
.GrantedAccess
&
3280 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3282 ObDereferenceObject(FileObject
);
3283 return STATUS_ACCESS_DENIED
;
3286 /* Enter SEH for probing */
3289 /* Probe the I/O Status block */
3290 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3292 /* Probe and capture the large integers */
3293 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3294 CapturedLength
= ProbeForReadLargeInteger(Length
);
3296 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3298 /* Dereference the object and return exception code */
3299 ObDereferenceObject(FileObject
);
3300 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3306 /* Otherwise, capture them directly */
3307 CapturedByteOffset
= *ByteOffset
;
3308 CapturedLength
= *Length
;
3311 /* Check if this is a direct open or not */
3312 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3314 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3318 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3321 /* Try to do it the FastIO way if possible */
3322 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3323 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3325 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3326 &CapturedByteOffset
,
3328 PsGetCurrentProcess(),
3333 /* Write the IOSB back */
3336 *IoStatusBlock
= KernelIosb
;
3338 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3340 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3344 /* We're done with FastIO! */
3345 ObDereferenceObject(FileObject
);
3346 return KernelIosb
.Status
;
3350 /* Check if we should use Sync IO or not */
3351 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3354 IopLockFileObject(FileObject
);
3358 /* Use local event */
3359 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3362 ObDereferenceObject(FileObject
);
3363 return STATUS_INSUFFICIENT_RESOURCES
;
3365 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3369 /* Clear File Object event */
3370 KeClearEvent(&FileObject
->Event
);
3372 /* Allocate the IRP */
3373 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3374 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3376 /* Set up the IRP */
3377 Irp
->RequestorMode
= PreviousMode
;
3378 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3379 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3380 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3381 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3382 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3383 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3385 /* Set up Stack Data */
3386 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3387 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3388 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3389 StackPtr
->FileObject
= FileObject
;
3394 /* Allocate a buffer */
3395 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3396 sizeof(LARGE_INTEGER
),
3399 /* Set the length */
3400 *LocalLength
= CapturedLength
;
3401 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3402 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3404 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3406 /* Allocating failed, clean up and return the exception code */
3407 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3408 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3410 /* Return the exception code */
3411 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3415 /* Set Parameters */
3416 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3417 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3419 /* Call the Driver */
3420 Status
= IopPerformSynchronousRequest(DeviceObject
,
3428 /* Check if this was async I/O */
3431 /* It was, finalize this request */
3432 Status
= IopFinalizeAsynchronousIo(Status
,
3449 NtWriteFile(IN HANDLE FileHandle
,
3450 IN HANDLE Event OPTIONAL
,
3451 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3452 IN PVOID ApcContext OPTIONAL
,
3453 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3456 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3457 IN PULONG Key OPTIONAL
)
3460 PFILE_OBJECT FileObject
;
3462 PDEVICE_OBJECT DeviceObject
;
3463 PIO_STACK_LOCATION StackPtr
;
3464 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3465 PKEVENT EventObject
= NULL
;
3466 LARGE_INTEGER CapturedByteOffset
;
3467 ULONG CapturedKey
= 0;
3468 BOOLEAN Synchronous
= FALSE
;
3470 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3471 PFAST_IO_DISPATCH FastIoDispatch
;
3472 IO_STATUS_BLOCK KernelIosb
;
3476 CapturedByteOffset
.QuadPart
= 0;
3477 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3479 /* Get File Object */
3480 Status
= ObReferenceObjectByHandle(FileHandle
,
3484 (PVOID
*)&FileObject
,
3486 if (!NT_SUCCESS(Status
)) return Status
;
3488 /* Validate User-Mode Buffers */
3489 if (PreviousMode
!= KernelMode
)
3494 * Check if the handle has either FILE_WRITE_DATA or
3495 * FILE_APPEND_DATA granted. However, if this is a named pipe,
3496 * make sure we don't ask for FILE_APPEND_DATA as it interferes
3497 * with the FILE_CREATE_PIPE_INSTANCE access right!
3499 if (!(ObjectHandleInfo
.GrantedAccess
&
3500 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
3501 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
3504 ObDereferenceObject(FileObject
);
3505 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
3508 /* Probe the status block */
3509 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3511 /* Probe the read buffer */
3512 ProbeForRead(Buffer
, Length
, 1);
3514 /* Check if we got a byte offset */
3517 /* Capture and probe it */
3518 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3521 /* Capture and probe the key */
3522 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3524 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3526 /* Release the file object and return the exception code */
3527 ObDereferenceObject(FileObject
);
3528 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3534 /* Kernel mode: capture directly */
3535 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3536 if (Key
) CapturedKey
= *Key
;
3539 /* Check if this is an append operation */
3540 if ((ObjectHandleInfo
.GrantedAccess
&
3541 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3543 /* Give the drivers something to understand */
3544 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3545 CapturedByteOffset
.u
.HighPart
= -1;
3548 /* Check for event */
3552 Status
= ObReferenceObjectByHandle(Event
,
3556 (PVOID
*)&EventObject
,
3558 if (!NT_SUCCESS(Status
))
3561 ObDereferenceObject(FileObject
);
3565 /* Otherwise reset the event */
3566 KeClearEvent(EventObject
);
3569 /* Get the device object */
3570 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3572 /* Check if we should use Sync IO or not */
3573 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3575 /* Lock the file object */
3576 IopLockFileObject(FileObject
);
3578 /* Check if we don't have a byte offset available */
3579 if (!(ByteOffset
) ||
3580 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3581 (CapturedByteOffset
.u
.HighPart
== -1)))
3583 /* Use the Current Byte Offset instead */
3584 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3587 /* If the file is cached, try fast I/O */
3588 if (FileObject
->PrivateCacheMap
)
3590 /* Perform fast write */
3591 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3592 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoWrite
!= NULL
);
3594 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3595 &CapturedByteOffset
,
3603 /* Only accept the result if it was successful */
3605 KernelIosb
.Status
== STATUS_SUCCESS
)
3607 /* Fast path -- update transfer & operation counts */
3608 IopUpdateOperationCount(IopWriteTransfer
);
3609 IopUpdateTransferCount(IopWriteTransfer
,
3610 (ULONG
)KernelIosb
.Information
);
3612 /* Enter SEH to write the IOSB back */
3615 /* Write it back to the caller */
3616 *IoStatusBlock
= KernelIosb
;
3618 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3620 /* The caller's IOSB was invalid, so fail */
3621 if (EventObject
) ObDereferenceObject(EventObject
);
3622 IopUnlockFileObject(FileObject
);
3623 ObDereferenceObject(FileObject
);
3624 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3628 /* Signal the completion event */
3631 KeSetEvent(EventObject
, 0, FALSE
);
3632 ObDereferenceObject(EventObject
);
3636 IopUnlockFileObject(FileObject
);
3637 ObDereferenceObject(FileObject
);
3638 return KernelIosb
.Status
;
3642 /* Remember we are sync */
3645 else if (!(ByteOffset
) &&
3646 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3648 /* Otherwise, this was async I/O without a byte offset, so fail */
3649 if (EventObject
) ObDereferenceObject(EventObject
);
3650 ObDereferenceObject(FileObject
);
3651 return STATUS_INVALID_PARAMETER
;
3654 /* Clear the File Object's event */
3655 KeClearEvent(&FileObject
->Event
);
3657 /* Allocate the IRP */
3658 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3659 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3662 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3663 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3664 Irp
->RequestorMode
= PreviousMode
;
3665 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3666 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3667 Irp
->UserIosb
= IoStatusBlock
;
3668 Irp
->UserEvent
= EventObject
;
3669 Irp
->PendingReturned
= FALSE
;
3670 Irp
->Cancel
= FALSE
;
3671 Irp
->CancelRoutine
= NULL
;
3672 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3673 Irp
->MdlAddress
= NULL
;
3675 /* Set the Stack Data */
3676 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3677 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3678 StackPtr
->FileObject
= FileObject
;
3679 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3680 SL_WRITE_THROUGH
: 0;
3681 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3682 StackPtr
->Parameters
.Write
.Length
= Length
;
3683 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3685 /* Check if this is buffered I/O */
3686 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3688 /* Check if we have a buffer length */
3694 /* Allocate a buffer */
3695 Irp
->AssociatedIrp
.SystemBuffer
=
3696 ExAllocatePoolWithTag(NonPagedPool
,
3700 /* Copy the data into it */
3701 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3703 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3705 /* Allocating failed, clean up and return the exception code */
3706 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3707 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3712 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3716 /* Not writing anything */
3717 Irp
->Flags
= IRP_BUFFERED_IO
;
3720 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3722 /* Check if we have a buffer length */
3727 /* Allocate an MDL */
3728 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3730 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3731 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3733 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3735 /* Allocating failed, clean up and return the exception code */
3736 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3737 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3742 /* No allocation flags */
3747 /* No allocation flags, and use the buffer directly */
3749 Irp
->UserBuffer
= Buffer
;
3752 /* Now set the deferred read flags */
3753 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3754 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3756 /* Perform the call */
3757 return IopPerformSynchronousRequest(DeviceObject
,
3768 NtWriteFileGather(IN HANDLE FileHandle
,
3769 IN HANDLE Event OPTIONAL
,
3770 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3771 IN PVOID UserApcContext OPTIONAL
,
3772 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3773 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3774 IN ULONG BufferLength
,
3775 IN PLARGE_INTEGER ByteOffset
,
3776 IN PULONG Key OPTIONAL
)
3779 return STATUS_NOT_IMPLEMENTED
;
3787 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3788 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3789 OUT PVOID FsInformation
,
3791 IN FS_INFORMATION_CLASS FsInformationClass
)
3793 PFILE_OBJECT FileObject
;
3795 PIO_STACK_LOCATION StackPtr
;
3796 PDEVICE_OBJECT DeviceObject
;
3797 PKEVENT Event
= NULL
;
3798 BOOLEAN LocalEvent
= FALSE
;
3799 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3801 IO_STATUS_BLOCK KernelIosb
;
3803 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3805 /* Check if we're called from user mode */
3806 if (PreviousMode
!= KernelMode
)
3808 /* Validate the information class */
3809 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3810 !(IopQueryFsOperationLength
[FsInformationClass
]))
3813 return STATUS_INVALID_INFO_CLASS
;
3816 /* Validate the length */
3817 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3819 /* Invalid length */
3820 return STATUS_INFO_LENGTH_MISMATCH
;
3823 /* Enter SEH for probing */
3826 /* Probe the I/O Status block */
3827 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3829 /* Probe the information */
3830 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3832 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3834 /* Return the exception code */
3835 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3840 /* Get File Object */
3841 Status
= ObReferenceObjectByHandle(FileHandle
,
3842 IopQueryFsOperationAccess
3843 [FsInformationClass
],
3846 (PVOID
*)&FileObject
,
3848 if (!NT_SUCCESS(Status
)) return Status
;
3850 /* Check if we should use Sync IO or not */
3851 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3854 IopLockFileObject(FileObject
);
3858 /* Use local event */
3859 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3862 ObDereferenceObject(FileObject
);
3863 return STATUS_INSUFFICIENT_RESOURCES
;
3865 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3869 /* Get the device object */
3870 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3872 /* Clear File Object event */
3873 KeClearEvent(&FileObject
->Event
);
3875 /* Allocate the IRP */
3876 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3877 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3879 /* Set up the IRP */
3880 Irp
->RequestorMode
= PreviousMode
;
3881 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3882 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3883 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3884 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3885 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3886 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3887 Irp
->UserBuffer
= FsInformation
;
3888 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3889 Irp
->MdlAddress
= NULL
;
3891 /* Set up Stack Data */
3892 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3893 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3894 StackPtr
->FileObject
= FileObject
;
3899 /* Allocate a buffer */
3900 Irp
->AssociatedIrp
.SystemBuffer
=
3901 ExAllocatePoolWithTag(NonPagedPool
,
3905 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3907 /* Allocating failed, clean up and return the exception code */
3908 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3909 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3913 /* Set the flags for this buffered + deferred I/O */
3914 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3915 IRP_DEALLOCATE_BUFFER
|
3916 IRP_INPUT_OPERATION
|
3917 IRP_DEFER_IO_COMPLETION
);
3919 /* Set Parameters */
3920 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3921 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3923 /* Call the Driver */
3924 Status
= IopPerformSynchronousRequest(DeviceObject
,
3932 /* Check if this was async I/O */
3935 /* It was, finalize this request */
3936 Status
= IopFinalizeAsynchronousIo(Status
,
3953 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3954 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3955 IN PVOID FsInformation
,
3957 IN FS_INFORMATION_CLASS FsInformationClass
)
3959 PFILE_OBJECT FileObject
;
3961 PIO_STACK_LOCATION StackPtr
;
3962 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3963 PKEVENT Event
= NULL
;
3964 BOOLEAN LocalEvent
= FALSE
;
3965 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3967 IO_STATUS_BLOCK KernelIosb
;
3968 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3970 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3972 /* Check if we're called from user mode */
3973 if (PreviousMode
!= KernelMode
)
3975 /* Validate the information class */
3976 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3977 !(IopSetFsOperationLength
[FsInformationClass
]))
3980 return STATUS_INVALID_INFO_CLASS
;
3983 /* Validate the length */
3984 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3986 /* Invalid length */
3987 return STATUS_INFO_LENGTH_MISMATCH
;
3990 /* Enter SEH for probing */
3993 /* Probe the I/O Status block */
3994 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3996 /* Probe the information */
3997 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3999 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4001 /* Return the exception code */
4002 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4007 /* Get File Object */
4008 Status
= ObReferenceObjectByHandle(FileHandle
,
4009 IopSetFsOperationAccess
4010 [FsInformationClass
],
4013 (PVOID
*)&FileObject
,
4015 if (!NT_SUCCESS(Status
)) return Status
;
4017 /* Get target device for notification */
4018 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4019 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4021 /* Check if we should use Sync IO or not */
4022 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4025 IopLockFileObject(FileObject
);
4029 /* Use local event */
4030 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4033 ObDereferenceObject(FileObject
);
4034 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4035 return STATUS_INSUFFICIENT_RESOURCES
;
4037 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4041 /* Get the device object */
4042 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4044 /* Clear File Object event */
4045 KeClearEvent(&FileObject
->Event
);
4047 /* Allocate the IRP */
4048 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4051 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4052 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4055 /* Set up the IRP */
4056 Irp
->RequestorMode
= PreviousMode
;
4057 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4058 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4059 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4060 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4061 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4062 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4063 Irp
->UserBuffer
= FsInformation
;
4064 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4065 Irp
->MdlAddress
= NULL
;
4067 /* Set up Stack Data */
4068 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4069 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
4070 StackPtr
->FileObject
= FileObject
;
4075 /* Allocate a buffer */
4076 Irp
->AssociatedIrp
.SystemBuffer
=
4077 ExAllocatePoolWithTag(NonPagedPool
,
4081 /* Copy the data into it */
4082 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
4084 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4086 /* Allocating failed, clean up and return the exception code */
4087 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4088 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4089 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4093 /* Set the flags for this buffered + deferred I/O */
4094 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4096 /* Set Parameters */
4097 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
4098 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
4100 /* Call the Driver */
4101 Status
= IopPerformSynchronousRequest(DeviceObject
,
4109 /* Check if this was async I/O */
4112 /* It was, finalize this request */
4113 Status
= IopFinalizeAsynchronousIo(Status
,
4121 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
4123 /* Time to report change */
4124 NotificationStructure
.Version
= 1;
4125 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
4126 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
4127 NotificationStructure
.FileObject
= NULL
;
4128 NotificationStructure
.NameBufferOffset
= - 1;
4129 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
4141 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
4144 return STATUS_NOT_IMPLEMENTED
;
4152 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
4155 return STATUS_NOT_IMPLEMENTED
;