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
;
1899 PFILE_ALL_INFORMATION AllBuffer
;
1901 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1903 /* Check if we're called from user mode */
1904 if (PreviousMode
!= KernelMode
)
1906 /* Validate the information class */
1907 if ((FileInformationClass
>= FileMaximumInformation
) ||
1908 !(IopQueryOperationLength
[FileInformationClass
]))
1911 return STATUS_INVALID_INFO_CLASS
;
1914 /* Validate the length */
1915 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1917 /* Invalid length */
1918 return STATUS_INFO_LENGTH_MISMATCH
;
1921 /* Enter SEH for probing */
1924 /* Probe the I/O Status block */
1925 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1927 /* Probe the information */
1928 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1930 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1932 /* Return the exception code */
1933 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1939 /* Validate the information class */
1940 if ((FileInformationClass
>= FileMaximumInformation
) ||
1941 !(IopQueryOperationLength
[FileInformationClass
]))
1944 return STATUS_INVALID_INFO_CLASS
;
1947 /* Validate the length */
1948 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1950 /* Invalid length */
1951 return STATUS_INFO_LENGTH_MISMATCH
;
1955 /* Reference the Handle */
1956 Status
= ObReferenceObjectByHandle(FileHandle
,
1957 IopQueryOperationAccess
1958 [FileInformationClass
],
1961 (PVOID
*)&FileObject
,
1962 &HandleInformation
);
1963 if (!NT_SUCCESS(Status
)) return Status
;
1965 /* Check if this is a direct open or not */
1966 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1968 /* Get the device object */
1969 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1973 /* Get the device object */
1974 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1977 /* Check if this is a file that was opened for Synch I/O */
1978 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1981 IopLockFileObject(FileObject
);
1983 /* Check if the caller just wants the position */
1984 if (FileInformationClass
== FilePositionInformation
)
1986 /* Protect write in SEH */
1989 /* Write the offset */
1990 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1991 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1993 /* Fill out the I/O Status Block */
1994 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1995 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1997 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1999 /* Get the exception code */
2000 Status
= _SEH2_GetExceptionCode();
2004 /* Release the file lock, dereference the file and return */
2005 IopUnlockFileObject(FileObject
);
2006 ObDereferenceObject(FileObject
);
2012 /* Use local event */
2013 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2016 ObDereferenceObject(FileObject
);
2017 return STATUS_INSUFFICIENT_RESOURCES
;
2019 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2023 /* Clear the File Object event */
2024 KeClearEvent(&FileObject
->Event
);
2026 /* Allocate the IRP */
2027 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2028 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2031 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2032 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2033 Irp
->RequestorMode
= PreviousMode
;
2034 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2035 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2036 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2037 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2038 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2039 Irp
->MdlAddress
= NULL
;
2040 Irp
->UserBuffer
= FileInformation
;
2042 /* Set the Stack Data */
2043 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2044 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2045 StackPtr
->FileObject
= FileObject
;
2050 /* Allocate a buffer */
2051 Irp
->AssociatedIrp
.SystemBuffer
=
2052 ExAllocatePoolWithTag(NonPagedPool
,
2056 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2058 /* Allocating failed, clean up and return the exception code */
2059 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2060 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2065 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2066 IRP_DEALLOCATE_BUFFER
|
2067 IRP_INPUT_OPERATION
|
2068 IRP_DEFER_IO_COMPLETION
);
2070 /* Set the Parameters */
2071 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2072 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2075 IopQueueIrpToThread(Irp
);
2077 /* Update operation counts */
2078 IopUpdateOperationCount(IopOtherTransfer
);
2080 /* Fill in file information before calling the driver.
2081 See 'File System Internals' page 485.*/
2082 if (FileInformationClass
== FileAccessInformation
)
2084 AccessBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2085 AccessBuffer
->AccessFlags
= HandleInformation
.GrantedAccess
;
2086 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
);
2089 else if (FileInformationClass
== FileModeInformation
)
2091 ModeBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2092 ModeBuffer
->Mode
= IopGetFileMode(FileObject
);
2093 Irp
->IoStatus
.Information
= sizeof(FILE_MODE_INFORMATION
);
2096 else if (FileInformationClass
== FileAlignmentInformation
)
2098 AlignmentBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2099 AlignmentBuffer
->AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2100 Irp
->IoStatus
.Information
= sizeof(FILE_ALIGNMENT_INFORMATION
);
2103 else if (FileInformationClass
== FileAllInformation
)
2105 AllBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2106 AllBuffer
->AccessInformation
.AccessFlags
= HandleInformation
.GrantedAccess
;
2107 AllBuffer
->ModeInformation
.Mode
= IopGetFileMode(FileObject
);
2108 AllBuffer
->AlignmentInformation
.AlignmentRequirement
= DeviceObject
->AlignmentRequirement
;
2109 Irp
->IoStatus
.Information
= sizeof(FILE_ACCESS_INFORMATION
) +
2110 sizeof(FILE_MODE_INFORMATION
) +
2111 sizeof(FILE_ALIGNMENT_INFORMATION
);
2114 /* Call the Driver */
2117 Status
= IoCallDriver(DeviceObject
, Irp
);
2121 Status
= STATUS_SUCCESS
;
2122 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2125 if (Status
== STATUS_PENDING
)
2127 /* Check if this was async I/O */
2130 /* Then to a non-alertable wait */
2131 Status
= KeWaitForSingleObject(Event
,
2136 if (Status
== STATUS_USER_APC
)
2138 /* Abort the request */
2139 IopAbortInterruptedIrp(Event
, Irp
);
2142 /* Set the final status */
2143 Status
= KernelIosb
.Status
;
2145 /* Enter SEH to write the IOSB back */
2148 /* Write it back to the caller */
2149 *IoStatusBlock
= KernelIosb
;
2151 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2153 /* Get the exception code */
2154 Status
= _SEH2_GetExceptionCode();
2158 /* Free the event */
2159 ExFreePoolWithTag(Event
, TAG_IO
);
2163 /* Wait for the IRP */
2164 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2167 (FileObject
->Flags
&
2168 FO_ALERTABLE_IO
) != 0,
2170 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2172 /* Abort the request */
2173 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2176 /* Set the final status */
2177 Status
= FileObject
->FinalStatus
;
2179 /* Release the file lock */
2180 IopUnlockFileObject(FileObject
);
2185 /* Free the event if we had one */
2188 /* Clear it in the IRP for completion */
2189 Irp
->UserEvent
= NULL
;
2190 ExFreePoolWithTag(Event
, TAG_IO
);
2193 /* Set the caller IOSB */
2194 Irp
->UserIosb
= IoStatusBlock
;
2196 /* The IRP wasn't completed, complete it ourselves */
2197 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2198 IopCompleteRequest(&Irp
->Tail
.Apc
,
2201 (PVOID
*)&FileObject
,
2203 KeLowerIrql(OldIrql
);
2205 /* Release the file object if we had locked it*/
2206 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2209 /* Return the Status */
2218 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2219 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2222 IN BOOLEAN ReturnSingleEntry
,
2223 IN PVOID SidList OPTIONAL
,
2224 IN ULONG SidListLength
,
2225 IN PSID StartSid OPTIONAL
,
2226 IN BOOLEAN RestartScan
)
2229 return STATUS_NOT_IMPLEMENTED
;
2237 NtReadFile(IN HANDLE FileHandle
,
2238 IN HANDLE Event OPTIONAL
,
2239 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2240 IN PVOID ApcContext OPTIONAL
,
2241 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2244 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2245 IN PULONG Key OPTIONAL
)
2248 PFILE_OBJECT FileObject
;
2250 PDEVICE_OBJECT DeviceObject
;
2251 PIO_STACK_LOCATION StackPtr
;
2252 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2253 PKEVENT EventObject
= NULL
;
2254 LARGE_INTEGER CapturedByteOffset
;
2255 ULONG CapturedKey
= 0;
2256 BOOLEAN Synchronous
= FALSE
;
2259 CapturedByteOffset
.QuadPart
= 0;
2260 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2262 /* Validate User-Mode Buffers */
2263 if (PreviousMode
!= KernelMode
)
2267 /* Probe the status block */
2268 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2270 /* Probe the read buffer */
2271 ProbeForWrite(Buffer
, Length
, 1);
2273 /* Check if we got a byte offset */
2276 /* Capture and probe it */
2277 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2280 /* Capture and probe the key */
2281 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2283 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2285 /* Return the exception code */
2286 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2292 /* Kernel mode: capture directly */
2293 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2294 if (Key
) CapturedKey
= *Key
;
2297 /* Get File Object */
2298 Status
= ObReferenceObjectByHandle(FileHandle
,
2302 (PVOID
*)&FileObject
,
2304 if (!NT_SUCCESS(Status
)) return Status
;
2306 /* Check for event */
2310 Status
= ObReferenceObjectByHandle(Event
,
2314 (PVOID
*)&EventObject
,
2316 if (!NT_SUCCESS(Status
))
2319 ObDereferenceObject(FileObject
);
2323 /* Otherwise reset the event */
2324 KeClearEvent(EventObject
);
2327 /* Check if we should use Sync IO or not */
2328 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2330 /* Lock the file object */
2331 IopLockFileObject(FileObject
);
2333 /* Check if we don't have a byte offset avilable */
2334 if (!(ByteOffset
) ||
2335 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2336 (CapturedByteOffset
.u
.HighPart
== -1)))
2338 /* Use the Current Byte Offset instead */
2339 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2342 /* Remember we are sync */
2345 else if (!(ByteOffset
) &&
2346 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2348 /* Otherwise, this was async I/O without a byte offset, so fail */
2349 if (EventObject
) ObDereferenceObject(EventObject
);
2350 ObDereferenceObject(FileObject
);
2351 return STATUS_INVALID_PARAMETER
;
2354 /* Get the device object */
2355 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2357 /* Clear the File Object's event */
2358 KeClearEvent(&FileObject
->Event
);
2360 /* Allocate the IRP */
2361 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2362 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2365 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2366 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2367 Irp
->RequestorMode
= PreviousMode
;
2368 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2369 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2370 Irp
->UserIosb
= IoStatusBlock
;
2371 Irp
->UserEvent
= EventObject
;
2372 Irp
->PendingReturned
= FALSE
;
2373 Irp
->Cancel
= FALSE
;
2374 Irp
->CancelRoutine
= NULL
;
2375 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2376 Irp
->MdlAddress
= NULL
;
2378 /* Set the Stack Data */
2379 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2380 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2381 StackPtr
->FileObject
= FileObject
;
2382 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2383 StackPtr
->Parameters
.Read
.Length
= Length
;
2384 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2386 /* Check if this is buffered I/O */
2387 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2389 /* Check if we have a buffer length */
2395 /* Allocate a buffer */
2396 Irp
->AssociatedIrp
.SystemBuffer
=
2397 ExAllocatePoolWithTag(NonPagedPool
,
2401 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2403 /* Allocating failed, clean up and return the exception code */
2404 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2405 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2409 /* Set the buffer and flags */
2410 Irp
->UserBuffer
= Buffer
;
2411 Irp
->Flags
= (IRP_BUFFERED_IO
|
2412 IRP_DEALLOCATE_BUFFER
|
2413 IRP_INPUT_OPERATION
);
2417 /* Not reading anything */
2418 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2421 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2423 /* Check if we have a buffer length */
2428 /* Allocate an MDL */
2429 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2431 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2432 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2434 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2436 /* Allocating failed, clean up and return the exception code */
2437 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2438 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2444 /* No allocation flags */
2449 /* No allocation flags, and use the buffer directly */
2451 Irp
->UserBuffer
= Buffer
;
2454 /* Now set the deferred read flags */
2455 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2457 /* FIXME: VFAT SUCKS */
2458 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2461 /* Perform the call */
2462 return IopPerformSynchronousRequest(DeviceObject
,
2476 NtReadFileScatter(IN HANDLE FileHandle
,
2477 IN HANDLE Event OPTIONAL
,
2478 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2479 IN PVOID UserApcContext OPTIONAL
,
2480 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2481 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2482 IN ULONG BufferLength
,
2483 IN PLARGE_INTEGER ByteOffset
,
2484 IN PULONG Key OPTIONAL
)
2487 return STATUS_NOT_IMPLEMENTED
;
2495 NtSetEaFile(IN HANDLE FileHandle
,
2496 IN PIO_STATUS_BLOCK IoStatusBlock
,
2498 IN ULONG EaBufferSize
)
2501 return STATUS_NOT_IMPLEMENTED
;
2509 NtSetInformationFile(IN HANDLE FileHandle
,
2510 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2511 IN PVOID FileInformation
,
2513 IN FILE_INFORMATION_CLASS FileInformationClass
)
2515 PFILE_OBJECT FileObject
;
2518 PDEVICE_OBJECT DeviceObject
;
2519 PIO_STACK_LOCATION StackPtr
;
2520 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2521 PKEVENT Event
= NULL
;
2522 BOOLEAN LocalEvent
= FALSE
;
2523 PKNORMAL_ROUTINE NormalRoutine
;
2524 PVOID NormalContext
;
2526 IO_STATUS_BLOCK KernelIosb
;
2528 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2529 PIO_COMPLETION_CONTEXT Context
;
2530 PFILE_RENAME_INFORMATION RenameInfo
;
2531 HANDLE TargetHandle
= NULL
;
2533 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2535 /* Check if we're called from user mode */
2536 if (PreviousMode
!= KernelMode
)
2538 /* Validate the information class */
2539 if ((FileInformationClass
>= FileMaximumInformation
) ||
2540 !(IopSetOperationLength
[FileInformationClass
]))
2543 return STATUS_INVALID_INFO_CLASS
;
2546 /* Validate the length */
2547 if (Length
< IopSetOperationLength
[FileInformationClass
])
2549 /* Invalid length */
2550 return STATUS_INFO_LENGTH_MISMATCH
;
2553 /* Enter SEH for probing */
2556 /* Probe the I/O Status block */
2557 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2559 /* Probe the information */
2560 ProbeForRead(FileInformation
,
2562 (Length
== sizeof(BOOLEAN
)) ?
2563 sizeof(BOOLEAN
) : sizeof(ULONG
));
2565 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2567 /* Return the exception code */
2568 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2574 /* Validate the information class */
2575 if ((FileInformationClass
>= FileMaximumInformation
) ||
2576 !(IopSetOperationLength
[FileInformationClass
]))
2579 return STATUS_INVALID_INFO_CLASS
;
2582 /* Validate the length */
2583 if (Length
< IopSetOperationLength
[FileInformationClass
])
2585 /* Invalid length */
2586 return STATUS_INFO_LENGTH_MISMATCH
;
2590 /* Reference the Handle */
2591 Status
= ObReferenceObjectByHandle(FileHandle
,
2592 IopSetOperationAccess
2593 [FileInformationClass
],
2596 (PVOID
*)&FileObject
,
2598 if (!NT_SUCCESS(Status
)) return Status
;
2600 /* Check if this is a direct open or not */
2601 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2603 /* Get the device object */
2604 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2608 /* Get the device object */
2609 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2612 /* Check if this is a file that was opened for Synch I/O */
2613 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2616 IopLockFileObject(FileObject
);
2618 /* Check if the caller just wants the position */
2619 if (FileInformationClass
== FilePositionInformation
)
2621 /* Protect write in SEH */
2624 /* Write the offset */
2625 FileObject
->CurrentByteOffset
=
2626 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2629 /* Fill out the I/O Status Block */
2630 IoStatusBlock
->Information
= 0;
2631 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2633 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2635 /* Get the exception code */
2636 Status
= _SEH2_GetExceptionCode();
2640 /* Update transfer count */
2641 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2643 /* Release the file lock, dereference the file and return */
2644 IopUnlockFileObject(FileObject
);
2645 ObDereferenceObject(FileObject
);
2651 /* Use local event */
2652 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2655 ObDereferenceObject(FileObject
);
2656 return STATUS_INSUFFICIENT_RESOURCES
;
2659 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2663 /* Clear the File Object event */
2664 KeClearEvent(&FileObject
->Event
);
2666 /* Allocate the IRP */
2667 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2668 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2671 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2672 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2673 Irp
->RequestorMode
= PreviousMode
;
2674 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2675 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2676 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2677 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2678 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2679 Irp
->MdlAddress
= NULL
;
2680 Irp
->UserBuffer
= FileInformation
;
2682 /* Set the Stack Data */
2683 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2684 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2685 StackPtr
->FileObject
= FileObject
;
2690 /* Allocate a buffer */
2691 Irp
->AssociatedIrp
.SystemBuffer
=
2692 ExAllocatePoolWithTag(NonPagedPool
,
2696 /* Copy the data into it */
2697 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2701 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2703 /* Allocating failed, clean up and return the exception code */
2704 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2705 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2710 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2711 IRP_DEALLOCATE_BUFFER
|
2712 IRP_DEFER_IO_COMPLETION
);
2714 /* Set the Parameters */
2715 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2716 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2719 IopQueueIrpToThread(Irp
);
2721 /* Update operation counts */
2722 IopUpdateOperationCount(IopOtherTransfer
);
2724 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2725 /* Handle IO Completion Port quickly */
2726 if (FileInformationClass
== FileCompletionInformation
)
2728 /* Check if the file object already has a completion port */
2729 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2730 (FileObject
->CompletionContext
))
2733 Status
= STATUS_INVALID_PARAMETER
;
2737 /* Reference the Port */
2738 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2739 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2740 IO_COMPLETION_MODIFY_STATE
,
2745 if (NT_SUCCESS(Status
))
2747 /* Allocate the Context */
2748 Context
= ExAllocatePoolWithTag(PagedPool
,
2749 sizeof(IO_COMPLETION_CONTEXT
),
2754 Context
->Key
= CompletionInfo
->Key
;
2755 Context
->Port
= Queue
;
2756 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
2762 * Someone else set the completion port in the
2763 * meanwhile, so dereference the port and fail.
2765 ExFreePoolWithTag(Context
, IOC_TAG
);
2766 ObDereferenceObject(Queue
);
2767 Status
= STATUS_INVALID_PARAMETER
;
2772 /* Dereference the Port now */
2773 ObDereferenceObject(Queue
);
2774 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2779 /* Set the IRP Status */
2780 Irp
->IoStatus
.Status
= Status
;
2781 Irp
->IoStatus
.Information
= 0;
2783 else if (FileInformationClass
== FileRenameInformation
||
2784 FileInformationClass
== FileLinkInformation
||
2785 FileInformationClass
== FileMoveClusterInformation
)
2787 /* Get associated information */
2788 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2793 * -> sizes are valid
2795 if (RenameInfo
->FileNameLength
!= 0 &&
2796 !(RenameInfo
->FileNameLength
& 1) &&
2797 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
2799 /* Properly set information received */
2800 if (FileInformationClass
== FileMoveClusterInformation
)
2802 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
2806 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
2809 /* If we got fully path OR relative target, attempt a parent directory open */
2810 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
2812 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
2813 if (!NT_SUCCESS(Status
))
2815 Irp
->IoStatus
.Status
= Status
;
2819 /* Call the Driver */
2820 Status
= IoCallDriver(DeviceObject
, Irp
);
2825 /* Call the Driver */
2826 Status
= IoCallDriver(DeviceObject
, Irp
);
2831 Status
= STATUS_INVALID_PARAMETER
;
2832 Irp
->IoStatus
.Status
= Status
;
2837 /* Call the Driver */
2838 Status
= IoCallDriver(DeviceObject
, Irp
);
2841 /* Check if we're waiting for the IRP to complete */
2842 if (Status
== STATUS_PENDING
)
2844 /* Check if this was async I/O */
2847 /* Then to a non-alertable wait */
2848 Status
= KeWaitForSingleObject(Event
,
2853 if (Status
== STATUS_USER_APC
)
2855 /* Abort the request */
2856 IopAbortInterruptedIrp(Event
, Irp
);
2859 /* Set the final status */
2860 Status
= KernelIosb
.Status
;
2862 /* Enter SEH to write the IOSB back */
2865 /* Write it back to the caller */
2866 *IoStatusBlock
= KernelIosb
;
2868 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2870 /* Get the exception code */
2871 Status
= _SEH2_GetExceptionCode();
2875 /* Free the event */
2876 ExFreePoolWithTag(Event
, TAG_IO
);
2880 /* Wait for the IRP */
2881 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2884 (FileObject
->Flags
&
2885 FO_ALERTABLE_IO
) != 0,
2887 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2889 /* Abort the request */
2890 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2893 /* Set the final status */
2894 Status
= FileObject
->FinalStatus
;
2896 /* Release the file lock */
2897 IopUnlockFileObject(FileObject
);
2902 /* Free the event if we had one */
2905 /* Clear it in the IRP for completion */
2906 Irp
->UserEvent
= NULL
;
2907 ExFreePoolWithTag(Event
, TAG_IO
);
2910 /* Set the caller IOSB */
2911 Irp
->UserIosb
= IoStatusBlock
;
2913 /* The IRP wasn't completed, complete it ourselves */
2914 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2915 IopCompleteRequest(&Irp
->Tail
.Apc
,
2918 (PVOID
*)&FileObject
,
2920 KeLowerIrql(OldIrql
);
2922 /* Release the file object if we had locked it*/
2923 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2926 if (TargetHandle
!= NULL
)
2928 ObCloseHandle(TargetHandle
, KernelMode
);
2931 /* Return the Status */
2940 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2941 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2943 IN ULONG BufferLength
)
2946 return STATUS_NOT_IMPLEMENTED
;
2954 NtUnlockFile(IN HANDLE FileHandle
,
2955 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2956 IN PLARGE_INTEGER ByteOffset
,
2957 IN PLARGE_INTEGER Length
,
2958 IN ULONG Key OPTIONAL
)
2960 PFILE_OBJECT FileObject
;
2961 PLARGE_INTEGER LocalLength
= NULL
;
2963 PIO_STACK_LOCATION StackPtr
;
2964 PDEVICE_OBJECT DeviceObject
;
2965 PKEVENT Event
= NULL
;
2966 BOOLEAN LocalEvent
= FALSE
;
2967 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2968 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2970 OBJECT_HANDLE_INFORMATION HandleInformation
;
2971 IO_STATUS_BLOCK KernelIosb
;
2973 CapturedByteOffset
.QuadPart
= 0;
2974 CapturedLength
.QuadPart
= 0;
2975 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2977 /* Get File Object */
2978 Status
= ObReferenceObjectByHandle(FileHandle
,
2982 (PVOID
*)&FileObject
,
2983 &HandleInformation
);
2984 if (!NT_SUCCESS(Status
)) return Status
;
2986 /* Check if we're called from user mode */
2987 if (PreviousMode
!= KernelMode
)
2989 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2990 if (!(HandleInformation
.GrantedAccess
&
2991 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2993 ObDereferenceObject(FileObject
);
2994 return STATUS_ACCESS_DENIED
;
2997 /* Enter SEH for probing */
3000 /* Probe the I/O Status block */
3001 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3003 /* Probe and capture the large integers */
3004 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3005 CapturedLength
= ProbeForReadLargeInteger(Length
);
3007 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3009 /* Dereference the object and return exception code */
3010 ObDereferenceObject(FileObject
);
3011 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3017 /* Otherwise, capture them directly */
3018 CapturedByteOffset
= *ByteOffset
;
3019 CapturedLength
= *Length
;
3022 /* Check if this is a direct open or not */
3023 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3025 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3029 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3032 /* Check if we should use Sync IO or not */
3033 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3036 IopLockFileObject(FileObject
);
3040 /* Use local event */
3041 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3044 ObDereferenceObject(FileObject
);
3045 return STATUS_INSUFFICIENT_RESOURCES
;
3047 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3051 /* Clear File Object event */
3052 KeClearEvent(&FileObject
->Event
);
3054 /* Allocate the IRP */
3055 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3056 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3058 /* Set up the IRP */
3059 Irp
->RequestorMode
= PreviousMode
;
3060 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3061 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3062 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3063 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3064 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3065 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3067 /* Set up Stack Data */
3068 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3069 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3070 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3071 StackPtr
->FileObject
= FileObject
;
3076 /* Allocate a buffer */
3077 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3078 sizeof(LARGE_INTEGER
),
3081 /* Set the length */
3082 *LocalLength
= CapturedLength
;
3083 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3084 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3086 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3088 /* Allocating failed, clean up and return the exception code */
3089 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3090 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3092 /* Return the exception code */
3093 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3097 /* Set Parameters */
3098 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3099 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3101 /* Call the Driver */
3102 Status
= IopPerformSynchronousRequest(DeviceObject
,
3110 /* Check if this was async I/O */
3113 /* It was, finalize this request */
3114 Status
= IopFinalizeAsynchronousIo(Status
,
3131 NtWriteFile(IN HANDLE FileHandle
,
3132 IN HANDLE Event OPTIONAL
,
3133 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3134 IN PVOID ApcContext OPTIONAL
,
3135 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3138 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3139 IN PULONG Key OPTIONAL
)
3142 PFILE_OBJECT FileObject
;
3144 PDEVICE_OBJECT DeviceObject
;
3145 PIO_STACK_LOCATION StackPtr
;
3146 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3147 PKEVENT EventObject
= NULL
;
3148 LARGE_INTEGER CapturedByteOffset
;
3149 ULONG CapturedKey
= 0;
3150 BOOLEAN Synchronous
= FALSE
;
3152 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3154 CapturedByteOffset
.QuadPart
= 0;
3155 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3157 /* Get File Object */
3158 Status
= ObReferenceObjectByHandle(FileHandle
,
3162 (PVOID
*)&FileObject
,
3164 if (!NT_SUCCESS(Status
)) return Status
;
3166 /* Validate User-Mode Buffers */
3167 if (PreviousMode
!= KernelMode
)
3172 * Check if the handle has either FILE_WRITE_DATA or
3173 * FILE_APPEND_DATA granted. However, if this is a named pipe,
3174 * make sure we don't ask for FILE_APPEND_DATA as it interferes
3175 * with the FILE_CREATE_PIPE_INSTANCE access right!
3177 if (!(ObjectHandleInfo
.GrantedAccess
&
3178 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
3179 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
3182 ObDereferenceObject(FileObject
);
3183 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
3186 /* Probe the status block */
3187 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3189 /* Probe the read buffer */
3190 ProbeForRead(Buffer
, Length
, 1);
3192 /* Check if we got a byte offset */
3195 /* Capture and probe it */
3196 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3199 /* Capture and probe the key */
3200 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3204 /* Return the exception code */
3205 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3211 /* Kernel mode: capture directly */
3212 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3213 if (Key
) CapturedKey
= *Key
;
3216 /* Check if this is an append operation */
3217 if ((ObjectHandleInfo
.GrantedAccess
&
3218 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3220 /* Give the drivers something to understand */
3221 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3222 CapturedByteOffset
.u
.HighPart
= -1;
3225 /* Check for event */
3229 Status
= ObReferenceObjectByHandle(Event
,
3233 (PVOID
*)&EventObject
,
3235 if (!NT_SUCCESS(Status
))
3238 ObDereferenceObject(FileObject
);
3242 /* Otherwise reset the event */
3243 KeClearEvent(EventObject
);
3246 /* Check if we should use Sync IO or not */
3247 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3249 /* Lock the file object */
3250 IopLockFileObject(FileObject
);
3252 /* Check if we don't have a byte offset avilable */
3253 if (!(ByteOffset
) ||
3254 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3255 (CapturedByteOffset
.u
.HighPart
== -1)))
3257 /* Use the Current Byte Offset instead */
3258 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3261 /* Remember we are sync */
3264 else if (!(ByteOffset
) &&
3265 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3267 /* Otherwise, this was async I/O without a byte offset, so fail */
3268 if (EventObject
) ObDereferenceObject(EventObject
);
3269 ObDereferenceObject(FileObject
);
3270 return STATUS_INVALID_PARAMETER
;
3273 /* Get the device object */
3274 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3276 /* Clear the File Object's event */
3277 KeClearEvent(&FileObject
->Event
);
3279 /* Allocate the IRP */
3280 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3281 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
3284 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3285 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3286 Irp
->RequestorMode
= PreviousMode
;
3287 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3288 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3289 Irp
->UserIosb
= IoStatusBlock
;
3290 Irp
->UserEvent
= EventObject
;
3291 Irp
->PendingReturned
= FALSE
;
3292 Irp
->Cancel
= FALSE
;
3293 Irp
->CancelRoutine
= NULL
;
3294 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3295 Irp
->MdlAddress
= NULL
;
3297 /* Set the Stack Data */
3298 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3299 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3300 StackPtr
->FileObject
= FileObject
;
3301 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3302 SL_WRITE_THROUGH
: 0;
3303 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3304 StackPtr
->Parameters
.Write
.Length
= Length
;
3305 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3307 /* Check if this is buffered I/O */
3308 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3310 /* Check if we have a buffer length */
3316 /* Allocate a buffer */
3317 Irp
->AssociatedIrp
.SystemBuffer
=
3318 ExAllocatePoolWithTag(NonPagedPool
,
3322 /* Copy the data into it */
3323 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3325 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3327 /* Allocating failed, clean up and return the exception code */
3328 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3329 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3334 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3338 /* Not writing anything */
3339 Irp
->Flags
= IRP_BUFFERED_IO
;
3342 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3344 /* Check if we have a buffer length */
3349 /* Allocate an MDL */
3350 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3352 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3353 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3355 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3357 /* Allocating failed, clean up and return the exception code */
3358 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3359 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3364 /* No allocation flags */
3369 /* No allocation flags, and use the buffer directly */
3371 Irp
->UserBuffer
= Buffer
;
3374 /* Now set the deferred read flags */
3375 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3377 /* FIXME: VFAT SUCKS */
3378 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3381 /* Perform the call */
3382 return IopPerformSynchronousRequest(DeviceObject
,
3393 NtWriteFileGather(IN HANDLE FileHandle
,
3394 IN HANDLE Event OPTIONAL
,
3395 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3396 IN PVOID UserApcContext OPTIONAL
,
3397 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3398 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3399 IN ULONG BufferLength
,
3400 IN PLARGE_INTEGER ByteOffset
,
3401 IN PULONG Key OPTIONAL
)
3404 return STATUS_NOT_IMPLEMENTED
;
3412 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3413 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3414 OUT PVOID FsInformation
,
3416 IN FS_INFORMATION_CLASS FsInformationClass
)
3418 PFILE_OBJECT FileObject
;
3420 PIO_STACK_LOCATION StackPtr
;
3421 PDEVICE_OBJECT DeviceObject
;
3422 PKEVENT Event
= NULL
;
3423 BOOLEAN LocalEvent
= FALSE
;
3424 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3426 IO_STATUS_BLOCK KernelIosb
;
3428 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3430 /* Check if we're called from user mode */
3431 if (PreviousMode
!= KernelMode
)
3433 /* Validate the information class */
3434 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3435 !(IopQueryFsOperationLength
[FsInformationClass
]))
3438 return STATUS_INVALID_INFO_CLASS
;
3441 /* Validate the length */
3442 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3444 /* Invalid length */
3445 return STATUS_INFO_LENGTH_MISMATCH
;
3448 /* Enter SEH for probing */
3451 /* Probe the I/O Status block */
3452 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3454 /* Probe the information */
3455 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3457 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3459 /* Return the exception code */
3460 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3465 /* Get File Object */
3466 Status
= ObReferenceObjectByHandle(FileHandle
,
3467 IopQueryFsOperationAccess
3468 [FsInformationClass
],
3471 (PVOID
*)&FileObject
,
3473 if (!NT_SUCCESS(Status
)) return Status
;
3475 /* Check if we should use Sync IO or not */
3476 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3479 IopLockFileObject(FileObject
);
3483 /* Use local event */
3484 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3487 ObDereferenceObject(FileObject
);
3488 return STATUS_INSUFFICIENT_RESOURCES
;
3490 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3494 /* Get the device object */
3495 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3497 /* Clear File Object event */
3498 KeClearEvent(&FileObject
->Event
);
3500 /* Allocate the IRP */
3501 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3502 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3504 /* Set up the IRP */
3505 Irp
->RequestorMode
= PreviousMode
;
3506 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3507 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3508 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3509 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3510 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3511 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3512 Irp
->UserBuffer
= FsInformation
;
3513 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3514 Irp
->MdlAddress
= NULL
;
3516 /* Set up Stack Data */
3517 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3518 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3519 StackPtr
->FileObject
= FileObject
;
3524 /* Allocate a buffer */
3525 Irp
->AssociatedIrp
.SystemBuffer
=
3526 ExAllocatePoolWithTag(NonPagedPool
,
3530 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3532 /* Allocating failed, clean up and return the exception code */
3533 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3534 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3538 /* Set the flags for this buffered + deferred I/O */
3539 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3540 IRP_DEALLOCATE_BUFFER
|
3541 IRP_INPUT_OPERATION
|
3542 IRP_DEFER_IO_COMPLETION
);
3544 /* Set Parameters */
3545 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3546 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3548 /* Call the Driver */
3549 Status
= IopPerformSynchronousRequest(DeviceObject
,
3557 /* Check if this was async I/O */
3560 /* It was, finalize this request */
3561 Status
= IopFinalizeAsynchronousIo(Status
,
3578 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3579 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3580 IN PVOID FsInformation
,
3582 IN FS_INFORMATION_CLASS FsInformationClass
)
3584 PFILE_OBJECT FileObject
;
3586 PIO_STACK_LOCATION StackPtr
;
3587 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3588 PKEVENT Event
= NULL
;
3589 BOOLEAN LocalEvent
= FALSE
;
3590 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3592 IO_STATUS_BLOCK KernelIosb
;
3593 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3595 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3597 /* Check if we're called from user mode */
3598 if (PreviousMode
!= KernelMode
)
3600 /* Validate the information class */
3601 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3602 !(IopSetFsOperationLength
[FsInformationClass
]))
3605 return STATUS_INVALID_INFO_CLASS
;
3608 /* Validate the length */
3609 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3611 /* Invalid length */
3612 return STATUS_INFO_LENGTH_MISMATCH
;
3615 /* Enter SEH for probing */
3618 /* Probe the I/O Status block */
3619 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3621 /* Probe the information */
3622 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3626 /* Return the exception code */
3627 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3632 /* Get File Object */
3633 Status
= ObReferenceObjectByHandle(FileHandle
,
3634 IopSetFsOperationAccess
3635 [FsInformationClass
],
3638 (PVOID
*)&FileObject
,
3640 if (!NT_SUCCESS(Status
)) return Status
;
3642 /* Get target device for notification */
3643 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
3644 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
3646 /* Check if we should use Sync IO or not */
3647 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3650 IopLockFileObject(FileObject
);
3654 /* Use local event */
3655 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3658 ObDereferenceObject(FileObject
);
3659 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3660 return STATUS_INSUFFICIENT_RESOURCES
;
3662 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3666 /* Get the device object */
3667 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3669 /* Clear File Object event */
3670 KeClearEvent(&FileObject
->Event
);
3672 /* Allocate the IRP */
3673 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3676 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3677 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3680 /* Set up the IRP */
3681 Irp
->RequestorMode
= PreviousMode
;
3682 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3683 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3684 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3685 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3686 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3687 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3688 Irp
->UserBuffer
= FsInformation
;
3689 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3690 Irp
->MdlAddress
= NULL
;
3692 /* Set up Stack Data */
3693 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3694 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3695 StackPtr
->FileObject
= FileObject
;
3700 /* Allocate a buffer */
3701 Irp
->AssociatedIrp
.SystemBuffer
=
3702 ExAllocatePoolWithTag(NonPagedPool
,
3706 /* Copy the data into it */
3707 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3709 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3711 /* Allocating failed, clean up and return the exception code */
3712 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3713 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3714 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3718 /* Set the flags for this buffered + deferred I/O */
3719 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3721 /* Set Parameters */
3722 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3723 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3725 /* Call the Driver */
3726 Status
= IopPerformSynchronousRequest(DeviceObject
,
3734 /* Check if this was async I/O */
3737 /* It was, finalize this request */
3738 Status
= IopFinalizeAsynchronousIo(Status
,
3746 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
3748 /* Time to report change */
3749 NotificationStructure
.Version
= 1;
3750 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
3751 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
3752 NotificationStructure
.FileObject
= NULL
;
3753 NotificationStructure
.NameBufferOffset
= - 1;
3754 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
3766 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3769 return STATUS_NOT_IMPLEMENTED
;
3777 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3780 return STATUS_NOT_IMPLEMENTED
;