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
;
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
,
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
,
606 FileObject
->Flags
& FO_ALERTABLE_IO
,
608 if (Status
== STATUS_ALERTED
)
610 /* Abort the operation */
611 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
614 /* Get the final status */
615 Status
= FileObject
->FinalStatus
;
618 /* Release the file lock */
619 IopUnlockFileObject(FileObject
);
621 else if (Status
== STATUS_PENDING
)
623 /* Wait on the local event and get the final status */
624 KeWaitForSingleObject(&Event
,
629 Status
= IoStatusBlock
.Status
;
632 /* Return the Length and Status. ReturnedLength is NOT optional */
633 *ReturnedLength
= IoStatusBlock
.Information
;
637 /* PUBLIC FUNCTIONS **********************************************************/
644 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
646 IN PLARGE_INTEGER Offset
,
648 IN PIO_STATUS_BLOCK StatusBlock
)
651 PIO_STACK_LOCATION StackPtr
;
652 PDEVICE_OBJECT DeviceObject
;
653 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
654 FileObject
, Mdl
, Offset
);
656 /* Get the Device Object */
657 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
660 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
661 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
664 StackPtr
= IoGetNextIrpStackLocation(Irp
);
666 /* Create the IRP Settings */
667 Irp
->MdlAddress
= Mdl
;
668 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
669 Irp
->UserIosb
= StatusBlock
;
670 Irp
->UserEvent
= Event
;
671 Irp
->RequestorMode
= KernelMode
;
672 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
673 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
674 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
676 /* Set the Stack Settings */
677 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
678 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
679 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
680 StackPtr
->FileObject
= FileObject
;
682 /* Call the Driver */
683 return IoCallDriver(DeviceObject
, Irp
);
691 IoPageRead(IN PFILE_OBJECT FileObject
,
693 IN PLARGE_INTEGER Offset
,
695 IN PIO_STATUS_BLOCK StatusBlock
)
698 PIO_STACK_LOCATION StackPtr
;
699 PDEVICE_OBJECT DeviceObject
;
700 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
701 FileObject
, Mdl
, Offset
);
703 /* Get the Device Object */
704 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
707 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
708 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
711 StackPtr
= IoGetNextIrpStackLocation(Irp
);
713 /* Create the IRP Settings */
714 Irp
->MdlAddress
= Mdl
;
715 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
716 Irp
->UserIosb
= StatusBlock
;
717 Irp
->UserEvent
= Event
;
718 Irp
->RequestorMode
= KernelMode
;
719 Irp
->Flags
= IRP_PAGING_IO
|
721 IRP_SYNCHRONOUS_PAGING_IO
|
723 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
724 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
726 /* Set the Stack Settings */
727 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
728 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
729 StackPtr
->MajorFunction
= IRP_MJ_READ
;
730 StackPtr
->FileObject
= FileObject
;
732 /* Call the Driver */
733 return IoCallDriver(DeviceObject
, Irp
);
741 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
742 IN FILE_INFORMATION_CLASS FileInformationClass
,
744 OUT PVOID FileInformation
,
745 OUT PULONG ReturnedLength
)
747 /* Call the shared routine */
748 return IopQueryDeviceInformation(FileObject
,
749 FileInformationClass
,
761 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
762 IN FS_INFORMATION_CLASS FsInformationClass
,
764 OUT PVOID FsInformation
,
765 OUT PULONG ReturnedLength
)
767 /* Call the shared routine */
768 return IopQueryDeviceInformation(FileObject
,
781 IoSetInformation(IN PFILE_OBJECT FileObject
,
782 IN FILE_INFORMATION_CLASS FileInformationClass
,
784 IN PVOID FileInformation
)
786 IO_STATUS_BLOCK IoStatusBlock
;
788 PDEVICE_OBJECT DeviceObject
;
789 PIO_STACK_LOCATION StackPtr
;
790 BOOLEAN LocalEvent
= FALSE
;
794 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
795 FileObject
, FileInformationClass
, Length
);
797 /* Reference the object */
798 ObReferenceObject(FileObject
);
800 /* Check if this is a file that was opened for Synch I/O */
801 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
804 IopLockFileObject(FileObject
);
806 /* Use File Object event */
807 KeClearEvent(&FileObject
->Event
);
811 /* Use local event */
812 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
816 /* Get the Device Object */
817 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
819 /* Allocate the IRP */
820 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
821 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
824 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
825 Irp
->RequestorMode
= KernelMode
;
826 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
827 Irp
->UserIosb
= &IoStatusBlock
;
828 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
829 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
830 Irp
->Flags
|= IRP_BUFFERED_IO
;
831 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
832 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
834 /* Set the Stack Data */
835 StackPtr
= IoGetNextIrpStackLocation(Irp
);
836 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
837 StackPtr
->FileObject
= FileObject
;
840 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
841 StackPtr
->Parameters
.SetFile
.Length
= Length
;
844 IopQueueIrpToThread(Irp
);
846 /* Call the Driver */
847 Status
= IoCallDriver(DeviceObject
, Irp
);
849 /* Check if this was synch I/O */
852 /* Check if the requet is pending */
853 if (Status
== STATUS_PENDING
)
855 /* Wait on the file object */
856 Status
= KeWaitForSingleObject(&FileObject
->Event
,
859 FileObject
->Flags
& FO_ALERTABLE_IO
,
861 if (Status
== STATUS_ALERTED
)
863 /* Abort the operation */
864 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
867 /* Get the final status */
868 Status
= FileObject
->FinalStatus
;
871 /* Release the file lock */
872 IopUnlockFileObject(FileObject
);
874 else if (Status
== STATUS_PENDING
)
876 /* Wait on the local event and get the final status */
877 KeWaitForSingleObject(&Event
,
882 Status
= IoStatusBlock
.Status
;
885 /* Return the status */
889 /* NATIVE SERVICES ***********************************************************/
896 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
897 IN HANDLE Event OPTIONAL
,
898 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
899 IN PVOID UserApcContext OPTIONAL
,
900 OUT PIO_STATUS_BLOCK IoStatusBlock
,
901 IN ULONG IoControlCode
,
902 IN PVOID InputBuffer
,
903 IN ULONG InputBufferLength OPTIONAL
,
904 OUT PVOID OutputBuffer
,
905 IN ULONG OutputBufferLength OPTIONAL
)
907 /* Call the Generic Function */
908 return IopDeviceFsIoControl(DeviceHandle
,
926 NtFsControlFile(IN HANDLE DeviceHandle
,
927 IN HANDLE Event OPTIONAL
,
928 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
929 IN PVOID UserApcContext OPTIONAL
,
930 OUT PIO_STATUS_BLOCK IoStatusBlock
,
931 IN ULONG IoControlCode
,
932 IN PVOID InputBuffer
,
933 IN ULONG InputBufferLength OPTIONAL
,
934 OUT PVOID OutputBuffer
,
935 IN ULONG OutputBufferLength OPTIONAL
)
937 /* Call the Generic Function */
938 return IopDeviceFsIoControl(DeviceHandle
,
953 NtFlushBuffersFile(IN HANDLE FileHandle
,
954 OUT PIO_STATUS_BLOCK IoStatusBlock
)
956 PFILE_OBJECT FileObject
;
958 PIO_STACK_LOCATION StackPtr
;
960 PDEVICE_OBJECT DeviceObject
;
961 PKEVENT Event
= NULL
;
962 BOOLEAN LocalEvent
= FALSE
;
963 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
964 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
965 IO_STATUS_BLOCK KernelIosb
;
967 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
969 if (PreviousMode
!= KernelMode
)
974 /* Probe the I/O Status block */
975 ProbeForWriteIoStatusBlock(IoStatusBlock
);
977 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
979 /* Return the exception code */
980 _SEH2_YIELD(return _SEH2_GetExceptionCode());
985 /* Get the File Object */
986 Status
= ObReferenceObjectByHandle(FileHandle
,
992 if (!NT_SUCCESS(Status
)) return Status
;
995 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
996 * granted. However, if this is a named pipe, make sure we don't ask for
997 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1000 if (!(ObjectHandleInfo
.GrantedAccess
&
1001 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1005 ObDereferenceObject(FileObject
);
1006 return STATUS_ACCESS_DENIED
;
1009 /* Check if we should use Sync IO or not */
1010 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1013 IopLockFileObject(FileObject
);
1017 /* Use local event */
1018 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1022 ObDereferenceObject(FileObject
);
1023 return STATUS_INSUFFICIENT_RESOURCES
;
1025 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1029 /* Get the Device Object */
1030 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1032 /* Clear the event */
1033 KeClearEvent(&FileObject
->Event
);
1035 /* Allocate the IRP */
1036 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1037 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1039 /* Set up the IRP */
1040 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1041 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1042 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1043 Irp
->RequestorMode
= PreviousMode
;
1044 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1045 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1046 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1048 /* Set up Stack Data */
1049 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1050 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1051 StackPtr
->FileObject
= FileObject
;
1053 /* Call the Driver */
1054 Status
= IopPerformSynchronousRequest(DeviceObject
,
1062 /* Check if this was async I/O */
1065 /* It was, finalize this request */
1066 Status
= IopFinalizeAsynchronousIo(Status
,
1074 /* Return the Status */
1083 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1084 IN HANDLE EventHandle OPTIONAL
,
1085 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1086 IN PVOID ApcContext OPTIONAL
,
1087 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1089 IN ULONG BufferSize
,
1090 IN ULONG CompletionFilter
,
1091 IN BOOLEAN WatchTree
)
1094 PKEVENT Event
= NULL
;
1095 PDEVICE_OBJECT DeviceObject
;
1096 PFILE_OBJECT FileObject
;
1097 PIO_STACK_LOCATION IoStack
;
1098 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1100 BOOLEAN LockedForSync
= FALSE
;
1102 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1104 /* Check if we're called from user mode */
1105 if (PreviousMode
!= KernelMode
)
1107 /* Enter SEH for probing */
1110 /* Probe the I/O STatus block */
1111 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1113 /* Probe the buffer */
1114 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1116 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1118 /* Return the exception code */
1119 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1123 /* Check if CompletionFilter is valid */
1124 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1126 return STATUS_INVALID_PARAMETER
;
1130 /* Get File Object */
1131 Status
= ObReferenceObjectByHandle(FileHandle
,
1132 FILE_LIST_DIRECTORY
,
1135 (PVOID
*)&FileObject
,
1137 if (!NT_SUCCESS(Status
)) return Status
;
1139 /* Check if we have an event handle */
1143 Status
= ObReferenceObjectByHandle(EventHandle
,
1149 if (Status
!= STATUS_SUCCESS
)
1151 ObDereferenceObject(FileObject
);
1154 KeClearEvent(Event
);
1157 /* Check if we should use Sync IO or not */
1158 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1161 IopLockFileObject(FileObject
);
1162 LockedForSync
= TRUE
;
1165 /* Clear File Object event */
1166 KeClearEvent(&FileObject
->Event
);
1168 /* Get the device object */
1169 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1171 /* Allocate the IRP */
1172 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1173 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1175 /* Set up the IRP */
1176 Irp
->RequestorMode
= PreviousMode
;
1177 Irp
->UserIosb
= IoStatusBlock
;
1178 Irp
->UserEvent
= Event
;
1179 Irp
->UserBuffer
= Buffer
;
1180 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1181 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1182 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1183 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1185 /* Set up Stack Data */
1186 IoStack
= IoGetNextIrpStackLocation(Irp
);
1187 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1188 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1189 IoStack
->FileObject
= FileObject
;
1191 /* Set parameters */
1192 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1193 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1194 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1196 /* Perform the call */
1197 return IopPerformSynchronousRequest(DeviceObject
,
1211 NtLockFile(IN HANDLE FileHandle
,
1212 IN HANDLE EventHandle OPTIONAL
,
1213 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1214 IN PVOID ApcContext OPTIONAL
,
1215 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1216 IN PLARGE_INTEGER ByteOffset
,
1217 IN PLARGE_INTEGER Length
,
1219 IN BOOLEAN FailImmediately
,
1220 IN BOOLEAN ExclusiveLock
)
1222 PFILE_OBJECT FileObject
;
1223 PLARGE_INTEGER LocalLength
= NULL
;
1225 PIO_STACK_LOCATION StackPtr
;
1226 PDEVICE_OBJECT DeviceObject
;
1227 PKEVENT Event
= NULL
;
1228 BOOLEAN LockedForSync
= FALSE
;
1229 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1230 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1232 OBJECT_HANDLE_INFORMATION HandleInformation
;
1234 CapturedByteOffset
.QuadPart
= 0;
1235 CapturedLength
.QuadPart
= 0;
1236 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1238 /* Get File Object */
1239 Status
= ObReferenceObjectByHandle(FileHandle
,
1243 (PVOID
*)&FileObject
,
1244 &HandleInformation
);
1245 if (!NT_SUCCESS(Status
)) return Status
;
1247 /* Check if we're called from user mode */
1248 if (PreviousMode
!= KernelMode
)
1250 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1251 if (!(HandleInformation
.GrantedAccess
&
1252 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1254 ObDereferenceObject(FileObject
);
1255 return STATUS_ACCESS_DENIED
;
1258 /* Enter SEH for probing */
1261 /* Probe the I/O STatus block */
1262 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1264 /* Probe and capture the large integers */
1265 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1266 CapturedLength
= ProbeForReadLargeInteger(Length
);
1268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1270 /* Dereference the object and return exception code */
1271 ObDereferenceObject(FileObject
);
1272 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1278 /* Otherwise, capture them directly */
1279 CapturedByteOffset
= *ByteOffset
;
1280 CapturedLength
= *Length
;
1283 /* Check if we have an event handle */
1287 Status
= ObReferenceObjectByHandle(EventHandle
,
1293 if (Status
!= STATUS_SUCCESS
) return Status
;
1294 KeClearEvent(Event
);
1297 /* Get the device object */
1298 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1300 /* Check if we should use Sync IO or not */
1301 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1304 IopLockFileObject(FileObject
);
1305 LockedForSync
= TRUE
;
1308 /* Clear File Object event */
1309 KeClearEvent(&FileObject
->Event
);
1310 FileObject
->LockOperation
= TRUE
;
1312 /* Allocate the IRP */
1313 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1314 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1316 /* Set up the IRP */
1317 Irp
->RequestorMode
= PreviousMode
;
1318 Irp
->UserIosb
= IoStatusBlock
;
1319 Irp
->UserEvent
= Event
;
1320 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1321 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1322 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1323 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1325 /* Set up Stack Data */
1326 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1327 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1328 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1329 StackPtr
->FileObject
= FileObject
;
1334 /* Allocate local buffer */
1335 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1336 sizeof(LARGE_INTEGER
),
1339 /* Set the length */
1340 *LocalLength
= CapturedLength
;
1341 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1342 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1344 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1346 /* Allocating failed, clean up and return the exception code */
1347 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1348 if (LocalLength
) ExFreePool(LocalLength
);
1350 /* Return the exception code */
1351 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1355 /* Set Parameters */
1356 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1357 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1360 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1361 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1363 /* Perform the call */
1364 return IopPerformSynchronousRequest(DeviceObject
,
1378 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1379 IN HANDLE EventHandle OPTIONAL
,
1380 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1381 IN PVOID ApcContext OPTIONAL
,
1382 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1383 OUT PVOID FileInformation
,
1385 IN FILE_INFORMATION_CLASS FileInformationClass
,
1386 IN BOOLEAN ReturnSingleEntry
,
1387 IN PUNICODE_STRING FileName OPTIONAL
,
1388 IN BOOLEAN RestartScan
)
1391 PDEVICE_OBJECT DeviceObject
;
1392 PFILE_OBJECT FileObject
;
1393 PIO_STACK_LOCATION StackPtr
;
1394 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1396 BOOLEAN LockedForSynch
= FALSE
;
1397 PKEVENT Event
= NULL
;
1398 PVOID AuxBuffer
= NULL
;
1400 UNICODE_STRING CapturedFileName
;
1401 PUNICODE_STRING SearchPattern
;
1403 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1405 /* Check if we came from user mode */
1406 if (PreviousMode
!= KernelMode
)
1408 /* Enter SEH for probing */
1411 /* Probe the I/O Status Block */
1412 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1414 /* Probe the file information */
1415 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1417 /* Check if we have a file name */
1421 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1422 if (CapturedFileName
.Length
)
1424 /* Probe its buffer */
1425 ProbeForRead(CapturedFileName
.Buffer
,
1426 CapturedFileName
.Length
,
1430 /* Allocate the auxiliary buffer */
1431 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1432 CapturedFileName
.Length
+
1433 sizeof(UNICODE_STRING
),
1435 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1436 sizeof(UNICODE_STRING
)),
1437 CapturedFileName
.Buffer
,
1438 CapturedFileName
.Length
);
1440 /* Setup the search pattern */
1441 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1442 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1443 sizeof(UNICODE_STRING
));
1444 SearchPattern
->Length
= CapturedFileName
.Length
;
1445 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1448 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1450 /* Free buffer and return the exception code */
1451 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1452 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1457 /* Get File Object */
1458 Status
= ObReferenceObjectByHandle(FileHandle
,
1459 FILE_LIST_DIRECTORY
,
1462 (PVOID
*)&FileObject
,
1464 if (!NT_SUCCESS(Status
))
1467 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1471 /* Check if we have an even handle */
1474 /* Get its pointer */
1475 Status
= ObReferenceObjectByHandle(EventHandle
,
1481 if (!NT_SUCCESS(Status
))
1484 ObDereferenceObject(FileObject
);
1489 KeClearEvent(Event
);
1492 /* Check if this is a file that was opened for Synch I/O */
1493 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1496 IopLockFileObject(FileObject
);
1498 /* Remember to unlock later */
1499 LockedForSynch
= TRUE
;
1502 /* Get the device object */
1503 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1505 /* Clear the File Object's event */
1506 KeClearEvent(&FileObject
->Event
);
1508 /* Allocate the IRP */
1509 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1510 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1512 /* Set up the IRP */
1513 Irp
->RequestorMode
= PreviousMode
;
1514 Irp
->UserIosb
= IoStatusBlock
;
1515 Irp
->UserEvent
= Event
;
1516 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1517 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1518 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1519 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1520 Irp
->MdlAddress
= NULL
;
1521 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1522 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1524 /* Check if this is buffered I/O */
1525 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1530 /* Allocate a buffer */
1531 Irp
->AssociatedIrp
.SystemBuffer
=
1532 ExAllocatePoolWithTag(NonPagedPool
,
1536 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1538 /* Allocating failed, clean up and return the exception code */
1539 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1540 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1542 /* Return the exception code */
1543 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1547 /* Set the buffer and flags */
1548 Irp
->UserBuffer
= FileInformation
;
1549 Irp
->Flags
= (IRP_BUFFERED_IO
|
1550 IRP_DEALLOCATE_BUFFER
|
1551 IRP_INPUT_OPERATION
);
1553 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1557 /* Allocate an MDL */
1558 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1559 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1560 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1562 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1564 /* Allocating failed, clean up and return the exception code */
1565 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1566 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1572 /* No allocation flags, and use the buffer directly */
1573 Irp
->UserBuffer
= FileInformation
;
1576 /* Set up Stack Data */
1577 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1578 StackPtr
->FileObject
= FileObject
;
1579 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1580 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1582 /* Set Parameters */
1583 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1584 FileInformationClass
;
1585 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1586 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1587 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1588 StackPtr
->Flags
= 0;
1589 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1590 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1592 /* Set deferred I/O */
1593 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1595 /* Perform the call */
1596 return IopPerformSynchronousRequest(DeviceObject
,
1610 NtQueryEaFile(IN HANDLE FileHandle
,
1611 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1614 IN BOOLEAN ReturnSingleEntry
,
1615 IN PVOID EaList OPTIONAL
,
1616 IN ULONG EaListLength
,
1617 IN PULONG EaIndex OPTIONAL
,
1618 IN BOOLEAN RestartScan
)
1621 return STATUS_NOT_IMPLEMENTED
;
1629 NtQueryInformationFile(IN HANDLE FileHandle
,
1630 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1631 IN PVOID FileInformation
,
1633 IN FILE_INFORMATION_CLASS FileInformationClass
)
1635 OBJECT_HANDLE_INFORMATION HandleInformation
;
1636 PFILE_OBJECT FileObject
;
1639 PDEVICE_OBJECT DeviceObject
;
1640 PIO_STACK_LOCATION StackPtr
;
1641 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1642 PKEVENT Event
= NULL
;
1643 BOOLEAN LocalEvent
= FALSE
;
1644 PKNORMAL_ROUTINE NormalRoutine
;
1645 PVOID NormalContext
;
1647 IO_STATUS_BLOCK KernelIosb
;
1649 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1651 /* Check if we're called from user mode */
1652 if (PreviousMode
!= KernelMode
)
1654 /* Validate the information class */
1655 if ((FileInformationClass
>= FileMaximumInformation
) ||
1656 !(IopQueryOperationLength
[FileInformationClass
]))
1659 return STATUS_INVALID_INFO_CLASS
;
1662 /* Validate the length */
1663 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1665 /* Invalid length */
1666 return STATUS_INFO_LENGTH_MISMATCH
;
1669 /* Enter SEH for probing */
1672 /* Probe the I/O Status block */
1673 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1675 /* Probe the information */
1676 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1678 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1680 /* Return the exception code */
1681 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1687 /* Validate the information class */
1688 if ((FileInformationClass
>= FileMaximumInformation
) ||
1689 !(IopQueryOperationLength
[FileInformationClass
]))
1692 return STATUS_INVALID_INFO_CLASS
;
1695 /* Validate the length */
1696 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1698 /* Invalid length */
1699 return STATUS_INFO_LENGTH_MISMATCH
;
1703 /* Reference the Handle */
1704 Status
= ObReferenceObjectByHandle(FileHandle
,
1705 IopQueryOperationAccess
1706 [FileInformationClass
],
1709 (PVOID
*)&FileObject
,
1710 &HandleInformation
);
1711 if (!NT_SUCCESS(Status
)) return Status
;
1713 /* Check if this is a direct open or not */
1714 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1716 /* Get the device object */
1717 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1721 /* Get the device object */
1722 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1725 /* Check if this is a file that was opened for Synch I/O */
1726 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1729 IopLockFileObject(FileObject
);
1731 /* Check if the caller just wants the position */
1732 if (FileInformationClass
== FilePositionInformation
)
1734 /* Protect write in SEH */
1737 /* Write the offset */
1738 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1739 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1741 /* Fill out the I/O Status Block */
1742 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1743 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1745 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1747 /* Get the exception code */
1748 Status
= _SEH2_GetExceptionCode();
1752 /* Release the file lock, dereference the file and return */
1753 IopUnlockFileObject(FileObject
);
1754 ObDereferenceObject(FileObject
);
1760 /* Use local event */
1761 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1764 ObDereferenceObject(FileObject
);
1765 return STATUS_INSUFFICIENT_RESOURCES
;
1767 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1771 /* Clear the File Object event */
1772 KeClearEvent(&FileObject
->Event
);
1774 /* Allocate the IRP */
1775 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1776 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1779 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1780 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1781 Irp
->RequestorMode
= PreviousMode
;
1782 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1783 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1784 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1785 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1786 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1787 Irp
->MdlAddress
= NULL
;
1788 Irp
->UserBuffer
= FileInformation
;
1790 /* Set the Stack Data */
1791 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1792 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1793 StackPtr
->FileObject
= FileObject
;
1798 /* Allocate a buffer */
1799 Irp
->AssociatedIrp
.SystemBuffer
=
1800 ExAllocatePoolWithTag(NonPagedPool
,
1804 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1806 /* Allocating failed, clean up and return the exception code */
1807 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
1808 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1813 Irp
->Flags
|= (IRP_BUFFERED_IO
|
1814 IRP_DEALLOCATE_BUFFER
|
1815 IRP_INPUT_OPERATION
|
1816 IRP_DEFER_IO_COMPLETION
);
1818 /* Set the Parameters */
1819 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1820 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1823 IopQueueIrpToThread(Irp
);
1825 /* Update operation counts */
1826 IopUpdateOperationCount(IopOtherTransfer
);
1828 /* Call the Driver */
1829 Status
= IoCallDriver(DeviceObject
, Irp
);
1830 if (Status
== STATUS_PENDING
)
1832 /* Check if this was async I/O */
1835 /* Then to a non-alertable wait */
1836 Status
= KeWaitForSingleObject(Event
,
1841 if (Status
== STATUS_USER_APC
)
1843 /* Abort the request */
1844 IopAbortInterruptedIrp(Event
, Irp
);
1847 /* Set the final status */
1848 Status
= KernelIosb
.Status
;
1850 /* Enter SEH to write the IOSB back */
1853 /* Write it back to the caller */
1854 *IoStatusBlock
= KernelIosb
;
1856 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1858 /* Get the exception code */
1859 Status
= _SEH2_GetExceptionCode();
1863 /* Free the event */
1868 /* Wait for the IRP */
1869 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1872 FileObject
->Flags
& FO_ALERTABLE_IO
,
1874 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
1876 /* Abort the request */
1877 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1880 /* Set the final status */
1881 Status
= FileObject
->FinalStatus
;
1883 /* Release the file lock */
1884 IopUnlockFileObject(FileObject
);
1889 /* Free the event if we had one */
1892 /* Clear it in the IRP for completion */
1893 Irp
->UserEvent
= NULL
;
1894 ExFreePoolWithTag(Event
, TAG_IO
);
1897 /* Set the caller IOSB */
1898 Irp
->UserIosb
= IoStatusBlock
;
1900 /* The IRP wasn't completed, complete it ourselves */
1901 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1902 IopCompleteRequest(&Irp
->Tail
.Apc
,
1905 (PVOID
*)&FileObject
,
1907 KeLowerIrql(OldIrql
);
1909 /* Release the file object if we had locked it*/
1910 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
1913 /* Return the Status */
1922 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
1923 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1926 IN BOOLEAN ReturnSingleEntry
,
1927 IN PVOID SidList OPTIONAL
,
1928 IN ULONG SidListLength
,
1929 IN PSID StartSid OPTIONAL
,
1930 IN BOOLEAN RestartScan
)
1933 return STATUS_NOT_IMPLEMENTED
;
1941 NtReadFile(IN HANDLE FileHandle
,
1942 IN HANDLE Event OPTIONAL
,
1943 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1944 IN PVOID ApcContext OPTIONAL
,
1945 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1948 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
1949 IN PULONG Key OPTIONAL
)
1952 PFILE_OBJECT FileObject
;
1954 PDEVICE_OBJECT DeviceObject
;
1955 PIO_STACK_LOCATION StackPtr
;
1956 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1957 PKEVENT EventObject
= NULL
;
1958 LARGE_INTEGER CapturedByteOffset
;
1959 ULONG CapturedKey
= 0;
1960 BOOLEAN Synchronous
= FALSE
;
1963 CapturedByteOffset
.QuadPart
= 0;
1964 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1966 /* Validate User-Mode Buffers */
1967 if (PreviousMode
!= KernelMode
)
1971 /* Probe the status block */
1972 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1974 /* Probe the read buffer */
1975 ProbeForWrite(Buffer
, Length
, 1);
1977 /* Check if we got a byte offset */
1980 /* Capture and probe it */
1981 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1984 /* Capture and probe the key */
1985 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
1987 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1989 /* Return the exception code */
1990 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1996 /* Kernel mode: capture directly */
1997 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
1998 if (Key
) CapturedKey
= *Key
;
2001 /* Get File Object */
2002 Status
= ObReferenceObjectByHandle(FileHandle
,
2006 (PVOID
*)&FileObject
,
2008 if (!NT_SUCCESS(Status
)) return Status
;
2010 /* Check for event */
2014 Status
= ObReferenceObjectByHandle(Event
,
2018 (PVOID
*)&EventObject
,
2020 if (!NT_SUCCESS(Status
))
2023 ObDereferenceObject(FileObject
);
2027 /* Otherwise reset the event */
2028 KeClearEvent(EventObject
);
2031 /* Check if we should use Sync IO or not */
2032 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2034 /* Lock the file object */
2035 IopLockFileObject(FileObject
);
2037 /* Check if we don't have a byte offset avilable */
2038 if (!(ByteOffset
) ||
2039 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2040 (CapturedByteOffset
.u
.HighPart
== -1)))
2042 /* Use the Current Byte Offset instead */
2043 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2046 /* Remember we are sync */
2049 else if (!(ByteOffset
) &&
2050 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2052 /* Otherwise, this was async I/O without a byte offset, so fail */
2053 if (EventObject
) ObDereferenceObject(EventObject
);
2054 ObDereferenceObject(FileObject
);
2055 return STATUS_INVALID_PARAMETER
;
2058 /* Get the device object */
2059 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2061 /* Clear the File Object's event */
2062 KeClearEvent(&FileObject
->Event
);
2064 /* Allocate the IRP */
2065 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2066 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2069 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2070 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2071 Irp
->RequestorMode
= PreviousMode
;
2072 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2073 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2074 Irp
->UserIosb
= IoStatusBlock
;
2075 Irp
->UserEvent
= EventObject
;
2076 Irp
->PendingReturned
= FALSE
;
2077 Irp
->Cancel
= FALSE
;
2078 Irp
->CancelRoutine
= NULL
;
2079 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2080 Irp
->MdlAddress
= NULL
;
2082 /* Set the Stack Data */
2083 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2084 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2085 StackPtr
->FileObject
= FileObject
;
2086 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2087 StackPtr
->Parameters
.Read
.Length
= Length
;
2088 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2090 /* Check if this is buffered I/O */
2091 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2093 /* Check if we have a buffer length */
2099 /* Allocate a buffer */
2100 Irp
->AssociatedIrp
.SystemBuffer
=
2101 ExAllocatePoolWithTag(NonPagedPool
,
2105 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2107 /* Allocating failed, clean up and return the exception code */
2108 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2109 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2113 /* Set the buffer and flags */
2114 Irp
->UserBuffer
= Buffer
;
2115 Irp
->Flags
= (IRP_BUFFERED_IO
|
2116 IRP_DEALLOCATE_BUFFER
|
2117 IRP_INPUT_OPERATION
);
2121 /* Not reading anything */
2122 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2125 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2127 /* Check if we have a buffer length */
2132 /* Allocate an MDL */
2133 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2134 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2136 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2138 /* Allocating failed, clean up and return the exception code */
2139 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2140 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2146 /* No allocation flags */
2151 /* No allocation flags, and use the buffer directly */
2153 Irp
->UserBuffer
= Buffer
;
2156 /* Now set the deferred read flags */
2157 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2159 /* FIXME: VFAT SUCKS */
2160 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2163 /* Perform the call */
2164 return IopPerformSynchronousRequest(DeviceObject
,
2178 NtReadFileScatter(IN HANDLE FileHandle
,
2179 IN HANDLE Event OPTIONAL
,
2180 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2181 IN PVOID UserApcContext OPTIONAL
,
2182 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2183 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2184 IN ULONG BufferLength
,
2185 IN PLARGE_INTEGER ByteOffset
,
2186 IN PULONG Key OPTIONAL
)
2189 return STATUS_NOT_IMPLEMENTED
;
2197 NtSetEaFile(IN HANDLE FileHandle
,
2198 IN PIO_STATUS_BLOCK IoStatusBlock
,
2200 IN ULONG EaBufferSize
)
2203 return STATUS_NOT_IMPLEMENTED
;
2211 NtSetInformationFile(IN HANDLE FileHandle
,
2212 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2213 IN PVOID FileInformation
,
2215 IN FILE_INFORMATION_CLASS FileInformationClass
)
2217 PFILE_OBJECT FileObject
;
2220 PDEVICE_OBJECT DeviceObject
;
2221 PIO_STACK_LOCATION StackPtr
;
2222 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2223 PKEVENT Event
= NULL
;
2224 BOOLEAN LocalEvent
= FALSE
;
2225 PKNORMAL_ROUTINE NormalRoutine
;
2226 PVOID NormalContext
;
2228 IO_STATUS_BLOCK KernelIosb
;
2230 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2231 PIO_COMPLETION_CONTEXT Context
;
2233 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2235 /* Check if we're called from user mode */
2236 if (PreviousMode
!= KernelMode
)
2238 /* Validate the information class */
2239 if ((FileInformationClass
>= FileMaximumInformation
) ||
2240 !(IopSetOperationLength
[FileInformationClass
]))
2243 return STATUS_INVALID_INFO_CLASS
;
2246 /* Validate the length */
2247 if (Length
< IopSetOperationLength
[FileInformationClass
])
2249 /* Invalid length */
2250 return STATUS_INFO_LENGTH_MISMATCH
;
2253 /* Enter SEH for probing */
2256 /* Probe the I/O Status block */
2257 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2259 /* Probe the information */
2260 ProbeForRead(FileInformation
,
2262 (Length
== sizeof(BOOLEAN
)) ?
2263 sizeof(BOOLEAN
) : sizeof(ULONG
));
2265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2267 /* Return the exception code */
2268 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2274 /* Validate the information class */
2275 if ((FileInformationClass
>= FileMaximumInformation
) ||
2276 !(IopSetOperationLength
[FileInformationClass
]))
2279 return STATUS_INVALID_INFO_CLASS
;
2282 /* Validate the length */
2283 if (Length
< IopSetOperationLength
[FileInformationClass
])
2285 /* Invalid length */
2286 return STATUS_INFO_LENGTH_MISMATCH
;
2290 /* Reference the Handle */
2291 Status
= ObReferenceObjectByHandle(FileHandle
,
2292 IopSetOperationAccess
2293 [FileInformationClass
],
2296 (PVOID
*)&FileObject
,
2298 if (!NT_SUCCESS(Status
)) return Status
;
2300 /* Check if this is a direct open or not */
2301 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2303 /* Get the device object */
2304 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2308 /* Get the device object */
2309 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2312 /* Check if this is a file that was opened for Synch I/O */
2313 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2316 IopLockFileObject(FileObject
);
2318 /* Check if the caller just wants the position */
2319 if (FileInformationClass
== FilePositionInformation
)
2321 /* Protect write in SEH */
2324 /* Write the offset */
2325 FileObject
->CurrentByteOffset
=
2326 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2329 /* Fill out the I/O Status Block */
2330 IoStatusBlock
->Information
= 0;
2331 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2333 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2335 /* Get the exception code */
2336 Status
= _SEH2_GetExceptionCode();
2340 /* Update transfer count */
2341 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2343 /* Release the file lock, dereference the file and return */
2344 IopUnlockFileObject(FileObject
);
2345 ObDereferenceObject(FileObject
);
2351 /* Use local event */
2352 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2355 ObDereferenceObject(FileObject
);
2356 return STATUS_INSUFFICIENT_RESOURCES
;
2359 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2363 /* Clear the File Object event */
2364 KeClearEvent(&FileObject
->Event
);
2366 /* Allocate the IRP */
2367 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2368 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2371 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2372 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2373 Irp
->RequestorMode
= PreviousMode
;
2374 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2375 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2376 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2377 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2378 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2379 Irp
->MdlAddress
= NULL
;
2380 Irp
->UserBuffer
= FileInformation
;
2382 /* Set the Stack Data */
2383 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2384 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2385 StackPtr
->FileObject
= FileObject
;
2390 /* Allocate a buffer */
2391 Irp
->AssociatedIrp
.SystemBuffer
=
2392 ExAllocatePoolWithTag(NonPagedPool
,
2396 /* Copy the data into it */
2397 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2401 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2403 /* Allocating failed, clean up and return the exception code */
2404 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2405 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2410 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2411 IRP_DEALLOCATE_BUFFER
|
2412 IRP_DEFER_IO_COMPLETION
);
2414 /* Set the Parameters */
2415 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2416 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2419 IopQueueIrpToThread(Irp
);
2421 /* Update operation counts */
2422 IopUpdateOperationCount(IopOtherTransfer
);
2424 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2425 /* Handle IO Completion Port quickly */
2426 if (FileInformationClass
== FileCompletionInformation
)
2428 /* Check if the file object already has a completion port */
2429 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2430 (FileObject
->CompletionContext
))
2433 Status
= STATUS_INVALID_PARAMETER
;
2437 /* Reference the Port */
2438 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2439 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2440 IO_COMPLETION_MODIFY_STATE
,
2445 if (NT_SUCCESS(Status
))
2447 /* Allocate the Context */
2448 Context
= ExAllocatePoolWithTag(PagedPool
,
2449 sizeof(IO_COMPLETION_CONTEXT
),
2454 Context
->Key
= CompletionInfo
->Key
;
2455 Context
->Port
= Queue
;
2456 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
2462 * Someone else set the completion port in the
2463 * meanwhile, so dereference the port and fail.
2465 ExFreePool(Context
);
2466 ObDereferenceObject(Queue
);
2467 Status
= STATUS_INVALID_PARAMETER
;
2472 /* Dereference the Port now */
2473 ObDereferenceObject(Queue
);
2474 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2479 /* Set the IRP Status */
2480 Irp
->IoStatus
.Status
= Status
;
2481 Irp
->IoStatus
.Information
= 0;
2485 /* Call the Driver */
2486 Status
= IoCallDriver(DeviceObject
, Irp
);
2489 /* Check if we're waiting for the IRP to complete */
2490 if (Status
== STATUS_PENDING
)
2492 /* Check if this was async I/O */
2495 /* Then to a non-alertable wait */
2496 Status
= KeWaitForSingleObject(Event
,
2501 if (Status
== STATUS_USER_APC
)
2503 /* Abort the request */
2504 IopAbortInterruptedIrp(Event
, Irp
);
2507 /* Set the final status */
2508 Status
= KernelIosb
.Status
;
2510 /* Enter SEH to write the IOSB back */
2513 /* Write it back to the caller */
2514 *IoStatusBlock
= KernelIosb
;
2516 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2518 /* Get the exception code */
2519 Status
= _SEH2_GetExceptionCode();
2523 /* Free the event */
2528 /* Wait for the IRP */
2529 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2532 FileObject
->Flags
& FO_ALERTABLE_IO
,
2534 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2536 /* Abort the request */
2537 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2540 /* Set the final status */
2541 Status
= FileObject
->FinalStatus
;
2543 /* Release the file lock */
2544 IopUnlockFileObject(FileObject
);
2549 /* Free the event if we had one */
2552 /* Clear it in the IRP for completion */
2553 Irp
->UserEvent
= NULL
;
2557 /* Set the caller IOSB */
2558 Irp
->UserIosb
= IoStatusBlock
;
2560 /* The IRP wasn't completed, complete it ourselves */
2561 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2562 IopCompleteRequest(&Irp
->Tail
.Apc
,
2565 (PVOID
*)&FileObject
,
2567 KeLowerIrql(OldIrql
);
2569 /* Release the file object if we had locked it*/
2570 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2573 /* Return the Status */
2582 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2583 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2585 IN ULONG BufferLength
)
2588 return STATUS_NOT_IMPLEMENTED
;
2596 NtUnlockFile(IN HANDLE FileHandle
,
2597 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2598 IN PLARGE_INTEGER ByteOffset
,
2599 IN PLARGE_INTEGER Length
,
2600 IN ULONG Key OPTIONAL
)
2602 PFILE_OBJECT FileObject
;
2603 PLARGE_INTEGER LocalLength
= NULL
;
2605 PIO_STACK_LOCATION StackPtr
;
2606 PDEVICE_OBJECT DeviceObject
;
2607 PKEVENT Event
= NULL
;
2608 BOOLEAN LocalEvent
= FALSE
;
2609 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2610 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2612 OBJECT_HANDLE_INFORMATION HandleInformation
;
2613 IO_STATUS_BLOCK KernelIosb
;
2615 CapturedByteOffset
.QuadPart
= 0;
2616 CapturedLength
.QuadPart
= 0;
2617 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2619 /* Get File Object */
2620 Status
= ObReferenceObjectByHandle(FileHandle
,
2624 (PVOID
*)&FileObject
,
2625 &HandleInformation
);
2626 if (!NT_SUCCESS(Status
)) return Status
;
2628 /* Check if we're called from user mode */
2629 if (PreviousMode
!= KernelMode
)
2631 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2632 if (!(HandleInformation
.GrantedAccess
&
2633 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2635 ObDereferenceObject(FileObject
);
2636 return STATUS_ACCESS_DENIED
;
2639 /* Enter SEH for probing */
2642 /* Probe the I/O Status block */
2643 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2645 /* Probe and capture the large integers */
2646 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2647 CapturedLength
= ProbeForReadLargeInteger(Length
);
2649 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2651 /* Dereference the object and return exception code */
2652 ObDereferenceObject(FileObject
);
2653 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2659 /* Otherwise, capture them directly */
2660 CapturedByteOffset
= *ByteOffset
;
2661 CapturedLength
= *Length
;
2664 /* Check if this is a direct open or not */
2665 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2667 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2671 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2674 /* Check if we should use Sync IO or not */
2675 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2678 IopLockFileObject(FileObject
);
2682 /* Use local event */
2683 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2686 ObDereferenceObject(FileObject
);
2687 return STATUS_INSUFFICIENT_RESOURCES
;
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 and return the exception code */
2731 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2732 if (LocalLength
) ExFreePool(LocalLength
);
2734 /* Return the exception code */
2735 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2739 /* Set Parameters */
2740 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
2741 StackPtr
->Parameters
.LockControl
.Key
= Key
;
2743 /* Call the Driver */
2744 Status
= IopPerformSynchronousRequest(DeviceObject
,
2752 /* Check if this was async I/O */
2755 /* It was, finalize this request */
2756 Status
= IopFinalizeAsynchronousIo(Status
,
2773 NtWriteFile(IN HANDLE FileHandle
,
2774 IN HANDLE Event OPTIONAL
,
2775 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2776 IN PVOID ApcContext OPTIONAL
,
2777 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2780 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2781 IN PULONG Key OPTIONAL
)
2784 PFILE_OBJECT FileObject
;
2786 PDEVICE_OBJECT DeviceObject
;
2787 PIO_STACK_LOCATION StackPtr
;
2788 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2789 PKEVENT EventObject
= NULL
;
2790 LARGE_INTEGER CapturedByteOffset
;
2791 ULONG CapturedKey
= 0;
2792 BOOLEAN Synchronous
= FALSE
;
2794 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
2796 CapturedByteOffset
.QuadPart
= 0;
2797 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2799 /* Get File Object */
2800 Status
= ObReferenceObjectByHandle(FileHandle
,
2804 (PVOID
*)&FileObject
,
2806 if (!NT_SUCCESS(Status
)) return Status
;
2808 /* Validate User-Mode Buffers */
2809 if (PreviousMode
!= KernelMode
)
2814 * Check if the handle has either FILE_WRITE_DATA or
2815 * FILE_APPEND_DATA granted. However, if this is a named pipe,
2816 * make sure we don't ask for FILE_APPEND_DATA as it interferes
2817 * with the FILE_CREATE_PIPE_INSTANCE access right!
2819 if (!(ObjectHandleInfo
.GrantedAccess
&
2820 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
2821 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
2824 ObDereferenceObject(FileObject
);
2825 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
2828 /* Probe the status block */
2829 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2831 /* Probe the read buffer */
2832 ProbeForRead(Buffer
, Length
, 1);
2834 /* Check if we got a byte offset */
2837 /* Capture and probe it */
2838 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2841 /* Capture and probe the key */
2842 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2844 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2846 /* Return the exception code */
2847 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2853 /* Kernel mode: capture directly */
2854 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2855 if (Key
) CapturedKey
= *Key
;
2858 /* Check if this is an append operation */
2859 if ((ObjectHandleInfo
.GrantedAccess
&
2860 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
2862 /* Give the drivers something to understand */
2863 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
2864 CapturedByteOffset
.u
.HighPart
= -1;
2867 /* Check for event */
2871 Status
= ObReferenceObjectByHandle(Event
,
2875 (PVOID
*)&EventObject
,
2877 if (!NT_SUCCESS(Status
))
2880 ObDereferenceObject(FileObject
);
2884 /* Otherwise reset the event */
2885 KeClearEvent(EventObject
);
2888 /* Check if we should use Sync IO or not */
2889 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2891 /* Lock the file object */
2892 IopLockFileObject(FileObject
);
2894 /* Check if we don't have a byte offset avilable */
2895 if (!(ByteOffset
) ||
2896 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2897 (CapturedByteOffset
.u
.HighPart
== -1)))
2899 /* Use the Current Byte Offset instead */
2900 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2903 /* Remember we are sync */
2906 else if (!(ByteOffset
) &&
2907 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2909 /* Otherwise, this was async I/O without a byte offset, so fail */
2910 if (EventObject
) ObDereferenceObject(EventObject
);
2911 ObDereferenceObject(FileObject
);
2912 return STATUS_INVALID_PARAMETER
;
2915 /* Get the device object */
2916 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2918 /* Clear the File Object's event */
2919 KeClearEvent(&FileObject
->Event
);
2921 /* Allocate the IRP */
2922 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2923 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2926 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2927 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2928 Irp
->RequestorMode
= PreviousMode
;
2929 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2930 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2931 Irp
->UserIosb
= IoStatusBlock
;
2932 Irp
->UserEvent
= EventObject
;
2933 Irp
->PendingReturned
= FALSE
;
2934 Irp
->Cancel
= FALSE
;
2935 Irp
->CancelRoutine
= NULL
;
2936 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2937 Irp
->MdlAddress
= NULL
;
2939 /* Set the Stack Data */
2940 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2941 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
2942 StackPtr
->FileObject
= FileObject
;
2943 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
2944 SL_WRITE_THROUGH
: 0;
2945 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
2946 StackPtr
->Parameters
.Write
.Length
= Length
;
2947 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
2949 /* Check if this is buffered I/O */
2950 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2952 /* Check if we have a buffer length */
2958 /* Allocate a buffer */
2959 Irp
->AssociatedIrp
.SystemBuffer
=
2960 ExAllocatePoolWithTag(NonPagedPool
,
2964 /* Copy the data into it */
2965 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
2967 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2969 /* Allocating failed, clean up and return the exception code */
2970 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2971 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2976 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
2980 /* Not writing anything */
2981 Irp
->Flags
= IRP_BUFFERED_IO
;
2984 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2986 /* Check if we have a buffer length */
2991 /* Allocate an MDL */
2992 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2993 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
2995 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2997 /* Allocating failed, clean up and return the exception code */
2998 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2999 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3004 /* No allocation flags */
3009 /* No allocation flags, and use the buffer directly */
3011 Irp
->UserBuffer
= Buffer
;
3014 /* Now set the deferred read flags */
3015 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3017 /* FIXME: VFAT SUCKS */
3018 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3021 /* Perform the call */
3022 return IopPerformSynchronousRequest(DeviceObject
,
3033 NtWriteFileGather(IN HANDLE FileHandle
,
3034 IN HANDLE Event OPTIONAL
,
3035 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3036 IN PVOID UserApcContext OPTIONAL
,
3037 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3038 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3039 IN ULONG BufferLength
,
3040 IN PLARGE_INTEGER ByteOffset
,
3041 IN PULONG Key OPTIONAL
)
3044 return STATUS_NOT_IMPLEMENTED
;
3052 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3053 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3054 OUT PVOID FsInformation
,
3056 IN FS_INFORMATION_CLASS FsInformationClass
)
3058 PFILE_OBJECT FileObject
;
3060 PIO_STACK_LOCATION StackPtr
;
3061 PDEVICE_OBJECT DeviceObject
;
3062 PKEVENT Event
= NULL
;
3063 BOOLEAN LocalEvent
= FALSE
;
3064 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3066 IO_STATUS_BLOCK KernelIosb
;
3068 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3070 /* Check if we're called from user mode */
3071 if (PreviousMode
!= KernelMode
)
3073 /* Validate the information class */
3074 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3075 !(IopQueryFsOperationLength
[FsInformationClass
]))
3078 return STATUS_INVALID_INFO_CLASS
;
3081 /* Validate the length */
3082 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3084 /* Invalid length */
3085 return STATUS_INFO_LENGTH_MISMATCH
;
3088 /* Enter SEH for probing */
3091 /* Probe the I/O Status block */
3092 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3094 /* Probe the information */
3095 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3097 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3099 /* Return the exception code */
3100 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3105 /* Get File Object */
3106 Status
= ObReferenceObjectByHandle(FileHandle
,
3107 IopQueryFsOperationAccess
3108 [FsInformationClass
],
3111 (PVOID
*)&FileObject
,
3113 if (!NT_SUCCESS(Status
)) return Status
;
3115 /* Check if we should use Sync IO or not */
3116 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3119 IopLockFileObject(FileObject
);
3123 /* Use local event */
3124 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3127 ObDereferenceObject(FileObject
);
3128 return STATUS_INSUFFICIENT_RESOURCES
;
3130 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3134 /* Get the device object */
3135 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3137 /* Clear File Object event */
3138 KeClearEvent(&FileObject
->Event
);
3140 /* Allocate the IRP */
3141 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3142 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3144 /* Set up the IRP */
3145 Irp
->RequestorMode
= PreviousMode
;
3146 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3147 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3148 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3149 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3150 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3151 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3152 Irp
->UserBuffer
= FsInformation
;
3153 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3154 Irp
->MdlAddress
= NULL
;
3156 /* Set up Stack Data */
3157 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3158 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3159 StackPtr
->FileObject
= FileObject
;
3164 /* Allocate a buffer */
3165 Irp
->AssociatedIrp
.SystemBuffer
=
3166 ExAllocatePoolWithTag(NonPagedPool
,
3170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3172 /* Allocating failed, clean up and return the exception code */
3173 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3174 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3178 /* Set the flags for this buffered + deferred I/O */
3179 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3180 IRP_DEALLOCATE_BUFFER
|
3181 IRP_INPUT_OPERATION
|
3182 IRP_DEFER_IO_COMPLETION
);
3184 /* Set Parameters */
3185 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3186 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3188 /* Call the Driver */
3189 Status
= IopPerformSynchronousRequest(DeviceObject
,
3197 /* Check if this was async I/O */
3200 /* It was, finalize this request */
3201 Status
= IopFinalizeAsynchronousIo(Status
,
3218 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3219 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3220 IN PVOID FsInformation
,
3222 IN FS_INFORMATION_CLASS FsInformationClass
)
3224 PFILE_OBJECT FileObject
;
3226 PIO_STACK_LOCATION StackPtr
;
3227 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3228 PKEVENT Event
= NULL
;
3229 BOOLEAN LocalEvent
= FALSE
;
3230 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3232 IO_STATUS_BLOCK KernelIosb
;
3233 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3235 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3237 /* Check if we're called from user mode */
3238 if (PreviousMode
!= KernelMode
)
3240 /* Validate the information class */
3241 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3242 !(IopSetFsOperationLength
[FsInformationClass
]))
3245 return STATUS_INVALID_INFO_CLASS
;
3248 /* Validate the length */
3249 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3251 /* Invalid length */
3252 return STATUS_INFO_LENGTH_MISMATCH
;
3255 /* Enter SEH for probing */
3258 /* Probe the I/O Status block */
3259 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3261 /* Probe the information */
3262 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3264 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3266 /* Return the exception code */
3267 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3272 /* Get File Object */
3273 Status
= ObReferenceObjectByHandle(FileHandle
,
3274 IopSetFsOperationAccess
3275 [FsInformationClass
],
3278 (PVOID
*)&FileObject
,
3280 if (!NT_SUCCESS(Status
)) return Status
;
3282 /* Get target device for notification */
3283 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
3284 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
3286 /* Check if we should use Sync IO or not */
3287 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3290 IopLockFileObject(FileObject
);
3294 /* Use local event */
3295 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3298 ObDereferenceObject(FileObject
);
3299 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3300 return STATUS_INSUFFICIENT_RESOURCES
;
3302 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3306 /* Get the device object */
3307 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3309 /* Clear File Object event */
3310 KeClearEvent(&FileObject
->Event
);
3312 /* Allocate the IRP */
3313 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3316 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3317 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3320 /* Set up the IRP */
3321 Irp
->RequestorMode
= PreviousMode
;
3322 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3323 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3324 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3325 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3326 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3327 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3328 Irp
->UserBuffer
= FsInformation
;
3329 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3330 Irp
->MdlAddress
= NULL
;
3332 /* Set up Stack Data */
3333 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3334 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3335 StackPtr
->FileObject
= FileObject
;
3340 /* Allocate a buffer */
3341 Irp
->AssociatedIrp
.SystemBuffer
=
3342 ExAllocatePoolWithTag(NonPagedPool
,
3346 /* Copy the data into it */
3347 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3349 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3351 /* Allocating failed, clean up and return the exception code */
3352 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3353 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3354 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3358 /* Set the flags for this buffered + deferred I/O */
3359 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3361 /* Set Parameters */
3362 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3363 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3365 /* Call the Driver */
3366 Status
= IopPerformSynchronousRequest(DeviceObject
,
3374 /* Check if this was async I/O */
3377 /* It was, finalize this request */
3378 Status
= IopFinalizeAsynchronousIo(Status
,
3386 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
3388 /* Time to report change */
3389 NotificationStructure
.Version
= 1;
3390 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
3391 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
3392 NotificationStructure
.FileObject
= NULL
;
3393 NotificationStructure
.NameBufferOffset
= - 1;
3394 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
3406 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3409 return STATUS_NOT_IMPLEMENTED
;
3417 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3420 return STATUS_NOT_IMPLEMENTED
;