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 *****************************************************************/
17 #include "internal/io_i.h"
19 /* PRIVATE FUNCTIONS *********************************************************/
23 IopCleanupAfterException(IN PFILE_OBJECT FileObject
,
25 IN PKEVENT Event OPTIONAL
,
26 IN PKEVENT LocalEvent OPTIONAL
)
29 IOTRACE(IO_API_DEBUG
, "IRP: %p. FO: %p \n", Irp
, FileObject
);
31 /* Check if we had a buffer */
32 if (Irp
->AssociatedIrp
.SystemBuffer
)
35 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
39 if (Irp
->MdlAddress
) IoFreeMdl(Irp
->MdlAddress
);
44 /* Check if we had a file lock */
45 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
48 IopUnlockFileObject(FileObject
);
51 /* Check if we had an event */
52 if (Event
) ObDereferenceObject(Event
);
54 /* Check if we had a local event */
55 if (LocalEvent
) ExFreePool(LocalEvent
);
57 /* Derefenrce the FO */
58 ObDereferenceObject(FileObject
);
63 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus
,
66 IN KPROCESSOR_MODE PreviousMode
,
67 IN PIO_STATUS_BLOCK KernelIosb
,
68 OUT PIO_STATUS_BLOCK IoStatusBlock
)
70 NTSTATUS FinalStatus
= SynchStatus
;
72 IOTRACE(IO_API_DEBUG
, "IRP: %p. Status: %lx \n", Irp
, SynchStatus
);
74 /* Make sure the IRP was completed, but returned pending */
75 if (FinalStatus
== STATUS_PENDING
)
77 /* Wait for the IRP */
78 FinalStatus
= KeWaitForSingleObject(Event
,
83 if (FinalStatus
== STATUS_USER_APC
)
85 /* Abort the request */
86 IopAbortInterruptedIrp(Event
, Irp
);
89 /* Set the final status */
90 FinalStatus
= KernelIosb
->Status
;
93 /* Wrap potential user-mode write in SEH */
96 *IoStatusBlock
= *KernelIosb
;
98 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
100 /* Get the exception code */
101 FinalStatus
= _SEH2_GetExceptionCode();
105 /* Free the event and return status */
112 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject
,
114 IN PFILE_OBJECT FileObject
,
116 IN KPROCESSOR_MODE PreviousMode
,
118 IN IOP_TRANSFER_TYPE TransferType
)
121 PKNORMAL_ROUTINE NormalRoutine
;
122 PVOID NormalContext
= NULL
;
125 IOTRACE(IO_API_DEBUG
, "IRP: %p. DO: %p. FO: %p \n",
126 Irp
, DeviceObject
, FileObject
);
129 IopQueueIrpToThread(Irp
);
131 /* Update operation counts */
132 IopUpdateOperationCount(TransferType
);
134 /* Call the driver */
135 Status
= IoCallDriver(DeviceObject
, Irp
);
137 /* Check if we're optimizing this case */
140 /* We are! Check if the IRP wasn't completed */
141 if (Status
!= STATUS_PENDING
)
143 /* Complete it ourselves */
144 ASSERT(!Irp
->PendingReturned
);
145 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
146 IopCompleteRequest(&Irp
->Tail
.Apc
,
151 KeLowerIrql(OldIrql
);
155 /* Check if this was synch I/O */
158 /* Make sure the IRP was completed, but returned pending */
159 if (Status
== STATUS_PENDING
)
161 /* Wait for the IRP */
162 Status
= KeWaitForSingleObject(&FileObject
->Event
,
166 FO_ALERTABLE_IO
) != 0,
168 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
170 /* Abort the request */
171 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
174 /* Set the final status */
175 Status
= FileObject
->FinalStatus
;
178 /* Release the file lock */
179 IopUnlockFileObject(FileObject
);
188 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
189 IN HANDLE Event OPTIONAL
,
190 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
191 IN PVOID UserApcContext OPTIONAL
,
192 OUT PIO_STATUS_BLOCK IoStatusBlock
,
193 IN ULONG IoControlCode
,
194 IN PVOID InputBuffer
,
195 IN ULONG InputBufferLength OPTIONAL
,
196 OUT PVOID OutputBuffer
,
197 IN ULONG OutputBufferLength OPTIONAL
,
198 IN BOOLEAN IsDevIoCtl
)
201 PFILE_OBJECT FileObject
;
202 PDEVICE_OBJECT DeviceObject
;
204 PIO_STACK_LOCATION StackPtr
;
205 PKEVENT EventObject
= NULL
;
206 BOOLEAN LockedForSynch
= FALSE
;
208 OBJECT_HANDLE_INFORMATION HandleInformation
;
209 ACCESS_MASK DesiredAccess
;
210 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
212 IOTRACE(IO_CTL_DEBUG
, "Handle: %lx. CTL: %lx. Type: %lx \n",
213 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
215 /* Get the access type */
216 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
218 /* Check if we came from user mode */
219 if (PreviousMode
!= KernelMode
)
223 /* Probe the status block */
224 ProbeForWriteIoStatusBlock(IoStatusBlock
);
226 /* Check if this is buffered I/O */
227 if (AccessType
== METHOD_BUFFERED
)
229 /* Check if we have an output buffer */
232 /* Probe the output buffer */
233 ProbeForWrite(OutputBuffer
,
239 /* Make sure the caller can't fake this as we depend on this */
240 OutputBufferLength
= 0;
244 /* Check if we we have an input buffer I/O */
245 if (AccessType
!= METHOD_NEITHER
)
247 /* Check if we have an input buffer */
250 /* Probe the input buffer */
251 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
255 /* Make sure the caller can't fake this as we depend on this */
256 InputBufferLength
= 0;
260 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
262 /* Return the exception code */
263 _SEH2_YIELD(return _SEH2_GetExceptionCode());
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; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
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 and return */
431 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
432 _SEH2_YIELD(return _SEH2_GetExceptionCode());
438 case METHOD_IN_DIRECT
:
439 case METHOD_OUT_DIRECT
:
444 /* Check if we got an input buffer */
445 if ((InputBufferLength
) && (InputBuffer
))
447 /* Allocate the System Buffer */
448 Irp
->AssociatedIrp
.SystemBuffer
=
449 ExAllocatePoolWithTag(NonPagedPool
,
453 /* Copy into the System Buffer */
454 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
458 /* Write the flags */
459 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
462 /* Check if we got an output buffer */
465 /* Allocate the System Buffer */
466 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
471 if (!Irp
->MdlAddress
)
473 /* Raise exception we'll catch */
474 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
478 MmProbeAndLockPages(Irp
->MdlAddress
,
480 (AccessType
== METHOD_IN_DIRECT
) ?
481 IoReadAccess
: IoWriteAccess
);
484 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
486 /* Cleanup after exception and return */
487 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
488 _SEH2_YIELD(return _SEH2_GetExceptionCode());
495 /* Just save the Buffer */
496 Irp
->UserBuffer
= OutputBuffer
;
497 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
500 /* Use deferred completion for FS I/O */
501 Irp
->Flags
|= (!IsDevIoCtl
) ? IRP_DEFER_IO_COMPLETION
: 0;
503 /* Perform the call */
504 return IopPerformSynchronousRequest(DeviceObject
,
515 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
516 IN ULONG InformationClass
,
518 OUT PVOID Information
,
519 OUT PULONG ReturnedLength
,
522 IO_STATUS_BLOCK IoStatusBlock
;
524 PDEVICE_OBJECT DeviceObject
;
525 PIO_STACK_LOCATION StackPtr
;
526 BOOLEAN LocalEvent
= FALSE
;
530 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
531 FileObject
, InformationClass
, File
);
533 /* Reference the object */
534 ObReferenceObject(FileObject
);
536 /* Check if this is a file that was opened for Synch I/O */
537 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
540 IopLockFileObject(FileObject
);
542 /* Use File Object event */
543 KeClearEvent(&FileObject
->Event
);
547 /* Use local event */
548 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
552 /* Get the Device Object */
553 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
555 /* Allocate the IRP */
556 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
557 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
560 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
561 Irp
->RequestorMode
= KernelMode
;
562 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
563 Irp
->UserIosb
= &IoStatusBlock
;
564 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
565 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
566 Irp
->Flags
|= IRP_BUFFERED_IO
;
567 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
568 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
570 /* Set the Stack Data */
571 StackPtr
= IoGetNextIrpStackLocation(Irp
);
572 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
573 IRP_MJ_QUERY_VOLUME_INFORMATION
;
574 StackPtr
->FileObject
= FileObject
;
576 /* Check which type this is */
580 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
581 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
586 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
587 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
591 IopQueueIrpToThread(Irp
);
593 /* Call the Driver */
594 Status
= IoCallDriver(DeviceObject
, Irp
);
596 /* Check if this was synch I/O */
599 /* Check if the requet is pending */
600 if (Status
== STATUS_PENDING
)
602 /* Wait on the file object */
603 Status
= KeWaitForSingleObject(&FileObject
->Event
,
607 FO_ALERTABLE_IO
) != 0,
609 if (Status
== STATUS_ALERTED
)
611 /* Abort the operation */
612 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
615 /* Get the final status */
616 Status
= FileObject
->FinalStatus
;
619 /* Release the file lock */
620 IopUnlockFileObject(FileObject
);
622 else if (Status
== STATUS_PENDING
)
624 /* Wait on the local event and get the final status */
625 KeWaitForSingleObject(&Event
,
630 Status
= IoStatusBlock
.Status
;
633 /* Return the Length and Status. ReturnedLength is NOT optional */
634 *ReturnedLength
= (ULONG
)IoStatusBlock
.Information
;
638 /* PUBLIC FUNCTIONS **********************************************************/
645 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
647 IN PLARGE_INTEGER Offset
,
649 IN PIO_STATUS_BLOCK StatusBlock
)
652 PIO_STACK_LOCATION StackPtr
;
653 PDEVICE_OBJECT DeviceObject
;
654 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
655 FileObject
, Mdl
, Offset
);
657 /* Get the Device Object */
658 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
661 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
662 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
665 StackPtr
= IoGetNextIrpStackLocation(Irp
);
667 /* Create the IRP Settings */
668 Irp
->MdlAddress
= Mdl
;
669 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
670 Irp
->UserIosb
= StatusBlock
;
671 Irp
->UserEvent
= Event
;
672 Irp
->RequestorMode
= KernelMode
;
673 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
674 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
675 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
677 /* Set the Stack Settings */
678 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
679 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
680 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
681 StackPtr
->FileObject
= FileObject
;
683 /* Call the Driver */
684 return IoCallDriver(DeviceObject
, Irp
);
692 IoPageRead(IN PFILE_OBJECT FileObject
,
694 IN PLARGE_INTEGER Offset
,
696 IN PIO_STATUS_BLOCK StatusBlock
)
699 PIO_STACK_LOCATION StackPtr
;
700 PDEVICE_OBJECT DeviceObject
;
701 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
702 FileObject
, Mdl
, Offset
);
704 /* Get the Device Object */
705 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
708 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
709 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
712 StackPtr
= IoGetNextIrpStackLocation(Irp
);
714 /* Create the IRP Settings */
715 Irp
->MdlAddress
= Mdl
;
716 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
717 Irp
->UserIosb
= StatusBlock
;
718 Irp
->UserEvent
= Event
;
719 Irp
->RequestorMode
= KernelMode
;
720 Irp
->Flags
= IRP_PAGING_IO
|
722 IRP_SYNCHRONOUS_PAGING_IO
|
724 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
725 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
727 /* Set the Stack Settings */
728 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
729 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
730 StackPtr
->MajorFunction
= IRP_MJ_READ
;
731 StackPtr
->FileObject
= FileObject
;
733 /* Call the Driver */
734 return IoCallDriver(DeviceObject
, Irp
);
742 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
743 IN FILE_INFORMATION_CLASS FileInformationClass
,
745 OUT PVOID FileInformation
,
746 OUT PULONG ReturnedLength
)
748 /* Call the shared routine */
749 return IopQueryDeviceInformation(FileObject
,
750 FileInformationClass
,
762 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
763 IN FS_INFORMATION_CLASS FsInformationClass
,
765 OUT PVOID FsInformation
,
766 OUT PULONG ReturnedLength
)
768 /* Call the shared routine */
769 return IopQueryDeviceInformation(FileObject
,
782 IoSetInformation(IN PFILE_OBJECT FileObject
,
783 IN FILE_INFORMATION_CLASS FileInformationClass
,
785 IN PVOID FileInformation
)
787 IO_STATUS_BLOCK IoStatusBlock
;
789 PDEVICE_OBJECT DeviceObject
;
790 PIO_STACK_LOCATION StackPtr
;
791 BOOLEAN LocalEvent
= FALSE
;
795 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
796 FileObject
, FileInformationClass
, Length
);
798 /* Reference the object */
799 ObReferenceObject(FileObject
);
801 /* Check if this is a file that was opened for Synch I/O */
802 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
805 IopLockFileObject(FileObject
);
807 /* Use File Object event */
808 KeClearEvent(&FileObject
->Event
);
812 /* Use local event */
813 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
817 /* Get the Device Object */
818 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
820 /* Allocate the IRP */
821 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
822 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
825 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
826 Irp
->RequestorMode
= KernelMode
;
827 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
828 Irp
->UserIosb
= &IoStatusBlock
;
829 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
830 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
831 Irp
->Flags
|= IRP_BUFFERED_IO
;
832 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
833 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
835 /* Set the Stack Data */
836 StackPtr
= IoGetNextIrpStackLocation(Irp
);
837 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
838 StackPtr
->FileObject
= FileObject
;
841 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
842 StackPtr
->Parameters
.SetFile
.Length
= Length
;
845 IopQueueIrpToThread(Irp
);
847 /* Call the Driver */
848 Status
= IoCallDriver(DeviceObject
, Irp
);
850 /* Check if this was synch I/O */
853 /* Check if the requet is pending */
854 if (Status
== STATUS_PENDING
)
856 /* Wait on the file object */
857 Status
= KeWaitForSingleObject(&FileObject
->Event
,
861 FO_ALERTABLE_IO
) != 0,
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
;
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 /* Return the exception code */
982 _SEH2_YIELD(return _SEH2_GetExceptionCode());
987 /* Get the File Object */
988 Status
= ObReferenceObjectByHandle(FileHandle
,
994 if (!NT_SUCCESS(Status
)) return Status
;
997 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
998 * granted. However, if this is a named pipe, make sure we don't ask for
999 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1002 if (!(ObjectHandleInfo
.GrantedAccess
&
1003 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1007 ObDereferenceObject(FileObject
);
1008 return STATUS_ACCESS_DENIED
;
1011 /* Check if we should use Sync IO or not */
1012 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1015 IopLockFileObject(FileObject
);
1019 /* Use local event */
1020 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1024 ObDereferenceObject(FileObject
);
1025 return STATUS_INSUFFICIENT_RESOURCES
;
1027 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1031 /* Get the Device Object */
1032 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1034 /* Clear the event */
1035 KeClearEvent(&FileObject
->Event
);
1037 /* Allocate the IRP */
1038 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1039 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1041 /* Set up the IRP */
1042 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1043 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1044 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1045 Irp
->RequestorMode
= PreviousMode
;
1046 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1047 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1048 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1050 /* Set up Stack Data */
1051 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1052 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1053 StackPtr
->FileObject
= FileObject
;
1055 /* Call the Driver */
1056 Status
= IopPerformSynchronousRequest(DeviceObject
,
1064 /* Check if this was async I/O */
1067 /* It was, finalize this request */
1068 Status
= IopFinalizeAsynchronousIo(Status
,
1076 /* Return the Status */
1085 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1086 IN HANDLE EventHandle OPTIONAL
,
1087 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1088 IN PVOID ApcContext OPTIONAL
,
1089 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1091 IN ULONG BufferSize
,
1092 IN ULONG CompletionFilter
,
1093 IN BOOLEAN WatchTree
)
1096 PKEVENT Event
= NULL
;
1097 PDEVICE_OBJECT DeviceObject
;
1098 PFILE_OBJECT FileObject
;
1099 PIO_STACK_LOCATION IoStack
;
1100 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1102 BOOLEAN LockedForSync
= FALSE
;
1104 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1106 /* Check if we're called from user mode */
1107 if (PreviousMode
!= KernelMode
)
1109 /* Enter SEH for probing */
1112 /* Probe the I/O STatus block */
1113 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1115 /* Probe the buffer */
1116 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1118 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1120 /* Return the exception code */
1121 _SEH2_YIELD(return _SEH2_GetExceptionCode());
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
->UserBuffer
= Buffer
;
1182 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1183 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1184 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1185 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1187 /* Set up Stack Data */
1188 IoStack
= IoGetNextIrpStackLocation(Irp
);
1189 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1190 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1191 IoStack
->FileObject
= FileObject
;
1193 /* Set parameters */
1194 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1195 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1196 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1198 /* Perform the call */
1199 return IopPerformSynchronousRequest(DeviceObject
,
1213 NtLockFile(IN HANDLE FileHandle
,
1214 IN HANDLE EventHandle OPTIONAL
,
1215 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1216 IN PVOID ApcContext OPTIONAL
,
1217 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1218 IN PLARGE_INTEGER ByteOffset
,
1219 IN PLARGE_INTEGER Length
,
1221 IN BOOLEAN FailImmediately
,
1222 IN BOOLEAN ExclusiveLock
)
1224 PFILE_OBJECT FileObject
;
1225 PLARGE_INTEGER LocalLength
= NULL
;
1227 PIO_STACK_LOCATION StackPtr
;
1228 PDEVICE_OBJECT DeviceObject
;
1229 PKEVENT Event
= NULL
;
1230 BOOLEAN LockedForSync
= FALSE
;
1231 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1232 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1234 OBJECT_HANDLE_INFORMATION HandleInformation
;
1236 CapturedByteOffset
.QuadPart
= 0;
1237 CapturedLength
.QuadPart
= 0;
1238 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1240 /* Get File Object */
1241 Status
= ObReferenceObjectByHandle(FileHandle
,
1245 (PVOID
*)&FileObject
,
1246 &HandleInformation
);
1247 if (!NT_SUCCESS(Status
)) return Status
;
1249 /* Check if we're called from user mode */
1250 if (PreviousMode
!= KernelMode
)
1252 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1253 if (!(HandleInformation
.GrantedAccess
&
1254 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1256 ObDereferenceObject(FileObject
);
1257 return STATUS_ACCESS_DENIED
;
1260 /* Enter SEH for probing */
1263 /* Probe the I/O STatus block */
1264 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1266 /* Probe and capture the large integers */
1267 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1268 CapturedLength
= ProbeForReadLargeInteger(Length
);
1270 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1272 /* Dereference the object and return exception code */
1273 ObDereferenceObject(FileObject
);
1274 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1280 /* Otherwise, capture them directly */
1281 CapturedByteOffset
= *ByteOffset
;
1282 CapturedLength
= *Length
;
1285 /* Check if we have an event handle */
1289 Status
= ObReferenceObjectByHandle(EventHandle
,
1295 if (Status
!= STATUS_SUCCESS
) return Status
;
1296 KeClearEvent(Event
);
1299 /* Get the device object */
1300 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1302 /* Check if we should use Sync IO or not */
1303 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1306 IopLockFileObject(FileObject
);
1307 LockedForSync
= TRUE
;
1310 /* Clear File Object event */
1311 KeClearEvent(&FileObject
->Event
);
1312 FileObject
->LockOperation
= TRUE
;
1314 /* Allocate the IRP */
1315 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1316 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1318 /* Set up the IRP */
1319 Irp
->RequestorMode
= PreviousMode
;
1320 Irp
->UserIosb
= IoStatusBlock
;
1321 Irp
->UserEvent
= Event
;
1322 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1323 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1324 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1325 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1327 /* Set up Stack Data */
1328 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1329 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1330 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1331 StackPtr
->FileObject
= FileObject
;
1333 /* Allocate local buffer */
1334 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1335 sizeof(LARGE_INTEGER
),
1339 /* Allocating failed, clean up and return failure */
1340 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1341 return STATUS_INSUFFICIENT_RESOURCES
;
1344 /* Set the length */
1345 *LocalLength
= CapturedLength
;
1346 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1347 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1349 /* Set Parameters */
1350 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1351 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1354 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1355 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1357 /* Perform the call */
1358 return IopPerformSynchronousRequest(DeviceObject
,
1372 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1373 IN HANDLE EventHandle OPTIONAL
,
1374 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1375 IN PVOID ApcContext OPTIONAL
,
1376 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1377 OUT PVOID FileInformation
,
1379 IN FILE_INFORMATION_CLASS FileInformationClass
,
1380 IN BOOLEAN ReturnSingleEntry
,
1381 IN PUNICODE_STRING FileName OPTIONAL
,
1382 IN BOOLEAN RestartScan
)
1385 PDEVICE_OBJECT DeviceObject
;
1386 PFILE_OBJECT FileObject
;
1387 PIO_STACK_LOCATION StackPtr
;
1388 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1390 BOOLEAN LockedForSynch
= FALSE
;
1391 PKEVENT Event
= NULL
;
1392 volatile PVOID AuxBuffer
= NULL
;
1394 UNICODE_STRING CapturedFileName
;
1395 PUNICODE_STRING SearchPattern
;
1397 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1399 /* Check if we came from user mode */
1400 if (PreviousMode
!= KernelMode
)
1402 /* Enter SEH for probing */
1405 /* Probe the I/O Status Block */
1406 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1408 /* Probe the file information */
1409 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1411 /* Check if we have a file name */
1415 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1416 if (CapturedFileName
.Length
)
1418 /* Probe its buffer */
1419 ProbeForRead(CapturedFileName
.Buffer
,
1420 CapturedFileName
.Length
,
1424 /* Allocate the auxiliary buffer */
1425 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1426 CapturedFileName
.Length
+
1427 sizeof(UNICODE_STRING
),
1429 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1430 sizeof(UNICODE_STRING
)),
1431 CapturedFileName
.Buffer
,
1432 CapturedFileName
.Length
);
1434 /* Setup the search pattern */
1435 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1436 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1437 sizeof(UNICODE_STRING
));
1438 SearchPattern
->Length
= CapturedFileName
.Length
;
1439 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1442 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1444 /* Free buffer and return the exception code */
1445 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1446 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1451 /* Get File Object */
1452 Status
= ObReferenceObjectByHandle(FileHandle
,
1453 FILE_LIST_DIRECTORY
,
1456 (PVOID
*)&FileObject
,
1458 if (!NT_SUCCESS(Status
))
1461 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1465 /* Check if we have an even handle */
1468 /* Get its pointer */
1469 Status
= ObReferenceObjectByHandle(EventHandle
,
1475 if (!NT_SUCCESS(Status
))
1478 ObDereferenceObject(FileObject
);
1483 KeClearEvent(Event
);
1486 /* Check if this is a file that was opened for Synch I/O */
1487 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1490 IopLockFileObject(FileObject
);
1492 /* Remember to unlock later */
1493 LockedForSynch
= TRUE
;
1496 /* Get the device object */
1497 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1499 /* Clear the File Object's event */
1500 KeClearEvent(&FileObject
->Event
);
1502 /* Allocate the IRP */
1503 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1504 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1506 /* Set up the IRP */
1507 Irp
->RequestorMode
= PreviousMode
;
1508 Irp
->UserIosb
= IoStatusBlock
;
1509 Irp
->UserEvent
= Event
;
1510 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1511 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1512 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1513 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1514 Irp
->MdlAddress
= NULL
;
1515 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1516 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1518 /* Check if this is buffered I/O */
1519 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1521 /* Allocate a buffer */
1522 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1525 if (!Irp
->AssociatedIrp
.SystemBuffer
)
1527 /* Allocating failed, clean up and return the exception code */
1528 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1529 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1531 /* Return the exception code */
1532 return STATUS_INSUFFICIENT_RESOURCES
;
1535 /* Set the buffer and flags */
1536 Irp
->UserBuffer
= FileInformation
;
1537 Irp
->Flags
= (IRP_BUFFERED_IO
|
1538 IRP_DEALLOCATE_BUFFER
|
1539 IRP_INPUT_OPERATION
);
1541 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1545 /* Allocate an MDL */
1546 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1547 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1548 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1550 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1552 /* Allocating failed, clean up and return the exception code */
1553 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1554 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1560 /* No allocation flags, and use the buffer directly */
1561 Irp
->UserBuffer
= FileInformation
;
1564 /* Set up Stack Data */
1565 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1566 StackPtr
->FileObject
= FileObject
;
1567 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1568 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1570 /* Set Parameters */
1571 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1572 FileInformationClass
;
1573 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1574 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1575 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1576 StackPtr
->Flags
= 0;
1577 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1578 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1580 /* Set deferred I/O */
1581 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1583 /* Perform the call */
1584 return IopPerformSynchronousRequest(DeviceObject
,
1598 NtQueryEaFile(IN HANDLE FileHandle
,
1599 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1602 IN BOOLEAN ReturnSingleEntry
,
1603 IN PVOID EaList OPTIONAL
,
1604 IN ULONG EaListLength
,
1605 IN PULONG EaIndex OPTIONAL
,
1606 IN BOOLEAN RestartScan
)
1609 return STATUS_NOT_IMPLEMENTED
;
1617 NtQueryInformationFile(IN HANDLE FileHandle
,
1618 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1619 IN PVOID FileInformation
,
1621 IN FILE_INFORMATION_CLASS FileInformationClass
)
1623 OBJECT_HANDLE_INFORMATION HandleInformation
;
1624 PFILE_OBJECT FileObject
;
1627 PDEVICE_OBJECT DeviceObject
;
1628 PIO_STACK_LOCATION StackPtr
;
1629 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1630 PKEVENT Event
= NULL
;
1631 BOOLEAN LocalEvent
= FALSE
;
1632 PKNORMAL_ROUTINE NormalRoutine
;
1633 PVOID NormalContext
;
1635 IO_STATUS_BLOCK KernelIosb
;
1637 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1639 /* Check if we're called from user mode */
1640 if (PreviousMode
!= KernelMode
)
1642 /* Validate the information class */
1643 if ((FileInformationClass
>= FileMaximumInformation
) ||
1644 !(IopQueryOperationLength
[FileInformationClass
]))
1647 return STATUS_INVALID_INFO_CLASS
;
1650 /* Validate the length */
1651 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1653 /* Invalid length */
1654 return STATUS_INFO_LENGTH_MISMATCH
;
1657 /* Enter SEH for probing */
1660 /* Probe the I/O Status block */
1661 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1663 /* Probe the information */
1664 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1666 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1668 /* Return the exception code */
1669 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1675 /* Validate the information class */
1676 if ((FileInformationClass
>= FileMaximumInformation
) ||
1677 !(IopQueryOperationLength
[FileInformationClass
]))
1680 return STATUS_INVALID_INFO_CLASS
;
1683 /* Validate the length */
1684 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1686 /* Invalid length */
1687 return STATUS_INFO_LENGTH_MISMATCH
;
1691 /* Reference the Handle */
1692 Status
= ObReferenceObjectByHandle(FileHandle
,
1693 IopQueryOperationAccess
1694 [FileInformationClass
],
1697 (PVOID
*)&FileObject
,
1698 &HandleInformation
);
1699 if (!NT_SUCCESS(Status
)) return Status
;
1701 /* Check if this is a direct open or not */
1702 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1704 /* Get the device object */
1705 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1709 /* Get the device object */
1710 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1713 /* Check if this is a file that was opened for Synch I/O */
1714 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1717 IopLockFileObject(FileObject
);
1719 /* Check if the caller just wants the position */
1720 if (FileInformationClass
== FilePositionInformation
)
1722 /* Protect write in SEH */
1725 /* Write the offset */
1726 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1727 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1729 /* Fill out the I/O Status Block */
1730 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1731 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1733 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1735 /* Get the exception code */
1736 Status
= _SEH2_GetExceptionCode();
1740 /* Release the file lock, dereference the file and return */
1741 IopUnlockFileObject(FileObject
);
1742 ObDereferenceObject(FileObject
);
1748 /* Use local event */
1749 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1752 ObDereferenceObject(FileObject
);
1753 return STATUS_INSUFFICIENT_RESOURCES
;
1755 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1759 /* Clear the File Object event */
1760 KeClearEvent(&FileObject
->Event
);
1762 /* Allocate the IRP */
1763 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1764 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1767 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1768 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1769 Irp
->RequestorMode
= PreviousMode
;
1770 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1771 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1772 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1773 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1774 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1775 Irp
->MdlAddress
= NULL
;
1776 Irp
->UserBuffer
= FileInformation
;
1778 /* Set the Stack Data */
1779 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1780 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1781 StackPtr
->FileObject
= FileObject
;
1786 /* Allocate a buffer */
1787 Irp
->AssociatedIrp
.SystemBuffer
=
1788 ExAllocatePoolWithTag(NonPagedPool
,
1792 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1794 /* Allocating failed, clean up and return the exception code */
1795 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
1796 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1801 Irp
->Flags
|= (IRP_BUFFERED_IO
|
1802 IRP_DEALLOCATE_BUFFER
|
1803 IRP_INPUT_OPERATION
|
1804 IRP_DEFER_IO_COMPLETION
);
1806 /* Set the Parameters */
1807 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1808 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1811 IopQueueIrpToThread(Irp
);
1813 /* Update operation counts */
1814 IopUpdateOperationCount(IopOtherTransfer
);
1816 /* Call the Driver */
1817 Status
= IoCallDriver(DeviceObject
, Irp
);
1818 if (Status
== STATUS_PENDING
)
1820 /* Check if this was async I/O */
1823 /* Then to a non-alertable wait */
1824 Status
= KeWaitForSingleObject(Event
,
1829 if (Status
== STATUS_USER_APC
)
1831 /* Abort the request */
1832 IopAbortInterruptedIrp(Event
, Irp
);
1835 /* Set the final status */
1836 Status
= KernelIosb
.Status
;
1838 /* Enter SEH to write the IOSB back */
1841 /* Write it back to the caller */
1842 *IoStatusBlock
= KernelIosb
;
1844 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1846 /* Get the exception code */
1847 Status
= _SEH2_GetExceptionCode();
1851 /* Free the event */
1852 ExFreePoolWithTag(Event
, TAG_IO
);
1856 /* Wait for the IRP */
1857 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1860 (FileObject
->Flags
&
1861 FO_ALERTABLE_IO
) != 0,
1863 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
1865 /* Abort the request */
1866 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1869 /* Set the final status */
1870 Status
= FileObject
->FinalStatus
;
1872 /* Release the file lock */
1873 IopUnlockFileObject(FileObject
);
1878 /* Free the event if we had one */
1881 /* Clear it in the IRP for completion */
1882 Irp
->UserEvent
= NULL
;
1883 ExFreePoolWithTag(Event
, TAG_IO
);
1886 /* Set the caller IOSB */
1887 Irp
->UserIosb
= IoStatusBlock
;
1889 /* The IRP wasn't completed, complete it ourselves */
1890 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1891 IopCompleteRequest(&Irp
->Tail
.Apc
,
1894 (PVOID
*)&FileObject
,
1896 KeLowerIrql(OldIrql
);
1898 /* Release the file object if we had locked it*/
1899 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
1902 /* Return the Status */
1911 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
1912 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1915 IN BOOLEAN ReturnSingleEntry
,
1916 IN PVOID SidList OPTIONAL
,
1917 IN ULONG SidListLength
,
1918 IN PSID StartSid OPTIONAL
,
1919 IN BOOLEAN RestartScan
)
1922 return STATUS_NOT_IMPLEMENTED
;
1930 NtReadFile(IN HANDLE FileHandle
,
1931 IN HANDLE Event OPTIONAL
,
1932 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1933 IN PVOID ApcContext OPTIONAL
,
1934 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1937 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
1938 IN PULONG Key OPTIONAL
)
1941 PFILE_OBJECT FileObject
;
1943 PDEVICE_OBJECT DeviceObject
;
1944 PIO_STACK_LOCATION StackPtr
;
1945 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1946 PKEVENT EventObject
= NULL
;
1947 LARGE_INTEGER CapturedByteOffset
;
1948 ULONG CapturedKey
= 0;
1949 BOOLEAN Synchronous
= FALSE
;
1952 CapturedByteOffset
.QuadPart
= 0;
1953 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1955 /* Validate User-Mode Buffers */
1956 if (PreviousMode
!= KernelMode
)
1960 /* Probe the status block */
1961 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1963 /* Probe the read buffer */
1964 ProbeForWrite(Buffer
, Length
, 1);
1966 /* Check if we got a byte offset */
1969 /* Capture and probe it */
1970 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1973 /* Capture and probe the key */
1974 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
1976 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1978 /* Return the exception code */
1979 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1985 /* Kernel mode: capture directly */
1986 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
1987 if (Key
) CapturedKey
= *Key
;
1990 /* Get File Object */
1991 Status
= ObReferenceObjectByHandle(FileHandle
,
1995 (PVOID
*)&FileObject
,
1997 if (!NT_SUCCESS(Status
)) return Status
;
1999 /* Check for event */
2003 Status
= ObReferenceObjectByHandle(Event
,
2007 (PVOID
*)&EventObject
,
2009 if (!NT_SUCCESS(Status
))
2012 ObDereferenceObject(FileObject
);
2016 /* Otherwise reset the event */
2017 KeClearEvent(EventObject
);
2020 /* Check if we should use Sync IO or not */
2021 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2023 /* Lock the file object */
2024 IopLockFileObject(FileObject
);
2026 /* Check if we don't have a byte offset avilable */
2027 if (!(ByteOffset
) ||
2028 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2029 (CapturedByteOffset
.u
.HighPart
== -1)))
2031 /* Use the Current Byte Offset instead */
2032 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2035 /* Remember we are sync */
2038 else if (!(ByteOffset
) &&
2039 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2041 /* Otherwise, this was async I/O without a byte offset, so fail */
2042 if (EventObject
) ObDereferenceObject(EventObject
);
2043 ObDereferenceObject(FileObject
);
2044 return STATUS_INVALID_PARAMETER
;
2047 /* Get the device object */
2048 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2050 /* Clear the File Object's event */
2051 KeClearEvent(&FileObject
->Event
);
2053 /* Allocate the IRP */
2054 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2055 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2058 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2059 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2060 Irp
->RequestorMode
= PreviousMode
;
2061 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2062 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2063 Irp
->UserIosb
= IoStatusBlock
;
2064 Irp
->UserEvent
= EventObject
;
2065 Irp
->PendingReturned
= FALSE
;
2066 Irp
->Cancel
= FALSE
;
2067 Irp
->CancelRoutine
= NULL
;
2068 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2069 Irp
->MdlAddress
= NULL
;
2071 /* Set the Stack Data */
2072 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2073 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2074 StackPtr
->FileObject
= FileObject
;
2075 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2076 StackPtr
->Parameters
.Read
.Length
= Length
;
2077 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2079 /* Check if this is buffered I/O */
2080 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2082 /* Check if we have a buffer length */
2088 /* Allocate a buffer */
2089 Irp
->AssociatedIrp
.SystemBuffer
=
2090 ExAllocatePoolWithTag(NonPagedPool
,
2094 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2096 /* Allocating failed, clean up and return the exception code */
2097 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2098 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2102 /* Set the buffer and flags */
2103 Irp
->UserBuffer
= Buffer
;
2104 Irp
->Flags
= (IRP_BUFFERED_IO
|
2105 IRP_DEALLOCATE_BUFFER
|
2106 IRP_INPUT_OPERATION
);
2110 /* Not reading anything */
2111 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2114 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2116 /* Check if we have a buffer length */
2121 /* Allocate an MDL */
2122 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2123 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2125 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2127 /* Allocating failed, clean up and return the exception code */
2128 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2129 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2135 /* No allocation flags */
2140 /* No allocation flags, and use the buffer directly */
2142 Irp
->UserBuffer
= Buffer
;
2145 /* Now set the deferred read flags */
2146 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2148 /* FIXME: VFAT SUCKS */
2149 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2152 /* Perform the call */
2153 return IopPerformSynchronousRequest(DeviceObject
,
2167 NtReadFileScatter(IN HANDLE FileHandle
,
2168 IN HANDLE Event OPTIONAL
,
2169 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2170 IN PVOID UserApcContext OPTIONAL
,
2171 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2172 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2173 IN ULONG BufferLength
,
2174 IN PLARGE_INTEGER ByteOffset
,
2175 IN PULONG Key OPTIONAL
)
2178 return STATUS_NOT_IMPLEMENTED
;
2186 NtSetEaFile(IN HANDLE FileHandle
,
2187 IN PIO_STATUS_BLOCK IoStatusBlock
,
2189 IN ULONG EaBufferSize
)
2192 return STATUS_NOT_IMPLEMENTED
;
2200 NtSetInformationFile(IN HANDLE FileHandle
,
2201 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2202 IN PVOID FileInformation
,
2204 IN FILE_INFORMATION_CLASS FileInformationClass
)
2206 PFILE_OBJECT FileObject
;
2209 PDEVICE_OBJECT DeviceObject
;
2210 PIO_STACK_LOCATION StackPtr
;
2211 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2212 PKEVENT Event
= NULL
;
2213 BOOLEAN LocalEvent
= FALSE
;
2214 PKNORMAL_ROUTINE NormalRoutine
;
2215 PVOID NormalContext
;
2217 IO_STATUS_BLOCK KernelIosb
;
2219 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2220 PIO_COMPLETION_CONTEXT Context
;
2222 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2224 /* Check if we're called from user mode */
2225 if (PreviousMode
!= KernelMode
)
2227 /* Validate the information class */
2228 if ((FileInformationClass
>= FileMaximumInformation
) ||
2229 !(IopSetOperationLength
[FileInformationClass
]))
2232 return STATUS_INVALID_INFO_CLASS
;
2235 /* Validate the length */
2236 if (Length
< IopSetOperationLength
[FileInformationClass
])
2238 /* Invalid length */
2239 return STATUS_INFO_LENGTH_MISMATCH
;
2242 /* Enter SEH for probing */
2245 /* Probe the I/O Status block */
2246 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2248 /* Probe the information */
2249 ProbeForRead(FileInformation
,
2251 (Length
== sizeof(BOOLEAN
)) ?
2252 sizeof(BOOLEAN
) : sizeof(ULONG
));
2254 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2256 /* Return the exception code */
2257 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2263 /* Validate the information class */
2264 if ((FileInformationClass
>= FileMaximumInformation
) ||
2265 !(IopSetOperationLength
[FileInformationClass
]))
2268 return STATUS_INVALID_INFO_CLASS
;
2271 /* Validate the length */
2272 if (Length
< IopSetOperationLength
[FileInformationClass
])
2274 /* Invalid length */
2275 return STATUS_INFO_LENGTH_MISMATCH
;
2279 /* Reference the Handle */
2280 Status
= ObReferenceObjectByHandle(FileHandle
,
2281 IopSetOperationAccess
2282 [FileInformationClass
],
2285 (PVOID
*)&FileObject
,
2287 if (!NT_SUCCESS(Status
)) return Status
;
2289 /* Check if this is a direct open or not */
2290 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2292 /* Get the device object */
2293 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2297 /* Get the device object */
2298 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2301 /* Check if this is a file that was opened for Synch I/O */
2302 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2305 IopLockFileObject(FileObject
);
2307 /* Check if the caller just wants the position */
2308 if (FileInformationClass
== FilePositionInformation
)
2310 /* Protect write in SEH */
2313 /* Write the offset */
2314 FileObject
->CurrentByteOffset
=
2315 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2318 /* Fill out the I/O Status Block */
2319 IoStatusBlock
->Information
= 0;
2320 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2322 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2324 /* Get the exception code */
2325 Status
= _SEH2_GetExceptionCode();
2329 /* Update transfer count */
2330 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2332 /* Release the file lock, dereference the file and return */
2333 IopUnlockFileObject(FileObject
);
2334 ObDereferenceObject(FileObject
);
2340 /* Use local event */
2341 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2344 ObDereferenceObject(FileObject
);
2345 return STATUS_INSUFFICIENT_RESOURCES
;
2348 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2352 /* Clear the File Object event */
2353 KeClearEvent(&FileObject
->Event
);
2355 /* Allocate the IRP */
2356 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2357 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2360 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2361 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2362 Irp
->RequestorMode
= PreviousMode
;
2363 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2364 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2365 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2366 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2367 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2368 Irp
->MdlAddress
= NULL
;
2369 Irp
->UserBuffer
= FileInformation
;
2371 /* Set the Stack Data */
2372 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2373 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2374 StackPtr
->FileObject
= FileObject
;
2379 /* Allocate a buffer */
2380 Irp
->AssociatedIrp
.SystemBuffer
=
2381 ExAllocatePoolWithTag(NonPagedPool
,
2385 /* Copy the data into it */
2386 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2390 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2392 /* Allocating failed, clean up and return the exception code */
2393 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2394 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2399 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2400 IRP_DEALLOCATE_BUFFER
|
2401 IRP_DEFER_IO_COMPLETION
);
2403 /* Set the Parameters */
2404 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2405 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2408 IopQueueIrpToThread(Irp
);
2410 /* Update operation counts */
2411 IopUpdateOperationCount(IopOtherTransfer
);
2413 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2414 /* Handle IO Completion Port quickly */
2415 if (FileInformationClass
== FileCompletionInformation
)
2417 /* Check if the file object already has a completion port */
2418 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2419 (FileObject
->CompletionContext
))
2422 Status
= STATUS_INVALID_PARAMETER
;
2426 /* Reference the Port */
2427 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2428 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2429 IO_COMPLETION_MODIFY_STATE
,
2434 if (NT_SUCCESS(Status
))
2436 /* Allocate the Context */
2437 Context
= ExAllocatePoolWithTag(PagedPool
,
2438 sizeof(IO_COMPLETION_CONTEXT
),
2443 Context
->Key
= CompletionInfo
->Key
;
2444 Context
->Port
= Queue
;
2445 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
2451 * Someone else set the completion port in the
2452 * meanwhile, so dereference the port and fail.
2454 ExFreePoolWithTag(Context
, IOC_TAG
);
2455 ObDereferenceObject(Queue
);
2456 Status
= STATUS_INVALID_PARAMETER
;
2461 /* Dereference the Port now */
2462 ObDereferenceObject(Queue
);
2463 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2468 /* Set the IRP Status */
2469 Irp
->IoStatus
.Status
= Status
;
2470 Irp
->IoStatus
.Information
= 0;
2474 /* Call the Driver */
2475 Status
= IoCallDriver(DeviceObject
, Irp
);
2478 /* Check if we're waiting for the IRP to complete */
2479 if (Status
== STATUS_PENDING
)
2481 /* Check if this was async I/O */
2484 /* Then to a non-alertable wait */
2485 Status
= KeWaitForSingleObject(Event
,
2490 if (Status
== STATUS_USER_APC
)
2492 /* Abort the request */
2493 IopAbortInterruptedIrp(Event
, Irp
);
2496 /* Set the final status */
2497 Status
= KernelIosb
.Status
;
2499 /* Enter SEH to write the IOSB back */
2502 /* Write it back to the caller */
2503 *IoStatusBlock
= KernelIosb
;
2505 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2507 /* Get the exception code */
2508 Status
= _SEH2_GetExceptionCode();
2512 /* Free the event */
2513 ExFreePoolWithTag(Event
, TAG_IO
);
2517 /* Wait for the IRP */
2518 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2521 (FileObject
->Flags
&
2522 FO_ALERTABLE_IO
) != 0,
2524 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2526 /* Abort the request */
2527 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2530 /* Set the final status */
2531 Status
= FileObject
->FinalStatus
;
2533 /* Release the file lock */
2534 IopUnlockFileObject(FileObject
);
2539 /* Free the event if we had one */
2542 /* Clear it in the IRP for completion */
2543 Irp
->UserEvent
= NULL
;
2544 ExFreePoolWithTag(Event
, TAG_IO
);
2547 /* Set the caller IOSB */
2548 Irp
->UserIosb
= IoStatusBlock
;
2550 /* The IRP wasn't completed, complete it ourselves */
2551 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2552 IopCompleteRequest(&Irp
->Tail
.Apc
,
2555 (PVOID
*)&FileObject
,
2557 KeLowerIrql(OldIrql
);
2559 /* Release the file object if we had locked it*/
2560 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2563 /* Return the Status */
2572 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2573 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2575 IN ULONG BufferLength
)
2578 return STATUS_NOT_IMPLEMENTED
;
2586 NtUnlockFile(IN HANDLE FileHandle
,
2587 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2588 IN PLARGE_INTEGER ByteOffset
,
2589 IN PLARGE_INTEGER Length
,
2590 IN ULONG Key OPTIONAL
)
2592 PFILE_OBJECT FileObject
;
2593 PLARGE_INTEGER LocalLength
= NULL
;
2595 PIO_STACK_LOCATION StackPtr
;
2596 PDEVICE_OBJECT DeviceObject
;
2597 PKEVENT Event
= NULL
;
2598 BOOLEAN LocalEvent
= FALSE
;
2599 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2600 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2602 OBJECT_HANDLE_INFORMATION HandleInformation
;
2603 IO_STATUS_BLOCK KernelIosb
;
2605 CapturedByteOffset
.QuadPart
= 0;
2606 CapturedLength
.QuadPart
= 0;
2607 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2609 /* Get File Object */
2610 Status
= ObReferenceObjectByHandle(FileHandle
,
2614 (PVOID
*)&FileObject
,
2615 &HandleInformation
);
2616 if (!NT_SUCCESS(Status
)) return Status
;
2618 /* Check if we're called from user mode */
2619 if (PreviousMode
!= KernelMode
)
2621 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2622 if (!(HandleInformation
.GrantedAccess
&
2623 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2625 ObDereferenceObject(FileObject
);
2626 return STATUS_ACCESS_DENIED
;
2629 /* Enter SEH for probing */
2632 /* Probe the I/O Status block */
2633 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2635 /* Probe and capture the large integers */
2636 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2637 CapturedLength
= ProbeForReadLargeInteger(Length
);
2639 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2641 /* Dereference the object and return exception code */
2642 ObDereferenceObject(FileObject
);
2643 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2649 /* Otherwise, capture them directly */
2650 CapturedByteOffset
= *ByteOffset
;
2651 CapturedLength
= *Length
;
2654 /* Check if this is a direct open or not */
2655 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2657 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2661 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2664 /* Check if we should use Sync IO or not */
2665 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2668 IopLockFileObject(FileObject
);
2672 /* Use local event */
2673 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2676 ObDereferenceObject(FileObject
);
2677 return STATUS_INSUFFICIENT_RESOURCES
;
2679 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2683 /* Clear File Object event */
2684 KeClearEvent(&FileObject
->Event
);
2686 /* Allocate the IRP */
2687 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2688 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2690 /* Set up the IRP */
2691 Irp
->RequestorMode
= PreviousMode
;
2692 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2693 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2694 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2695 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2696 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2697 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2699 /* Set up Stack Data */
2700 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2701 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2702 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2703 StackPtr
->FileObject
= FileObject
;
2708 /* Allocate a buffer */
2709 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2710 sizeof(LARGE_INTEGER
),
2713 /* Set the length */
2714 *LocalLength
= CapturedLength
;
2715 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
2716 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2718 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2720 /* Allocating failed, clean up and return the exception code */
2721 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2722 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
2724 /* Return the exception code */
2725 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2729 /* Set Parameters */
2730 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
2731 StackPtr
->Parameters
.LockControl
.Key
= Key
;
2733 /* Call the Driver */
2734 Status
= IopPerformSynchronousRequest(DeviceObject
,
2742 /* Check if this was async I/O */
2745 /* It was, finalize this request */
2746 Status
= IopFinalizeAsynchronousIo(Status
,
2763 NtWriteFile(IN HANDLE FileHandle
,
2764 IN HANDLE Event OPTIONAL
,
2765 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2766 IN PVOID ApcContext OPTIONAL
,
2767 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2770 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2771 IN PULONG Key OPTIONAL
)
2774 PFILE_OBJECT FileObject
;
2776 PDEVICE_OBJECT DeviceObject
;
2777 PIO_STACK_LOCATION StackPtr
;
2778 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2779 PKEVENT EventObject
= NULL
;
2780 LARGE_INTEGER CapturedByteOffset
;
2781 ULONG CapturedKey
= 0;
2782 BOOLEAN Synchronous
= FALSE
;
2784 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
2786 CapturedByteOffset
.QuadPart
= 0;
2787 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2789 /* Get File Object */
2790 Status
= ObReferenceObjectByHandle(FileHandle
,
2794 (PVOID
*)&FileObject
,
2796 if (!NT_SUCCESS(Status
)) return Status
;
2798 /* Validate User-Mode Buffers */
2799 if (PreviousMode
!= KernelMode
)
2804 * Check if the handle has either FILE_WRITE_DATA or
2805 * FILE_APPEND_DATA granted. However, if this is a named pipe,
2806 * make sure we don't ask for FILE_APPEND_DATA as it interferes
2807 * with the FILE_CREATE_PIPE_INSTANCE access right!
2809 if (!(ObjectHandleInfo
.GrantedAccess
&
2810 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
2811 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
2814 ObDereferenceObject(FileObject
);
2815 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
2818 /* Probe the status block */
2819 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2821 /* Probe the read buffer */
2822 ProbeForRead(Buffer
, Length
, 1);
2824 /* Check if we got a byte offset */
2827 /* Capture and probe it */
2828 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2831 /* Capture and probe the key */
2832 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2834 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2836 /* Return the exception code */
2837 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2843 /* Kernel mode: capture directly */
2844 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2845 if (Key
) CapturedKey
= *Key
;
2848 /* Check if this is an append operation */
2849 if ((ObjectHandleInfo
.GrantedAccess
&
2850 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
2852 /* Give the drivers something to understand */
2853 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
2854 CapturedByteOffset
.u
.HighPart
= -1;
2857 /* Check for event */
2861 Status
= ObReferenceObjectByHandle(Event
,
2865 (PVOID
*)&EventObject
,
2867 if (!NT_SUCCESS(Status
))
2870 ObDereferenceObject(FileObject
);
2874 /* Otherwise reset the event */
2875 KeClearEvent(EventObject
);
2878 /* Check if we should use Sync IO or not */
2879 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2881 /* Lock the file object */
2882 IopLockFileObject(FileObject
);
2884 /* Check if we don't have a byte offset avilable */
2885 if (!(ByteOffset
) ||
2886 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2887 (CapturedByteOffset
.u
.HighPart
== -1)))
2889 /* Use the Current Byte Offset instead */
2890 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2893 /* Remember we are sync */
2896 else if (!(ByteOffset
) &&
2897 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2899 /* Otherwise, this was async I/O without a byte offset, so fail */
2900 if (EventObject
) ObDereferenceObject(EventObject
);
2901 ObDereferenceObject(FileObject
);
2902 return STATUS_INVALID_PARAMETER
;
2905 /* Get the device object */
2906 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2908 /* Clear the File Object's event */
2909 KeClearEvent(&FileObject
->Event
);
2911 /* Allocate the IRP */
2912 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2913 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2916 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2917 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2918 Irp
->RequestorMode
= PreviousMode
;
2919 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2920 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2921 Irp
->UserIosb
= IoStatusBlock
;
2922 Irp
->UserEvent
= EventObject
;
2923 Irp
->PendingReturned
= FALSE
;
2924 Irp
->Cancel
= FALSE
;
2925 Irp
->CancelRoutine
= NULL
;
2926 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2927 Irp
->MdlAddress
= NULL
;
2929 /* Set the Stack Data */
2930 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2931 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
2932 StackPtr
->FileObject
= FileObject
;
2933 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
2934 SL_WRITE_THROUGH
: 0;
2935 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
2936 StackPtr
->Parameters
.Write
.Length
= Length
;
2937 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
2939 /* Check if this is buffered I/O */
2940 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2942 /* Check if we have a buffer length */
2948 /* Allocate a buffer */
2949 Irp
->AssociatedIrp
.SystemBuffer
=
2950 ExAllocatePoolWithTag(NonPagedPool
,
2954 /* Copy the data into it */
2955 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
2957 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2959 /* Allocating failed, clean up and return the exception code */
2960 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2961 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2966 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
2970 /* Not writing anything */
2971 Irp
->Flags
= IRP_BUFFERED_IO
;
2974 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2976 /* Check if we have a buffer length */
2981 /* Allocate an MDL */
2982 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2983 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
2985 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2987 /* Allocating failed, clean up and return the exception code */
2988 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2989 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2994 /* No allocation flags */
2999 /* No allocation flags, and use the buffer directly */
3001 Irp
->UserBuffer
= Buffer
;
3004 /* Now set the deferred read flags */
3005 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3007 /* FIXME: VFAT SUCKS */
3008 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3011 /* Perform the call */
3012 return IopPerformSynchronousRequest(DeviceObject
,
3023 NtWriteFileGather(IN HANDLE FileHandle
,
3024 IN HANDLE Event OPTIONAL
,
3025 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3026 IN PVOID UserApcContext OPTIONAL
,
3027 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3028 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3029 IN ULONG BufferLength
,
3030 IN PLARGE_INTEGER ByteOffset
,
3031 IN PULONG Key OPTIONAL
)
3034 return STATUS_NOT_IMPLEMENTED
;
3042 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3043 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3044 OUT PVOID FsInformation
,
3046 IN FS_INFORMATION_CLASS FsInformationClass
)
3048 PFILE_OBJECT FileObject
;
3050 PIO_STACK_LOCATION StackPtr
;
3051 PDEVICE_OBJECT DeviceObject
;
3052 PKEVENT Event
= NULL
;
3053 BOOLEAN LocalEvent
= FALSE
;
3054 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3056 IO_STATUS_BLOCK KernelIosb
;
3058 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3060 /* Check if we're called from user mode */
3061 if (PreviousMode
!= KernelMode
)
3063 /* Validate the information class */
3064 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3065 !(IopQueryFsOperationLength
[FsInformationClass
]))
3068 return STATUS_INVALID_INFO_CLASS
;
3071 /* Validate the length */
3072 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3074 /* Invalid length */
3075 return STATUS_INFO_LENGTH_MISMATCH
;
3078 /* Enter SEH for probing */
3081 /* Probe the I/O Status block */
3082 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3084 /* Probe the information */
3085 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3087 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3089 /* Return the exception code */
3090 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3095 /* Get File Object */
3096 Status
= ObReferenceObjectByHandle(FileHandle
,
3097 IopQueryFsOperationAccess
3098 [FsInformationClass
],
3101 (PVOID
*)&FileObject
,
3103 if (!NT_SUCCESS(Status
)) return Status
;
3105 /* Check if we should use Sync IO or not */
3106 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3109 IopLockFileObject(FileObject
);
3113 /* Use local event */
3114 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3117 ObDereferenceObject(FileObject
);
3118 return STATUS_INSUFFICIENT_RESOURCES
;
3120 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3124 /* Get the device object */
3125 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3127 /* Clear File Object event */
3128 KeClearEvent(&FileObject
->Event
);
3130 /* Allocate the IRP */
3131 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3132 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3134 /* Set up the IRP */
3135 Irp
->RequestorMode
= PreviousMode
;
3136 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3137 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3138 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3139 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3140 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3141 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3142 Irp
->UserBuffer
= FsInformation
;
3143 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3144 Irp
->MdlAddress
= NULL
;
3146 /* Set up Stack Data */
3147 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3148 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3149 StackPtr
->FileObject
= FileObject
;
3154 /* Allocate a buffer */
3155 Irp
->AssociatedIrp
.SystemBuffer
=
3156 ExAllocatePoolWithTag(NonPagedPool
,
3160 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3162 /* Allocating failed, clean up and return the exception code */
3163 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3164 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3168 /* Set the flags for this buffered + deferred I/O */
3169 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3170 IRP_DEALLOCATE_BUFFER
|
3171 IRP_INPUT_OPERATION
|
3172 IRP_DEFER_IO_COMPLETION
);
3174 /* Set Parameters */
3175 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3176 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3178 /* Call the Driver */
3179 Status
= IopPerformSynchronousRequest(DeviceObject
,
3187 /* Check if this was async I/O */
3190 /* It was, finalize this request */
3191 Status
= IopFinalizeAsynchronousIo(Status
,
3208 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3209 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3210 IN PVOID FsInformation
,
3212 IN FS_INFORMATION_CLASS FsInformationClass
)
3214 PFILE_OBJECT FileObject
;
3216 PIO_STACK_LOCATION StackPtr
;
3217 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3218 PKEVENT Event
= NULL
;
3219 BOOLEAN LocalEvent
= FALSE
;
3220 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3222 IO_STATUS_BLOCK KernelIosb
;
3223 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3225 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3227 /* Check if we're called from user mode */
3228 if (PreviousMode
!= KernelMode
)
3230 /* Validate the information class */
3231 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3232 !(IopSetFsOperationLength
[FsInformationClass
]))
3235 return STATUS_INVALID_INFO_CLASS
;
3238 /* Validate the length */
3239 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3241 /* Invalid length */
3242 return STATUS_INFO_LENGTH_MISMATCH
;
3245 /* Enter SEH for probing */
3248 /* Probe the I/O Status block */
3249 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3251 /* Probe the information */
3252 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3254 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3256 /* Return the exception code */
3257 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3262 /* Get File Object */
3263 Status
= ObReferenceObjectByHandle(FileHandle
,
3264 IopSetFsOperationAccess
3265 [FsInformationClass
],
3268 (PVOID
*)&FileObject
,
3270 if (!NT_SUCCESS(Status
)) return Status
;
3272 /* Get target device for notification */
3273 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
3274 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
3276 /* Check if we should use Sync IO or not */
3277 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3280 IopLockFileObject(FileObject
);
3284 /* Use local event */
3285 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3288 ObDereferenceObject(FileObject
);
3289 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3290 return STATUS_INSUFFICIENT_RESOURCES
;
3292 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3296 /* Get the device object */
3297 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3299 /* Clear File Object event */
3300 KeClearEvent(&FileObject
->Event
);
3302 /* Allocate the IRP */
3303 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3306 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3307 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3310 /* Set up the IRP */
3311 Irp
->RequestorMode
= PreviousMode
;
3312 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3313 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3314 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3315 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3316 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3317 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3318 Irp
->UserBuffer
= FsInformation
;
3319 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3320 Irp
->MdlAddress
= NULL
;
3322 /* Set up Stack Data */
3323 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3324 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3325 StackPtr
->FileObject
= FileObject
;
3330 /* Allocate a buffer */
3331 Irp
->AssociatedIrp
.SystemBuffer
=
3332 ExAllocatePoolWithTag(NonPagedPool
,
3336 /* Copy the data into it */
3337 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3339 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3341 /* Allocating failed, clean up and return the exception code */
3342 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3343 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3344 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3348 /* Set the flags for this buffered + deferred I/O */
3349 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3351 /* Set Parameters */
3352 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3353 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3355 /* Call the Driver */
3356 Status
= IopPerformSynchronousRequest(DeviceObject
,
3364 /* Check if this was async I/O */
3367 /* It was, finalize this request */
3368 Status
= IopFinalizeAsynchronousIo(Status
,
3376 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
3378 /* Time to report change */
3379 NotificationStructure
.Version
= 1;
3380 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
3381 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
3382 NotificationStructure
.FileObject
= NULL
;
3383 NotificationStructure
.NameBufferOffset
= - 1;
3384 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
3396 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3399 return STATUS_NOT_IMPLEMENTED
;
3407 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3410 return STATUS_NOT_IMPLEMENTED
;