2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iofunc.c
5 * PURPOSE: Generic I/O Functions that build IRPs for various operations
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Filip Navara (navaraf@reactos.org)
11 /* INCLUDES *****************************************************************/
17 #include "internal/io_i.h"
19 /* PRIVATE FUNCTIONS *********************************************************/
23 IopCleanupAfterException(IN PFILE_OBJECT FileObject
,
25 IN PKEVENT Event OPTIONAL
,
26 IN PKEVENT LocalEvent OPTIONAL
)
29 IOTRACE(IO_API_DEBUG
, "IRP: %p. FO: %p \n", Irp
, FileObject
);
31 /* Check if we had a buffer */
32 if (Irp
->AssociatedIrp
.SystemBuffer
)
35 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
39 if (Irp
->MdlAddress
) IoFreeMdl(Irp
->MdlAddress
);
44 /* Check if we had a file lock */
45 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
48 IopUnlockFileObject(FileObject
);
51 /* Check if we had an event */
52 if (Event
) ObDereferenceObject(Event
);
54 /* Check if we had a local event */
55 if (LocalEvent
) ExFreePool(LocalEvent
);
57 /* Derefenrce the FO */
58 ObDereferenceObject(FileObject
);
63 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus
,
66 IN KPROCESSOR_MODE PreviousMode
,
67 IN PIO_STATUS_BLOCK KernelIosb
,
68 OUT PIO_STATUS_BLOCK IoStatusBlock
)
70 NTSTATUS FinalStatus
= SynchStatus
;
72 IOTRACE(IO_API_DEBUG
, "IRP: %p. Status: %lx \n", Irp
, SynchStatus
);
74 /* Make sure the IRP was completed, but returned pending */
75 if (FinalStatus
== STATUS_PENDING
)
77 /* Wait for the IRP */
78 FinalStatus
= KeWaitForSingleObject(Event
,
83 if (FinalStatus
== STATUS_USER_APC
)
85 /* Abort the request */
86 IopAbortInterruptedIrp(Event
, Irp
);
89 /* Set the final status */
90 FinalStatus
= KernelIosb
->Status
;
93 /* Wrap potential user-mode write in SEH */
96 *IoStatusBlock
= *KernelIosb
;
98 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
100 /* Get the exception code */
101 FinalStatus
= _SEH2_GetExceptionCode();
105 /* Free the event and return status */
112 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject
,
114 IN PFILE_OBJECT FileObject
,
116 IN KPROCESSOR_MODE PreviousMode
,
118 IN IOP_TRANSFER_TYPE TransferType
)
121 PKNORMAL_ROUTINE NormalRoutine
;
122 PVOID NormalContext
= NULL
;
125 IOTRACE(IO_API_DEBUG
, "IRP: %p. DO: %p. FO: %p \n",
126 Irp
, DeviceObject
, FileObject
);
129 IopQueueIrpToThread(Irp
);
131 /* Update operation counts */
132 IopUpdateOperationCount(TransferType
);
134 /* Call the driver */
135 Status
= IoCallDriver(DeviceObject
, Irp
);
137 /* Check if we're optimizing this case */
140 /* We are! Check if the IRP wasn't completed */
141 if (Status
!= STATUS_PENDING
)
143 /* Complete it ourselves */
144 ASSERT(!Irp
->PendingReturned
);
145 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
146 IopCompleteRequest(&Irp
->Tail
.Apc
,
151 KeLowerIrql(OldIrql
);
155 /* Check if this was synch I/O */
158 /* Make sure the IRP was completed, but returned pending */
159 if (Status
== STATUS_PENDING
)
161 /* Wait for the IRP */
162 Status
= KeWaitForSingleObject(&FileObject
->Event
,
166 FO_ALERTABLE_IO
) != 0,
168 if ((Status
== STATUS_ALERTED
) || (Status
== STATUS_USER_APC
))
170 /* Abort the request */
171 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
174 /* Set the final status */
175 Status
= FileObject
->FinalStatus
;
178 /* Release the file lock */
179 IopUnlockFileObject(FileObject
);
188 IopDeviceFsIoControl(IN HANDLE DeviceHandle
,
189 IN HANDLE Event OPTIONAL
,
190 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
191 IN PVOID UserApcContext OPTIONAL
,
192 OUT PIO_STATUS_BLOCK IoStatusBlock
,
193 IN ULONG IoControlCode
,
194 IN PVOID InputBuffer
,
195 IN ULONG InputBufferLength OPTIONAL
,
196 OUT PVOID OutputBuffer
,
197 IN ULONG OutputBufferLength OPTIONAL
,
198 IN BOOLEAN IsDevIoCtl
)
201 PFILE_OBJECT FileObject
;
202 PDEVICE_OBJECT DeviceObject
;
204 PIO_STACK_LOCATION StackPtr
;
205 PKEVENT EventObject
= NULL
;
206 BOOLEAN LockedForSynch
= FALSE
;
208 OBJECT_HANDLE_INFORMATION HandleInformation
;
209 ACCESS_MASK DesiredAccess
;
210 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
212 IOTRACE(IO_CTL_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
213 DeviceHandle
, IoControlCode
, IsDevIoCtl
);
215 /* Get the access type */
216 AccessType
= IO_METHOD_FROM_CTL_CODE(IoControlCode
);
218 /* Check if we came from user mode */
219 if (PreviousMode
!= KernelMode
)
223 /* Probe the status block */
224 ProbeForWriteIoStatusBlock(IoStatusBlock
);
226 /* Check if this is buffered I/O */
227 if (AccessType
== METHOD_BUFFERED
)
229 /* Check if we have an output buffer */
232 /* Probe the output buffer */
233 ProbeForWrite(OutputBuffer
,
239 /* Make sure the caller can't fake this as we depend on this */
240 OutputBufferLength
= 0;
244 /* Check if we we have an input buffer I/O */
245 if (AccessType
!= METHOD_NEITHER
)
247 /* Check if we have an input buffer */
250 /* Probe the input buffer */
251 ProbeForRead(InputBuffer
, InputBufferLength
, sizeof(CHAR
));
255 /* Make sure the caller can't fake this as we depend on this */
256 InputBufferLength
= 0;
260 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
262 /* Return the exception code */
263 _SEH2_YIELD(return _SEH2_GetExceptionCode());
268 /* Don't check for access rights right now, KernelMode can do anything */
269 Status
= ObReferenceObjectByHandle(DeviceHandle
,
275 if (!NT_SUCCESS(Status
)) return Status
;
277 /* Can't use an I/O completion port and an APC in the same time */
278 if ((FileObject
->CompletionContext
) && (UserApcRoutine
))
281 ObDereferenceObject(FileObject
);
282 return STATUS_INVALID_PARAMETER
;
285 /* Check if we from user mode */
286 if (PreviousMode
!= KernelMode
)
288 /* Get the access mask */
289 DesiredAccess
= (ACCESS_MASK
)((IoControlCode
>> 14) & 3);
291 /* Check if we can open it */
292 if ((DesiredAccess
!= FILE_ANY_ACCESS
) &&
293 (HandleInformation
.GrantedAccess
& DesiredAccess
) != DesiredAccess
)
295 /* Dereference the file object and fail */
296 ObDereferenceObject(FileObject
);
297 return STATUS_ACCESS_DENIED
;
301 /* Check for an event */
305 Status
= ObReferenceObjectByHandle(Event
,
309 (PVOID
*)&EventObject
,
311 if (!NT_SUCCESS(Status
))
313 /* Dereference the file object and fail */
314 ObDereferenceObject(FileObject
);
319 KeClearEvent(EventObject
);
322 /* Check if this is a file that was opened for Synch I/O */
323 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
326 IopLockFileObject(FileObject
);
328 /* Remember to unlock later */
329 LockedForSynch
= TRUE
;
332 /* Check if this is a direct open or not */
333 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
335 /* It's a direct open, get the attached device */
336 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
340 /* Otherwise get the related device */
341 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
344 /* Clear the event */
345 KeClearEvent(&FileObject
->Event
);
348 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
349 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
352 Irp
->UserIosb
= IoStatusBlock
;
353 Irp
->UserEvent
= EventObject
;
354 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
355 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
357 Irp
->CancelRoutine
= NULL
;
358 Irp
->PendingReturned
= FALSE
;
359 Irp
->RequestorMode
= PreviousMode
;
360 Irp
->MdlAddress
= NULL
;
361 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
363 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
364 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
365 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
367 /* Set stack location settings */
368 StackPtr
= IoGetNextIrpStackLocation(Irp
);
369 StackPtr
->FileObject
= FileObject
;
370 StackPtr
->MajorFunction
= IsDevIoCtl
?
371 IRP_MJ_DEVICE_CONTROL
:
372 IRP_MJ_FILE_SYSTEM_CONTROL
;
373 StackPtr
->MinorFunction
= 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
374 StackPtr
->Control
= 0;
376 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= NULL
;
378 /* Set the IOCTL Data */
379 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
380 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
381 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
384 /* Handle the Methods */
388 case METHOD_BUFFERED
:
390 /* Enter SEH for allocations */
393 /* Select the right Buffer Length */
394 BufferLength
= (InputBufferLength
> OutputBufferLength
) ?
395 InputBufferLength
: OutputBufferLength
;
397 /* Make sure there is one */
400 /* Allocate the System Buffer */
401 Irp
->AssociatedIrp
.SystemBuffer
=
402 ExAllocatePoolWithTag(NonPagedPool
,
406 /* Check if we got a buffer */
409 /* Copy into the System Buffer */
410 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
415 /* Write the flags */
416 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
417 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
419 /* Save the Buffer */
420 Irp
->UserBuffer
= OutputBuffer
;
424 /* Clear the Flags and Buffer */
425 Irp
->UserBuffer
= NULL
;
428 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
430 /* Cleanup after exception and return */
431 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
432 _SEH2_YIELD(return _SEH2_GetExceptionCode());
438 case METHOD_IN_DIRECT
:
439 case METHOD_OUT_DIRECT
:
444 /* Check if we got an input buffer */
445 if ((InputBufferLength
) && (InputBuffer
))
447 /* Allocate the System Buffer */
448 Irp
->AssociatedIrp
.SystemBuffer
=
449 ExAllocatePoolWithTag(NonPagedPool
,
453 /* Copy into the System Buffer */
454 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
458 /* Write the flags */
459 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
462 /* Check if we got an output buffer */
465 /* Allocate the System Buffer */
466 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
471 if (!Irp
->MdlAddress
)
473 /* Raise exception we'll catch */
474 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
478 MmProbeAndLockPages(Irp
->MdlAddress
,
480 (AccessType
== METHOD_IN_DIRECT
) ?
481 IoReadAccess
: IoWriteAccess
);
484 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
486 /* Cleanup after exception and return */
487 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
488 _SEH2_YIELD(return _SEH2_GetExceptionCode());
495 /* Just save the Buffer */
496 Irp
->UserBuffer
= OutputBuffer
;
497 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
500 /* Use deferred completion for FS I/O */
501 Irp
->Flags
|= (!IsDevIoCtl
) ? IRP_DEFER_IO_COMPLETION
: 0;
503 /* Perform the call */
504 return IopPerformSynchronousRequest(DeviceObject
,
515 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject
,
516 IN ULONG InformationClass
,
518 OUT PVOID Information
,
519 OUT PULONG ReturnedLength
,
522 IO_STATUS_BLOCK IoStatusBlock
;
524 PDEVICE_OBJECT DeviceObject
;
525 PIO_STACK_LOCATION StackPtr
;
526 BOOLEAN LocalEvent
= FALSE
;
530 IOTRACE(IO_API_DEBUG
, "Handle: %p. CTL: %lx. Type: %lx \n",
531 FileObject
, InformationClass
, File
);
533 /* Reference the object */
534 ObReferenceObject(FileObject
);
536 /* Check if this is a file that was opened for Synch I/O */
537 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
540 IopLockFileObject(FileObject
);
542 /* Use File Object event */
543 KeClearEvent(&FileObject
->Event
);
547 /* Use local event */
548 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
552 /* Get the Device Object */
553 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
555 /* Allocate the IRP */
556 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
557 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
560 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
561 Irp
->RequestorMode
= KernelMode
;
562 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
563 Irp
->UserIosb
= &IoStatusBlock
;
564 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
565 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
566 Irp
->Flags
|= IRP_BUFFERED_IO
;
567 Irp
->AssociatedIrp
.SystemBuffer
= Information
;
568 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
570 /* Set the Stack Data */
571 StackPtr
= IoGetNextIrpStackLocation(Irp
);
572 StackPtr
->MajorFunction
= File
? IRP_MJ_QUERY_INFORMATION
:
573 IRP_MJ_QUERY_VOLUME_INFORMATION
;
574 StackPtr
->FileObject
= FileObject
;
576 /* Check which type this is */
580 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= InformationClass
;
581 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
586 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= InformationClass
;
587 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
591 IopQueueIrpToThread(Irp
);
593 /* Call the Driver */
594 Status
= IoCallDriver(DeviceObject
, Irp
);
596 /* Check if this was synch I/O */
599 /* Check if the requet is pending */
600 if (Status
== STATUS_PENDING
)
602 /* Wait on the file object */
603 Status
= KeWaitForSingleObject(&FileObject
->Event
,
607 FO_ALERTABLE_IO
) != 0,
609 if (Status
== STATUS_ALERTED
)
611 /* Abort the operation */
612 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
615 /* Get the final status */
616 Status
= FileObject
->FinalStatus
;
619 /* Release the file lock */
620 IopUnlockFileObject(FileObject
);
622 else if (Status
== STATUS_PENDING
)
624 /* Wait on the local event and get the final status */
625 KeWaitForSingleObject(&Event
,
630 Status
= IoStatusBlock
.Status
;
633 /* Return the Length and Status. ReturnedLength is NOT optional */
634 *ReturnedLength
= (ULONG
)IoStatusBlock
.Information
;
640 IopGetFileInformation(IN PFILE_OBJECT FileObject
,
642 IN FILE_INFORMATION_CLASS FileInfoClass
,
644 OUT PULONG ReturnedLength
)
649 PIO_STACK_LOCATION Stack
;
650 PDEVICE_OBJECT DeviceObject
;
651 IO_STATUS_BLOCK IoStatusBlock
;
655 /* Allocate an IRP */
656 ObReferenceObject(FileObject
);
657 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
658 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
661 ObDereferenceObject(FileObject
);
662 return STATUS_INSUFFICIENT_RESOURCES
;
666 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
669 Irp
->UserIosb
= &IoStatusBlock
;
670 Irp
->UserEvent
= &Event
;
671 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
672 Irp
->RequestorMode
= KernelMode
;
673 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
674 Irp
->Flags
= IRP_SYNCHRONOUS_API
| IRP_BUFFERED_IO
| IRP_OB_QUERY_NAME
;
675 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
676 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
678 Stack
= IoGetNextIrpStackLocation(Irp
);
679 Stack
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
680 Stack
->FileObject
= FileObject
;
681 Stack
->Parameters
.QueryFile
.FileInformationClass
= FileInfoClass
;
682 Stack
->Parameters
.QueryFile
.Length
= Length
;
686 IopQueueIrpToThread(Irp
);
688 /* Call the driver */
689 Status
= IoCallDriver(DeviceObject
, Irp
);
690 if (Status
== STATUS_PENDING
)
692 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
693 Status
= IoStatusBlock
.Status
;
696 *ReturnedLength
= IoStatusBlock
.Information
;
702 IopGetBasicInformationFile(IN PFILE_OBJECT FileObject
,
703 OUT PFILE_BASIC_INFORMATION BasicInfo
)
705 ULONG ReturnedLength
;
706 PDEVICE_OBJECT DeviceObject
;
707 IO_STATUS_BLOCK IoStatusBlock
;
711 /* Try to do it the fast way if possible */
712 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
713 if (DeviceObject
->DriverObject
->FastIoDispatch
!= NULL
&&
714 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
&&
715 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo(FileObject
,
716 ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) != 0),
721 return IoStatusBlock
.Status
;
724 /* In case it failed, fall back to IRP-based method */
725 return IopGetFileInformation(FileObject
, sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
, BasicInfo
, &ReturnedLength
);
730 IopOpenLinkOrRenameTarget(OUT PHANDLE Handle
,
732 IN PFILE_RENAME_INFORMATION RenameInfo
,
733 IN PFILE_OBJECT FileObject
)
737 UNICODE_STRING FileName
;
738 PIO_STACK_LOCATION Stack
;
739 PFILE_OBJECT TargetFileObject
;
740 IO_STATUS_BLOCK IoStatusBlock
;
741 FILE_BASIC_INFORMATION BasicInfo
;
742 OBJECT_ATTRIBUTES ObjectAttributes
;
743 OBJECT_HANDLE_INFORMATION HandleInformation
;
744 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
748 /* First, establish whether our target is a directory */
749 if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
751 Status
= IopGetBasicInformationFile(FileObject
, &BasicInfo
);
752 if (!NT_SUCCESS(Status
))
757 if (BasicInfo
.FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
758 DesiredAccess
= FILE_ADD_SUBDIRECTORY
;
762 /* Setup the string to the target */
763 FileName
.Buffer
= RenameInfo
->FileName
;
764 FileName
.Length
= RenameInfo
->FileNameLength
;
765 FileName
.MaximumLength
= RenameInfo
->FileNameLength
;
767 InitializeObjectAttributes(&ObjectAttributes
,
769 (FileObject
->Flags
& FO_OPENED_CASE_SENSITIVE
? 0 : OBJ_CASE_INSENSITIVE
) | OBJ_KERNEL_HANDLE
,
770 RenameInfo
->RootDirectory
,
773 /* And open its parent directory */
774 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
776 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
778 /* Commented out - we don't support FO extension yet
779 * FIXME: Corrected last arg when it's supported
781 Status
= IoCreateFileSpecifyDeviceObjectHint(&TargetHandle
,
782 DesiredAccess
| SYNCHRONIZE
,
787 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
789 FILE_OPEN_FOR_BACKUP_INTENT
,
794 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
,
795 FileObject
->DeviceObject
);
799 return STATUS_NOT_IMPLEMENTED
;
804 Status
= IoCreateFile(&TargetHandle
,
805 DesiredAccess
| SYNCHRONIZE
,
810 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
812 FILE_OPEN_FOR_BACKUP_INTENT
,
817 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
);
820 if (!NT_SUCCESS(Status
))
825 /* Once open, continue only if:
826 * Target exists and we're allowed to overwrite it
828 Stack
= IoGetNextIrpStackLocation(Irp
);
829 if (Stack
->Parameters
.SetFile
.FileInformationClass
== FileLinkInformation
&&
830 !RenameInfo
->ReplaceIfExists
&&
831 IoStatusBlock
.Information
== FILE_EXISTS
)
833 ObCloseHandle(TargetHandle
, KernelMode
);
834 return STATUS_OBJECT_NAME_COLLISION
;
837 /* Now, we'll get the associated device of the target, to check for same device location
838 * So, get the FO first
840 Status
= ObReferenceObjectByHandle(TargetHandle
,
844 (PVOID
*)&TargetFileObject
,
846 if (!NT_SUCCESS(Status
))
848 ObCloseHandle(TargetHandle
, KernelMode
);
852 /* We can dereference, we have the handle */
853 ObDereferenceObject(TargetFileObject
);
854 /* If we're not on the same device, error out **/
855 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
857 ObCloseHandle(TargetHandle
, KernelMode
);
858 return STATUS_NOT_SAME_DEVICE
;
861 /* Return parent directory file object and handle */
862 Stack
->Parameters
.SetFile
.FileObject
= TargetFileObject
;
863 *Handle
= TargetHandle
;
865 return STATUS_SUCCESS
;
868 /* PUBLIC FUNCTIONS **********************************************************/
875 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
877 IN PLARGE_INTEGER Offset
,
879 IN PIO_STATUS_BLOCK StatusBlock
)
882 PIO_STACK_LOCATION StackPtr
;
883 PDEVICE_OBJECT DeviceObject
;
884 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
885 FileObject
, Mdl
, Offset
);
887 /* Get the Device Object */
888 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
891 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
892 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
895 StackPtr
= IoGetNextIrpStackLocation(Irp
);
897 /* Create the IRP Settings */
898 Irp
->MdlAddress
= Mdl
;
899 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
900 Irp
->UserIosb
= StatusBlock
;
901 Irp
->UserEvent
= Event
;
902 Irp
->RequestorMode
= KernelMode
;
903 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
904 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
905 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
907 /* Set the Stack Settings */
908 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
909 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
910 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
911 StackPtr
->FileObject
= FileObject
;
913 /* Call the Driver */
914 return IoCallDriver(DeviceObject
, Irp
);
922 IoPageRead(IN PFILE_OBJECT FileObject
,
924 IN PLARGE_INTEGER Offset
,
926 IN PIO_STATUS_BLOCK StatusBlock
)
929 PIO_STACK_LOCATION StackPtr
;
930 PDEVICE_OBJECT DeviceObject
;
931 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
932 FileObject
, Mdl
, Offset
);
934 /* Get the Device Object */
935 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
938 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
939 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
942 StackPtr
= IoGetNextIrpStackLocation(Irp
);
944 /* Create the IRP Settings */
945 Irp
->MdlAddress
= Mdl
;
946 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
947 Irp
->UserIosb
= StatusBlock
;
948 Irp
->UserEvent
= Event
;
949 Irp
->RequestorMode
= KernelMode
;
950 Irp
->Flags
= IRP_PAGING_IO
|
952 IRP_SYNCHRONOUS_PAGING_IO
|
954 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
955 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
957 /* Set the Stack Settings */
958 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
959 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
960 StackPtr
->MajorFunction
= IRP_MJ_READ
;
961 StackPtr
->FileObject
= FileObject
;
963 /* Call the Driver */
964 return IoCallDriver(DeviceObject
, Irp
);
972 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
973 IN FILE_INFORMATION_CLASS FileInformationClass
,
975 OUT PVOID FileInformation
,
976 OUT PULONG ReturnedLength
)
978 /* Call the shared routine */
979 return IopQueryDeviceInformation(FileObject
,
980 FileInformationClass
,
992 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
993 IN FS_INFORMATION_CLASS FsInformationClass
,
995 OUT PVOID FsInformation
,
996 OUT PULONG ReturnedLength
)
998 /* Call the shared routine */
999 return IopQueryDeviceInformation(FileObject
,
1012 IoSetInformation(IN PFILE_OBJECT FileObject
,
1013 IN FILE_INFORMATION_CLASS FileInformationClass
,
1015 IN PVOID FileInformation
)
1017 IO_STATUS_BLOCK IoStatusBlock
;
1019 PDEVICE_OBJECT DeviceObject
;
1020 PIO_STACK_LOCATION StackPtr
;
1021 BOOLEAN LocalEvent
= FALSE
;
1025 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
1026 FileObject
, FileInformationClass
, Length
);
1028 /* Reference the object */
1029 ObReferenceObject(FileObject
);
1031 /* Check if this is a file that was opened for Synch I/O */
1032 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1035 IopLockFileObject(FileObject
);
1037 /* Use File Object event */
1038 KeClearEvent(&FileObject
->Event
);
1042 /* Use local event */
1043 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1047 /* Get the Device Object */
1048 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1050 /* Allocate the IRP */
1051 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1052 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1055 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1056 Irp
->RequestorMode
= KernelMode
;
1057 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1058 Irp
->UserIosb
= &IoStatusBlock
;
1059 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1060 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1061 Irp
->Flags
|= IRP_BUFFERED_IO
;
1062 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1063 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1065 /* Set the Stack Data */
1066 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1067 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
1068 StackPtr
->FileObject
= FileObject
;
1070 /* Set Parameters */
1071 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
1072 StackPtr
->Parameters
.SetFile
.Length
= Length
;
1075 IopQueueIrpToThread(Irp
);
1077 /* Call the Driver */
1078 Status
= IoCallDriver(DeviceObject
, Irp
);
1080 /* Check if this was synch I/O */
1083 /* Check if the requet is pending */
1084 if (Status
== STATUS_PENDING
)
1086 /* Wait on the file object */
1087 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1090 (FileObject
->Flags
&
1091 FO_ALERTABLE_IO
) != 0,
1093 if (Status
== STATUS_ALERTED
)
1095 /* Abort the operation */
1096 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1099 /* Get the final status */
1100 Status
= FileObject
->FinalStatus
;
1103 /* Release the file lock */
1104 IopUnlockFileObject(FileObject
);
1106 else if (Status
== STATUS_PENDING
)
1108 /* Wait on the local event and get the final status */
1109 KeWaitForSingleObject(&Event
,
1114 Status
= IoStatusBlock
.Status
;
1117 /* Return the status */
1121 /* NATIVE SERVICES ***********************************************************/
1128 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1129 IN HANDLE Event OPTIONAL
,
1130 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1131 IN PVOID UserApcContext OPTIONAL
,
1132 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1133 IN ULONG IoControlCode
,
1134 IN PVOID InputBuffer
,
1135 IN ULONG InputBufferLength OPTIONAL
,
1136 OUT PVOID OutputBuffer
,
1137 IN ULONG OutputBufferLength OPTIONAL
)
1139 /* Call the Generic Function */
1140 return IopDeviceFsIoControl(DeviceHandle
,
1158 NtFsControlFile(IN HANDLE DeviceHandle
,
1159 IN HANDLE Event OPTIONAL
,
1160 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1161 IN PVOID UserApcContext OPTIONAL
,
1162 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1163 IN ULONG IoControlCode
,
1164 IN PVOID InputBuffer
,
1165 IN ULONG InputBufferLength OPTIONAL
,
1166 OUT PVOID OutputBuffer
,
1167 IN ULONG OutputBufferLength OPTIONAL
)
1169 /* Call the Generic Function */
1170 return IopDeviceFsIoControl(DeviceHandle
,
1185 NtFlushBuffersFile(IN HANDLE FileHandle
,
1186 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1188 PFILE_OBJECT FileObject
;
1190 PIO_STACK_LOCATION StackPtr
;
1192 PDEVICE_OBJECT DeviceObject
;
1193 PKEVENT Event
= NULL
;
1194 BOOLEAN LocalEvent
= FALSE
;
1195 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1196 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1197 IO_STATUS_BLOCK KernelIosb
;
1199 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1201 if (PreviousMode
!= KernelMode
)
1203 /* Protect probes */
1206 /* Probe the I/O Status block */
1207 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1209 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1211 /* Return the exception code */
1212 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1217 /* Get the File Object */
1218 Status
= ObReferenceObjectByHandle(FileHandle
,
1222 (PVOID
*)&FileObject
,
1224 if (!NT_SUCCESS(Status
)) return Status
;
1227 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1228 * granted. However, if this is a named pipe, make sure we don't ask for
1229 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1232 if (!(ObjectHandleInfo
.GrantedAccess
&
1233 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1237 ObDereferenceObject(FileObject
);
1238 return STATUS_ACCESS_DENIED
;
1241 /* Check if we should use Sync IO or not */
1242 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1245 IopLockFileObject(FileObject
);
1249 /* Use local event */
1250 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1254 ObDereferenceObject(FileObject
);
1255 return STATUS_INSUFFICIENT_RESOURCES
;
1257 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1261 /* Get the Device Object */
1262 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1264 /* Clear the event */
1265 KeClearEvent(&FileObject
->Event
);
1267 /* Allocate the IRP */
1268 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1269 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1271 /* Set up the IRP */
1272 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1273 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1274 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1275 Irp
->RequestorMode
= PreviousMode
;
1276 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1277 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1278 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1280 /* Set up Stack Data */
1281 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1282 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1283 StackPtr
->FileObject
= FileObject
;
1285 /* Call the Driver */
1286 Status
= IopPerformSynchronousRequest(DeviceObject
,
1294 /* Check if this was async I/O */
1297 /* It was, finalize this request */
1298 Status
= IopFinalizeAsynchronousIo(Status
,
1306 /* Return the Status */
1315 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1316 IN HANDLE EventHandle OPTIONAL
,
1317 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1318 IN PVOID ApcContext OPTIONAL
,
1319 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1321 IN ULONG BufferSize
,
1322 IN ULONG CompletionFilter
,
1323 IN BOOLEAN WatchTree
)
1326 PKEVENT Event
= NULL
;
1327 PDEVICE_OBJECT DeviceObject
;
1328 PFILE_OBJECT FileObject
;
1329 PIO_STACK_LOCATION IoStack
;
1330 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1332 BOOLEAN LockedForSync
= FALSE
;
1334 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1336 /* Check if we're called from user mode */
1337 if (PreviousMode
!= KernelMode
)
1339 /* Enter SEH for probing */
1342 /* Probe the I/O STatus block */
1343 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1345 /* Probe the buffer */
1346 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1348 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1350 /* Return the exception code */
1351 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1355 /* Check if CompletionFilter is valid */
1356 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1358 return STATUS_INVALID_PARAMETER
;
1362 /* Get File Object */
1363 Status
= ObReferenceObjectByHandle(FileHandle
,
1364 FILE_LIST_DIRECTORY
,
1367 (PVOID
*)&FileObject
,
1369 if (!NT_SUCCESS(Status
)) return Status
;
1371 /* Check if we have an event handle */
1375 Status
= ObReferenceObjectByHandle(EventHandle
,
1381 if (Status
!= STATUS_SUCCESS
)
1383 ObDereferenceObject(FileObject
);
1386 KeClearEvent(Event
);
1389 /* Check if we should use Sync IO or not */
1390 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1393 IopLockFileObject(FileObject
);
1394 LockedForSync
= TRUE
;
1397 /* Clear File Object event */
1398 KeClearEvent(&FileObject
->Event
);
1400 /* Get the device object */
1401 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1403 /* Allocate the IRP */
1404 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1405 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1407 /* Set up the IRP */
1408 Irp
->RequestorMode
= PreviousMode
;
1409 Irp
->UserIosb
= IoStatusBlock
;
1410 Irp
->UserEvent
= Event
;
1411 Irp
->UserBuffer
= Buffer
;
1412 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1413 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1414 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1415 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1417 /* Set up Stack Data */
1418 IoStack
= IoGetNextIrpStackLocation(Irp
);
1419 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1420 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1421 IoStack
->FileObject
= FileObject
;
1423 /* Set parameters */
1424 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1425 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1426 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1428 /* Perform the call */
1429 return IopPerformSynchronousRequest(DeviceObject
,
1443 NtLockFile(IN HANDLE FileHandle
,
1444 IN HANDLE EventHandle OPTIONAL
,
1445 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1446 IN PVOID ApcContext OPTIONAL
,
1447 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1448 IN PLARGE_INTEGER ByteOffset
,
1449 IN PLARGE_INTEGER Length
,
1451 IN BOOLEAN FailImmediately
,
1452 IN BOOLEAN ExclusiveLock
)
1454 PFILE_OBJECT FileObject
;
1455 PLARGE_INTEGER LocalLength
= NULL
;
1457 PIO_STACK_LOCATION StackPtr
;
1458 PDEVICE_OBJECT DeviceObject
;
1459 PKEVENT Event
= NULL
;
1460 BOOLEAN LockedForSync
= FALSE
;
1461 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1462 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1464 OBJECT_HANDLE_INFORMATION HandleInformation
;
1466 CapturedByteOffset
.QuadPart
= 0;
1467 CapturedLength
.QuadPart
= 0;
1468 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1470 /* Get File Object */
1471 Status
= ObReferenceObjectByHandle(FileHandle
,
1475 (PVOID
*)&FileObject
,
1476 &HandleInformation
);
1477 if (!NT_SUCCESS(Status
)) return Status
;
1479 /* Check if we're called from user mode */
1480 if (PreviousMode
!= KernelMode
)
1482 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1483 if (!(HandleInformation
.GrantedAccess
&
1484 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1486 ObDereferenceObject(FileObject
);
1487 return STATUS_ACCESS_DENIED
;
1490 /* Enter SEH for probing */
1493 /* Probe the I/O STatus block */
1494 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1496 /* Probe and capture the large integers */
1497 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1498 CapturedLength
= ProbeForReadLargeInteger(Length
);
1500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1502 /* Dereference the object and return exception code */
1503 ObDereferenceObject(FileObject
);
1504 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1510 /* Otherwise, capture them directly */
1511 CapturedByteOffset
= *ByteOffset
;
1512 CapturedLength
= *Length
;
1515 /* Check if we have an event handle */
1519 Status
= ObReferenceObjectByHandle(EventHandle
,
1525 if (Status
!= STATUS_SUCCESS
) return Status
;
1526 KeClearEvent(Event
);
1529 /* Get the device object */
1530 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1532 /* Check if we should use Sync IO or not */
1533 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1536 IopLockFileObject(FileObject
);
1537 LockedForSync
= TRUE
;
1540 /* Clear File Object event */
1541 KeClearEvent(&FileObject
->Event
);
1542 FileObject
->LockOperation
= TRUE
;
1544 /* Allocate the IRP */
1545 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1546 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1548 /* Set up the IRP */
1549 Irp
->RequestorMode
= PreviousMode
;
1550 Irp
->UserIosb
= IoStatusBlock
;
1551 Irp
->UserEvent
= Event
;
1552 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1553 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1554 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1555 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1557 /* Set up Stack Data */
1558 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1559 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1560 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1561 StackPtr
->FileObject
= FileObject
;
1563 /* Allocate local buffer */
1564 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1565 sizeof(LARGE_INTEGER
),
1569 /* Allocating failed, clean up and return failure */
1570 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1571 return STATUS_INSUFFICIENT_RESOURCES
;
1574 /* Set the length */
1575 *LocalLength
= CapturedLength
;
1576 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1577 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1579 /* Set Parameters */
1580 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1581 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1584 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1585 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1587 /* Perform the call */
1588 return IopPerformSynchronousRequest(DeviceObject
,
1602 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1603 IN HANDLE EventHandle OPTIONAL
,
1604 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1605 IN PVOID ApcContext OPTIONAL
,
1606 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1607 OUT PVOID FileInformation
,
1609 IN FILE_INFORMATION_CLASS FileInformationClass
,
1610 IN BOOLEAN ReturnSingleEntry
,
1611 IN PUNICODE_STRING FileName OPTIONAL
,
1612 IN BOOLEAN RestartScan
)
1615 PDEVICE_OBJECT DeviceObject
;
1616 PFILE_OBJECT FileObject
;
1617 PIO_STACK_LOCATION StackPtr
;
1618 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1620 BOOLEAN LockedForSynch
= FALSE
;
1621 PKEVENT Event
= NULL
;
1622 volatile PVOID AuxBuffer
= NULL
;
1624 UNICODE_STRING CapturedFileName
;
1625 PUNICODE_STRING SearchPattern
;
1627 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1629 /* Check if we came from user mode */
1630 if (PreviousMode
!= KernelMode
)
1632 /* Enter SEH for probing */
1635 /* Probe the I/O Status Block */
1636 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1638 /* Probe the file information */
1639 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1641 /* Check if we have a file name */
1645 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1646 if (CapturedFileName
.Length
)
1648 /* Probe its buffer */
1649 ProbeForRead(CapturedFileName
.Buffer
,
1650 CapturedFileName
.Length
,
1654 /* Allocate the auxiliary buffer */
1655 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1656 CapturedFileName
.Length
+
1657 sizeof(UNICODE_STRING
),
1659 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1660 sizeof(UNICODE_STRING
)),
1661 CapturedFileName
.Buffer
,
1662 CapturedFileName
.Length
);
1664 /* Setup the search pattern */
1665 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1666 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1667 sizeof(UNICODE_STRING
));
1668 SearchPattern
->Length
= CapturedFileName
.Length
;
1669 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1672 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1674 /* Free buffer and return the exception code */
1675 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1676 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1681 /* Get File Object */
1682 Status
= ObReferenceObjectByHandle(FileHandle
,
1683 FILE_LIST_DIRECTORY
,
1686 (PVOID
*)&FileObject
,
1688 if (!NT_SUCCESS(Status
))
1691 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1695 /* Check if we have an even handle */
1698 /* Get its pointer */
1699 Status
= ObReferenceObjectByHandle(EventHandle
,
1705 if (!NT_SUCCESS(Status
))
1708 ObDereferenceObject(FileObject
);
1713 KeClearEvent(Event
);
1716 /* Check if this is a file that was opened for Synch I/O */
1717 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1720 IopLockFileObject(FileObject
);
1722 /* Remember to unlock later */
1723 LockedForSynch
= TRUE
;
1726 /* Get the device object */
1727 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1729 /* Clear the File Object's event */
1730 KeClearEvent(&FileObject
->Event
);
1732 /* Allocate the IRP */
1733 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1734 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1736 /* Set up the IRP */
1737 Irp
->RequestorMode
= PreviousMode
;
1738 Irp
->UserIosb
= IoStatusBlock
;
1739 Irp
->UserEvent
= Event
;
1740 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1741 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1742 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1743 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1744 Irp
->MdlAddress
= NULL
;
1745 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1746 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1748 /* Check if this is buffered I/O */
1749 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1751 /* Allocate a buffer */
1752 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1755 if (!Irp
->AssociatedIrp
.SystemBuffer
)
1757 /* Allocating failed, clean up and return the exception code */
1758 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1759 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1761 /* Return the exception code */
1762 return STATUS_INSUFFICIENT_RESOURCES
;
1765 /* Set the buffer and flags */
1766 Irp
->UserBuffer
= FileInformation
;
1767 Irp
->Flags
= (IRP_BUFFERED_IO
|
1768 IRP_DEALLOCATE_BUFFER
|
1769 IRP_INPUT_OPERATION
);
1771 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1775 /* Allocate an MDL */
1776 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1777 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1778 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1780 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1782 /* Allocating failed, clean up and return the exception code */
1783 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1784 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1790 /* No allocation flags, and use the buffer directly */
1791 Irp
->UserBuffer
= FileInformation
;
1794 /* Set up Stack Data */
1795 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1796 StackPtr
->FileObject
= FileObject
;
1797 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1798 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1800 /* Set Parameters */
1801 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1802 FileInformationClass
;
1803 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1804 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1805 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1806 StackPtr
->Flags
= 0;
1807 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1808 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1810 /* Set deferred I/O */
1811 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1813 /* Perform the call */
1814 return IopPerformSynchronousRequest(DeviceObject
,
1828 NtQueryEaFile(IN HANDLE FileHandle
,
1829 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1832 IN BOOLEAN ReturnSingleEntry
,
1833 IN PVOID EaList OPTIONAL
,
1834 IN ULONG EaListLength
,
1835 IN PULONG EaIndex OPTIONAL
,
1836 IN BOOLEAN RestartScan
)
1839 return STATUS_NOT_IMPLEMENTED
;
1847 NtQueryInformationFile(IN HANDLE FileHandle
,
1848 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1849 IN PVOID FileInformation
,
1851 IN FILE_INFORMATION_CLASS FileInformationClass
)
1853 OBJECT_HANDLE_INFORMATION HandleInformation
;
1854 PFILE_OBJECT FileObject
;
1857 PDEVICE_OBJECT DeviceObject
;
1858 PIO_STACK_LOCATION StackPtr
;
1859 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1860 PKEVENT Event
= NULL
;
1861 BOOLEAN LocalEvent
= FALSE
;
1862 PKNORMAL_ROUTINE NormalRoutine
;
1863 PVOID NormalContext
;
1865 IO_STATUS_BLOCK KernelIosb
;
1867 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1869 /* Check if we're called from user mode */
1870 if (PreviousMode
!= KernelMode
)
1872 /* Validate the information class */
1873 if ((FileInformationClass
>= FileMaximumInformation
) ||
1874 !(IopQueryOperationLength
[FileInformationClass
]))
1877 return STATUS_INVALID_INFO_CLASS
;
1880 /* Validate the length */
1881 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1883 /* Invalid length */
1884 return STATUS_INFO_LENGTH_MISMATCH
;
1887 /* Enter SEH for probing */
1890 /* Probe the I/O Status block */
1891 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1893 /* Probe the information */
1894 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1896 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1898 /* Return the exception code */
1899 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1905 /* Validate the information class */
1906 if ((FileInformationClass
>= FileMaximumInformation
) ||
1907 !(IopQueryOperationLength
[FileInformationClass
]))
1910 return STATUS_INVALID_INFO_CLASS
;
1913 /* Validate the length */
1914 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1916 /* Invalid length */
1917 return STATUS_INFO_LENGTH_MISMATCH
;
1921 /* Reference the Handle */
1922 Status
= ObReferenceObjectByHandle(FileHandle
,
1923 IopQueryOperationAccess
1924 [FileInformationClass
],
1927 (PVOID
*)&FileObject
,
1928 &HandleInformation
);
1929 if (!NT_SUCCESS(Status
)) return Status
;
1931 /* Check if this is a direct open or not */
1932 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1934 /* Get the device object */
1935 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1939 /* Get the device object */
1940 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1943 /* Check if this is a file that was opened for Synch I/O */
1944 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1947 IopLockFileObject(FileObject
);
1949 /* Check if the caller just wants the position */
1950 if (FileInformationClass
== FilePositionInformation
)
1952 /* Protect write in SEH */
1955 /* Write the offset */
1956 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1957 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1959 /* Fill out the I/O Status Block */
1960 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1961 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1963 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1965 /* Get the exception code */
1966 Status
= _SEH2_GetExceptionCode();
1970 /* Release the file lock, dereference the file and return */
1971 IopUnlockFileObject(FileObject
);
1972 ObDereferenceObject(FileObject
);
1978 /* Use local event */
1979 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1982 ObDereferenceObject(FileObject
);
1983 return STATUS_INSUFFICIENT_RESOURCES
;
1985 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1989 /* Clear the File Object event */
1990 KeClearEvent(&FileObject
->Event
);
1992 /* Allocate the IRP */
1993 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1994 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1997 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1998 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1999 Irp
->RequestorMode
= PreviousMode
;
2000 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2001 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2002 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2003 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2004 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2005 Irp
->MdlAddress
= NULL
;
2006 Irp
->UserBuffer
= FileInformation
;
2008 /* Set the Stack Data */
2009 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2010 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2011 StackPtr
->FileObject
= FileObject
;
2016 /* Allocate a buffer */
2017 Irp
->AssociatedIrp
.SystemBuffer
=
2018 ExAllocatePoolWithTag(NonPagedPool
,
2022 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2024 /* Allocating failed, clean up and return the exception code */
2025 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2026 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2031 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2032 IRP_DEALLOCATE_BUFFER
|
2033 IRP_INPUT_OPERATION
|
2034 IRP_DEFER_IO_COMPLETION
);
2036 /* Set the Parameters */
2037 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2038 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2041 IopQueueIrpToThread(Irp
);
2043 /* Update operation counts */
2044 IopUpdateOperationCount(IopOtherTransfer
);
2046 /* Call the Driver */
2047 Status
= IoCallDriver(DeviceObject
, Irp
);
2048 if (Status
== STATUS_PENDING
)
2050 /* Check if this was async I/O */
2053 /* Then to a non-alertable wait */
2054 Status
= KeWaitForSingleObject(Event
,
2059 if (Status
== STATUS_USER_APC
)
2061 /* Abort the request */
2062 IopAbortInterruptedIrp(Event
, Irp
);
2065 /* Set the final status */
2066 Status
= KernelIosb
.Status
;
2068 /* Enter SEH to write the IOSB back */
2071 /* Write it back to the caller */
2072 *IoStatusBlock
= KernelIosb
;
2074 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2076 /* Get the exception code */
2077 Status
= _SEH2_GetExceptionCode();
2081 /* Free the event */
2082 ExFreePoolWithTag(Event
, TAG_IO
);
2086 /* Wait for the IRP */
2087 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2090 (FileObject
->Flags
&
2091 FO_ALERTABLE_IO
) != 0,
2093 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2095 /* Abort the request */
2096 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2099 /* Set the final status */
2100 Status
= FileObject
->FinalStatus
;
2102 /* Release the file lock */
2103 IopUnlockFileObject(FileObject
);
2108 /* Free the event if we had one */
2111 /* Clear it in the IRP for completion */
2112 Irp
->UserEvent
= NULL
;
2113 ExFreePoolWithTag(Event
, TAG_IO
);
2116 /* Set the caller IOSB */
2117 Irp
->UserIosb
= IoStatusBlock
;
2119 /* The IRP wasn't completed, complete it ourselves */
2120 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2121 IopCompleteRequest(&Irp
->Tail
.Apc
,
2124 (PVOID
*)&FileObject
,
2126 KeLowerIrql(OldIrql
);
2128 /* Release the file object if we had locked it*/
2129 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2132 /* Return the Status */
2141 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2142 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2145 IN BOOLEAN ReturnSingleEntry
,
2146 IN PVOID SidList OPTIONAL
,
2147 IN ULONG SidListLength
,
2148 IN PSID StartSid OPTIONAL
,
2149 IN BOOLEAN RestartScan
)
2152 return STATUS_NOT_IMPLEMENTED
;
2160 NtReadFile(IN HANDLE FileHandle
,
2161 IN HANDLE Event OPTIONAL
,
2162 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2163 IN PVOID ApcContext OPTIONAL
,
2164 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2167 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2168 IN PULONG Key OPTIONAL
)
2171 PFILE_OBJECT FileObject
;
2173 PDEVICE_OBJECT DeviceObject
;
2174 PIO_STACK_LOCATION StackPtr
;
2175 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2176 PKEVENT EventObject
= NULL
;
2177 LARGE_INTEGER CapturedByteOffset
;
2178 ULONG CapturedKey
= 0;
2179 BOOLEAN Synchronous
= FALSE
;
2182 CapturedByteOffset
.QuadPart
= 0;
2183 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2185 /* Validate User-Mode Buffers */
2186 if (PreviousMode
!= KernelMode
)
2190 /* Probe the status block */
2191 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2193 /* Probe the read buffer */
2194 ProbeForWrite(Buffer
, Length
, 1);
2196 /* Check if we got a byte offset */
2199 /* Capture and probe it */
2200 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2203 /* Capture and probe the key */
2204 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2206 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2208 /* Return the exception code */
2209 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2215 /* Kernel mode: capture directly */
2216 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2217 if (Key
) CapturedKey
= *Key
;
2220 /* Get File Object */
2221 Status
= ObReferenceObjectByHandle(FileHandle
,
2225 (PVOID
*)&FileObject
,
2227 if (!NT_SUCCESS(Status
)) return Status
;
2229 /* Check for event */
2233 Status
= ObReferenceObjectByHandle(Event
,
2237 (PVOID
*)&EventObject
,
2239 if (!NT_SUCCESS(Status
))
2242 ObDereferenceObject(FileObject
);
2246 /* Otherwise reset the event */
2247 KeClearEvent(EventObject
);
2250 /* Check if we should use Sync IO or not */
2251 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2253 /* Lock the file object */
2254 IopLockFileObject(FileObject
);
2256 /* Check if we don't have a byte offset avilable */
2257 if (!(ByteOffset
) ||
2258 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2259 (CapturedByteOffset
.u
.HighPart
== -1)))
2261 /* Use the Current Byte Offset instead */
2262 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2265 /* Remember we are sync */
2268 else if (!(ByteOffset
) &&
2269 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2271 /* Otherwise, this was async I/O without a byte offset, so fail */
2272 if (EventObject
) ObDereferenceObject(EventObject
);
2273 ObDereferenceObject(FileObject
);
2274 return STATUS_INVALID_PARAMETER
;
2277 /* Get the device object */
2278 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2280 /* Clear the File Object's event */
2281 KeClearEvent(&FileObject
->Event
);
2283 /* Allocate the IRP */
2284 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2285 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2288 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2289 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2290 Irp
->RequestorMode
= PreviousMode
;
2291 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2292 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2293 Irp
->UserIosb
= IoStatusBlock
;
2294 Irp
->UserEvent
= EventObject
;
2295 Irp
->PendingReturned
= FALSE
;
2296 Irp
->Cancel
= FALSE
;
2297 Irp
->CancelRoutine
= NULL
;
2298 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2299 Irp
->MdlAddress
= NULL
;
2301 /* Set the Stack Data */
2302 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2303 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2304 StackPtr
->FileObject
= FileObject
;
2305 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2306 StackPtr
->Parameters
.Read
.Length
= Length
;
2307 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2309 /* Check if this is buffered I/O */
2310 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2312 /* Check if we have a buffer length */
2318 /* Allocate a buffer */
2319 Irp
->AssociatedIrp
.SystemBuffer
=
2320 ExAllocatePoolWithTag(NonPagedPool
,
2324 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2326 /* Allocating failed, clean up and return the exception code */
2327 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2328 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2332 /* Set the buffer and flags */
2333 Irp
->UserBuffer
= Buffer
;
2334 Irp
->Flags
= (IRP_BUFFERED_IO
|
2335 IRP_DEALLOCATE_BUFFER
|
2336 IRP_INPUT_OPERATION
);
2340 /* Not reading anything */
2341 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2344 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2346 /* Check if we have a buffer length */
2351 /* Allocate an MDL */
2352 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2354 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2355 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2357 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2359 /* Allocating failed, clean up and return the exception code */
2360 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2361 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2367 /* No allocation flags */
2372 /* No allocation flags, and use the buffer directly */
2374 Irp
->UserBuffer
= Buffer
;
2377 /* Now set the deferred read flags */
2378 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2380 /* FIXME: VFAT SUCKS */
2381 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2384 /* Perform the call */
2385 return IopPerformSynchronousRequest(DeviceObject
,
2399 NtReadFileScatter(IN HANDLE FileHandle
,
2400 IN HANDLE Event OPTIONAL
,
2401 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2402 IN PVOID UserApcContext OPTIONAL
,
2403 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2404 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2405 IN ULONG BufferLength
,
2406 IN PLARGE_INTEGER ByteOffset
,
2407 IN PULONG Key OPTIONAL
)
2410 return STATUS_NOT_IMPLEMENTED
;
2418 NtSetEaFile(IN HANDLE FileHandle
,
2419 IN PIO_STATUS_BLOCK IoStatusBlock
,
2421 IN ULONG EaBufferSize
)
2424 return STATUS_NOT_IMPLEMENTED
;
2432 NtSetInformationFile(IN HANDLE FileHandle
,
2433 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2434 IN PVOID FileInformation
,
2436 IN FILE_INFORMATION_CLASS FileInformationClass
)
2438 PFILE_OBJECT FileObject
;
2441 PDEVICE_OBJECT DeviceObject
;
2442 PIO_STACK_LOCATION StackPtr
;
2443 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2444 PKEVENT Event
= NULL
;
2445 BOOLEAN LocalEvent
= FALSE
;
2446 PKNORMAL_ROUTINE NormalRoutine
;
2447 PVOID NormalContext
;
2449 IO_STATUS_BLOCK KernelIosb
;
2451 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2452 PIO_COMPLETION_CONTEXT Context
;
2453 PFILE_RENAME_INFORMATION RenameInfo
;
2454 HANDLE TargetHandle
= NULL
;
2456 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2458 /* Check if we're called from user mode */
2459 if (PreviousMode
!= KernelMode
)
2461 /* Validate the information class */
2462 if ((FileInformationClass
>= FileMaximumInformation
) ||
2463 !(IopSetOperationLength
[FileInformationClass
]))
2466 return STATUS_INVALID_INFO_CLASS
;
2469 /* Validate the length */
2470 if (Length
< IopSetOperationLength
[FileInformationClass
])
2472 /* Invalid length */
2473 return STATUS_INFO_LENGTH_MISMATCH
;
2476 /* Enter SEH for probing */
2479 /* Probe the I/O Status block */
2480 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2482 /* Probe the information */
2483 ProbeForRead(FileInformation
,
2485 (Length
== sizeof(BOOLEAN
)) ?
2486 sizeof(BOOLEAN
) : sizeof(ULONG
));
2488 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2490 /* Return the exception code */
2491 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2497 /* Validate the information class */
2498 if ((FileInformationClass
>= FileMaximumInformation
) ||
2499 !(IopSetOperationLength
[FileInformationClass
]))
2502 return STATUS_INVALID_INFO_CLASS
;
2505 /* Validate the length */
2506 if (Length
< IopSetOperationLength
[FileInformationClass
])
2508 /* Invalid length */
2509 return STATUS_INFO_LENGTH_MISMATCH
;
2513 /* Reference the Handle */
2514 Status
= ObReferenceObjectByHandle(FileHandle
,
2515 IopSetOperationAccess
2516 [FileInformationClass
],
2519 (PVOID
*)&FileObject
,
2521 if (!NT_SUCCESS(Status
)) return Status
;
2523 /* Check if this is a direct open or not */
2524 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2526 /* Get the device object */
2527 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2531 /* Get the device object */
2532 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2535 /* Check if this is a file that was opened for Synch I/O */
2536 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2539 IopLockFileObject(FileObject
);
2541 /* Check if the caller just wants the position */
2542 if (FileInformationClass
== FilePositionInformation
)
2544 /* Protect write in SEH */
2547 /* Write the offset */
2548 FileObject
->CurrentByteOffset
=
2549 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2552 /* Fill out the I/O Status Block */
2553 IoStatusBlock
->Information
= 0;
2554 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2556 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2558 /* Get the exception code */
2559 Status
= _SEH2_GetExceptionCode();
2563 /* Update transfer count */
2564 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2566 /* Release the file lock, dereference the file and return */
2567 IopUnlockFileObject(FileObject
);
2568 ObDereferenceObject(FileObject
);
2574 /* Use local event */
2575 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2578 ObDereferenceObject(FileObject
);
2579 return STATUS_INSUFFICIENT_RESOURCES
;
2582 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2586 /* Clear the File Object event */
2587 KeClearEvent(&FileObject
->Event
);
2589 /* Allocate the IRP */
2590 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2591 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2594 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2595 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2596 Irp
->RequestorMode
= PreviousMode
;
2597 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2598 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2599 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2600 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2601 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2602 Irp
->MdlAddress
= NULL
;
2603 Irp
->UserBuffer
= FileInformation
;
2605 /* Set the Stack Data */
2606 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2607 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2608 StackPtr
->FileObject
= FileObject
;
2613 /* Allocate a buffer */
2614 Irp
->AssociatedIrp
.SystemBuffer
=
2615 ExAllocatePoolWithTag(NonPagedPool
,
2619 /* Copy the data into it */
2620 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2626 /* Allocating failed, clean up and return the exception code */
2627 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2628 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2633 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2634 IRP_DEALLOCATE_BUFFER
|
2635 IRP_DEFER_IO_COMPLETION
);
2637 /* Set the Parameters */
2638 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2639 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2642 IopQueueIrpToThread(Irp
);
2644 /* Update operation counts */
2645 IopUpdateOperationCount(IopOtherTransfer
);
2647 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2648 /* Handle IO Completion Port quickly */
2649 if (FileInformationClass
== FileCompletionInformation
)
2651 /* Check if the file object already has a completion port */
2652 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2653 (FileObject
->CompletionContext
))
2656 Status
= STATUS_INVALID_PARAMETER
;
2660 /* Reference the Port */
2661 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2662 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2663 IO_COMPLETION_MODIFY_STATE
,
2668 if (NT_SUCCESS(Status
))
2670 /* Allocate the Context */
2671 Context
= ExAllocatePoolWithTag(PagedPool
,
2672 sizeof(IO_COMPLETION_CONTEXT
),
2677 Context
->Key
= CompletionInfo
->Key
;
2678 Context
->Port
= Queue
;
2679 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
2685 * Someone else set the completion port in the
2686 * meanwhile, so dereference the port and fail.
2688 ExFreePoolWithTag(Context
, IOC_TAG
);
2689 ObDereferenceObject(Queue
);
2690 Status
= STATUS_INVALID_PARAMETER
;
2695 /* Dereference the Port now */
2696 ObDereferenceObject(Queue
);
2697 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2702 /* Set the IRP Status */
2703 Irp
->IoStatus
.Status
= Status
;
2704 Irp
->IoStatus
.Information
= 0;
2706 else if (FileInformationClass
== FileRenameInformation
||
2707 FileInformationClass
== FileLinkInformation
||
2708 FileInformationClass
== FileMoveClusterInformation
)
2710 /* Get associated information */
2711 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2716 * -> sizes are valid
2718 if (RenameInfo
->FileNameLength
!= 0 &&
2719 !(RenameInfo
->FileNameLength
& 1) &&
2720 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
2722 /* Properly set information received */
2723 if (FileInformationClass
== FileMoveClusterInformation
)
2725 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
2729 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
2732 /* If we got fully path OR relative target, attempt a parent directory open */
2733 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
2735 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
2736 if (!NT_SUCCESS(Status
))
2738 Irp
->IoStatus
.Status
= Status
;
2742 /* Call the Driver */
2743 Status
= IoCallDriver(DeviceObject
, Irp
);
2748 /* Call the Driver */
2749 Status
= IoCallDriver(DeviceObject
, Irp
);
2754 Status
= STATUS_INVALID_PARAMETER
;
2755 Irp
->IoStatus
.Status
= Status
;
2760 /* Call the Driver */
2761 Status
= IoCallDriver(DeviceObject
, Irp
);
2764 /* Check if we're waiting for the IRP to complete */
2765 if (Status
== STATUS_PENDING
)
2767 /* Check if this was async I/O */
2770 /* Then to a non-alertable wait */
2771 Status
= KeWaitForSingleObject(Event
,
2776 if (Status
== STATUS_USER_APC
)
2778 /* Abort the request */
2779 IopAbortInterruptedIrp(Event
, Irp
);
2782 /* Set the final status */
2783 Status
= KernelIosb
.Status
;
2785 /* Enter SEH to write the IOSB back */
2788 /* Write it back to the caller */
2789 *IoStatusBlock
= KernelIosb
;
2791 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2793 /* Get the exception code */
2794 Status
= _SEH2_GetExceptionCode();
2798 /* Free the event */
2799 ExFreePoolWithTag(Event
, TAG_IO
);
2803 /* Wait for the IRP */
2804 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2807 (FileObject
->Flags
&
2808 FO_ALERTABLE_IO
) != 0,
2810 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2812 /* Abort the request */
2813 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2816 /* Set the final status */
2817 Status
= FileObject
->FinalStatus
;
2819 /* Release the file lock */
2820 IopUnlockFileObject(FileObject
);
2825 /* Free the event if we had one */
2828 /* Clear it in the IRP for completion */
2829 Irp
->UserEvent
= NULL
;
2830 ExFreePoolWithTag(Event
, TAG_IO
);
2833 /* Set the caller IOSB */
2834 Irp
->UserIosb
= IoStatusBlock
;
2836 /* The IRP wasn't completed, complete it ourselves */
2837 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2838 IopCompleteRequest(&Irp
->Tail
.Apc
,
2841 (PVOID
*)&FileObject
,
2843 KeLowerIrql(OldIrql
);
2845 /* Release the file object if we had locked it*/
2846 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2849 if (TargetHandle
!= NULL
)
2851 ObCloseHandle(TargetHandle
, KernelMode
);
2854 /* Return the Status */
2863 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2864 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2866 IN ULONG BufferLength
)
2869 return STATUS_NOT_IMPLEMENTED
;
2877 NtUnlockFile(IN HANDLE FileHandle
,
2878 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2879 IN PLARGE_INTEGER ByteOffset
,
2880 IN PLARGE_INTEGER Length
,
2881 IN ULONG Key OPTIONAL
)
2883 PFILE_OBJECT FileObject
;
2884 PLARGE_INTEGER LocalLength
= NULL
;
2886 PIO_STACK_LOCATION StackPtr
;
2887 PDEVICE_OBJECT DeviceObject
;
2888 PKEVENT Event
= NULL
;
2889 BOOLEAN LocalEvent
= FALSE
;
2890 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2891 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2893 OBJECT_HANDLE_INFORMATION HandleInformation
;
2894 IO_STATUS_BLOCK KernelIosb
;
2896 CapturedByteOffset
.QuadPart
= 0;
2897 CapturedLength
.QuadPart
= 0;
2898 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2900 /* Get File Object */
2901 Status
= ObReferenceObjectByHandle(FileHandle
,
2905 (PVOID
*)&FileObject
,
2906 &HandleInformation
);
2907 if (!NT_SUCCESS(Status
)) return Status
;
2909 /* Check if we're called from user mode */
2910 if (PreviousMode
!= KernelMode
)
2912 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2913 if (!(HandleInformation
.GrantedAccess
&
2914 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2916 ObDereferenceObject(FileObject
);
2917 return STATUS_ACCESS_DENIED
;
2920 /* Enter SEH for probing */
2923 /* Probe the I/O Status block */
2924 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2926 /* Probe and capture the large integers */
2927 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2928 CapturedLength
= ProbeForReadLargeInteger(Length
);
2930 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2932 /* Dereference the object and return exception code */
2933 ObDereferenceObject(FileObject
);
2934 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2940 /* Otherwise, capture them directly */
2941 CapturedByteOffset
= *ByteOffset
;
2942 CapturedLength
= *Length
;
2945 /* Check if this is a direct open or not */
2946 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2948 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2952 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2955 /* Check if we should use Sync IO or not */
2956 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2959 IopLockFileObject(FileObject
);
2963 /* Use local event */
2964 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2967 ObDereferenceObject(FileObject
);
2968 return STATUS_INSUFFICIENT_RESOURCES
;
2970 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2974 /* Clear File Object event */
2975 KeClearEvent(&FileObject
->Event
);
2977 /* Allocate the IRP */
2978 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2979 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2981 /* Set up the IRP */
2982 Irp
->RequestorMode
= PreviousMode
;
2983 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2984 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2985 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2986 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2987 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2988 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2990 /* Set up Stack Data */
2991 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2992 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2993 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2994 StackPtr
->FileObject
= FileObject
;
2999 /* Allocate a buffer */
3000 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3001 sizeof(LARGE_INTEGER
),
3004 /* Set the length */
3005 *LocalLength
= CapturedLength
;
3006 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3007 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3009 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3011 /* Allocating failed, clean up and return the exception code */
3012 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3013 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3015 /* Return the exception code */
3016 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3020 /* Set Parameters */
3021 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3022 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3024 /* Call the Driver */
3025 Status
= IopPerformSynchronousRequest(DeviceObject
,
3033 /* Check if this was async I/O */
3036 /* It was, finalize this request */
3037 Status
= IopFinalizeAsynchronousIo(Status
,
3054 NtWriteFile(IN HANDLE FileHandle
,
3055 IN HANDLE Event OPTIONAL
,
3056 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3057 IN PVOID ApcContext OPTIONAL
,
3058 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3061 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3062 IN PULONG Key OPTIONAL
)
3065 PFILE_OBJECT FileObject
;
3067 PDEVICE_OBJECT DeviceObject
;
3068 PIO_STACK_LOCATION StackPtr
;
3069 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3070 PKEVENT EventObject
= NULL
;
3071 LARGE_INTEGER CapturedByteOffset
;
3072 ULONG CapturedKey
= 0;
3073 BOOLEAN Synchronous
= FALSE
;
3075 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3077 CapturedByteOffset
.QuadPart
= 0;
3078 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3080 /* Get File Object */
3081 Status
= ObReferenceObjectByHandle(FileHandle
,
3085 (PVOID
*)&FileObject
,
3087 if (!NT_SUCCESS(Status
)) return Status
;
3089 /* Validate User-Mode Buffers */
3090 if (PreviousMode
!= KernelMode
)
3095 * Check if the handle has either FILE_WRITE_DATA or
3096 * FILE_APPEND_DATA granted. However, if this is a named pipe,
3097 * make sure we don't ask for FILE_APPEND_DATA as it interferes
3098 * with the FILE_CREATE_PIPE_INSTANCE access right!
3100 if (!(ObjectHandleInfo
.GrantedAccess
&
3101 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
3102 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
3105 ObDereferenceObject(FileObject
);
3106 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
3109 /* Probe the status block */
3110 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3112 /* Probe the read buffer */
3113 ProbeForRead(Buffer
, Length
, 1);
3115 /* Check if we got a byte offset */
3118 /* Capture and probe it */
3119 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3122 /* Capture and probe the key */
3123 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3125 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3127 /* Return the exception code */
3128 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3134 /* Kernel mode: capture directly */
3135 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3136 if (Key
) CapturedKey
= *Key
;
3139 /* Check if this is an append operation */
3140 if ((ObjectHandleInfo
.GrantedAccess
&
3141 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3143 /* Give the drivers something to understand */
3144 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3145 CapturedByteOffset
.u
.HighPart
= -1;
3148 /* Check for event */
3152 Status
= ObReferenceObjectByHandle(Event
,
3156 (PVOID
*)&EventObject
,
3158 if (!NT_SUCCESS(Status
))
3161 ObDereferenceObject(FileObject
);
3165 /* Otherwise reset the event */
3166 KeClearEvent(EventObject
);
3169 /* Check if we should use Sync IO or not */
3170 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3172 /* Lock the file object */
3173 IopLockFileObject(FileObject
);
3175 /* Check if we don't have a byte offset avilable */
3176 if (!(ByteOffset
) ||
3177 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3178 (CapturedByteOffset
.u
.HighPart
== -1)))
3180 /* Use the Current Byte Offset instead */
3181 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3184 /* Remember we are sync */
3187 else if (!(ByteOffset
) &&
3188 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3190 /* Otherwise, this was async I/O without a byte offset, so fail */
3191 if (EventObject
) ObDereferenceObject(EventObject
);
3192 ObDereferenceObject(FileObject
);
3193 return STATUS_INVALID_PARAMETER
;
3196 /* Get the device object */
3197 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3199 /* Clear the File Object's event */
3200 KeClearEvent(&FileObject
->Event
);
3202 /* Allocate the IRP */
3203 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3204 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
3207 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3208 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3209 Irp
->RequestorMode
= PreviousMode
;
3210 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3211 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3212 Irp
->UserIosb
= IoStatusBlock
;
3213 Irp
->UserEvent
= EventObject
;
3214 Irp
->PendingReturned
= FALSE
;
3215 Irp
->Cancel
= FALSE
;
3216 Irp
->CancelRoutine
= NULL
;
3217 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3218 Irp
->MdlAddress
= NULL
;
3220 /* Set the Stack Data */
3221 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3222 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3223 StackPtr
->FileObject
= FileObject
;
3224 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3225 SL_WRITE_THROUGH
: 0;
3226 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3227 StackPtr
->Parameters
.Write
.Length
= Length
;
3228 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3230 /* Check if this is buffered I/O */
3231 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3233 /* Check if we have a buffer length */
3239 /* Allocate a buffer */
3240 Irp
->AssociatedIrp
.SystemBuffer
=
3241 ExAllocatePoolWithTag(NonPagedPool
,
3245 /* Copy the data into it */
3246 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3248 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3250 /* Allocating failed, clean up and return the exception code */
3251 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3252 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3257 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3261 /* Not writing anything */
3262 Irp
->Flags
= IRP_BUFFERED_IO
;
3265 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3267 /* Check if we have a buffer length */
3272 /* Allocate an MDL */
3273 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3275 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3276 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3278 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3280 /* Allocating failed, clean up and return the exception code */
3281 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3282 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3287 /* No allocation flags */
3292 /* No allocation flags, and use the buffer directly */
3294 Irp
->UserBuffer
= Buffer
;
3297 /* Now set the deferred read flags */
3298 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3300 /* FIXME: VFAT SUCKS */
3301 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3304 /* Perform the call */
3305 return IopPerformSynchronousRequest(DeviceObject
,
3316 NtWriteFileGather(IN HANDLE FileHandle
,
3317 IN HANDLE Event OPTIONAL
,
3318 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3319 IN PVOID UserApcContext OPTIONAL
,
3320 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3321 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3322 IN ULONG BufferLength
,
3323 IN PLARGE_INTEGER ByteOffset
,
3324 IN PULONG Key OPTIONAL
)
3327 return STATUS_NOT_IMPLEMENTED
;
3335 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3336 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3337 OUT PVOID FsInformation
,
3339 IN FS_INFORMATION_CLASS FsInformationClass
)
3341 PFILE_OBJECT FileObject
;
3343 PIO_STACK_LOCATION StackPtr
;
3344 PDEVICE_OBJECT DeviceObject
;
3345 PKEVENT Event
= NULL
;
3346 BOOLEAN LocalEvent
= FALSE
;
3347 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3349 IO_STATUS_BLOCK KernelIosb
;
3351 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3353 /* Check if we're called from user mode */
3354 if (PreviousMode
!= KernelMode
)
3356 /* Validate the information class */
3357 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3358 !(IopQueryFsOperationLength
[FsInformationClass
]))
3361 return STATUS_INVALID_INFO_CLASS
;
3364 /* Validate the length */
3365 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3367 /* Invalid length */
3368 return STATUS_INFO_LENGTH_MISMATCH
;
3371 /* Enter SEH for probing */
3374 /* Probe the I/O Status block */
3375 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3377 /* Probe the information */
3378 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3380 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3382 /* Return the exception code */
3383 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3388 /* Get File Object */
3389 Status
= ObReferenceObjectByHandle(FileHandle
,
3390 IopQueryFsOperationAccess
3391 [FsInformationClass
],
3394 (PVOID
*)&FileObject
,
3396 if (!NT_SUCCESS(Status
)) return Status
;
3398 /* Check if we should use Sync IO or not */
3399 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3402 IopLockFileObject(FileObject
);
3406 /* Use local event */
3407 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3410 ObDereferenceObject(FileObject
);
3411 return STATUS_INSUFFICIENT_RESOURCES
;
3413 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3417 /* Get the device object */
3418 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3420 /* Clear File Object event */
3421 KeClearEvent(&FileObject
->Event
);
3423 /* Allocate the IRP */
3424 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3425 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3427 /* Set up the IRP */
3428 Irp
->RequestorMode
= PreviousMode
;
3429 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3430 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3431 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3432 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3433 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3434 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3435 Irp
->UserBuffer
= FsInformation
;
3436 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3437 Irp
->MdlAddress
= NULL
;
3439 /* Set up Stack Data */
3440 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3441 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3442 StackPtr
->FileObject
= FileObject
;
3447 /* Allocate a buffer */
3448 Irp
->AssociatedIrp
.SystemBuffer
=
3449 ExAllocatePoolWithTag(NonPagedPool
,
3453 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3455 /* Allocating failed, clean up and return the exception code */
3456 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3457 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3461 /* Set the flags for this buffered + deferred I/O */
3462 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3463 IRP_DEALLOCATE_BUFFER
|
3464 IRP_INPUT_OPERATION
|
3465 IRP_DEFER_IO_COMPLETION
);
3467 /* Set Parameters */
3468 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3469 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3471 /* Call the Driver */
3472 Status
= IopPerformSynchronousRequest(DeviceObject
,
3480 /* Check if this was async I/O */
3483 /* It was, finalize this request */
3484 Status
= IopFinalizeAsynchronousIo(Status
,
3501 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3502 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3503 IN PVOID FsInformation
,
3505 IN FS_INFORMATION_CLASS FsInformationClass
)
3507 PFILE_OBJECT FileObject
;
3509 PIO_STACK_LOCATION StackPtr
;
3510 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3511 PKEVENT Event
= NULL
;
3512 BOOLEAN LocalEvent
= FALSE
;
3513 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3515 IO_STATUS_BLOCK KernelIosb
;
3516 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3518 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3520 /* Check if we're called from user mode */
3521 if (PreviousMode
!= KernelMode
)
3523 /* Validate the information class */
3524 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3525 !(IopSetFsOperationLength
[FsInformationClass
]))
3528 return STATUS_INVALID_INFO_CLASS
;
3531 /* Validate the length */
3532 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3534 /* Invalid length */
3535 return STATUS_INFO_LENGTH_MISMATCH
;
3538 /* Enter SEH for probing */
3541 /* Probe the I/O Status block */
3542 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3544 /* Probe the information */
3545 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3547 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3549 /* Return the exception code */
3550 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3555 /* Get File Object */
3556 Status
= ObReferenceObjectByHandle(FileHandle
,
3557 IopSetFsOperationAccess
3558 [FsInformationClass
],
3561 (PVOID
*)&FileObject
,
3563 if (!NT_SUCCESS(Status
)) return Status
;
3565 /* Get target device for notification */
3566 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
3567 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
3569 /* Check if we should use Sync IO or not */
3570 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3573 IopLockFileObject(FileObject
);
3577 /* Use local event */
3578 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3581 ObDereferenceObject(FileObject
);
3582 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3583 return STATUS_INSUFFICIENT_RESOURCES
;
3585 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3589 /* Get the device object */
3590 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3592 /* Clear File Object event */
3593 KeClearEvent(&FileObject
->Event
);
3595 /* Allocate the IRP */
3596 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3599 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3600 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3603 /* Set up the IRP */
3604 Irp
->RequestorMode
= PreviousMode
;
3605 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3606 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3607 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3608 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3609 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3610 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3611 Irp
->UserBuffer
= FsInformation
;
3612 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3613 Irp
->MdlAddress
= NULL
;
3615 /* Set up Stack Data */
3616 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3617 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3618 StackPtr
->FileObject
= FileObject
;
3623 /* Allocate a buffer */
3624 Irp
->AssociatedIrp
.SystemBuffer
=
3625 ExAllocatePoolWithTag(NonPagedPool
,
3629 /* Copy the data into it */
3630 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3632 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3634 /* Allocating failed, clean up and return the exception code */
3635 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3636 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3637 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3641 /* Set the flags for this buffered + deferred I/O */
3642 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3644 /* Set Parameters */
3645 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3646 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3648 /* Call the Driver */
3649 Status
= IopPerformSynchronousRequest(DeviceObject
,
3657 /* Check if this was async I/O */
3660 /* It was, finalize this request */
3661 Status
= IopFinalizeAsynchronousIo(Status
,
3669 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
3671 /* Time to report change */
3672 NotificationStructure
.Version
= 1;
3673 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
3674 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
3675 NotificationStructure
.FileObject
= NULL
;
3676 NotificationStructure
.NameBufferOffset
= - 1;
3677 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
3689 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3692 return STATUS_NOT_IMPLEMENTED
;
3700 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3703 return STATUS_NOT_IMPLEMENTED
;