2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iofunc.c
5 * PURPOSE: Generic I/O Functions that build IRPs for various operations
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Filip Navara (navaraf@reactos.org)
11 /* INCLUDES *****************************************************************/
16 #include "internal/io_i.h"
18 /* PRIVATE FUNCTIONS *********************************************************/
22 IopCleanupAfterException(IN PFILE_OBJECT FileObject
,
24 IN PKEVENT Event OPTIONAL
,
25 IN PKEVENT LocalEvent OPTIONAL
)
28 IOTRACE(IO_API_DEBUG
, "IRP: %p. FO: %p \n", Irp
, FileObject
);
30 /* Check if we had a buffer */
31 if (Irp
->AssociatedIrp
.SystemBuffer
)
34 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
38 if (Irp
->MdlAddress
) IoFreeMdl(Irp
->MdlAddress
);
43 /* Check if we had a file lock */
44 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
47 IopUnlockFileObject(FileObject
);
50 /* Check if we had an event */
51 if (Event
) ObDereferenceObject(Event
);
53 /* Check if we had a local event */
54 if (LocalEvent
) ExFreePool(LocalEvent
);
56 /* Derefenrce the FO */
57 ObDereferenceObject(FileObject
);
62 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus
,
65 IN KPROCESSOR_MODE PreviousMode
,
66 IN PIO_STATUS_BLOCK KernelIosb
,
67 OUT PIO_STATUS_BLOCK IoStatusBlock
)
69 NTSTATUS FinalStatus
= SynchStatus
;
71 IOTRACE(IO_API_DEBUG
, "IRP: %p. Status: %lx \n", Irp
, SynchStatus
);
73 /* Make sure the IRP was completed, but returned pending */
74 if (FinalStatus
== STATUS_PENDING
)
76 /* Wait for the IRP */
77 FinalStatus
= KeWaitForSingleObject(Event
,
82 if (FinalStatus
== STATUS_USER_APC
)
84 /* Abort the request */
85 IopAbortInterruptedIrp(Event
, Irp
);
88 /* Set the final status */
89 FinalStatus
= KernelIosb
->Status
;
92 /* Wrap potential user-mode write in SEH */
95 *IoStatusBlock
= *KernelIosb
;
99 /* Get the exception code */
100 FinalStatus
= _SEH_GetExceptionCode();
104 /* Free the event and return status */
111 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject
,
113 IN PFILE_OBJECT FileObject
,
115 IN KPROCESSOR_MODE PreviousMode
,
117 IN IOP_TRANSFER_TYPE TransferType
)
120 PKNORMAL_ROUTINE NormalRoutine
;
124 IOTRACE(IO_API_DEBUG
, "IRP: %p. DO: %p. FO: %p \n",
125 Irp
, DeviceObject
, FileObject
);
128 IopQueueIrpToThread(Irp
);
130 /* Update operation counts */
131 IopUpdateOperationCount(TransferType
);
133 /* Call the driver */
134 Status
= IoCallDriver(DeviceObject
, Irp
);
136 /* Check if we're optimizing this case */
139 /* We are! Check if the IRP wasn't completed */
140 if (Status
!= STATUS_PENDING
)
142 /* Complete it ourselves */
143 ASSERT(!Irp
->PendingReturned
);
144 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
145 IopCompleteRequest(&Irp
->Tail
.Apc
,
150 KeLowerIrql(OldIrql
);
154 /* Check if this was synch I/O */
157 /* Make sure the IRP was completed, but returned pending */
158 if (Status
== STATUS_PENDING
)
160 /* Wait for the IRP */
161 Status
= KeWaitForSingleObject(&FileObject
->Event
,
167 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
169 /* Abort the request */
170 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
173 /* Set the final status */
174 Status
= FileObject
->FinalStatus
;
177 /* Release the file lock */
178 IopUnlockFileObject(FileObject
);
187 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
188 IN HANDLE Event OPTIONAL
,
189 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
190 IN PVOID UserApcContext OPTIONAL
,
191 OUT PIO_STATUS_BLOCK IoStatusBlock
,
192 IN ULONG IoControlCode
,
193 IN PVOID InputBuffer
,
194 IN ULONG InputBufferLength OPTIONAL
,
195 OUT PVOID OutputBuffer
,
196 IN ULONG OutputBufferLength OPTIONAL
,
197 IN BOOLEAN IsDevIoCtl
)
199 NTSTATUS Status
= STATUS_SUCCESS
;
200 PFILE_OBJECT FileObject
;
201 PDEVICE_OBJECT DeviceObject
;
203 PIO_STACK_LOCATION StackPtr
;
204 PKEVENT EventObject
= NULL
;
205 BOOLEAN LockedForSynch
= FALSE
;
207 OBJECT_HANDLE_INFORMATION HandleInformation
;
208 ACCESS_MASK DesiredAccess
;
209 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
211 IOTRACE(IO_CTL_DEBUG
, "Handle: %lx. CTL: %lx. Type: %lx \n",
212 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
214 /* Get the access type */
215 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
217 /* Check if we came from user mode */
218 if (PreviousMode
!= KernelMode
)
222 /* Probe the status block */
223 ProbeForWriteIoStatusBlock(IoStatusBlock
);
225 /* Check if this is buffered I/O */
226 if (AccessType
== METHOD_BUFFERED
)
228 /* Check if we have an output buffer */
231 /* Probe the output buffer */
232 ProbeForWrite(OutputBuffer
,
238 /* Make sure the caller can't fake this as we depend on this */
239 OutputBufferLength
= 0;
243 /* Check if we we have an input buffer I/O */
244 if (AccessType
!= METHOD_NEITHER
)
246 /* Check if we have an input buffer */
249 /* Probe the input buffer */
250 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
254 /* Make sure the caller can't fake this as we depend on this */
255 InputBufferLength
= 0;
261 /* Get the exception code */
262 Status
= _SEH_GetExceptionCode();
265 if (!NT_SUCCESS(Status
)) return Status
;
268 /* Don't check for access rights right now, KernelMode can do anything */
269 Status
= ObReferenceObjectByHandle(DeviceHandle
,
275 if (!NT_SUCCESS(Status
)) return Status
;
277 /* Can't use an I/O completion port and an APC in the same time */
278 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
281 ObDereferenceObject(FileObject
);
282 return STATUS_INVALID_PARAMETER
;
285 /* Check if we from user mode */
286 if (PreviousMode
!= KernelMode
)
288 /* Get the access mask */
289 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
291 /* Check if we can open it */
292 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
293 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
295 /* Dereference the file object and fail */
296 ObDereferenceObject(FileObject
);
297 return STATUS_ACCESS_DENIED
;
301 /* Check for an event */
305 Status
= ObReferenceObjectByHandle(Event
,
309 (PVOID
*)&EventObject
,
311 if (!NT_SUCCESS(Status
))
313 /* Dereference the file object and fail */
314 ObDereferenceObject(FileObject
);
319 KeClearEvent(EventObject
);
322 /* Check if this is a file that was opened for Synch I/O */
323 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
326 IopLockFileObject(FileObject
);
328 /* Remember to unlock later */
329 LockedForSynch
= TRUE
;
332 /* Check if this is a direct open or not */
333 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
335 /* It's a direct open, get the attached device */
336 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
340 /* Otherwise get the related device */
341 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
344 /* Clear the event */
345 KeClearEvent(&FileObject
->Event
);
348 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
349 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
352 Irp
->UserIosb
= IoStatusBlock
;
353 Irp
->UserEvent
= EventObject
;
354 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
355 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
357 Irp
->CancelRoutine
= NULL
;
358 Irp
->PendingReturned
= FALSE
;
359 Irp
->RequestorMode
= PreviousMode
;
360 Irp
->MdlAddress
= NULL
;
361 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
363 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
364 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
365 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
367 /* Set stack location settings */
368 StackPtr
= IoGetNextIrpStackLocation(Irp
);
369 StackPtr
->FileObject
= FileObject
;
370 StackPtr
->MajorFunction
= IsDevIoCtl
?
371 IRP_MJ_DEVICE_CONTROL
:
372 IRP_MJ_FILE_SYSTEM_CONTROL
;
373 StackPtr
->MinorFunction
= 0;
374 StackPtr
->Control
= 0;
376 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
378 /* Set the IOCTL Data */
379 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
380 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
381 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
384 /* Handle the Methods */
388 case METHOD_BUFFERED
:
390 /* Enter SEH for allocations */
393 /* Select the right Buffer Length */
394 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
395 InputBufferLength
: OutputBufferLength
;
397 /* Make sure there is one */
400 /* Allocate the System Buffer */
401 Irp
->AssociatedIrp
.SystemBuffer
=
402 ExAllocatePoolWithTag(NonPagedPool
,
406 /* Check if we got a buffer */
409 /* Copy into the System Buffer */
410 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
415 /* Write the flags */
416 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
417 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
419 /* Save the Buffer */
420 Irp
->UserBuffer
= OutputBuffer
;
424 /* Clear the Flags and Buffer */
425 Irp
->UserBuffer
= NULL
;
430 /* Cleanup after exception */
431 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
432 Status
= _SEH_GetExceptionCode();
435 if (!NT_SUCCESS(Status
)) return Status
;
439 case METHOD_IN_DIRECT
:
440 case METHOD_OUT_DIRECT
:
445 /* Check if we got an input buffer */
446 if ((InputBufferLength
) && (InputBuffer
))
448 /* Allocate the System Buffer */
449 Irp
->AssociatedIrp
.SystemBuffer
=
450 ExAllocatePoolWithTag(NonPagedPool
,
454 /* Copy into the System Buffer */
455 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
459 /* Write the flags */
460 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
463 /* Check if we got an output buffer */
466 /* Allocate the System Buffer */
467 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
472 if (!Irp
->MdlAddress
)
474 /* Raise exception we'll catch */
475 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
479 MmProbeAndLockPages(Irp
->MdlAddress
,
481 (AccessType
== METHOD_IN_DIRECT
) ?
482 IoReadAccess
: IoWriteAccess
);
487 /* Cleanup after exception */
488 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
489 Status
= _SEH_GetExceptionCode();
492 if (!NT_SUCCESS(Status
)) return Status
;
497 /* Just save the Buffer */
498 Irp
->UserBuffer
= OutputBuffer
;
499 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
502 /* Use deferred completion for FS I/O */
503 Irp
->Flags
|= (!IsDevIoCtl
) ? IRP_DEFER_IO_COMPLETION
: 0;
505 /* Perform the call */
506 return IopPerformSynchronousRequest(DeviceObject
,
517 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
518 IN ULONG InformationClass
,
520 OUT PVOID Information
,
521 OUT PULONG ReturnedLength
,
524 IO_STATUS_BLOCK IoStatusBlock
;
526 PDEVICE_OBJECT DeviceObject
;
527 PIO_STACK_LOCATION StackPtr
;
528 BOOLEAN LocalEvent
= FALSE
;
532 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
533 FileObject
, InformationClass
, File
);
535 /* Reference the object */
536 ObReferenceObject(FileObject
);
538 /* Check if this is a file that was opened for Synch I/O */
539 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
542 IopLockFileObject(FileObject
);
544 /* Use File Object event */
545 KeClearEvent(&FileObject
->Event
);
549 /* Use local event */
550 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
554 /* Get the Device Object */
555 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
557 /* Allocate the IRP */
558 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
559 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
562 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
563 Irp
->RequestorMode
= KernelMode
;
564 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
565 Irp
->UserIosb
= &IoStatusBlock
;
566 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
567 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
568 Irp
->Flags
|= IRP_BUFFERED_IO
;
569 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
570 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
572 /* Set the Stack Data */
573 StackPtr
= IoGetNextIrpStackLocation(Irp
);
574 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
575 IRP_MJ_QUERY_VOLUME_INFORMATION
;
576 StackPtr
->FileObject
= FileObject
;
578 /* Check which type this is */
582 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
583 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
588 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
589 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
593 IopQueueIrpToThread(Irp
);
595 /* Call the Driver */
596 Status
= IoCallDriver(DeviceObject
, Irp
);
598 /* Check if this was synch I/O */
601 /* Check if the requet is pending */
602 if (Status
== STATUS_PENDING
)
604 /* Wait on the file object */
605 Status
= KeWaitForSingleObject(&FileObject
->Event
,
608 FileObject
->Flags
& FO_ALERTABLE_IO
,
610 if (Status
== STATUS_ALERTED
)
612 /* Abort the operation */
613 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
616 /* Get the final status */
617 Status
= FileObject
->FinalStatus
;
620 /* Release the file lock */
621 IopUnlockFileObject(FileObject
);
623 else if (Status
== STATUS_PENDING
)
625 /* Wait on the local event and get the final status */
626 KeWaitForSingleObject(&Event
,
631 Status
= IoStatusBlock
.Status
;
634 /* Return the Length and Status. ReturnedLength is NOT optional */
635 *ReturnedLength
= IoStatusBlock
.Information
;
639 /* PUBLIC FUNCTIONS **********************************************************/
646 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
648 IN PLARGE_INTEGER Offset
,
650 IN PIO_STATUS_BLOCK StatusBlock
)
653 PIO_STACK_LOCATION StackPtr
;
654 PDEVICE_OBJECT DeviceObject
;
655 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
656 FileObject
, Mdl
, Offset
);
658 /* Get the Device Object */
659 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
662 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
663 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
666 StackPtr
= IoGetNextIrpStackLocation(Irp
);
668 /* Create the IRP Settings */
669 Irp
->MdlAddress
= Mdl
;
670 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
671 Irp
->UserIosb
= StatusBlock
;
672 Irp
->UserEvent
= Event
;
673 Irp
->RequestorMode
= KernelMode
;
674 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
675 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
676 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
678 /* Set the Stack Settings */
679 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
680 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
681 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
682 StackPtr
->FileObject
= FileObject
;
684 /* Call the Driver */
685 return IofCallDriver(DeviceObject
, Irp
);
693 IoPageRead(IN PFILE_OBJECT FileObject
,
695 IN PLARGE_INTEGER Offset
,
697 IN PIO_STATUS_BLOCK StatusBlock
)
700 PIO_STACK_LOCATION StackPtr
;
701 PDEVICE_OBJECT DeviceObject
;
702 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
703 FileObject
, Mdl
, Offset
);
705 /* Get the Device Object */
706 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
709 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
710 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
713 StackPtr
= IoGetNextIrpStackLocation(Irp
);
715 /* Create the IRP Settings */
716 Irp
->MdlAddress
= Mdl
;
717 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
718 Irp
->UserIosb
= StatusBlock
;
719 Irp
->UserEvent
= Event
;
720 Irp
->RequestorMode
= KernelMode
;
721 Irp
->Flags
= IRP_PAGING_IO
|
723 IRP_SYNCHRONOUS_PAGING_IO
|
725 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
726 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
728 /* Set the Stack Settings */
729 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
730 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
731 StackPtr
->MajorFunction
= IRP_MJ_READ
;
732 StackPtr
->FileObject
= FileObject
;
734 /* Call the Driver */
735 return IofCallDriver(DeviceObject
, Irp
);
743 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
744 IN FILE_INFORMATION_CLASS FileInformationClass
,
746 OUT PVOID FileInformation
,
747 OUT PULONG ReturnedLength
)
749 /* Call the shared routine */
750 return IopQueryDeviceInformation(FileObject
,
751 FileInformationClass
,
763 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
764 IN FS_INFORMATION_CLASS FsInformationClass
,
766 OUT PVOID FsInformation
,
767 OUT PULONG ReturnedLength
)
769 /* Call the shared routine */
770 return IopQueryDeviceInformation(FileObject
,
783 IoSetInformation(IN PFILE_OBJECT FileObject
,
784 IN FILE_INFORMATION_CLASS FileInformationClass
,
786 IN PVOID FileInformation
)
788 IO_STATUS_BLOCK IoStatusBlock
;
790 PDEVICE_OBJECT DeviceObject
;
791 PIO_STACK_LOCATION StackPtr
;
792 BOOLEAN LocalEvent
= FALSE
;
796 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
797 FileObject
, FileInformationClass
, Length
);
799 /* Reference the object */
800 ObReferenceObject(FileObject
);
802 /* Check if this is a file that was opened for Synch I/O */
803 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
806 IopLockFileObject(FileObject
);
808 /* Use File Object event */
809 KeClearEvent(&FileObject
->Event
);
813 /* Use local event */
814 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
818 /* Get the Device Object */
819 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
821 /* Allocate the IRP */
822 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
823 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
826 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
827 Irp
->RequestorMode
= KernelMode
;
828 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
829 Irp
->UserIosb
= &IoStatusBlock
;
830 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
831 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
832 Irp
->Flags
|= IRP_BUFFERED_IO
;
833 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
834 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
836 /* Set the Stack Data */
837 StackPtr
= IoGetNextIrpStackLocation(Irp
);
838 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
839 StackPtr
->FileObject
= FileObject
;
842 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
843 StackPtr
->Parameters
.SetFile
.Length
= Length
;
846 IopQueueIrpToThread(Irp
);
848 /* Call the Driver */
849 Status
= IoCallDriver(DeviceObject
, Irp
);
851 /* Check if this was synch I/O */
854 /* Check if the requet is pending */
855 if (Status
== STATUS_PENDING
)
857 /* Wait on the file object */
858 Status
= KeWaitForSingleObject(&FileObject
->Event
,
861 FileObject
->Flags
& FO_ALERTABLE_IO
,
863 if (Status
== STATUS_ALERTED
)
865 /* Abort the operation */
866 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
869 /* Get the final status */
870 Status
= FileObject
->FinalStatus
;
873 /* Release the file lock */
874 IopUnlockFileObject(FileObject
);
876 else if (Status
== STATUS_PENDING
)
878 /* Wait on the local event and get the final status */
879 KeWaitForSingleObject(&Event
,
884 Status
= IoStatusBlock
.Status
;
887 /* Return the status */
891 /* NATIVE SERVICES ***********************************************************/
898 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
899 IN HANDLE Event OPTIONAL
,
900 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
901 IN PVOID UserApcContext OPTIONAL
,
902 OUT PIO_STATUS_BLOCK IoStatusBlock
,
903 IN ULONG IoControlCode
,
904 IN PVOID InputBuffer
,
905 IN ULONG InputBufferLength OPTIONAL
,
906 OUT PVOID OutputBuffer
,
907 IN ULONG OutputBufferLength OPTIONAL
)
909 /* Call the Generic Function */
910 return IopDeviceFsIoControl(DeviceHandle
,
928 NtFsControlFile(IN HANDLE DeviceHandle
,
929 IN HANDLE Event OPTIONAL
,
930 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
931 IN PVOID UserApcContext OPTIONAL
,
932 OUT PIO_STATUS_BLOCK IoStatusBlock
,
933 IN ULONG IoControlCode
,
934 IN PVOID InputBuffer
,
935 IN ULONG InputBufferLength OPTIONAL
,
936 OUT PVOID OutputBuffer
,
937 IN ULONG OutputBufferLength OPTIONAL
)
939 /* Call the Generic Function */
940 return IopDeviceFsIoControl(DeviceHandle
,
955 NtFlushBuffersFile(IN HANDLE FileHandle
,
956 OUT PIO_STATUS_BLOCK IoStatusBlock
)
958 PFILE_OBJECT FileObject
;
960 PIO_STACK_LOCATION StackPtr
;
961 NTSTATUS Status
= STATUS_SUCCESS
;
962 PDEVICE_OBJECT DeviceObject
;
963 PKEVENT Event
= NULL
;
964 BOOLEAN LocalEvent
= FALSE
;
965 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
966 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
967 IO_STATUS_BLOCK KernelIosb
;
969 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
971 if (PreviousMode
!= KernelMode
)
976 /* Probe the I/O Status block */
977 ProbeForWriteIoStatusBlock(IoStatusBlock
);
981 /* Get the exception code */
982 Status
= _SEH_GetExceptionCode();
986 /* Return exception code, if any */
987 if (!NT_SUCCESS(Status
)) return Status
;
990 /* Get the File Object */
991 Status
= ObReferenceObjectByHandle(FileHandle
,
997 if (!NT_SUCCESS(Status
)) return Status
;
1000 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1001 * granted. However, if this is a named pipe, make sure we don't ask for
1002 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1005 if (!(ObjectHandleInfo
.GrantedAccess
&
1006 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1010 ObDereferenceObject(FileObject
);
1011 return STATUS_ACCESS_DENIED
;
1014 /* Check if we should use Sync IO or not */
1015 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1018 IopLockFileObject(FileObject
);
1022 /* Use local event */
1023 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1024 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1028 /* Get the Device Object */
1029 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1031 /* Clear the event */
1032 KeClearEvent(&FileObject
->Event
);
1034 /* Allocate the IRP */
1035 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1036 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1038 /* Set up the IRP */
1039 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1040 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1041 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1042 Irp
->RequestorMode
= PreviousMode
;
1043 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1044 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1045 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1047 /* Set up Stack Data */
1048 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1049 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1050 StackPtr
->FileObject
= FileObject
;
1052 /* Call the Driver */
1053 Status
= IopPerformSynchronousRequest(DeviceObject
,
1061 /* Check if this was async I/O */
1064 /* It was, finalize this request */
1065 Status
= IopFinalizeAsynchronousIo(Status
,
1073 /* Return the Status */
1082 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1083 IN HANDLE EventHandle OPTIONAL
,
1084 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1085 IN PVOID ApcContext OPTIONAL
,
1086 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1088 IN ULONG BufferSize
,
1089 IN ULONG CompletionFilter
,
1090 IN BOOLEAN WatchTree
)
1093 PKEVENT Event
= NULL
;
1094 PDEVICE_OBJECT DeviceObject
;
1095 PFILE_OBJECT FileObject
;
1096 PIO_STACK_LOCATION IoStack
;
1097 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1098 NTSTATUS Status
= STATUS_SUCCESS
;
1099 BOOLEAN LockedForSync
= FALSE
;
1101 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1103 /* Check if we're called from user mode */
1104 if (PreviousMode
!= KernelMode
)
1106 /* Enter SEH for probing */
1109 /* Probe the I/O STatus block */
1110 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1112 /* Probe the buffer */
1113 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1117 /* Get the exception code */
1118 Status
= _SEH_GetExceptionCode();
1122 /* Check if probing failed */
1123 if (!NT_SUCCESS(Status
)) return Status
;
1126 /* Get File Object */
1127 Status
= ObReferenceObjectByHandle(FileHandle
,
1128 FILE_LIST_DIRECTORY
,
1131 (PVOID
*)&FileObject
,
1133 if (!NT_SUCCESS(Status
)) return Status
;
1135 /* Check if we have an event handle */
1139 Status
= ObReferenceObjectByHandle(EventHandle
,
1145 if (Status
!= STATUS_SUCCESS
) return Status
;
1146 KeClearEvent(Event
);
1149 /* Check if we should use Sync IO or not */
1150 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1153 IopLockFileObject(FileObject
);
1154 LockedForSync
= TRUE
;
1157 /* Clear File Object event */
1158 KeClearEvent(&FileObject
->Event
);
1160 /* Get the device object */
1161 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1163 /* Allocate the IRP */
1164 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1165 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1167 /* Set up the IRP */
1168 Irp
->RequestorMode
= PreviousMode
;
1169 Irp
->UserIosb
= IoStatusBlock
;
1170 Irp
->UserEvent
= Event
;
1171 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1172 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1173 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1174 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1176 /* Set up Stack Data */
1177 IoStack
= IoGetNextIrpStackLocation(Irp
);
1178 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1179 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1180 IoStack
->FileObject
= FileObject
;
1182 /* Set parameters */
1183 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1184 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1185 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1187 /* Perform the call */
1188 return IopPerformSynchronousRequest(DeviceObject
,
1202 NtLockFile(IN HANDLE FileHandle
,
1203 IN HANDLE EventHandle OPTIONAL
,
1204 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1205 IN PVOID ApcContext OPTIONAL
,
1206 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1207 IN PLARGE_INTEGER ByteOffset
,
1208 IN PLARGE_INTEGER Length
,
1210 IN BOOLEAN FailImmediately
,
1211 IN BOOLEAN ExclusiveLock
)
1213 PFILE_OBJECT FileObject
;
1214 PLARGE_INTEGER LocalLength
= NULL
;
1216 PIO_STACK_LOCATION StackPtr
;
1217 PDEVICE_OBJECT DeviceObject
;
1218 PKEVENT Event
= NULL
;
1219 BOOLEAN LockedForSync
= FALSE
;
1220 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1221 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1222 NTSTATUS Status
= STATUS_SUCCESS
;
1223 OBJECT_HANDLE_INFORMATION HandleInformation
;
1225 CapturedByteOffset
.QuadPart
= 0;
1226 CapturedLength
.QuadPart
= 0;
1227 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1229 /* Get File Object */
1230 Status
= ObReferenceObjectByHandle(FileHandle
,
1234 (PVOID
*)&FileObject
,
1235 &HandleInformation
);
1236 if (!NT_SUCCESS(Status
)) return Status
;
1238 /* Check if we're called from user mode */
1239 if (PreviousMode
!= KernelMode
)
1241 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1242 if (!(HandleInformation
.GrantedAccess
&
1243 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1245 ObDereferenceObject(FileObject
);
1246 return STATUS_ACCESS_DENIED
;
1249 /* Enter SEH for probing */
1252 /* Probe the I/O STatus block */
1253 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1255 /* Probe and capture the large integers */
1256 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1257 CapturedLength
= ProbeForReadLargeInteger(Length
);
1261 /* Get the exception code */
1262 Status
= _SEH_GetExceptionCode();
1266 /* Check if probing failed */
1267 if (!NT_SUCCESS(Status
))
1269 /* Dereference the object and return exception code */
1270 ObDereferenceObject(FileObject
);
1276 /* Otherwise, capture them directly */
1277 CapturedByteOffset
= *ByteOffset
;
1278 CapturedLength
= *Length
;
1281 /* Check if we have an event handle */
1285 Status
= ObReferenceObjectByHandle(EventHandle
,
1291 if (Status
!= STATUS_SUCCESS
) return Status
;
1292 KeClearEvent(Event
);
1295 /* Get the device object */
1296 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1298 /* Check if we should use Sync IO or not */
1299 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1302 IopLockFileObject(FileObject
);
1303 LockedForSync
= TRUE
;
1306 /* Clear File Object event */
1307 KeClearEvent(&FileObject
->Event
);
1308 FileObject
->LockOperation
= TRUE
;
1310 /* Allocate the IRP */
1311 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1312 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1314 /* Set up the IRP */
1315 Irp
->RequestorMode
= PreviousMode
;
1316 Irp
->UserIosb
= IoStatusBlock
;
1317 Irp
->UserEvent
= Event
;
1318 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1319 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1320 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1321 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1323 /* Set up Stack Data */
1324 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1325 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1326 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1327 StackPtr
->FileObject
= FileObject
;
1332 /* Allocate local buffer */
1333 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1334 sizeof(LARGE_INTEGER
),
1337 /* Set the length */
1338 *LocalLength
= CapturedLength
;
1339 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1340 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1344 /* Allocating failed, clean up */
1345 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1346 if (LocalLength
) ExFreePool(LocalLength
);
1349 Status
= _SEH_GetExceptionCode();
1352 if (!NT_SUCCESS(Status
)) return Status
;
1354 /* Set Parameters */
1355 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1356 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1359 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1360 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1362 /* Perform the call */
1363 return IopPerformSynchronousRequest(DeviceObject
,
1377 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1378 IN HANDLE EventHandle OPTIONAL
,
1379 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1380 IN PVOID ApcContext OPTIONAL
,
1381 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1382 OUT PVOID FileInformation
,
1384 IN FILE_INFORMATION_CLASS FileInformationClass
,
1385 IN BOOLEAN ReturnSingleEntry
,
1386 IN PUNICODE_STRING FileName OPTIONAL
,
1387 IN BOOLEAN RestartScan
)
1390 PDEVICE_OBJECT DeviceObject
;
1391 PFILE_OBJECT FileObject
;
1392 PIO_STACK_LOCATION StackPtr
;
1393 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1394 NTSTATUS Status
= STATUS_SUCCESS
;
1395 BOOLEAN LockedForSynch
= FALSE
;
1396 PKEVENT Event
= NULL
;
1397 PVOID AuxBuffer
= NULL
;
1399 UNICODE_STRING CapturedFileName
;
1400 PUNICODE_STRING SearchPattern
;
1402 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1404 /* Check if we came from user mode */
1405 if (PreviousMode
!= KernelMode
)
1407 /* Enter SEH for probing */
1410 /* Probe the I/O Status Block */
1411 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1413 /* Probe the file information */
1414 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1416 /* Check if we have a file name */
1420 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1421 if (CapturedFileName
.Length
)
1423 /* Probe its buffer */
1424 ProbeForRead(CapturedFileName
.Buffer
,
1425 CapturedFileName
.Length
,
1429 /* Allocate the auxiliary buffer */
1430 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1431 CapturedFileName
.Length
+
1432 sizeof(UNICODE_STRING
),
1434 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1435 sizeof(UNICODE_STRING
)),
1436 CapturedFileName
.Buffer
,
1437 CapturedFileName
.Length
);
1439 /* Setup the search pattern */
1440 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1441 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1442 sizeof(UNICODE_STRING
));
1443 SearchPattern
->Length
= CapturedFileName
.Length
;
1444 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1449 /* Get exception code and free the buffer */
1450 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1451 Status
= _SEH_GetExceptionCode();
1455 /* Return status on failure */
1456 if (!NT_SUCCESS(Status
)) return Status
;
1459 /* Get File Object */
1460 Status
= ObReferenceObjectByHandle(FileHandle
,
1461 FILE_LIST_DIRECTORY
,
1464 (PVOID
*)&FileObject
,
1466 if (!NT_SUCCESS(Status
))
1469 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1473 /* Check if we have an even handle */
1476 /* Get its pointer */
1477 Status
= ObReferenceObjectByHandle(EventHandle
,
1483 if (!NT_SUCCESS(Status
))
1486 ObDereferenceObject(FileObject
);
1491 KeClearEvent(Event
);
1494 /* Check if this is a file that was opened for Synch I/O */
1495 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1498 IopLockFileObject(FileObject
);
1500 /* Remember to unlock later */
1501 LockedForSynch
= TRUE
;
1504 /* Get the device object */
1505 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1507 /* Clear the File Object's event */
1508 KeClearEvent(&FileObject
->Event
);
1510 /* Allocate the IRP */
1511 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1512 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1514 /* Set up the IRP */
1515 Irp
->RequestorMode
= PreviousMode
;
1516 Irp
->UserIosb
= IoStatusBlock
;
1517 Irp
->UserEvent
= Event
;
1518 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1519 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1520 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1521 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1522 Irp
->MdlAddress
= NULL
;
1523 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1524 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1526 /* Check if this is buffered I/O */
1527 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1532 /* Allocate a buffer */
1533 Irp
->AssociatedIrp
.SystemBuffer
=
1534 ExAllocatePoolWithTag(NonPagedPool
,
1540 /* Allocating failed, clean up */
1541 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1542 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1545 Status
= _SEH_GetExceptionCode();
1548 if (!NT_SUCCESS(Status
)) return Status
;
1550 /* Set the buffer and flags */
1551 Irp
->UserBuffer
= FileInformation
;
1552 Irp
->Flags
= (IRP_BUFFERED_IO
|
1553 IRP_DEALLOCATE_BUFFER
|
1554 IRP_INPUT_OPERATION
);
1556 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1558 /* Allocate an MDL */
1559 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1560 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1564 /* No allocation flags, and use the buffer directly */
1565 Irp
->UserBuffer
= FileInformation
;
1568 /* Set up Stack Data */
1569 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1570 StackPtr
->FileObject
= FileObject
;
1571 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1572 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1574 /* Set Parameters */
1575 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1576 FileInformationClass
;
1577 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1578 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1579 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1580 StackPtr
->Flags
= 0;
1581 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1582 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1584 /* Set deferred I/O */
1585 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1587 /* Perform the call */
1588 return IopPerformSynchronousRequest(DeviceObject
,
1602 NtQueryEaFile(IN HANDLE FileHandle
,
1603 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1606 IN BOOLEAN ReturnSingleEntry
,
1607 IN PVOID EaList OPTIONAL
,
1608 IN ULONG EaListLength
,
1609 IN PULONG EaIndex OPTIONAL
,
1610 IN BOOLEAN RestartScan
)
1613 return STATUS_NOT_IMPLEMENTED
;
1621 NtQueryInformationFile(IN HANDLE FileHandle
,
1622 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1623 IN PVOID FileInformation
,
1625 IN FILE_INFORMATION_CLASS FileInformationClass
)
1627 OBJECT_HANDLE_INFORMATION HandleInformation
;
1628 PFILE_OBJECT FileObject
;
1629 NTSTATUS Status
= STATUS_SUCCESS
;
1631 PDEVICE_OBJECT DeviceObject
;
1632 PIO_STACK_LOCATION StackPtr
;
1633 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1634 PKEVENT Event
= NULL
;
1635 BOOLEAN LocalEvent
= FALSE
;
1636 PKNORMAL_ROUTINE NormalRoutine
;
1637 PVOID NormalContext
;
1639 IO_STATUS_BLOCK KernelIosb
;
1640 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1642 /* Check if we're called from user mode */
1643 if (PreviousMode
!= KernelMode
)
1645 /* Validate the information class */
1646 if ((FileInformationClass
>= FileMaximumInformation
) ||
1647 !(IopQueryOperationLength
[FileInformationClass
]))
1650 return STATUS_INVALID_INFO_CLASS
;
1653 /* Validate the length */
1654 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1656 /* Invalid length */
1657 return STATUS_INFO_LENGTH_MISMATCH
;
1660 /* Enter SEH for probing */
1663 /* Probe the I/O Status block */
1664 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1666 /* Probe the information */
1667 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1671 /* Get the exception code */
1672 Status
= _SEH_GetExceptionCode();
1675 if (!NT_SUCCESS(Status
)) return Status
;
1679 /* Validate the information class */
1680 if ((FileInformationClass
>= FileMaximumInformation
) ||
1681 !(IopQueryOperationLength
[FileInformationClass
]))
1684 return STATUS_INVALID_INFO_CLASS
;
1687 /* Validate the length */
1688 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1690 /* Invalid length */
1691 return STATUS_INFO_LENGTH_MISMATCH
;
1695 /* Reference the Handle */
1696 Status
= ObReferenceObjectByHandle(FileHandle
,
1697 IopQueryOperationAccess
1698 [FileInformationClass
],
1701 (PVOID
*)&FileObject
,
1702 &HandleInformation
);
1703 if (!NT_SUCCESS(Status
)) return Status
;
1705 /* Check if this is a direct open or not */
1706 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1708 /* Get the device object */
1709 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1713 /* Get the device object */
1714 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1717 /* Check if this is a file that was opened for Synch I/O */
1718 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1721 IopLockFileObject(FileObject
);
1723 /* Check if the caller just wants the position */
1724 if (FileInformationClass
== FilePositionInformation
)
1726 /* Protect write in SEH */
1729 /* Write the offset */
1730 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1731 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1733 /* Fill out the I/O Status Block */
1734 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1735 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1739 /* Get the exception code */
1740 Status
= _SEH_GetExceptionCode();
1744 /* Release the file lock, dereference the file and return */
1745 IopUnlockFileObject(FileObject
);
1746 ObDereferenceObject(FileObject
);
1752 /* Use local event */
1753 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1754 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1758 /* Clear the File Object event */
1759 KeClearEvent(&FileObject
->Event
);
1761 /* Allocate the IRP */
1762 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1763 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1766 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1767 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1768 Irp
->RequestorMode
= PreviousMode
;
1769 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1770 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1771 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1772 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1773 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1774 Irp
->MdlAddress
= NULL
;
1775 Irp
->UserBuffer
= FileInformation
;
1777 /* Set the Stack Data */
1778 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1779 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1780 StackPtr
->FileObject
= FileObject
;
1785 /* Allocate a buffer */
1786 Irp
->AssociatedIrp
.SystemBuffer
=
1787 ExAllocatePoolWithTag(NonPagedPool
,
1793 /* Allocating failed, clean up */
1794 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
1795 Status
= _SEH_GetExceptionCode();
1798 if (!NT_SUCCESS(Status
)) return Status
;
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
;
1846 /* Get the exception code */
1847 Status
= _SEH_GetExceptionCode();
1851 /* Free the event */
1856 /* Wait for the IRP */
1857 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1860 FileObject
->Flags
& FO_ALERTABLE_IO
,
1862 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
1864 /* Abort the request */
1865 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1868 /* Set the final status */
1869 Status
= FileObject
->FinalStatus
;
1871 /* Release the file lock */
1872 IopUnlockFileObject(FileObject
);
1877 /* Free the event if we had one */
1880 /* Clear it in the IRP for completion */
1881 Irp
->UserEvent
= NULL
;
1885 /* Set the caller IOSB */
1886 Irp
->UserIosb
= IoStatusBlock
;
1888 /* The IRP wasn't completed, complete it ourselves */
1889 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1890 IopCompleteRequest(&Irp
->Tail
.Apc
,
1893 (PVOID
*)&FileObject
,
1895 KeLowerIrql(OldIrql
);
1897 /* Release the file object if we had locked it*/
1898 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
1901 /* Return the Status */
1910 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
1911 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1914 IN BOOLEAN ReturnSingleEntry
,
1915 IN PVOID SidList OPTIONAL
,
1916 IN ULONG SidListLength
,
1917 IN PSID StartSid OPTIONAL
,
1918 IN BOOLEAN RestartScan
)
1921 return STATUS_NOT_IMPLEMENTED
;
1929 NtReadFile(IN HANDLE FileHandle
,
1930 IN HANDLE Event OPTIONAL
,
1931 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1932 IN PVOID ApcContext OPTIONAL
,
1933 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1936 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
1937 IN PULONG Key OPTIONAL
)
1939 NTSTATUS Status
= STATUS_SUCCESS
;
1940 PFILE_OBJECT FileObject
;
1942 PDEVICE_OBJECT DeviceObject
;
1943 PIO_STACK_LOCATION StackPtr
;
1944 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1945 PKEVENT EventObject
= NULL
;
1946 LARGE_INTEGER CapturedByteOffset
;
1947 ULONG CapturedKey
= 0;
1948 BOOLEAN Synchronous
= FALSE
;
1951 CapturedByteOffset
.QuadPart
= 0;
1952 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1954 /* Validate User-Mode Buffers */
1955 if(PreviousMode
!= KernelMode
)
1959 /* Probe the status block */
1960 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1962 /* Probe the read buffer */
1963 ProbeForWrite(Buffer
, Length
, 1);
1965 /* Check if we got a byte offset */
1968 /* Capture and probe it */
1969 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1972 /* Capture and probe the key */
1973 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
1977 /* Get the exception code */
1978 Status
= _SEH_GetExceptionCode();
1982 /* Check for probe failure */
1983 if (!NT_SUCCESS(Status
)) return Status
;
1987 /* Kernel mode: capture directly */
1988 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
1989 if (Key
) CapturedKey
= *Key
;
1992 /* Get File Object */
1993 Status
= ObReferenceObjectByHandle(FileHandle
,
1997 (PVOID
*)&FileObject
,
1999 if (!NT_SUCCESS(Status
)) return Status
;
2001 /* Check for event */
2005 Status
= ObReferenceObjectByHandle(Event
,
2009 (PVOID
*)&EventObject
,
2011 if (!NT_SUCCESS(Status
))
2014 ObDereferenceObject(FileObject
);
2018 /* Otherwise reset the event */
2019 KeClearEvent(EventObject
);
2022 /* Check if we should use Sync IO or not */
2023 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2025 /* Lock the file object */
2026 IopLockFileObject(FileObject
);
2028 /* Check if we don't have a byte offset avilable */
2029 if (!(ByteOffset
) ||
2030 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2031 (CapturedByteOffset
.u
.HighPart
== -1)))
2033 /* Use the Current Byte Offset instead */
2034 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2037 /* Rememer we are sync */
2040 else if (!(ByteOffset
) &&
2041 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2043 /* Otherwise, this was async I/O without a byte offset, so fail */
2044 if (EventObject
) ObDereferenceObject(EventObject
);
2045 ObDereferenceObject(FileObject
);
2046 return STATUS_INVALID_PARAMETER
;
2049 /* Get the device object */
2050 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2052 /* Clear the File Object's event */
2053 KeClearEvent(&FileObject
->Event
);
2055 /* Allocate the IRP */
2056 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2057 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2060 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2061 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2062 Irp
->RequestorMode
= KernelMode
;
2063 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2064 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2065 Irp
->UserIosb
= IoStatusBlock
;
2066 Irp
->UserEvent
= EventObject
;
2067 Irp
->PendingReturned
= FALSE
;
2068 Irp
->Cancel
= FALSE
;
2069 Irp
->CancelRoutine
= NULL
;
2070 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2071 Irp
->MdlAddress
= NULL
;
2073 /* Set the Stack Data */
2074 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2075 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2076 StackPtr
->FileObject
= FileObject
;
2077 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2078 StackPtr
->Parameters
.Read
.Length
= Length
;
2079 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2081 /* Check if this is buffered I/O */
2082 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2084 /* Check if we have a buffer length */
2090 /* Allocate a buffer */
2091 Irp
->AssociatedIrp
.SystemBuffer
=
2092 ExAllocatePoolWithTag(NonPagedPool
,
2098 /* Allocating failed, clean up */
2099 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2100 Status
= _SEH_GetExceptionCode();
2103 if (!NT_SUCCESS(Status
)) return Status
;
2105 /* Set the buffer and flags */
2106 Irp
->UserBuffer
= Buffer
;
2107 Irp
->Flags
= (IRP_BUFFERED_IO
|
2108 IRP_DEALLOCATE_BUFFER
|
2109 IRP_INPUT_OPERATION
);
2113 /* Not reading anything */
2114 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2117 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2119 /* Check if we have a buffer length */
2122 /* Allocate an MDL */
2123 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2124 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2127 /* No allocation flags */
2132 /* No allocation flags, and use the buffer directly */
2134 Irp
->UserBuffer
= Buffer
;
2137 /* Now set the deferred read flags */
2138 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2140 /* FIXME: VFAT SUCKS */
2141 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2144 /* Perform the call */
2145 return IopPerformSynchronousRequest(DeviceObject
,
2159 NtReadFileScatter(IN HANDLE FileHandle
,
2160 IN HANDLE Event OPTIONAL
,
2161 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2162 IN PVOID UserApcContext OPTIONAL
,
2163 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2164 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2165 IN ULONG BufferLength
,
2166 IN PLARGE_INTEGER ByteOffset
,
2167 IN PULONG Key OPTIONAL
)
2170 return STATUS_NOT_IMPLEMENTED
;
2178 NtSetEaFile(IN HANDLE FileHandle
,
2179 IN PIO_STATUS_BLOCK IoStatusBlock
,
2181 IN ULONG EaBufferSize
)
2184 return STATUS_NOT_IMPLEMENTED
;
2192 NtSetInformationFile(IN HANDLE FileHandle
,
2193 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2194 IN PVOID FileInformation
,
2196 IN FILE_INFORMATION_CLASS FileInformationClass
)
2198 PFILE_OBJECT FileObject
;
2199 NTSTATUS Status
= STATUS_SUCCESS
;
2201 PDEVICE_OBJECT DeviceObject
;
2202 PIO_STACK_LOCATION StackPtr
;
2203 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2204 PKEVENT Event
= NULL
;
2205 BOOLEAN LocalEvent
= FALSE
;
2206 PKNORMAL_ROUTINE NormalRoutine
;
2207 PVOID NormalContext
;
2209 IO_STATUS_BLOCK KernelIosb
;
2211 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2212 PIO_COMPLETION_CONTEXT Context
;
2213 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2215 /* Check if we're called from user mode */
2216 if (PreviousMode
!= KernelMode
)
2218 /* Validate the information class */
2219 if ((FileInformationClass
>= FileMaximumInformation
) ||
2220 !(IopSetOperationLength
[FileInformationClass
]))
2223 return STATUS_INVALID_INFO_CLASS
;
2226 /* Validate the length */
2227 if (Length
< IopSetOperationLength
[FileInformationClass
])
2229 /* Invalid length */
2230 return STATUS_INFO_LENGTH_MISMATCH
;
2233 /* Enter SEH for probing */
2236 /* Probe the I/O Status block */
2237 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2239 /* Probe the information */
2240 ProbeForRead(FileInformation
,
2242 (Length
== sizeof(BOOLEAN
)) ?
2243 sizeof(BOOLEAN
) : sizeof(ULONG
));
2247 /* Get the exception code */
2248 Status
= _SEH_GetExceptionCode();
2252 /* Check if probing failed */
2253 if (!NT_SUCCESS(Status
)) return Status
;
2257 /* Validate the information class */
2258 if ((FileInformationClass
>= FileMaximumInformation
) ||
2259 !(IopSetOperationLength
[FileInformationClass
]))
2262 return STATUS_INVALID_INFO_CLASS
;
2265 /* Validate the length */
2266 if (Length
< IopSetOperationLength
[FileInformationClass
])
2268 /* Invalid length */
2269 return STATUS_INFO_LENGTH_MISMATCH
;
2273 /* Reference the Handle */
2274 Status
= ObReferenceObjectByHandle(FileHandle
,
2275 IopSetOperationAccess
2276 [FileInformationClass
],
2279 (PVOID
*)&FileObject
,
2281 if (!NT_SUCCESS(Status
)) return Status
;
2283 /* Check if this is a direct open or not */
2284 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2286 /* Get the device object */
2287 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2291 /* Get the device object */
2292 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2295 /* Check if this is a file that was opened for Synch I/O */
2296 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2299 IopLockFileObject(FileObject
);
2301 /* Check if the caller just wants the position */
2302 if (FileInformationClass
== FilePositionInformation
)
2304 /* Protect write in SEH */
2307 /* Write the offset */
2308 FileObject
->CurrentByteOffset
=
2309 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2312 /* Fill out the I/O Status Block */
2313 IoStatusBlock
->Information
= 0;
2314 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2318 /* Get the exception code */
2319 Status
= _SEH_GetExceptionCode();
2323 /* Release the file lock, dereference the file and return */
2324 IopUnlockFileObject(FileObject
);
2325 ObDereferenceObject(FileObject
);
2331 /* Use local event */
2332 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2333 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2337 /* Clear the File Object event */
2338 KeClearEvent(&FileObject
->Event
);
2340 /* Allocate the IRP */
2341 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2342 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2345 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2346 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2347 Irp
->RequestorMode
= PreviousMode
;
2348 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2349 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2350 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2351 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2352 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2353 Irp
->MdlAddress
= NULL
;
2354 Irp
->UserBuffer
= FileInformation
;
2356 /* Set the Stack Data */
2357 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2358 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2359 StackPtr
->FileObject
= FileObject
;
2364 /* Allocate a buffer */
2365 Irp
->AssociatedIrp
.SystemBuffer
=
2366 ExAllocatePoolWithTag(NonPagedPool
,
2370 /* Copy the data into it */
2371 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2377 /* Allocating failed, clean up */
2378 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2379 Status
= _SEH_GetExceptionCode();
2382 if (!NT_SUCCESS(Status
)) return Status
;
2385 Irp
->Flags
= (IRP_BUFFERED_IO
|
2386 IRP_DEALLOCATE_BUFFER
|
2387 IRP_DEFER_IO_COMPLETION
);
2389 /* Set the Parameters */
2390 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2391 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2394 IopQueueIrpToThread(Irp
);
2396 /* Update operation counts */
2397 IopUpdateOperationCount(IopOtherTransfer
);
2399 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2400 /* Handle IO Completion Port quickly */
2401 if (FileInformationClass
== FileCompletionInformation
)
2403 /* Check if the file object already has a completion port */
2404 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2405 (FileObject
->CompletionContext
))
2408 Status
= STATUS_INVALID_PARAMETER
;
2412 /* Reference the Port */
2413 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2414 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2415 IO_COMPLETION_MODIFY_STATE
,
2420 if (NT_SUCCESS(Status
))
2422 /* Allocate the Context */
2423 Context
= ExAllocatePoolWithTag(PagedPool
,
2424 sizeof(IO_COMPLETION_CONTEXT
),
2429 Context
->Key
= CompletionInfo
->Key
;
2430 Context
->Port
= Queue
;
2431 if (InterlockedCompareExchangePointer(&FileObject
->
2437 * Someone else set the completion port in the
2438 * meanwhile, so dereference the port and fail.
2440 ExFreePool(Context
);
2441 ObDereferenceObject(Queue
);
2442 Status
= STATUS_INVALID_PARAMETER
;
2447 /* Dereference the Port now */
2448 ObDereferenceObject(Queue
);
2449 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2454 /* Set the IRP Status */
2455 Irp
->IoStatus
.Status
= Status
;
2456 Irp
->IoStatus
.Information
= 0;
2460 /* Call the Driver */
2461 Status
= IoCallDriver(DeviceObject
, Irp
);
2464 /* Check if we're waiting for the IRP to complete */
2465 if (Status
== STATUS_PENDING
)
2467 /* Check if this was async I/O */
2470 /* Then to a non-alertable wait */
2471 Status
= KeWaitForSingleObject(Event
,
2476 if (Status
== STATUS_USER_APC
)
2478 /* Abort the request */
2479 IopAbortInterruptedIrp(Event
, Irp
);
2482 /* Set the final status */
2483 Status
= KernelIosb
.Status
;
2485 /* Enter SEH to write the IOSB back */
2488 /* Write it back to the caller */
2489 *IoStatusBlock
= KernelIosb
;
2493 /* Get the exception code */
2494 Status
= _SEH_GetExceptionCode();
2498 /* Free the event */
2503 /* Wait for the IRP */
2504 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2507 FileObject
->Flags
& FO_ALERTABLE_IO
,
2509 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2511 /* Abort the request */
2512 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2515 /* Set the final status */
2516 Status
= FileObject
->FinalStatus
;
2518 /* Release the file lock */
2519 IopUnlockFileObject(FileObject
);
2524 /* Free the event if we had one */
2527 /* Clear it in the IRP for completion */
2528 Irp
->UserEvent
= NULL
;
2532 /* Set the caller IOSB */
2533 Irp
->UserIosb
= IoStatusBlock
;
2535 /* The IRP wasn't completed, complete it ourselves */
2536 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2537 IopCompleteRequest(&Irp
->Tail
.Apc
,
2540 (PVOID
*)&FileObject
,
2542 KeLowerIrql(OldIrql
);
2544 /* Release the file object if we had locked it*/
2545 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2548 /* Return the Status */
2557 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2558 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2560 IN ULONG BufferLength
)
2563 return STATUS_NOT_IMPLEMENTED
;
2571 NtUnlockFile(IN HANDLE FileHandle
,
2572 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2573 IN PLARGE_INTEGER ByteOffset
,
2574 IN PLARGE_INTEGER Length
,
2575 IN ULONG Key OPTIONAL
)
2577 PFILE_OBJECT FileObject
;
2578 PLARGE_INTEGER LocalLength
= NULL
;
2580 PIO_STACK_LOCATION StackPtr
;
2581 PDEVICE_OBJECT DeviceObject
;
2582 PKEVENT Event
= NULL
;
2583 BOOLEAN LocalEvent
= FALSE
;
2584 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2585 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2586 NTSTATUS Status
= STATUS_SUCCESS
;
2587 OBJECT_HANDLE_INFORMATION HandleInformation
;
2588 IO_STATUS_BLOCK KernelIosb
;
2590 CapturedByteOffset
.QuadPart
= 0;
2591 CapturedLength
.QuadPart
= 0;
2592 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2594 /* Get File Object */
2595 Status
= ObReferenceObjectByHandle(FileHandle
,
2599 (PVOID
*)&FileObject
,
2600 &HandleInformation
);
2601 if (!NT_SUCCESS(Status
)) return Status
;
2603 /* Check if we're called from user mode */
2604 if (PreviousMode
!= KernelMode
)
2606 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2607 if (!(HandleInformation
.GrantedAccess
&
2608 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2610 ObDereferenceObject(FileObject
);
2611 return STATUS_ACCESS_DENIED
;
2614 /* Enter SEH for probing */
2617 /* Probe the I/O Status block */
2618 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2620 /* Probe and capture the large integers */
2621 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2622 CapturedLength
= ProbeForReadLargeInteger(Length
);
2626 /* Get the exception code */
2627 Status
= _SEH_GetExceptionCode();
2631 /* Check if probing failed */
2632 if (!NT_SUCCESS(Status
))
2634 /* Dereference the object and return exception code */
2635 ObDereferenceObject(FileObject
);
2641 /* Otherwise, capture them directly */
2642 CapturedByteOffset
= *ByteOffset
;
2643 CapturedLength
= *Length
;
2646 /* Check if this is a direct open or not */
2647 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2649 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2653 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2656 /* Check if we should use Sync IO or not */
2657 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2660 IopLockFileObject(FileObject
);
2664 /* Use local event */
2665 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2666 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2670 /* Clear File Object event */
2671 KeClearEvent(&FileObject
->Event
);
2673 /* Allocate the IRP */
2674 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2675 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2677 /* Set up the IRP */
2678 Irp
->RequestorMode
= PreviousMode
;
2679 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2680 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2681 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2682 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2683 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2684 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2686 /* Set up Stack Data */
2687 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2688 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2689 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2690 StackPtr
->FileObject
= FileObject
;
2695 /* Allocate a buffer */
2696 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2697 sizeof(LARGE_INTEGER
),
2700 /* Set the length */
2701 *LocalLength
= CapturedLength
;
2702 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
2703 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2707 /* Allocating failed, clean up */
2708 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2709 if (LocalLength
) ExFreePool(LocalLength
);
2711 /* Get exception status */
2712 Status
= _SEH_GetExceptionCode();
2715 if (!NT_SUCCESS(Status
)) return Status
;
2717 /* Set Parameters */
2718 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
2719 StackPtr
->Parameters
.LockControl
.Key
= Key
;
2721 /* Call the Driver */
2722 Status
= IopPerformSynchronousRequest(DeviceObject
,
2730 /* Check if this was async I/O */
2733 /* It was, finalize this request */
2734 Status
= IopFinalizeAsynchronousIo(Status
,
2751 NtWriteFile(IN HANDLE FileHandle
,
2752 IN HANDLE Event OPTIONAL
,
2753 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2754 IN PVOID ApcContext OPTIONAL
,
2755 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2758 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2759 IN PULONG Key OPTIONAL
)
2761 NTSTATUS Status
= STATUS_SUCCESS
;
2762 PFILE_OBJECT FileObject
;
2764 PDEVICE_OBJECT DeviceObject
;
2765 PIO_STACK_LOCATION StackPtr
;
2766 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2767 PKEVENT EventObject
= NULL
;
2768 LARGE_INTEGER CapturedByteOffset
;
2769 ULONG CapturedKey
= 0;
2770 BOOLEAN Synchronous
= FALSE
;
2772 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
2774 CapturedByteOffset
.QuadPart
= 0;
2775 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2777 /* Get File Object */
2778 Status
= ObReferenceObjectByHandle(FileHandle
,
2782 (PVOID
*)&FileObject
,
2784 if (!NT_SUCCESS(Status
)) return Status
;
2786 /* Validate User-Mode Buffers */
2787 if(PreviousMode
!= KernelMode
)
2792 * Check if the handle has either FILE_WRITE_DATA or
2793 * FILE_APPEND_DATA granted. However, if this is a named pipe,
2794 * make sure we don't ask for FILE_APPEND_DATA as it interferes
2795 * with the FILE_CREATE_PIPE_INSTANCE access right!
2797 if (!(ObjectHandleInfo
.GrantedAccess
&
2798 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
2799 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
2802 ObDereferenceObject(FileObject
);
2803 _SEH_YIELD(return STATUS_ACCESS_DENIED
);
2806 /* Probe the status block */
2807 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2809 /* Probe the read buffer */
2810 ProbeForRead(Buffer
, Length
, 1);
2812 /* Check if we got a byte offset */
2815 /* Capture and probe it */
2816 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2819 /* Capture and probe the key */
2820 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2824 /* Get the exception code */
2825 Status
= _SEH_GetExceptionCode();
2829 /* Check for probe failure */
2830 if (!NT_SUCCESS(Status
)) return Status
;
2834 /* Kernel mode: capture directly */
2835 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2836 if (Key
) CapturedKey
= *Key
;
2839 /* Check if this is an append operation */
2840 if ((ObjectHandleInfo
.GrantedAccess
&
2841 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
2843 /* Give the drivers something to understand */
2844 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
2845 CapturedByteOffset
.u
.HighPart
= -1;
2848 /* Check for event */
2852 Status
= ObReferenceObjectByHandle(Event
,
2856 (PVOID
*)&EventObject
,
2858 if (!NT_SUCCESS(Status
))
2861 ObDereferenceObject(FileObject
);
2865 /* Otherwise reset the event */
2866 KeClearEvent(EventObject
);
2869 /* Check if we should use Sync IO or not */
2870 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2872 /* Lock the file object */
2873 IopLockFileObject(FileObject
);
2875 /* Check if we don't have a byte offset avilable */
2876 if (!(ByteOffset
) ||
2877 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2878 (CapturedByteOffset
.u
.HighPart
== -1)))
2880 /* Use the Current Byte Offset instead */
2881 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2884 /* Rememer we are sync */
2887 else if (!(ByteOffset
) &&
2888 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2890 /* Otherwise, this was async I/O without a byte offset, so fail */
2891 if (EventObject
) ObDereferenceObject(EventObject
);
2892 ObDereferenceObject(FileObject
);
2893 return STATUS_INVALID_PARAMETER
;
2896 /* Get the device object */
2897 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2899 /* Clear the File Object's event */
2900 KeClearEvent(&FileObject
->Event
);
2902 /* Allocate the IRP */
2903 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2904 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2907 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2908 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2909 Irp
->RequestorMode
= KernelMode
;
2910 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2911 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2912 Irp
->UserIosb
= IoStatusBlock
;
2913 Irp
->UserEvent
= EventObject
;
2914 Irp
->PendingReturned
= FALSE
;
2915 Irp
->Cancel
= FALSE
;
2916 Irp
->CancelRoutine
= NULL
;
2917 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2918 Irp
->MdlAddress
= NULL
;
2920 /* Set the Stack Data */
2921 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2922 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
2923 StackPtr
->FileObject
= FileObject
;
2924 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
2925 SL_WRITE_THROUGH
: 0;
2926 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
2927 StackPtr
->Parameters
.Write
.Length
= Length
;
2928 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
2930 /* Check if this is buffered I/O */
2931 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2933 /* Check if we have a buffer length */
2939 /* Allocate a buffer */
2940 Irp
->AssociatedIrp
.SystemBuffer
=
2941 ExAllocatePoolWithTag(NonPagedPool
,
2945 /* Copy the data into it */
2946 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
2950 /* Allocating failed, clean up */
2951 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
2952 Status
= _SEH_GetExceptionCode();
2957 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
2961 /* Not writing anything */
2962 Irp
->Flags
= IRP_BUFFERED_IO
;
2965 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2967 /* Check if we have a buffer length */
2970 /* Allocate an MDL */
2971 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2972 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
2975 /* No allocation flags */
2980 /* No allocation flags, and use the buffer directly */
2982 Irp
->UserBuffer
= Buffer
;
2985 /* Now set the deferred read flags */
2986 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2988 /* FIXME: VFAT SUCKS */
2989 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2992 /* Perform the call */
2993 return IopPerformSynchronousRequest(DeviceObject
,
3004 NtWriteFileGather(IN HANDLE FileHandle
,
3005 IN HANDLE Event OPTIONAL
,
3006 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3007 IN PVOID UserApcContext OPTIONAL
,
3008 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3009 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3010 IN ULONG BufferLength
,
3011 IN PLARGE_INTEGER ByteOffset
,
3012 IN PULONG Key OPTIONAL
)
3015 return STATUS_NOT_IMPLEMENTED
;
3023 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3024 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3025 OUT PVOID FsInformation
,
3027 IN FS_INFORMATION_CLASS FsInformationClass
)
3029 PFILE_OBJECT FileObject
;
3031 PIO_STACK_LOCATION StackPtr
;
3032 PDEVICE_OBJECT DeviceObject
;
3033 PKEVENT Event
= NULL
;
3034 BOOLEAN LocalEvent
= FALSE
;
3035 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3036 NTSTATUS Status
= STATUS_SUCCESS
;
3037 IO_STATUS_BLOCK KernelIosb
;
3039 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3041 /* Check if we're called from user mode */
3042 if (PreviousMode
!= KernelMode
)
3044 /* Validate the information class */
3045 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3046 !(IopQueryFsOperationLength
[FsInformationClass
]))
3049 return STATUS_INVALID_INFO_CLASS
;
3052 /* Validate the length */
3053 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3055 /* Invalid length */
3056 return STATUS_INFO_LENGTH_MISMATCH
;
3059 /* Enter SEH for probing */
3062 /* Probe the I/O Status block */
3063 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3065 /* Probe the information */
3066 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3070 /* Get the exception code */
3071 Status
= _SEH_GetExceptionCode();
3074 if (!NT_SUCCESS(Status
)) return Status
;
3077 /* Get File Object */
3078 Status
= ObReferenceObjectByHandle(FileHandle
,
3079 IopQueryFsOperationAccess
3080 [FsInformationClass
],
3083 (PVOID
*)&FileObject
,
3085 if (!NT_SUCCESS(Status
)) return Status
;
3087 /* Check if we should use Sync IO or not */
3088 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3091 IopLockFileObject(FileObject
);
3095 /* Use local event */
3096 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3097 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3101 /* Get the device object */
3102 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3104 /* Clear File Object event */
3105 KeClearEvent(&FileObject
->Event
);
3107 /* Allocate the IRP */
3108 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3109 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3111 /* Set up the IRP */
3112 Irp
->RequestorMode
= PreviousMode
;
3113 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3114 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3115 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3116 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3117 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3118 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3119 Irp
->UserBuffer
= FsInformation
;
3120 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3121 Irp
->MdlAddress
= NULL
;
3123 /* Set up Stack Data */
3124 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3125 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3126 StackPtr
->FileObject
= FileObject
;
3131 /* Allocate a buffer */
3132 Irp
->AssociatedIrp
.SystemBuffer
=
3133 ExAllocatePoolWithTag(NonPagedPool
,
3139 /* Allocating failed, clean up */
3140 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3141 Status
= _SEH_GetExceptionCode();
3144 if (!NT_SUCCESS(Status
)) return Status
;
3146 /* Set the flags for this buffered + deferred I/O */
3147 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3148 IRP_DEALLOCATE_BUFFER
|
3149 IRP_INPUT_OPERATION
|
3150 IRP_DEFER_IO_COMPLETION
);
3152 /* Set Parameters */
3153 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3154 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3156 /* Call the Driver */
3157 Status
= IopPerformSynchronousRequest(DeviceObject
,
3165 /* Check if this was async I/O */
3168 /* It was, finalize this request */
3169 Status
= IopFinalizeAsynchronousIo(Status
,
3186 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3187 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3188 IN PVOID FsInformation
,
3190 IN FS_INFORMATION_CLASS FsInformationClass
)
3192 PFILE_OBJECT FileObject
;
3194 PIO_STACK_LOCATION StackPtr
;
3195 PDEVICE_OBJECT DeviceObject
;
3196 PKEVENT Event
= NULL
;
3197 BOOLEAN LocalEvent
= FALSE
;
3198 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3199 NTSTATUS Status
= STATUS_SUCCESS
;
3200 IO_STATUS_BLOCK KernelIosb
;
3202 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3204 /* Check if we're called from user mode */
3205 if (PreviousMode
!= KernelMode
)
3207 /* Validate the information class */
3208 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3209 !(IopSetFsOperationLength
[FsInformationClass
]))
3212 return STATUS_INVALID_INFO_CLASS
;
3215 /* Validate the length */
3216 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3218 /* Invalid length */
3219 return STATUS_INFO_LENGTH_MISMATCH
;
3222 /* Enter SEH for probing */
3225 /* Probe the I/O Status block */
3226 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3228 /* Probe the information */
3229 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3233 /* Get the exception code */
3234 Status
= _SEH_GetExceptionCode();
3237 if (!NT_SUCCESS(Status
)) return Status
;
3240 /* Get File Object */
3241 Status
= ObReferenceObjectByHandle(FileHandle
,
3242 IopSetFsOperationAccess
3243 [FsInformationClass
],
3246 (PVOID
*)&FileObject
,
3248 if (!NT_SUCCESS(Status
)) return Status
;
3250 /* Check if we should use Sync IO or not */
3251 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3254 IopLockFileObject(FileObject
);
3258 /* Use local event */
3259 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3260 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3264 /* Get the device object */
3265 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3267 /* Clear File Object event */
3268 KeClearEvent(&FileObject
->Event
);
3270 /* Allocate the IRP */
3271 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3272 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3274 /* Set up the IRP */
3275 Irp
->RequestorMode
= PreviousMode
;
3276 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3277 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3278 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3279 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3280 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3281 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3282 Irp
->UserBuffer
= FsInformation
;
3283 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3284 Irp
->MdlAddress
= NULL
;
3286 /* Set up Stack Data */
3287 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3288 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3289 StackPtr
->FileObject
= FileObject
;
3294 /* Allocate a buffer */
3295 Irp
->AssociatedIrp
.SystemBuffer
=
3296 ExAllocatePoolWithTag(NonPagedPool
,
3300 /* Copy the data into it */
3301 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3305 /* Allocating failed, clean up */
3306 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3307 Status
= _SEH_GetExceptionCode();
3310 if (!NT_SUCCESS(Status
)) return Status
;
3312 /* Set the flags for this buffered + deferred I/O */
3313 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3315 /* Set Parameters */
3316 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3317 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3319 /* Call the Driver */
3320 Status
= IopPerformSynchronousRequest(DeviceObject
,
3328 /* Check if this was async I/O */
3331 /* It was, finalize this request */
3332 Status
= IopFinalizeAsynchronousIo(Status
,