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
;
2247 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2249 /* Check if we're called from user mode */
2250 if (PreviousMode
!= KernelMode
)
2252 /* Validate the information class */
2253 if ((FileInformationClass
>= FileMaximumInformation
) ||
2254 !(IopSetOperationLength
[FileInformationClass
]))
2257 return STATUS_INVALID_INFO_CLASS
;
2260 /* Validate the length */
2261 if (Length
< IopSetOperationLength
[FileInformationClass
])
2263 /* Invalid length */
2264 return STATUS_INFO_LENGTH_MISMATCH
;
2267 /* Enter SEH for probing */
2270 /* Probe the I/O Status block */
2271 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2273 /* Probe the information */
2274 ProbeForRead(FileInformation
,
2276 (Length
== sizeof(BOOLEAN
)) ?
2277 sizeof(BOOLEAN
) : sizeof(ULONG
));
2279 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2281 /* Get the exception code */
2282 Status
= _SEH2_GetExceptionCode();
2286 /* Check if probing failed */
2287 if (!NT_SUCCESS(Status
)) return Status
;
2291 /* Validate the information class */
2292 if ((FileInformationClass
>= FileMaximumInformation
) ||
2293 !(IopSetOperationLength
[FileInformationClass
]))
2296 return STATUS_INVALID_INFO_CLASS
;
2299 /* Validate the length */
2300 if (Length
< IopSetOperationLength
[FileInformationClass
])
2302 /* Invalid length */
2303 return STATUS_INFO_LENGTH_MISMATCH
;
2307 /* Reference the Handle */
2308 Status
= ObReferenceObjectByHandle(FileHandle
,
2309 IopSetOperationAccess
2310 [FileInformationClass
],
2313 (PVOID
*)&FileObject
,
2315 if (!NT_SUCCESS(Status
)) return Status
;
2317 /* Check if this is a direct open or not */
2318 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2320 /* Get the device object */
2321 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2325 /* Get the device object */
2326 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2329 /* Check if this is a file that was opened for Synch I/O */
2330 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2333 IopLockFileObject(FileObject
);
2335 /* Check if the caller just wants the position */
2336 if (FileInformationClass
== FilePositionInformation
)
2338 /* Protect write in SEH */
2341 /* Write the offset */
2342 FileObject
->CurrentByteOffset
=
2343 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2346 /* Fill out the I/O Status Block */
2347 IoStatusBlock
->Information
= 0;
2348 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2350 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2352 /* Get the exception code */
2353 Status
= _SEH2_GetExceptionCode();
2357 /* Update transfer count */
2358 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2360 /* Release the file lock, dereference the file and return */
2361 IopUnlockFileObject(FileObject
);
2362 ObDereferenceObject(FileObject
);
2368 /* Use local event */
2369 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2372 ObDereferenceObject(FileObject
);
2373 return STATUS_INSUFFICIENT_RESOURCES
;
2376 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2380 /* Clear the File Object event */
2381 KeClearEvent(&FileObject
->Event
);
2383 /* Allocate the IRP */
2384 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2385 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2388 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2389 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2390 Irp
->RequestorMode
= PreviousMode
;
2391 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2392 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2393 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2394 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2395 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2396 Irp
->MdlAddress
= NULL
;
2397 Irp
->UserBuffer
= FileInformation
;
2399 /* Set the Stack Data */
2400 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2401 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2402 StackPtr
->FileObject
= FileObject
;
2407 /* Allocate a buffer */
2408 Irp
->AssociatedIrp
.SystemBuffer
=
2409 ExAllocatePoolWithTag(NonPagedPool
,
2413 /* Copy the data into it */
2414 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2418 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2420 /* Allocating failed, clean up */
2421 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2422 Status
= _SEH2_GetExceptionCode();
2425 if (!NT_SUCCESS(Status
)) return Status
;
2428 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2429 IRP_DEALLOCATE_BUFFER
|
2430 IRP_DEFER_IO_COMPLETION
);
2432 /* Set the Parameters */
2433 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2434 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2437 IopQueueIrpToThread(Irp
);
2439 /* Update operation counts */
2440 IopUpdateOperationCount(IopOtherTransfer
);
2442 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2443 /* Handle IO Completion Port quickly */
2444 if (FileInformationClass
== FileCompletionInformation
)
2446 /* Check if the file object already has a completion port */
2447 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2448 (FileObject
->CompletionContext
))
2451 Status
= STATUS_INVALID_PARAMETER
;
2455 /* Reference the Port */
2456 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2457 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2458 IO_COMPLETION_MODIFY_STATE
,
2463 if (NT_SUCCESS(Status
))
2465 /* Allocate the Context */
2466 Context
= ExAllocatePoolWithTag(PagedPool
,
2467 sizeof(IO_COMPLETION_CONTEXT
),
2472 Context
->Key
= CompletionInfo
->Key
;
2473 Context
->Port
= Queue
;
2474 if (InterlockedCompareExchangePointer(&FileObject
->
2480 * Someone else set the completion port in the
2481 * meanwhile, so dereference the port and fail.
2483 ExFreePool(Context
);
2484 ObDereferenceObject(Queue
);
2485 Status
= STATUS_INVALID_PARAMETER
;
2490 /* Dereference the Port now */
2491 ObDereferenceObject(Queue
);
2492 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2497 /* Set the IRP Status */
2498 Irp
->IoStatus
.Status
= Status
;
2499 Irp
->IoStatus
.Information
= 0;
2503 /* Call the Driver */
2504 Status
= IoCallDriver(DeviceObject
, Irp
);
2507 /* Check if we're waiting for the IRP to complete */
2508 if (Status
== STATUS_PENDING
)
2510 /* Check if this was async I/O */
2513 /* Then to a non-alertable wait */
2514 Status
= KeWaitForSingleObject(Event
,
2519 if (Status
== STATUS_USER_APC
)
2521 /* Abort the request */
2522 IopAbortInterruptedIrp(Event
, Irp
);
2525 /* Set the final status */
2526 Status
= KernelIosb
.Status
;
2528 /* Enter SEH to write the IOSB back */
2531 /* Write it back to the caller */
2532 *IoStatusBlock
= KernelIosb
;
2534 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2536 /* Get the exception code */
2537 Status
= _SEH2_GetExceptionCode();
2541 /* Free the event */
2546 /* Wait for the IRP */
2547 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2550 FileObject
->Flags
& FO_ALERTABLE_IO
,
2552 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2554 /* Abort the request */
2555 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2558 /* Set the final status */
2559 Status
= FileObject
->FinalStatus
;
2561 /* Release the file lock */
2562 IopUnlockFileObject(FileObject
);
2567 /* Free the event if we had one */
2570 /* Clear it in the IRP for completion */
2571 Irp
->UserEvent
= NULL
;
2575 /* Set the caller IOSB */
2576 Irp
->UserIosb
= IoStatusBlock
;
2578 /* The IRP wasn't completed, complete it ourselves */
2579 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2580 IopCompleteRequest(&Irp
->Tail
.Apc
,
2583 (PVOID
*)&FileObject
,
2585 KeLowerIrql(OldIrql
);
2587 /* Release the file object if we had locked it*/
2588 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2591 /* Return the Status */
2600 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2601 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2603 IN ULONG BufferLength
)
2606 return STATUS_NOT_IMPLEMENTED
;
2614 NtUnlockFile(IN HANDLE FileHandle
,
2615 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2616 IN PLARGE_INTEGER ByteOffset
,
2617 IN PLARGE_INTEGER Length
,
2618 IN ULONG Key OPTIONAL
)
2620 PFILE_OBJECT FileObject
;
2621 PLARGE_INTEGER LocalLength
= NULL
;
2623 PIO_STACK_LOCATION StackPtr
;
2624 PDEVICE_OBJECT DeviceObject
;
2625 PKEVENT Event
= NULL
;
2626 BOOLEAN LocalEvent
= FALSE
;
2627 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2628 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2629 NTSTATUS Status
= STATUS_SUCCESS
;
2630 OBJECT_HANDLE_INFORMATION HandleInformation
;
2631 IO_STATUS_BLOCK KernelIosb
;
2633 CapturedByteOffset
.QuadPart
= 0;
2634 CapturedLength
.QuadPart
= 0;
2635 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2637 /* Get File Object */
2638 Status
= ObReferenceObjectByHandle(FileHandle
,
2642 (PVOID
*)&FileObject
,
2643 &HandleInformation
);
2644 if (!NT_SUCCESS(Status
)) return Status
;
2646 /* Check if we're called from user mode */
2647 if (PreviousMode
!= KernelMode
)
2649 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2650 if (!(HandleInformation
.GrantedAccess
&
2651 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2653 ObDereferenceObject(FileObject
);
2654 return STATUS_ACCESS_DENIED
;
2657 /* Enter SEH for probing */
2660 /* Probe the I/O Status block */
2661 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2663 /* Probe and capture the large integers */
2664 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2665 CapturedLength
= ProbeForReadLargeInteger(Length
);
2667 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2669 /* Get the exception code */
2670 Status
= _SEH2_GetExceptionCode();
2674 /* Check if probing failed */
2675 if (!NT_SUCCESS(Status
))
2677 /* Dereference the object and return exception code */
2678 ObDereferenceObject(FileObject
);
2684 /* Otherwise, capture them directly */
2685 CapturedByteOffset
= *ByteOffset
;
2686 CapturedLength
= *Length
;
2689 /* Check if this is a direct open or not */
2690 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2692 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2696 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2699 /* Check if we should use Sync IO or not */
2700 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2703 IopLockFileObject(FileObject
);
2707 /* Use local event */
2708 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2709 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2713 /* Clear File Object event */
2714 KeClearEvent(&FileObject
->Event
);
2716 /* Allocate the IRP */
2717 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2718 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2720 /* Set up the IRP */
2721 Irp
->RequestorMode
= PreviousMode
;
2722 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2723 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2724 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2725 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2726 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2727 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2729 /* Set up Stack Data */
2730 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2731 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2732 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2733 StackPtr
->FileObject
= FileObject
;
2738 /* Allocate a buffer */
2739 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2740 sizeof(LARGE_INTEGER
),
2743 /* Set the length */
2744 *LocalLength
= CapturedLength
;
2745 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
2746 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2748 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2750 /* Allocating failed, clean up */
2751 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2752 if (LocalLength
) ExFreePool(LocalLength
);
2754 /* Get exception status */
2755 Status
= _SEH2_GetExceptionCode();
2758 if (!NT_SUCCESS(Status
)) return Status
;
2760 /* Set Parameters */
2761 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
2762 StackPtr
->Parameters
.LockControl
.Key
= Key
;
2764 /* Call the Driver */
2765 Status
= IopPerformSynchronousRequest(DeviceObject
,
2773 /* Check if this was async I/O */
2776 /* It was, finalize this request */
2777 Status
= IopFinalizeAsynchronousIo(Status
,
2794 NtWriteFile(IN HANDLE FileHandle
,
2795 IN HANDLE Event OPTIONAL
,
2796 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2797 IN PVOID ApcContext OPTIONAL
,
2798 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2801 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2802 IN PULONG Key OPTIONAL
)
2804 NTSTATUS Status
= STATUS_SUCCESS
;
2805 PFILE_OBJECT FileObject
;
2807 PDEVICE_OBJECT DeviceObject
;
2808 PIO_STACK_LOCATION StackPtr
;
2809 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2810 PKEVENT EventObject
= NULL
;
2811 LARGE_INTEGER CapturedByteOffset
;
2812 ULONG CapturedKey
= 0;
2813 BOOLEAN Synchronous
= FALSE
;
2815 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
2817 CapturedByteOffset
.QuadPart
= 0;
2818 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2820 /* Get File Object */
2821 Status
= ObReferenceObjectByHandle(FileHandle
,
2825 (PVOID
*)&FileObject
,
2827 if (!NT_SUCCESS(Status
)) return Status
;
2829 /* Validate User-Mode Buffers */
2830 if(PreviousMode
!= KernelMode
)
2835 * Check if the handle has either FILE_WRITE_DATA or
2836 * FILE_APPEND_DATA granted. However, if this is a named pipe,
2837 * make sure we don't ask for FILE_APPEND_DATA as it interferes
2838 * with the FILE_CREATE_PIPE_INSTANCE access right!
2840 if (!(ObjectHandleInfo
.GrantedAccess
&
2841 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
2842 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
2845 ObDereferenceObject(FileObject
);
2846 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
2849 /* Probe the status block */
2850 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2852 /* Probe the read buffer */
2853 ProbeForRead(Buffer
, Length
, 1);
2855 /* Check if we got a byte offset */
2858 /* Capture and probe it */
2859 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2862 /* Capture and probe the key */
2863 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2865 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2867 /* Get the exception code */
2868 Status
= _SEH2_GetExceptionCode();
2872 /* Check for probe failure */
2873 if (!NT_SUCCESS(Status
)) return Status
;
2877 /* Kernel mode: capture directly */
2878 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2879 if (Key
) CapturedKey
= *Key
;
2882 /* Check if this is an append operation */
2883 if ((ObjectHandleInfo
.GrantedAccess
&
2884 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
2886 /* Give the drivers something to understand */
2887 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
2888 CapturedByteOffset
.u
.HighPart
= -1;
2891 /* Check for event */
2895 Status
= ObReferenceObjectByHandle(Event
,
2899 (PVOID
*)&EventObject
,
2901 if (!NT_SUCCESS(Status
))
2904 ObDereferenceObject(FileObject
);
2908 /* Otherwise reset the event */
2909 KeClearEvent(EventObject
);
2912 /* Check if we should use Sync IO or not */
2913 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2915 /* Lock the file object */
2916 IopLockFileObject(FileObject
);
2918 /* Check if we don't have a byte offset avilable */
2919 if (!(ByteOffset
) ||
2920 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2921 (CapturedByteOffset
.u
.HighPart
== -1)))
2923 /* Use the Current Byte Offset instead */
2924 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2927 /* Remember we are sync */
2930 else if (!(ByteOffset
) &&
2931 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2933 /* Otherwise, this was async I/O without a byte offset, so fail */
2934 if (EventObject
) ObDereferenceObject(EventObject
);
2935 ObDereferenceObject(FileObject
);
2936 return STATUS_INVALID_PARAMETER
;
2939 /* Get the device object */
2940 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2942 /* Clear the File Object's event */
2943 KeClearEvent(&FileObject
->Event
);
2945 /* Allocate the IRP */
2946 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2947 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2950 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2951 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2952 Irp
->RequestorMode
= PreviousMode
;
2953 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2954 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2955 Irp
->UserIosb
= IoStatusBlock
;
2956 Irp
->UserEvent
= EventObject
;
2957 Irp
->PendingReturned
= FALSE
;
2958 Irp
->Cancel
= FALSE
;
2959 Irp
->CancelRoutine
= NULL
;
2960 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2961 Irp
->MdlAddress
= NULL
;
2963 /* Set the Stack Data */
2964 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2965 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
2966 StackPtr
->FileObject
= FileObject
;
2967 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
2968 SL_WRITE_THROUGH
: 0;
2969 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
2970 StackPtr
->Parameters
.Write
.Length
= Length
;
2971 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
2973 /* Check if this is buffered I/O */
2974 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2976 /* Check if we have a buffer length */
2982 /* Allocate a buffer */
2983 Irp
->AssociatedIrp
.SystemBuffer
=
2984 ExAllocatePoolWithTag(NonPagedPool
,
2988 /* Copy the data into it */
2989 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
2991 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2993 /* Allocating failed, clean up */
2994 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2995 Status
= _SEH2_GetExceptionCode();
2996 _SEH2_YIELD(return Status
);
3001 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3005 /* Not writing anything */
3006 Irp
->Flags
= IRP_BUFFERED_IO
;
3009 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3011 /* Check if we have a buffer length */
3016 /* Allocate an MDL */
3017 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3018 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3020 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3022 /* Allocating failed, clean up */
3023 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3024 Status
= _SEH2_GetExceptionCode();
3025 _SEH2_YIELD(return Status
);
3030 /* No allocation flags */
3035 /* No allocation flags, and use the buffer directly */
3037 Irp
->UserBuffer
= Buffer
;
3040 /* Now set the deferred read flags */
3041 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3043 /* FIXME: VFAT SUCKS */
3044 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3047 /* Perform the call */
3048 return IopPerformSynchronousRequest(DeviceObject
,
3059 NtWriteFileGather(IN HANDLE FileHandle
,
3060 IN HANDLE Event OPTIONAL
,
3061 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3062 IN PVOID UserApcContext OPTIONAL
,
3063 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3064 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3065 IN ULONG BufferLength
,
3066 IN PLARGE_INTEGER ByteOffset
,
3067 IN PULONG Key OPTIONAL
)
3070 return STATUS_NOT_IMPLEMENTED
;
3078 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3079 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3080 OUT PVOID FsInformation
,
3082 IN FS_INFORMATION_CLASS FsInformationClass
)
3084 PFILE_OBJECT FileObject
;
3086 PIO_STACK_LOCATION StackPtr
;
3087 PDEVICE_OBJECT DeviceObject
;
3088 PKEVENT Event
= NULL
;
3089 BOOLEAN LocalEvent
= FALSE
;
3090 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3091 NTSTATUS Status
= STATUS_SUCCESS
;
3092 IO_STATUS_BLOCK KernelIosb
;
3094 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3096 /* Check if we're called from user mode */
3097 if (PreviousMode
!= KernelMode
)
3099 /* Validate the information class */
3100 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3101 !(IopQueryFsOperationLength
[FsInformationClass
]))
3104 return STATUS_INVALID_INFO_CLASS
;
3107 /* Validate the length */
3108 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3110 /* Invalid length */
3111 return STATUS_INFO_LENGTH_MISMATCH
;
3114 /* Enter SEH for probing */
3117 /* Probe the I/O Status block */
3118 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3120 /* Probe the information */
3121 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3123 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3125 /* Get the exception code */
3126 Status
= _SEH2_GetExceptionCode();
3129 if (!NT_SUCCESS(Status
)) return Status
;
3132 /* Get File Object */
3133 Status
= ObReferenceObjectByHandle(FileHandle
,
3134 IopQueryFsOperationAccess
3135 [FsInformationClass
],
3138 (PVOID
*)&FileObject
,
3140 if (!NT_SUCCESS(Status
)) return Status
;
3142 /* Check if we should use Sync IO or not */
3143 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3146 IopLockFileObject(FileObject
);
3150 /* Use local event */
3151 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3152 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3156 /* Get the device object */
3157 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3159 /* Clear File Object event */
3160 KeClearEvent(&FileObject
->Event
);
3162 /* Allocate the IRP */
3163 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3164 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3166 /* Set up the IRP */
3167 Irp
->RequestorMode
= PreviousMode
;
3168 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3169 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3170 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3171 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3172 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3173 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3174 Irp
->UserBuffer
= FsInformation
;
3175 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3176 Irp
->MdlAddress
= NULL
;
3178 /* Set up Stack Data */
3179 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3180 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3181 StackPtr
->FileObject
= FileObject
;
3186 /* Allocate a buffer */
3187 Irp
->AssociatedIrp
.SystemBuffer
=
3188 ExAllocatePoolWithTag(NonPagedPool
,
3192 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3194 /* Allocating failed, clean up */
3195 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3196 Status
= _SEH2_GetExceptionCode();
3199 if (!NT_SUCCESS(Status
)) return Status
;
3201 /* Set the flags for this buffered + deferred I/O */
3202 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3203 IRP_DEALLOCATE_BUFFER
|
3204 IRP_INPUT_OPERATION
|
3205 IRP_DEFER_IO_COMPLETION
);
3207 /* Set Parameters */
3208 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3209 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3211 /* Call the Driver */
3212 Status
= IopPerformSynchronousRequest(DeviceObject
,
3220 /* Check if this was async I/O */
3223 /* It was, finalize this request */
3224 Status
= IopFinalizeAsynchronousIo(Status
,
3241 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3242 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3243 IN PVOID FsInformation
,
3245 IN FS_INFORMATION_CLASS FsInformationClass
)
3247 PFILE_OBJECT FileObject
;
3249 PIO_STACK_LOCATION StackPtr
;
3250 PDEVICE_OBJECT DeviceObject
;
3251 PKEVENT Event
= NULL
;
3252 BOOLEAN LocalEvent
= FALSE
;
3253 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3254 NTSTATUS Status
= STATUS_SUCCESS
;
3255 IO_STATUS_BLOCK KernelIosb
;
3257 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3259 /* Check if we're called from user mode */
3260 if (PreviousMode
!= KernelMode
)
3262 /* Validate the information class */
3263 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3264 !(IopSetFsOperationLength
[FsInformationClass
]))
3267 return STATUS_INVALID_INFO_CLASS
;
3270 /* Validate the length */
3271 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3273 /* Invalid length */
3274 return STATUS_INFO_LENGTH_MISMATCH
;
3277 /* Enter SEH for probing */
3280 /* Probe the I/O Status block */
3281 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3283 /* Probe the information */
3284 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3286 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3288 /* Get the exception code */
3289 Status
= _SEH2_GetExceptionCode();
3292 if (!NT_SUCCESS(Status
)) return Status
;
3295 /* Get File Object */
3296 Status
= ObReferenceObjectByHandle(FileHandle
,
3297 IopSetFsOperationAccess
3298 [FsInformationClass
],
3301 (PVOID
*)&FileObject
,
3303 if (!NT_SUCCESS(Status
)) return Status
;
3305 /* Check if we should use Sync IO or not */
3306 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3309 IopLockFileObject(FileObject
);
3313 /* Use local event */
3314 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3315 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3319 /* Get the device object */
3320 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3322 /* Clear File Object event */
3323 KeClearEvent(&FileObject
->Event
);
3325 /* Allocate the IRP */
3326 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3327 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3329 /* Set up the IRP */
3330 Irp
->RequestorMode
= PreviousMode
;
3331 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3332 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3333 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3334 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3335 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3336 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3337 Irp
->UserBuffer
= FsInformation
;
3338 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3339 Irp
->MdlAddress
= NULL
;
3341 /* Set up Stack Data */
3342 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3343 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3344 StackPtr
->FileObject
= FileObject
;
3349 /* Allocate a buffer */
3350 Irp
->AssociatedIrp
.SystemBuffer
=
3351 ExAllocatePoolWithTag(NonPagedPool
,
3355 /* Copy the data into it */
3356 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3358 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3360 /* Allocating failed, clean up */
3361 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3362 Status
= _SEH2_GetExceptionCode();
3365 if (!NT_SUCCESS(Status
)) return Status
;
3367 /* Set the flags for this buffered + deferred I/O */
3368 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3370 /* Set Parameters */
3371 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3372 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3374 /* Call the Driver */
3375 Status
= IopPerformSynchronousRequest(DeviceObject
,
3383 /* Check if this was async I/O */
3386 /* It was, finalize this request */
3387 Status
= IopFinalizeAsynchronousIo(Status
,
3404 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3407 return STATUS_NOT_IMPLEMENTED
;
3415 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3418 return STATUS_NOT_IMPLEMENTED
;