2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/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)
11 /* INCLUDES *****************************************************************/
16 #include "internal/io_i.h"
18 /* PRIVATE FUNCTIONS *********************************************************/
22 IopCleanupAfterException(IN PFILE_OBJECT FileObject
,
24 IN PKEVENT Event OPTIONAL
,
25 IN PKEVENT LocalEvent OPTIONAL
)
28 IOTRACE(IO_API_DEBUG
, "IRP: %p. FO: %p \n", Irp
, FileObject
);
30 /* Check if we had a buffer */
31 if (Irp
->AssociatedIrp
.SystemBuffer
)
34 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
38 if (Irp
->MdlAddress
) IoFreeMdl(Irp
->MdlAddress
);
43 /* Check if we had a file lock */
44 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
47 IopUnlockFileObject(FileObject
);
50 /* Check if we had an event */
51 if (Event
) ObDereferenceObject(Event
);
53 /* Check if we had a local event */
54 if (LocalEvent
) ExFreePool(LocalEvent
);
56 /* Derefenrce the FO */
57 ObDereferenceObject(FileObject
);
62 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus
,
65 IN KPROCESSOR_MODE PreviousMode
,
66 IN PIO_STATUS_BLOCK KernelIosb
,
67 OUT PIO_STATUS_BLOCK IoStatusBlock
)
69 NTSTATUS FinalStatus
= SynchStatus
;
71 IOTRACE(IO_API_DEBUG
, "IRP: %p. Status: %lx \n", Irp
, SynchStatus
);
73 /* Make sure the IRP was completed, but returned pending */
74 if (FinalStatus
== STATUS_PENDING
)
76 /* Wait for the IRP */
77 FinalStatus
= KeWaitForSingleObject(Event
,
82 if (FinalStatus
== STATUS_USER_APC
)
84 /* Abort the request */
85 IopAbortInterruptedIrp(Event
, Irp
);
88 /* Set the final status */
89 FinalStatus
= KernelIosb
->Status
;
92 /* Wrap potential user-mode write in SEH */
95 *IoStatusBlock
= *KernelIosb
;
97 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
99 /* Get the exception code */
100 FinalStatus
= _SEH2_GetExceptionCode();
104 /* Free the event and return status */
111 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject
,
113 IN PFILE_OBJECT FileObject
,
115 IN KPROCESSOR_MODE PreviousMode
,
117 IN IOP_TRANSFER_TYPE TransferType
)
120 PKNORMAL_ROUTINE NormalRoutine
;
124 IOTRACE(IO_API_DEBUG
, "IRP: %p. DO: %p. FO: %p \n",
125 Irp
, DeviceObject
, FileObject
);
128 IopQueueIrpToThread(Irp
);
130 /* Update operation counts */
131 IopUpdateOperationCount(TransferType
);
133 /* Call the driver */
134 Status
= IoCallDriver(DeviceObject
, Irp
);
136 /* Check if we're optimizing this case */
139 /* We are! Check if the IRP wasn't completed */
140 if (Status
!= STATUS_PENDING
)
142 /* Complete it ourselves */
143 ASSERT(!Irp
->PendingReturned
);
144 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
145 IopCompleteRequest(&Irp
->Tail
.Apc
,
150 KeLowerIrql(OldIrql
);
154 /* Check if this was synch I/O */
157 /* Make sure the IRP was completed, but returned pending */
158 if (Status
== STATUS_PENDING
)
160 /* Wait for the IRP */
161 Status
= KeWaitForSingleObject(&FileObject
->Event
,
167 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
169 /* Abort the request */
170 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
173 /* Set the final status */
174 Status
= FileObject
->FinalStatus
;
177 /* Release the file lock */
178 IopUnlockFileObject(FileObject
);
187 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
188 IN HANDLE Event OPTIONAL
,
189 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
190 IN PVOID UserApcContext OPTIONAL
,
191 OUT PIO_STATUS_BLOCK IoStatusBlock
,
192 IN ULONG IoControlCode
,
193 IN PVOID InputBuffer
,
194 IN ULONG InputBufferLength OPTIONAL
,
195 OUT PVOID OutputBuffer
,
196 IN ULONG OutputBufferLength OPTIONAL
,
197 IN BOOLEAN IsDevIoCtl
)
199 NTSTATUS Status
= STATUS_SUCCESS
;
200 PFILE_OBJECT FileObject
;
201 PDEVICE_OBJECT DeviceObject
;
203 PIO_STACK_LOCATION StackPtr
;
204 PKEVENT EventObject
= NULL
;
205 BOOLEAN LockedForSynch
= FALSE
;
207 OBJECT_HANDLE_INFORMATION HandleInformation
;
208 ACCESS_MASK DesiredAccess
;
209 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
211 IOTRACE(IO_CTL_DEBUG
, "Handle: %lx. CTL: %lx. Type: %lx \n",
212 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
214 /* Get the access type */
215 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
217 /* Check if we came from user mode */
218 if (PreviousMode
!= KernelMode
)
222 /* Probe the status block */
223 ProbeForWriteIoStatusBlock(IoStatusBlock
);
225 /* Check if this is buffered I/O */
226 if (AccessType
== METHOD_BUFFERED
)
228 /* Check if we have an output buffer */
231 /* Probe the output buffer */
232 ProbeForWrite(OutputBuffer
,
238 /* Make sure the caller can't fake this as we depend on this */
239 OutputBufferLength
= 0;
243 /* Check if we we have an input buffer I/O */
244 if (AccessType
!= METHOD_NEITHER
)
246 /* Check if we have an input buffer */
249 /* Probe the input buffer */
250 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
254 /* Make sure the caller can't fake this as we depend on this */
255 InputBufferLength
= 0;
259 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
261 /* Get the exception code */
262 Status
= _SEH2_GetExceptionCode();
265 if (!NT_SUCCESS(Status
)) return Status
;
268 /* Don't check for access rights right now, KernelMode can do anything */
269 Status
= ObReferenceObjectByHandle(DeviceHandle
,
275 if (!NT_SUCCESS(Status
)) return Status
;
277 /* Can't use an I/O completion port and an APC in the same time */
278 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
281 ObDereferenceObject(FileObject
);
282 return STATUS_INVALID_PARAMETER
;
285 /* Check if we from user mode */
286 if (PreviousMode
!= KernelMode
)
288 /* Get the access mask */
289 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
291 /* Check if we can open it */
292 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
293 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
295 /* Dereference the file object and fail */
296 ObDereferenceObject(FileObject
);
297 return STATUS_ACCESS_DENIED
;
301 /* Check for an event */
305 Status
= ObReferenceObjectByHandle(Event
,
309 (PVOID
*)&EventObject
,
311 if (!NT_SUCCESS(Status
))
313 /* Dereference the file object and fail */
314 ObDereferenceObject(FileObject
);
319 KeClearEvent(EventObject
);
322 /* Check if this is a file that was opened for Synch I/O */
323 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
326 IopLockFileObject(FileObject
);
328 /* Remember to unlock later */
329 LockedForSynch
= TRUE
;
332 /* Check if this is a direct open or not */
333 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
335 /* It's a direct open, get the attached device */
336 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
340 /* Otherwise get the related device */
341 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
344 /* Clear the event */
345 KeClearEvent(&FileObject
->Event
);
348 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
349 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
352 Irp
->UserIosb
= IoStatusBlock
;
353 Irp
->UserEvent
= EventObject
;
354 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
355 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
357 Irp
->CancelRoutine
= NULL
;
358 Irp
->PendingReturned
= FALSE
;
359 Irp
->RequestorMode
= PreviousMode
;
360 Irp
->MdlAddress
= NULL
;
361 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
363 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
364 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
365 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
367 /* Set stack location settings */
368 StackPtr
= IoGetNextIrpStackLocation(Irp
);
369 StackPtr
->FileObject
= FileObject
;
370 StackPtr
->MajorFunction
= IsDevIoCtl
?
371 IRP_MJ_DEVICE_CONTROL
:
372 IRP_MJ_FILE_SYSTEM_CONTROL
;
373 StackPtr
->MinorFunction
= 0;
374 StackPtr
->Control
= 0;
376 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
378 /* Set the IOCTL Data */
379 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
380 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
381 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
384 /* Handle the Methods */
388 case METHOD_BUFFERED
:
390 /* Enter SEH for allocations */
393 /* Select the right Buffer Length */
394 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
395 InputBufferLength
: OutputBufferLength
;
397 /* Make sure there is one */
400 /* Allocate the System Buffer */
401 Irp
->AssociatedIrp
.SystemBuffer
=
402 ExAllocatePoolWithTag(NonPagedPool
,
406 /* Check if we got a buffer */
409 /* Copy into the System Buffer */
410 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
415 /* Write the flags */
416 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
417 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
419 /* Save the Buffer */
420 Irp
->UserBuffer
= OutputBuffer
;
424 /* Clear the Flags and Buffer */
425 Irp
->UserBuffer
= NULL
;
428 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
430 /* Cleanup after exception */
431 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
432 Status
= _SEH2_GetExceptionCode();
435 if (!NT_SUCCESS(Status
)) return Status
;
439 case METHOD_IN_DIRECT
:
440 case METHOD_OUT_DIRECT
:
445 /* Check if we got an input buffer */
446 if ((InputBufferLength
) && (InputBuffer
))
448 /* Allocate the System Buffer */
449 Irp
->AssociatedIrp
.SystemBuffer
=
450 ExAllocatePoolWithTag(NonPagedPool
,
454 /* Copy into the System Buffer */
455 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
459 /* Write the flags */
460 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
463 /* Check if we got an output buffer */
466 /* Allocate the System Buffer */
467 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
472 if (!Irp
->MdlAddress
)
474 /* Raise exception we'll catch */
475 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
479 MmProbeAndLockPages(Irp
->MdlAddress
,
481 (AccessType
== METHOD_IN_DIRECT
) ?
482 IoReadAccess
: IoWriteAccess
);
485 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
487 /* Cleanup after exception */
488 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
489 Status
= _SEH2_GetExceptionCode();
492 if (!NT_SUCCESS(Status
)) return Status
;
497 /* Just save the Buffer */
498 Irp
->UserBuffer
= OutputBuffer
;
499 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
502 /* Use deferred completion for FS I/O */
503 Irp
->Flags
|= (!IsDevIoCtl
) ? IRP_DEFER_IO_COMPLETION
: 0;
505 /* Perform the call */
506 return IopPerformSynchronousRequest(DeviceObject
,
517 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
518 IN ULONG InformationClass
,
520 OUT PVOID Information
,
521 OUT PULONG ReturnedLength
,
524 IO_STATUS_BLOCK IoStatusBlock
;
526 PDEVICE_OBJECT DeviceObject
;
527 PIO_STACK_LOCATION StackPtr
;
528 BOOLEAN LocalEvent
= FALSE
;
532 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
533 FileObject
, InformationClass
, File
);
535 /* Reference the object */
536 ObReferenceObject(FileObject
);
538 /* Check if this is a file that was opened for Synch I/O */
539 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
542 IopLockFileObject(FileObject
);
544 /* Use File Object event */
545 KeClearEvent(&FileObject
->Event
);
549 /* Use local event */
550 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
554 /* Get the Device Object */
555 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
557 /* Allocate the IRP */
558 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
559 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
562 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
563 Irp
->RequestorMode
= KernelMode
;
564 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
565 Irp
->UserIosb
= &IoStatusBlock
;
566 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
567 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
568 Irp
->Flags
|= IRP_BUFFERED_IO
;
569 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
570 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
572 /* Set the Stack Data */
573 StackPtr
= IoGetNextIrpStackLocation(Irp
);
574 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
575 IRP_MJ_QUERY_VOLUME_INFORMATION
;
576 StackPtr
->FileObject
= FileObject
;
578 /* Check which type this is */
582 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
583 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
588 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
589 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
593 IopQueueIrpToThread(Irp
);
595 /* Call the Driver */
596 Status
= IoCallDriver(DeviceObject
, Irp
);
598 /* Check if this was synch I/O */
601 /* Check if the requet is pending */
602 if (Status
== STATUS_PENDING
)
604 /* Wait on the file object */
605 Status
= KeWaitForSingleObject(&FileObject
->Event
,
608 FileObject
->Flags
& FO_ALERTABLE_IO
,
610 if (Status
== STATUS_ALERTED
)
612 /* Abort the operation */
613 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
616 /* Get the final status */
617 Status
= FileObject
->FinalStatus
;
620 /* Release the file lock */
621 IopUnlockFileObject(FileObject
);
623 else if (Status
== STATUS_PENDING
)
625 /* Wait on the local event and get the final status */
626 KeWaitForSingleObject(&Event
,
631 Status
= IoStatusBlock
.Status
;
634 /* Return the Length and Status. ReturnedLength is NOT optional */
635 *ReturnedLength
= IoStatusBlock
.Information
;
639 /* PUBLIC FUNCTIONS **********************************************************/
646 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
648 IN PLARGE_INTEGER Offset
,
650 IN PIO_STATUS_BLOCK StatusBlock
)
653 PIO_STACK_LOCATION StackPtr
;
654 PDEVICE_OBJECT DeviceObject
;
655 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
656 FileObject
, Mdl
, Offset
);
658 /* Get the Device Object */
659 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
662 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
663 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
666 StackPtr
= IoGetNextIrpStackLocation(Irp
);
668 /* Create the IRP Settings */
669 Irp
->MdlAddress
= Mdl
;
670 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
671 Irp
->UserIosb
= StatusBlock
;
672 Irp
->UserEvent
= Event
;
673 Irp
->RequestorMode
= KernelMode
;
674 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
675 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
676 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
678 /* Set the Stack Settings */
679 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
680 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
681 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
682 StackPtr
->FileObject
= FileObject
;
684 /* Call the Driver */
685 return IoCallDriver(DeviceObject
, Irp
);
693 IoPageRead(IN PFILE_OBJECT FileObject
,
695 IN PLARGE_INTEGER Offset
,
697 IN PIO_STATUS_BLOCK StatusBlock
)
700 PIO_STACK_LOCATION StackPtr
;
701 PDEVICE_OBJECT DeviceObject
;
702 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
703 FileObject
, Mdl
, Offset
);
705 /* Get the Device Object */
706 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
709 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
710 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
713 StackPtr
= IoGetNextIrpStackLocation(Irp
);
715 /* Create the IRP Settings */
716 Irp
->MdlAddress
= Mdl
;
717 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
718 Irp
->UserIosb
= StatusBlock
;
719 Irp
->UserEvent
= Event
;
720 Irp
->RequestorMode
= KernelMode
;
721 Irp
->Flags
= IRP_PAGING_IO
|
723 IRP_SYNCHRONOUS_PAGING_IO
|
725 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
726 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
728 /* Set the Stack Settings */
729 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
730 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
731 StackPtr
->MajorFunction
= IRP_MJ_READ
;
732 StackPtr
->FileObject
= FileObject
;
734 /* Call the Driver */
735 return IoCallDriver(DeviceObject
, Irp
);
743 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
744 IN FILE_INFORMATION_CLASS FileInformationClass
,
746 OUT PVOID FileInformation
,
747 OUT PULONG ReturnedLength
)
749 /* Call the shared routine */
750 return IopQueryDeviceInformation(FileObject
,
751 FileInformationClass
,
763 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
764 IN FS_INFORMATION_CLASS FsInformationClass
,
766 OUT PVOID FsInformation
,
767 OUT PULONG ReturnedLength
)
769 /* Call the shared routine */
770 return IopQueryDeviceInformation(FileObject
,
783 IoSetInformation(IN PFILE_OBJECT FileObject
,
784 IN FILE_INFORMATION_CLASS FileInformationClass
,
786 IN PVOID FileInformation
)
788 IO_STATUS_BLOCK IoStatusBlock
;
790 PDEVICE_OBJECT DeviceObject
;
791 PIO_STACK_LOCATION StackPtr
;
792 BOOLEAN LocalEvent
= FALSE
;
796 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
797 FileObject
, FileInformationClass
, Length
);
799 /* Reference the object */
800 ObReferenceObject(FileObject
);
802 /* Check if this is a file that was opened for Synch I/O */
803 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
806 IopLockFileObject(FileObject
);
808 /* Use File Object event */
809 KeClearEvent(&FileObject
->Event
);
813 /* Use local event */
814 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
818 /* Get the Device Object */
819 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
821 /* Allocate the IRP */
822 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
823 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
826 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
827 Irp
->RequestorMode
= KernelMode
;
828 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
829 Irp
->UserIosb
= &IoStatusBlock
;
830 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
831 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
832 Irp
->Flags
|= IRP_BUFFERED_IO
;
833 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
834 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
836 /* Set the Stack Data */
837 StackPtr
= IoGetNextIrpStackLocation(Irp
);
838 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
839 StackPtr
->FileObject
= FileObject
;
842 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
843 StackPtr
->Parameters
.SetFile
.Length
= Length
;
846 IopQueueIrpToThread(Irp
);
848 /* Call the Driver */
849 Status
= IoCallDriver(DeviceObject
, Irp
);
851 /* Check if this was synch I/O */
854 /* Check if the requet is pending */
855 if (Status
== STATUS_PENDING
)
857 /* Wait on the file object */
858 Status
= KeWaitForSingleObject(&FileObject
->Event
,
861 FileObject
->Flags
& FO_ALERTABLE_IO
,
863 if (Status
== STATUS_ALERTED
)
865 /* Abort the operation */
866 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
869 /* Get the final status */
870 Status
= FileObject
->FinalStatus
;
873 /* Release the file lock */
874 IopUnlockFileObject(FileObject
);
876 else if (Status
== STATUS_PENDING
)
878 /* Wait on the local event and get the final status */
879 KeWaitForSingleObject(&Event
,
884 Status
= IoStatusBlock
.Status
;
887 /* Return the status */
891 /* NATIVE SERVICES ***********************************************************/
898 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
899 IN HANDLE Event OPTIONAL
,
900 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
901 IN PVOID UserApcContext OPTIONAL
,
902 OUT PIO_STATUS_BLOCK IoStatusBlock
,
903 IN ULONG IoControlCode
,
904 IN PVOID InputBuffer
,
905 IN ULONG InputBufferLength OPTIONAL
,
906 OUT PVOID OutputBuffer
,
907 IN ULONG OutputBufferLength OPTIONAL
)
909 /* Call the Generic Function */
910 return IopDeviceFsIoControl(DeviceHandle
,
928 NtFsControlFile(IN HANDLE DeviceHandle
,
929 IN HANDLE Event OPTIONAL
,
930 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
931 IN PVOID UserApcContext OPTIONAL
,
932 OUT PIO_STATUS_BLOCK IoStatusBlock
,
933 IN ULONG IoControlCode
,
934 IN PVOID InputBuffer
,
935 IN ULONG InputBufferLength OPTIONAL
,
936 OUT PVOID OutputBuffer
,
937 IN ULONG OutputBufferLength OPTIONAL
)
939 /* Call the Generic Function */
940 return IopDeviceFsIoControl(DeviceHandle
,
955 NtFlushBuffersFile(IN HANDLE FileHandle
,
956 OUT PIO_STATUS_BLOCK IoStatusBlock
)
958 PFILE_OBJECT FileObject
;
960 PIO_STACK_LOCATION StackPtr
;
961 NTSTATUS Status
= STATUS_SUCCESS
;
962 PDEVICE_OBJECT DeviceObject
;
963 PKEVENT Event
= NULL
;
964 BOOLEAN LocalEvent
= FALSE
;
965 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
966 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
967 IO_STATUS_BLOCK KernelIosb
;
969 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
971 if (PreviousMode
!= KernelMode
)
976 /* Probe the I/O Status block */
977 ProbeForWriteIoStatusBlock(IoStatusBlock
);
979 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
981 /* Get the exception code */
982 Status
= _SEH2_GetExceptionCode();
986 /* Return exception code, if any */
987 if (!NT_SUCCESS(Status
)) return Status
;
990 /* Get the File Object */
991 Status
= ObReferenceObjectByHandle(FileHandle
,
997 if (!NT_SUCCESS(Status
)) return Status
;
1000 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1001 * granted. However, if this is a named pipe, make sure we don't ask for
1002 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1005 if (!(ObjectHandleInfo
.GrantedAccess
&
1006 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1010 ObDereferenceObject(FileObject
);
1011 return STATUS_ACCESS_DENIED
;
1014 /* Check if we should use Sync IO or not */
1015 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1018 IopLockFileObject(FileObject
);
1022 /* Use local event */
1023 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1024 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1028 /* Get the Device Object */
1029 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1031 /* Clear the event */
1032 KeClearEvent(&FileObject
->Event
);
1034 /* Allocate the IRP */
1035 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1036 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1038 /* Set up the IRP */
1039 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1040 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1041 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1042 Irp
->RequestorMode
= PreviousMode
;
1043 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1044 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1045 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1047 /* Set up Stack Data */
1048 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1049 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1050 StackPtr
->FileObject
= FileObject
;
1052 /* Call the Driver */
1053 Status
= IopPerformSynchronousRequest(DeviceObject
,
1061 /* Check if this was async I/O */
1064 /* It was, finalize this request */
1065 Status
= IopFinalizeAsynchronousIo(Status
,
1073 /* Return the Status */
1082 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1083 IN HANDLE EventHandle OPTIONAL
,
1084 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1085 IN PVOID ApcContext OPTIONAL
,
1086 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1088 IN ULONG BufferSize
,
1089 IN ULONG CompletionFilter
,
1090 IN BOOLEAN WatchTree
)
1093 PKEVENT Event
= NULL
;
1094 PDEVICE_OBJECT DeviceObject
;
1095 PFILE_OBJECT FileObject
;
1096 PIO_STACK_LOCATION IoStack
;
1097 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1098 NTSTATUS Status
= STATUS_SUCCESS
;
1099 BOOLEAN LockedForSync
= FALSE
;
1101 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1103 /* Check if we're called from user mode */
1104 if (PreviousMode
!= KernelMode
)
1106 /* Enter SEH for probing */
1109 /* Probe the I/O STatus block */
1110 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1112 /* Probe the buffer */
1113 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1115 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1117 /* Get the exception code */
1118 Status
= _SEH2_GetExceptionCode();
1122 /* Check if probing failed */
1123 if (!NT_SUCCESS(Status
)) return Status
;
1125 /* Check if CompletionFilter is valid */
1126 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1128 return STATUS_INVALID_PARAMETER
;
1132 /* Get File Object */
1133 Status
= ObReferenceObjectByHandle(FileHandle
,
1134 FILE_LIST_DIRECTORY
,
1137 (PVOID
*)&FileObject
,
1139 if (!NT_SUCCESS(Status
)) return Status
;
1141 /* Check if we have an event handle */
1145 Status
= ObReferenceObjectByHandle(EventHandle
,
1151 if (Status
!= STATUS_SUCCESS
) return Status
;
1152 KeClearEvent(Event
);
1155 /* Check if we should use Sync IO or not */
1156 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1159 IopLockFileObject(FileObject
);
1160 LockedForSync
= TRUE
;
1163 /* Clear File Object event */
1164 KeClearEvent(&FileObject
->Event
);
1166 /* Get the device object */
1167 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1169 /* Allocate the IRP */
1170 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1171 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1173 /* Set up the IRP */
1174 Irp
->RequestorMode
= PreviousMode
;
1175 Irp
->UserIosb
= IoStatusBlock
;
1176 Irp
->UserEvent
= Event
;
1177 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1178 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1179 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1180 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1182 /* Set up Stack Data */
1183 IoStack
= IoGetNextIrpStackLocation(Irp
);
1184 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1185 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1186 IoStack
->FileObject
= FileObject
;
1188 /* Set parameters */
1189 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1190 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1191 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1193 /* Perform the call */
1194 return IopPerformSynchronousRequest(DeviceObject
,
1208 NtLockFile(IN HANDLE FileHandle
,
1209 IN HANDLE EventHandle OPTIONAL
,
1210 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1211 IN PVOID ApcContext OPTIONAL
,
1212 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1213 IN PLARGE_INTEGER ByteOffset
,
1214 IN PLARGE_INTEGER Length
,
1216 IN BOOLEAN FailImmediately
,
1217 IN BOOLEAN ExclusiveLock
)
1219 PFILE_OBJECT FileObject
;
1220 PLARGE_INTEGER LocalLength
= NULL
;
1222 PIO_STACK_LOCATION StackPtr
;
1223 PDEVICE_OBJECT DeviceObject
;
1224 PKEVENT Event
= NULL
;
1225 BOOLEAN LockedForSync
= FALSE
;
1226 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1227 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1228 NTSTATUS Status
= STATUS_SUCCESS
;
1229 OBJECT_HANDLE_INFORMATION HandleInformation
;
1231 CapturedByteOffset
.QuadPart
= 0;
1232 CapturedLength
.QuadPart
= 0;
1233 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1235 /* Get File Object */
1236 Status
= ObReferenceObjectByHandle(FileHandle
,
1240 (PVOID
*)&FileObject
,
1241 &HandleInformation
);
1242 if (!NT_SUCCESS(Status
)) return Status
;
1244 /* Check if we're called from user mode */
1245 if (PreviousMode
!= KernelMode
)
1247 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1248 if (!(HandleInformation
.GrantedAccess
&
1249 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1251 ObDereferenceObject(FileObject
);
1252 return STATUS_ACCESS_DENIED
;
1255 /* Enter SEH for probing */
1258 /* Probe the I/O STatus block */
1259 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1261 /* Probe and capture the large integers */
1262 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1263 CapturedLength
= ProbeForReadLargeInteger(Length
);
1265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1267 /* Get the exception code */
1268 Status
= _SEH2_GetExceptionCode();
1272 /* Check if probing failed */
1273 if (!NT_SUCCESS(Status
))
1275 /* Dereference the object and return exception code */
1276 ObDereferenceObject(FileObject
);
1282 /* Otherwise, capture them directly */
1283 CapturedByteOffset
= *ByteOffset
;
1284 CapturedLength
= *Length
;
1287 /* Check if we have an event handle */
1291 Status
= ObReferenceObjectByHandle(EventHandle
,
1297 if (Status
!= STATUS_SUCCESS
) return Status
;
1298 KeClearEvent(Event
);
1301 /* Get the device object */
1302 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1304 /* Check if we should use Sync IO or not */
1305 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1308 IopLockFileObject(FileObject
);
1309 LockedForSync
= TRUE
;
1312 /* Clear File Object event */
1313 KeClearEvent(&FileObject
->Event
);
1314 FileObject
->LockOperation
= TRUE
;
1316 /* Allocate the IRP */
1317 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1318 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1320 /* Set up the IRP */
1321 Irp
->RequestorMode
= PreviousMode
;
1322 Irp
->UserIosb
= IoStatusBlock
;
1323 Irp
->UserEvent
= Event
;
1324 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1325 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1326 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1327 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1329 /* Set up Stack Data */
1330 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1331 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1332 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1333 StackPtr
->FileObject
= FileObject
;
1338 /* Allocate local buffer */
1339 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1340 sizeof(LARGE_INTEGER
),
1343 /* Set the length */
1344 *LocalLength
= CapturedLength
;
1345 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1346 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1348 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1350 /* Allocating failed, clean up */
1351 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1352 if (LocalLength
) ExFreePool(LocalLength
);
1355 Status
= _SEH2_GetExceptionCode();
1358 if (!NT_SUCCESS(Status
)) return Status
;
1360 /* Set Parameters */
1361 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1362 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1365 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1366 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1368 /* Perform the call */
1369 return IopPerformSynchronousRequest(DeviceObject
,
1383 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1384 IN HANDLE EventHandle OPTIONAL
,
1385 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1386 IN PVOID ApcContext OPTIONAL
,
1387 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1388 OUT PVOID FileInformation
,
1390 IN FILE_INFORMATION_CLASS FileInformationClass
,
1391 IN BOOLEAN ReturnSingleEntry
,
1392 IN PUNICODE_STRING FileName OPTIONAL
,
1393 IN BOOLEAN RestartScan
)
1396 PDEVICE_OBJECT DeviceObject
;
1397 PFILE_OBJECT FileObject
;
1398 PIO_STACK_LOCATION StackPtr
;
1399 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1400 NTSTATUS Status
= STATUS_SUCCESS
;
1401 BOOLEAN LockedForSynch
= FALSE
;
1402 PKEVENT Event
= NULL
;
1403 PVOID AuxBuffer
= NULL
;
1405 UNICODE_STRING CapturedFileName
;
1406 PUNICODE_STRING SearchPattern
;
1408 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1410 /* Check if we came from user mode */
1411 if (PreviousMode
!= KernelMode
)
1413 /* Enter SEH for probing */
1416 /* Probe the I/O Status Block */
1417 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1419 /* Probe the file information */
1420 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1422 /* Check if we have a file name */
1426 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1427 if (CapturedFileName
.Length
)
1429 /* Probe its buffer */
1430 ProbeForRead(CapturedFileName
.Buffer
,
1431 CapturedFileName
.Length
,
1435 /* Allocate the auxiliary buffer */
1436 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1437 CapturedFileName
.Length
+
1438 sizeof(UNICODE_STRING
),
1440 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1441 sizeof(UNICODE_STRING
)),
1442 CapturedFileName
.Buffer
,
1443 CapturedFileName
.Length
);
1445 /* Setup the search pattern */
1446 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1447 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1448 sizeof(UNICODE_STRING
));
1449 SearchPattern
->Length
= CapturedFileName
.Length
;
1450 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1453 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1455 /* Get exception code and free the buffer */
1456 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1457 Status
= _SEH2_GetExceptionCode();
1461 /* Return status on failure */
1462 if (!NT_SUCCESS(Status
)) return Status
;
1465 /* Get File Object */
1466 Status
= ObReferenceObjectByHandle(FileHandle
,
1467 FILE_LIST_DIRECTORY
,
1470 (PVOID
*)&FileObject
,
1472 if (!NT_SUCCESS(Status
))
1475 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1479 /* Check if we have an even handle */
1482 /* Get its pointer */
1483 Status
= ObReferenceObjectByHandle(EventHandle
,
1489 if (!NT_SUCCESS(Status
))
1492 ObDereferenceObject(FileObject
);
1497 KeClearEvent(Event
);
1500 /* Check if this is a file that was opened for Synch I/O */
1501 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1504 IopLockFileObject(FileObject
);
1506 /* Remember to unlock later */
1507 LockedForSynch
= TRUE
;
1510 /* Get the device object */
1511 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1513 /* Clear the File Object's event */
1514 KeClearEvent(&FileObject
->Event
);
1516 /* Allocate the IRP */
1517 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1518 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1520 /* Set up the IRP */
1521 Irp
->RequestorMode
= PreviousMode
;
1522 Irp
->UserIosb
= IoStatusBlock
;
1523 Irp
->UserEvent
= Event
;
1524 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1525 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1526 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1527 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1528 Irp
->MdlAddress
= NULL
;
1529 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1530 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1532 /* Check if this is buffered I/O */
1533 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1538 /* Allocate a buffer */
1539 Irp
->AssociatedIrp
.SystemBuffer
=
1540 ExAllocatePoolWithTag(NonPagedPool
,
1544 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1546 /* Allocating failed, clean up */
1547 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1548 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1551 Status
= _SEH2_GetExceptionCode();
1554 if (!NT_SUCCESS(Status
)) return Status
;
1556 /* Set the buffer and flags */
1557 Irp
->UserBuffer
= FileInformation
;
1558 Irp
->Flags
= (IRP_BUFFERED_IO
|
1559 IRP_DEALLOCATE_BUFFER
|
1560 IRP_INPUT_OPERATION
);
1562 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1566 /* Allocate an MDL */
1567 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1568 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1570 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1572 /* Allocating failed, clean up */
1573 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1574 Status
= _SEH2_GetExceptionCode();
1575 _SEH2_YIELD(return Status
);
1581 /* No allocation flags, and use the buffer directly */
1582 Irp
->UserBuffer
= FileInformation
;
1585 /* Set up Stack Data */
1586 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1587 StackPtr
->FileObject
= FileObject
;
1588 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1589 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1591 /* Set Parameters */
1592 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1593 FileInformationClass
;
1594 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1595 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1596 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1597 StackPtr
->Flags
= 0;
1598 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1599 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1601 /* Set deferred I/O */
1602 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1604 /* Perform the call */
1605 return IopPerformSynchronousRequest(DeviceObject
,
1619 NtQueryEaFile(IN HANDLE FileHandle
,
1620 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1623 IN BOOLEAN ReturnSingleEntry
,
1624 IN PVOID EaList OPTIONAL
,
1625 IN ULONG EaListLength
,
1626 IN PULONG EaIndex OPTIONAL
,
1627 IN BOOLEAN RestartScan
)
1630 return STATUS_NOT_IMPLEMENTED
;
1638 NtQueryInformationFile(IN HANDLE FileHandle
,
1639 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1640 IN PVOID FileInformation
,
1642 IN FILE_INFORMATION_CLASS FileInformationClass
)
1644 OBJECT_HANDLE_INFORMATION HandleInformation
;
1645 PFILE_OBJECT FileObject
;
1646 NTSTATUS Status
= STATUS_SUCCESS
;
1648 PDEVICE_OBJECT DeviceObject
;
1649 PIO_STACK_LOCATION StackPtr
;
1650 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1651 PKEVENT Event
= NULL
;
1652 BOOLEAN LocalEvent
= FALSE
;
1653 PKNORMAL_ROUTINE NormalRoutine
;
1654 PVOID NormalContext
;
1656 IO_STATUS_BLOCK KernelIosb
;
1657 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1659 /* Check if we're called from user mode */
1660 if (PreviousMode
!= KernelMode
)
1662 /* Validate the information class */
1663 if ((FileInformationClass
>= FileMaximumInformation
) ||
1664 !(IopQueryOperationLength
[FileInformationClass
]))
1667 return STATUS_INVALID_INFO_CLASS
;
1670 /* Validate the length */
1671 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1673 /* Invalid length */
1674 return STATUS_INFO_LENGTH_MISMATCH
;
1677 /* Enter SEH for probing */
1680 /* Probe the I/O Status block */
1681 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1683 /* Probe the information */
1684 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1686 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1688 /* Get the exception code */
1689 Status
= _SEH2_GetExceptionCode();
1692 if (!NT_SUCCESS(Status
)) return Status
;
1696 /* Validate the information class */
1697 if ((FileInformationClass
>= FileMaximumInformation
) ||
1698 !(IopQueryOperationLength
[FileInformationClass
]))
1701 return STATUS_INVALID_INFO_CLASS
;
1704 /* Validate the length */
1705 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1707 /* Invalid length */
1708 return STATUS_INFO_LENGTH_MISMATCH
;
1712 /* Reference the Handle */
1713 Status
= ObReferenceObjectByHandle(FileHandle
,
1714 IopQueryOperationAccess
1715 [FileInformationClass
],
1718 (PVOID
*)&FileObject
,
1719 &HandleInformation
);
1720 if (!NT_SUCCESS(Status
)) return Status
;
1722 /* Check if this is a direct open or not */
1723 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1725 /* Get the device object */
1726 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1730 /* Get the device object */
1731 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1734 /* Check if this is a file that was opened for Synch I/O */
1735 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1738 IopLockFileObject(FileObject
);
1740 /* Check if the caller just wants the position */
1741 if (FileInformationClass
== FilePositionInformation
)
1743 /* Protect write in SEH */
1746 /* Write the offset */
1747 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1748 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1750 /* Fill out the I/O Status Block */
1751 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1752 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1754 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1756 /* Get the exception code */
1757 Status
= _SEH2_GetExceptionCode();
1761 /* Release the file lock, dereference the file and return */
1762 IopUnlockFileObject(FileObject
);
1763 ObDereferenceObject(FileObject
);
1769 /* Use local event */
1770 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1771 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1775 /* Clear the File Object event */
1776 KeClearEvent(&FileObject
->Event
);
1778 /* Allocate the IRP */
1779 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1780 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1783 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1784 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1785 Irp
->RequestorMode
= PreviousMode
;
1786 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1787 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1788 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1789 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1790 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1791 Irp
->MdlAddress
= NULL
;
1792 Irp
->UserBuffer
= FileInformation
;
1794 /* Set the Stack Data */
1795 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1796 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1797 StackPtr
->FileObject
= FileObject
;
1802 /* Allocate a buffer */
1803 Irp
->AssociatedIrp
.SystemBuffer
=
1804 ExAllocatePoolWithTag(NonPagedPool
,
1808 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1810 /* Allocating failed, clean up */
1811 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
1812 Status
= _SEH2_GetExceptionCode();
1815 if (!NT_SUCCESS(Status
)) return Status
;
1818 Irp
->Flags
|= (IRP_BUFFERED_IO
|
1819 IRP_DEALLOCATE_BUFFER
|
1820 IRP_INPUT_OPERATION
|
1821 IRP_DEFER_IO_COMPLETION
);
1823 /* Set the Parameters */
1824 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1825 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1828 IopQueueIrpToThread(Irp
);
1830 /* Update operation counts */
1831 IopUpdateOperationCount(IopOtherTransfer
);
1833 /* Call the Driver */
1834 Status
= IoCallDriver(DeviceObject
, Irp
);
1835 if (Status
== STATUS_PENDING
)
1837 /* Check if this was async I/O */
1840 /* Then to a non-alertable wait */
1841 Status
= KeWaitForSingleObject(Event
,
1846 if (Status
== STATUS_USER_APC
)
1848 /* Abort the request */
1849 IopAbortInterruptedIrp(Event
, Irp
);
1852 /* Set the final status */
1853 Status
= KernelIosb
.Status
;
1855 /* Enter SEH to write the IOSB back */
1858 /* Write it back to the caller */
1859 *IoStatusBlock
= KernelIosb
;
1861 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1863 /* Get the exception code */
1864 Status
= _SEH2_GetExceptionCode();
1868 /* Free the event */
1873 /* Wait for the IRP */
1874 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1877 FileObject
->Flags
& FO_ALERTABLE_IO
,
1879 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
1881 /* Abort the request */
1882 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1885 /* Set the final status */
1886 Status
= FileObject
->FinalStatus
;
1888 /* Release the file lock */
1889 IopUnlockFileObject(FileObject
);
1894 /* Free the event if we had one */
1897 /* Clear it in the IRP for completion */
1898 Irp
->UserEvent
= NULL
;
1899 ExFreePoolWithTag(Event
, TAG_IO
);
1902 /* Set the caller IOSB */
1903 Irp
->UserIosb
= IoStatusBlock
;
1905 /* The IRP wasn't completed, complete it ourselves */
1906 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1907 IopCompleteRequest(&Irp
->Tail
.Apc
,
1910 (PVOID
*)&FileObject
,
1912 KeLowerIrql(OldIrql
);
1914 /* Release the file object if we had locked it*/
1915 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
1918 /* Return the Status */
1927 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
1928 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1931 IN BOOLEAN ReturnSingleEntry
,
1932 IN PVOID SidList OPTIONAL
,
1933 IN ULONG SidListLength
,
1934 IN PSID StartSid OPTIONAL
,
1935 IN BOOLEAN RestartScan
)
1938 return STATUS_NOT_IMPLEMENTED
;
1946 NtReadFile(IN HANDLE FileHandle
,
1947 IN HANDLE Event OPTIONAL
,
1948 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1949 IN PVOID ApcContext OPTIONAL
,
1950 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1953 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
1954 IN PULONG Key OPTIONAL
)
1956 NTSTATUS Status
= STATUS_SUCCESS
;
1957 PFILE_OBJECT FileObject
;
1959 PDEVICE_OBJECT DeviceObject
;
1960 PIO_STACK_LOCATION StackPtr
;
1961 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1962 PKEVENT EventObject
= NULL
;
1963 LARGE_INTEGER CapturedByteOffset
;
1964 ULONG CapturedKey
= 0;
1965 BOOLEAN Synchronous
= FALSE
;
1968 CapturedByteOffset
.QuadPart
= 0;
1969 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1971 /* Validate User-Mode Buffers */
1972 if(PreviousMode
!= KernelMode
)
1976 /* Probe the status block */
1977 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1979 /* Probe the read buffer */
1980 ProbeForWrite(Buffer
, Length
, 1);
1982 /* Check if we got a byte offset */
1985 /* Capture and probe it */
1986 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1989 /* Capture and probe the key */
1990 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
1992 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1994 /* Get the exception code */
1995 Status
= _SEH2_GetExceptionCode();
1999 /* Check for probe failure */
2000 if (!NT_SUCCESS(Status
)) return Status
;
2004 /* Kernel mode: capture directly */
2005 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2006 if (Key
) CapturedKey
= *Key
;
2009 /* Get File Object */
2010 Status
= ObReferenceObjectByHandle(FileHandle
,
2014 (PVOID
*)&FileObject
,
2016 if (!NT_SUCCESS(Status
)) return Status
;
2018 /* Check for event */
2022 Status
= ObReferenceObjectByHandle(Event
,
2026 (PVOID
*)&EventObject
,
2028 if (!NT_SUCCESS(Status
))
2031 ObDereferenceObject(FileObject
);
2035 /* Otherwise reset the event */
2036 KeClearEvent(EventObject
);
2039 /* Check if we should use Sync IO or not */
2040 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2042 /* Lock the file object */
2043 IopLockFileObject(FileObject
);
2045 /* Check if we don't have a byte offset avilable */
2046 if (!(ByteOffset
) ||
2047 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2048 (CapturedByteOffset
.u
.HighPart
== -1)))
2050 /* Use the Current Byte Offset instead */
2051 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2054 /* Remember we are sync */
2057 else if (!(ByteOffset
) &&
2058 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2060 /* Otherwise, this was async I/O without a byte offset, so fail */
2061 if (EventObject
) ObDereferenceObject(EventObject
);
2062 ObDereferenceObject(FileObject
);
2063 return STATUS_INVALID_PARAMETER
;
2066 /* Get the device object */
2067 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2069 /* Clear the File Object's event */
2070 KeClearEvent(&FileObject
->Event
);
2072 /* Allocate the IRP */
2073 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2074 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2077 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2078 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2079 Irp
->RequestorMode
= PreviousMode
;
2080 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2081 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2082 Irp
->UserIosb
= IoStatusBlock
;
2083 Irp
->UserEvent
= EventObject
;
2084 Irp
->PendingReturned
= FALSE
;
2085 Irp
->Cancel
= FALSE
;
2086 Irp
->CancelRoutine
= NULL
;
2087 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2088 Irp
->MdlAddress
= NULL
;
2090 /* Set the Stack Data */
2091 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2092 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2093 StackPtr
->FileObject
= FileObject
;
2094 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2095 StackPtr
->Parameters
.Read
.Length
= Length
;
2096 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2098 /* Check if this is buffered I/O */
2099 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2101 /* Check if we have a buffer length */
2107 /* Allocate a buffer */
2108 Irp
->AssociatedIrp
.SystemBuffer
=
2109 ExAllocatePoolWithTag(NonPagedPool
,
2113 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2115 /* Allocating failed, clean up */
2116 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2117 Status
= _SEH2_GetExceptionCode();
2120 if (!NT_SUCCESS(Status
)) return Status
;
2122 /* Set the buffer and flags */
2123 Irp
->UserBuffer
= Buffer
;
2124 Irp
->Flags
= (IRP_BUFFERED_IO
|
2125 IRP_DEALLOCATE_BUFFER
|
2126 IRP_INPUT_OPERATION
);
2130 /* Not reading anything */
2131 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2134 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2136 /* Check if we have a buffer length */
2141 /* Allocate an MDL */
2142 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2143 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2145 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2147 /* Allocating failed, clean up */
2148 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2149 Status
= _SEH2_GetExceptionCode();
2150 _SEH2_YIELD(return Status
);
2156 /* No allocation flags */
2161 /* No allocation flags, and use the buffer directly */
2163 Irp
->UserBuffer
= Buffer
;
2166 /* Now set the deferred read flags */
2167 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2169 /* FIXME: VFAT SUCKS */
2170 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2173 /* Perform the call */
2174 return IopPerformSynchronousRequest(DeviceObject
,
2188 NtReadFileScatter(IN HANDLE FileHandle
,
2189 IN HANDLE Event OPTIONAL
,
2190 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2191 IN PVOID UserApcContext OPTIONAL
,
2192 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2193 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2194 IN ULONG BufferLength
,
2195 IN PLARGE_INTEGER ByteOffset
,
2196 IN PULONG Key OPTIONAL
)
2199 return STATUS_NOT_IMPLEMENTED
;
2207 NtSetEaFile(IN HANDLE FileHandle
,
2208 IN PIO_STATUS_BLOCK IoStatusBlock
,
2210 IN ULONG EaBufferSize
)
2213 return STATUS_NOT_IMPLEMENTED
;
2221 NtSetInformationFile(IN HANDLE FileHandle
,
2222 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2223 IN PVOID FileInformation
,
2225 IN FILE_INFORMATION_CLASS FileInformationClass
)
2227 PFILE_OBJECT FileObject
;
2228 NTSTATUS Status
= STATUS_SUCCESS
;
2230 PDEVICE_OBJECT DeviceObject
;
2231 PIO_STACK_LOCATION StackPtr
;
2232 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2233 PKEVENT Event
= NULL
;
2234 BOOLEAN LocalEvent
= FALSE
;
2235 PKNORMAL_ROUTINE NormalRoutine
;
2236 PVOID NormalContext
;
2238 IO_STATUS_BLOCK KernelIosb
;
2240 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2241 PIO_COMPLETION_CONTEXT Context
;
2242 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2244 /* Check if we're called from user mode */
2245 if (PreviousMode
!= KernelMode
)
2247 /* Validate the information class */
2248 if ((FileInformationClass
>= FileMaximumInformation
) ||
2249 !(IopSetOperationLength
[FileInformationClass
]))
2252 return STATUS_INVALID_INFO_CLASS
;
2255 /* Validate the length */
2256 if (Length
< IopSetOperationLength
[FileInformationClass
])
2258 /* Invalid length */
2259 return STATUS_INFO_LENGTH_MISMATCH
;
2262 /* Enter SEH for probing */
2265 /* Probe the I/O Status block */
2266 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2268 /* Probe the information */
2269 ProbeForRead(FileInformation
,
2271 (Length
== sizeof(BOOLEAN
)) ?
2272 sizeof(BOOLEAN
) : sizeof(ULONG
));
2274 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2276 /* Get the exception code */
2277 Status
= _SEH2_GetExceptionCode();
2281 /* Check if probing failed */
2282 if (!NT_SUCCESS(Status
)) return Status
;
2286 /* Validate the information class */
2287 if ((FileInformationClass
>= FileMaximumInformation
) ||
2288 !(IopSetOperationLength
[FileInformationClass
]))
2291 return STATUS_INVALID_INFO_CLASS
;
2294 /* Validate the length */
2295 if (Length
< IopSetOperationLength
[FileInformationClass
])
2297 /* Invalid length */
2298 return STATUS_INFO_LENGTH_MISMATCH
;
2302 /* Reference the Handle */
2303 Status
= ObReferenceObjectByHandle(FileHandle
,
2304 IopSetOperationAccess
2305 [FileInformationClass
],
2308 (PVOID
*)&FileObject
,
2310 if (!NT_SUCCESS(Status
)) return Status
;
2312 /* Check if this is a direct open or not */
2313 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2315 /* Get the device object */
2316 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2320 /* Get the device object */
2321 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2324 /* Check if this is a file that was opened for Synch I/O */
2325 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2328 IopLockFileObject(FileObject
);
2330 /* Check if the caller just wants the position */
2331 if (FileInformationClass
== FilePositionInformation
)
2333 /* Protect write in SEH */
2336 /* Write the offset */
2337 FileObject
->CurrentByteOffset
=
2338 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2341 /* Fill out the I/O Status Block */
2342 IoStatusBlock
->Information
= 0;
2343 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2345 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2347 /* Get the exception code */
2348 Status
= _SEH2_GetExceptionCode();
2352 /* Release the file lock, dereference the file and return */
2353 IopUnlockFileObject(FileObject
);
2354 ObDereferenceObject(FileObject
);
2360 /* Use local event */
2361 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2362 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2366 /* Clear the File Object event */
2367 KeClearEvent(&FileObject
->Event
);
2369 /* Allocate the IRP */
2370 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2371 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2374 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2375 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2376 Irp
->RequestorMode
= PreviousMode
;
2377 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2378 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2379 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2380 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2381 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2382 Irp
->MdlAddress
= NULL
;
2383 Irp
->UserBuffer
= FileInformation
;
2385 /* Set the Stack Data */
2386 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2387 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2388 StackPtr
->FileObject
= FileObject
;
2393 /* Allocate a buffer */
2394 Irp
->AssociatedIrp
.SystemBuffer
=
2395 ExAllocatePoolWithTag(NonPagedPool
,
2399 /* Copy the data into it */
2400 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2404 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2406 /* Allocating failed, clean up */
2407 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2408 Status
= _SEH2_GetExceptionCode();
2411 if (!NT_SUCCESS(Status
)) return Status
;
2414 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2415 IRP_DEALLOCATE_BUFFER
|
2416 IRP_DEFER_IO_COMPLETION
);
2418 /* Set the Parameters */
2419 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2420 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2423 IopQueueIrpToThread(Irp
);
2425 /* Update operation counts */
2426 IopUpdateOperationCount(IopOtherTransfer
);
2428 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2429 /* Handle IO Completion Port quickly */
2430 if (FileInformationClass
== FileCompletionInformation
)
2432 /* Check if the file object already has a completion port */
2433 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2434 (FileObject
->CompletionContext
))
2437 Status
= STATUS_INVALID_PARAMETER
;
2441 /* Reference the Port */
2442 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2443 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2444 IO_COMPLETION_MODIFY_STATE
,
2449 if (NT_SUCCESS(Status
))
2451 /* Allocate the Context */
2452 Context
= ExAllocatePoolWithTag(PagedPool
,
2453 sizeof(IO_COMPLETION_CONTEXT
),
2458 Context
->Key
= CompletionInfo
->Key
;
2459 Context
->Port
= Queue
;
2460 if (InterlockedCompareExchangePointer(&FileObject
->
2466 * Someone else set the completion port in the
2467 * meanwhile, so dereference the port and fail.
2469 ExFreePool(Context
);
2470 ObDereferenceObject(Queue
);
2471 Status
= STATUS_INVALID_PARAMETER
;
2476 /* Dereference the Port now */
2477 ObDereferenceObject(Queue
);
2478 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2483 /* Set the IRP Status */
2484 Irp
->IoStatus
.Status
= Status
;
2485 Irp
->IoStatus
.Information
= 0;
2489 /* Call the Driver */
2490 Status
= IoCallDriver(DeviceObject
, Irp
);
2493 /* Check if we're waiting for the IRP to complete */
2494 if (Status
== STATUS_PENDING
)
2496 /* Check if this was async I/O */
2499 /* Then to a non-alertable wait */
2500 Status
= KeWaitForSingleObject(Event
,
2505 if (Status
== STATUS_USER_APC
)
2507 /* Abort the request */
2508 IopAbortInterruptedIrp(Event
, Irp
);
2511 /* Set the final status */
2512 Status
= KernelIosb
.Status
;
2514 /* Enter SEH to write the IOSB back */
2517 /* Write it back to the caller */
2518 *IoStatusBlock
= KernelIosb
;
2520 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2522 /* Get the exception code */
2523 Status
= _SEH2_GetExceptionCode();
2527 /* Free the event */
2532 /* Wait for the IRP */
2533 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2536 FileObject
->Flags
& FO_ALERTABLE_IO
,
2538 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2540 /* Abort the request */
2541 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2544 /* Set the final status */
2545 Status
= FileObject
->FinalStatus
;
2547 /* Release the file lock */
2548 IopUnlockFileObject(FileObject
);
2553 /* Free the event if we had one */
2556 /* Clear it in the IRP for completion */
2557 Irp
->UserEvent
= NULL
;
2561 /* Set the caller IOSB */
2562 Irp
->UserIosb
= IoStatusBlock
;
2564 /* The IRP wasn't completed, complete it ourselves */
2565 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2566 IopCompleteRequest(&Irp
->Tail
.Apc
,
2569 (PVOID
*)&FileObject
,
2571 KeLowerIrql(OldIrql
);
2573 /* Release the file object if we had locked it*/
2574 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2577 /* Return the Status */
2586 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2587 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2589 IN ULONG BufferLength
)
2592 return STATUS_NOT_IMPLEMENTED
;
2600 NtUnlockFile(IN HANDLE FileHandle
,
2601 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2602 IN PLARGE_INTEGER ByteOffset
,
2603 IN PLARGE_INTEGER Length
,
2604 IN ULONG Key OPTIONAL
)
2606 PFILE_OBJECT FileObject
;
2607 PLARGE_INTEGER LocalLength
= NULL
;
2609 PIO_STACK_LOCATION StackPtr
;
2610 PDEVICE_OBJECT DeviceObject
;
2611 PKEVENT Event
= NULL
;
2612 BOOLEAN LocalEvent
= FALSE
;
2613 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2614 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2615 NTSTATUS Status
= STATUS_SUCCESS
;
2616 OBJECT_HANDLE_INFORMATION HandleInformation
;
2617 IO_STATUS_BLOCK KernelIosb
;
2619 CapturedByteOffset
.QuadPart
= 0;
2620 CapturedLength
.QuadPart
= 0;
2621 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2623 /* Get File Object */
2624 Status
= ObReferenceObjectByHandle(FileHandle
,
2628 (PVOID
*)&FileObject
,
2629 &HandleInformation
);
2630 if (!NT_SUCCESS(Status
)) return Status
;
2632 /* Check if we're called from user mode */
2633 if (PreviousMode
!= KernelMode
)
2635 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2636 if (!(HandleInformation
.GrantedAccess
&
2637 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2639 ObDereferenceObject(FileObject
);
2640 return STATUS_ACCESS_DENIED
;
2643 /* Enter SEH for probing */
2646 /* Probe the I/O Status block */
2647 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2649 /* Probe and capture the large integers */
2650 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2651 CapturedLength
= ProbeForReadLargeInteger(Length
);
2653 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2655 /* Get the exception code */
2656 Status
= _SEH2_GetExceptionCode();
2660 /* Check if probing failed */
2661 if (!NT_SUCCESS(Status
))
2663 /* Dereference the object and return exception code */
2664 ObDereferenceObject(FileObject
);
2670 /* Otherwise, capture them directly */
2671 CapturedByteOffset
= *ByteOffset
;
2672 CapturedLength
= *Length
;
2675 /* Check if this is a direct open or not */
2676 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2678 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2682 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2685 /* Check if we should use Sync IO or not */
2686 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2689 IopLockFileObject(FileObject
);
2693 /* Use local event */
2694 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2695 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2699 /* Clear File Object event */
2700 KeClearEvent(&FileObject
->Event
);
2702 /* Allocate the IRP */
2703 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2704 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2706 /* Set up the IRP */
2707 Irp
->RequestorMode
= PreviousMode
;
2708 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2709 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2710 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2711 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2712 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2713 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2715 /* Set up Stack Data */
2716 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2717 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2718 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2719 StackPtr
->FileObject
= FileObject
;
2724 /* Allocate a buffer */
2725 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2726 sizeof(LARGE_INTEGER
),
2729 /* Set the length */
2730 *LocalLength
= CapturedLength
;
2731 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
2732 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2734 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2736 /* Allocating failed, clean up */
2737 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2738 if (LocalLength
) ExFreePool(LocalLength
);
2740 /* Get exception status */
2741 Status
= _SEH2_GetExceptionCode();
2744 if (!NT_SUCCESS(Status
)) return Status
;
2746 /* Set Parameters */
2747 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
2748 StackPtr
->Parameters
.LockControl
.Key
= Key
;
2750 /* Call the Driver */
2751 Status
= IopPerformSynchronousRequest(DeviceObject
,
2759 /* Check if this was async I/O */
2762 /* It was, finalize this request */
2763 Status
= IopFinalizeAsynchronousIo(Status
,
2780 NtWriteFile(IN HANDLE FileHandle
,
2781 IN HANDLE Event OPTIONAL
,
2782 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2783 IN PVOID ApcContext OPTIONAL
,
2784 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2787 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2788 IN PULONG Key OPTIONAL
)
2790 NTSTATUS Status
= STATUS_SUCCESS
;
2791 PFILE_OBJECT FileObject
;
2793 PDEVICE_OBJECT DeviceObject
;
2794 PIO_STACK_LOCATION StackPtr
;
2795 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2796 PKEVENT EventObject
= NULL
;
2797 LARGE_INTEGER CapturedByteOffset
;
2798 ULONG CapturedKey
= 0;
2799 BOOLEAN Synchronous
= FALSE
;
2801 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
2803 CapturedByteOffset
.QuadPart
= 0;
2804 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2806 /* Get File Object */
2807 Status
= ObReferenceObjectByHandle(FileHandle
,
2811 (PVOID
*)&FileObject
,
2813 if (!NT_SUCCESS(Status
)) return Status
;
2815 /* Validate User-Mode Buffers */
2816 if(PreviousMode
!= KernelMode
)
2821 * Check if the handle has either FILE_WRITE_DATA or
2822 * FILE_APPEND_DATA granted. However, if this is a named pipe,
2823 * make sure we don't ask for FILE_APPEND_DATA as it interferes
2824 * with the FILE_CREATE_PIPE_INSTANCE access right!
2826 if (!(ObjectHandleInfo
.GrantedAccess
&
2827 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
2828 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
2831 ObDereferenceObject(FileObject
);
2832 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
2835 /* Probe the status block */
2836 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2838 /* Probe the read buffer */
2839 ProbeForRead(Buffer
, Length
, 1);
2841 /* Check if we got a byte offset */
2844 /* Capture and probe it */
2845 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2848 /* Capture and probe the key */
2849 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2851 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2853 /* Get the exception code */
2854 Status
= _SEH2_GetExceptionCode();
2858 /* Check for probe failure */
2859 if (!NT_SUCCESS(Status
)) return Status
;
2863 /* Kernel mode: capture directly */
2864 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2865 if (Key
) CapturedKey
= *Key
;
2868 /* Check if this is an append operation */
2869 if ((ObjectHandleInfo
.GrantedAccess
&
2870 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
2872 /* Give the drivers something to understand */
2873 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
2874 CapturedByteOffset
.u
.HighPart
= -1;
2877 /* Check for event */
2881 Status
= ObReferenceObjectByHandle(Event
,
2885 (PVOID
*)&EventObject
,
2887 if (!NT_SUCCESS(Status
))
2890 ObDereferenceObject(FileObject
);
2894 /* Otherwise reset the event */
2895 KeClearEvent(EventObject
);
2898 /* Check if we should use Sync IO or not */
2899 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2901 /* Lock the file object */
2902 IopLockFileObject(FileObject
);
2904 /* Check if we don't have a byte offset avilable */
2905 if (!(ByteOffset
) ||
2906 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2907 (CapturedByteOffset
.u
.HighPart
== -1)))
2909 /* Use the Current Byte Offset instead */
2910 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2913 /* Remember we are sync */
2916 else if (!(ByteOffset
) &&
2917 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2919 /* Otherwise, this was async I/O without a byte offset, so fail */
2920 if (EventObject
) ObDereferenceObject(EventObject
);
2921 ObDereferenceObject(FileObject
);
2922 return STATUS_INVALID_PARAMETER
;
2925 /* Get the device object */
2926 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2928 /* Clear the File Object's event */
2929 KeClearEvent(&FileObject
->Event
);
2931 /* Allocate the IRP */
2932 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2933 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2936 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2937 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2938 Irp
->RequestorMode
= PreviousMode
;
2939 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2940 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2941 Irp
->UserIosb
= IoStatusBlock
;
2942 Irp
->UserEvent
= EventObject
;
2943 Irp
->PendingReturned
= FALSE
;
2944 Irp
->Cancel
= FALSE
;
2945 Irp
->CancelRoutine
= NULL
;
2946 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2947 Irp
->MdlAddress
= NULL
;
2949 /* Set the Stack Data */
2950 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2951 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
2952 StackPtr
->FileObject
= FileObject
;
2953 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
2954 SL_WRITE_THROUGH
: 0;
2955 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
2956 StackPtr
->Parameters
.Write
.Length
= Length
;
2957 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
2959 /* Check if this is buffered I/O */
2960 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2962 /* Check if we have a buffer length */
2968 /* Allocate a buffer */
2969 Irp
->AssociatedIrp
.SystemBuffer
=
2970 ExAllocatePoolWithTag(NonPagedPool
,
2974 /* Copy the data into it */
2975 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
2977 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2979 /* Allocating failed, clean up */
2980 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2981 Status
= _SEH2_GetExceptionCode();
2982 _SEH2_YIELD(return Status
);
2987 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
2991 /* Not writing anything */
2992 Irp
->Flags
= IRP_BUFFERED_IO
;
2995 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2997 /* Check if we have a buffer length */
3002 /* Allocate an MDL */
3003 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3004 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3006 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3008 /* Allocating failed, clean up */
3009 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3010 Status
= _SEH2_GetExceptionCode();
3011 _SEH2_YIELD(return Status
);
3016 /* No allocation flags */
3021 /* No allocation flags, and use the buffer directly */
3023 Irp
->UserBuffer
= Buffer
;
3026 /* Now set the deferred read flags */
3027 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3029 /* FIXME: VFAT SUCKS */
3030 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3033 /* Perform the call */
3034 return IopPerformSynchronousRequest(DeviceObject
,
3045 NtWriteFileGather(IN HANDLE FileHandle
,
3046 IN HANDLE Event OPTIONAL
,
3047 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3048 IN PVOID UserApcContext OPTIONAL
,
3049 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3050 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3051 IN ULONG BufferLength
,
3052 IN PLARGE_INTEGER ByteOffset
,
3053 IN PULONG Key OPTIONAL
)
3056 return STATUS_NOT_IMPLEMENTED
;
3064 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3065 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3066 OUT PVOID FsInformation
,
3068 IN FS_INFORMATION_CLASS FsInformationClass
)
3070 PFILE_OBJECT FileObject
;
3072 PIO_STACK_LOCATION StackPtr
;
3073 PDEVICE_OBJECT DeviceObject
;
3074 PKEVENT Event
= NULL
;
3075 BOOLEAN LocalEvent
= FALSE
;
3076 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3077 NTSTATUS Status
= STATUS_SUCCESS
;
3078 IO_STATUS_BLOCK KernelIosb
;
3080 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3082 /* Check if we're called from user mode */
3083 if (PreviousMode
!= KernelMode
)
3085 /* Validate the information class */
3086 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3087 !(IopQueryFsOperationLength
[FsInformationClass
]))
3090 return STATUS_INVALID_INFO_CLASS
;
3093 /* Validate the length */
3094 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3096 /* Invalid length */
3097 return STATUS_INFO_LENGTH_MISMATCH
;
3100 /* Enter SEH for probing */
3103 /* Probe the I/O Status block */
3104 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3106 /* Probe the information */
3107 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3109 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3111 /* Get the exception code */
3112 Status
= _SEH2_GetExceptionCode();
3115 if (!NT_SUCCESS(Status
)) return Status
;
3118 /* Get File Object */
3119 Status
= ObReferenceObjectByHandle(FileHandle
,
3120 IopQueryFsOperationAccess
3121 [FsInformationClass
],
3124 (PVOID
*)&FileObject
,
3126 if (!NT_SUCCESS(Status
)) return Status
;
3128 /* Check if we should use Sync IO or not */
3129 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3132 IopLockFileObject(FileObject
);
3136 /* Use local event */
3137 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3138 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3142 /* Get the device object */
3143 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3145 /* Clear File Object event */
3146 KeClearEvent(&FileObject
->Event
);
3148 /* Allocate the IRP */
3149 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3150 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3152 /* Set up the IRP */
3153 Irp
->RequestorMode
= PreviousMode
;
3154 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3155 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3156 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3157 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3158 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3159 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3160 Irp
->UserBuffer
= FsInformation
;
3161 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3162 Irp
->MdlAddress
= NULL
;
3164 /* Set up Stack Data */
3165 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3166 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3167 StackPtr
->FileObject
= FileObject
;
3172 /* Allocate a buffer */
3173 Irp
->AssociatedIrp
.SystemBuffer
=
3174 ExAllocatePoolWithTag(NonPagedPool
,
3178 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3180 /* Allocating failed, clean up */
3181 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3182 Status
= _SEH2_GetExceptionCode();
3185 if (!NT_SUCCESS(Status
)) return Status
;
3187 /* Set the flags for this buffered + deferred I/O */
3188 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3189 IRP_DEALLOCATE_BUFFER
|
3190 IRP_INPUT_OPERATION
|
3191 IRP_DEFER_IO_COMPLETION
);
3193 /* Set Parameters */
3194 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3195 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3197 /* Call the Driver */
3198 Status
= IopPerformSynchronousRequest(DeviceObject
,
3206 /* Check if this was async I/O */
3209 /* It was, finalize this request */
3210 Status
= IopFinalizeAsynchronousIo(Status
,
3227 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3228 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3229 IN PVOID FsInformation
,
3231 IN FS_INFORMATION_CLASS FsInformationClass
)
3233 PFILE_OBJECT FileObject
;
3235 PIO_STACK_LOCATION StackPtr
;
3236 PDEVICE_OBJECT DeviceObject
;
3237 PKEVENT Event
= NULL
;
3238 BOOLEAN LocalEvent
= FALSE
;
3239 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3240 NTSTATUS Status
= STATUS_SUCCESS
;
3241 IO_STATUS_BLOCK KernelIosb
;
3243 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3245 /* Check if we're called from user mode */
3246 if (PreviousMode
!= KernelMode
)
3248 /* Validate the information class */
3249 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3250 !(IopSetFsOperationLength
[FsInformationClass
]))
3253 return STATUS_INVALID_INFO_CLASS
;
3256 /* Validate the length */
3257 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3259 /* Invalid length */
3260 return STATUS_INFO_LENGTH_MISMATCH
;
3263 /* Enter SEH for probing */
3266 /* Probe the I/O Status block */
3267 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3269 /* Probe the information */
3270 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3272 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3274 /* Get the exception code */
3275 Status
= _SEH2_GetExceptionCode();
3278 if (!NT_SUCCESS(Status
)) return Status
;
3281 /* Get File Object */
3282 Status
= ObReferenceObjectByHandle(FileHandle
,
3283 IopSetFsOperationAccess
3284 [FsInformationClass
],
3287 (PVOID
*)&FileObject
,
3289 if (!NT_SUCCESS(Status
)) return Status
;
3291 /* Check if we should use Sync IO or not */
3292 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3295 IopLockFileObject(FileObject
);
3299 /* Use local event */
3300 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3301 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3305 /* Get the device object */
3306 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3308 /* Clear File Object event */
3309 KeClearEvent(&FileObject
->Event
);
3311 /* Allocate the IRP */
3312 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3313 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3315 /* Set up the IRP */
3316 Irp
->RequestorMode
= PreviousMode
;
3317 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3318 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3319 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3320 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3321 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3322 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3323 Irp
->UserBuffer
= FsInformation
;
3324 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3325 Irp
->MdlAddress
= NULL
;
3327 /* Set up Stack Data */
3328 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3329 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3330 StackPtr
->FileObject
= FileObject
;
3335 /* Allocate a buffer */
3336 Irp
->AssociatedIrp
.SystemBuffer
=
3337 ExAllocatePoolWithTag(NonPagedPool
,
3341 /* Copy the data into it */
3342 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3344 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3346 /* Allocating failed, clean up */
3347 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3348 Status
= _SEH2_GetExceptionCode();
3351 if (!NT_SUCCESS(Status
)) return Status
;
3353 /* Set the flags for this buffered + deferred I/O */
3354 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3356 /* Set Parameters */
3357 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3358 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3360 /* Call the Driver */
3361 Status
= IopPerformSynchronousRequest(DeviceObject
,
3369 /* Check if this was async I/O */
3372 /* It was, finalize this request */
3373 Status
= IopFinalizeAsynchronousIo(Status
,
3390 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3393 return STATUS_NOT_IMPLEMENTED
;
3401 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3404 return STATUS_NOT_IMPLEMENTED
;