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
;
1126 /* Get File Object */
1127 Status
= ObReferenceObjectByHandle(FileHandle
,
1128 FILE_LIST_DIRECTORY
,
1131 (PVOID
*)&FileObject
,
1133 if (!NT_SUCCESS(Status
)) return Status
;
1135 /* Check if we have an event handle */
1139 Status
= ObReferenceObjectByHandle(EventHandle
,
1145 if (Status
!= STATUS_SUCCESS
) return Status
;
1146 KeClearEvent(Event
);
1149 /* Check if we should use Sync IO or not */
1150 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1153 IopLockFileObject(FileObject
);
1154 LockedForSync
= TRUE
;
1157 /* Clear File Object event */
1158 KeClearEvent(&FileObject
->Event
);
1160 /* Get the device object */
1161 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1163 /* Allocate the IRP */
1164 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1165 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1167 /* Set up the IRP */
1168 Irp
->RequestorMode
= PreviousMode
;
1169 Irp
->UserIosb
= IoStatusBlock
;
1170 Irp
->UserEvent
= Event
;
1171 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1172 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1173 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1174 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1176 /* Set up Stack Data */
1177 IoStack
= IoGetNextIrpStackLocation(Irp
);
1178 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1179 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1180 IoStack
->FileObject
= FileObject
;
1182 /* Set parameters */
1183 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1184 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1185 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1187 /* Perform the call */
1188 return IopPerformSynchronousRequest(DeviceObject
,
1202 NtLockFile(IN HANDLE FileHandle
,
1203 IN HANDLE EventHandle OPTIONAL
,
1204 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1205 IN PVOID ApcContext OPTIONAL
,
1206 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1207 IN PLARGE_INTEGER ByteOffset
,
1208 IN PLARGE_INTEGER Length
,
1210 IN BOOLEAN FailImmediately
,
1211 IN BOOLEAN ExclusiveLock
)
1213 PFILE_OBJECT FileObject
;
1214 PLARGE_INTEGER LocalLength
= NULL
;
1216 PIO_STACK_LOCATION StackPtr
;
1217 PDEVICE_OBJECT DeviceObject
;
1218 PKEVENT Event
= NULL
;
1219 BOOLEAN LockedForSync
= FALSE
;
1220 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1221 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1222 NTSTATUS Status
= STATUS_SUCCESS
;
1223 OBJECT_HANDLE_INFORMATION HandleInformation
;
1225 CapturedByteOffset
.QuadPart
= 0;
1226 CapturedLength
.QuadPart
= 0;
1227 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1229 /* Get File Object */
1230 Status
= ObReferenceObjectByHandle(FileHandle
,
1234 (PVOID
*)&FileObject
,
1235 &HandleInformation
);
1236 if (!NT_SUCCESS(Status
)) return Status
;
1238 /* Check if we're called from user mode */
1239 if (PreviousMode
!= KernelMode
)
1241 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1242 if (!(HandleInformation
.GrantedAccess
&
1243 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1245 ObDereferenceObject(FileObject
);
1246 return STATUS_ACCESS_DENIED
;
1249 /* Enter SEH for probing */
1252 /* Probe the I/O STatus block */
1253 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1255 /* Probe and capture the large integers */
1256 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1257 CapturedLength
= ProbeForReadLargeInteger(Length
);
1259 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1261 /* Get the exception code */
1262 Status
= _SEH2_GetExceptionCode();
1266 /* Check if probing failed */
1267 if (!NT_SUCCESS(Status
))
1269 /* Dereference the object and return exception code */
1270 ObDereferenceObject(FileObject
);
1276 /* Otherwise, capture them directly */
1277 CapturedByteOffset
= *ByteOffset
;
1278 CapturedLength
= *Length
;
1281 /* Check if we have an event handle */
1285 Status
= ObReferenceObjectByHandle(EventHandle
,
1291 if (Status
!= STATUS_SUCCESS
) return Status
;
1292 KeClearEvent(Event
);
1295 /* Get the device object */
1296 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1298 /* Check if we should use Sync IO or not */
1299 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1302 IopLockFileObject(FileObject
);
1303 LockedForSync
= TRUE
;
1306 /* Clear File Object event */
1307 KeClearEvent(&FileObject
->Event
);
1308 FileObject
->LockOperation
= TRUE
;
1310 /* Allocate the IRP */
1311 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1312 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1314 /* Set up the IRP */
1315 Irp
->RequestorMode
= PreviousMode
;
1316 Irp
->UserIosb
= IoStatusBlock
;
1317 Irp
->UserEvent
= Event
;
1318 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1319 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1320 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1321 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1323 /* Set up Stack Data */
1324 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1325 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1326 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1327 StackPtr
->FileObject
= FileObject
;
1332 /* Allocate local buffer */
1333 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1334 sizeof(LARGE_INTEGER
),
1337 /* Set the length */
1338 *LocalLength
= CapturedLength
;
1339 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1340 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1342 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1344 /* Allocating failed, clean up */
1345 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1346 if (LocalLength
) ExFreePool(LocalLength
);
1349 Status
= _SEH2_GetExceptionCode();
1352 if (!NT_SUCCESS(Status
)) return Status
;
1354 /* Set Parameters */
1355 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1356 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1359 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1360 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1362 /* Perform the call */
1363 return IopPerformSynchronousRequest(DeviceObject
,
1377 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1378 IN HANDLE EventHandle OPTIONAL
,
1379 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1380 IN PVOID ApcContext OPTIONAL
,
1381 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1382 OUT PVOID FileInformation
,
1384 IN FILE_INFORMATION_CLASS FileInformationClass
,
1385 IN BOOLEAN ReturnSingleEntry
,
1386 IN PUNICODE_STRING FileName OPTIONAL
,
1387 IN BOOLEAN RestartScan
)
1390 PDEVICE_OBJECT DeviceObject
;
1391 PFILE_OBJECT FileObject
;
1392 PIO_STACK_LOCATION StackPtr
;
1393 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1394 NTSTATUS Status
= STATUS_SUCCESS
;
1395 BOOLEAN LockedForSynch
= FALSE
;
1396 PKEVENT Event
= NULL
;
1397 PVOID AuxBuffer
= NULL
;
1399 UNICODE_STRING CapturedFileName
;
1400 PUNICODE_STRING SearchPattern
;
1402 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1404 /* Check if we came from user mode */
1405 if (PreviousMode
!= KernelMode
)
1407 /* Enter SEH for probing */
1410 /* Probe the I/O Status Block */
1411 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1413 /* Probe the file information */
1414 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1416 /* Check if we have a file name */
1420 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1421 if (CapturedFileName
.Length
)
1423 /* Probe its buffer */
1424 ProbeForRead(CapturedFileName
.Buffer
,
1425 CapturedFileName
.Length
,
1429 /* Allocate the auxiliary buffer */
1430 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1431 CapturedFileName
.Length
+
1432 sizeof(UNICODE_STRING
),
1434 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1435 sizeof(UNICODE_STRING
)),
1436 CapturedFileName
.Buffer
,
1437 CapturedFileName
.Length
);
1439 /* Setup the search pattern */
1440 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1441 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1442 sizeof(UNICODE_STRING
));
1443 SearchPattern
->Length
= CapturedFileName
.Length
;
1444 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1447 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1449 /* Get exception code and free the buffer */
1450 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1451 Status
= _SEH2_GetExceptionCode();
1455 /* Return status on failure */
1456 if (!NT_SUCCESS(Status
)) return Status
;
1459 /* Get File Object */
1460 Status
= ObReferenceObjectByHandle(FileHandle
,
1461 FILE_LIST_DIRECTORY
,
1464 (PVOID
*)&FileObject
,
1466 if (!NT_SUCCESS(Status
))
1469 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1473 /* Check if we have an even handle */
1476 /* Get its pointer */
1477 Status
= ObReferenceObjectByHandle(EventHandle
,
1483 if (!NT_SUCCESS(Status
))
1486 ObDereferenceObject(FileObject
);
1491 KeClearEvent(Event
);
1494 /* Check if this is a file that was opened for Synch I/O */
1495 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1498 IopLockFileObject(FileObject
);
1500 /* Remember to unlock later */
1501 LockedForSynch
= TRUE
;
1504 /* Get the device object */
1505 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1507 /* Clear the File Object's event */
1508 KeClearEvent(&FileObject
->Event
);
1510 /* Allocate the IRP */
1511 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1512 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1514 /* Set up the IRP */
1515 Irp
->RequestorMode
= PreviousMode
;
1516 Irp
->UserIosb
= IoStatusBlock
;
1517 Irp
->UserEvent
= Event
;
1518 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1519 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1520 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1521 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1522 Irp
->MdlAddress
= NULL
;
1523 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1524 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1526 /* Check if this is buffered I/O */
1527 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1532 /* Allocate a buffer */
1533 Irp
->AssociatedIrp
.SystemBuffer
=
1534 ExAllocatePoolWithTag(NonPagedPool
,
1538 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1540 /* Allocating failed, clean up */
1541 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1542 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1545 Status
= _SEH2_GetExceptionCode();
1548 if (!NT_SUCCESS(Status
)) return Status
;
1550 /* Set the buffer and flags */
1551 Irp
->UserBuffer
= FileInformation
;
1552 Irp
->Flags
= (IRP_BUFFERED_IO
|
1553 IRP_DEALLOCATE_BUFFER
|
1554 IRP_INPUT_OPERATION
);
1556 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1560 /* Allocate an MDL */
1561 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1562 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1564 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1566 /* Allocating failed, clean up */
1567 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1568 Status
= _SEH2_GetExceptionCode();
1569 _SEH2_YIELD(return Status
);
1575 /* No allocation flags, and use the buffer directly */
1576 Irp
->UserBuffer
= FileInformation
;
1579 /* Set up Stack Data */
1580 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1581 StackPtr
->FileObject
= FileObject
;
1582 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1583 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1585 /* Set Parameters */
1586 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1587 FileInformationClass
;
1588 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1589 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1590 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1591 StackPtr
->Flags
= 0;
1592 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1593 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1595 /* Set deferred I/O */
1596 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1598 /* Perform the call */
1599 return IopPerformSynchronousRequest(DeviceObject
,
1613 NtQueryEaFile(IN HANDLE FileHandle
,
1614 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1617 IN BOOLEAN ReturnSingleEntry
,
1618 IN PVOID EaList OPTIONAL
,
1619 IN ULONG EaListLength
,
1620 IN PULONG EaIndex OPTIONAL
,
1621 IN BOOLEAN RestartScan
)
1624 return STATUS_NOT_IMPLEMENTED
;
1632 NtQueryInformationFile(IN HANDLE FileHandle
,
1633 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1634 IN PVOID FileInformation
,
1636 IN FILE_INFORMATION_CLASS FileInformationClass
)
1638 OBJECT_HANDLE_INFORMATION HandleInformation
;
1639 PFILE_OBJECT FileObject
;
1640 NTSTATUS Status
= STATUS_SUCCESS
;
1642 PDEVICE_OBJECT DeviceObject
;
1643 PIO_STACK_LOCATION StackPtr
;
1644 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1645 PKEVENT Event
= NULL
;
1646 BOOLEAN LocalEvent
= FALSE
;
1647 PKNORMAL_ROUTINE NormalRoutine
;
1648 PVOID NormalContext
;
1650 IO_STATUS_BLOCK KernelIosb
;
1651 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1653 /* Check if we're called from user mode */
1654 if (PreviousMode
!= KernelMode
)
1656 /* Validate the information class */
1657 if ((FileInformationClass
>= FileMaximumInformation
) ||
1658 !(IopQueryOperationLength
[FileInformationClass
]))
1661 return STATUS_INVALID_INFO_CLASS
;
1664 /* Validate the length */
1665 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1667 /* Invalid length */
1668 return STATUS_INFO_LENGTH_MISMATCH
;
1671 /* Enter SEH for probing */
1674 /* Probe the I/O Status block */
1675 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1677 /* Probe the information */
1678 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1680 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1682 /* Get the exception code */
1683 Status
= _SEH2_GetExceptionCode();
1686 if (!NT_SUCCESS(Status
)) return Status
;
1690 /* Validate the information class */
1691 if ((FileInformationClass
>= FileMaximumInformation
) ||
1692 !(IopQueryOperationLength
[FileInformationClass
]))
1695 return STATUS_INVALID_INFO_CLASS
;
1698 /* Validate the length */
1699 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1701 /* Invalid length */
1702 return STATUS_INFO_LENGTH_MISMATCH
;
1706 /* Reference the Handle */
1707 Status
= ObReferenceObjectByHandle(FileHandle
,
1708 IopQueryOperationAccess
1709 [FileInformationClass
],
1712 (PVOID
*)&FileObject
,
1713 &HandleInformation
);
1714 if (!NT_SUCCESS(Status
)) return Status
;
1716 /* Check if this is a direct open or not */
1717 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1719 /* Get the device object */
1720 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1724 /* Get the device object */
1725 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1728 /* Check if this is a file that was opened for Synch I/O */
1729 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1732 IopLockFileObject(FileObject
);
1734 /* Check if the caller just wants the position */
1735 if (FileInformationClass
== FilePositionInformation
)
1737 /* Protect write in SEH */
1740 /* Write the offset */
1741 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1742 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1744 /* Fill out the I/O Status Block */
1745 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1746 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1748 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1750 /* Get the exception code */
1751 Status
= _SEH2_GetExceptionCode();
1755 /* Release the file lock, dereference the file and return */
1756 IopUnlockFileObject(FileObject
);
1757 ObDereferenceObject(FileObject
);
1763 /* Use local event */
1764 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1765 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1769 /* Clear the File Object event */
1770 KeClearEvent(&FileObject
->Event
);
1772 /* Allocate the IRP */
1773 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1774 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1777 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1778 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1779 Irp
->RequestorMode
= PreviousMode
;
1780 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1781 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1782 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1783 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1784 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1785 Irp
->MdlAddress
= NULL
;
1786 Irp
->UserBuffer
= FileInformation
;
1788 /* Set the Stack Data */
1789 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1790 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1791 StackPtr
->FileObject
= FileObject
;
1796 /* Allocate a buffer */
1797 Irp
->AssociatedIrp
.SystemBuffer
=
1798 ExAllocatePoolWithTag(NonPagedPool
,
1802 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1804 /* Allocating failed, clean up */
1805 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
1806 Status
= _SEH2_GetExceptionCode();
1809 if (!NT_SUCCESS(Status
)) return Status
;
1812 Irp
->Flags
|= (IRP_BUFFERED_IO
|
1813 IRP_DEALLOCATE_BUFFER
|
1814 IRP_INPUT_OPERATION
|
1815 IRP_DEFER_IO_COMPLETION
);
1817 /* Set the Parameters */
1818 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1819 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1822 IopQueueIrpToThread(Irp
);
1824 /* Update operation counts */
1825 IopUpdateOperationCount(IopOtherTransfer
);
1827 /* Call the Driver */
1828 Status
= IoCallDriver(DeviceObject
, Irp
);
1829 if (Status
== STATUS_PENDING
)
1831 /* Check if this was async I/O */
1834 /* Then to a non-alertable wait */
1835 Status
= KeWaitForSingleObject(Event
,
1840 if (Status
== STATUS_USER_APC
)
1842 /* Abort the request */
1843 IopAbortInterruptedIrp(Event
, Irp
);
1846 /* Set the final status */
1847 Status
= KernelIosb
.Status
;
1849 /* Enter SEH to write the IOSB back */
1852 /* Write it back to the caller */
1853 *IoStatusBlock
= KernelIosb
;
1855 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1857 /* Get the exception code */
1858 Status
= _SEH2_GetExceptionCode();
1862 /* Free the event */
1867 /* Wait for the IRP */
1868 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1871 FileObject
->Flags
& FO_ALERTABLE_IO
,
1873 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
1875 /* Abort the request */
1876 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1879 /* Set the final status */
1880 Status
= FileObject
->FinalStatus
;
1882 /* Release the file lock */
1883 IopUnlockFileObject(FileObject
);
1888 /* Free the event if we had one */
1891 /* Clear it in the IRP for completion */
1892 Irp
->UserEvent
= NULL
;
1893 ExFreePoolWithTag(Event
, TAG_IO
);
1896 /* Set the caller IOSB */
1897 Irp
->UserIosb
= IoStatusBlock
;
1899 /* The IRP wasn't completed, complete it ourselves */
1900 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1901 IopCompleteRequest(&Irp
->Tail
.Apc
,
1904 (PVOID
*)&FileObject
,
1906 KeLowerIrql(OldIrql
);
1908 /* Release the file object if we had locked it*/
1909 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
1912 /* Return the Status */
1921 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
1922 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1925 IN BOOLEAN ReturnSingleEntry
,
1926 IN PVOID SidList OPTIONAL
,
1927 IN ULONG SidListLength
,
1928 IN PSID StartSid OPTIONAL
,
1929 IN BOOLEAN RestartScan
)
1932 return STATUS_NOT_IMPLEMENTED
;
1940 NtReadFile(IN HANDLE FileHandle
,
1941 IN HANDLE Event OPTIONAL
,
1942 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1943 IN PVOID ApcContext OPTIONAL
,
1944 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1947 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
1948 IN PULONG Key OPTIONAL
)
1950 NTSTATUS Status
= STATUS_SUCCESS
;
1951 PFILE_OBJECT FileObject
;
1953 PDEVICE_OBJECT DeviceObject
;
1954 PIO_STACK_LOCATION StackPtr
;
1955 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1956 PKEVENT EventObject
= NULL
;
1957 LARGE_INTEGER CapturedByteOffset
;
1958 ULONG CapturedKey
= 0;
1959 BOOLEAN Synchronous
= FALSE
;
1962 CapturedByteOffset
.QuadPart
= 0;
1963 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1965 /* Validate User-Mode Buffers */
1966 if(PreviousMode
!= KernelMode
)
1970 /* Probe the status block */
1971 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1973 /* Probe the read buffer */
1974 ProbeForWrite(Buffer
, Length
, 1);
1976 /* Check if we got a byte offset */
1979 /* Capture and probe it */
1980 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1983 /* Capture and probe the key */
1984 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
1986 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1988 /* Get the exception code */
1989 Status
= _SEH2_GetExceptionCode();
1993 /* Check for probe failure */
1994 if (!NT_SUCCESS(Status
)) return Status
;
1998 /* Kernel mode: capture directly */
1999 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2000 if (Key
) CapturedKey
= *Key
;
2003 /* Get File Object */
2004 Status
= ObReferenceObjectByHandle(FileHandle
,
2008 (PVOID
*)&FileObject
,
2010 if (!NT_SUCCESS(Status
)) return Status
;
2012 /* Check for event */
2016 Status
= ObReferenceObjectByHandle(Event
,
2020 (PVOID
*)&EventObject
,
2022 if (!NT_SUCCESS(Status
))
2025 ObDereferenceObject(FileObject
);
2029 /* Otherwise reset the event */
2030 KeClearEvent(EventObject
);
2033 /* Check if we should use Sync IO or not */
2034 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2036 /* Lock the file object */
2037 IopLockFileObject(FileObject
);
2039 /* Check if we don't have a byte offset avilable */
2040 if (!(ByteOffset
) ||
2041 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2042 (CapturedByteOffset
.u
.HighPart
== -1)))
2044 /* Use the Current Byte Offset instead */
2045 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2048 /* Remember we are sync */
2051 else if (!(ByteOffset
) &&
2052 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2054 /* Otherwise, this was async I/O without a byte offset, so fail */
2055 if (EventObject
) ObDereferenceObject(EventObject
);
2056 ObDereferenceObject(FileObject
);
2057 return STATUS_INVALID_PARAMETER
;
2060 /* Get the device object */
2061 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2063 /* Clear the File Object's event */
2064 KeClearEvent(&FileObject
->Event
);
2066 /* Allocate the IRP */
2067 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2068 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2071 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2072 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2073 Irp
->RequestorMode
= PreviousMode
;
2074 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2075 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2076 Irp
->UserIosb
= IoStatusBlock
;
2077 Irp
->UserEvent
= EventObject
;
2078 Irp
->PendingReturned
= FALSE
;
2079 Irp
->Cancel
= FALSE
;
2080 Irp
->CancelRoutine
= NULL
;
2081 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2082 Irp
->MdlAddress
= NULL
;
2084 /* Set the Stack Data */
2085 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2086 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2087 StackPtr
->FileObject
= FileObject
;
2088 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2089 StackPtr
->Parameters
.Read
.Length
= Length
;
2090 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2092 /* Check if this is buffered I/O */
2093 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2095 /* Check if we have a buffer length */
2101 /* Allocate a buffer */
2102 Irp
->AssociatedIrp
.SystemBuffer
=
2103 ExAllocatePoolWithTag(NonPagedPool
,
2107 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2109 /* Allocating failed, clean up */
2110 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2111 Status
= _SEH2_GetExceptionCode();
2114 if (!NT_SUCCESS(Status
)) return Status
;
2116 /* Set the buffer and flags */
2117 Irp
->UserBuffer
= Buffer
;
2118 Irp
->Flags
= (IRP_BUFFERED_IO
|
2119 IRP_DEALLOCATE_BUFFER
|
2120 IRP_INPUT_OPERATION
);
2124 /* Not reading anything */
2125 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2128 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2130 /* Check if we have a buffer length */
2135 /* Allocate an MDL */
2136 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2137 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2139 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2141 /* Allocating failed, clean up */
2142 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2143 Status
= _SEH2_GetExceptionCode();
2144 _SEH2_YIELD(return Status
);
2150 /* No allocation flags */
2155 /* No allocation flags, and use the buffer directly */
2157 Irp
->UserBuffer
= Buffer
;
2160 /* Now set the deferred read flags */
2161 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2163 /* FIXME: VFAT SUCKS */
2164 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2167 /* Perform the call */
2168 return IopPerformSynchronousRequest(DeviceObject
,
2182 NtReadFileScatter(IN HANDLE FileHandle
,
2183 IN HANDLE Event OPTIONAL
,
2184 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2185 IN PVOID UserApcContext OPTIONAL
,
2186 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2187 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2188 IN ULONG BufferLength
,
2189 IN PLARGE_INTEGER ByteOffset
,
2190 IN PULONG Key OPTIONAL
)
2193 return STATUS_NOT_IMPLEMENTED
;
2201 NtSetEaFile(IN HANDLE FileHandle
,
2202 IN PIO_STATUS_BLOCK IoStatusBlock
,
2204 IN ULONG EaBufferSize
)
2207 return STATUS_NOT_IMPLEMENTED
;
2215 NtSetInformationFile(IN HANDLE FileHandle
,
2216 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2217 IN PVOID FileInformation
,
2219 IN FILE_INFORMATION_CLASS FileInformationClass
)
2221 PFILE_OBJECT FileObject
;
2222 NTSTATUS Status
= STATUS_SUCCESS
;
2224 PDEVICE_OBJECT DeviceObject
;
2225 PIO_STACK_LOCATION StackPtr
;
2226 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2227 PKEVENT Event
= NULL
;
2228 BOOLEAN LocalEvent
= FALSE
;
2229 PKNORMAL_ROUTINE NormalRoutine
;
2230 PVOID NormalContext
;
2232 IO_STATUS_BLOCK KernelIosb
;
2234 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2235 PIO_COMPLETION_CONTEXT Context
;
2236 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2238 /* Check if we're called from user mode */
2239 if (PreviousMode
!= KernelMode
)
2241 /* Validate the information class */
2242 if ((FileInformationClass
>= FileMaximumInformation
) ||
2243 !(IopSetOperationLength
[FileInformationClass
]))
2246 return STATUS_INVALID_INFO_CLASS
;
2249 /* Validate the length */
2250 if (Length
< IopSetOperationLength
[FileInformationClass
])
2252 /* Invalid length */
2253 return STATUS_INFO_LENGTH_MISMATCH
;
2256 /* Enter SEH for probing */
2259 /* Probe the I/O Status block */
2260 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2262 /* Probe the information */
2263 ProbeForRead(FileInformation
,
2265 (Length
== sizeof(BOOLEAN
)) ?
2266 sizeof(BOOLEAN
) : sizeof(ULONG
));
2268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2270 /* Get the exception code */
2271 Status
= _SEH2_GetExceptionCode();
2275 /* Check if probing failed */
2276 if (!NT_SUCCESS(Status
)) return Status
;
2280 /* Validate the information class */
2281 if ((FileInformationClass
>= FileMaximumInformation
) ||
2282 !(IopSetOperationLength
[FileInformationClass
]))
2285 return STATUS_INVALID_INFO_CLASS
;
2288 /* Validate the length */
2289 if (Length
< IopSetOperationLength
[FileInformationClass
])
2291 /* Invalid length */
2292 return STATUS_INFO_LENGTH_MISMATCH
;
2296 /* Reference the Handle */
2297 Status
= ObReferenceObjectByHandle(FileHandle
,
2298 IopSetOperationAccess
2299 [FileInformationClass
],
2302 (PVOID
*)&FileObject
,
2304 if (!NT_SUCCESS(Status
)) return Status
;
2306 /* Check if this is a direct open or not */
2307 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2309 /* Get the device object */
2310 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2314 /* Get the device object */
2315 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2318 /* Check if this is a file that was opened for Synch I/O */
2319 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2322 IopLockFileObject(FileObject
);
2324 /* Check if the caller just wants the position */
2325 if (FileInformationClass
== FilePositionInformation
)
2327 /* Protect write in SEH */
2330 /* Write the offset */
2331 FileObject
->CurrentByteOffset
=
2332 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2335 /* Fill out the I/O Status Block */
2336 IoStatusBlock
->Information
= 0;
2337 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2339 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2341 /* Get the exception code */
2342 Status
= _SEH2_GetExceptionCode();
2346 /* Release the file lock, dereference the file and return */
2347 IopUnlockFileObject(FileObject
);
2348 ObDereferenceObject(FileObject
);
2354 /* Use local event */
2355 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2356 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2360 /* Clear the File Object event */
2361 KeClearEvent(&FileObject
->Event
);
2363 /* Allocate the IRP */
2364 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2365 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2368 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2369 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2370 Irp
->RequestorMode
= PreviousMode
;
2371 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2372 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2373 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2374 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2375 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2376 Irp
->MdlAddress
= NULL
;
2377 Irp
->UserBuffer
= FileInformation
;
2379 /* Set the Stack Data */
2380 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2381 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2382 StackPtr
->FileObject
= FileObject
;
2387 /* Allocate a buffer */
2388 Irp
->AssociatedIrp
.SystemBuffer
=
2389 ExAllocatePoolWithTag(NonPagedPool
,
2393 /* Copy the data into it */
2394 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2398 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2400 /* Allocating failed, clean up */
2401 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2402 Status
= _SEH2_GetExceptionCode();
2405 if (!NT_SUCCESS(Status
)) return Status
;
2408 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2409 IRP_DEALLOCATE_BUFFER
|
2410 IRP_DEFER_IO_COMPLETION
);
2412 /* Set the Parameters */
2413 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2414 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2417 IopQueueIrpToThread(Irp
);
2419 /* Update operation counts */
2420 IopUpdateOperationCount(IopOtherTransfer
);
2422 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2423 /* Handle IO Completion Port quickly */
2424 if (FileInformationClass
== FileCompletionInformation
)
2426 /* Check if the file object already has a completion port */
2427 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2428 (FileObject
->CompletionContext
))
2431 Status
= STATUS_INVALID_PARAMETER
;
2435 /* Reference the Port */
2436 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2437 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2438 IO_COMPLETION_MODIFY_STATE
,
2443 if (NT_SUCCESS(Status
))
2445 /* Allocate the Context */
2446 Context
= ExAllocatePoolWithTag(PagedPool
,
2447 sizeof(IO_COMPLETION_CONTEXT
),
2452 Context
->Key
= CompletionInfo
->Key
;
2453 Context
->Port
= Queue
;
2454 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
2460 * Someone else set the completion port in the
2461 * meanwhile, so dereference the port and fail.
2463 ExFreePool(Context
);
2464 ObDereferenceObject(Queue
);
2465 Status
= STATUS_INVALID_PARAMETER
;
2470 /* Dereference the Port now */
2471 ObDereferenceObject(Queue
);
2472 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2477 /* Set the IRP Status */
2478 Irp
->IoStatus
.Status
= Status
;
2479 Irp
->IoStatus
.Information
= 0;
2483 /* Call the Driver */
2484 Status
= IoCallDriver(DeviceObject
, Irp
);
2487 /* Check if we're waiting for the IRP to complete */
2488 if (Status
== STATUS_PENDING
)
2490 /* Check if this was async I/O */
2493 /* Then to a non-alertable wait */
2494 Status
= KeWaitForSingleObject(Event
,
2499 if (Status
== STATUS_USER_APC
)
2501 /* Abort the request */
2502 IopAbortInterruptedIrp(Event
, Irp
);
2505 /* Set the final status */
2506 Status
= KernelIosb
.Status
;
2508 /* Enter SEH to write the IOSB back */
2511 /* Write it back to the caller */
2512 *IoStatusBlock
= KernelIosb
;
2514 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2516 /* Get the exception code */
2517 Status
= _SEH2_GetExceptionCode();
2521 /* Free the event */
2526 /* Wait for the IRP */
2527 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2530 FileObject
->Flags
& FO_ALERTABLE_IO
,
2532 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2534 /* Abort the request */
2535 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2538 /* Set the final status */
2539 Status
= FileObject
->FinalStatus
;
2541 /* Release the file lock */
2542 IopUnlockFileObject(FileObject
);
2547 /* Free the event if we had one */
2550 /* Clear it in the IRP for completion */
2551 Irp
->UserEvent
= NULL
;
2555 /* Set the caller IOSB */
2556 Irp
->UserIosb
= IoStatusBlock
;
2558 /* The IRP wasn't completed, complete it ourselves */
2559 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2560 IopCompleteRequest(&Irp
->Tail
.Apc
,
2563 (PVOID
*)&FileObject
,
2565 KeLowerIrql(OldIrql
);
2567 /* Release the file object if we had locked it*/
2568 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2571 /* Return the Status */
2580 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2581 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2583 IN ULONG BufferLength
)
2586 return STATUS_NOT_IMPLEMENTED
;
2594 NtUnlockFile(IN HANDLE FileHandle
,
2595 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2596 IN PLARGE_INTEGER ByteOffset
,
2597 IN PLARGE_INTEGER Length
,
2598 IN ULONG Key OPTIONAL
)
2600 PFILE_OBJECT FileObject
;
2601 PLARGE_INTEGER LocalLength
= NULL
;
2603 PIO_STACK_LOCATION StackPtr
;
2604 PDEVICE_OBJECT DeviceObject
;
2605 PKEVENT Event
= NULL
;
2606 BOOLEAN LocalEvent
= FALSE
;
2607 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2608 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2609 NTSTATUS Status
= STATUS_SUCCESS
;
2610 OBJECT_HANDLE_INFORMATION HandleInformation
;
2611 IO_STATUS_BLOCK KernelIosb
;
2613 CapturedByteOffset
.QuadPart
= 0;
2614 CapturedLength
.QuadPart
= 0;
2615 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2617 /* Get File Object */
2618 Status
= ObReferenceObjectByHandle(FileHandle
,
2622 (PVOID
*)&FileObject
,
2623 &HandleInformation
);
2624 if (!NT_SUCCESS(Status
)) return Status
;
2626 /* Check if we're called from user mode */
2627 if (PreviousMode
!= KernelMode
)
2629 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2630 if (!(HandleInformation
.GrantedAccess
&
2631 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2633 ObDereferenceObject(FileObject
);
2634 return STATUS_ACCESS_DENIED
;
2637 /* Enter SEH for probing */
2640 /* Probe the I/O Status block */
2641 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2643 /* Probe and capture the large integers */
2644 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2645 CapturedLength
= ProbeForReadLargeInteger(Length
);
2647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2649 /* Get the exception code */
2650 Status
= _SEH2_GetExceptionCode();
2654 /* Check if probing failed */
2655 if (!NT_SUCCESS(Status
))
2657 /* Dereference the object and return exception code */
2658 ObDereferenceObject(FileObject
);
2664 /* Otherwise, capture them directly */
2665 CapturedByteOffset
= *ByteOffset
;
2666 CapturedLength
= *Length
;
2669 /* Check if this is a direct open or not */
2670 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2672 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2676 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2679 /* Check if we should use Sync IO or not */
2680 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2683 IopLockFileObject(FileObject
);
2687 /* Use local event */
2688 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2689 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2693 /* Clear File Object event */
2694 KeClearEvent(&FileObject
->Event
);
2696 /* Allocate the IRP */
2697 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2698 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2700 /* Set up the IRP */
2701 Irp
->RequestorMode
= PreviousMode
;
2702 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2703 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2704 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2705 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2706 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2707 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2709 /* Set up Stack Data */
2710 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2711 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2712 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2713 StackPtr
->FileObject
= FileObject
;
2718 /* Allocate a buffer */
2719 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2720 sizeof(LARGE_INTEGER
),
2723 /* Set the length */
2724 *LocalLength
= CapturedLength
;
2725 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
2726 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2728 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2730 /* Allocating failed, clean up */
2731 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2732 if (LocalLength
) ExFreePool(LocalLength
);
2734 /* Get exception status */
2735 Status
= _SEH2_GetExceptionCode();
2738 if (!NT_SUCCESS(Status
)) return Status
;
2740 /* Set Parameters */
2741 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
2742 StackPtr
->Parameters
.LockControl
.Key
= Key
;
2744 /* Call the Driver */
2745 Status
= IopPerformSynchronousRequest(DeviceObject
,
2753 /* Check if this was async I/O */
2756 /* It was, finalize this request */
2757 Status
= IopFinalizeAsynchronousIo(Status
,
2774 NtWriteFile(IN HANDLE FileHandle
,
2775 IN HANDLE Event OPTIONAL
,
2776 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2777 IN PVOID ApcContext OPTIONAL
,
2778 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2781 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2782 IN PULONG Key OPTIONAL
)
2784 NTSTATUS Status
= STATUS_SUCCESS
;
2785 PFILE_OBJECT FileObject
;
2787 PDEVICE_OBJECT DeviceObject
;
2788 PIO_STACK_LOCATION StackPtr
;
2789 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2790 PKEVENT EventObject
= NULL
;
2791 LARGE_INTEGER CapturedByteOffset
;
2792 ULONG CapturedKey
= 0;
2793 BOOLEAN Synchronous
= FALSE
;
2795 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
2797 CapturedByteOffset
.QuadPart
= 0;
2798 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2800 /* Get File Object */
2801 Status
= ObReferenceObjectByHandle(FileHandle
,
2805 (PVOID
*)&FileObject
,
2807 if (!NT_SUCCESS(Status
)) return Status
;
2809 /* Validate User-Mode Buffers */
2810 if(PreviousMode
!= KernelMode
)
2815 * Check if the handle has either FILE_WRITE_DATA or
2816 * FILE_APPEND_DATA granted. However, if this is a named pipe,
2817 * make sure we don't ask for FILE_APPEND_DATA as it interferes
2818 * with the FILE_CREATE_PIPE_INSTANCE access right!
2820 if (!(ObjectHandleInfo
.GrantedAccess
&
2821 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
2822 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
2825 ObDereferenceObject(FileObject
);
2826 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
2829 /* Probe the status block */
2830 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2832 /* Probe the read buffer */
2833 ProbeForRead(Buffer
, Length
, 1);
2835 /* Check if we got a byte offset */
2838 /* Capture and probe it */
2839 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2842 /* Capture and probe the key */
2843 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2845 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2847 /* Get the exception code */
2848 Status
= _SEH2_GetExceptionCode();
2852 /* Check for probe failure */
2853 if (!NT_SUCCESS(Status
)) return Status
;
2857 /* Kernel mode: capture directly */
2858 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2859 if (Key
) CapturedKey
= *Key
;
2862 /* Check if this is an append operation */
2863 if ((ObjectHandleInfo
.GrantedAccess
&
2864 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
2866 /* Give the drivers something to understand */
2867 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
2868 CapturedByteOffset
.u
.HighPart
= -1;
2871 /* Check for event */
2875 Status
= ObReferenceObjectByHandle(Event
,
2879 (PVOID
*)&EventObject
,
2881 if (!NT_SUCCESS(Status
))
2884 ObDereferenceObject(FileObject
);
2888 /* Otherwise reset the event */
2889 KeClearEvent(EventObject
);
2892 /* Check if we should use Sync IO or not */
2893 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2895 /* Lock the file object */
2896 IopLockFileObject(FileObject
);
2898 /* Check if we don't have a byte offset avilable */
2899 if (!(ByteOffset
) ||
2900 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2901 (CapturedByteOffset
.u
.HighPart
== -1)))
2903 /* Use the Current Byte Offset instead */
2904 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2907 /* Remember we are sync */
2910 else if (!(ByteOffset
) &&
2911 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2913 /* Otherwise, this was async I/O without a byte offset, so fail */
2914 if (EventObject
) ObDereferenceObject(EventObject
);
2915 ObDereferenceObject(FileObject
);
2916 return STATUS_INVALID_PARAMETER
;
2919 /* Get the device object */
2920 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2922 /* Clear the File Object's event */
2923 KeClearEvent(&FileObject
->Event
);
2925 /* Allocate the IRP */
2926 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2927 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2930 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2931 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2932 Irp
->RequestorMode
= PreviousMode
;
2933 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2934 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2935 Irp
->UserIosb
= IoStatusBlock
;
2936 Irp
->UserEvent
= EventObject
;
2937 Irp
->PendingReturned
= FALSE
;
2938 Irp
->Cancel
= FALSE
;
2939 Irp
->CancelRoutine
= NULL
;
2940 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2941 Irp
->MdlAddress
= NULL
;
2943 /* Set the Stack Data */
2944 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2945 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
2946 StackPtr
->FileObject
= FileObject
;
2947 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
2948 SL_WRITE_THROUGH
: 0;
2949 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
2950 StackPtr
->Parameters
.Write
.Length
= Length
;
2951 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
2953 /* Check if this is buffered I/O */
2954 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2956 /* Check if we have a buffer length */
2962 /* Allocate a buffer */
2963 Irp
->AssociatedIrp
.SystemBuffer
=
2964 ExAllocatePoolWithTag(NonPagedPool
,
2968 /* Copy the data into it */
2969 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
2971 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2973 /* Allocating failed, clean up */
2974 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2975 Status
= _SEH2_GetExceptionCode();
2976 _SEH2_YIELD(return Status
);
2981 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
2985 /* Not writing anything */
2986 Irp
->Flags
= IRP_BUFFERED_IO
;
2989 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2991 /* Check if we have a buffer length */
2996 /* Allocate an MDL */
2997 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2998 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3000 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3002 /* Allocating failed, clean up */
3003 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3004 Status
= _SEH2_GetExceptionCode();
3005 _SEH2_YIELD(return Status
);
3010 /* No allocation flags */
3015 /* No allocation flags, and use the buffer directly */
3017 Irp
->UserBuffer
= Buffer
;
3020 /* Now set the deferred read flags */
3021 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3023 /* FIXME: VFAT SUCKS */
3024 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3027 /* Perform the call */
3028 return IopPerformSynchronousRequest(DeviceObject
,
3039 NtWriteFileGather(IN HANDLE FileHandle
,
3040 IN HANDLE Event OPTIONAL
,
3041 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3042 IN PVOID UserApcContext OPTIONAL
,
3043 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3044 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3045 IN ULONG BufferLength
,
3046 IN PLARGE_INTEGER ByteOffset
,
3047 IN PULONG Key OPTIONAL
)
3050 return STATUS_NOT_IMPLEMENTED
;
3058 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3059 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3060 OUT PVOID FsInformation
,
3062 IN FS_INFORMATION_CLASS FsInformationClass
)
3064 PFILE_OBJECT FileObject
;
3066 PIO_STACK_LOCATION StackPtr
;
3067 PDEVICE_OBJECT DeviceObject
;
3068 PKEVENT Event
= NULL
;
3069 BOOLEAN LocalEvent
= FALSE
;
3070 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3071 NTSTATUS Status
= STATUS_SUCCESS
;
3072 IO_STATUS_BLOCK KernelIosb
;
3074 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3076 /* Check if we're called from user mode */
3077 if (PreviousMode
!= KernelMode
)
3079 /* Validate the information class */
3080 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3081 !(IopQueryFsOperationLength
[FsInformationClass
]))
3084 return STATUS_INVALID_INFO_CLASS
;
3087 /* Validate the length */
3088 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3090 /* Invalid length */
3091 return STATUS_INFO_LENGTH_MISMATCH
;
3094 /* Enter SEH for probing */
3097 /* Probe the I/O Status block */
3098 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3100 /* Probe the information */
3101 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3103 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3105 /* Get the exception code */
3106 Status
= _SEH2_GetExceptionCode();
3109 if (!NT_SUCCESS(Status
)) return Status
;
3112 /* Get File Object */
3113 Status
= ObReferenceObjectByHandle(FileHandle
,
3114 IopQueryFsOperationAccess
3115 [FsInformationClass
],
3118 (PVOID
*)&FileObject
,
3120 if (!NT_SUCCESS(Status
)) return Status
;
3122 /* Check if we should use Sync IO or not */
3123 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3126 IopLockFileObject(FileObject
);
3130 /* Use local event */
3131 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3132 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3136 /* Get the device object */
3137 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3139 /* Clear File Object event */
3140 KeClearEvent(&FileObject
->Event
);
3142 /* Allocate the IRP */
3143 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3144 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3146 /* Set up the IRP */
3147 Irp
->RequestorMode
= PreviousMode
;
3148 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3149 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3150 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3151 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3152 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3153 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3154 Irp
->UserBuffer
= FsInformation
;
3155 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3156 Irp
->MdlAddress
= NULL
;
3158 /* Set up Stack Data */
3159 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3160 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3161 StackPtr
->FileObject
= FileObject
;
3166 /* Allocate a buffer */
3167 Irp
->AssociatedIrp
.SystemBuffer
=
3168 ExAllocatePoolWithTag(NonPagedPool
,
3172 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3174 /* Allocating failed, clean up */
3175 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3176 Status
= _SEH2_GetExceptionCode();
3179 if (!NT_SUCCESS(Status
)) return Status
;
3181 /* Set the flags for this buffered + deferred I/O */
3182 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3183 IRP_DEALLOCATE_BUFFER
|
3184 IRP_INPUT_OPERATION
|
3185 IRP_DEFER_IO_COMPLETION
);
3187 /* Set Parameters */
3188 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3189 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3191 /* Call the Driver */
3192 Status
= IopPerformSynchronousRequest(DeviceObject
,
3200 /* Check if this was async I/O */
3203 /* It was, finalize this request */
3204 Status
= IopFinalizeAsynchronousIo(Status
,
3221 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3222 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3223 IN PVOID FsInformation
,
3225 IN FS_INFORMATION_CLASS FsInformationClass
)
3227 PFILE_OBJECT FileObject
;
3229 PIO_STACK_LOCATION StackPtr
;
3230 PDEVICE_OBJECT DeviceObject
;
3231 PKEVENT Event
= NULL
;
3232 BOOLEAN LocalEvent
= FALSE
;
3233 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3234 NTSTATUS Status
= STATUS_SUCCESS
;
3235 IO_STATUS_BLOCK KernelIosb
;
3237 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3239 /* Check if we're called from user mode */
3240 if (PreviousMode
!= KernelMode
)
3242 /* Validate the information class */
3243 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3244 !(IopSetFsOperationLength
[FsInformationClass
]))
3247 return STATUS_INVALID_INFO_CLASS
;
3250 /* Validate the length */
3251 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3253 /* Invalid length */
3254 return STATUS_INFO_LENGTH_MISMATCH
;
3257 /* Enter SEH for probing */
3260 /* Probe the I/O Status block */
3261 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3263 /* Probe the information */
3264 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3266 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3268 /* Get the exception code */
3269 Status
= _SEH2_GetExceptionCode();
3272 if (!NT_SUCCESS(Status
)) return Status
;
3275 /* Get File Object */
3276 Status
= ObReferenceObjectByHandle(FileHandle
,
3277 IopSetFsOperationAccess
3278 [FsInformationClass
],
3281 (PVOID
*)&FileObject
,
3283 if (!NT_SUCCESS(Status
)) return Status
;
3285 /* Check if we should use Sync IO or not */
3286 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3289 IopLockFileObject(FileObject
);
3293 /* Use local event */
3294 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3295 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3299 /* Get the device object */
3300 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3302 /* Clear File Object event */
3303 KeClearEvent(&FileObject
->Event
);
3305 /* Allocate the IRP */
3306 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3307 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3309 /* Set up the IRP */
3310 Irp
->RequestorMode
= PreviousMode
;
3311 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3312 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3313 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3314 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3315 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3316 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3317 Irp
->UserBuffer
= FsInformation
;
3318 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3319 Irp
->MdlAddress
= NULL
;
3321 /* Set up Stack Data */
3322 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3323 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3324 StackPtr
->FileObject
= FileObject
;
3329 /* Allocate a buffer */
3330 Irp
->AssociatedIrp
.SystemBuffer
=
3331 ExAllocatePoolWithTag(NonPagedPool
,
3335 /* Copy the data into it */
3336 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3338 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3340 /* Allocating failed, clean up */
3341 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3342 Status
= _SEH2_GetExceptionCode();
3345 if (!NT_SUCCESS(Status
)) return Status
;
3347 /* Set the flags for this buffered + deferred I/O */
3348 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3350 /* Set Parameters */
3351 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3352 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3354 /* Call the Driver */
3355 Status
= IopPerformSynchronousRequest(DeviceObject
,
3363 /* Check if this was async I/O */
3366 /* It was, finalize this request */
3367 Status
= IopFinalizeAsynchronousIo(Status
,
3384 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3387 return STATUS_NOT_IMPLEMENTED
;
3395 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3398 return STATUS_NOT_IMPLEMENTED
;