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 /* Are there two associated completion routines? */
1905 if (FileObject
->CompletionContext
!= NULL
&& ApcRoutine
!= NULL
)
1907 ObDereferenceObject(FileObject
);
1908 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1909 return STATUS_INVALID_PARAMETER
;
1912 /* Check if we have an even handle */
1915 /* Get its pointer */
1916 Status
= ObReferenceObjectByHandle(EventHandle
,
1922 if (!NT_SUCCESS(Status
))
1925 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1926 ObDereferenceObject(FileObject
);
1931 KeClearEvent(Event
);
1934 /* Check if this is a file that was opened for Synch I/O */
1935 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1938 IopLockFileObject(FileObject
);
1940 /* Remember to unlock later */
1941 LockedForSynch
= TRUE
;
1944 /* Get the device object */
1945 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1947 /* Clear the File Object's event */
1948 KeClearEvent(&FileObject
->Event
);
1950 /* Allocate the IRP */
1951 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1952 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1954 /* Set up the IRP */
1955 Irp
->RequestorMode
= PreviousMode
;
1956 Irp
->UserIosb
= IoStatusBlock
;
1957 Irp
->UserEvent
= Event
;
1958 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1959 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1960 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1961 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1962 Irp
->MdlAddress
= NULL
;
1963 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1964 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1966 /* Check if this is buffered I/O */
1967 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1969 /* Allocate a buffer */
1970 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1973 if (!Irp
->AssociatedIrp
.SystemBuffer
)
1975 /* Allocating failed, clean up and return the exception code */
1976 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1977 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1979 /* Return the exception code */
1980 return STATUS_INSUFFICIENT_RESOURCES
;
1983 /* Set the buffer and flags */
1984 Irp
->UserBuffer
= FileInformation
;
1985 Irp
->Flags
= (IRP_BUFFERED_IO
|
1986 IRP_DEALLOCATE_BUFFER
|
1987 IRP_INPUT_OPERATION
);
1989 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1993 /* Allocate an MDL */
1994 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1995 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1996 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1998 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2000 /* Allocating failed, clean up and return the exception code */
2001 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2002 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2008 /* No allocation flags, and use the buffer directly */
2009 Irp
->UserBuffer
= FileInformation
;
2012 /* Set up Stack Data */
2013 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2014 StackPtr
->FileObject
= FileObject
;
2015 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
2016 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
2018 /* Set Parameters */
2019 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
2020 FileInformationClass
;
2021 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
2022 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
2023 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
2024 StackPtr
->Flags
= 0;
2025 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
2026 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
2028 /* Set deferred I/O */
2029 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
2031 /* Perform the call */
2032 return IopPerformSynchronousRequest(DeviceObject
,
2046 NtQueryEaFile(IN HANDLE FileHandle
,
2047 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2050 IN BOOLEAN ReturnSingleEntry
,
2051 IN PVOID EaList OPTIONAL
,
2052 IN ULONG EaListLength
,
2053 IN PULONG EaIndex OPTIONAL
,
2054 IN BOOLEAN RestartScan
)
2057 return STATUS_NOT_IMPLEMENTED
;
2065 NtQueryInformationFile(IN HANDLE FileHandle
,
2066 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2067 IN PVOID FileInformation
,
2069 IN FILE_INFORMATION_CLASS FileInformationClass
)
2071 OBJECT_HANDLE_INFORMATION HandleInformation
;
2072 PFILE_OBJECT FileObject
;
2075 PDEVICE_OBJECT DeviceObject
;
2076 PIO_STACK_LOCATION StackPtr
;
2077 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2078 PKEVENT Event
= NULL
;
2079 BOOLEAN LocalEvent
= FALSE
;
2080 PKNORMAL_ROUTINE NormalRoutine
;
2081 PVOID NormalContext
;
2083 IO_STATUS_BLOCK KernelIosb
;
2084 BOOLEAN CallDriver
= TRUE
;
2085 PFILE_ACCESS_INFORMATION AccessBuffer
;
2086 PFILE_MODE_INFORMATION ModeBuffer
;
2087 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer
;
2088 PFILE_ALL_INFORMATION AllBuffer
;
2089 PFAST_IO_DISPATCH FastIoDispatch
;
2091 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2093 /* Check if we're called from user mode */
2094 if (PreviousMode
!= KernelMode
)
2096 /* Validate the information class */
2097 if ((FileInformationClass
>= FileMaximumInformation
) ||
2098 !(IopQueryOperationLength
[FileInformationClass
]))
2101 return STATUS_INVALID_INFO_CLASS
;
2104 /* Validate the length */
2105 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2107 /* Invalid length */
2108 return STATUS_INFO_LENGTH_MISMATCH
;
2111 /* Enter SEH for probing */
2114 /* Probe the I/O Status block */
2115 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2117 /* Probe the information */
2118 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
2120 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2122 /* Return the exception code */
2123 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2130 /* Validate the information class */
2131 if ((FileInformationClass
>= FileMaximumInformation
) ||
2132 !(IopQueryOperationLength
[FileInformationClass
]))
2135 return STATUS_INVALID_INFO_CLASS
;
2138 /* Validate the length */
2139 if (Length
< IopQueryOperationLength
[FileInformationClass
])
2141 /* Invalid length */
2142 return STATUS_INFO_LENGTH_MISMATCH
;
2147 /* Reference the Handle */
2148 Status
= ObReferenceObjectByHandle(FileHandle
,
2149 IopQueryOperationAccess
2150 [FileInformationClass
],
2153 (PVOID
*)&FileObject
,
2154 &HandleInformation
);
2155 if (!NT_SUCCESS(Status
)) return Status
;
2157 /* Check if this is a direct open or not */
2158 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2160 /* Get the device object */
2161 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2165 /* Get the device object */
2166 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2169 /* Check if this is a file that was opened for Synch I/O */
2170 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2173 IopLockFileObject(FileObject
);
2175 /* Check if the caller just wants the position */
2176 if (FileInformationClass
== FilePositionInformation
)
2178 /* Protect write in SEH */
2181 /* Write the offset */
2182 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2183 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
2185 /* Fill out the I/O Status Block */
2186 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
2187 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2189 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2191 /* Get the exception code */
2192 Status
= _SEH2_GetExceptionCode();
2196 /* Release the file lock, dereference the file and return */
2197 IopUnlockFileObject(FileObject
);
2198 ObDereferenceObject(FileObject
);
2204 /* Use local event */
2205 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2208 ObDereferenceObject(FileObject
);
2209 return STATUS_INSUFFICIENT_RESOURCES
;
2211 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2215 /* Check if FastIO is possible for the two available information classes */
2216 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2217 if (FastIoDispatch
!= NULL
&&
2218 ((FileInformationClass
== FileBasicInformation
&& FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
) ||
2219 (FileInformationClass
== FileStandardInformation
&& FastIoDispatch
->FastIoQueryStandardInfo
!= NULL
)))
2221 BOOLEAN Success
= FALSE
;
2223 if (FileInformationClass
== FileBasicInformation
)
2225 Success
= FastIoDispatch
->FastIoQueryBasicInfo(FileObject
, TRUE
,
2232 Success
= FastIoDispatch
->FastIoQueryStandardInfo(FileObject
, TRUE
,
2238 /* If call succeed */
2241 /* Write the IOSB back */
2244 *IoStatusBlock
= KernelIosb
;
2246 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2248 KernelIosb
.Status
= _SEH2_GetExceptionCode();
2252 /* Free the event if we had one */
2255 ExFreePoolWithTag(Event
, TAG_IO
);
2258 /* If FO was locked, unlock it */
2259 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2261 IopUnlockFileObject(FileObject
);
2264 /* We're done with FastIO! */
2265 ObDereferenceObject(FileObject
);
2266 return KernelIosb
.Status
;
2270 /* Clear the File Object event */
2271 KeClearEvent(&FileObject
->Event
);
2273 /* Allocate the IRP */
2274 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2275 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2278 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2279 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2280 Irp
->RequestorMode
= PreviousMode
;
2281 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2282 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2283 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2284 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2285 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2286 Irp
->MdlAddress
= NULL
;
2287 Irp
->UserBuffer
= FileInformation
;
2289 /* Set the Stack Data */
2290 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2291 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2292 StackPtr
->FileObject
= FileObject
;
2297 /* Allocate a buffer */
2298 Irp
->AssociatedIrp
.SystemBuffer
=
2299 ExAllocatePoolWithTag(NonPagedPool
,
2303 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2305 /* Allocating failed, clean up and return the exception code */
2306 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2307 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2312 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2313 IRP_DEALLOCATE_BUFFER
|
2314 IRP_INPUT_OPERATION
|
2315 IRP_DEFER_IO_COMPLETION
);
2317 /* Set the Parameters */
2318 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2319 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2322 IopQueueIrpToThread(Irp
);
2324 /* Update operation counts */
2325 IopUpdateOperationCount(IopOtherTransfer
);
2327 /* Fill in file information before calling the driver.
2328 See 'File System Internals' page 485.*/
2329 if (FileInformationClass
== FileAccessInformation
)
2331 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2332 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2333 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2336 else if (FileInformationClass
== FileModeInformation
)
2338 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2339 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2340 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2343 else if (FileInformationClass
== FileAlignmentInformation
)
2345 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2346 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2347 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2350 else if (FileInformationClass
== FileAllInformation
)
2352 AllBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2353 AllBuffer
->AccessInformation
.AccessFlags
= HandleInformation
.GrantedAccess
;
2354 AllBuffer
->ModeInformation
.Mode
= IopGetFileMode(FileObject
);
2355 AllBuffer
->AlignmentInformation
.AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2356 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
) +
2357 sizeof(FILE_MODE_INFORMATION
) +
2358 sizeof(FILE_ALIGNMENT_INFORMATION
);
2361 /* Call the Driver */
2364 Status
= IoCallDriver(DeviceObject
, Irp
);
2368 Status
= STATUS_SUCCESS
;
2369 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2372 if (Status
== STATUS_PENDING
)
2374 /* Check if this was async I/O */
2377 /* Then to a non-alertable wait */
2378 Status
= KeWaitForSingleObject(Event
,
2383 if (Status
== STATUS_USER_APC
)
2385 /* Abort the request */
2386 IopAbortInterruptedIrp(Event
, Irp
);
2389 /* Set the final status */
2390 Status
= KernelIosb
.Status
;
2392 /* Enter SEH to write the IOSB back */
2395 /* Write it back to the caller */
2396 *IoStatusBlock
= KernelIosb
;
2398 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2400 /* Get the exception code */
2401 Status
= _SEH2_GetExceptionCode();
2405 /* Free the event */
2406 ExFreePoolWithTag(Event
, TAG_IO
);
2410 /* Wait for the IRP */
2411 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2414 (FileObject
->Flags
&
2415 FO_ALERTABLE_IO
) != 0,
2417 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2419 /* Abort the request */
2420 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2423 /* Set the final status */
2424 Status
= FileObject
->FinalStatus
;
2426 /* Release the file lock */
2427 IopUnlockFileObject(FileObject
);
2432 /* Free the event if we had one */
2435 /* Clear it in the IRP for completion */
2436 Irp
->UserEvent
= NULL
;
2437 ExFreePoolWithTag(Event
, TAG_IO
);
2440 /* Set the caller IOSB */
2441 Irp
->UserIosb
= IoStatusBlock
;
2443 /* The IRP wasn't completed, complete it ourselves */
2444 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2445 IopCompleteRequest(&Irp
->Tail
.Apc
,
2448 (PVOID
*)&FileObject
,
2450 KeLowerIrql(OldIrql
);
2452 /* Release the file object if we had locked it*/
2453 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2456 /* Return the Status */
2465 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2466 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2469 IN BOOLEAN ReturnSingleEntry
,
2470 IN PVOID SidList OPTIONAL
,
2471 IN ULONG SidListLength
,
2472 IN PSID StartSid OPTIONAL
,
2473 IN BOOLEAN RestartScan
)
2476 return STATUS_NOT_IMPLEMENTED
;
2484 NtReadFile(IN HANDLE FileHandle
,
2485 IN HANDLE Event OPTIONAL
,
2486 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2487 IN PVOID ApcContext OPTIONAL
,
2488 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2491 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2492 IN PULONG Key OPTIONAL
)
2495 PFILE_OBJECT FileObject
;
2497 PDEVICE_OBJECT DeviceObject
;
2498 PIO_STACK_LOCATION StackPtr
;
2499 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2500 PKEVENT EventObject
= NULL
;
2501 LARGE_INTEGER CapturedByteOffset
;
2502 ULONG CapturedKey
= 0;
2503 BOOLEAN Synchronous
= FALSE
;
2505 PFAST_IO_DISPATCH FastIoDispatch
;
2506 IO_STATUS_BLOCK KernelIosb
;
2510 CapturedByteOffset
.QuadPart
= 0;
2511 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2513 /* Validate User-Mode Buffers */
2514 if (PreviousMode
!= KernelMode
)
2518 /* Probe the status block */
2519 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2521 /* Probe the read buffer */
2522 ProbeForWrite(Buffer
, Length
, 1);
2524 /* Check if we got a byte offset */
2527 /* Capture and probe it */
2528 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2531 /* Capture and probe the key */
2532 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2534 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2536 /* Return the exception code */
2537 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2543 /* Kernel mode: capture directly */
2544 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2545 if (Key
) CapturedKey
= *Key
;
2548 /* Get File Object */
2549 Status
= ObReferenceObjectByHandle(FileHandle
,
2553 (PVOID
*)&FileObject
,
2555 if (!NT_SUCCESS(Status
)) return Status
;
2557 /* Check for event */
2561 Status
= ObReferenceObjectByHandle(Event
,
2565 (PVOID
*)&EventObject
,
2567 if (!NT_SUCCESS(Status
))
2570 ObDereferenceObject(FileObject
);
2574 /* Otherwise reset the event */
2575 KeClearEvent(EventObject
);
2578 /* Get the device object */
2579 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2581 /* Check if we should use Sync IO or not */
2582 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2584 /* Lock the file object */
2585 IopLockFileObject(FileObject
);
2587 /* Check if we don't have a byte offset available */
2588 if (!(ByteOffset
) ||
2589 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2590 (CapturedByteOffset
.u
.HighPart
== -1)))
2592 /* Use the Current Byte Offset instead */
2593 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2596 /* If the file is cached, try fast I/O */
2597 if (FileObject
->PrivateCacheMap
)
2599 /* Perform fast read */
2600 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2601 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoRead
!= NULL
);
2603 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2604 &CapturedByteOffset
,
2612 /* Only accept the result if we got a straightforward status */
2614 (KernelIosb
.Status
== STATUS_SUCCESS
||
2615 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2616 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2618 /* Fast path -- update transfer & operation counts */
2619 IopUpdateOperationCount(IopReadTransfer
);
2620 IopUpdateTransferCount(IopReadTransfer
,
2621 (ULONG
)KernelIosb
.Information
);
2623 /* Enter SEH to write the IOSB back */
2626 /* Write it back to the caller */
2627 *IoStatusBlock
= KernelIosb
;
2629 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2631 /* The caller's IOSB was invalid, so fail */
2632 if (EventObject
) ObDereferenceObject(EventObject
);
2633 IopUnlockFileObject(FileObject
);
2634 ObDereferenceObject(FileObject
);
2635 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2639 /* Signal the completion event */
2642 KeSetEvent(EventObject
, 0, FALSE
);
2643 ObDereferenceObject(EventObject
);
2647 IopUnlockFileObject(FileObject
);
2648 ObDereferenceObject(FileObject
);
2649 return KernelIosb
.Status
;
2653 /* Remember we are sync */
2656 else if (!(ByteOffset
) &&
2657 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2659 /* Otherwise, this was async I/O without a byte offset, so fail */
2660 if (EventObject
) ObDereferenceObject(EventObject
);
2661 ObDereferenceObject(FileObject
);
2662 return STATUS_INVALID_PARAMETER
;
2665 /* Clear the File Object's event */
2666 KeClearEvent(&FileObject
->Event
);
2668 /* Allocate the IRP */
2669 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2670 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2673 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2674 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2675 Irp
->RequestorMode
= PreviousMode
;
2676 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2677 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2678 Irp
->UserIosb
= IoStatusBlock
;
2679 Irp
->UserEvent
= EventObject
;
2680 Irp
->PendingReturned
= FALSE
;
2681 Irp
->Cancel
= FALSE
;
2682 Irp
->CancelRoutine
= NULL
;
2683 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2684 Irp
->MdlAddress
= NULL
;
2686 /* Set the Stack Data */
2687 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2688 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2689 StackPtr
->FileObject
= FileObject
;
2690 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2691 StackPtr
->Parameters
.Read
.Length
= Length
;
2692 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2694 /* Check if this is buffered I/O */
2695 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2697 /* Check if we have a buffer length */
2703 /* Allocate a buffer */
2704 Irp
->AssociatedIrp
.SystemBuffer
=
2705 ExAllocatePoolWithTag(NonPagedPool
,
2709 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2711 /* Allocating failed, clean up and return the exception code */
2712 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2713 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2717 /* Set the buffer and flags */
2718 Irp
->UserBuffer
= Buffer
;
2719 Irp
->Flags
= (IRP_BUFFERED_IO
|
2720 IRP_DEALLOCATE_BUFFER
|
2721 IRP_INPUT_OPERATION
);
2725 /* Not reading anything */
2726 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2729 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2731 /* Check if we have a buffer length */
2736 /* Allocate an MDL */
2737 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2739 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2740 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2742 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2744 /* Allocating failed, clean up and return the exception code */
2745 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2746 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2752 /* No allocation flags */
2757 /* No allocation flags, and use the buffer directly */
2759 Irp
->UserBuffer
= Buffer
;
2762 /* Now set the deferred read flags */
2763 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2765 /* FIXME: VFAT SUCKS */
2766 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2769 /* Perform the call */
2770 return IopPerformSynchronousRequest(DeviceObject
,
2784 NtReadFileScatter(IN HANDLE FileHandle
,
2785 IN HANDLE Event OPTIONAL
,
2786 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2787 IN PVOID UserApcContext OPTIONAL
,
2788 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2789 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2790 IN ULONG BufferLength
,
2791 IN PLARGE_INTEGER ByteOffset
,
2792 IN PULONG Key OPTIONAL
)
2795 return STATUS_NOT_IMPLEMENTED
;
2803 NtSetEaFile(IN HANDLE FileHandle
,
2804 IN PIO_STATUS_BLOCK IoStatusBlock
,
2806 IN ULONG EaBufferSize
)
2809 return STATUS_NOT_IMPLEMENTED
;
2817 NtSetInformationFile(IN HANDLE FileHandle
,
2818 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2819 IN PVOID FileInformation
,
2821 IN FILE_INFORMATION_CLASS FileInformationClass
)
2823 PFILE_OBJECT FileObject
;
2826 PDEVICE_OBJECT DeviceObject
;
2827 PIO_STACK_LOCATION StackPtr
;
2828 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2829 PKEVENT Event
= NULL
;
2830 BOOLEAN LocalEvent
= FALSE
;
2831 PKNORMAL_ROUTINE NormalRoutine
;
2832 PVOID NormalContext
;
2834 IO_STATUS_BLOCK KernelIosb
;
2836 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2837 PIO_COMPLETION_CONTEXT Context
;
2838 PFILE_RENAME_INFORMATION RenameInfo
;
2839 HANDLE TargetHandle
= NULL
;
2841 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2843 /* Check if we're called from user mode */
2844 if (PreviousMode
!= KernelMode
)
2846 /* Validate the information class */
2847 if ((FileInformationClass
>= FileMaximumInformation
) ||
2848 !(IopSetOperationLength
[FileInformationClass
]))
2851 return STATUS_INVALID_INFO_CLASS
;
2854 /* Validate the length */
2855 if (Length
< IopSetOperationLength
[FileInformationClass
])
2857 /* Invalid length */
2858 return STATUS_INFO_LENGTH_MISMATCH
;
2861 /* Enter SEH for probing */
2864 /* Probe the I/O Status block */
2865 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2867 /* Probe the information */
2868 ProbeForRead(FileInformation
,
2870 (Length
== sizeof(BOOLEAN
)) ?
2871 sizeof(BOOLEAN
) : sizeof(ULONG
));
2873 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2875 /* Return the exception code */
2876 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2882 /* Validate the information class */
2883 if ((FileInformationClass
>= FileMaximumInformation
) ||
2884 !(IopSetOperationLength
[FileInformationClass
]))
2887 return STATUS_INVALID_INFO_CLASS
;
2890 /* Validate the length */
2891 if (Length
< IopSetOperationLength
[FileInformationClass
])
2893 /* Invalid length */
2894 return STATUS_INFO_LENGTH_MISMATCH
;
2898 /* Reference the Handle */
2899 Status
= ObReferenceObjectByHandle(FileHandle
,
2900 IopSetOperationAccess
2901 [FileInformationClass
],
2904 (PVOID
*)&FileObject
,
2906 if (!NT_SUCCESS(Status
)) return Status
;
2908 /* Check if this is a direct open or not */
2909 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2911 /* Get the device object */
2912 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2916 /* Get the device object */
2917 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2920 DPRINT("Will call: %p\n", DeviceObject
);
2921 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject
->DriverObject
, &DeviceObject
->DriverObject
->DriverName
);
2923 /* Check if this is a file that was opened for Synch I/O */
2924 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2927 IopLockFileObject(FileObject
);
2929 /* Check if the caller just wants the position */
2930 if (FileInformationClass
== FilePositionInformation
)
2932 /* Protect write in SEH */
2935 /* Write the offset */
2936 FileObject
->CurrentByteOffset
=
2937 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2940 /* Fill out the I/O Status Block */
2941 IoStatusBlock
->Information
= 0;
2942 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2944 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2946 /* Get the exception code */
2947 Status
= _SEH2_GetExceptionCode();
2951 /* Update transfer count */
2952 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2954 /* Release the file lock, dereference the file and return */
2955 IopUnlockFileObject(FileObject
);
2956 ObDereferenceObject(FileObject
);
2962 /* Use local event */
2963 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2966 ObDereferenceObject(FileObject
);
2967 return STATUS_INSUFFICIENT_RESOURCES
;
2970 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2974 /* Clear the File Object event */
2975 KeClearEvent(&FileObject
->Event
);
2977 /* Allocate the IRP */
2978 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2979 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2982 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2983 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2984 Irp
->RequestorMode
= PreviousMode
;
2985 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2986 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2987 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2988 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2989 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2990 Irp
->MdlAddress
= NULL
;
2991 Irp
->UserBuffer
= FileInformation
;
2993 /* Set the Stack Data */
2994 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2995 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2996 StackPtr
->FileObject
= FileObject
;
3001 /* Allocate a buffer */
3002 Irp
->AssociatedIrp
.SystemBuffer
=
3003 ExAllocatePoolWithTag(NonPagedPool
,
3007 /* Copy the data into it */
3008 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
3012 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3014 /* Allocating failed, clean up and return the exception code */
3015 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3016 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3021 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3022 IRP_DEALLOCATE_BUFFER
|
3023 IRP_DEFER_IO_COMPLETION
);
3025 /* Set the Parameters */
3026 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
3027 StackPtr
->Parameters
.SetFile
.Length
= Length
;
3030 IopQueueIrpToThread(Irp
);
3032 /* Update operation counts */
3033 IopUpdateOperationCount(IopOtherTransfer
);
3035 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3036 /* Handle IO Completion Port quickly */
3037 if (FileInformationClass
== FileCompletionInformation
)
3039 /* Check if the file object already has a completion port */
3040 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
3041 (FileObject
->CompletionContext
))
3044 Status
= STATUS_INVALID_PARAMETER
;
3048 /* Reference the Port */
3049 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3050 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
3051 IO_COMPLETION_MODIFY_STATE
,
3056 if (NT_SUCCESS(Status
))
3058 /* Allocate the Context */
3059 Context
= ExAllocatePoolWithTag(PagedPool
,
3060 sizeof(IO_COMPLETION_CONTEXT
),
3065 Context
->Key
= CompletionInfo
->Key
;
3066 Context
->Port
= Queue
;
3067 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
3073 * Someone else set the completion port in the
3074 * meanwhile, so dereference the port and fail.
3076 ExFreePoolWithTag(Context
, IOC_TAG
);
3077 ObDereferenceObject(Queue
);
3078 Status
= STATUS_INVALID_PARAMETER
;
3083 /* Dereference the Port now */
3084 ObDereferenceObject(Queue
);
3085 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3090 /* Set the IRP Status */
3091 Irp
->IoStatus
.Status
= Status
;
3092 Irp
->IoStatus
.Information
= 0;
3094 else if (FileInformationClass
== FileRenameInformation
||
3095 FileInformationClass
== FileLinkInformation
||
3096 FileInformationClass
== FileMoveClusterInformation
)
3098 /* Get associated information */
3099 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
3104 * -> sizes are valid
3106 if (RenameInfo
->FileNameLength
!= 0 &&
3107 !(RenameInfo
->FileNameLength
& 1) &&
3108 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
3110 /* Properly set information received */
3111 if (FileInformationClass
== FileMoveClusterInformation
)
3113 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
3117 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
3120 /* If we got fully path OR relative target, attempt a parent directory open */
3121 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
3123 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
3124 if (!NT_SUCCESS(Status
))
3126 Irp
->IoStatus
.Status
= Status
;
3130 /* Call the Driver */
3131 Status
= IoCallDriver(DeviceObject
, Irp
);
3136 /* Call the Driver */
3137 Status
= IoCallDriver(DeviceObject
, Irp
);
3142 Status
= STATUS_INVALID_PARAMETER
;
3143 Irp
->IoStatus
.Status
= Status
;
3148 /* Call the Driver */
3149 Status
= IoCallDriver(DeviceObject
, Irp
);
3152 /* Check if we're waiting for the IRP to complete */
3153 if (Status
== STATUS_PENDING
)
3155 /* Check if this was async I/O */
3158 /* Then to a non-alertable wait */
3159 Status
= KeWaitForSingleObject(Event
,
3164 if (Status
== STATUS_USER_APC
)
3166 /* Abort the request */
3167 IopAbortInterruptedIrp(Event
, Irp
);
3170 /* Set the final status */
3171 Status
= KernelIosb
.Status
;
3173 /* Enter SEH to write the IOSB back */
3176 /* Write it back to the caller */
3177 *IoStatusBlock
= KernelIosb
;
3179 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3181 /* Get the exception code */
3182 Status
= _SEH2_GetExceptionCode();
3186 /* Free the event */
3187 ExFreePoolWithTag(Event
, TAG_IO
);
3191 /* Wait for the IRP */
3192 Status
= KeWaitForSingleObject(&FileObject
->Event
,
3195 (FileObject
->Flags
&
3196 FO_ALERTABLE_IO
) != 0,
3198 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
3200 /* Abort the request */
3201 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
3204 /* Set the final status */
3205 Status
= FileObject
->FinalStatus
;
3207 /* Release the file lock */
3208 IopUnlockFileObject(FileObject
);
3213 /* Free the event if we had one */
3216 /* Clear it in the IRP for completion */
3217 Irp
->UserEvent
= NULL
;
3218 ExFreePoolWithTag(Event
, TAG_IO
);
3221 /* Set the caller IOSB */
3222 Irp
->UserIosb
= IoStatusBlock
;
3224 /* The IRP wasn't completed, complete it ourselves */
3225 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
3226 IopCompleteRequest(&Irp
->Tail
.Apc
,
3229 (PVOID
*)&FileObject
,
3231 KeLowerIrql(OldIrql
);
3233 /* Release the file object if we had locked it*/
3234 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
3237 if (TargetHandle
!= NULL
)
3239 ObCloseHandle(TargetHandle
, KernelMode
);
3242 /* Return the Status */
3251 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3252 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3254 IN ULONG BufferLength
)
3257 return STATUS_NOT_IMPLEMENTED
;
3265 NtUnlockFile(IN HANDLE FileHandle
,
3266 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3267 IN PLARGE_INTEGER ByteOffset
,
3268 IN PLARGE_INTEGER Length
,
3269 IN ULONG Key OPTIONAL
)
3271 PFILE_OBJECT FileObject
;
3272 PLARGE_INTEGER LocalLength
= NULL
;
3274 PIO_STACK_LOCATION StackPtr
;
3275 PDEVICE_OBJECT DeviceObject
;
3276 PKEVENT Event
= NULL
;
3277 BOOLEAN LocalEvent
= FALSE
;
3278 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3279 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3281 OBJECT_HANDLE_INFORMATION HandleInformation
;
3282 IO_STATUS_BLOCK KernelIosb
;
3283 PFAST_IO_DISPATCH FastIoDispatch
;
3285 CapturedByteOffset
.QuadPart
= 0;
3286 CapturedLength
.QuadPart
= 0;
3287 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3289 /* Get File Object */
3290 Status
= ObReferenceObjectByHandle(FileHandle
,
3294 (PVOID
*)&FileObject
,
3295 &HandleInformation
);
3296 if (!NT_SUCCESS(Status
)) return Status
;
3298 /* Check if we're called from user mode */
3299 if (PreviousMode
!= KernelMode
)
3301 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3302 if (!(HandleInformation
.GrantedAccess
&
3303 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3305 ObDereferenceObject(FileObject
);
3306 return STATUS_ACCESS_DENIED
;
3309 /* Enter SEH for probing */
3312 /* Probe the I/O Status block */
3313 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3315 /* Probe and capture the large integers */
3316 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3317 CapturedLength
= ProbeForReadLargeInteger(Length
);
3319 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3321 /* Dereference the object and return exception code */
3322 ObDereferenceObject(FileObject
);
3323 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3329 /* Otherwise, capture them directly */
3330 CapturedByteOffset
= *ByteOffset
;
3331 CapturedLength
= *Length
;
3334 /* Check if this is a direct open or not */
3335 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3337 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3341 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3344 /* Try to do it the FastIO way if possible */
3345 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3346 if (FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoUnlockSingle
!= NULL
)
3348 if (FastIoDispatch
->FastIoUnlockSingle(FileObject
,
3349 &CapturedByteOffset
,
3351 PsGetCurrentProcess(),
3356 /* Write the IOSB back */
3359 *IoStatusBlock
= KernelIosb
;
3361 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3363 KernelIosb
.Status
= _SEH2_GetExceptionCode();
3367 /* We're done with FastIO! */
3368 ObDereferenceObject(FileObject
);
3369 return KernelIosb
.Status
;
3373 /* Check if we should use Sync IO or not */
3374 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3377 IopLockFileObject(FileObject
);
3381 /* Use local event */
3382 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3385 ObDereferenceObject(FileObject
);
3386 return STATUS_INSUFFICIENT_RESOURCES
;
3388 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3392 /* Clear File Object event */
3393 KeClearEvent(&FileObject
->Event
);
3395 /* Allocate the IRP */
3396 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3397 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3399 /* Set up the IRP */
3400 Irp
->RequestorMode
= PreviousMode
;
3401 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3402 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3403 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3404 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3405 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3406 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3408 /* Set up Stack Data */
3409 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3410 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3411 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3412 StackPtr
->FileObject
= FileObject
;
3417 /* Allocate a buffer */
3418 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3419 sizeof(LARGE_INTEGER
),
3422 /* Set the length */
3423 *LocalLength
= CapturedLength
;
3424 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3425 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3427 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3429 /* Allocating failed, clean up and return the exception code */
3430 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3431 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3433 /* Return the exception code */
3434 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3438 /* Set Parameters */
3439 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3440 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3442 /* Call the Driver */
3443 Status
= IopPerformSynchronousRequest(DeviceObject
,
3451 /* Check if this was async I/O */
3454 /* It was, finalize this request */
3455 Status
= IopFinalizeAsynchronousIo(Status
,
3472 NtWriteFile(IN HANDLE FileHandle
,
3473 IN HANDLE Event OPTIONAL
,
3474 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3475 IN PVOID ApcContext OPTIONAL
,
3476 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3479 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3480 IN PULONG Key OPTIONAL
)
3483 PFILE_OBJECT FileObject
;
3485 PDEVICE_OBJECT DeviceObject
;
3486 PIO_STACK_LOCATION StackPtr
;
3487 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3488 PKEVENT EventObject
= NULL
;
3489 LARGE_INTEGER CapturedByteOffset
;
3490 ULONG CapturedKey
= 0;
3491 BOOLEAN Synchronous
= FALSE
;
3493 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3494 PFAST_IO_DISPATCH FastIoDispatch
;
3495 IO_STATUS_BLOCK KernelIosb
;
3499 CapturedByteOffset
.QuadPart
= 0;
3500 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3502 /* Get File Object for write */
3503 Status
= ObReferenceFileObjectForWrite(FileHandle
,
3507 if (!NT_SUCCESS(Status
)) return Status
;
3509 /* Validate User-Mode Buffers */
3510 if (PreviousMode
!= KernelMode
)
3514 /* Probe the status block */
3515 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3517 /* Probe the read buffer */
3518 ProbeForRead(Buffer
, Length
, 1);
3520 /* Check if we got a byte offset */
3523 /* Capture and probe it */
3524 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3527 /* Capture and probe the key */
3528 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3530 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3532 /* Release the file object and return the exception code */
3533 ObDereferenceObject(FileObject
);
3534 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3540 /* Kernel mode: capture directly */
3541 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3542 if (Key
) CapturedKey
= *Key
;
3545 /* Check if this is an append operation */
3546 if ((ObjectHandleInfo
.GrantedAccess
&
3547 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3549 /* Give the drivers something to understand */
3550 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3551 CapturedByteOffset
.u
.HighPart
= -1;
3554 /* Check for event */
3558 Status
= ObReferenceObjectByHandle(Event
,
3562 (PVOID
*)&EventObject
,
3564 if (!NT_SUCCESS(Status
))
3567 ObDereferenceObject(FileObject
);
3571 /* Otherwise reset the event */
3572 KeClearEvent(EventObject
);
3575 /* Get the device object */
3576 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3578 /* Check if we should use Sync IO or not */
3579 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3581 /* Lock the file object */
3582 IopLockFileObject(FileObject
);
3584 /* Check if we don't have a byte offset available */
3585 if (!(ByteOffset
) ||
3586 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3587 (CapturedByteOffset
.u
.HighPart
== -1)))
3589 /* Use the Current Byte Offset instead */
3590 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3593 /* If the file is cached, try fast I/O */
3594 if (FileObject
->PrivateCacheMap
)
3596 /* Perform fast write */
3597 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3598 ASSERT(FastIoDispatch
!= NULL
&& FastIoDispatch
->FastIoWrite
!= NULL
);
3600 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3601 &CapturedByteOffset
,
3609 /* Only accept the result if it was successful */
3611 KernelIosb
.Status
== STATUS_SUCCESS
)
3613 /* Fast path -- update transfer & operation counts */
3614 IopUpdateOperationCount(IopWriteTransfer
);
3615 IopUpdateTransferCount(IopWriteTransfer
,
3616 (ULONG
)KernelIosb
.Information
);
3618 /* Enter SEH to write the IOSB back */
3621 /* Write it back to the caller */
3622 *IoStatusBlock
= KernelIosb
;
3624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3626 /* The caller's IOSB was invalid, so fail */
3627 if (EventObject
) ObDereferenceObject(EventObject
);
3628 IopUnlockFileObject(FileObject
);
3629 ObDereferenceObject(FileObject
);
3630 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3634 /* Signal the completion event */
3637 KeSetEvent(EventObject
, 0, FALSE
);
3638 ObDereferenceObject(EventObject
);
3642 IopUnlockFileObject(FileObject
);
3643 ObDereferenceObject(FileObject
);
3644 return KernelIosb
.Status
;
3648 /* Remember we are sync */
3651 else if (!(ByteOffset
) &&
3652 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3654 /* Otherwise, this was async I/O without a byte offset, so fail */
3655 if (EventObject
) ObDereferenceObject(EventObject
);
3656 ObDereferenceObject(FileObject
);
3657 return STATUS_INVALID_PARAMETER
;
3660 /* Clear the File Object's event */
3661 KeClearEvent(&FileObject
->Event
);
3663 /* Allocate the IRP */
3664 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3665 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3668 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3669 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3670 Irp
->RequestorMode
= PreviousMode
;
3671 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3672 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3673 Irp
->UserIosb
= IoStatusBlock
;
3674 Irp
->UserEvent
= EventObject
;
3675 Irp
->PendingReturned
= FALSE
;
3676 Irp
->Cancel
= FALSE
;
3677 Irp
->CancelRoutine
= NULL
;
3678 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3679 Irp
->MdlAddress
= NULL
;
3681 /* Set the Stack Data */
3682 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3683 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3684 StackPtr
->FileObject
= FileObject
;
3685 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3686 SL_WRITE_THROUGH
: 0;
3687 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3688 StackPtr
->Parameters
.Write
.Length
= Length
;
3689 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3691 /* Check if this is buffered I/O */
3692 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3694 /* Check if we have a buffer length */
3700 /* Allocate a buffer */
3701 Irp
->AssociatedIrp
.SystemBuffer
=
3702 ExAllocatePoolWithTag(NonPagedPool
,
3706 /* Copy the data into it */
3707 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3709 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3711 /* Allocating failed, clean up and return the exception code */
3712 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3713 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3718 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3722 /* Not writing anything */
3723 Irp
->Flags
= IRP_BUFFERED_IO
;
3726 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3728 /* Check if we have a buffer length */
3733 /* Allocate an MDL */
3734 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3736 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3737 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3739 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3741 /* Allocating failed, clean up and return the exception code */
3742 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3743 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3748 /* No allocation flags */
3753 /* No allocation flags, and use the buffer directly */
3755 Irp
->UserBuffer
= Buffer
;
3758 /* Now set the deferred read flags */
3759 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3761 /* FIXME: VFAT SUCKS */
3762 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3765 /* Perform the call */
3766 return IopPerformSynchronousRequest(DeviceObject
,
3777 NtWriteFileGather(IN HANDLE FileHandle
,
3778 IN HANDLE Event OPTIONAL
,
3779 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3780 IN PVOID UserApcContext OPTIONAL
,
3781 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3782 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3783 IN ULONG BufferLength
,
3784 IN PLARGE_INTEGER ByteOffset
,
3785 IN PULONG Key OPTIONAL
)
3788 return STATUS_NOT_IMPLEMENTED
;
3796 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3797 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3798 OUT PVOID FsInformation
,
3800 IN FS_INFORMATION_CLASS FsInformationClass
)
3802 PFILE_OBJECT FileObject
;
3804 PIO_STACK_LOCATION StackPtr
;
3805 PDEVICE_OBJECT DeviceObject
;
3806 PKEVENT Event
= NULL
;
3807 BOOLEAN LocalEvent
= FALSE
;
3808 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3810 IO_STATUS_BLOCK KernelIosb
;
3812 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3814 /* Check if we're called from user mode */
3815 if (PreviousMode
!= KernelMode
)
3817 /* Validate the information class */
3818 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3819 !(IopQueryFsOperationLength
[FsInformationClass
]))
3822 return STATUS_INVALID_INFO_CLASS
;
3825 /* Validate the length */
3826 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3828 /* Invalid length */
3829 return STATUS_INFO_LENGTH_MISMATCH
;
3832 /* Enter SEH for probing */
3835 /* Probe the I/O Status block */
3836 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3838 /* Probe the information */
3839 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3841 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3843 /* Return the exception code */
3844 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3849 /* Get File Object */
3850 Status
= ObReferenceObjectByHandle(FileHandle
,
3851 IopQueryFsOperationAccess
3852 [FsInformationClass
],
3855 (PVOID
*)&FileObject
,
3857 if (!NT_SUCCESS(Status
)) return Status
;
3859 /* Check if we should use Sync IO or not */
3860 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3863 IopLockFileObject(FileObject
);
3867 /* Use local event */
3868 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3871 ObDereferenceObject(FileObject
);
3872 return STATUS_INSUFFICIENT_RESOURCES
;
3874 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3878 /* Get the device object */
3879 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3881 /* Clear File Object event */
3882 KeClearEvent(&FileObject
->Event
);
3884 /* Allocate the IRP */
3885 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3886 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3888 /* Set up the IRP */
3889 Irp
->RequestorMode
= PreviousMode
;
3890 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3891 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3892 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3893 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3894 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3895 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3896 Irp
->UserBuffer
= FsInformation
;
3897 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3898 Irp
->MdlAddress
= NULL
;
3900 /* Set up Stack Data */
3901 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3902 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3903 StackPtr
->FileObject
= FileObject
;
3908 /* Allocate a buffer */
3909 Irp
->AssociatedIrp
.SystemBuffer
=
3910 ExAllocatePoolWithTag(NonPagedPool
,
3914 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3916 /* Allocating failed, clean up and return the exception code */
3917 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3918 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3922 /* Set the flags for this buffered + deferred I/O */
3923 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3924 IRP_DEALLOCATE_BUFFER
|
3925 IRP_INPUT_OPERATION
|
3926 IRP_DEFER_IO_COMPLETION
);
3928 /* Set Parameters */
3929 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3930 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3932 /* Call the Driver */
3933 Status
= IopPerformSynchronousRequest(DeviceObject
,
3941 /* Check if this was async I/O */
3944 /* It was, finalize this request */
3945 Status
= IopFinalizeAsynchronousIo(Status
,
3962 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3963 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3964 IN PVOID FsInformation
,
3966 IN FS_INFORMATION_CLASS FsInformationClass
)
3968 PFILE_OBJECT FileObject
;
3970 PIO_STACK_LOCATION StackPtr
;
3971 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3972 PKEVENT Event
= NULL
;
3973 BOOLEAN LocalEvent
= FALSE
;
3974 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3976 IO_STATUS_BLOCK KernelIosb
;
3977 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3979 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3981 /* Check if we're called from user mode */
3982 if (PreviousMode
!= KernelMode
)
3984 /* Validate the information class */
3985 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3986 !(IopSetFsOperationLength
[FsInformationClass
]))
3989 return STATUS_INVALID_INFO_CLASS
;
3992 /* Validate the length */
3993 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3995 /* Invalid length */
3996 return STATUS_INFO_LENGTH_MISMATCH
;
3999 /* Enter SEH for probing */
4002 /* Probe the I/O Status block */
4003 ProbeForWriteIoStatusBlock(IoStatusBlock
);
4005 /* Probe the information */
4006 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
4008 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4010 /* Return the exception code */
4011 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4016 /* Get File Object */
4017 Status
= ObReferenceObjectByHandle(FileHandle
,
4018 IopSetFsOperationAccess
4019 [FsInformationClass
],
4022 (PVOID
*)&FileObject
,
4024 if (!NT_SUCCESS(Status
)) return Status
;
4026 /* Get target device for notification */
4027 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
4028 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
4030 /* Check if we should use Sync IO or not */
4031 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
4034 IopLockFileObject(FileObject
);
4038 /* Use local event */
4039 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
4042 ObDereferenceObject(FileObject
);
4043 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4044 return STATUS_INSUFFICIENT_RESOURCES
;
4046 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
4050 /* Get the device object */
4051 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
4053 /* Clear File Object event */
4054 KeClearEvent(&FileObject
->Event
);
4056 /* Allocate the IRP */
4057 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
4060 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4061 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
4064 /* Set up the IRP */
4065 Irp
->RequestorMode
= PreviousMode
;
4066 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
4067 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
4068 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
4069 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4070 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
4071 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
4072 Irp
->UserBuffer
= FsInformation
;
4073 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
4074 Irp
->MdlAddress
= NULL
;
4076 /* Set up Stack Data */
4077 StackPtr
= IoGetNextIrpStackLocation(Irp
);
4078 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
4079 StackPtr
->FileObject
= FileObject
;
4084 /* Allocate a buffer */
4085 Irp
->AssociatedIrp
.SystemBuffer
=
4086 ExAllocatePoolWithTag(NonPagedPool
,
4090 /* Copy the data into it */
4091 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
4093 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4095 /* Allocating failed, clean up and return the exception code */
4096 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
4097 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
4098 _SEH2_YIELD(return _SEH2_GetExceptionCode());
4102 /* Set the flags for this buffered + deferred I/O */
4103 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
4105 /* Set Parameters */
4106 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
4107 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
4109 /* Call the Driver */
4110 Status
= IopPerformSynchronousRequest(DeviceObject
,
4118 /* Check if this was async I/O */
4121 /* It was, finalize this request */
4122 Status
= IopFinalizeAsynchronousIo(Status
,
4130 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
4132 /* Time to report change */
4133 NotificationStructure
.Version
= 1;
4134 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
4135 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
4136 NotificationStructure
.FileObject
= NULL
;
4137 NotificationStructure
.NameBufferOffset
= - 1;
4138 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
4150 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
4153 return STATUS_NOT_IMPLEMENTED
;
4161 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
4164 return STATUS_NOT_IMPLEMENTED
;