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
;
870 IopGetFileMode(IN PFILE_OBJECT FileObject
)
874 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
875 Mode
|= FILE_WRITE_THROUGH
;
877 if (FileObject
->Flags
& FO_SEQUENTIAL_ONLY
)
878 Mode
|= FILE_SEQUENTIAL_ONLY
;
880 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
)
881 Mode
|= FILE_NO_INTERMEDIATE_BUFFERING
;
883 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
885 if (FileObject
->Flags
& FO_ALERTABLE_IO
)
886 Mode
|= FILE_SYNCHRONOUS_IO_ALERT
;
888 Mode
|= FILE_SYNCHRONOUS_IO_NONALERT
;
891 if (FileObject
->Flags
& FO_DELETE_ON_CLOSE
)
892 Mode
|= FILE_DELETE_ON_CLOSE
;
897 /* PUBLIC FUNCTIONS **********************************************************/
904 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
906 IN PLARGE_INTEGER Offset
,
908 IN PIO_STATUS_BLOCK StatusBlock
)
911 PIO_STACK_LOCATION StackPtr
;
912 PDEVICE_OBJECT DeviceObject
;
913 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
914 FileObject
, Mdl
, Offset
);
916 /* Get the Device Object */
917 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
920 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
921 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
924 StackPtr
= IoGetNextIrpStackLocation(Irp
);
926 /* Create the IRP Settings */
927 Irp
->MdlAddress
= Mdl
;
928 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
929 Irp
->UserIosb
= StatusBlock
;
930 Irp
->UserEvent
= Event
;
931 Irp
->RequestorMode
= KernelMode
;
932 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
933 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
934 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
936 /* Set the Stack Settings */
937 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
938 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
939 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
940 StackPtr
->FileObject
= FileObject
;
942 /* Call the Driver */
943 return IoCallDriver(DeviceObject
, Irp
);
951 IoPageRead(IN PFILE_OBJECT FileObject
,
953 IN PLARGE_INTEGER Offset
,
955 IN PIO_STATUS_BLOCK StatusBlock
)
958 PIO_STACK_LOCATION StackPtr
;
959 PDEVICE_OBJECT DeviceObject
;
960 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
961 FileObject
, Mdl
, Offset
);
963 /* Get the Device Object */
964 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
967 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
968 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
971 StackPtr
= IoGetNextIrpStackLocation(Irp
);
973 /* Create the IRP Settings */
974 Irp
->MdlAddress
= Mdl
;
975 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
976 Irp
->UserIosb
= StatusBlock
;
977 Irp
->UserEvent
= Event
;
978 Irp
->RequestorMode
= KernelMode
;
979 Irp
->Flags
= IRP_PAGING_IO
|
981 IRP_SYNCHRONOUS_PAGING_IO
|
983 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
984 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
986 /* Set the Stack Settings */
987 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
988 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
989 StackPtr
->MajorFunction
= IRP_MJ_READ
;
990 StackPtr
->FileObject
= FileObject
;
992 /* Call the Driver */
993 return IoCallDriver(DeviceObject
, Irp
);
1001 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
1002 IN FILE_INFORMATION_CLASS FileInformationClass
,
1004 OUT PVOID FileInformation
,
1005 OUT PULONG ReturnedLength
)
1007 /* Call the shared routine */
1008 return IopQueryDeviceInformation(FileObject
,
1009 FileInformationClass
,
1021 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
1022 IN FS_INFORMATION_CLASS FsInformationClass
,
1024 OUT PVOID FsInformation
,
1025 OUT PULONG ReturnedLength
)
1027 /* Call the shared routine */
1028 return IopQueryDeviceInformation(FileObject
,
1041 IoSetInformation(IN PFILE_OBJECT FileObject
,
1042 IN FILE_INFORMATION_CLASS FileInformationClass
,
1044 IN PVOID FileInformation
)
1046 IO_STATUS_BLOCK IoStatusBlock
;
1048 PDEVICE_OBJECT DeviceObject
;
1049 PIO_STACK_LOCATION StackPtr
;
1050 BOOLEAN LocalEvent
= FALSE
;
1054 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
1055 FileObject
, FileInformationClass
, Length
);
1057 /* Reference the object */
1058 ObReferenceObject(FileObject
);
1060 /* Check if this is a file that was opened for Synch I/O */
1061 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1064 IopLockFileObject(FileObject
);
1066 /* Use File Object event */
1067 KeClearEvent(&FileObject
->Event
);
1071 /* Use local event */
1072 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1076 /* Get the Device Object */
1077 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1079 /* Allocate the IRP */
1080 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1081 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1084 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1085 Irp
->RequestorMode
= KernelMode
;
1086 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1087 Irp
->UserIosb
= &IoStatusBlock
;
1088 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1089 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1090 Irp
->Flags
|= IRP_BUFFERED_IO
;
1091 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1092 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1094 /* Set the Stack Data */
1095 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1096 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
1097 StackPtr
->FileObject
= FileObject
;
1099 /* Set Parameters */
1100 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
1101 StackPtr
->Parameters
.SetFile
.Length
= Length
;
1104 IopQueueIrpToThread(Irp
);
1106 /* Call the Driver */
1107 Status
= IoCallDriver(DeviceObject
, Irp
);
1109 /* Check if this was synch I/O */
1112 /* Check if the requet is pending */
1113 if (Status
== STATUS_PENDING
)
1115 /* Wait on the file object */
1116 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1119 (FileObject
->Flags
&
1120 FO_ALERTABLE_IO
) != 0,
1122 if (Status
== STATUS_ALERTED
)
1124 /* Abort the operation */
1125 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1128 /* Get the final status */
1129 Status
= FileObject
->FinalStatus
;
1132 /* Release the file lock */
1133 IopUnlockFileObject(FileObject
);
1135 else if (Status
== STATUS_PENDING
)
1137 /* Wait on the local event and get the final status */
1138 KeWaitForSingleObject(&Event
,
1143 Status
= IoStatusBlock
.Status
;
1146 /* Return the status */
1150 /* NATIVE SERVICES ***********************************************************/
1157 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1158 IN HANDLE Event OPTIONAL
,
1159 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1160 IN PVOID UserApcContext OPTIONAL
,
1161 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1162 IN ULONG IoControlCode
,
1163 IN PVOID InputBuffer
,
1164 IN ULONG InputBufferLength OPTIONAL
,
1165 OUT PVOID OutputBuffer
,
1166 IN ULONG OutputBufferLength OPTIONAL
)
1168 /* Call the Generic Function */
1169 return IopDeviceFsIoControl(DeviceHandle
,
1187 NtFsControlFile(IN HANDLE DeviceHandle
,
1188 IN HANDLE Event OPTIONAL
,
1189 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1190 IN PVOID UserApcContext OPTIONAL
,
1191 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1192 IN ULONG IoControlCode
,
1193 IN PVOID InputBuffer
,
1194 IN ULONG InputBufferLength OPTIONAL
,
1195 OUT PVOID OutputBuffer
,
1196 IN ULONG OutputBufferLength OPTIONAL
)
1198 /* Call the Generic Function */
1199 return IopDeviceFsIoControl(DeviceHandle
,
1214 NtFlushBuffersFile(IN HANDLE FileHandle
,
1215 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1217 PFILE_OBJECT FileObject
;
1219 PIO_STACK_LOCATION StackPtr
;
1221 PDEVICE_OBJECT DeviceObject
;
1222 PKEVENT Event
= NULL
;
1223 BOOLEAN LocalEvent
= FALSE
;
1224 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1225 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1226 IO_STATUS_BLOCK KernelIosb
;
1228 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1230 if (PreviousMode
!= KernelMode
)
1232 /* Protect probes */
1235 /* Probe the I/O Status block */
1236 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1238 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1240 /* Return the exception code */
1241 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1246 /* Get the File Object */
1247 Status
= ObReferenceObjectByHandle(FileHandle
,
1251 (PVOID
*)&FileObject
,
1253 if (!NT_SUCCESS(Status
)) return Status
;
1256 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1257 * granted. However, if this is a named pipe, make sure we don't ask for
1258 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1261 if (!(ObjectHandleInfo
.GrantedAccess
&
1262 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1266 ObDereferenceObject(FileObject
);
1267 return STATUS_ACCESS_DENIED
;
1270 /* Check if we should use Sync IO or not */
1271 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1274 IopLockFileObject(FileObject
);
1278 /* Use local event */
1279 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1283 ObDereferenceObject(FileObject
);
1284 return STATUS_INSUFFICIENT_RESOURCES
;
1286 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1290 /* Get the Device Object */
1291 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1293 /* Clear the event */
1294 KeClearEvent(&FileObject
->Event
);
1296 /* Allocate the IRP */
1297 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1298 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1300 /* Set up the IRP */
1301 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1302 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1303 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1304 Irp
->RequestorMode
= PreviousMode
;
1305 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1306 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1307 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1309 /* Set up Stack Data */
1310 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1311 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1312 StackPtr
->FileObject
= FileObject
;
1314 /* Call the Driver */
1315 Status
= IopPerformSynchronousRequest(DeviceObject
,
1323 /* Check if this was async I/O */
1326 /* It was, finalize this request */
1327 Status
= IopFinalizeAsynchronousIo(Status
,
1335 /* Return the Status */
1344 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1345 IN HANDLE EventHandle OPTIONAL
,
1346 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1347 IN PVOID ApcContext OPTIONAL
,
1348 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1350 IN ULONG BufferSize
,
1351 IN ULONG CompletionFilter
,
1352 IN BOOLEAN WatchTree
)
1355 PKEVENT Event
= NULL
;
1356 PDEVICE_OBJECT DeviceObject
;
1357 PFILE_OBJECT FileObject
;
1358 PIO_STACK_LOCATION IoStack
;
1359 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1361 BOOLEAN LockedForSync
= FALSE
;
1363 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1365 /* Check if we're called from user mode */
1366 if (PreviousMode
!= KernelMode
)
1368 /* Enter SEH for probing */
1371 /* Probe the I/O STatus block */
1372 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1374 /* Probe the buffer */
1375 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1377 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1379 /* Return the exception code */
1380 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1384 /* Check if CompletionFilter is valid */
1385 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1387 return STATUS_INVALID_PARAMETER
;
1391 /* Get File Object */
1392 Status
= ObReferenceObjectByHandle(FileHandle
,
1393 FILE_LIST_DIRECTORY
,
1396 (PVOID
*)&FileObject
,
1398 if (!NT_SUCCESS(Status
)) return Status
;
1400 /* Check if we have an event handle */
1404 Status
= ObReferenceObjectByHandle(EventHandle
,
1410 if (Status
!= STATUS_SUCCESS
)
1412 ObDereferenceObject(FileObject
);
1415 KeClearEvent(Event
);
1418 /* Check if we should use Sync IO or not */
1419 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1422 IopLockFileObject(FileObject
);
1423 LockedForSync
= TRUE
;
1426 /* Clear File Object event */
1427 KeClearEvent(&FileObject
->Event
);
1429 /* Get the device object */
1430 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1432 /* Allocate the IRP */
1433 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1434 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1436 /* Set up the IRP */
1437 Irp
->RequestorMode
= PreviousMode
;
1438 Irp
->UserIosb
= IoStatusBlock
;
1439 Irp
->UserEvent
= Event
;
1440 Irp
->UserBuffer
= Buffer
;
1441 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1442 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1443 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1444 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1446 /* Set up Stack Data */
1447 IoStack
= IoGetNextIrpStackLocation(Irp
);
1448 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1449 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1450 IoStack
->FileObject
= FileObject
;
1452 /* Set parameters */
1453 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1454 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1455 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1457 /* Perform the call */
1458 return IopPerformSynchronousRequest(DeviceObject
,
1472 NtLockFile(IN HANDLE FileHandle
,
1473 IN HANDLE EventHandle OPTIONAL
,
1474 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1475 IN PVOID ApcContext OPTIONAL
,
1476 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1477 IN PLARGE_INTEGER ByteOffset
,
1478 IN PLARGE_INTEGER Length
,
1480 IN BOOLEAN FailImmediately
,
1481 IN BOOLEAN ExclusiveLock
)
1483 PFILE_OBJECT FileObject
;
1484 PLARGE_INTEGER LocalLength
= NULL
;
1486 PIO_STACK_LOCATION StackPtr
;
1487 PDEVICE_OBJECT DeviceObject
;
1488 PKEVENT Event
= NULL
;
1489 BOOLEAN LockedForSync
= FALSE
;
1490 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1491 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1493 OBJECT_HANDLE_INFORMATION HandleInformation
;
1495 CapturedByteOffset
.QuadPart
= 0;
1496 CapturedLength
.QuadPart
= 0;
1497 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1499 /* Get File Object */
1500 Status
= ObReferenceObjectByHandle(FileHandle
,
1504 (PVOID
*)&FileObject
,
1505 &HandleInformation
);
1506 if (!NT_SUCCESS(Status
)) return Status
;
1508 /* Check if we're called from user mode */
1509 if (PreviousMode
!= KernelMode
)
1511 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1512 if (!(HandleInformation
.GrantedAccess
&
1513 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1515 ObDereferenceObject(FileObject
);
1516 return STATUS_ACCESS_DENIED
;
1519 /* Enter SEH for probing */
1522 /* Probe the I/O STatus block */
1523 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1525 /* Probe and capture the large integers */
1526 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1527 CapturedLength
= ProbeForReadLargeInteger(Length
);
1529 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1531 /* Dereference the object and return exception code */
1532 ObDereferenceObject(FileObject
);
1533 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1539 /* Otherwise, capture them directly */
1540 CapturedByteOffset
= *ByteOffset
;
1541 CapturedLength
= *Length
;
1544 /* Check if we have an event handle */
1548 Status
= ObReferenceObjectByHandle(EventHandle
,
1554 if (Status
!= STATUS_SUCCESS
) return Status
;
1555 KeClearEvent(Event
);
1558 /* Get the device object */
1559 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1561 /* Check if we should use Sync IO or not */
1562 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1565 IopLockFileObject(FileObject
);
1566 LockedForSync
= TRUE
;
1569 /* Clear File Object event */
1570 KeClearEvent(&FileObject
->Event
);
1571 FileObject
->LockOperation
= TRUE
;
1573 /* Allocate the IRP */
1574 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1575 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1577 /* Set up the IRP */
1578 Irp
->RequestorMode
= PreviousMode
;
1579 Irp
->UserIosb
= IoStatusBlock
;
1580 Irp
->UserEvent
= Event
;
1581 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1582 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1583 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1584 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1586 /* Set up Stack Data */
1587 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1588 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1589 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1590 StackPtr
->FileObject
= FileObject
;
1592 /* Allocate local buffer */
1593 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1594 sizeof(LARGE_INTEGER
),
1598 /* Allocating failed, clean up and return failure */
1599 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1600 return STATUS_INSUFFICIENT_RESOURCES
;
1603 /* Set the length */
1604 *LocalLength
= CapturedLength
;
1605 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1606 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1608 /* Set Parameters */
1609 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1610 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1613 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1614 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1616 /* Perform the call */
1617 return IopPerformSynchronousRequest(DeviceObject
,
1631 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1632 IN HANDLE EventHandle OPTIONAL
,
1633 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1634 IN PVOID ApcContext OPTIONAL
,
1635 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1636 OUT PVOID FileInformation
,
1638 IN FILE_INFORMATION_CLASS FileInformationClass
,
1639 IN BOOLEAN ReturnSingleEntry
,
1640 IN PUNICODE_STRING FileName OPTIONAL
,
1641 IN BOOLEAN RestartScan
)
1644 PDEVICE_OBJECT DeviceObject
;
1645 PFILE_OBJECT FileObject
;
1646 PIO_STACK_LOCATION StackPtr
;
1647 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1649 BOOLEAN LockedForSynch
= FALSE
;
1650 PKEVENT Event
= NULL
;
1651 volatile PVOID AuxBuffer
= NULL
;
1653 UNICODE_STRING CapturedFileName
;
1654 PUNICODE_STRING SearchPattern
;
1656 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1658 /* Check if we came from user mode */
1659 if (PreviousMode
!= KernelMode
)
1661 /* Enter SEH for probing */
1664 /* Probe the I/O Status Block */
1665 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1667 /* Probe the file information */
1668 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1670 /* Check if we have a file name */
1674 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1675 if (CapturedFileName
.Length
)
1677 /* Probe its buffer */
1678 ProbeForRead(CapturedFileName
.Buffer
,
1679 CapturedFileName
.Length
,
1683 /* Allocate the auxiliary buffer */
1684 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1685 CapturedFileName
.Length
+
1686 sizeof(UNICODE_STRING
),
1688 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1689 sizeof(UNICODE_STRING
)),
1690 CapturedFileName
.Buffer
,
1691 CapturedFileName
.Length
);
1693 /* Setup the search pattern */
1694 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1695 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1696 sizeof(UNICODE_STRING
));
1697 SearchPattern
->Length
= CapturedFileName
.Length
;
1698 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1701 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1703 /* Free buffer and return the exception code */
1704 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1705 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1710 /* Get File Object */
1711 Status
= ObReferenceObjectByHandle(FileHandle
,
1712 FILE_LIST_DIRECTORY
,
1715 (PVOID
*)&FileObject
,
1717 if (!NT_SUCCESS(Status
))
1720 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1724 /* Check if we have an even handle */
1727 /* Get its pointer */
1728 Status
= ObReferenceObjectByHandle(EventHandle
,
1734 if (!NT_SUCCESS(Status
))
1737 ObDereferenceObject(FileObject
);
1742 KeClearEvent(Event
);
1745 /* Check if this is a file that was opened for Synch I/O */
1746 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1749 IopLockFileObject(FileObject
);
1751 /* Remember to unlock later */
1752 LockedForSynch
= TRUE
;
1755 /* Get the device object */
1756 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1758 /* Clear the File Object's event */
1759 KeClearEvent(&FileObject
->Event
);
1761 /* Allocate the IRP */
1762 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1763 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1765 /* Set up the IRP */
1766 Irp
->RequestorMode
= PreviousMode
;
1767 Irp
->UserIosb
= IoStatusBlock
;
1768 Irp
->UserEvent
= Event
;
1769 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1770 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1771 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1772 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1773 Irp
->MdlAddress
= NULL
;
1774 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1775 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1777 /* Check if this is buffered I/O */
1778 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1780 /* Allocate a buffer */
1781 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1784 if (!Irp
->AssociatedIrp
.SystemBuffer
)
1786 /* Allocating failed, clean up and return the exception code */
1787 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1788 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1790 /* Return the exception code */
1791 return STATUS_INSUFFICIENT_RESOURCES
;
1794 /* Set the buffer and flags */
1795 Irp
->UserBuffer
= FileInformation
;
1796 Irp
->Flags
= (IRP_BUFFERED_IO
|
1797 IRP_DEALLOCATE_BUFFER
|
1798 IRP_INPUT_OPERATION
);
1800 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1804 /* Allocate an MDL */
1805 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1806 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1807 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1809 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1811 /* Allocating failed, clean up and return the exception code */
1812 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1813 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1819 /* No allocation flags, and use the buffer directly */
1820 Irp
->UserBuffer
= FileInformation
;
1823 /* Set up Stack Data */
1824 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1825 StackPtr
->FileObject
= FileObject
;
1826 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1827 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1829 /* Set Parameters */
1830 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1831 FileInformationClass
;
1832 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1833 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1834 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1835 StackPtr
->Flags
= 0;
1836 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1837 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1839 /* Set deferred I/O */
1840 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1842 /* Perform the call */
1843 return IopPerformSynchronousRequest(DeviceObject
,
1857 NtQueryEaFile(IN HANDLE FileHandle
,
1858 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1861 IN BOOLEAN ReturnSingleEntry
,
1862 IN PVOID EaList OPTIONAL
,
1863 IN ULONG EaListLength
,
1864 IN PULONG EaIndex OPTIONAL
,
1865 IN BOOLEAN RestartScan
)
1868 return STATUS_NOT_IMPLEMENTED
;
1876 NtQueryInformationFile(IN HANDLE FileHandle
,
1877 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1878 IN PVOID FileInformation
,
1880 IN FILE_INFORMATION_CLASS FileInformationClass
)
1882 OBJECT_HANDLE_INFORMATION HandleInformation
;
1883 PFILE_OBJECT FileObject
;
1886 PDEVICE_OBJECT DeviceObject
;
1887 PIO_STACK_LOCATION StackPtr
;
1888 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1889 PKEVENT Event
= NULL
;
1890 BOOLEAN LocalEvent
= FALSE
;
1891 PKNORMAL_ROUTINE NormalRoutine
;
1892 PVOID NormalContext
;
1894 IO_STATUS_BLOCK KernelIosb
;
1895 BOOLEAN CallDriver
= TRUE
;
1896 PFILE_ACCESS_INFORMATION AccessBuffer
;
1897 PFILE_MODE_INFORMATION ModeBuffer
;
1898 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer
;
1900 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1902 /* Check if we're called from user mode */
1903 if (PreviousMode
!= KernelMode
)
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
;
1920 /* Enter SEH for probing */
1923 /* Probe the I/O Status block */
1924 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1926 /* Probe the information */
1927 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1929 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1931 /* Return the exception code */
1932 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1938 /* Validate the information class */
1939 if ((FileInformationClass
>= FileMaximumInformation
) ||
1940 !(IopQueryOperationLength
[FileInformationClass
]))
1943 return STATUS_INVALID_INFO_CLASS
;
1946 /* Validate the length */
1947 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1949 /* Invalid length */
1950 return STATUS_INFO_LENGTH_MISMATCH
;
1954 /* Reference the Handle */
1955 Status
= ObReferenceObjectByHandle(FileHandle
,
1956 IopQueryOperationAccess
1957 [FileInformationClass
],
1960 (PVOID
*)&FileObject
,
1961 &HandleInformation
);
1962 if (!NT_SUCCESS(Status
)) return Status
;
1964 /* Check if this is a direct open or not */
1965 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1967 /* Get the device object */
1968 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1972 /* Get the device object */
1973 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1976 /* Check if this is a file that was opened for Synch I/O */
1977 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1980 IopLockFileObject(FileObject
);
1982 /* Check if the caller just wants the position */
1983 if (FileInformationClass
== FilePositionInformation
)
1985 /* Protect write in SEH */
1988 /* Write the offset */
1989 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1990 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1992 /* Fill out the I/O Status Block */
1993 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1994 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1996 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1998 /* Get the exception code */
1999 Status
= _SEH2_GetExceptionCode();
2003 /* Release the file lock, dereference the file and return */
2004 IopUnlockFileObject(FileObject
);
2005 ObDereferenceObject(FileObject
);
2011 /* Use local event */
2012 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2015 ObDereferenceObject(FileObject
);
2016 return STATUS_INSUFFICIENT_RESOURCES
;
2018 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2022 /* Clear the File Object event */
2023 KeClearEvent(&FileObject
->Event
);
2025 /* Allocate the IRP */
2026 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2027 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2030 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2031 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2032 Irp
->RequestorMode
= PreviousMode
;
2033 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2034 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2035 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2036 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2037 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2038 Irp
->MdlAddress
= NULL
;
2039 Irp
->UserBuffer
= FileInformation
;
2041 /* Set the Stack Data */
2042 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2043 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2044 StackPtr
->FileObject
= FileObject
;
2049 /* Allocate a buffer */
2050 Irp
->AssociatedIrp
.SystemBuffer
=
2051 ExAllocatePoolWithTag(NonPagedPool
,
2055 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2057 /* Allocating failed, clean up and return the exception code */
2058 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2059 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2064 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2065 IRP_DEALLOCATE_BUFFER
|
2066 IRP_INPUT_OPERATION
|
2067 IRP_DEFER_IO_COMPLETION
);
2069 /* Set the Parameters */
2070 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2071 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2074 IopQueueIrpToThread(Irp
);
2076 /* Update operation counts */
2077 IopUpdateOperationCount(IopOtherTransfer
);
2079 /* Fill in file information before calling the driver.
2080 See 'File System Internals' page 485.*/
2081 if (FileInformationClass
== FileAccessInformation
)
2083 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2084 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2085 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2088 else if (FileInformationClass
== FileModeInformation
)
2090 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2091 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2092 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2095 else if (FileInformationClass
== FileAlignmentInformation
)
2097 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2098 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2099 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2103 /* Call the Driver */
2106 Status
= IoCallDriver(DeviceObject
, Irp
);
2110 Status
= STATUS_SUCCESS
;
2111 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2114 if (Status
== STATUS_PENDING
)
2116 /* Check if this was async I/O */
2119 /* Then to a non-alertable wait */
2120 Status
= KeWaitForSingleObject(Event
,
2125 if (Status
== STATUS_USER_APC
)
2127 /* Abort the request */
2128 IopAbortInterruptedIrp(Event
, Irp
);
2131 /* Set the final status */
2132 Status
= KernelIosb
.Status
;
2134 /* Enter SEH to write the IOSB back */
2137 /* Write it back to the caller */
2138 *IoStatusBlock
= KernelIosb
;
2140 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2142 /* Get the exception code */
2143 Status
= _SEH2_GetExceptionCode();
2147 /* Free the event */
2148 ExFreePoolWithTag(Event
, TAG_IO
);
2152 /* Wait for the IRP */
2153 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2156 (FileObject
->Flags
&
2157 FO_ALERTABLE_IO
) != 0,
2159 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2161 /* Abort the request */
2162 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2165 /* Set the final status */
2166 Status
= FileObject
->FinalStatus
;
2168 /* Release the file lock */
2169 IopUnlockFileObject(FileObject
);
2174 /* Free the event if we had one */
2177 /* Clear it in the IRP for completion */
2178 Irp
->UserEvent
= NULL
;
2179 ExFreePoolWithTag(Event
, TAG_IO
);
2182 /* Set the caller IOSB */
2183 Irp
->UserIosb
= IoStatusBlock
;
2185 /* The IRP wasn't completed, complete it ourselves */
2186 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2187 IopCompleteRequest(&Irp
->Tail
.Apc
,
2190 (PVOID
*)&FileObject
,
2192 KeLowerIrql(OldIrql
);
2194 /* Release the file object if we had locked it*/
2195 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2198 /* Return the Status */
2207 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2208 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2211 IN BOOLEAN ReturnSingleEntry
,
2212 IN PVOID SidList OPTIONAL
,
2213 IN ULONG SidListLength
,
2214 IN PSID StartSid OPTIONAL
,
2215 IN BOOLEAN RestartScan
)
2218 return STATUS_NOT_IMPLEMENTED
;
2226 NtReadFile(IN HANDLE FileHandle
,
2227 IN HANDLE Event OPTIONAL
,
2228 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2229 IN PVOID ApcContext OPTIONAL
,
2230 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2233 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2234 IN PULONG Key OPTIONAL
)
2237 PFILE_OBJECT FileObject
;
2239 PDEVICE_OBJECT DeviceObject
;
2240 PIO_STACK_LOCATION StackPtr
;
2241 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2242 PKEVENT EventObject
= NULL
;
2243 LARGE_INTEGER CapturedByteOffset
;
2244 ULONG CapturedKey
= 0;
2245 BOOLEAN Synchronous
= FALSE
;
2248 CapturedByteOffset
.QuadPart
= 0;
2249 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2251 /* Validate User-Mode Buffers */
2252 if (PreviousMode
!= KernelMode
)
2256 /* Probe the status block */
2257 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2259 /* Probe the read buffer */
2260 ProbeForWrite(Buffer
, Length
, 1);
2262 /* Check if we got a byte offset */
2265 /* Capture and probe it */
2266 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2269 /* Capture and probe the key */
2270 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2272 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2274 /* Return the exception code */
2275 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2281 /* Kernel mode: capture directly */
2282 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2283 if (Key
) CapturedKey
= *Key
;
2286 /* Get File Object */
2287 Status
= ObReferenceObjectByHandle(FileHandle
,
2291 (PVOID
*)&FileObject
,
2293 if (!NT_SUCCESS(Status
)) return Status
;
2295 /* Check for event */
2299 Status
= ObReferenceObjectByHandle(Event
,
2303 (PVOID
*)&EventObject
,
2305 if (!NT_SUCCESS(Status
))
2308 ObDereferenceObject(FileObject
);
2312 /* Otherwise reset the event */
2313 KeClearEvent(EventObject
);
2316 /* Check if we should use Sync IO or not */
2317 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2319 /* Lock the file object */
2320 IopLockFileObject(FileObject
);
2322 /* Check if we don't have a byte offset avilable */
2323 if (!(ByteOffset
) ||
2324 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2325 (CapturedByteOffset
.u
.HighPart
== -1)))
2327 /* Use the Current Byte Offset instead */
2328 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2331 /* Remember we are sync */
2334 else if (!(ByteOffset
) &&
2335 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2337 /* Otherwise, this was async I/O without a byte offset, so fail */
2338 if (EventObject
) ObDereferenceObject(EventObject
);
2339 ObDereferenceObject(FileObject
);
2340 return STATUS_INVALID_PARAMETER
;
2343 /* Get the device object */
2344 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2346 /* Clear the File Object's event */
2347 KeClearEvent(&FileObject
->Event
);
2349 /* Allocate the IRP */
2350 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2351 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2354 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2355 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2356 Irp
->RequestorMode
= PreviousMode
;
2357 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2358 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2359 Irp
->UserIosb
= IoStatusBlock
;
2360 Irp
->UserEvent
= EventObject
;
2361 Irp
->PendingReturned
= FALSE
;
2362 Irp
->Cancel
= FALSE
;
2363 Irp
->CancelRoutine
= NULL
;
2364 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2365 Irp
->MdlAddress
= NULL
;
2367 /* Set the Stack Data */
2368 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2369 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2370 StackPtr
->FileObject
= FileObject
;
2371 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2372 StackPtr
->Parameters
.Read
.Length
= Length
;
2373 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2375 /* Check if this is buffered I/O */
2376 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2378 /* Check if we have a buffer length */
2384 /* Allocate a buffer */
2385 Irp
->AssociatedIrp
.SystemBuffer
=
2386 ExAllocatePoolWithTag(NonPagedPool
,
2390 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2392 /* Allocating failed, clean up and return the exception code */
2393 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2394 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2398 /* Set the buffer and flags */
2399 Irp
->UserBuffer
= Buffer
;
2400 Irp
->Flags
= (IRP_BUFFERED_IO
|
2401 IRP_DEALLOCATE_BUFFER
|
2402 IRP_INPUT_OPERATION
);
2406 /* Not reading anything */
2407 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2410 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2412 /* Check if we have a buffer length */
2417 /* Allocate an MDL */
2418 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2420 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2421 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2423 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2425 /* Allocating failed, clean up and return the exception code */
2426 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2427 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2433 /* No allocation flags */
2438 /* No allocation flags, and use the buffer directly */
2440 Irp
->UserBuffer
= Buffer
;
2443 /* Now set the deferred read flags */
2444 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2446 /* FIXME: VFAT SUCKS */
2447 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2450 /* Perform the call */
2451 return IopPerformSynchronousRequest(DeviceObject
,
2465 NtReadFileScatter(IN HANDLE FileHandle
,
2466 IN HANDLE Event OPTIONAL
,
2467 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2468 IN PVOID UserApcContext OPTIONAL
,
2469 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2470 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2471 IN ULONG BufferLength
,
2472 IN PLARGE_INTEGER ByteOffset
,
2473 IN PULONG Key OPTIONAL
)
2476 return STATUS_NOT_IMPLEMENTED
;
2484 NtSetEaFile(IN HANDLE FileHandle
,
2485 IN PIO_STATUS_BLOCK IoStatusBlock
,
2487 IN ULONG EaBufferSize
)
2490 return STATUS_NOT_IMPLEMENTED
;
2498 NtSetInformationFile(IN HANDLE FileHandle
,
2499 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2500 IN PVOID FileInformation
,
2502 IN FILE_INFORMATION_CLASS FileInformationClass
)
2504 PFILE_OBJECT FileObject
;
2507 PDEVICE_OBJECT DeviceObject
;
2508 PIO_STACK_LOCATION StackPtr
;
2509 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2510 PKEVENT Event
= NULL
;
2511 BOOLEAN LocalEvent
= FALSE
;
2512 PKNORMAL_ROUTINE NormalRoutine
;
2513 PVOID NormalContext
;
2515 IO_STATUS_BLOCK KernelIosb
;
2517 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2518 PIO_COMPLETION_CONTEXT Context
;
2519 PFILE_RENAME_INFORMATION RenameInfo
;
2520 HANDLE TargetHandle
= NULL
;
2522 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2524 /* Check if we're called from user mode */
2525 if (PreviousMode
!= KernelMode
)
2527 /* Validate the information class */
2528 if ((FileInformationClass
>= FileMaximumInformation
) ||
2529 !(IopSetOperationLength
[FileInformationClass
]))
2532 return STATUS_INVALID_INFO_CLASS
;
2535 /* Validate the length */
2536 if (Length
< IopSetOperationLength
[FileInformationClass
])
2538 /* Invalid length */
2539 return STATUS_INFO_LENGTH_MISMATCH
;
2542 /* Enter SEH for probing */
2545 /* Probe the I/O Status block */
2546 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2548 /* Probe the information */
2549 ProbeForRead(FileInformation
,
2551 (Length
== sizeof(BOOLEAN
)) ?
2552 sizeof(BOOLEAN
) : sizeof(ULONG
));
2554 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2556 /* Return the exception code */
2557 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2563 /* Validate the information class */
2564 if ((FileInformationClass
>= FileMaximumInformation
) ||
2565 !(IopSetOperationLength
[FileInformationClass
]))
2568 return STATUS_INVALID_INFO_CLASS
;
2571 /* Validate the length */
2572 if (Length
< IopSetOperationLength
[FileInformationClass
])
2574 /* Invalid length */
2575 return STATUS_INFO_LENGTH_MISMATCH
;
2579 /* Reference the Handle */
2580 Status
= ObReferenceObjectByHandle(FileHandle
,
2581 IopSetOperationAccess
2582 [FileInformationClass
],
2585 (PVOID
*)&FileObject
,
2587 if (!NT_SUCCESS(Status
)) return Status
;
2589 /* Check if this is a direct open or not */
2590 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2592 /* Get the device object */
2593 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2597 /* Get the device object */
2598 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2601 /* Check if this is a file that was opened for Synch I/O */
2602 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2605 IopLockFileObject(FileObject
);
2607 /* Check if the caller just wants the position */
2608 if (FileInformationClass
== FilePositionInformation
)
2610 /* Protect write in SEH */
2613 /* Write the offset */
2614 FileObject
->CurrentByteOffset
=
2615 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2618 /* Fill out the I/O Status Block */
2619 IoStatusBlock
->Information
= 0;
2620 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2622 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2624 /* Get the exception code */
2625 Status
= _SEH2_GetExceptionCode();
2629 /* Update transfer count */
2630 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2632 /* Release the file lock, dereference the file and return */
2633 IopUnlockFileObject(FileObject
);
2634 ObDereferenceObject(FileObject
);
2640 /* Use local event */
2641 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2644 ObDereferenceObject(FileObject
);
2645 return STATUS_INSUFFICIENT_RESOURCES
;
2648 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2652 /* Clear the File Object event */
2653 KeClearEvent(&FileObject
->Event
);
2655 /* Allocate the IRP */
2656 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2657 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2660 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2661 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2662 Irp
->RequestorMode
= PreviousMode
;
2663 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2664 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2665 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2666 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2667 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2668 Irp
->MdlAddress
= NULL
;
2669 Irp
->UserBuffer
= FileInformation
;
2671 /* Set the Stack Data */
2672 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2673 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2674 StackPtr
->FileObject
= FileObject
;
2679 /* Allocate a buffer */
2680 Irp
->AssociatedIrp
.SystemBuffer
=
2681 ExAllocatePoolWithTag(NonPagedPool
,
2685 /* Copy the data into it */
2686 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2690 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2692 /* Allocating failed, clean up and return the exception code */
2693 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2694 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2699 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2700 IRP_DEALLOCATE_BUFFER
|
2701 IRP_DEFER_IO_COMPLETION
);
2703 /* Set the Parameters */
2704 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2705 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2708 IopQueueIrpToThread(Irp
);
2710 /* Update operation counts */
2711 IopUpdateOperationCount(IopOtherTransfer
);
2713 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2714 /* Handle IO Completion Port quickly */
2715 if (FileInformationClass
== FileCompletionInformation
)
2717 /* Check if the file object already has a completion port */
2718 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2719 (FileObject
->CompletionContext
))
2722 Status
= STATUS_INVALID_PARAMETER
;
2726 /* Reference the Port */
2727 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2728 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2729 IO_COMPLETION_MODIFY_STATE
,
2734 if (NT_SUCCESS(Status
))
2736 /* Allocate the Context */
2737 Context
= ExAllocatePoolWithTag(PagedPool
,
2738 sizeof(IO_COMPLETION_CONTEXT
),
2743 Context
->Key
= CompletionInfo
->Key
;
2744 Context
->Port
= Queue
;
2745 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
2751 * Someone else set the completion port in the
2752 * meanwhile, so dereference the port and fail.
2754 ExFreePoolWithTag(Context
, IOC_TAG
);
2755 ObDereferenceObject(Queue
);
2756 Status
= STATUS_INVALID_PARAMETER
;
2761 /* Dereference the Port now */
2762 ObDereferenceObject(Queue
);
2763 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2768 /* Set the IRP Status */
2769 Irp
->IoStatus
.Status
= Status
;
2770 Irp
->IoStatus
.Information
= 0;
2772 else if (FileInformationClass
== FileRenameInformation
||
2773 FileInformationClass
== FileLinkInformation
||
2774 FileInformationClass
== FileMoveClusterInformation
)
2776 /* Get associated information */
2777 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2782 * -> sizes are valid
2784 if (RenameInfo
->FileNameLength
!= 0 &&
2785 !(RenameInfo
->FileNameLength
& 1) &&
2786 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
2788 /* Properly set information received */
2789 if (FileInformationClass
== FileMoveClusterInformation
)
2791 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
2795 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
2798 /* If we got fully path OR relative target, attempt a parent directory open */
2799 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
2801 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
2802 if (!NT_SUCCESS(Status
))
2804 Irp
->IoStatus
.Status
= Status
;
2808 /* Call the Driver */
2809 Status
= IoCallDriver(DeviceObject
, Irp
);
2814 /* Call the Driver */
2815 Status
= IoCallDriver(DeviceObject
, Irp
);
2820 Status
= STATUS_INVALID_PARAMETER
;
2821 Irp
->IoStatus
.Status
= Status
;
2826 /* Call the Driver */
2827 Status
= IoCallDriver(DeviceObject
, Irp
);
2830 /* Check if we're waiting for the IRP to complete */
2831 if (Status
== STATUS_PENDING
)
2833 /* Check if this was async I/O */
2836 /* Then to a non-alertable wait */
2837 Status
= KeWaitForSingleObject(Event
,
2842 if (Status
== STATUS_USER_APC
)
2844 /* Abort the request */
2845 IopAbortInterruptedIrp(Event
, Irp
);
2848 /* Set the final status */
2849 Status
= KernelIosb
.Status
;
2851 /* Enter SEH to write the IOSB back */
2854 /* Write it back to the caller */
2855 *IoStatusBlock
= KernelIosb
;
2857 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2859 /* Get the exception code */
2860 Status
= _SEH2_GetExceptionCode();
2864 /* Free the event */
2865 ExFreePoolWithTag(Event
, TAG_IO
);
2869 /* Wait for the IRP */
2870 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2873 (FileObject
->Flags
&
2874 FO_ALERTABLE_IO
) != 0,
2876 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2878 /* Abort the request */
2879 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2882 /* Set the final status */
2883 Status
= FileObject
->FinalStatus
;
2885 /* Release the file lock */
2886 IopUnlockFileObject(FileObject
);
2891 /* Free the event if we had one */
2894 /* Clear it in the IRP for completion */
2895 Irp
->UserEvent
= NULL
;
2896 ExFreePoolWithTag(Event
, TAG_IO
);
2899 /* Set the caller IOSB */
2900 Irp
->UserIosb
= IoStatusBlock
;
2902 /* The IRP wasn't completed, complete it ourselves */
2903 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2904 IopCompleteRequest(&Irp
->Tail
.Apc
,
2907 (PVOID
*)&FileObject
,
2909 KeLowerIrql(OldIrql
);
2911 /* Release the file object if we had locked it*/
2912 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2915 if (TargetHandle
!= NULL
)
2917 ObCloseHandle(TargetHandle
, KernelMode
);
2920 /* Return the Status */
2929 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2930 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2932 IN ULONG BufferLength
)
2935 return STATUS_NOT_IMPLEMENTED
;
2943 NtUnlockFile(IN HANDLE FileHandle
,
2944 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2945 IN PLARGE_INTEGER ByteOffset
,
2946 IN PLARGE_INTEGER Length
,
2947 IN ULONG Key OPTIONAL
)
2949 PFILE_OBJECT FileObject
;
2950 PLARGE_INTEGER LocalLength
= NULL
;
2952 PIO_STACK_LOCATION StackPtr
;
2953 PDEVICE_OBJECT DeviceObject
;
2954 PKEVENT Event
= NULL
;
2955 BOOLEAN LocalEvent
= FALSE
;
2956 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2957 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2959 OBJECT_HANDLE_INFORMATION HandleInformation
;
2960 IO_STATUS_BLOCK KernelIosb
;
2962 CapturedByteOffset
.QuadPart
= 0;
2963 CapturedLength
.QuadPart
= 0;
2964 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2966 /* Get File Object */
2967 Status
= ObReferenceObjectByHandle(FileHandle
,
2971 (PVOID
*)&FileObject
,
2972 &HandleInformation
);
2973 if (!NT_SUCCESS(Status
)) return Status
;
2975 /* Check if we're called from user mode */
2976 if (PreviousMode
!= KernelMode
)
2978 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2979 if (!(HandleInformation
.GrantedAccess
&
2980 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2982 ObDereferenceObject(FileObject
);
2983 return STATUS_ACCESS_DENIED
;
2986 /* Enter SEH for probing */
2989 /* Probe the I/O Status block */
2990 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2992 /* Probe and capture the large integers */
2993 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2994 CapturedLength
= ProbeForReadLargeInteger(Length
);
2996 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2998 /* Dereference the object and return exception code */
2999 ObDereferenceObject(FileObject
);
3000 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3006 /* Otherwise, capture them directly */
3007 CapturedByteOffset
= *ByteOffset
;
3008 CapturedLength
= *Length
;
3011 /* Check if this is a direct open or not */
3012 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3014 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3018 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3021 /* Check if we should use Sync IO or not */
3022 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3025 IopLockFileObject(FileObject
);
3029 /* Use local event */
3030 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3033 ObDereferenceObject(FileObject
);
3034 return STATUS_INSUFFICIENT_RESOURCES
;
3036 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3040 /* Clear File Object event */
3041 KeClearEvent(&FileObject
->Event
);
3043 /* Allocate the IRP */
3044 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3045 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3047 /* Set up the IRP */
3048 Irp
->RequestorMode
= PreviousMode
;
3049 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3050 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3051 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3052 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3053 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3054 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3056 /* Set up Stack Data */
3057 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3058 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3059 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3060 StackPtr
->FileObject
= FileObject
;
3065 /* Allocate a buffer */
3066 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3067 sizeof(LARGE_INTEGER
),
3070 /* Set the length */
3071 *LocalLength
= CapturedLength
;
3072 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3073 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3075 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3077 /* Allocating failed, clean up and return the exception code */
3078 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3079 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3081 /* Return the exception code */
3082 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3086 /* Set Parameters */
3087 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3088 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3090 /* Call the Driver */
3091 Status
= IopPerformSynchronousRequest(DeviceObject
,
3099 /* Check if this was async I/O */
3102 /* It was, finalize this request */
3103 Status
= IopFinalizeAsynchronousIo(Status
,
3120 NtWriteFile(IN HANDLE FileHandle
,
3121 IN HANDLE Event OPTIONAL
,
3122 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3123 IN PVOID ApcContext OPTIONAL
,
3124 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3127 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3128 IN PULONG Key OPTIONAL
)
3131 PFILE_OBJECT FileObject
;
3133 PDEVICE_OBJECT DeviceObject
;
3134 PIO_STACK_LOCATION StackPtr
;
3135 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3136 PKEVENT EventObject
= NULL
;
3137 LARGE_INTEGER CapturedByteOffset
;
3138 ULONG CapturedKey
= 0;
3139 BOOLEAN Synchronous
= FALSE
;
3141 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3143 CapturedByteOffset
.QuadPart
= 0;
3144 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3146 /* Get File Object */
3147 Status
= ObReferenceObjectByHandle(FileHandle
,
3151 (PVOID
*)&FileObject
,
3153 if (!NT_SUCCESS(Status
)) return Status
;
3155 /* Validate User-Mode Buffers */
3156 if (PreviousMode
!= KernelMode
)
3161 * Check if the handle has either FILE_WRITE_DATA or
3162 * FILE_APPEND_DATA granted. However, if this is a named pipe,
3163 * make sure we don't ask for FILE_APPEND_DATA as it interferes
3164 * with the FILE_CREATE_PIPE_INSTANCE access right!
3166 if (!(ObjectHandleInfo
.GrantedAccess
&
3167 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
3168 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
3171 ObDereferenceObject(FileObject
);
3172 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
3175 /* Probe the status block */
3176 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3178 /* Probe the read buffer */
3179 ProbeForRead(Buffer
, Length
, 1);
3181 /* Check if we got a byte offset */
3184 /* Capture and probe it */
3185 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3188 /* Capture and probe the key */
3189 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3191 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3193 /* Return the exception code */
3194 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3200 /* Kernel mode: capture directly */
3201 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3202 if (Key
) CapturedKey
= *Key
;
3205 /* Check if this is an append operation */
3206 if ((ObjectHandleInfo
.GrantedAccess
&
3207 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3209 /* Give the drivers something to understand */
3210 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3211 CapturedByteOffset
.u
.HighPart
= -1;
3214 /* Check for event */
3218 Status
= ObReferenceObjectByHandle(Event
,
3222 (PVOID
*)&EventObject
,
3224 if (!NT_SUCCESS(Status
))
3227 ObDereferenceObject(FileObject
);
3231 /* Otherwise reset the event */
3232 KeClearEvent(EventObject
);
3235 /* Check if we should use Sync IO or not */
3236 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3238 /* Lock the file object */
3239 IopLockFileObject(FileObject
);
3241 /* Check if we don't have a byte offset avilable */
3242 if (!(ByteOffset
) ||
3243 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3244 (CapturedByteOffset
.u
.HighPart
== -1)))
3246 /* Use the Current Byte Offset instead */
3247 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3250 /* Remember we are sync */
3253 else if (!(ByteOffset
) &&
3254 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3256 /* Otherwise, this was async I/O without a byte offset, so fail */
3257 if (EventObject
) ObDereferenceObject(EventObject
);
3258 ObDereferenceObject(FileObject
);
3259 return STATUS_INVALID_PARAMETER
;
3262 /* Get the device object */
3263 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3265 /* Clear the File Object's event */
3266 KeClearEvent(&FileObject
->Event
);
3268 /* Allocate the IRP */
3269 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3270 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
3273 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3274 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3275 Irp
->RequestorMode
= PreviousMode
;
3276 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3277 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3278 Irp
->UserIosb
= IoStatusBlock
;
3279 Irp
->UserEvent
= EventObject
;
3280 Irp
->PendingReturned
= FALSE
;
3281 Irp
->Cancel
= FALSE
;
3282 Irp
->CancelRoutine
= NULL
;
3283 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3284 Irp
->MdlAddress
= NULL
;
3286 /* Set the Stack Data */
3287 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3288 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3289 StackPtr
->FileObject
= FileObject
;
3290 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3291 SL_WRITE_THROUGH
: 0;
3292 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3293 StackPtr
->Parameters
.Write
.Length
= Length
;
3294 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3296 /* Check if this is buffered I/O */
3297 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3299 /* Check if we have a buffer length */
3305 /* Allocate a buffer */
3306 Irp
->AssociatedIrp
.SystemBuffer
=
3307 ExAllocatePoolWithTag(NonPagedPool
,
3311 /* Copy the data into it */
3312 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3314 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3316 /* Allocating failed, clean up and return the exception code */
3317 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3318 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3323 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3327 /* Not writing anything */
3328 Irp
->Flags
= IRP_BUFFERED_IO
;
3331 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3333 /* Check if we have a buffer length */
3338 /* Allocate an MDL */
3339 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3341 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3342 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3344 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3346 /* Allocating failed, clean up and return the exception code */
3347 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3348 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3353 /* No allocation flags */
3358 /* No allocation flags, and use the buffer directly */
3360 Irp
->UserBuffer
= Buffer
;
3363 /* Now set the deferred read flags */
3364 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3366 /* FIXME: VFAT SUCKS */
3367 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3370 /* Perform the call */
3371 return IopPerformSynchronousRequest(DeviceObject
,
3382 NtWriteFileGather(IN HANDLE FileHandle
,
3383 IN HANDLE Event OPTIONAL
,
3384 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3385 IN PVOID UserApcContext OPTIONAL
,
3386 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3387 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3388 IN ULONG BufferLength
,
3389 IN PLARGE_INTEGER ByteOffset
,
3390 IN PULONG Key OPTIONAL
)
3393 return STATUS_NOT_IMPLEMENTED
;
3401 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3402 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3403 OUT PVOID FsInformation
,
3405 IN FS_INFORMATION_CLASS FsInformationClass
)
3407 PFILE_OBJECT FileObject
;
3409 PIO_STACK_LOCATION StackPtr
;
3410 PDEVICE_OBJECT DeviceObject
;
3411 PKEVENT Event
= NULL
;
3412 BOOLEAN LocalEvent
= FALSE
;
3413 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3415 IO_STATUS_BLOCK KernelIosb
;
3417 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3419 /* Check if we're called from user mode */
3420 if (PreviousMode
!= KernelMode
)
3422 /* Validate the information class */
3423 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3424 !(IopQueryFsOperationLength
[FsInformationClass
]))
3427 return STATUS_INVALID_INFO_CLASS
;
3430 /* Validate the length */
3431 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3433 /* Invalid length */
3434 return STATUS_INFO_LENGTH_MISMATCH
;
3437 /* Enter SEH for probing */
3440 /* Probe the I/O Status block */
3441 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3443 /* Probe the information */
3444 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3446 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3448 /* Return the exception code */
3449 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3454 /* Get File Object */
3455 Status
= ObReferenceObjectByHandle(FileHandle
,
3456 IopQueryFsOperationAccess
3457 [FsInformationClass
],
3460 (PVOID
*)&FileObject
,
3462 if (!NT_SUCCESS(Status
)) return Status
;
3464 /* Check if we should use Sync IO or not */
3465 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3468 IopLockFileObject(FileObject
);
3472 /* Use local event */
3473 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3476 ObDereferenceObject(FileObject
);
3477 return STATUS_INSUFFICIENT_RESOURCES
;
3479 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3483 /* Get the device object */
3484 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3486 /* Clear File Object event */
3487 KeClearEvent(&FileObject
->Event
);
3489 /* Allocate the IRP */
3490 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3491 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3493 /* Set up the IRP */
3494 Irp
->RequestorMode
= PreviousMode
;
3495 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3496 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3497 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3498 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3499 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3500 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3501 Irp
->UserBuffer
= FsInformation
;
3502 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3503 Irp
->MdlAddress
= NULL
;
3505 /* Set up Stack Data */
3506 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3507 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3508 StackPtr
->FileObject
= FileObject
;
3513 /* Allocate a buffer */
3514 Irp
->AssociatedIrp
.SystemBuffer
=
3515 ExAllocatePoolWithTag(NonPagedPool
,
3519 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3521 /* Allocating failed, clean up and return the exception code */
3522 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3523 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3527 /* Set the flags for this buffered + deferred I/O */
3528 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3529 IRP_DEALLOCATE_BUFFER
|
3530 IRP_INPUT_OPERATION
|
3531 IRP_DEFER_IO_COMPLETION
);
3533 /* Set Parameters */
3534 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3535 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3537 /* Call the Driver */
3538 Status
= IopPerformSynchronousRequest(DeviceObject
,
3546 /* Check if this was async I/O */
3549 /* It was, finalize this request */
3550 Status
= IopFinalizeAsynchronousIo(Status
,
3567 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3568 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3569 IN PVOID FsInformation
,
3571 IN FS_INFORMATION_CLASS FsInformationClass
)
3573 PFILE_OBJECT FileObject
;
3575 PIO_STACK_LOCATION StackPtr
;
3576 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3577 PKEVENT Event
= NULL
;
3578 BOOLEAN LocalEvent
= FALSE
;
3579 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3581 IO_STATUS_BLOCK KernelIosb
;
3582 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3584 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3586 /* Check if we're called from user mode */
3587 if (PreviousMode
!= KernelMode
)
3589 /* Validate the information class */
3590 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3591 !(IopSetFsOperationLength
[FsInformationClass
]))
3594 return STATUS_INVALID_INFO_CLASS
;
3597 /* Validate the length */
3598 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3600 /* Invalid length */
3601 return STATUS_INFO_LENGTH_MISMATCH
;
3604 /* Enter SEH for probing */
3607 /* Probe the I/O Status block */
3608 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3610 /* Probe the information */
3611 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3613 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3615 /* Return the exception code */
3616 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3621 /* Get File Object */
3622 Status
= ObReferenceObjectByHandle(FileHandle
,
3623 IopSetFsOperationAccess
3624 [FsInformationClass
],
3627 (PVOID
*)&FileObject
,
3629 if (!NT_SUCCESS(Status
)) return Status
;
3631 /* Get target device for notification */
3632 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
3633 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
3635 /* Check if we should use Sync IO or not */
3636 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3639 IopLockFileObject(FileObject
);
3643 /* Use local event */
3644 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3647 ObDereferenceObject(FileObject
);
3648 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3649 return STATUS_INSUFFICIENT_RESOURCES
;
3651 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3655 /* Get the device object */
3656 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3658 /* Clear File Object event */
3659 KeClearEvent(&FileObject
->Event
);
3661 /* Allocate the IRP */
3662 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3665 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3666 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3669 /* Set up the IRP */
3670 Irp
->RequestorMode
= PreviousMode
;
3671 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3672 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3673 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3674 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3675 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3676 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3677 Irp
->UserBuffer
= FsInformation
;
3678 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3679 Irp
->MdlAddress
= NULL
;
3681 /* Set up Stack Data */
3682 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3683 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3684 StackPtr
->FileObject
= FileObject
;
3689 /* Allocate a buffer */
3690 Irp
->AssociatedIrp
.SystemBuffer
=
3691 ExAllocatePoolWithTag(NonPagedPool
,
3695 /* Copy the data into it */
3696 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3698 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3700 /* Allocating failed, clean up and return the exception code */
3701 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3702 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3703 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3707 /* Set the flags for this buffered + deferred I/O */
3708 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3710 /* Set Parameters */
3711 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3712 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3714 /* Call the Driver */
3715 Status
= IopPerformSynchronousRequest(DeviceObject
,
3723 /* Check if this was async I/O */
3726 /* It was, finalize this request */
3727 Status
= IopFinalizeAsynchronousIo(Status
,
3735 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
3737 /* Time to report change */
3738 NotificationStructure
.Version
= 1;
3739 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
3740 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
3741 NotificationStructure
.FileObject
= NULL
;
3742 NotificationStructure
.NameBufferOffset
= - 1;
3743 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
3755 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3758 return STATUS_NOT_IMPLEMENTED
;
3766 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3769 return STATUS_NOT_IMPLEMENTED
;