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
)
1153 ObDereferenceObject(FileObject
);
1156 KeClearEvent(Event
);
1159 /* Check if we should use Sync IO or not */
1160 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1163 IopLockFileObject(FileObject
);
1164 LockedForSync
= TRUE
;
1167 /* Clear File Object event */
1168 KeClearEvent(&FileObject
->Event
);
1170 /* Get the device object */
1171 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1173 /* Allocate the IRP */
1174 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1175 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1177 /* Set up the IRP */
1178 Irp
->RequestorMode
= PreviousMode
;
1179 Irp
->UserIosb
= IoStatusBlock
;
1180 Irp
->UserEvent
= Event
;
1181 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1182 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1183 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1184 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1186 /* Set up Stack Data */
1187 IoStack
= IoGetNextIrpStackLocation(Irp
);
1188 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1189 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1190 IoStack
->FileObject
= FileObject
;
1192 /* Set parameters */
1193 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1194 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1195 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1197 /* Perform the call */
1198 return IopPerformSynchronousRequest(DeviceObject
,
1212 NtLockFile(IN HANDLE FileHandle
,
1213 IN HANDLE EventHandle OPTIONAL
,
1214 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1215 IN PVOID ApcContext OPTIONAL
,
1216 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1217 IN PLARGE_INTEGER ByteOffset
,
1218 IN PLARGE_INTEGER Length
,
1220 IN BOOLEAN FailImmediately
,
1221 IN BOOLEAN ExclusiveLock
)
1223 PFILE_OBJECT FileObject
;
1224 PLARGE_INTEGER LocalLength
= NULL
;
1226 PIO_STACK_LOCATION StackPtr
;
1227 PDEVICE_OBJECT DeviceObject
;
1228 PKEVENT Event
= NULL
;
1229 BOOLEAN LockedForSync
= FALSE
;
1230 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1231 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1232 NTSTATUS Status
= STATUS_SUCCESS
;
1233 OBJECT_HANDLE_INFORMATION HandleInformation
;
1235 CapturedByteOffset
.QuadPart
= 0;
1236 CapturedLength
.QuadPart
= 0;
1237 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1239 /* Get File Object */
1240 Status
= ObReferenceObjectByHandle(FileHandle
,
1244 (PVOID
*)&FileObject
,
1245 &HandleInformation
);
1246 if (!NT_SUCCESS(Status
)) return Status
;
1248 /* Check if we're called from user mode */
1249 if (PreviousMode
!= KernelMode
)
1251 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1252 if (!(HandleInformation
.GrantedAccess
&
1253 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1255 ObDereferenceObject(FileObject
);
1256 return STATUS_ACCESS_DENIED
;
1259 /* Enter SEH for probing */
1262 /* Probe the I/O STatus block */
1263 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1265 /* Probe and capture the large integers */
1266 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1267 CapturedLength
= ProbeForReadLargeInteger(Length
);
1269 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1271 /* Get the exception code */
1272 Status
= _SEH2_GetExceptionCode();
1276 /* Check if probing failed */
1277 if (!NT_SUCCESS(Status
))
1279 /* Dereference the object and return exception code */
1280 ObDereferenceObject(FileObject
);
1286 /* Otherwise, capture them directly */
1287 CapturedByteOffset
= *ByteOffset
;
1288 CapturedLength
= *Length
;
1291 /* Check if we have an event handle */
1295 Status
= ObReferenceObjectByHandle(EventHandle
,
1301 if (Status
!= STATUS_SUCCESS
) return Status
;
1302 KeClearEvent(Event
);
1305 /* Get the device object */
1306 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1308 /* Check if we should use Sync IO or not */
1309 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1312 IopLockFileObject(FileObject
);
1313 LockedForSync
= TRUE
;
1316 /* Clear File Object event */
1317 KeClearEvent(&FileObject
->Event
);
1318 FileObject
->LockOperation
= TRUE
;
1320 /* Allocate the IRP */
1321 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1322 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1324 /* Set up the IRP */
1325 Irp
->RequestorMode
= PreviousMode
;
1326 Irp
->UserIosb
= IoStatusBlock
;
1327 Irp
->UserEvent
= Event
;
1328 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1329 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1330 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1331 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1333 /* Set up Stack Data */
1334 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1335 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1336 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1337 StackPtr
->FileObject
= FileObject
;
1342 /* Allocate local buffer */
1343 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1344 sizeof(LARGE_INTEGER
),
1347 /* Set the length */
1348 *LocalLength
= CapturedLength
;
1349 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1350 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1352 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1354 /* Allocating failed, clean up */
1355 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1356 if (LocalLength
) ExFreePool(LocalLength
);
1359 Status
= _SEH2_GetExceptionCode();
1362 if (!NT_SUCCESS(Status
)) return Status
;
1364 /* Set Parameters */
1365 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1366 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1369 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1370 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1372 /* Perform the call */
1373 return IopPerformSynchronousRequest(DeviceObject
,
1387 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1388 IN HANDLE EventHandle OPTIONAL
,
1389 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1390 IN PVOID ApcContext OPTIONAL
,
1391 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1392 OUT PVOID FileInformation
,
1394 IN FILE_INFORMATION_CLASS FileInformationClass
,
1395 IN BOOLEAN ReturnSingleEntry
,
1396 IN PUNICODE_STRING FileName OPTIONAL
,
1397 IN BOOLEAN RestartScan
)
1400 PDEVICE_OBJECT DeviceObject
;
1401 PFILE_OBJECT FileObject
;
1402 PIO_STACK_LOCATION StackPtr
;
1403 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1404 NTSTATUS Status
= STATUS_SUCCESS
;
1405 BOOLEAN LockedForSynch
= FALSE
;
1406 PKEVENT Event
= NULL
;
1407 PVOID AuxBuffer
= NULL
;
1409 UNICODE_STRING CapturedFileName
;
1410 PUNICODE_STRING SearchPattern
;
1412 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1414 /* Check if we came from user mode */
1415 if (PreviousMode
!= KernelMode
)
1417 /* Enter SEH for probing */
1420 /* Probe the I/O Status Block */
1421 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1423 /* Probe the file information */
1424 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1426 /* Check if we have a file name */
1430 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1431 if (CapturedFileName
.Length
)
1433 /* Probe its buffer */
1434 ProbeForRead(CapturedFileName
.Buffer
,
1435 CapturedFileName
.Length
,
1439 /* Allocate the auxiliary buffer */
1440 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1441 CapturedFileName
.Length
+
1442 sizeof(UNICODE_STRING
),
1444 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1445 sizeof(UNICODE_STRING
)),
1446 CapturedFileName
.Buffer
,
1447 CapturedFileName
.Length
);
1449 /* Setup the search pattern */
1450 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1451 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1452 sizeof(UNICODE_STRING
));
1453 SearchPattern
->Length
= CapturedFileName
.Length
;
1454 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1457 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1459 /* Get exception code and free the buffer */
1460 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1461 Status
= _SEH2_GetExceptionCode();
1465 /* Return status on failure */
1466 if (!NT_SUCCESS(Status
)) return Status
;
1469 /* Get File Object */
1470 Status
= ObReferenceObjectByHandle(FileHandle
,
1471 FILE_LIST_DIRECTORY
,
1474 (PVOID
*)&FileObject
,
1476 if (!NT_SUCCESS(Status
))
1479 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1483 /* Check if we have an even handle */
1486 /* Get its pointer */
1487 Status
= ObReferenceObjectByHandle(EventHandle
,
1493 if (!NT_SUCCESS(Status
))
1496 ObDereferenceObject(FileObject
);
1501 KeClearEvent(Event
);
1504 /* Check if this is a file that was opened for Synch I/O */
1505 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1508 IopLockFileObject(FileObject
);
1510 /* Remember to unlock later */
1511 LockedForSynch
= TRUE
;
1514 /* Get the device object */
1515 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1517 /* Clear the File Object's event */
1518 KeClearEvent(&FileObject
->Event
);
1520 /* Allocate the IRP */
1521 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1522 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1524 /* Set up the IRP */
1525 Irp
->RequestorMode
= PreviousMode
;
1526 Irp
->UserIosb
= IoStatusBlock
;
1527 Irp
->UserEvent
= Event
;
1528 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1529 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1530 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1531 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1532 Irp
->MdlAddress
= NULL
;
1533 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1534 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1536 /* Check if this is buffered I/O */
1537 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1542 /* Allocate a buffer */
1543 Irp
->AssociatedIrp
.SystemBuffer
=
1544 ExAllocatePoolWithTag(NonPagedPool
,
1548 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1550 /* Allocating failed, clean up */
1551 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1552 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1555 Status
= _SEH2_GetExceptionCode();
1558 if (!NT_SUCCESS(Status
)) return Status
;
1560 /* Set the buffer and flags */
1561 Irp
->UserBuffer
= FileInformation
;
1562 Irp
->Flags
= (IRP_BUFFERED_IO
|
1563 IRP_DEALLOCATE_BUFFER
|
1564 IRP_INPUT_OPERATION
);
1566 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1570 /* Allocate an MDL */
1571 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1572 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1574 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1576 /* Allocating failed, clean up */
1577 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1578 Status
= _SEH2_GetExceptionCode();
1579 _SEH2_YIELD(return Status
);
1585 /* No allocation flags, and use the buffer directly */
1586 Irp
->UserBuffer
= FileInformation
;
1589 /* Set up Stack Data */
1590 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1591 StackPtr
->FileObject
= FileObject
;
1592 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1593 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1595 /* Set Parameters */
1596 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1597 FileInformationClass
;
1598 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1599 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1600 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1601 StackPtr
->Flags
= 0;
1602 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1603 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1605 /* Set deferred I/O */
1606 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1608 /* Perform the call */
1609 return IopPerformSynchronousRequest(DeviceObject
,
1623 NtQueryEaFile(IN HANDLE FileHandle
,
1624 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1627 IN BOOLEAN ReturnSingleEntry
,
1628 IN PVOID EaList OPTIONAL
,
1629 IN ULONG EaListLength
,
1630 IN PULONG EaIndex OPTIONAL
,
1631 IN BOOLEAN RestartScan
)
1634 return STATUS_NOT_IMPLEMENTED
;
1642 NtQueryInformationFile(IN HANDLE FileHandle
,
1643 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1644 IN PVOID FileInformation
,
1646 IN FILE_INFORMATION_CLASS FileInformationClass
)
1648 OBJECT_HANDLE_INFORMATION HandleInformation
;
1649 PFILE_OBJECT FileObject
;
1650 NTSTATUS Status
= STATUS_SUCCESS
;
1652 PDEVICE_OBJECT DeviceObject
;
1653 PIO_STACK_LOCATION StackPtr
;
1654 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1655 PKEVENT Event
= NULL
;
1656 BOOLEAN LocalEvent
= FALSE
;
1657 PKNORMAL_ROUTINE NormalRoutine
;
1658 PVOID NormalContext
;
1660 IO_STATUS_BLOCK KernelIosb
;
1661 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1663 /* Check if we're called from user mode */
1664 if (PreviousMode
!= KernelMode
)
1666 /* Validate the information class */
1667 if ((FileInformationClass
>= FileMaximumInformation
) ||
1668 !(IopQueryOperationLength
[FileInformationClass
]))
1671 return STATUS_INVALID_INFO_CLASS
;
1674 /* Validate the length */
1675 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1677 /* Invalid length */
1678 return STATUS_INFO_LENGTH_MISMATCH
;
1681 /* Enter SEH for probing */
1684 /* Probe the I/O Status block */
1685 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1687 /* Probe the information */
1688 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1690 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1692 /* Get the exception code */
1693 Status
= _SEH2_GetExceptionCode();
1696 if (!NT_SUCCESS(Status
)) return Status
;
1700 /* Validate the information class */
1701 if ((FileInformationClass
>= FileMaximumInformation
) ||
1702 !(IopQueryOperationLength
[FileInformationClass
]))
1705 return STATUS_INVALID_INFO_CLASS
;
1708 /* Validate the length */
1709 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1711 /* Invalid length */
1712 return STATUS_INFO_LENGTH_MISMATCH
;
1716 /* Reference the Handle */
1717 Status
= ObReferenceObjectByHandle(FileHandle
,
1718 IopQueryOperationAccess
1719 [FileInformationClass
],
1722 (PVOID
*)&FileObject
,
1723 &HandleInformation
);
1724 if (!NT_SUCCESS(Status
)) return Status
;
1726 /* Check if this is a direct open or not */
1727 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1729 /* Get the device object */
1730 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1734 /* Get the device object */
1735 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1738 /* Check if this is a file that was opened for Synch I/O */
1739 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1742 IopLockFileObject(FileObject
);
1744 /* Check if the caller just wants the position */
1745 if (FileInformationClass
== FilePositionInformation
)
1747 /* Protect write in SEH */
1750 /* Write the offset */
1751 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1752 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1754 /* Fill out the I/O Status Block */
1755 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1756 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1758 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1760 /* Get the exception code */
1761 Status
= _SEH2_GetExceptionCode();
1765 /* Release the file lock, dereference the file and return */
1766 IopUnlockFileObject(FileObject
);
1767 ObDereferenceObject(FileObject
);
1773 /* Use local event */
1774 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1775 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1779 /* Clear the File Object event */
1780 KeClearEvent(&FileObject
->Event
);
1782 /* Allocate the IRP */
1783 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1784 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1787 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1788 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1789 Irp
->RequestorMode
= PreviousMode
;
1790 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1791 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1792 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1793 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1794 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1795 Irp
->MdlAddress
= NULL
;
1796 Irp
->UserBuffer
= FileInformation
;
1798 /* Set the Stack Data */
1799 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1800 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1801 StackPtr
->FileObject
= FileObject
;
1806 /* Allocate a buffer */
1807 Irp
->AssociatedIrp
.SystemBuffer
=
1808 ExAllocatePoolWithTag(NonPagedPool
,
1812 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1814 /* Allocating failed, clean up */
1815 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
1816 Status
= _SEH2_GetExceptionCode();
1819 if (!NT_SUCCESS(Status
)) return Status
;
1822 Irp
->Flags
|= (IRP_BUFFERED_IO
|
1823 IRP_DEALLOCATE_BUFFER
|
1824 IRP_INPUT_OPERATION
|
1825 IRP_DEFER_IO_COMPLETION
);
1827 /* Set the Parameters */
1828 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1829 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1832 IopQueueIrpToThread(Irp
);
1834 /* Update operation counts */
1835 IopUpdateOperationCount(IopOtherTransfer
);
1837 /* Call the Driver */
1838 Status
= IoCallDriver(DeviceObject
, Irp
);
1839 if (Status
== STATUS_PENDING
)
1841 /* Check if this was async I/O */
1844 /* Then to a non-alertable wait */
1845 Status
= KeWaitForSingleObject(Event
,
1850 if (Status
== STATUS_USER_APC
)
1852 /* Abort the request */
1853 IopAbortInterruptedIrp(Event
, Irp
);
1856 /* Set the final status */
1857 Status
= KernelIosb
.Status
;
1859 /* Enter SEH to write the IOSB back */
1862 /* Write it back to the caller */
1863 *IoStatusBlock
= KernelIosb
;
1865 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1867 /* Get the exception code */
1868 Status
= _SEH2_GetExceptionCode();
1872 /* Free the event */
1877 /* Wait for the IRP */
1878 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1881 FileObject
->Flags
& FO_ALERTABLE_IO
,
1883 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
1885 /* Abort the request */
1886 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1889 /* Set the final status */
1890 Status
= FileObject
->FinalStatus
;
1892 /* Release the file lock */
1893 IopUnlockFileObject(FileObject
);
1898 /* Free the event if we had one */
1901 /* Clear it in the IRP for completion */
1902 Irp
->UserEvent
= NULL
;
1903 ExFreePoolWithTag(Event
, TAG_IO
);
1906 /* Set the caller IOSB */
1907 Irp
->UserIosb
= IoStatusBlock
;
1909 /* The IRP wasn't completed, complete it ourselves */
1910 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1911 IopCompleteRequest(&Irp
->Tail
.Apc
,
1914 (PVOID
*)&FileObject
,
1916 KeLowerIrql(OldIrql
);
1918 /* Release the file object if we had locked it*/
1919 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
1922 /* Return the Status */
1931 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
1932 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1935 IN BOOLEAN ReturnSingleEntry
,
1936 IN PVOID SidList OPTIONAL
,
1937 IN ULONG SidListLength
,
1938 IN PSID StartSid OPTIONAL
,
1939 IN BOOLEAN RestartScan
)
1942 return STATUS_NOT_IMPLEMENTED
;
1950 NtReadFile(IN HANDLE FileHandle
,
1951 IN HANDLE Event OPTIONAL
,
1952 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1953 IN PVOID ApcContext OPTIONAL
,
1954 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1957 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
1958 IN PULONG Key OPTIONAL
)
1960 NTSTATUS Status
= STATUS_SUCCESS
;
1961 PFILE_OBJECT FileObject
;
1963 PDEVICE_OBJECT DeviceObject
;
1964 PIO_STACK_LOCATION StackPtr
;
1965 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1966 PKEVENT EventObject
= NULL
;
1967 LARGE_INTEGER CapturedByteOffset
;
1968 ULONG CapturedKey
= 0;
1969 BOOLEAN Synchronous
= FALSE
;
1972 CapturedByteOffset
.QuadPart
= 0;
1973 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1975 /* Validate User-Mode Buffers */
1976 if(PreviousMode
!= KernelMode
)
1980 /* Probe the status block */
1981 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1983 /* Probe the read buffer */
1984 ProbeForWrite(Buffer
, Length
, 1);
1986 /* Check if we got a byte offset */
1989 /* Capture and probe it */
1990 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1993 /* Capture and probe the key */
1994 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
1996 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1998 /* Get the exception code */
1999 Status
= _SEH2_GetExceptionCode();
2003 /* Check for probe failure */
2004 if (!NT_SUCCESS(Status
)) return Status
;
2008 /* Kernel mode: capture directly */
2009 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2010 if (Key
) CapturedKey
= *Key
;
2013 /* Get File Object */
2014 Status
= ObReferenceObjectByHandle(FileHandle
,
2018 (PVOID
*)&FileObject
,
2020 if (!NT_SUCCESS(Status
)) return Status
;
2022 /* Check for event */
2026 Status
= ObReferenceObjectByHandle(Event
,
2030 (PVOID
*)&EventObject
,
2032 if (!NT_SUCCESS(Status
))
2035 ObDereferenceObject(FileObject
);
2039 /* Otherwise reset the event */
2040 KeClearEvent(EventObject
);
2043 /* Check if we should use Sync IO or not */
2044 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2046 /* Lock the file object */
2047 IopLockFileObject(FileObject
);
2049 /* Check if we don't have a byte offset avilable */
2050 if (!(ByteOffset
) ||
2051 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2052 (CapturedByteOffset
.u
.HighPart
== -1)))
2054 /* Use the Current Byte Offset instead */
2055 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2058 /* Remember we are sync */
2061 else if (!(ByteOffset
) &&
2062 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2064 /* Otherwise, this was async I/O without a byte offset, so fail */
2065 if (EventObject
) ObDereferenceObject(EventObject
);
2066 ObDereferenceObject(FileObject
);
2067 return STATUS_INVALID_PARAMETER
;
2070 /* Get the device object */
2071 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2073 /* Clear the File Object's event */
2074 KeClearEvent(&FileObject
->Event
);
2076 /* Allocate the IRP */
2077 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2078 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2081 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2082 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2083 Irp
->RequestorMode
= PreviousMode
;
2084 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2085 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2086 Irp
->UserIosb
= IoStatusBlock
;
2087 Irp
->UserEvent
= EventObject
;
2088 Irp
->PendingReturned
= FALSE
;
2089 Irp
->Cancel
= FALSE
;
2090 Irp
->CancelRoutine
= NULL
;
2091 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2092 Irp
->MdlAddress
= NULL
;
2094 /* Set the Stack Data */
2095 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2096 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2097 StackPtr
->FileObject
= FileObject
;
2098 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2099 StackPtr
->Parameters
.Read
.Length
= Length
;
2100 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2102 /* Check if this is buffered I/O */
2103 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2105 /* Check if we have a buffer length */
2111 /* Allocate a buffer */
2112 Irp
->AssociatedIrp
.SystemBuffer
=
2113 ExAllocatePoolWithTag(NonPagedPool
,
2117 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2119 /* Allocating failed, clean up */
2120 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2121 Status
= _SEH2_GetExceptionCode();
2124 if (!NT_SUCCESS(Status
)) return Status
;
2126 /* Set the buffer and flags */
2127 Irp
->UserBuffer
= Buffer
;
2128 Irp
->Flags
= (IRP_BUFFERED_IO
|
2129 IRP_DEALLOCATE_BUFFER
|
2130 IRP_INPUT_OPERATION
);
2134 /* Not reading anything */
2135 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2138 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2140 /* Check if we have a buffer length */
2145 /* Allocate an MDL */
2146 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2147 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2149 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2151 /* Allocating failed, clean up */
2152 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2153 Status
= _SEH2_GetExceptionCode();
2154 _SEH2_YIELD(return Status
);
2160 /* No allocation flags */
2165 /* No allocation flags, and use the buffer directly */
2167 Irp
->UserBuffer
= Buffer
;
2170 /* Now set the deferred read flags */
2171 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2173 /* FIXME: VFAT SUCKS */
2174 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2177 /* Perform the call */
2178 return IopPerformSynchronousRequest(DeviceObject
,
2192 NtReadFileScatter(IN HANDLE FileHandle
,
2193 IN HANDLE Event OPTIONAL
,
2194 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2195 IN PVOID UserApcContext OPTIONAL
,
2196 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2197 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2198 IN ULONG BufferLength
,
2199 IN PLARGE_INTEGER ByteOffset
,
2200 IN PULONG Key OPTIONAL
)
2203 return STATUS_NOT_IMPLEMENTED
;
2211 NtSetEaFile(IN HANDLE FileHandle
,
2212 IN PIO_STATUS_BLOCK IoStatusBlock
,
2214 IN ULONG EaBufferSize
)
2217 return STATUS_NOT_IMPLEMENTED
;
2225 NtSetInformationFile(IN HANDLE FileHandle
,
2226 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2227 IN PVOID FileInformation
,
2229 IN FILE_INFORMATION_CLASS FileInformationClass
)
2231 PFILE_OBJECT FileObject
;
2232 NTSTATUS Status
= STATUS_SUCCESS
;
2234 PDEVICE_OBJECT DeviceObject
;
2235 PIO_STACK_LOCATION StackPtr
;
2236 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2237 PKEVENT Event
= NULL
;
2238 BOOLEAN LocalEvent
= FALSE
;
2239 PKNORMAL_ROUTINE NormalRoutine
;
2240 PVOID NormalContext
;
2242 IO_STATUS_BLOCK KernelIosb
;
2244 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2245 PIO_COMPLETION_CONTEXT Context
;
2246 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2248 /* Check if we're called from user mode */
2249 if (PreviousMode
!= KernelMode
)
2251 /* Validate the information class */
2252 if ((FileInformationClass
>= FileMaximumInformation
) ||
2253 !(IopSetOperationLength
[FileInformationClass
]))
2256 return STATUS_INVALID_INFO_CLASS
;
2259 /* Validate the length */
2260 if (Length
< IopSetOperationLength
[FileInformationClass
])
2262 /* Invalid length */
2263 return STATUS_INFO_LENGTH_MISMATCH
;
2266 /* Enter SEH for probing */
2269 /* Probe the I/O Status block */
2270 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2272 /* Probe the information */
2273 ProbeForRead(FileInformation
,
2275 (Length
== sizeof(BOOLEAN
)) ?
2276 sizeof(BOOLEAN
) : sizeof(ULONG
));
2278 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2280 /* Get the exception code */
2281 Status
= _SEH2_GetExceptionCode();
2285 /* Check if probing failed */
2286 if (!NT_SUCCESS(Status
)) return Status
;
2290 /* Validate the information class */
2291 if ((FileInformationClass
>= FileMaximumInformation
) ||
2292 !(IopSetOperationLength
[FileInformationClass
]))
2295 return STATUS_INVALID_INFO_CLASS
;
2298 /* Validate the length */
2299 if (Length
< IopSetOperationLength
[FileInformationClass
])
2301 /* Invalid length */
2302 return STATUS_INFO_LENGTH_MISMATCH
;
2306 /* Reference the Handle */
2307 Status
= ObReferenceObjectByHandle(FileHandle
,
2308 IopSetOperationAccess
2309 [FileInformationClass
],
2312 (PVOID
*)&FileObject
,
2314 if (!NT_SUCCESS(Status
)) return Status
;
2316 /* Check if this is a direct open or not */
2317 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2319 /* Get the device object */
2320 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2324 /* Get the device object */
2325 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2328 /* Check if this is a file that was opened for Synch I/O */
2329 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2332 IopLockFileObject(FileObject
);
2334 /* Check if the caller just wants the position */
2335 if (FileInformationClass
== FilePositionInformation
)
2337 /* Protect write in SEH */
2340 /* Write the offset */
2341 FileObject
->CurrentByteOffset
=
2342 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2345 /* Fill out the I/O Status Block */
2346 IoStatusBlock
->Information
= 0;
2347 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2349 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2351 /* Get the exception code */
2352 Status
= _SEH2_GetExceptionCode();
2356 /* Release the file lock, dereference the file and return */
2357 IopUnlockFileObject(FileObject
);
2358 ObDereferenceObject(FileObject
);
2364 /* Use local event */
2365 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2366 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2370 /* Clear the File Object event */
2371 KeClearEvent(&FileObject
->Event
);
2373 /* Allocate the IRP */
2374 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2375 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2378 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2379 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2380 Irp
->RequestorMode
= PreviousMode
;
2381 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2382 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2383 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2384 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2385 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2386 Irp
->MdlAddress
= NULL
;
2387 Irp
->UserBuffer
= FileInformation
;
2389 /* Set the Stack Data */
2390 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2391 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2392 StackPtr
->FileObject
= FileObject
;
2397 /* Allocate a buffer */
2398 Irp
->AssociatedIrp
.SystemBuffer
=
2399 ExAllocatePoolWithTag(NonPagedPool
,
2403 /* Copy the data into it */
2404 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2408 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2410 /* Allocating failed, clean up */
2411 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2412 Status
= _SEH2_GetExceptionCode();
2415 if (!NT_SUCCESS(Status
)) return Status
;
2418 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2419 IRP_DEALLOCATE_BUFFER
|
2420 IRP_DEFER_IO_COMPLETION
);
2422 /* Set the Parameters */
2423 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2424 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2427 IopQueueIrpToThread(Irp
);
2429 /* Update operation counts */
2430 IopUpdateOperationCount(IopOtherTransfer
);
2432 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2433 /* Handle IO Completion Port quickly */
2434 if (FileInformationClass
== FileCompletionInformation
)
2436 /* Check if the file object already has a completion port */
2437 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2438 (FileObject
->CompletionContext
))
2441 Status
= STATUS_INVALID_PARAMETER
;
2445 /* Reference the Port */
2446 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2447 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2448 IO_COMPLETION_MODIFY_STATE
,
2453 if (NT_SUCCESS(Status
))
2455 /* Allocate the Context */
2456 Context
= ExAllocatePoolWithTag(PagedPool
,
2457 sizeof(IO_COMPLETION_CONTEXT
),
2462 Context
->Key
= CompletionInfo
->Key
;
2463 Context
->Port
= Queue
;
2464 if (InterlockedCompareExchangePointer(&FileObject
->
2470 * Someone else set the completion port in the
2471 * meanwhile, so dereference the port and fail.
2473 ExFreePool(Context
);
2474 ObDereferenceObject(Queue
);
2475 Status
= STATUS_INVALID_PARAMETER
;
2480 /* Dereference the Port now */
2481 ObDereferenceObject(Queue
);
2482 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2487 /* Set the IRP Status */
2488 Irp
->IoStatus
.Status
= Status
;
2489 Irp
->IoStatus
.Information
= 0;
2493 /* Call the Driver */
2494 Status
= IoCallDriver(DeviceObject
, Irp
);
2497 /* Check if we're waiting for the IRP to complete */
2498 if (Status
== STATUS_PENDING
)
2500 /* Check if this was async I/O */
2503 /* Then to a non-alertable wait */
2504 Status
= KeWaitForSingleObject(Event
,
2509 if (Status
== STATUS_USER_APC
)
2511 /* Abort the request */
2512 IopAbortInterruptedIrp(Event
, Irp
);
2515 /* Set the final status */
2516 Status
= KernelIosb
.Status
;
2518 /* Enter SEH to write the IOSB back */
2521 /* Write it back to the caller */
2522 *IoStatusBlock
= KernelIosb
;
2524 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2526 /* Get the exception code */
2527 Status
= _SEH2_GetExceptionCode();
2531 /* Free the event */
2536 /* Wait for the IRP */
2537 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2540 FileObject
->Flags
& FO_ALERTABLE_IO
,
2542 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2544 /* Abort the request */
2545 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2548 /* Set the final status */
2549 Status
= FileObject
->FinalStatus
;
2551 /* Release the file lock */
2552 IopUnlockFileObject(FileObject
);
2557 /* Free the event if we had one */
2560 /* Clear it in the IRP for completion */
2561 Irp
->UserEvent
= NULL
;
2565 /* Set the caller IOSB */
2566 Irp
->UserIosb
= IoStatusBlock
;
2568 /* The IRP wasn't completed, complete it ourselves */
2569 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2570 IopCompleteRequest(&Irp
->Tail
.Apc
,
2573 (PVOID
*)&FileObject
,
2575 KeLowerIrql(OldIrql
);
2577 /* Release the file object if we had locked it*/
2578 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2581 /* Return the Status */
2590 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2591 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2593 IN ULONG BufferLength
)
2596 return STATUS_NOT_IMPLEMENTED
;
2604 NtUnlockFile(IN HANDLE FileHandle
,
2605 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2606 IN PLARGE_INTEGER ByteOffset
,
2607 IN PLARGE_INTEGER Length
,
2608 IN ULONG Key OPTIONAL
)
2610 PFILE_OBJECT FileObject
;
2611 PLARGE_INTEGER LocalLength
= NULL
;
2613 PIO_STACK_LOCATION StackPtr
;
2614 PDEVICE_OBJECT DeviceObject
;
2615 PKEVENT Event
= NULL
;
2616 BOOLEAN LocalEvent
= FALSE
;
2617 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2618 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2619 NTSTATUS Status
= STATUS_SUCCESS
;
2620 OBJECT_HANDLE_INFORMATION HandleInformation
;
2621 IO_STATUS_BLOCK KernelIosb
;
2623 CapturedByteOffset
.QuadPart
= 0;
2624 CapturedLength
.QuadPart
= 0;
2625 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2627 /* Get File Object */
2628 Status
= ObReferenceObjectByHandle(FileHandle
,
2632 (PVOID
*)&FileObject
,
2633 &HandleInformation
);
2634 if (!NT_SUCCESS(Status
)) return Status
;
2636 /* Check if we're called from user mode */
2637 if (PreviousMode
!= KernelMode
)
2639 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2640 if (!(HandleInformation
.GrantedAccess
&
2641 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2643 ObDereferenceObject(FileObject
);
2644 return STATUS_ACCESS_DENIED
;
2647 /* Enter SEH for probing */
2650 /* Probe the I/O Status block */
2651 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2653 /* Probe and capture the large integers */
2654 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2655 CapturedLength
= ProbeForReadLargeInteger(Length
);
2657 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2659 /* Get the exception code */
2660 Status
= _SEH2_GetExceptionCode();
2664 /* Check if probing failed */
2665 if (!NT_SUCCESS(Status
))
2667 /* Dereference the object and return exception code */
2668 ObDereferenceObject(FileObject
);
2674 /* Otherwise, capture them directly */
2675 CapturedByteOffset
= *ByteOffset
;
2676 CapturedLength
= *Length
;
2679 /* Check if this is a direct open or not */
2680 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2682 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2686 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2689 /* Check if we should use Sync IO or not */
2690 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2693 IopLockFileObject(FileObject
);
2697 /* Use local event */
2698 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2699 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2703 /* Clear File Object event */
2704 KeClearEvent(&FileObject
->Event
);
2706 /* Allocate the IRP */
2707 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2708 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2710 /* Set up the IRP */
2711 Irp
->RequestorMode
= PreviousMode
;
2712 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2713 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2714 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2715 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2716 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2717 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2719 /* Set up Stack Data */
2720 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2721 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2722 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2723 StackPtr
->FileObject
= FileObject
;
2728 /* Allocate a buffer */
2729 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2730 sizeof(LARGE_INTEGER
),
2733 /* Set the length */
2734 *LocalLength
= CapturedLength
;
2735 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
2736 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2738 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2740 /* Allocating failed, clean up */
2741 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2742 if (LocalLength
) ExFreePool(LocalLength
);
2744 /* Get exception status */
2745 Status
= _SEH2_GetExceptionCode();
2748 if (!NT_SUCCESS(Status
)) return Status
;
2750 /* Set Parameters */
2751 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
2752 StackPtr
->Parameters
.LockControl
.Key
= Key
;
2754 /* Call the Driver */
2755 Status
= IopPerformSynchronousRequest(DeviceObject
,
2763 /* Check if this was async I/O */
2766 /* It was, finalize this request */
2767 Status
= IopFinalizeAsynchronousIo(Status
,
2784 NtWriteFile(IN HANDLE FileHandle
,
2785 IN HANDLE Event OPTIONAL
,
2786 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2787 IN PVOID ApcContext OPTIONAL
,
2788 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2791 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2792 IN PULONG Key OPTIONAL
)
2794 NTSTATUS Status
= STATUS_SUCCESS
;
2795 PFILE_OBJECT FileObject
;
2797 PDEVICE_OBJECT DeviceObject
;
2798 PIO_STACK_LOCATION StackPtr
;
2799 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2800 PKEVENT EventObject
= NULL
;
2801 LARGE_INTEGER CapturedByteOffset
;
2802 ULONG CapturedKey
= 0;
2803 BOOLEAN Synchronous
= FALSE
;
2805 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
2807 CapturedByteOffset
.QuadPart
= 0;
2808 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2810 /* Get File Object */
2811 Status
= ObReferenceObjectByHandle(FileHandle
,
2815 (PVOID
*)&FileObject
,
2817 if (!NT_SUCCESS(Status
)) return Status
;
2819 /* Validate User-Mode Buffers */
2820 if(PreviousMode
!= KernelMode
)
2825 * Check if the handle has either FILE_WRITE_DATA or
2826 * FILE_APPEND_DATA granted. However, if this is a named pipe,
2827 * make sure we don't ask for FILE_APPEND_DATA as it interferes
2828 * with the FILE_CREATE_PIPE_INSTANCE access right!
2830 if (!(ObjectHandleInfo
.GrantedAccess
&
2831 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
2832 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
2835 ObDereferenceObject(FileObject
);
2836 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
2839 /* Probe the status block */
2840 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2842 /* Probe the read buffer */
2843 ProbeForRead(Buffer
, Length
, 1);
2845 /* Check if we got a byte offset */
2848 /* Capture and probe it */
2849 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2852 /* Capture and probe the key */
2853 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2855 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2857 /* Get the exception code */
2858 Status
= _SEH2_GetExceptionCode();
2862 /* Check for probe failure */
2863 if (!NT_SUCCESS(Status
)) return Status
;
2867 /* Kernel mode: capture directly */
2868 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2869 if (Key
) CapturedKey
= *Key
;
2872 /* Check if this is an append operation */
2873 if ((ObjectHandleInfo
.GrantedAccess
&
2874 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
2876 /* Give the drivers something to understand */
2877 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
2878 CapturedByteOffset
.u
.HighPart
= -1;
2881 /* Check for event */
2885 Status
= ObReferenceObjectByHandle(Event
,
2889 (PVOID
*)&EventObject
,
2891 if (!NT_SUCCESS(Status
))
2894 ObDereferenceObject(FileObject
);
2898 /* Otherwise reset the event */
2899 KeClearEvent(EventObject
);
2902 /* Check if we should use Sync IO or not */
2903 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2905 /* Lock the file object */
2906 IopLockFileObject(FileObject
);
2908 /* Check if we don't have a byte offset avilable */
2909 if (!(ByteOffset
) ||
2910 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2911 (CapturedByteOffset
.u
.HighPart
== -1)))
2913 /* Use the Current Byte Offset instead */
2914 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2917 /* Remember we are sync */
2920 else if (!(ByteOffset
) &&
2921 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2923 /* Otherwise, this was async I/O without a byte offset, so fail */
2924 if (EventObject
) ObDereferenceObject(EventObject
);
2925 ObDereferenceObject(FileObject
);
2926 return STATUS_INVALID_PARAMETER
;
2929 /* Get the device object */
2930 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2932 /* Clear the File Object's event */
2933 KeClearEvent(&FileObject
->Event
);
2935 /* Allocate the IRP */
2936 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2937 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2940 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2941 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2942 Irp
->RequestorMode
= PreviousMode
;
2943 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2944 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2945 Irp
->UserIosb
= IoStatusBlock
;
2946 Irp
->UserEvent
= EventObject
;
2947 Irp
->PendingReturned
= FALSE
;
2948 Irp
->Cancel
= FALSE
;
2949 Irp
->CancelRoutine
= NULL
;
2950 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2951 Irp
->MdlAddress
= NULL
;
2953 /* Set the Stack Data */
2954 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2955 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
2956 StackPtr
->FileObject
= FileObject
;
2957 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
2958 SL_WRITE_THROUGH
: 0;
2959 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
2960 StackPtr
->Parameters
.Write
.Length
= Length
;
2961 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
2963 /* Check if this is buffered I/O */
2964 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2966 /* Check if we have a buffer length */
2972 /* Allocate a buffer */
2973 Irp
->AssociatedIrp
.SystemBuffer
=
2974 ExAllocatePoolWithTag(NonPagedPool
,
2978 /* Copy the data into it */
2979 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
2981 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2983 /* Allocating failed, clean up */
2984 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2985 Status
= _SEH2_GetExceptionCode();
2986 _SEH2_YIELD(return Status
);
2991 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
2995 /* Not writing anything */
2996 Irp
->Flags
= IRP_BUFFERED_IO
;
2999 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3001 /* Check if we have a buffer length */
3006 /* Allocate an MDL */
3007 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3008 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3010 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3012 /* Allocating failed, clean up */
3013 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3014 Status
= _SEH2_GetExceptionCode();
3015 _SEH2_YIELD(return Status
);
3020 /* No allocation flags */
3025 /* No allocation flags, and use the buffer directly */
3027 Irp
->UserBuffer
= Buffer
;
3030 /* Now set the deferred read flags */
3031 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3033 /* FIXME: VFAT SUCKS */
3034 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3037 /* Perform the call */
3038 return IopPerformSynchronousRequest(DeviceObject
,
3049 NtWriteFileGather(IN HANDLE FileHandle
,
3050 IN HANDLE Event OPTIONAL
,
3051 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3052 IN PVOID UserApcContext OPTIONAL
,
3053 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3054 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3055 IN ULONG BufferLength
,
3056 IN PLARGE_INTEGER ByteOffset
,
3057 IN PULONG Key OPTIONAL
)
3060 return STATUS_NOT_IMPLEMENTED
;
3068 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3069 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3070 OUT PVOID FsInformation
,
3072 IN FS_INFORMATION_CLASS FsInformationClass
)
3074 PFILE_OBJECT FileObject
;
3076 PIO_STACK_LOCATION StackPtr
;
3077 PDEVICE_OBJECT DeviceObject
;
3078 PKEVENT Event
= NULL
;
3079 BOOLEAN LocalEvent
= FALSE
;
3080 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3081 NTSTATUS Status
= STATUS_SUCCESS
;
3082 IO_STATUS_BLOCK KernelIosb
;
3084 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3086 /* Check if we're called from user mode */
3087 if (PreviousMode
!= KernelMode
)
3089 /* Validate the information class */
3090 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3091 !(IopQueryFsOperationLength
[FsInformationClass
]))
3094 return STATUS_INVALID_INFO_CLASS
;
3097 /* Validate the length */
3098 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3100 /* Invalid length */
3101 return STATUS_INFO_LENGTH_MISMATCH
;
3104 /* Enter SEH for probing */
3107 /* Probe the I/O Status block */
3108 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3110 /* Probe the information */
3111 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3113 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3115 /* Get the exception code */
3116 Status
= _SEH2_GetExceptionCode();
3119 if (!NT_SUCCESS(Status
)) return Status
;
3122 /* Get File Object */
3123 Status
= ObReferenceObjectByHandle(FileHandle
,
3124 IopQueryFsOperationAccess
3125 [FsInformationClass
],
3128 (PVOID
*)&FileObject
,
3130 if (!NT_SUCCESS(Status
)) return Status
;
3132 /* Check if we should use Sync IO or not */
3133 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3136 IopLockFileObject(FileObject
);
3140 /* Use local event */
3141 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3142 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3146 /* Get the device object */
3147 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3149 /* Clear File Object event */
3150 KeClearEvent(&FileObject
->Event
);
3152 /* Allocate the IRP */
3153 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3154 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3156 /* Set up the IRP */
3157 Irp
->RequestorMode
= PreviousMode
;
3158 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3159 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3160 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3161 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3162 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3163 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3164 Irp
->UserBuffer
= FsInformation
;
3165 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3166 Irp
->MdlAddress
= NULL
;
3168 /* Set up Stack Data */
3169 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3170 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3171 StackPtr
->FileObject
= FileObject
;
3176 /* Allocate a buffer */
3177 Irp
->AssociatedIrp
.SystemBuffer
=
3178 ExAllocatePoolWithTag(NonPagedPool
,
3182 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3184 /* Allocating failed, clean up */
3185 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3186 Status
= _SEH2_GetExceptionCode();
3189 if (!NT_SUCCESS(Status
)) return Status
;
3191 /* Set the flags for this buffered + deferred I/O */
3192 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3193 IRP_DEALLOCATE_BUFFER
|
3194 IRP_INPUT_OPERATION
|
3195 IRP_DEFER_IO_COMPLETION
);
3197 /* Set Parameters */
3198 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3199 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3201 /* Call the Driver */
3202 Status
= IopPerformSynchronousRequest(DeviceObject
,
3210 /* Check if this was async I/O */
3213 /* It was, finalize this request */
3214 Status
= IopFinalizeAsynchronousIo(Status
,
3231 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3232 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3233 IN PVOID FsInformation
,
3235 IN FS_INFORMATION_CLASS FsInformationClass
)
3237 PFILE_OBJECT FileObject
;
3239 PIO_STACK_LOCATION StackPtr
;
3240 PDEVICE_OBJECT DeviceObject
;
3241 PKEVENT Event
= NULL
;
3242 BOOLEAN LocalEvent
= FALSE
;
3243 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3244 NTSTATUS Status
= STATUS_SUCCESS
;
3245 IO_STATUS_BLOCK KernelIosb
;
3247 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3249 /* Check if we're called from user mode */
3250 if (PreviousMode
!= KernelMode
)
3252 /* Validate the information class */
3253 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3254 !(IopSetFsOperationLength
[FsInformationClass
]))
3257 return STATUS_INVALID_INFO_CLASS
;
3260 /* Validate the length */
3261 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3263 /* Invalid length */
3264 return STATUS_INFO_LENGTH_MISMATCH
;
3267 /* Enter SEH for probing */
3270 /* Probe the I/O Status block */
3271 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3273 /* Probe the information */
3274 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3276 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3278 /* Get the exception code */
3279 Status
= _SEH2_GetExceptionCode();
3282 if (!NT_SUCCESS(Status
)) return Status
;
3285 /* Get File Object */
3286 Status
= ObReferenceObjectByHandle(FileHandle
,
3287 IopSetFsOperationAccess
3288 [FsInformationClass
],
3291 (PVOID
*)&FileObject
,
3293 if (!NT_SUCCESS(Status
)) return Status
;
3295 /* Check if we should use Sync IO or not */
3296 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3299 IopLockFileObject(FileObject
);
3303 /* Use local event */
3304 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3305 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3309 /* Get the device object */
3310 Status
= IoGetRelatedTargetDevice(FileObject
, &DeviceObject
);
3311 if (!NT_SUCCESS(Status
)) return Status
;
3313 /* Clear File Object event */
3314 KeClearEvent(&FileObject
->Event
);
3316 /* Allocate the IRP */
3317 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3318 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3320 /* Set up the IRP */
3321 Irp
->RequestorMode
= PreviousMode
;
3322 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3323 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3324 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3325 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3326 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3327 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3328 Irp
->UserBuffer
= FsInformation
;
3329 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3330 Irp
->MdlAddress
= NULL
;
3332 /* Set up Stack Data */
3333 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3334 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3335 StackPtr
->FileObject
= FileObject
;
3340 /* Allocate a buffer */
3341 Irp
->AssociatedIrp
.SystemBuffer
=
3342 ExAllocatePoolWithTag(NonPagedPool
,
3346 /* Copy the data into it */
3347 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3349 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3351 /* Allocating failed, clean up */
3352 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3353 Status
= _SEH2_GetExceptionCode();
3356 if (!NT_SUCCESS(Status
)) return Status
;
3358 /* Set the flags for this buffered + deferred I/O */
3359 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3361 /* Set Parameters */
3362 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3363 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3365 /* Call the Driver */
3366 Status
= IopPerformSynchronousRequest(DeviceObject
,
3374 /* Check if this was async I/O */
3377 /* It was, finalize this request */
3378 Status
= IopFinalizeAsynchronousIo(Status
,
3395 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3398 return STATUS_NOT_IMPLEMENTED
;
3406 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3409 return STATUS_NOT_IMPLEMENTED
;