2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iofunc.c
5 * PURPOSE: Generic I/O Functions that build IRPs for various operations
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Filip Navara (navaraf@reactos.org)
11 /* INCLUDES *****************************************************************/
16 #include "internal/io_i.h"
18 /* PRIVATE FUNCTIONS *********************************************************/
22 IopCleanupAfterException(IN PFILE_OBJECT FileObject
,
24 IN PKEVENT Event OPTIONAL
,
25 IN PKEVENT LocalEvent OPTIONAL
)
28 IOTRACE(IO_API_DEBUG
, "IRP: %p. FO: %p \n", Irp
, FileObject
);
30 /* Check if we had a buffer */
31 if (Irp
->AssociatedIrp
.SystemBuffer
)
34 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
38 if (Irp
->MdlAddress
) IoFreeMdl(Irp
->MdlAddress
);
43 /* Check if we had a file lock */
44 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
47 IopUnlockFileObject(FileObject
);
50 /* Check if we had an event */
51 if (Event
) ObDereferenceObject(Event
);
53 /* Check if we had a local event */
54 if (LocalEvent
) ExFreePool(LocalEvent
);
56 /* Derefenrce the FO */
57 ObDereferenceObject(FileObject
);
62 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus
,
65 IN KPROCESSOR_MODE PreviousMode
,
66 IN PIO_STATUS_BLOCK KernelIosb
,
67 OUT PIO_STATUS_BLOCK IoStatusBlock
)
69 NTSTATUS FinalStatus
= SynchStatus
;
71 IOTRACE(IO_API_DEBUG
, "IRP: %p. Status: %lx \n", Irp
, SynchStatus
);
73 /* Make sure the IRP was completed, but returned pending */
74 if (FinalStatus
== STATUS_PENDING
)
76 /* Wait for the IRP */
77 FinalStatus
= KeWaitForSingleObject(Event
,
82 if (FinalStatus
== STATUS_USER_APC
)
84 /* Abort the request */
85 IopAbortInterruptedIrp(Event
, Irp
);
88 /* Set the final status */
89 FinalStatus
= KernelIosb
->Status
;
92 /* Wrap potential user-mode write in SEH */
95 *IoStatusBlock
= *KernelIosb
;
97 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
99 /* Get the exception code */
100 FinalStatus
= _SEH2_GetExceptionCode();
104 /* Free the event and return status */
111 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject
,
113 IN PFILE_OBJECT FileObject
,
115 IN KPROCESSOR_MODE PreviousMode
,
117 IN IOP_TRANSFER_TYPE TransferType
)
120 PKNORMAL_ROUTINE NormalRoutine
;
124 IOTRACE(IO_API_DEBUG
, "IRP: %p. DO: %p. FO: %p \n",
125 Irp
, DeviceObject
, FileObject
);
128 IopQueueIrpToThread(Irp
);
130 /* Update operation counts */
131 IopUpdateOperationCount(TransferType
);
133 /* Call the driver */
134 Status
= IoCallDriver(DeviceObject
, Irp
);
136 /* Check if we're optimizing this case */
139 /* We are! Check if the IRP wasn't completed */
140 if (Status
!= STATUS_PENDING
)
142 /* Complete it ourselves */
143 ASSERT(!Irp
->PendingReturned
);
144 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
145 IopCompleteRequest(&Irp
->Tail
.Apc
,
150 KeLowerIrql(OldIrql
);
154 /* Check if this was synch I/O */
157 /* Make sure the IRP was completed, but returned pending */
158 if (Status
== STATUS_PENDING
)
160 /* Wait for the IRP */
161 Status
= KeWaitForSingleObject(&FileObject
->Event
,
167 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
169 /* Abort the request */
170 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
173 /* Set the final status */
174 Status
= FileObject
->FinalStatus
;
177 /* Release the file lock */
178 IopUnlockFileObject(FileObject
);
187 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
188 IN HANDLE Event OPTIONAL
,
189 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
190 IN PVOID UserApcContext OPTIONAL
,
191 OUT PIO_STATUS_BLOCK IoStatusBlock
,
192 IN ULONG IoControlCode
,
193 IN PVOID InputBuffer
,
194 IN ULONG InputBufferLength OPTIONAL
,
195 OUT PVOID OutputBuffer
,
196 IN ULONG OutputBufferLength OPTIONAL
,
197 IN BOOLEAN IsDevIoCtl
)
200 PFILE_OBJECT FileObject
;
201 PDEVICE_OBJECT DeviceObject
;
203 PIO_STACK_LOCATION StackPtr
;
204 PKEVENT EventObject
= NULL
;
205 BOOLEAN LockedForSynch
= FALSE
;
207 OBJECT_HANDLE_INFORMATION HandleInformation
;
208 ACCESS_MASK DesiredAccess
;
209 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
211 IOTRACE(IO_CTL_DEBUG
, "Handle: %lx. CTL: %lx. Type: %lx \n",
212 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
214 /* Get the access type */
215 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
217 /* Check if we came from user mode */
218 if (PreviousMode
!= KernelMode
)
222 /* Probe the status block */
223 ProbeForWriteIoStatusBlock(IoStatusBlock
);
225 /* Check if this is buffered I/O */
226 if (AccessType
== METHOD_BUFFERED
)
228 /* Check if we have an output buffer */
231 /* Probe the output buffer */
232 ProbeForWrite(OutputBuffer
,
238 /* Make sure the caller can't fake this as we depend on this */
239 OutputBufferLength
= 0;
243 /* Check if we we have an input buffer I/O */
244 if (AccessType
!= METHOD_NEITHER
)
246 /* Check if we have an input buffer */
249 /* Probe the input buffer */
250 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
254 /* Make sure the caller can't fake this as we depend on this */
255 InputBufferLength
= 0;
259 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
261 /* Return the exception code */
262 _SEH2_YIELD(return _SEH2_GetExceptionCode());
267 /* Don't check for access rights right now, KernelMode can do anything */
268 Status
= ObReferenceObjectByHandle(DeviceHandle
,
274 if (!NT_SUCCESS(Status
)) return Status
;
276 /* Can't use an I/O completion port and an APC in the same time */
277 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
280 ObDereferenceObject(FileObject
);
281 return STATUS_INVALID_PARAMETER
;
284 /* Check if we from user mode */
285 if (PreviousMode
!= KernelMode
)
287 /* Get the access mask */
288 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
290 /* Check if we can open it */
291 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
292 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
294 /* Dereference the file object and fail */
295 ObDereferenceObject(FileObject
);
296 return STATUS_ACCESS_DENIED
;
300 /* Check for an event */
304 Status
= ObReferenceObjectByHandle(Event
,
308 (PVOID
*)&EventObject
,
310 if (!NT_SUCCESS(Status
))
312 /* Dereference the file object and fail */
313 ObDereferenceObject(FileObject
);
318 KeClearEvent(EventObject
);
321 /* Check if this is a file that was opened for Synch I/O */
322 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
325 IopLockFileObject(FileObject
);
327 /* Remember to unlock later */
328 LockedForSynch
= TRUE
;
331 /* Check if this is a direct open or not */
332 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
334 /* It's a direct open, get the attached device */
335 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
339 /* Otherwise get the related device */
340 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
343 /* Clear the event */
344 KeClearEvent(&FileObject
->Event
);
347 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
348 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
351 Irp
->UserIosb
= IoStatusBlock
;
352 Irp
->UserEvent
= EventObject
;
353 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
354 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
356 Irp
->CancelRoutine
= NULL
;
357 Irp
->PendingReturned
= FALSE
;
358 Irp
->RequestorMode
= PreviousMode
;
359 Irp
->MdlAddress
= NULL
;
360 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
362 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
363 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
364 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
366 /* Set stack location settings */
367 StackPtr
= IoGetNextIrpStackLocation(Irp
);
368 StackPtr
->FileObject
= FileObject
;
369 StackPtr
->MajorFunction
= IsDevIoCtl
?
370 IRP_MJ_DEVICE_CONTROL
:
371 IRP_MJ_FILE_SYSTEM_CONTROL
;
372 StackPtr
->MinorFunction
= 0;
373 StackPtr
->Control
= 0;
375 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
377 /* Set the IOCTL Data */
378 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
379 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
380 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
383 /* Handle the Methods */
387 case METHOD_BUFFERED
:
389 /* Enter SEH for allocations */
392 /* Select the right Buffer Length */
393 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
394 InputBufferLength
: OutputBufferLength
;
396 /* Make sure there is one */
399 /* Allocate the System Buffer */
400 Irp
->AssociatedIrp
.SystemBuffer
=
401 ExAllocatePoolWithTag(NonPagedPool
,
405 /* Check if we got a buffer */
408 /* Copy into the System Buffer */
409 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
414 /* Write the flags */
415 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
416 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
418 /* Save the Buffer */
419 Irp
->UserBuffer
= OutputBuffer
;
423 /* Clear the Flags and Buffer */
424 Irp
->UserBuffer
= NULL
;
427 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
429 /* Cleanup after exception and return */
430 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
431 _SEH2_YIELD(return _SEH2_GetExceptionCode());
437 case METHOD_IN_DIRECT
:
438 case METHOD_OUT_DIRECT
:
443 /* Check if we got an input buffer */
444 if ((InputBufferLength
) && (InputBuffer
))
446 /* Allocate the System Buffer */
447 Irp
->AssociatedIrp
.SystemBuffer
=
448 ExAllocatePoolWithTag(NonPagedPool
,
452 /* Copy into the System Buffer */
453 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
457 /* Write the flags */
458 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
461 /* Check if we got an output buffer */
464 /* Allocate the System Buffer */
465 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
470 if (!Irp
->MdlAddress
)
472 /* Raise exception we'll catch */
473 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
477 MmProbeAndLockPages(Irp
->MdlAddress
,
479 (AccessType
== METHOD_IN_DIRECT
) ?
480 IoReadAccess
: IoWriteAccess
);
483 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
485 /* Cleanup after exception and return */
486 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
487 _SEH2_YIELD(return _SEH2_GetExceptionCode());
494 /* Just save the Buffer */
495 Irp
->UserBuffer
= OutputBuffer
;
496 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
499 /* Use deferred completion for FS I/O */
500 Irp
->Flags
|= (!IsDevIoCtl
) ? IRP_DEFER_IO_COMPLETION
: 0;
502 /* Perform the call */
503 return IopPerformSynchronousRequest(DeviceObject
,
514 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
515 IN ULONG InformationClass
,
517 OUT PVOID Information
,
518 OUT PULONG ReturnedLength
,
521 IO_STATUS_BLOCK IoStatusBlock
;
523 PDEVICE_OBJECT DeviceObject
;
524 PIO_STACK_LOCATION StackPtr
;
525 BOOLEAN LocalEvent
= FALSE
;
529 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
530 FileObject
, InformationClass
, File
);
532 /* Reference the object */
533 ObReferenceObject(FileObject
);
535 /* Check if this is a file that was opened for Synch I/O */
536 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
539 IopLockFileObject(FileObject
);
541 /* Use File Object event */
542 KeClearEvent(&FileObject
->Event
);
546 /* Use local event */
547 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
551 /* Get the Device Object */
552 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
554 /* Allocate the IRP */
555 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
556 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
559 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
560 Irp
->RequestorMode
= KernelMode
;
561 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
562 Irp
->UserIosb
= &IoStatusBlock
;
563 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
564 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
565 Irp
->Flags
|= IRP_BUFFERED_IO
;
566 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
567 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
569 /* Set the Stack Data */
570 StackPtr
= IoGetNextIrpStackLocation(Irp
);
571 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
572 IRP_MJ_QUERY_VOLUME_INFORMATION
;
573 StackPtr
->FileObject
= FileObject
;
575 /* Check which type this is */
579 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
580 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
585 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
586 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
590 IopQueueIrpToThread(Irp
);
592 /* Call the Driver */
593 Status
= IoCallDriver(DeviceObject
, Irp
);
595 /* Check if this was synch I/O */
598 /* Check if the requet is pending */
599 if (Status
== STATUS_PENDING
)
601 /* Wait on the file object */
602 Status
= KeWaitForSingleObject(&FileObject
->Event
,
605 FileObject
->Flags
& FO_ALERTABLE_IO
,
607 if (Status
== STATUS_ALERTED
)
609 /* Abort the operation */
610 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
613 /* Get the final status */
614 Status
= FileObject
->FinalStatus
;
617 /* Release the file lock */
618 IopUnlockFileObject(FileObject
);
620 else if (Status
== STATUS_PENDING
)
622 /* Wait on the local event and get the final status */
623 KeWaitForSingleObject(&Event
,
628 Status
= IoStatusBlock
.Status
;
631 /* Return the Length and Status. ReturnedLength is NOT optional */
632 *ReturnedLength
= IoStatusBlock
.Information
;
636 /* PUBLIC FUNCTIONS **********************************************************/
643 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
645 IN PLARGE_INTEGER Offset
,
647 IN PIO_STATUS_BLOCK StatusBlock
)
650 PIO_STACK_LOCATION StackPtr
;
651 PDEVICE_OBJECT DeviceObject
;
652 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
653 FileObject
, Mdl
, Offset
);
655 /* Get the Device Object */
656 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
659 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
660 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
663 StackPtr
= IoGetNextIrpStackLocation(Irp
);
665 /* Create the IRP Settings */
666 Irp
->MdlAddress
= Mdl
;
667 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
668 Irp
->UserIosb
= StatusBlock
;
669 Irp
->UserEvent
= Event
;
670 Irp
->RequestorMode
= KernelMode
;
671 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
672 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
673 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
675 /* Set the Stack Settings */
676 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
677 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
678 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
679 StackPtr
->FileObject
= FileObject
;
681 /* Call the Driver */
682 return IoCallDriver(DeviceObject
, Irp
);
690 IoPageRead(IN PFILE_OBJECT FileObject
,
692 IN PLARGE_INTEGER Offset
,
694 IN PIO_STATUS_BLOCK StatusBlock
)
697 PIO_STACK_LOCATION StackPtr
;
698 PDEVICE_OBJECT DeviceObject
;
699 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
700 FileObject
, Mdl
, Offset
);
702 /* Get the Device Object */
703 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
706 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
707 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
710 StackPtr
= IoGetNextIrpStackLocation(Irp
);
712 /* Create the IRP Settings */
713 Irp
->MdlAddress
= Mdl
;
714 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
715 Irp
->UserIosb
= StatusBlock
;
716 Irp
->UserEvent
= Event
;
717 Irp
->RequestorMode
= KernelMode
;
718 Irp
->Flags
= IRP_PAGING_IO
|
720 IRP_SYNCHRONOUS_PAGING_IO
|
722 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
723 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
725 /* Set the Stack Settings */
726 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
727 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
728 StackPtr
->MajorFunction
= IRP_MJ_READ
;
729 StackPtr
->FileObject
= FileObject
;
731 /* Call the Driver */
732 return IoCallDriver(DeviceObject
, Irp
);
740 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
741 IN FILE_INFORMATION_CLASS FileInformationClass
,
743 OUT PVOID FileInformation
,
744 OUT PULONG ReturnedLength
)
746 /* Call the shared routine */
747 return IopQueryDeviceInformation(FileObject
,
748 FileInformationClass
,
760 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
761 IN FS_INFORMATION_CLASS FsInformationClass
,
763 OUT PVOID FsInformation
,
764 OUT PULONG ReturnedLength
)
766 /* Call the shared routine */
767 return IopQueryDeviceInformation(FileObject
,
780 IoSetInformation(IN PFILE_OBJECT FileObject
,
781 IN FILE_INFORMATION_CLASS FileInformationClass
,
783 IN PVOID FileInformation
)
785 IO_STATUS_BLOCK IoStatusBlock
;
787 PDEVICE_OBJECT DeviceObject
;
788 PIO_STACK_LOCATION StackPtr
;
789 BOOLEAN LocalEvent
= FALSE
;
793 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
794 FileObject
, FileInformationClass
, Length
);
796 /* Reference the object */
797 ObReferenceObject(FileObject
);
799 /* Check if this is a file that was opened for Synch I/O */
800 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
803 IopLockFileObject(FileObject
);
805 /* Use File Object event */
806 KeClearEvent(&FileObject
->Event
);
810 /* Use local event */
811 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
815 /* Get the Device Object */
816 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
818 /* Allocate the IRP */
819 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
820 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
823 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
824 Irp
->RequestorMode
= KernelMode
;
825 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
826 Irp
->UserIosb
= &IoStatusBlock
;
827 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
828 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
829 Irp
->Flags
|= IRP_BUFFERED_IO
;
830 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
831 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
833 /* Set the Stack Data */
834 StackPtr
= IoGetNextIrpStackLocation(Irp
);
835 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
836 StackPtr
->FileObject
= FileObject
;
839 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
840 StackPtr
->Parameters
.SetFile
.Length
= Length
;
843 IopQueueIrpToThread(Irp
);
845 /* Call the Driver */
846 Status
= IoCallDriver(DeviceObject
, Irp
);
848 /* Check if this was synch I/O */
851 /* Check if the requet is pending */
852 if (Status
== STATUS_PENDING
)
854 /* Wait on the file object */
855 Status
= KeWaitForSingleObject(&FileObject
->Event
,
858 FileObject
->Flags
& FO_ALERTABLE_IO
,
860 if (Status
== STATUS_ALERTED
)
862 /* Abort the operation */
863 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
866 /* Get the final status */
867 Status
= FileObject
->FinalStatus
;
870 /* Release the file lock */
871 IopUnlockFileObject(FileObject
);
873 else if (Status
== STATUS_PENDING
)
875 /* Wait on the local event and get the final status */
876 KeWaitForSingleObject(&Event
,
881 Status
= IoStatusBlock
.Status
;
884 /* Return the status */
888 /* NATIVE SERVICES ***********************************************************/
895 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
896 IN HANDLE Event OPTIONAL
,
897 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
898 IN PVOID UserApcContext OPTIONAL
,
899 OUT PIO_STATUS_BLOCK IoStatusBlock
,
900 IN ULONG IoControlCode
,
901 IN PVOID InputBuffer
,
902 IN ULONG InputBufferLength OPTIONAL
,
903 OUT PVOID OutputBuffer
,
904 IN ULONG OutputBufferLength OPTIONAL
)
906 /* Call the Generic Function */
907 return IopDeviceFsIoControl(DeviceHandle
,
925 NtFsControlFile(IN HANDLE DeviceHandle
,
926 IN HANDLE Event OPTIONAL
,
927 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
928 IN PVOID UserApcContext OPTIONAL
,
929 OUT PIO_STATUS_BLOCK IoStatusBlock
,
930 IN ULONG IoControlCode
,
931 IN PVOID InputBuffer
,
932 IN ULONG InputBufferLength OPTIONAL
,
933 OUT PVOID OutputBuffer
,
934 IN ULONG OutputBufferLength OPTIONAL
)
936 /* Call the Generic Function */
937 return IopDeviceFsIoControl(DeviceHandle
,
952 NtFlushBuffersFile(IN HANDLE FileHandle
,
953 OUT PIO_STATUS_BLOCK IoStatusBlock
)
955 PFILE_OBJECT FileObject
;
957 PIO_STACK_LOCATION StackPtr
;
959 PDEVICE_OBJECT DeviceObject
;
960 PKEVENT Event
= NULL
;
961 BOOLEAN LocalEvent
= FALSE
;
962 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
963 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
964 IO_STATUS_BLOCK KernelIosb
;
966 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
968 if (PreviousMode
!= KernelMode
)
973 /* Probe the I/O Status block */
974 ProbeForWriteIoStatusBlock(IoStatusBlock
);
976 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
978 /* Return the exception code */
979 _SEH2_YIELD(return _SEH2_GetExceptionCode());
984 /* Get the File Object */
985 Status
= ObReferenceObjectByHandle(FileHandle
,
991 if (!NT_SUCCESS(Status
)) return Status
;
994 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
995 * granted. However, if this is a named pipe, make sure we don't ask for
996 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
999 if (!(ObjectHandleInfo
.GrantedAccess
&
1000 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1004 ObDereferenceObject(FileObject
);
1005 return STATUS_ACCESS_DENIED
;
1008 /* Check if we should use Sync IO or not */
1009 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1012 IopLockFileObject(FileObject
);
1016 /* Use local event */
1017 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1021 ObDereferenceObject(FileObject
);
1022 return STATUS_INSUFFICIENT_RESOURCES
;
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();
1099 BOOLEAN LockedForSync
= FALSE
;
1101 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1103 /* Check if we're called from user mode */
1104 if (PreviousMode
!= KernelMode
)
1106 /* Enter SEH for probing */
1109 /* Probe the I/O STatus block */
1110 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1112 /* Probe the buffer */
1113 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1115 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1117 /* Return the exception code */
1118 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1122 /* Check if CompletionFilter is valid */
1123 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1125 return STATUS_INVALID_PARAMETER
;
1129 /* Get File Object */
1130 Status
= ObReferenceObjectByHandle(FileHandle
,
1131 FILE_LIST_DIRECTORY
,
1134 (PVOID
*)&FileObject
,
1136 if (!NT_SUCCESS(Status
)) return Status
;
1138 /* Check if we have an event handle */
1142 Status
= ObReferenceObjectByHandle(EventHandle
,
1148 if (Status
!= STATUS_SUCCESS
)
1150 ObDereferenceObject(FileObject
);
1153 KeClearEvent(Event
);
1156 /* Check if we should use Sync IO or not */
1157 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1160 IopLockFileObject(FileObject
);
1161 LockedForSync
= TRUE
;
1164 /* Clear File Object event */
1165 KeClearEvent(&FileObject
->Event
);
1167 /* Get the device object */
1168 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1170 /* Allocate the IRP */
1171 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1172 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1174 /* Set up the IRP */
1175 Irp
->RequestorMode
= PreviousMode
;
1176 Irp
->UserIosb
= IoStatusBlock
;
1177 Irp
->UserEvent
= Event
;
1178 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1179 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1180 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1181 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1183 /* Set up Stack Data */
1184 IoStack
= IoGetNextIrpStackLocation(Irp
);
1185 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1186 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1187 IoStack
->FileObject
= FileObject
;
1189 /* Set parameters */
1190 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1191 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1192 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1194 /* Perform the call */
1195 return IopPerformSynchronousRequest(DeviceObject
,
1209 NtLockFile(IN HANDLE FileHandle
,
1210 IN HANDLE EventHandle OPTIONAL
,
1211 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1212 IN PVOID ApcContext OPTIONAL
,
1213 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1214 IN PLARGE_INTEGER ByteOffset
,
1215 IN PLARGE_INTEGER Length
,
1217 IN BOOLEAN FailImmediately
,
1218 IN BOOLEAN ExclusiveLock
)
1220 PFILE_OBJECT FileObject
;
1221 PLARGE_INTEGER LocalLength
= NULL
;
1223 PIO_STACK_LOCATION StackPtr
;
1224 PDEVICE_OBJECT DeviceObject
;
1225 PKEVENT Event
= NULL
;
1226 BOOLEAN LockedForSync
= FALSE
;
1227 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1228 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1230 OBJECT_HANDLE_INFORMATION HandleInformation
;
1232 CapturedByteOffset
.QuadPart
= 0;
1233 CapturedLength
.QuadPart
= 0;
1234 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1236 /* Get File Object */
1237 Status
= ObReferenceObjectByHandle(FileHandle
,
1241 (PVOID
*)&FileObject
,
1242 &HandleInformation
);
1243 if (!NT_SUCCESS(Status
)) return Status
;
1245 /* Check if we're called from user mode */
1246 if (PreviousMode
!= KernelMode
)
1248 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1249 if (!(HandleInformation
.GrantedAccess
&
1250 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1252 ObDereferenceObject(FileObject
);
1253 return STATUS_ACCESS_DENIED
;
1256 /* Enter SEH for probing */
1259 /* Probe the I/O STatus block */
1260 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1262 /* Probe and capture the large integers */
1263 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1264 CapturedLength
= ProbeForReadLargeInteger(Length
);
1266 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1268 /* Dereference the object and return exception code */
1269 ObDereferenceObject(FileObject
);
1270 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1276 /* Otherwise, capture them directly */
1277 CapturedByteOffset
= *ByteOffset
;
1278 CapturedLength
= *Length
;
1281 /* Check if we have an event handle */
1285 Status
= ObReferenceObjectByHandle(EventHandle
,
1291 if (Status
!= STATUS_SUCCESS
) return Status
;
1292 KeClearEvent(Event
);
1295 /* Get the device object */
1296 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1298 /* Check if we should use Sync IO or not */
1299 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1302 IopLockFileObject(FileObject
);
1303 LockedForSync
= TRUE
;
1306 /* Clear File Object event */
1307 KeClearEvent(&FileObject
->Event
);
1308 FileObject
->LockOperation
= TRUE
;
1310 /* Allocate the IRP */
1311 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1312 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1314 /* Set up the IRP */
1315 Irp
->RequestorMode
= PreviousMode
;
1316 Irp
->UserIosb
= IoStatusBlock
;
1317 Irp
->UserEvent
= Event
;
1318 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1319 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1320 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1321 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1323 /* Set up Stack Data */
1324 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1325 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1326 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1327 StackPtr
->FileObject
= FileObject
;
1332 /* Allocate local buffer */
1333 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1334 sizeof(LARGE_INTEGER
),
1337 /* Set the length */
1338 *LocalLength
= CapturedLength
;
1339 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1340 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1342 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1344 /* Allocating failed, clean up and return the exception code */
1345 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1346 if (LocalLength
) ExFreePool(LocalLength
);
1348 /* Return the exception code */
1349 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1353 /* Set Parameters */
1354 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1355 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1358 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1359 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1361 /* Perform the call */
1362 return IopPerformSynchronousRequest(DeviceObject
,
1376 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1377 IN HANDLE EventHandle OPTIONAL
,
1378 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1379 IN PVOID ApcContext OPTIONAL
,
1380 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1381 OUT PVOID FileInformation
,
1383 IN FILE_INFORMATION_CLASS FileInformationClass
,
1384 IN BOOLEAN ReturnSingleEntry
,
1385 IN PUNICODE_STRING FileName OPTIONAL
,
1386 IN BOOLEAN RestartScan
)
1389 PDEVICE_OBJECT DeviceObject
;
1390 PFILE_OBJECT FileObject
;
1391 PIO_STACK_LOCATION StackPtr
;
1392 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1394 BOOLEAN LockedForSynch
= FALSE
;
1395 PKEVENT Event
= NULL
;
1396 PVOID AuxBuffer
= NULL
;
1398 UNICODE_STRING CapturedFileName
;
1399 PUNICODE_STRING SearchPattern
;
1401 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1403 /* Check if we came from user mode */
1404 if (PreviousMode
!= KernelMode
)
1406 /* Enter SEH for probing */
1409 /* Probe the I/O Status Block */
1410 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1412 /* Probe the file information */
1413 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1415 /* Check if we have a file name */
1419 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1420 if (CapturedFileName
.Length
)
1422 /* Probe its buffer */
1423 ProbeForRead(CapturedFileName
.Buffer
,
1424 CapturedFileName
.Length
,
1428 /* Allocate the auxiliary buffer */
1429 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1430 CapturedFileName
.Length
+
1431 sizeof(UNICODE_STRING
),
1433 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1434 sizeof(UNICODE_STRING
)),
1435 CapturedFileName
.Buffer
,
1436 CapturedFileName
.Length
);
1438 /* Setup the search pattern */
1439 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1440 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1441 sizeof(UNICODE_STRING
));
1442 SearchPattern
->Length
= CapturedFileName
.Length
;
1443 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1446 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1448 /* Free buffer and return the exception code */
1449 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1450 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1455 /* Get File Object */
1456 Status
= ObReferenceObjectByHandle(FileHandle
,
1457 FILE_LIST_DIRECTORY
,
1460 (PVOID
*)&FileObject
,
1462 if (!NT_SUCCESS(Status
))
1465 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1469 /* Check if we have an even handle */
1472 /* Get its pointer */
1473 Status
= ObReferenceObjectByHandle(EventHandle
,
1479 if (!NT_SUCCESS(Status
))
1482 ObDereferenceObject(FileObject
);
1487 KeClearEvent(Event
);
1490 /* Check if this is a file that was opened for Synch I/O */
1491 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1494 IopLockFileObject(FileObject
);
1496 /* Remember to unlock later */
1497 LockedForSynch
= TRUE
;
1500 /* Get the device object */
1501 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1503 /* Clear the File Object's event */
1504 KeClearEvent(&FileObject
->Event
);
1506 /* Allocate the IRP */
1507 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1508 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1510 /* Set up the IRP */
1511 Irp
->RequestorMode
= PreviousMode
;
1512 Irp
->UserIosb
= IoStatusBlock
;
1513 Irp
->UserEvent
= Event
;
1514 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1515 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1516 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1517 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1518 Irp
->MdlAddress
= NULL
;
1519 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1520 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1522 /* Check if this is buffered I/O */
1523 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1528 /* Allocate a buffer */
1529 Irp
->AssociatedIrp
.SystemBuffer
=
1530 ExAllocatePoolWithTag(NonPagedPool
,
1534 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1536 /* Allocating failed, clean up and return the exception code */
1537 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1538 if (AuxBuffer
) ExFreePool(AuxBuffer
);
1540 /* Return the exception code */
1541 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1545 /* Set the buffer and flags */
1546 Irp
->UserBuffer
= FileInformation
;
1547 Irp
->Flags
= (IRP_BUFFERED_IO
|
1548 IRP_DEALLOCATE_BUFFER
|
1549 IRP_INPUT_OPERATION
);
1551 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1555 /* Allocate an MDL */
1556 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1557 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1558 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1560 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1562 /* Allocating failed, clean up and return the exception code */
1563 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1564 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1570 /* No allocation flags, and use the buffer directly */
1571 Irp
->UserBuffer
= FileInformation
;
1574 /* Set up Stack Data */
1575 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1576 StackPtr
->FileObject
= FileObject
;
1577 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1578 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1580 /* Set Parameters */
1581 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1582 FileInformationClass
;
1583 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1584 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1585 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1586 StackPtr
->Flags
= 0;
1587 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1588 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1590 /* Set deferred I/O */
1591 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1593 /* Perform the call */
1594 return IopPerformSynchronousRequest(DeviceObject
,
1608 NtQueryEaFile(IN HANDLE FileHandle
,
1609 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1612 IN BOOLEAN ReturnSingleEntry
,
1613 IN PVOID EaList OPTIONAL
,
1614 IN ULONG EaListLength
,
1615 IN PULONG EaIndex OPTIONAL
,
1616 IN BOOLEAN RestartScan
)
1619 return STATUS_NOT_IMPLEMENTED
;
1627 NtQueryInformationFile(IN HANDLE FileHandle
,
1628 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1629 IN PVOID FileInformation
,
1631 IN FILE_INFORMATION_CLASS FileInformationClass
)
1633 OBJECT_HANDLE_INFORMATION HandleInformation
;
1634 PFILE_OBJECT FileObject
;
1637 PDEVICE_OBJECT DeviceObject
;
1638 PIO_STACK_LOCATION StackPtr
;
1639 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1640 PKEVENT Event
= NULL
;
1641 BOOLEAN LocalEvent
= FALSE
;
1642 PKNORMAL_ROUTINE NormalRoutine
;
1643 PVOID NormalContext
;
1645 IO_STATUS_BLOCK KernelIosb
;
1647 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1649 /* Check if we're called from user mode */
1650 if (PreviousMode
!= KernelMode
)
1652 /* Validate the information class */
1653 if ((FileInformationClass
>= FileMaximumInformation
) ||
1654 !(IopQueryOperationLength
[FileInformationClass
]))
1657 return STATUS_INVALID_INFO_CLASS
;
1660 /* Validate the length */
1661 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1663 /* Invalid length */
1664 return STATUS_INFO_LENGTH_MISMATCH
;
1667 /* Enter SEH for probing */
1670 /* Probe the I/O Status block */
1671 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1673 /* Probe the information */
1674 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1676 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1678 /* Return the exception code */
1679 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1685 /* Validate the information class */
1686 if ((FileInformationClass
>= FileMaximumInformation
) ||
1687 !(IopQueryOperationLength
[FileInformationClass
]))
1690 return STATUS_INVALID_INFO_CLASS
;
1693 /* Validate the length */
1694 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1696 /* Invalid length */
1697 return STATUS_INFO_LENGTH_MISMATCH
;
1701 /* Reference the Handle */
1702 Status
= ObReferenceObjectByHandle(FileHandle
,
1703 IopQueryOperationAccess
1704 [FileInformationClass
],
1707 (PVOID
*)&FileObject
,
1708 &HandleInformation
);
1709 if (!NT_SUCCESS(Status
)) return Status
;
1711 /* Check if this is a direct open or not */
1712 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1714 /* Get the device object */
1715 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1719 /* Get the device object */
1720 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1723 /* Check if this is a file that was opened for Synch I/O */
1724 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1727 IopLockFileObject(FileObject
);
1729 /* Check if the caller just wants the position */
1730 if (FileInformationClass
== FilePositionInformation
)
1732 /* Protect write in SEH */
1735 /* Write the offset */
1736 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1737 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1739 /* Fill out the I/O Status Block */
1740 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1741 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1743 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1745 /* Get the exception code */
1746 Status
= _SEH2_GetExceptionCode();
1750 /* Release the file lock, dereference the file and return */
1751 IopUnlockFileObject(FileObject
);
1752 ObDereferenceObject(FileObject
);
1758 /* Use local event */
1759 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1762 ObDereferenceObject(FileObject
);
1763 return STATUS_INSUFFICIENT_RESOURCES
;
1765 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1769 /* Clear the File Object event */
1770 KeClearEvent(&FileObject
->Event
);
1772 /* Allocate the IRP */
1773 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1774 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1777 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1778 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1779 Irp
->RequestorMode
= PreviousMode
;
1780 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1781 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1782 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1783 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1784 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1785 Irp
->MdlAddress
= NULL
;
1786 Irp
->UserBuffer
= FileInformation
;
1788 /* Set the Stack Data */
1789 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1790 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
1791 StackPtr
->FileObject
= FileObject
;
1796 /* Allocate a buffer */
1797 Irp
->AssociatedIrp
.SystemBuffer
=
1798 ExAllocatePoolWithTag(NonPagedPool
,
1802 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1804 /* Allocating failed, clean up and return the exception code */
1805 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
1806 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1811 Irp
->Flags
|= (IRP_BUFFERED_IO
|
1812 IRP_DEALLOCATE_BUFFER
|
1813 IRP_INPUT_OPERATION
|
1814 IRP_DEFER_IO_COMPLETION
);
1816 /* Set the Parameters */
1817 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
1818 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
1821 IopQueueIrpToThread(Irp
);
1823 /* Update operation counts */
1824 IopUpdateOperationCount(IopOtherTransfer
);
1826 /* Call the Driver */
1827 Status
= IoCallDriver(DeviceObject
, Irp
);
1828 if (Status
== STATUS_PENDING
)
1830 /* Check if this was async I/O */
1833 /* Then to a non-alertable wait */
1834 Status
= KeWaitForSingleObject(Event
,
1839 if (Status
== STATUS_USER_APC
)
1841 /* Abort the request */
1842 IopAbortInterruptedIrp(Event
, Irp
);
1845 /* Set the final status */
1846 Status
= KernelIosb
.Status
;
1848 /* Enter SEH to write the IOSB back */
1851 /* Write it back to the caller */
1852 *IoStatusBlock
= KernelIosb
;
1854 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1856 /* Get the exception code */
1857 Status
= _SEH2_GetExceptionCode();
1861 /* Free the event */
1866 /* Wait for the IRP */
1867 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1870 FileObject
->Flags
& FO_ALERTABLE_IO
,
1872 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
1874 /* Abort the request */
1875 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1878 /* Set the final status */
1879 Status
= FileObject
->FinalStatus
;
1881 /* Release the file lock */
1882 IopUnlockFileObject(FileObject
);
1887 /* Free the event if we had one */
1890 /* Clear it in the IRP for completion */
1891 Irp
->UserEvent
= NULL
;
1892 ExFreePoolWithTag(Event
, TAG_IO
);
1895 /* Set the caller IOSB */
1896 Irp
->UserIosb
= IoStatusBlock
;
1898 /* The IRP wasn't completed, complete it ourselves */
1899 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1900 IopCompleteRequest(&Irp
->Tail
.Apc
,
1903 (PVOID
*)&FileObject
,
1905 KeLowerIrql(OldIrql
);
1907 /* Release the file object if we had locked it*/
1908 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
1911 /* Return the Status */
1920 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
1921 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1924 IN BOOLEAN ReturnSingleEntry
,
1925 IN PVOID SidList OPTIONAL
,
1926 IN ULONG SidListLength
,
1927 IN PSID StartSid OPTIONAL
,
1928 IN BOOLEAN RestartScan
)
1931 return STATUS_NOT_IMPLEMENTED
;
1939 NtReadFile(IN HANDLE FileHandle
,
1940 IN HANDLE Event OPTIONAL
,
1941 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1942 IN PVOID ApcContext OPTIONAL
,
1943 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1946 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
1947 IN PULONG Key OPTIONAL
)
1950 PFILE_OBJECT FileObject
;
1952 PDEVICE_OBJECT DeviceObject
;
1953 PIO_STACK_LOCATION StackPtr
;
1954 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1955 PKEVENT EventObject
= NULL
;
1956 LARGE_INTEGER CapturedByteOffset
;
1957 ULONG CapturedKey
= 0;
1958 BOOLEAN Synchronous
= FALSE
;
1961 CapturedByteOffset
.QuadPart
= 0;
1962 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1964 /* Validate User-Mode Buffers */
1965 if (PreviousMode
!= KernelMode
)
1969 /* Probe the status block */
1970 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1972 /* Probe the read buffer */
1973 ProbeForWrite(Buffer
, Length
, 1);
1975 /* Check if we got a byte offset */
1978 /* Capture and probe it */
1979 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1982 /* Capture and probe the key */
1983 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
1985 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1987 /* Return the exception code */
1988 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1994 /* Kernel mode: capture directly */
1995 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
1996 if (Key
) CapturedKey
= *Key
;
1999 /* Get File Object */
2000 Status
= ObReferenceObjectByHandle(FileHandle
,
2004 (PVOID
*)&FileObject
,
2006 if (!NT_SUCCESS(Status
)) return Status
;
2008 /* Check for event */
2012 Status
= ObReferenceObjectByHandle(Event
,
2016 (PVOID
*)&EventObject
,
2018 if (!NT_SUCCESS(Status
))
2021 ObDereferenceObject(FileObject
);
2025 /* Otherwise reset the event */
2026 KeClearEvent(EventObject
);
2029 /* Check if we should use Sync IO or not */
2030 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2032 /* Lock the file object */
2033 IopLockFileObject(FileObject
);
2035 /* Check if we don't have a byte offset avilable */
2036 if (!(ByteOffset
) ||
2037 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2038 (CapturedByteOffset
.u
.HighPart
== -1)))
2040 /* Use the Current Byte Offset instead */
2041 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2044 /* Remember we are sync */
2047 else if (!(ByteOffset
) &&
2048 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2050 /* Otherwise, this was async I/O without a byte offset, so fail */
2051 if (EventObject
) ObDereferenceObject(EventObject
);
2052 ObDereferenceObject(FileObject
);
2053 return STATUS_INVALID_PARAMETER
;
2056 /* Get the device object */
2057 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2059 /* Clear the File Object's event */
2060 KeClearEvent(&FileObject
->Event
);
2062 /* Allocate the IRP */
2063 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2064 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2067 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2068 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2069 Irp
->RequestorMode
= PreviousMode
;
2070 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2071 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2072 Irp
->UserIosb
= IoStatusBlock
;
2073 Irp
->UserEvent
= EventObject
;
2074 Irp
->PendingReturned
= FALSE
;
2075 Irp
->Cancel
= FALSE
;
2076 Irp
->CancelRoutine
= NULL
;
2077 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2078 Irp
->MdlAddress
= NULL
;
2080 /* Set the Stack Data */
2081 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2082 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2083 StackPtr
->FileObject
= FileObject
;
2084 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2085 StackPtr
->Parameters
.Read
.Length
= Length
;
2086 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2088 /* Check if this is buffered I/O */
2089 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2091 /* Check if we have a buffer length */
2097 /* Allocate a buffer */
2098 Irp
->AssociatedIrp
.SystemBuffer
=
2099 ExAllocatePoolWithTag(NonPagedPool
,
2103 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2105 /* Allocating failed, clean up and return the exception code */
2106 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2107 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2111 /* Set the buffer and flags */
2112 Irp
->UserBuffer
= Buffer
;
2113 Irp
->Flags
= (IRP_BUFFERED_IO
|
2114 IRP_DEALLOCATE_BUFFER
|
2115 IRP_INPUT_OPERATION
);
2119 /* Not reading anything */
2120 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2123 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2125 /* Check if we have a buffer length */
2130 /* Allocate an MDL */
2131 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2132 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2134 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2136 /* Allocating failed, clean up and return the exception code */
2137 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2138 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2144 /* No allocation flags */
2149 /* No allocation flags, and use the buffer directly */
2151 Irp
->UserBuffer
= Buffer
;
2154 /* Now set the deferred read flags */
2155 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2157 /* FIXME: VFAT SUCKS */
2158 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2161 /* Perform the call */
2162 return IopPerformSynchronousRequest(DeviceObject
,
2176 NtReadFileScatter(IN HANDLE FileHandle
,
2177 IN HANDLE Event OPTIONAL
,
2178 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2179 IN PVOID UserApcContext OPTIONAL
,
2180 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2181 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2182 IN ULONG BufferLength
,
2183 IN PLARGE_INTEGER ByteOffset
,
2184 IN PULONG Key OPTIONAL
)
2187 return STATUS_NOT_IMPLEMENTED
;
2195 NtSetEaFile(IN HANDLE FileHandle
,
2196 IN PIO_STATUS_BLOCK IoStatusBlock
,
2198 IN ULONG EaBufferSize
)
2201 return STATUS_NOT_IMPLEMENTED
;
2209 NtSetInformationFile(IN HANDLE FileHandle
,
2210 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2211 IN PVOID FileInformation
,
2213 IN FILE_INFORMATION_CLASS FileInformationClass
)
2215 PFILE_OBJECT FileObject
;
2218 PDEVICE_OBJECT DeviceObject
;
2219 PIO_STACK_LOCATION StackPtr
;
2220 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2221 PKEVENT Event
= NULL
;
2222 BOOLEAN LocalEvent
= FALSE
;
2223 PKNORMAL_ROUTINE NormalRoutine
;
2224 PVOID NormalContext
;
2226 IO_STATUS_BLOCK KernelIosb
;
2228 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2229 PIO_COMPLETION_CONTEXT Context
;
2231 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2233 /* Check if we're called from user mode */
2234 if (PreviousMode
!= KernelMode
)
2236 /* Validate the information class */
2237 if ((FileInformationClass
>= FileMaximumInformation
) ||
2238 !(IopSetOperationLength
[FileInformationClass
]))
2241 return STATUS_INVALID_INFO_CLASS
;
2244 /* Validate the length */
2245 if (Length
< IopSetOperationLength
[FileInformationClass
])
2247 /* Invalid length */
2248 return STATUS_INFO_LENGTH_MISMATCH
;
2251 /* Enter SEH for probing */
2254 /* Probe the I/O Status block */
2255 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2257 /* Probe the information */
2258 ProbeForRead(FileInformation
,
2260 (Length
== sizeof(BOOLEAN
)) ?
2261 sizeof(BOOLEAN
) : sizeof(ULONG
));
2263 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2265 /* Return the exception code */
2266 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2272 /* Validate the information class */
2273 if ((FileInformationClass
>= FileMaximumInformation
) ||
2274 !(IopSetOperationLength
[FileInformationClass
]))
2277 return STATUS_INVALID_INFO_CLASS
;
2280 /* Validate the length */
2281 if (Length
< IopSetOperationLength
[FileInformationClass
])
2283 /* Invalid length */
2284 return STATUS_INFO_LENGTH_MISMATCH
;
2288 /* Reference the Handle */
2289 Status
= ObReferenceObjectByHandle(FileHandle
,
2290 IopSetOperationAccess
2291 [FileInformationClass
],
2294 (PVOID
*)&FileObject
,
2296 if (!NT_SUCCESS(Status
)) return Status
;
2298 /* Check if this is a direct open or not */
2299 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2301 /* Get the device object */
2302 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2306 /* Get the device object */
2307 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2310 /* Check if this is a file that was opened for Synch I/O */
2311 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2314 IopLockFileObject(FileObject
);
2316 /* Check if the caller just wants the position */
2317 if (FileInformationClass
== FilePositionInformation
)
2319 /* Protect write in SEH */
2322 /* Write the offset */
2323 FileObject
->CurrentByteOffset
=
2324 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2327 /* Fill out the I/O Status Block */
2328 IoStatusBlock
->Information
= 0;
2329 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2331 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2333 /* Get the exception code */
2334 Status
= _SEH2_GetExceptionCode();
2338 /* Update transfer count */
2339 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2341 /* Release the file lock, dereference the file and return */
2342 IopUnlockFileObject(FileObject
);
2343 ObDereferenceObject(FileObject
);
2349 /* Use local event */
2350 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2353 ObDereferenceObject(FileObject
);
2354 return STATUS_INSUFFICIENT_RESOURCES
;
2357 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2361 /* Clear the File Object event */
2362 KeClearEvent(&FileObject
->Event
);
2364 /* Allocate the IRP */
2365 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2366 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2369 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2370 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2371 Irp
->RequestorMode
= PreviousMode
;
2372 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2373 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2374 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2375 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2376 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2377 Irp
->MdlAddress
= NULL
;
2378 Irp
->UserBuffer
= FileInformation
;
2380 /* Set the Stack Data */
2381 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2382 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2383 StackPtr
->FileObject
= FileObject
;
2388 /* Allocate a buffer */
2389 Irp
->AssociatedIrp
.SystemBuffer
=
2390 ExAllocatePoolWithTag(NonPagedPool
,
2394 /* Copy the data into it */
2395 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2399 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2401 /* Allocating failed, clean up and return the exception code */
2402 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2403 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2408 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2409 IRP_DEALLOCATE_BUFFER
|
2410 IRP_DEFER_IO_COMPLETION
);
2412 /* Set the Parameters */
2413 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2414 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2417 IopQueueIrpToThread(Irp
);
2419 /* Update operation counts */
2420 IopUpdateOperationCount(IopOtherTransfer
);
2422 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2423 /* Handle IO Completion Port quickly */
2424 if (FileInformationClass
== FileCompletionInformation
)
2426 /* Check if the file object already has a completion port */
2427 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2428 (FileObject
->CompletionContext
))
2431 Status
= STATUS_INVALID_PARAMETER
;
2435 /* Reference the Port */
2436 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2437 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2438 IO_COMPLETION_MODIFY_STATE
,
2443 if (NT_SUCCESS(Status
))
2445 /* Allocate the Context */
2446 Context
= ExAllocatePoolWithTag(PagedPool
,
2447 sizeof(IO_COMPLETION_CONTEXT
),
2452 Context
->Key
= CompletionInfo
->Key
;
2453 Context
->Port
= Queue
;
2454 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
2460 * Someone else set the completion port in the
2461 * meanwhile, so dereference the port and fail.
2463 ExFreePool(Context
);
2464 ObDereferenceObject(Queue
);
2465 Status
= STATUS_INVALID_PARAMETER
;
2470 /* Dereference the Port now */
2471 ObDereferenceObject(Queue
);
2472 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2477 /* Set the IRP Status */
2478 Irp
->IoStatus
.Status
= Status
;
2479 Irp
->IoStatus
.Information
= 0;
2483 /* Call the Driver */
2484 Status
= IoCallDriver(DeviceObject
, Irp
);
2487 /* Check if we're waiting for the IRP to complete */
2488 if (Status
== STATUS_PENDING
)
2490 /* Check if this was async I/O */
2493 /* Then to a non-alertable wait */
2494 Status
= KeWaitForSingleObject(Event
,
2499 if (Status
== STATUS_USER_APC
)
2501 /* Abort the request */
2502 IopAbortInterruptedIrp(Event
, Irp
);
2505 /* Set the final status */
2506 Status
= KernelIosb
.Status
;
2508 /* Enter SEH to write the IOSB back */
2511 /* Write it back to the caller */
2512 *IoStatusBlock
= KernelIosb
;
2514 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2516 /* Get the exception code */
2517 Status
= _SEH2_GetExceptionCode();
2521 /* Free the event */
2526 /* Wait for the IRP */
2527 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2530 FileObject
->Flags
& FO_ALERTABLE_IO
,
2532 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2534 /* Abort the request */
2535 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2538 /* Set the final status */
2539 Status
= FileObject
->FinalStatus
;
2541 /* Release the file lock */
2542 IopUnlockFileObject(FileObject
);
2547 /* Free the event if we had one */
2550 /* Clear it in the IRP for completion */
2551 Irp
->UserEvent
= NULL
;
2555 /* Set the caller IOSB */
2556 Irp
->UserIosb
= IoStatusBlock
;
2558 /* The IRP wasn't completed, complete it ourselves */
2559 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2560 IopCompleteRequest(&Irp
->Tail
.Apc
,
2563 (PVOID
*)&FileObject
,
2565 KeLowerIrql(OldIrql
);
2567 /* Release the file object if we had locked it*/
2568 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2571 /* Return the Status */
2580 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2581 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2583 IN ULONG BufferLength
)
2586 return STATUS_NOT_IMPLEMENTED
;
2594 NtUnlockFile(IN HANDLE FileHandle
,
2595 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2596 IN PLARGE_INTEGER ByteOffset
,
2597 IN PLARGE_INTEGER Length
,
2598 IN ULONG Key OPTIONAL
)
2600 PFILE_OBJECT FileObject
;
2601 PLARGE_INTEGER LocalLength
= NULL
;
2603 PIO_STACK_LOCATION StackPtr
;
2604 PDEVICE_OBJECT DeviceObject
;
2605 PKEVENT Event
= NULL
;
2606 BOOLEAN LocalEvent
= FALSE
;
2607 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2608 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2610 OBJECT_HANDLE_INFORMATION HandleInformation
;
2611 IO_STATUS_BLOCK KernelIosb
;
2613 CapturedByteOffset
.QuadPart
= 0;
2614 CapturedLength
.QuadPart
= 0;
2615 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2617 /* Get File Object */
2618 Status
= ObReferenceObjectByHandle(FileHandle
,
2622 (PVOID
*)&FileObject
,
2623 &HandleInformation
);
2624 if (!NT_SUCCESS(Status
)) return Status
;
2626 /* Check if we're called from user mode */
2627 if (PreviousMode
!= KernelMode
)
2629 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2630 if (!(HandleInformation
.GrantedAccess
&
2631 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2633 ObDereferenceObject(FileObject
);
2634 return STATUS_ACCESS_DENIED
;
2637 /* Enter SEH for probing */
2640 /* Probe the I/O Status block */
2641 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2643 /* Probe and capture the large integers */
2644 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2645 CapturedLength
= ProbeForReadLargeInteger(Length
);
2647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2649 /* Dereference the object and return exception code */
2650 ObDereferenceObject(FileObject
);
2651 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2657 /* Otherwise, capture them directly */
2658 CapturedByteOffset
= *ByteOffset
;
2659 CapturedLength
= *Length
;
2662 /* Check if this is a direct open or not */
2663 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2665 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2669 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2672 /* Check if we should use Sync IO or not */
2673 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2676 IopLockFileObject(FileObject
);
2680 /* Use local event */
2681 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2684 ObDereferenceObject(FileObject
);
2685 return STATUS_INSUFFICIENT_RESOURCES
;
2687 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2691 /* Clear File Object event */
2692 KeClearEvent(&FileObject
->Event
);
2694 /* Allocate the IRP */
2695 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2696 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2698 /* Set up the IRP */
2699 Irp
->RequestorMode
= PreviousMode
;
2700 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2701 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2702 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2703 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2704 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2705 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2707 /* Set up Stack Data */
2708 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2709 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2710 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2711 StackPtr
->FileObject
= FileObject
;
2716 /* Allocate a buffer */
2717 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2718 sizeof(LARGE_INTEGER
),
2721 /* Set the length */
2722 *LocalLength
= CapturedLength
;
2723 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
2724 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
2726 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2728 /* Allocating failed, clean up and return the exception code */
2729 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2730 if (LocalLength
) ExFreePool(LocalLength
);
2732 /* Return the exception code */
2733 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2737 /* Set Parameters */
2738 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
2739 StackPtr
->Parameters
.LockControl
.Key
= Key
;
2741 /* Call the Driver */
2742 Status
= IopPerformSynchronousRequest(DeviceObject
,
2750 /* Check if this was async I/O */
2753 /* It was, finalize this request */
2754 Status
= IopFinalizeAsynchronousIo(Status
,
2771 NtWriteFile(IN HANDLE FileHandle
,
2772 IN HANDLE Event OPTIONAL
,
2773 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2774 IN PVOID ApcContext OPTIONAL
,
2775 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2778 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2779 IN PULONG Key OPTIONAL
)
2782 PFILE_OBJECT FileObject
;
2784 PDEVICE_OBJECT DeviceObject
;
2785 PIO_STACK_LOCATION StackPtr
;
2786 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2787 PKEVENT EventObject
= NULL
;
2788 LARGE_INTEGER CapturedByteOffset
;
2789 ULONG CapturedKey
= 0;
2790 BOOLEAN Synchronous
= FALSE
;
2792 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
2794 CapturedByteOffset
.QuadPart
= 0;
2795 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2797 /* Get File Object */
2798 Status
= ObReferenceObjectByHandle(FileHandle
,
2802 (PVOID
*)&FileObject
,
2804 if (!NT_SUCCESS(Status
)) return Status
;
2806 /* Validate User-Mode Buffers */
2807 if (PreviousMode
!= KernelMode
)
2812 * Check if the handle has either FILE_WRITE_DATA or
2813 * FILE_APPEND_DATA granted. However, if this is a named pipe,
2814 * make sure we don't ask for FILE_APPEND_DATA as it interferes
2815 * with the FILE_CREATE_PIPE_INSTANCE access right!
2817 if (!(ObjectHandleInfo
.GrantedAccess
&
2818 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
2819 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
2822 ObDereferenceObject(FileObject
);
2823 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
2826 /* Probe the status block */
2827 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2829 /* Probe the read buffer */
2830 ProbeForRead(Buffer
, Length
, 1);
2832 /* Check if we got a byte offset */
2835 /* Capture and probe it */
2836 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2839 /* Capture and probe the key */
2840 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2842 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2844 /* Return the exception code */
2845 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2851 /* Kernel mode: capture directly */
2852 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2853 if (Key
) CapturedKey
= *Key
;
2856 /* Check if this is an append operation */
2857 if ((ObjectHandleInfo
.GrantedAccess
&
2858 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
2860 /* Give the drivers something to understand */
2861 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
2862 CapturedByteOffset
.u
.HighPart
= -1;
2865 /* Check for event */
2869 Status
= ObReferenceObjectByHandle(Event
,
2873 (PVOID
*)&EventObject
,
2875 if (!NT_SUCCESS(Status
))
2878 ObDereferenceObject(FileObject
);
2882 /* Otherwise reset the event */
2883 KeClearEvent(EventObject
);
2886 /* Check if we should use Sync IO or not */
2887 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2889 /* Lock the file object */
2890 IopLockFileObject(FileObject
);
2892 /* Check if we don't have a byte offset avilable */
2893 if (!(ByteOffset
) ||
2894 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2895 (CapturedByteOffset
.u
.HighPart
== -1)))
2897 /* Use the Current Byte Offset instead */
2898 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2901 /* Remember we are sync */
2904 else if (!(ByteOffset
) &&
2905 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2907 /* Otherwise, this was async I/O without a byte offset, so fail */
2908 if (EventObject
) ObDereferenceObject(EventObject
);
2909 ObDereferenceObject(FileObject
);
2910 return STATUS_INVALID_PARAMETER
;
2913 /* Get the device object */
2914 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2916 /* Clear the File Object's event */
2917 KeClearEvent(&FileObject
->Event
);
2919 /* Allocate the IRP */
2920 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2921 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2924 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2925 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2926 Irp
->RequestorMode
= PreviousMode
;
2927 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2928 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2929 Irp
->UserIosb
= IoStatusBlock
;
2930 Irp
->UserEvent
= EventObject
;
2931 Irp
->PendingReturned
= FALSE
;
2932 Irp
->Cancel
= FALSE
;
2933 Irp
->CancelRoutine
= NULL
;
2934 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2935 Irp
->MdlAddress
= NULL
;
2937 /* Set the Stack Data */
2938 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2939 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
2940 StackPtr
->FileObject
= FileObject
;
2941 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
2942 SL_WRITE_THROUGH
: 0;
2943 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
2944 StackPtr
->Parameters
.Write
.Length
= Length
;
2945 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
2947 /* Check if this is buffered I/O */
2948 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2950 /* Check if we have a buffer length */
2956 /* Allocate a buffer */
2957 Irp
->AssociatedIrp
.SystemBuffer
=
2958 ExAllocatePoolWithTag(NonPagedPool
,
2962 /* Copy the data into it */
2963 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
2965 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2967 /* Allocating failed, clean up and return the exception code */
2968 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2969 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2974 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
2978 /* Not writing anything */
2979 Irp
->Flags
= IRP_BUFFERED_IO
;
2982 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2984 /* Check if we have a buffer length */
2989 /* Allocate an MDL */
2990 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2991 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
2993 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2995 /* Allocating failed, clean up and return the exception code */
2996 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2997 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3002 /* No allocation flags */
3007 /* No allocation flags, and use the buffer directly */
3009 Irp
->UserBuffer
= Buffer
;
3012 /* Now set the deferred read flags */
3013 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3015 /* FIXME: VFAT SUCKS */
3016 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3019 /* Perform the call */
3020 return IopPerformSynchronousRequest(DeviceObject
,
3031 NtWriteFileGather(IN HANDLE FileHandle
,
3032 IN HANDLE Event OPTIONAL
,
3033 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3034 IN PVOID UserApcContext OPTIONAL
,
3035 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3036 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3037 IN ULONG BufferLength
,
3038 IN PLARGE_INTEGER ByteOffset
,
3039 IN PULONG Key OPTIONAL
)
3042 return STATUS_NOT_IMPLEMENTED
;
3050 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3051 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3052 OUT PVOID FsInformation
,
3054 IN FS_INFORMATION_CLASS FsInformationClass
)
3056 PFILE_OBJECT FileObject
;
3058 PIO_STACK_LOCATION StackPtr
;
3059 PDEVICE_OBJECT DeviceObject
;
3060 PKEVENT Event
= NULL
;
3061 BOOLEAN LocalEvent
= FALSE
;
3062 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3064 IO_STATUS_BLOCK KernelIosb
;
3066 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3068 /* Check if we're called from user mode */
3069 if (PreviousMode
!= KernelMode
)
3071 /* Validate the information class */
3072 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3073 !(IopQueryFsOperationLength
[FsInformationClass
]))
3076 return STATUS_INVALID_INFO_CLASS
;
3079 /* Validate the length */
3080 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3082 /* Invalid length */
3083 return STATUS_INFO_LENGTH_MISMATCH
;
3086 /* Enter SEH for probing */
3089 /* Probe the I/O Status block */
3090 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3092 /* Probe the information */
3093 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3095 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3097 /* Return the exception code */
3098 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3103 /* Get File Object */
3104 Status
= ObReferenceObjectByHandle(FileHandle
,
3105 IopQueryFsOperationAccess
3106 [FsInformationClass
],
3109 (PVOID
*)&FileObject
,
3111 if (!NT_SUCCESS(Status
)) return Status
;
3113 /* Check if we should use Sync IO or not */
3114 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3117 IopLockFileObject(FileObject
);
3121 /* Use local event */
3122 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3125 ObDereferenceObject(FileObject
);
3126 return STATUS_INSUFFICIENT_RESOURCES
;
3128 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3132 /* Get the device object */
3133 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3135 /* Clear File Object event */
3136 KeClearEvent(&FileObject
->Event
);
3138 /* Allocate the IRP */
3139 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3140 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3142 /* Set up the IRP */
3143 Irp
->RequestorMode
= PreviousMode
;
3144 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3145 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3146 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3147 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3148 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3149 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3150 Irp
->UserBuffer
= FsInformation
;
3151 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3152 Irp
->MdlAddress
= NULL
;
3154 /* Set up Stack Data */
3155 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3156 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3157 StackPtr
->FileObject
= FileObject
;
3162 /* Allocate a buffer */
3163 Irp
->AssociatedIrp
.SystemBuffer
=
3164 ExAllocatePoolWithTag(NonPagedPool
,
3168 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3170 /* Allocating failed, clean up and return the exception code */
3171 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3172 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3176 /* Set the flags for this buffered + deferred I/O */
3177 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3178 IRP_DEALLOCATE_BUFFER
|
3179 IRP_INPUT_OPERATION
|
3180 IRP_DEFER_IO_COMPLETION
);
3182 /* Set Parameters */
3183 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3184 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3186 /* Call the Driver */
3187 Status
= IopPerformSynchronousRequest(DeviceObject
,
3195 /* Check if this was async I/O */
3198 /* It was, finalize this request */
3199 Status
= IopFinalizeAsynchronousIo(Status
,
3216 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3217 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3218 IN PVOID FsInformation
,
3220 IN FS_INFORMATION_CLASS FsInformationClass
)
3222 PFILE_OBJECT FileObject
;
3224 PIO_STACK_LOCATION StackPtr
;
3225 PDEVICE_OBJECT DeviceObject
;
3226 PKEVENT Event
= NULL
;
3227 BOOLEAN LocalEvent
= FALSE
;
3228 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3230 IO_STATUS_BLOCK KernelIosb
;
3232 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3234 /* Check if we're called from user mode */
3235 if (PreviousMode
!= KernelMode
)
3237 /* Validate the information class */
3238 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3239 !(IopSetFsOperationLength
[FsInformationClass
]))
3242 return STATUS_INVALID_INFO_CLASS
;
3245 /* Validate the length */
3246 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3248 /* Invalid length */
3249 return STATUS_INFO_LENGTH_MISMATCH
;
3252 /* Enter SEH for probing */
3255 /* Probe the I/O Status block */
3256 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3258 /* Probe the information */
3259 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3263 /* Return the exception code */
3264 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3269 /* Get File Object */
3270 Status
= ObReferenceObjectByHandle(FileHandle
,
3271 IopSetFsOperationAccess
3272 [FsInformationClass
],
3275 (PVOID
*)&FileObject
,
3277 if (!NT_SUCCESS(Status
)) return Status
;
3279 /* Check if we should use Sync IO or not */
3280 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3283 IopLockFileObject(FileObject
);
3287 /* Use local event */
3288 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3291 ObDereferenceObject(FileObject
);
3292 return STATUS_INSUFFICIENT_RESOURCES
;
3294 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3298 /* Get the device object */
3299 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3301 /* Clear File Object event */
3302 KeClearEvent(&FileObject
->Event
);
3304 /* Allocate the IRP */
3305 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3306 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3308 /* Set up the IRP */
3309 Irp
->RequestorMode
= PreviousMode
;
3310 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3311 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3312 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3313 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3314 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3315 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3316 Irp
->UserBuffer
= FsInformation
;
3317 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3318 Irp
->MdlAddress
= NULL
;
3320 /* Set up Stack Data */
3321 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3322 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3323 StackPtr
->FileObject
= FileObject
;
3328 /* Allocate a buffer */
3329 Irp
->AssociatedIrp
.SystemBuffer
=
3330 ExAllocatePoolWithTag(NonPagedPool
,
3334 /* Copy the data into it */
3335 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3337 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3339 /* Allocating failed, clean up and return the exception code */
3340 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3341 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3345 /* Set the flags for this buffered + deferred I/O */
3346 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3348 /* Set Parameters */
3349 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3350 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3352 /* Call the Driver */
3353 Status
= IopPerformSynchronousRequest(DeviceObject
,
3361 /* Check if this was async I/O */
3364 /* It was, finalize this request */
3365 Status
= IopFinalizeAsynchronousIo(Status
,
3382 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3385 return STATUS_NOT_IMPLEMENTED
;
3393 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3396 return STATUS_NOT_IMPLEMENTED
;