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 Irp
->UserIosb
= &IoStatusBlock
;
667 Irp
->UserEvent
= &Event
;
668 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
669 Irp
->RequestorMode
= KernelMode
;
670 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
671 Irp
->Flags
= IRP_SYNCHRONOUS_API
| IRP_BUFFERED_IO
| IRP_OB_QUERY_NAME
;
672 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
673 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
675 Stack
= IoGetNextIrpStackLocation(Irp
);
676 Stack
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
677 Stack
->FileObject
= FileObject
;
678 Stack
->Parameters
.QueryFile
.FileInformationClass
= FileInfoClass
;
679 Stack
->Parameters
.QueryFile
.Length
= Length
;
683 IopQueueIrpToThread(Irp
);
685 /* Call the driver */
686 Status
= IoCallDriver(DeviceObject
, Irp
);
687 if (Status
== STATUS_PENDING
)
689 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
690 Status
= IoStatusBlock
.Status
;
693 *ReturnedLength
= IoStatusBlock
.Information
;
699 IopGetBasicInformationFile(IN PFILE_OBJECT FileObject
,
700 OUT PFILE_BASIC_INFORMATION BasicInfo
)
702 ULONG ReturnedLength
;
703 PDEVICE_OBJECT DeviceObject
;
704 IO_STATUS_BLOCK IoStatusBlock
;
708 /* Try to do it the fast way if possible */
709 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
710 if (DeviceObject
->DriverObject
->FastIoDispatch
!= NULL
&&
711 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo
!= NULL
&&
712 DeviceObject
->DriverObject
->FastIoDispatch
->FastIoQueryBasicInfo(FileObject
,
713 ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) != 0),
718 return IoStatusBlock
.Status
;
721 /* In case it failed, fall back to IRP-based method */
722 return IopGetFileInformation(FileObject
, sizeof(FILE_BASIC_INFORMATION
), FileBasicInformation
, BasicInfo
, &ReturnedLength
);
727 IopOpenLinkOrRenameTarget(OUT PHANDLE Handle
,
729 IN PFILE_RENAME_INFORMATION RenameInfo
,
730 IN PFILE_OBJECT FileObject
)
734 UNICODE_STRING FileName
;
735 PIO_STACK_LOCATION Stack
;
736 PFILE_OBJECT TargetFileObject
;
737 IO_STATUS_BLOCK IoStatusBlock
;
738 FILE_BASIC_INFORMATION BasicInfo
;
739 OBJECT_ATTRIBUTES ObjectAttributes
;
740 OBJECT_HANDLE_INFORMATION HandleInformation
;
741 ACCESS_MASK DesiredAccess
= FILE_WRITE_DATA
;
745 /* First, establish whether our target is a directory */
746 if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
))
748 Status
= IopGetBasicInformationFile(FileObject
, &BasicInfo
);
749 if (!NT_SUCCESS(Status
))
754 if (BasicInfo
.FileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
755 DesiredAccess
= FILE_ADD_SUBDIRECTORY
;
759 /* Setup the string to the target */
760 FileName
.Buffer
= RenameInfo
->FileName
;
761 FileName
.Length
= RenameInfo
->FileNameLength
;
762 FileName
.MaximumLength
= RenameInfo
->FileNameLength
;
764 InitializeObjectAttributes(&ObjectAttributes
,
766 (FileObject
->Flags
& FO_OPENED_CASE_SENSITIVE
? 0 : OBJ_CASE_INSENSITIVE
) | OBJ_KERNEL_HANDLE
,
767 RenameInfo
->RootDirectory
,
770 /* And open its parent directory */
771 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
773 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
775 /* Commented out - we don't support FO extension yet
776 * FIXME: Corrected last arg when it's supported
778 Status
= IoCreateFileSpecifyDeviceObjectHint(&TargetHandle
,
779 DesiredAccess
| SYNCHRONIZE
,
784 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
786 FILE_OPEN_FOR_BACKUP_INTENT
,
791 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
,
792 FileObject
->DeviceObject
);
796 return STATUS_NOT_IMPLEMENTED
;
801 Status
= IoCreateFile(&TargetHandle
,
802 DesiredAccess
| SYNCHRONIZE
,
807 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
809 FILE_OPEN_FOR_BACKUP_INTENT
,
814 IO_FORCE_ACCESS_CHECK
| IO_OPEN_TARGET_DIRECTORY
| IO_NO_PARAMETER_CHECKING
);
817 if (!NT_SUCCESS(Status
))
822 /* Once open, continue only if:
823 * Target exists and we're allowed to overwrite it
825 Stack
= IoGetNextIrpStackLocation(Irp
);
826 if (Stack
->Parameters
.SetFile
.FileInformationClass
== FileLinkInformation
&&
827 !RenameInfo
->ReplaceIfExists
&&
828 IoStatusBlock
.Information
== FILE_EXISTS
)
830 ObCloseHandle(TargetHandle
, KernelMode
);
831 return STATUS_OBJECT_NAME_COLLISION
;
834 /* Now, we'll get the associated device of the target, to check for same device location
835 * So, get the FO first
837 Status
= ObReferenceObjectByHandle(TargetHandle
,
841 (PVOID
*)&TargetFileObject
,
843 if (!NT_SUCCESS(Status
))
845 ObCloseHandle(TargetHandle
, KernelMode
);
849 /* We can dereference, we have the handle */
850 ObDereferenceObject(TargetFileObject
);
851 /* If we're not on the same device, error out **/
852 if (IoGetRelatedDeviceObject(TargetFileObject
) != IoGetRelatedDeviceObject(FileObject
))
854 ObCloseHandle(TargetHandle
, KernelMode
);
855 return STATUS_NOT_SAME_DEVICE
;
858 /* Return parent directory file object and handle */
859 Stack
->Parameters
.SetFile
.FileObject
= TargetFileObject
;
860 *Handle
= TargetHandle
;
862 return STATUS_SUCCESS
;
865 /* PUBLIC FUNCTIONS **********************************************************/
872 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject
,
874 IN PLARGE_INTEGER Offset
,
876 IN PIO_STATUS_BLOCK StatusBlock
)
879 PIO_STACK_LOCATION StackPtr
;
880 PDEVICE_OBJECT DeviceObject
;
881 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
882 FileObject
, Mdl
, Offset
);
884 /* Get the Device Object */
885 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
888 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
889 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
892 StackPtr
= IoGetNextIrpStackLocation(Irp
);
894 /* Create the IRP Settings */
895 Irp
->MdlAddress
= Mdl
;
896 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
897 Irp
->UserIosb
= StatusBlock
;
898 Irp
->UserEvent
= Event
;
899 Irp
->RequestorMode
= KernelMode
;
900 Irp
->Flags
= IRP_PAGING_IO
| IRP_NOCACHE
| IRP_SYNCHRONOUS_PAGING_IO
;
901 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
902 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
904 /* Set the Stack Settings */
905 StackPtr
->Parameters
.Write
.Length
= MmGetMdlByteCount(Mdl
);
906 StackPtr
->Parameters
.Write
.ByteOffset
= *Offset
;
907 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
908 StackPtr
->FileObject
= FileObject
;
910 /* Call the Driver */
911 return IoCallDriver(DeviceObject
, Irp
);
919 IoPageRead(IN PFILE_OBJECT FileObject
,
921 IN PLARGE_INTEGER Offset
,
923 IN PIO_STATUS_BLOCK StatusBlock
)
926 PIO_STACK_LOCATION StackPtr
;
927 PDEVICE_OBJECT DeviceObject
;
928 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Mdl: %p. Offset: %p \n",
929 FileObject
, Mdl
, Offset
);
931 /* Get the Device Object */
932 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
935 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
936 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
939 StackPtr
= IoGetNextIrpStackLocation(Irp
);
941 /* Create the IRP Settings */
942 Irp
->MdlAddress
= Mdl
;
943 Irp
->UserBuffer
= MmGetMdlVirtualAddress(Mdl
);
944 Irp
->UserIosb
= StatusBlock
;
945 Irp
->UserEvent
= Event
;
946 Irp
->RequestorMode
= KernelMode
;
947 Irp
->Flags
= IRP_PAGING_IO
|
949 IRP_SYNCHRONOUS_PAGING_IO
|
951 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
952 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
954 /* Set the Stack Settings */
955 StackPtr
->Parameters
.Read
.Length
= MmGetMdlByteCount(Mdl
);
956 StackPtr
->Parameters
.Read
.ByteOffset
= *Offset
;
957 StackPtr
->MajorFunction
= IRP_MJ_READ
;
958 StackPtr
->FileObject
= FileObject
;
960 /* Call the Driver */
961 return IoCallDriver(DeviceObject
, Irp
);
969 IoQueryFileInformation(IN PFILE_OBJECT FileObject
,
970 IN FILE_INFORMATION_CLASS FileInformationClass
,
972 OUT PVOID FileInformation
,
973 OUT PULONG ReturnedLength
)
975 /* Call the shared routine */
976 return IopQueryDeviceInformation(FileObject
,
977 FileInformationClass
,
989 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject
,
990 IN FS_INFORMATION_CLASS FsInformationClass
,
992 OUT PVOID FsInformation
,
993 OUT PULONG ReturnedLength
)
995 /* Call the shared routine */
996 return IopQueryDeviceInformation(FileObject
,
1009 IoSetInformation(IN PFILE_OBJECT FileObject
,
1010 IN FILE_INFORMATION_CLASS FileInformationClass
,
1012 IN PVOID FileInformation
)
1014 IO_STATUS_BLOCK IoStatusBlock
;
1016 PDEVICE_OBJECT DeviceObject
;
1017 PIO_STACK_LOCATION StackPtr
;
1018 BOOLEAN LocalEvent
= FALSE
;
1022 IOTRACE(IO_API_DEBUG
, "FileObject: %p. Class: %lx. Length: %lx \n",
1023 FileObject
, FileInformationClass
, Length
);
1025 /* Reference the object */
1026 ObReferenceObject(FileObject
);
1028 /* Check if this is a file that was opened for Synch I/O */
1029 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1032 IopLockFileObject(FileObject
);
1034 /* Use File Object event */
1035 KeClearEvent(&FileObject
->Event
);
1039 /* Use local event */
1040 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1044 /* Get the Device Object */
1045 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1047 /* Allocate the IRP */
1048 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1049 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
1052 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1053 Irp
->RequestorMode
= KernelMode
;
1054 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1055 Irp
->UserIosb
= &IoStatusBlock
;
1056 Irp
->UserEvent
= (LocalEvent
) ? &Event
: NULL
;
1057 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1058 Irp
->Flags
|= IRP_BUFFERED_IO
;
1059 Irp
->AssociatedIrp
.SystemBuffer
= FileInformation
;
1060 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1062 /* Set the Stack Data */
1063 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1064 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
1065 StackPtr
->FileObject
= FileObject
;
1067 /* Set Parameters */
1068 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
1069 StackPtr
->Parameters
.SetFile
.Length
= Length
;
1072 IopQueueIrpToThread(Irp
);
1074 /* Call the Driver */
1075 Status
= IoCallDriver(DeviceObject
, Irp
);
1077 /* Check if this was synch I/O */
1080 /* Check if the requet is pending */
1081 if (Status
== STATUS_PENDING
)
1083 /* Wait on the file object */
1084 Status
= KeWaitForSingleObject(&FileObject
->Event
,
1087 (FileObject
->Flags
&
1088 FO_ALERTABLE_IO
) != 0,
1090 if (Status
== STATUS_ALERTED
)
1092 /* Abort the operation */
1093 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
1096 /* Get the final status */
1097 Status
= FileObject
->FinalStatus
;
1100 /* Release the file lock */
1101 IopUnlockFileObject(FileObject
);
1103 else if (Status
== STATUS_PENDING
)
1105 /* Wait on the local event and get the final status */
1106 KeWaitForSingleObject(&Event
,
1111 Status
= IoStatusBlock
.Status
;
1114 /* Return the status */
1118 /* NATIVE SERVICES ***********************************************************/
1125 NtDeviceIoControlFile(IN HANDLE DeviceHandle
,
1126 IN HANDLE Event OPTIONAL
,
1127 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1128 IN PVOID UserApcContext OPTIONAL
,
1129 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1130 IN ULONG IoControlCode
,
1131 IN PVOID InputBuffer
,
1132 IN ULONG InputBufferLength OPTIONAL
,
1133 OUT PVOID OutputBuffer
,
1134 IN ULONG OutputBufferLength OPTIONAL
)
1136 /* Call the Generic Function */
1137 return IopDeviceFsIoControl(DeviceHandle
,
1155 NtFsControlFile(IN HANDLE DeviceHandle
,
1156 IN HANDLE Event OPTIONAL
,
1157 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1158 IN PVOID UserApcContext OPTIONAL
,
1159 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1160 IN ULONG IoControlCode
,
1161 IN PVOID InputBuffer
,
1162 IN ULONG InputBufferLength OPTIONAL
,
1163 OUT PVOID OutputBuffer
,
1164 IN ULONG OutputBufferLength OPTIONAL
)
1166 /* Call the Generic Function */
1167 return IopDeviceFsIoControl(DeviceHandle
,
1182 NtFlushBuffersFile(IN HANDLE FileHandle
,
1183 OUT PIO_STATUS_BLOCK IoStatusBlock
)
1185 PFILE_OBJECT FileObject
;
1187 PIO_STACK_LOCATION StackPtr
;
1189 PDEVICE_OBJECT DeviceObject
;
1190 PKEVENT Event
= NULL
;
1191 BOOLEAN LocalEvent
= FALSE
;
1192 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1193 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1194 IO_STATUS_BLOCK KernelIosb
;
1196 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1198 if (PreviousMode
!= KernelMode
)
1200 /* Protect probes */
1203 /* Probe the I/O Status block */
1204 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1206 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1208 /* Return the exception code */
1209 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1214 /* Get the File Object */
1215 Status
= ObReferenceObjectByHandle(FileHandle
,
1219 (PVOID
*)&FileObject
,
1221 if (!NT_SUCCESS(Status
)) return Status
;
1224 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1225 * granted. However, if this is a named pipe, make sure we don't ask for
1226 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1229 if (!(ObjectHandleInfo
.GrantedAccess
&
1230 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ? FILE_APPEND_DATA
: 0) |
1234 ObDereferenceObject(FileObject
);
1235 return STATUS_ACCESS_DENIED
;
1238 /* Check if we should use Sync IO or not */
1239 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1242 IopLockFileObject(FileObject
);
1246 /* Use local event */
1247 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1251 ObDereferenceObject(FileObject
);
1252 return STATUS_INSUFFICIENT_RESOURCES
;
1254 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1258 /* Get the Device Object */
1259 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1261 /* Clear the event */
1262 KeClearEvent(&FileObject
->Event
);
1264 /* Allocate the IRP */
1265 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1266 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1268 /* Set up the IRP */
1269 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1270 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
1271 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
1272 Irp
->RequestorMode
= PreviousMode
;
1273 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1274 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1275 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1277 /* Set up Stack Data */
1278 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1279 StackPtr
->MajorFunction
= IRP_MJ_FLUSH_BUFFERS
;
1280 StackPtr
->FileObject
= FileObject
;
1282 /* Call the Driver */
1283 Status
= IopPerformSynchronousRequest(DeviceObject
,
1291 /* Check if this was async I/O */
1294 /* It was, finalize this request */
1295 Status
= IopFinalizeAsynchronousIo(Status
,
1303 /* Return the Status */
1312 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle
,
1313 IN HANDLE EventHandle OPTIONAL
,
1314 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1315 IN PVOID ApcContext OPTIONAL
,
1316 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1318 IN ULONG BufferSize
,
1319 IN ULONG CompletionFilter
,
1320 IN BOOLEAN WatchTree
)
1323 PKEVENT Event
= NULL
;
1324 PDEVICE_OBJECT DeviceObject
;
1325 PFILE_OBJECT FileObject
;
1326 PIO_STACK_LOCATION IoStack
;
1327 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1329 BOOLEAN LockedForSync
= FALSE
;
1331 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1333 /* Check if we're called from user mode */
1334 if (PreviousMode
!= KernelMode
)
1336 /* Enter SEH for probing */
1339 /* Probe the I/O STatus block */
1340 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1342 /* Probe the buffer */
1343 if (BufferSize
) ProbeForWrite(Buffer
, BufferSize
, sizeof(ULONG
));
1345 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1347 /* Return the exception code */
1348 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1352 /* Check if CompletionFilter is valid */
1353 if (!CompletionFilter
|| (CompletionFilter
& ~FILE_NOTIFY_VALID_MASK
))
1355 return STATUS_INVALID_PARAMETER
;
1359 /* Get File Object */
1360 Status
= ObReferenceObjectByHandle(FileHandle
,
1361 FILE_LIST_DIRECTORY
,
1364 (PVOID
*)&FileObject
,
1366 if (!NT_SUCCESS(Status
)) return Status
;
1368 /* Check if we have an event handle */
1372 Status
= ObReferenceObjectByHandle(EventHandle
,
1378 if (Status
!= STATUS_SUCCESS
)
1380 ObDereferenceObject(FileObject
);
1383 KeClearEvent(Event
);
1386 /* Check if we should use Sync IO or not */
1387 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1390 IopLockFileObject(FileObject
);
1391 LockedForSync
= TRUE
;
1394 /* Clear File Object event */
1395 KeClearEvent(&FileObject
->Event
);
1397 /* Get the device object */
1398 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1400 /* Allocate the IRP */
1401 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1402 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1404 /* Set up the IRP */
1405 Irp
->RequestorMode
= PreviousMode
;
1406 Irp
->UserIosb
= IoStatusBlock
;
1407 Irp
->UserEvent
= Event
;
1408 Irp
->UserBuffer
= Buffer
;
1409 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1410 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1411 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1412 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1414 /* Set up Stack Data */
1415 IoStack
= IoGetNextIrpStackLocation(Irp
);
1416 IoStack
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1417 IoStack
->MinorFunction
= IRP_MN_NOTIFY_CHANGE_DIRECTORY
;
1418 IoStack
->FileObject
= FileObject
;
1420 /* Set parameters */
1421 IoStack
->Parameters
.NotifyDirectory
.CompletionFilter
= CompletionFilter
;
1422 IoStack
->Parameters
.NotifyDirectory
.Length
= BufferSize
;
1423 if (WatchTree
) IoStack
->Flags
= SL_WATCH_TREE
;
1425 /* Perform the call */
1426 return IopPerformSynchronousRequest(DeviceObject
,
1440 NtLockFile(IN HANDLE FileHandle
,
1441 IN HANDLE EventHandle OPTIONAL
,
1442 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1443 IN PVOID ApcContext OPTIONAL
,
1444 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1445 IN PLARGE_INTEGER ByteOffset
,
1446 IN PLARGE_INTEGER Length
,
1448 IN BOOLEAN FailImmediately
,
1449 IN BOOLEAN ExclusiveLock
)
1451 PFILE_OBJECT FileObject
;
1452 PLARGE_INTEGER LocalLength
= NULL
;
1454 PIO_STACK_LOCATION StackPtr
;
1455 PDEVICE_OBJECT DeviceObject
;
1456 PKEVENT Event
= NULL
;
1457 BOOLEAN LockedForSync
= FALSE
;
1458 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1459 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
1461 OBJECT_HANDLE_INFORMATION HandleInformation
;
1463 CapturedByteOffset
.QuadPart
= 0;
1464 CapturedLength
.QuadPart
= 0;
1465 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1467 /* Get File Object */
1468 Status
= ObReferenceObjectByHandle(FileHandle
,
1472 (PVOID
*)&FileObject
,
1473 &HandleInformation
);
1474 if (!NT_SUCCESS(Status
)) return Status
;
1476 /* Check if we're called from user mode */
1477 if (PreviousMode
!= KernelMode
)
1479 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1480 if (!(HandleInformation
.GrantedAccess
&
1481 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
1483 ObDereferenceObject(FileObject
);
1484 return STATUS_ACCESS_DENIED
;
1487 /* Enter SEH for probing */
1490 /* Probe the I/O STatus block */
1491 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1493 /* Probe and capture the large integers */
1494 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
1495 CapturedLength
= ProbeForReadLargeInteger(Length
);
1497 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1499 /* Dereference the object and return exception code */
1500 ObDereferenceObject(FileObject
);
1501 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1507 /* Otherwise, capture them directly */
1508 CapturedByteOffset
= *ByteOffset
;
1509 CapturedLength
= *Length
;
1512 /* Check if we have an event handle */
1516 Status
= ObReferenceObjectByHandle(EventHandle
,
1522 if (Status
!= STATUS_SUCCESS
) return Status
;
1523 KeClearEvent(Event
);
1526 /* Get the device object */
1527 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1529 /* Check if we should use Sync IO or not */
1530 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1533 IopLockFileObject(FileObject
);
1534 LockedForSync
= TRUE
;
1537 /* Clear File Object event */
1538 KeClearEvent(&FileObject
->Event
);
1539 FileObject
->LockOperation
= TRUE
;
1541 /* Allocate the IRP */
1542 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1543 if (!Irp
) return IopCleanupFailedIrp(FileObject
, Event
, NULL
);
1545 /* Set up the IRP */
1546 Irp
->RequestorMode
= PreviousMode
;
1547 Irp
->UserIosb
= IoStatusBlock
;
1548 Irp
->UserEvent
= Event
;
1549 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1550 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1551 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1552 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1554 /* Set up Stack Data */
1555 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1556 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
1557 StackPtr
->MinorFunction
= IRP_MN_LOCK
;
1558 StackPtr
->FileObject
= FileObject
;
1560 /* Allocate local buffer */
1561 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
1562 sizeof(LARGE_INTEGER
),
1566 /* Allocating failed, clean up and return failure */
1567 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1568 return STATUS_INSUFFICIENT_RESOURCES
;
1571 /* Set the length */
1572 *LocalLength
= CapturedLength
;
1573 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
1574 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
1576 /* Set Parameters */
1577 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
1578 StackPtr
->Parameters
.LockControl
.Key
= Key
;
1581 if (FailImmediately
) StackPtr
->Flags
= SL_FAIL_IMMEDIATELY
;
1582 if (ExclusiveLock
) StackPtr
->Flags
|= SL_EXCLUSIVE_LOCK
;
1584 /* Perform the call */
1585 return IopPerformSynchronousRequest(DeviceObject
,
1599 NtQueryDirectoryFile(IN HANDLE FileHandle
,
1600 IN HANDLE EventHandle OPTIONAL
,
1601 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1602 IN PVOID ApcContext OPTIONAL
,
1603 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1604 OUT PVOID FileInformation
,
1606 IN FILE_INFORMATION_CLASS FileInformationClass
,
1607 IN BOOLEAN ReturnSingleEntry
,
1608 IN PUNICODE_STRING FileName OPTIONAL
,
1609 IN BOOLEAN RestartScan
)
1612 PDEVICE_OBJECT DeviceObject
;
1613 PFILE_OBJECT FileObject
;
1614 PIO_STACK_LOCATION StackPtr
;
1615 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1617 BOOLEAN LockedForSynch
= FALSE
;
1618 PKEVENT Event
= NULL
;
1619 volatile PVOID AuxBuffer
= NULL
;
1621 UNICODE_STRING CapturedFileName
;
1622 PUNICODE_STRING SearchPattern
;
1624 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1626 /* Check if we came from user mode */
1627 if (PreviousMode
!= KernelMode
)
1629 /* Enter SEH for probing */
1632 /* Probe the I/O Status Block */
1633 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1635 /* Probe the file information */
1636 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1638 /* Check if we have a file name */
1642 CapturedFileName
= ProbeForReadUnicodeString(FileName
);
1643 if (CapturedFileName
.Length
)
1645 /* Probe its buffer */
1646 ProbeForRead(CapturedFileName
.Buffer
,
1647 CapturedFileName
.Length
,
1651 /* Allocate the auxiliary buffer */
1652 AuxBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1653 CapturedFileName
.Length
+
1654 sizeof(UNICODE_STRING
),
1656 RtlCopyMemory((PVOID
)((ULONG_PTR
)AuxBuffer
+
1657 sizeof(UNICODE_STRING
)),
1658 CapturedFileName
.Buffer
,
1659 CapturedFileName
.Length
);
1661 /* Setup the search pattern */
1662 SearchPattern
= (PUNICODE_STRING
)AuxBuffer
;
1663 SearchPattern
->Buffer
= (PWCHAR
)((ULONG_PTR
)AuxBuffer
+
1664 sizeof(UNICODE_STRING
));
1665 SearchPattern
->Length
= CapturedFileName
.Length
;
1666 SearchPattern
->MaximumLength
= CapturedFileName
.Length
;
1669 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1671 /* Free buffer and return the exception code */
1672 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1673 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1678 /* Get File Object */
1679 Status
= ObReferenceObjectByHandle(FileHandle
,
1680 FILE_LIST_DIRECTORY
,
1683 (PVOID
*)&FileObject
,
1685 if (!NT_SUCCESS(Status
))
1688 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1692 /* Check if we have an even handle */
1695 /* Get its pointer */
1696 Status
= ObReferenceObjectByHandle(EventHandle
,
1702 if (!NT_SUCCESS(Status
))
1705 ObDereferenceObject(FileObject
);
1710 KeClearEvent(Event
);
1713 /* Check if this is a file that was opened for Synch I/O */
1714 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1717 IopLockFileObject(FileObject
);
1719 /* Remember to unlock later */
1720 LockedForSynch
= TRUE
;
1723 /* Get the device object */
1724 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1726 /* Clear the File Object's event */
1727 KeClearEvent(&FileObject
->Event
);
1729 /* Allocate the IRP */
1730 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
1731 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventHandle
, AuxBuffer
);
1733 /* Set up the IRP */
1734 Irp
->RequestorMode
= PreviousMode
;
1735 Irp
->UserIosb
= IoStatusBlock
;
1736 Irp
->UserEvent
= Event
;
1737 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1738 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1739 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
1740 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
1741 Irp
->MdlAddress
= NULL
;
1742 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= AuxBuffer
;
1743 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
1745 /* Check if this is buffered I/O */
1746 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
1748 /* Allocate a buffer */
1749 Irp
->AssociatedIrp
.SystemBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1752 if (!Irp
->AssociatedIrp
.SystemBuffer
)
1754 /* Allocating failed, clean up and return the exception code */
1755 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1756 if (AuxBuffer
) ExFreePoolWithTag(AuxBuffer
, TAG_SYSB
);
1758 /* Return the exception code */
1759 return STATUS_INSUFFICIENT_RESOURCES
;
1762 /* Set the buffer and flags */
1763 Irp
->UserBuffer
= FileInformation
;
1764 Irp
->Flags
= (IRP_BUFFERED_IO
|
1765 IRP_DEALLOCATE_BUFFER
|
1766 IRP_INPUT_OPERATION
);
1768 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
1772 /* Allocate an MDL */
1773 Mdl
= IoAllocateMdl(FileInformation
, Length
, FALSE
, TRUE
, Irp
);
1774 if (!Mdl
) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
1775 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
1777 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1779 /* Allocating failed, clean up and return the exception code */
1780 IopCleanupAfterException(FileObject
, Irp
, Event
, NULL
);
1781 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1787 /* No allocation flags, and use the buffer directly */
1788 Irp
->UserBuffer
= FileInformation
;
1791 /* Set up Stack Data */
1792 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1793 StackPtr
->FileObject
= FileObject
;
1794 StackPtr
->MajorFunction
= IRP_MJ_DIRECTORY_CONTROL
;
1795 StackPtr
->MinorFunction
= IRP_MN_QUERY_DIRECTORY
;
1797 /* Set Parameters */
1798 StackPtr
->Parameters
.QueryDirectory
.FileInformationClass
=
1799 FileInformationClass
;
1800 StackPtr
->Parameters
.QueryDirectory
.FileName
= AuxBuffer
;
1801 StackPtr
->Parameters
.QueryDirectory
.FileIndex
= 0;
1802 StackPtr
->Parameters
.QueryDirectory
.Length
= Length
;
1803 StackPtr
->Flags
= 0;
1804 if (RestartScan
) StackPtr
->Flags
= SL_RESTART_SCAN
;
1805 if (ReturnSingleEntry
) StackPtr
->Flags
|= SL_RETURN_SINGLE_ENTRY
;
1807 /* Set deferred I/O */
1808 Irp
->Flags
|= IRP_DEFER_IO_COMPLETION
;
1810 /* Perform the call */
1811 return IopPerformSynchronousRequest(DeviceObject
,
1825 NtQueryEaFile(IN HANDLE FileHandle
,
1826 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1829 IN BOOLEAN ReturnSingleEntry
,
1830 IN PVOID EaList OPTIONAL
,
1831 IN ULONG EaListLength
,
1832 IN PULONG EaIndex OPTIONAL
,
1833 IN BOOLEAN RestartScan
)
1836 return STATUS_NOT_IMPLEMENTED
;
1844 NtQueryInformationFile(IN HANDLE FileHandle
,
1845 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1846 IN PVOID FileInformation
,
1848 IN FILE_INFORMATION_CLASS FileInformationClass
)
1850 OBJECT_HANDLE_INFORMATION HandleInformation
;
1851 PFILE_OBJECT FileObject
;
1854 PDEVICE_OBJECT DeviceObject
;
1855 PIO_STACK_LOCATION StackPtr
;
1856 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1857 PKEVENT Event
= NULL
;
1858 BOOLEAN LocalEvent
= FALSE
;
1859 PKNORMAL_ROUTINE NormalRoutine
;
1860 PVOID NormalContext
;
1862 IO_STATUS_BLOCK KernelIosb
;
1864 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
1866 /* Check if we're called from user mode */
1867 if (PreviousMode
!= KernelMode
)
1869 /* Validate the information class */
1870 if ((FileInformationClass
>= FileMaximumInformation
) ||
1871 !(IopQueryOperationLength
[FileInformationClass
]))
1874 return STATUS_INVALID_INFO_CLASS
;
1877 /* Validate the length */
1878 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1880 /* Invalid length */
1881 return STATUS_INFO_LENGTH_MISMATCH
;
1884 /* Enter SEH for probing */
1887 /* Probe the I/O Status block */
1888 ProbeForWriteIoStatusBlock(IoStatusBlock
);
1890 /* Probe the information */
1891 ProbeForWrite(FileInformation
, Length
, sizeof(ULONG
));
1893 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1895 /* Return the exception code */
1896 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1902 /* Validate the information class */
1903 if ((FileInformationClass
>= FileMaximumInformation
) ||
1904 !(IopQueryOperationLength
[FileInformationClass
]))
1907 return STATUS_INVALID_INFO_CLASS
;
1910 /* Validate the length */
1911 if (Length
< IopQueryOperationLength
[FileInformationClass
])
1913 /* Invalid length */
1914 return STATUS_INFO_LENGTH_MISMATCH
;
1918 /* Reference the Handle */
1919 Status
= ObReferenceObjectByHandle(FileHandle
,
1920 IopQueryOperationAccess
1921 [FileInformationClass
],
1924 (PVOID
*)&FileObject
,
1925 &HandleInformation
);
1926 if (!NT_SUCCESS(Status
)) return Status
;
1928 /* Check if this is a direct open or not */
1929 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
1931 /* Get the device object */
1932 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
1936 /* Get the device object */
1937 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1940 /* Check if this is a file that was opened for Synch I/O */
1941 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
1944 IopLockFileObject(FileObject
);
1946 /* Check if the caller just wants the position */
1947 if (FileInformationClass
== FilePositionInformation
)
1949 /* Protect write in SEH */
1952 /* Write the offset */
1953 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
1954 CurrentByteOffset
= FileObject
->CurrentByteOffset
;
1956 /* Fill out the I/O Status Block */
1957 IoStatusBlock
->Information
= sizeof(FILE_POSITION_INFORMATION
);
1958 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
1960 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1962 /* Get the exception code */
1963 Status
= _SEH2_GetExceptionCode();
1967 /* Release the file lock, dereference the file and return */
1968 IopUnlockFileObject(FileObject
);
1969 ObDereferenceObject(FileObject
);
1975 /* Use local event */
1976 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
1979 ObDereferenceObject(FileObject
);
1980 return STATUS_INSUFFICIENT_RESOURCES
;
1982 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
1986 /* Clear the File Object event */
1987 KeClearEvent(&FileObject
->Event
);
1989 /* Allocate the IRP */
1990 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
1991 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
1994 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1995 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1996 Irp
->RequestorMode
= PreviousMode
;
1997 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
1998 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
1999 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2000 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2001 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2002 Irp
->MdlAddress
= NULL
;
2003 Irp
->UserBuffer
= FileInformation
;
2005 /* Set the Stack Data */
2006 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2007 StackPtr
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
2008 StackPtr
->FileObject
= FileObject
;
2013 /* Allocate a buffer */
2014 Irp
->AssociatedIrp
.SystemBuffer
=
2015 ExAllocatePoolWithTag(NonPagedPool
,
2019 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2021 /* Allocating failed, clean up and return the exception code */
2022 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2023 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2028 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2029 IRP_DEALLOCATE_BUFFER
|
2030 IRP_INPUT_OPERATION
|
2031 IRP_DEFER_IO_COMPLETION
);
2033 /* Set the Parameters */
2034 StackPtr
->Parameters
.QueryFile
.FileInformationClass
= FileInformationClass
;
2035 StackPtr
->Parameters
.QueryFile
.Length
= Length
;
2038 IopQueueIrpToThread(Irp
);
2040 /* Update operation counts */
2041 IopUpdateOperationCount(IopOtherTransfer
);
2043 /* Call the Driver */
2044 Status
= IoCallDriver(DeviceObject
, Irp
);
2045 if (Status
== STATUS_PENDING
)
2047 /* Check if this was async I/O */
2050 /* Then to a non-alertable wait */
2051 Status
= KeWaitForSingleObject(Event
,
2056 if (Status
== STATUS_USER_APC
)
2058 /* Abort the request */
2059 IopAbortInterruptedIrp(Event
, Irp
);
2062 /* Set the final status */
2063 Status
= KernelIosb
.Status
;
2065 /* Enter SEH to write the IOSB back */
2068 /* Write it back to the caller */
2069 *IoStatusBlock
= KernelIosb
;
2071 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2073 /* Get the exception code */
2074 Status
= _SEH2_GetExceptionCode();
2078 /* Free the event */
2079 ExFreePoolWithTag(Event
, TAG_IO
);
2083 /* Wait for the IRP */
2084 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2087 (FileObject
->Flags
&
2088 FO_ALERTABLE_IO
) != 0,
2090 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2092 /* Abort the request */
2093 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2096 /* Set the final status */
2097 Status
= FileObject
->FinalStatus
;
2099 /* Release the file lock */
2100 IopUnlockFileObject(FileObject
);
2105 /* Free the event if we had one */
2108 /* Clear it in the IRP for completion */
2109 Irp
->UserEvent
= NULL
;
2110 ExFreePoolWithTag(Event
, TAG_IO
);
2113 /* Set the caller IOSB */
2114 Irp
->UserIosb
= IoStatusBlock
;
2116 /* The IRP wasn't completed, complete it ourselves */
2117 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2118 IopCompleteRequest(&Irp
->Tail
.Apc
,
2121 (PVOID
*)&FileObject
,
2123 KeLowerIrql(OldIrql
);
2125 /* Release the file object if we had locked it*/
2126 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2129 /* Return the Status */
2138 NtQueryQuotaInformationFile(IN HANDLE FileHandle
,
2139 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2142 IN BOOLEAN ReturnSingleEntry
,
2143 IN PVOID SidList OPTIONAL
,
2144 IN ULONG SidListLength
,
2145 IN PSID StartSid OPTIONAL
,
2146 IN BOOLEAN RestartScan
)
2149 return STATUS_NOT_IMPLEMENTED
;
2157 NtReadFile(IN HANDLE FileHandle
,
2158 IN HANDLE Event OPTIONAL
,
2159 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
2160 IN PVOID ApcContext OPTIONAL
,
2161 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2164 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
2165 IN PULONG Key OPTIONAL
)
2168 PFILE_OBJECT FileObject
;
2170 PDEVICE_OBJECT DeviceObject
;
2171 PIO_STACK_LOCATION StackPtr
;
2172 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2173 PKEVENT EventObject
= NULL
;
2174 LARGE_INTEGER CapturedByteOffset
;
2175 ULONG CapturedKey
= 0;
2176 BOOLEAN Synchronous
= FALSE
;
2179 CapturedByteOffset
.QuadPart
= 0;
2180 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2182 /* Validate User-Mode Buffers */
2183 if (PreviousMode
!= KernelMode
)
2187 /* Probe the status block */
2188 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2190 /* Probe the read buffer */
2191 ProbeForWrite(Buffer
, Length
, 1);
2193 /* Check if we got a byte offset */
2196 /* Capture and probe it */
2197 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2200 /* Capture and probe the key */
2201 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2203 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2205 /* Return the exception code */
2206 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2212 /* Kernel mode: capture directly */
2213 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2214 if (Key
) CapturedKey
= *Key
;
2217 /* Get File Object */
2218 Status
= ObReferenceObjectByHandle(FileHandle
,
2222 (PVOID
*)&FileObject
,
2224 if (!NT_SUCCESS(Status
)) return Status
;
2226 /* Check for event */
2230 Status
= ObReferenceObjectByHandle(Event
,
2234 (PVOID
*)&EventObject
,
2236 if (!NT_SUCCESS(Status
))
2239 ObDereferenceObject(FileObject
);
2243 /* Otherwise reset the event */
2244 KeClearEvent(EventObject
);
2247 /* Check if we should use Sync IO or not */
2248 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2250 /* Lock the file object */
2251 IopLockFileObject(FileObject
);
2253 /* Check if we don't have a byte offset avilable */
2254 if (!(ByteOffset
) ||
2255 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2256 (CapturedByteOffset
.u
.HighPart
== -1)))
2258 /* Use the Current Byte Offset instead */
2259 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2262 /* Remember we are sync */
2265 else if (!(ByteOffset
) &&
2266 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2268 /* Otherwise, this was async I/O without a byte offset, so fail */
2269 if (EventObject
) ObDereferenceObject(EventObject
);
2270 ObDereferenceObject(FileObject
);
2271 return STATUS_INVALID_PARAMETER
;
2274 /* Get the device object */
2275 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2277 /* Clear the File Object's event */
2278 KeClearEvent(&FileObject
->Event
);
2280 /* Allocate the IRP */
2281 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2282 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
2285 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2286 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2287 Irp
->RequestorMode
= PreviousMode
;
2288 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2289 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2290 Irp
->UserIosb
= IoStatusBlock
;
2291 Irp
->UserEvent
= EventObject
;
2292 Irp
->PendingReturned
= FALSE
;
2293 Irp
->Cancel
= FALSE
;
2294 Irp
->CancelRoutine
= NULL
;
2295 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2296 Irp
->MdlAddress
= NULL
;
2298 /* Set the Stack Data */
2299 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2300 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2301 StackPtr
->FileObject
= FileObject
;
2302 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2303 StackPtr
->Parameters
.Read
.Length
= Length
;
2304 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2306 /* Check if this is buffered I/O */
2307 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2309 /* Check if we have a buffer length */
2315 /* Allocate a buffer */
2316 Irp
->AssociatedIrp
.SystemBuffer
=
2317 ExAllocatePoolWithTag(NonPagedPool
,
2321 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2323 /* Allocating failed, clean up and return the exception code */
2324 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2325 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2329 /* Set the buffer and flags */
2330 Irp
->UserBuffer
= Buffer
;
2331 Irp
->Flags
= (IRP_BUFFERED_IO
|
2332 IRP_DEALLOCATE_BUFFER
|
2333 IRP_INPUT_OPERATION
);
2337 /* Not reading anything */
2338 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2341 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2343 /* Check if we have a buffer length */
2348 /* Allocate an MDL */
2349 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2350 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2352 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2354 /* Allocating failed, clean up and return the exception code */
2355 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2356 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2362 /* No allocation flags */
2367 /* No allocation flags, and use the buffer directly */
2369 Irp
->UserBuffer
= Buffer
;
2372 /* Now set the deferred read flags */
2373 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2375 /* FIXME: VFAT SUCKS */
2376 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2379 /* Perform the call */
2380 return IopPerformSynchronousRequest(DeviceObject
,
2394 NtReadFileScatter(IN HANDLE FileHandle
,
2395 IN HANDLE Event OPTIONAL
,
2396 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2397 IN PVOID UserApcContext OPTIONAL
,
2398 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2399 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2400 IN ULONG BufferLength
,
2401 IN PLARGE_INTEGER ByteOffset
,
2402 IN PULONG Key OPTIONAL
)
2405 return STATUS_NOT_IMPLEMENTED
;
2413 NtSetEaFile(IN HANDLE FileHandle
,
2414 IN PIO_STATUS_BLOCK IoStatusBlock
,
2416 IN ULONG EaBufferSize
)
2419 return STATUS_NOT_IMPLEMENTED
;
2427 NtSetInformationFile(IN HANDLE FileHandle
,
2428 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2429 IN PVOID FileInformation
,
2431 IN FILE_INFORMATION_CLASS FileInformationClass
)
2433 PFILE_OBJECT FileObject
;
2436 PDEVICE_OBJECT DeviceObject
;
2437 PIO_STACK_LOCATION StackPtr
;
2438 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2439 PKEVENT Event
= NULL
;
2440 BOOLEAN LocalEvent
= FALSE
;
2441 PKNORMAL_ROUTINE NormalRoutine
;
2442 PVOID NormalContext
;
2444 IO_STATUS_BLOCK KernelIosb
;
2446 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2447 PIO_COMPLETION_CONTEXT Context
;
2448 PFILE_RENAME_INFORMATION RenameInfo
;
2449 HANDLE TargetHandle
= NULL
;
2451 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2453 /* Check if we're called from user mode */
2454 if (PreviousMode
!= KernelMode
)
2456 /* Validate the information class */
2457 if ((FileInformationClass
>= FileMaximumInformation
) ||
2458 !(IopSetOperationLength
[FileInformationClass
]))
2461 return STATUS_INVALID_INFO_CLASS
;
2464 /* Validate the length */
2465 if (Length
< IopSetOperationLength
[FileInformationClass
])
2467 /* Invalid length */
2468 return STATUS_INFO_LENGTH_MISMATCH
;
2471 /* Enter SEH for probing */
2474 /* Probe the I/O Status block */
2475 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2477 /* Probe the information */
2478 ProbeForRead(FileInformation
,
2480 (Length
== sizeof(BOOLEAN
)) ?
2481 sizeof(BOOLEAN
) : sizeof(ULONG
));
2483 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2485 /* Return the exception code */
2486 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2492 /* Validate the information class */
2493 if ((FileInformationClass
>= FileMaximumInformation
) ||
2494 !(IopSetOperationLength
[FileInformationClass
]))
2497 return STATUS_INVALID_INFO_CLASS
;
2500 /* Validate the length */
2501 if (Length
< IopSetOperationLength
[FileInformationClass
])
2503 /* Invalid length */
2504 return STATUS_INFO_LENGTH_MISMATCH
;
2508 /* Reference the Handle */
2509 Status
= ObReferenceObjectByHandle(FileHandle
,
2510 IopSetOperationAccess
2511 [FileInformationClass
],
2514 (PVOID
*)&FileObject
,
2516 if (!NT_SUCCESS(Status
)) return Status
;
2518 /* Check if this is a direct open or not */
2519 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2521 /* Get the device object */
2522 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2526 /* Get the device object */
2527 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2530 /* Check if this is a file that was opened for Synch I/O */
2531 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2534 IopLockFileObject(FileObject
);
2536 /* Check if the caller just wants the position */
2537 if (FileInformationClass
== FilePositionInformation
)
2539 /* Protect write in SEH */
2542 /* Write the offset */
2543 FileObject
->CurrentByteOffset
=
2544 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2547 /* Fill out the I/O Status Block */
2548 IoStatusBlock
->Information
= 0;
2549 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2551 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2553 /* Get the exception code */
2554 Status
= _SEH2_GetExceptionCode();
2558 /* Update transfer count */
2559 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2561 /* Release the file lock, dereference the file and return */
2562 IopUnlockFileObject(FileObject
);
2563 ObDereferenceObject(FileObject
);
2569 /* Use local event */
2570 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2573 ObDereferenceObject(FileObject
);
2574 return STATUS_INSUFFICIENT_RESOURCES
;
2577 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2581 /* Clear the File Object event */
2582 KeClearEvent(&FileObject
->Event
);
2584 /* Allocate the IRP */
2585 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2586 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2589 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2590 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2591 Irp
->RequestorMode
= PreviousMode
;
2592 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2593 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2594 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2595 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2596 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2597 Irp
->MdlAddress
= NULL
;
2598 Irp
->UserBuffer
= FileInformation
;
2600 /* Set the Stack Data */
2601 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2602 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2603 StackPtr
->FileObject
= FileObject
;
2608 /* Allocate a buffer */
2609 Irp
->AssociatedIrp
.SystemBuffer
=
2610 ExAllocatePoolWithTag(NonPagedPool
,
2614 /* Copy the data into it */
2615 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2619 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2621 /* Allocating failed, clean up and return the exception code */
2622 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2623 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2628 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2629 IRP_DEALLOCATE_BUFFER
|
2630 IRP_DEFER_IO_COMPLETION
);
2632 /* Set the Parameters */
2633 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2634 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2637 IopQueueIrpToThread(Irp
);
2639 /* Update operation counts */
2640 IopUpdateOperationCount(IopOtherTransfer
);
2642 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2643 /* Handle IO Completion Port quickly */
2644 if (FileInformationClass
== FileCompletionInformation
)
2646 /* Check if the file object already has a completion port */
2647 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2648 (FileObject
->CompletionContext
))
2651 Status
= STATUS_INVALID_PARAMETER
;
2655 /* Reference the Port */
2656 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2657 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2658 IO_COMPLETION_MODIFY_STATE
,
2663 if (NT_SUCCESS(Status
))
2665 /* Allocate the Context */
2666 Context
= ExAllocatePoolWithTag(PagedPool
,
2667 sizeof(IO_COMPLETION_CONTEXT
),
2672 Context
->Key
= CompletionInfo
->Key
;
2673 Context
->Port
= Queue
;
2674 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
2680 * Someone else set the completion port in the
2681 * meanwhile, so dereference the port and fail.
2683 ExFreePoolWithTag(Context
, IOC_TAG
);
2684 ObDereferenceObject(Queue
);
2685 Status
= STATUS_INVALID_PARAMETER
;
2690 /* Dereference the Port now */
2691 ObDereferenceObject(Queue
);
2692 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2697 /* Set the IRP Status */
2698 Irp
->IoStatus
.Status
= Status
;
2699 Irp
->IoStatus
.Information
= 0;
2701 else if (FileInformationClass
== FileRenameInformation
||
2702 FileInformationClass
== FileLinkInformation
||
2703 FileInformationClass
== FileMoveClusterInformation
)
2705 /* Get associated information */
2706 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2711 * -> sizes are valid
2713 if (RenameInfo
->FileNameLength
!= 0 &&
2714 !(RenameInfo
->FileNameLength
& 1) &&
2715 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
2717 /* Properly set information received */
2718 if (FileInformationClass
== FileMoveClusterInformation
)
2720 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
2724 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
2727 /* If we got fully path OR relative target, attempt a parent directory open */
2728 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
2730 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
2731 if (!NT_SUCCESS(Status
))
2733 Irp
->IoStatus
.Status
= Status
;
2737 /* Call the Driver */
2738 Status
= IoCallDriver(DeviceObject
, Irp
);
2743 /* Call the Driver */
2744 Status
= IoCallDriver(DeviceObject
, Irp
);
2749 Status
= STATUS_INVALID_PARAMETER
;
2750 Irp
->IoStatus
.Status
= Status
;
2755 /* Call the Driver */
2756 Status
= IoCallDriver(DeviceObject
, Irp
);
2759 /* Check if we're waiting for the IRP to complete */
2760 if (Status
== STATUS_PENDING
)
2762 /* Check if this was async I/O */
2765 /* Then to a non-alertable wait */
2766 Status
= KeWaitForSingleObject(Event
,
2771 if (Status
== STATUS_USER_APC
)
2773 /* Abort the request */
2774 IopAbortInterruptedIrp(Event
, Irp
);
2777 /* Set the final status */
2778 Status
= KernelIosb
.Status
;
2780 /* Enter SEH to write the IOSB back */
2783 /* Write it back to the caller */
2784 *IoStatusBlock
= KernelIosb
;
2786 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2788 /* Get the exception code */
2789 Status
= _SEH2_GetExceptionCode();
2793 /* Free the event */
2794 ExFreePoolWithTag(Event
, TAG_IO
);
2798 /* Wait for the IRP */
2799 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2802 (FileObject
->Flags
&
2803 FO_ALERTABLE_IO
) != 0,
2805 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2807 /* Abort the request */
2808 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2811 /* Set the final status */
2812 Status
= FileObject
->FinalStatus
;
2814 /* Release the file lock */
2815 IopUnlockFileObject(FileObject
);
2820 /* Free the event if we had one */
2823 /* Clear it in the IRP for completion */
2824 Irp
->UserEvent
= NULL
;
2825 ExFreePoolWithTag(Event
, TAG_IO
);
2828 /* Set the caller IOSB */
2829 Irp
->UserIosb
= IoStatusBlock
;
2831 /* The IRP wasn't completed, complete it ourselves */
2832 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2833 IopCompleteRequest(&Irp
->Tail
.Apc
,
2836 (PVOID
*)&FileObject
,
2838 KeLowerIrql(OldIrql
);
2840 /* Release the file object if we had locked it*/
2841 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2844 if (TargetHandle
!= NULL
)
2846 ObCloseHandle(TargetHandle
, KernelMode
);
2849 /* Return the Status */
2858 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
2859 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2861 IN ULONG BufferLength
)
2864 return STATUS_NOT_IMPLEMENTED
;
2872 NtUnlockFile(IN HANDLE FileHandle
,
2873 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2874 IN PLARGE_INTEGER ByteOffset
,
2875 IN PLARGE_INTEGER Length
,
2876 IN ULONG Key OPTIONAL
)
2878 PFILE_OBJECT FileObject
;
2879 PLARGE_INTEGER LocalLength
= NULL
;
2881 PIO_STACK_LOCATION StackPtr
;
2882 PDEVICE_OBJECT DeviceObject
;
2883 PKEVENT Event
= NULL
;
2884 BOOLEAN LocalEvent
= FALSE
;
2885 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2886 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
2888 OBJECT_HANDLE_INFORMATION HandleInformation
;
2889 IO_STATUS_BLOCK KernelIosb
;
2891 CapturedByteOffset
.QuadPart
= 0;
2892 CapturedLength
.QuadPart
= 0;
2893 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2895 /* Get File Object */
2896 Status
= ObReferenceObjectByHandle(FileHandle
,
2900 (PVOID
*)&FileObject
,
2901 &HandleInformation
);
2902 if (!NT_SUCCESS(Status
)) return Status
;
2904 /* Check if we're called from user mode */
2905 if (PreviousMode
!= KernelMode
)
2907 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
2908 if (!(HandleInformation
.GrantedAccess
&
2909 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
2911 ObDereferenceObject(FileObject
);
2912 return STATUS_ACCESS_DENIED
;
2915 /* Enter SEH for probing */
2918 /* Probe the I/O Status block */
2919 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2921 /* Probe and capture the large integers */
2922 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2923 CapturedLength
= ProbeForReadLargeInteger(Length
);
2925 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2927 /* Dereference the object and return exception code */
2928 ObDereferenceObject(FileObject
);
2929 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2935 /* Otherwise, capture them directly */
2936 CapturedByteOffset
= *ByteOffset
;
2937 CapturedLength
= *Length
;
2940 /* Check if this is a direct open or not */
2941 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2943 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2947 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2950 /* Check if we should use Sync IO or not */
2951 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2954 IopLockFileObject(FileObject
);
2958 /* Use local event */
2959 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2962 ObDereferenceObject(FileObject
);
2963 return STATUS_INSUFFICIENT_RESOURCES
;
2965 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2969 /* Clear File Object event */
2970 KeClearEvent(&FileObject
->Event
);
2972 /* Allocate the IRP */
2973 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2974 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2976 /* Set up the IRP */
2977 Irp
->RequestorMode
= PreviousMode
;
2978 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2979 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2980 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2981 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2982 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2983 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2985 /* Set up Stack Data */
2986 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2987 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
2988 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
2989 StackPtr
->FileObject
= FileObject
;
2994 /* Allocate a buffer */
2995 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
2996 sizeof(LARGE_INTEGER
),
2999 /* Set the length */
3000 *LocalLength
= CapturedLength
;
3001 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3002 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3004 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3006 /* Allocating failed, clean up and return the exception code */
3007 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3008 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3010 /* Return the exception code */
3011 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3015 /* Set Parameters */
3016 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3017 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3019 /* Call the Driver */
3020 Status
= IopPerformSynchronousRequest(DeviceObject
,
3028 /* Check if this was async I/O */
3031 /* It was, finalize this request */
3032 Status
= IopFinalizeAsynchronousIo(Status
,
3049 NtWriteFile(IN HANDLE FileHandle
,
3050 IN HANDLE Event OPTIONAL
,
3051 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3052 IN PVOID ApcContext OPTIONAL
,
3053 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3056 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3057 IN PULONG Key OPTIONAL
)
3060 PFILE_OBJECT FileObject
;
3062 PDEVICE_OBJECT DeviceObject
;
3063 PIO_STACK_LOCATION StackPtr
;
3064 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3065 PKEVENT EventObject
= NULL
;
3066 LARGE_INTEGER CapturedByteOffset
;
3067 ULONG CapturedKey
= 0;
3068 BOOLEAN Synchronous
= FALSE
;
3070 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3072 CapturedByteOffset
.QuadPart
= 0;
3073 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3075 /* Get File Object */
3076 Status
= ObReferenceObjectByHandle(FileHandle
,
3080 (PVOID
*)&FileObject
,
3082 if (!NT_SUCCESS(Status
)) return Status
;
3084 /* Validate User-Mode Buffers */
3085 if (PreviousMode
!= KernelMode
)
3090 * Check if the handle has either FILE_WRITE_DATA or
3091 * FILE_APPEND_DATA granted. However, if this is a named pipe,
3092 * make sure we don't ask for FILE_APPEND_DATA as it interferes
3093 * with the FILE_CREATE_PIPE_INSTANCE access right!
3095 if (!(ObjectHandleInfo
.GrantedAccess
&
3096 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
3097 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
3100 ObDereferenceObject(FileObject
);
3101 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
3104 /* Probe the status block */
3105 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3107 /* Probe the read buffer */
3108 ProbeForRead(Buffer
, Length
, 1);
3110 /* Check if we got a byte offset */
3113 /* Capture and probe it */
3114 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3117 /* Capture and probe the key */
3118 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3120 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3122 /* Return the exception code */
3123 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3129 /* Kernel mode: capture directly */
3130 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3131 if (Key
) CapturedKey
= *Key
;
3134 /* Check if this is an append operation */
3135 if ((ObjectHandleInfo
.GrantedAccess
&
3136 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3138 /* Give the drivers something to understand */
3139 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3140 CapturedByteOffset
.u
.HighPart
= -1;
3143 /* Check for event */
3147 Status
= ObReferenceObjectByHandle(Event
,
3151 (PVOID
*)&EventObject
,
3153 if (!NT_SUCCESS(Status
))
3156 ObDereferenceObject(FileObject
);
3160 /* Otherwise reset the event */
3161 KeClearEvent(EventObject
);
3164 /* Check if we should use Sync IO or not */
3165 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3167 /* Lock the file object */
3168 IopLockFileObject(FileObject
);
3170 /* Check if we don't have a byte offset avilable */
3171 if (!(ByteOffset
) ||
3172 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3173 (CapturedByteOffset
.u
.HighPart
== -1)))
3175 /* Use the Current Byte Offset instead */
3176 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3179 /* Remember we are sync */
3182 else if (!(ByteOffset
) &&
3183 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3185 /* Otherwise, this was async I/O without a byte offset, so fail */
3186 if (EventObject
) ObDereferenceObject(EventObject
);
3187 ObDereferenceObject(FileObject
);
3188 return STATUS_INVALID_PARAMETER
;
3191 /* Get the device object */
3192 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3194 /* Clear the File Object's event */
3195 KeClearEvent(&FileObject
->Event
);
3197 /* Allocate the IRP */
3198 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3199 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, NULL
);
3202 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3203 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3204 Irp
->RequestorMode
= PreviousMode
;
3205 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3206 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3207 Irp
->UserIosb
= IoStatusBlock
;
3208 Irp
->UserEvent
= EventObject
;
3209 Irp
->PendingReturned
= FALSE
;
3210 Irp
->Cancel
= FALSE
;
3211 Irp
->CancelRoutine
= NULL
;
3212 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3213 Irp
->MdlAddress
= NULL
;
3215 /* Set the Stack Data */
3216 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3217 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3218 StackPtr
->FileObject
= FileObject
;
3219 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3220 SL_WRITE_THROUGH
: 0;
3221 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3222 StackPtr
->Parameters
.Write
.Length
= Length
;
3223 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3225 /* Check if this is buffered I/O */
3226 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3228 /* Check if we have a buffer length */
3234 /* Allocate a buffer */
3235 Irp
->AssociatedIrp
.SystemBuffer
=
3236 ExAllocatePoolWithTag(NonPagedPool
,
3240 /* Copy the data into it */
3241 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3243 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3245 /* Allocating failed, clean up and return the exception code */
3246 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3247 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3252 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3256 /* Not writing anything */
3257 Irp
->Flags
= IRP_BUFFERED_IO
;
3260 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3262 /* Check if we have a buffer length */
3267 /* Allocate an MDL */
3268 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3269 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3271 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3273 /* Allocating failed, clean up and return the exception code */
3274 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3275 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3280 /* No allocation flags */
3285 /* No allocation flags, and use the buffer directly */
3287 Irp
->UserBuffer
= Buffer
;
3290 /* Now set the deferred read flags */
3291 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3293 /* FIXME: VFAT SUCKS */
3294 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3297 /* Perform the call */
3298 return IopPerformSynchronousRequest(DeviceObject
,
3309 NtWriteFileGather(IN HANDLE FileHandle
,
3310 IN HANDLE Event OPTIONAL
,
3311 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3312 IN PVOID UserApcContext OPTIONAL
,
3313 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3314 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3315 IN ULONG BufferLength
,
3316 IN PLARGE_INTEGER ByteOffset
,
3317 IN PULONG Key OPTIONAL
)
3320 return STATUS_NOT_IMPLEMENTED
;
3328 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3329 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3330 OUT PVOID FsInformation
,
3332 IN FS_INFORMATION_CLASS FsInformationClass
)
3334 PFILE_OBJECT FileObject
;
3336 PIO_STACK_LOCATION StackPtr
;
3337 PDEVICE_OBJECT DeviceObject
;
3338 PKEVENT Event
= NULL
;
3339 BOOLEAN LocalEvent
= FALSE
;
3340 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3342 IO_STATUS_BLOCK KernelIosb
;
3344 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3346 /* Check if we're called from user mode */
3347 if (PreviousMode
!= KernelMode
)
3349 /* Validate the information class */
3350 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3351 !(IopQueryFsOperationLength
[FsInformationClass
]))
3354 return STATUS_INVALID_INFO_CLASS
;
3357 /* Validate the length */
3358 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3360 /* Invalid length */
3361 return STATUS_INFO_LENGTH_MISMATCH
;
3364 /* Enter SEH for probing */
3367 /* Probe the I/O Status block */
3368 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3370 /* Probe the information */
3371 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3373 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3375 /* Return the exception code */
3376 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3381 /* Get File Object */
3382 Status
= ObReferenceObjectByHandle(FileHandle
,
3383 IopQueryFsOperationAccess
3384 [FsInformationClass
],
3387 (PVOID
*)&FileObject
,
3389 if (!NT_SUCCESS(Status
)) return Status
;
3391 /* Check if we should use Sync IO or not */
3392 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3395 IopLockFileObject(FileObject
);
3399 /* Use local event */
3400 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3403 ObDereferenceObject(FileObject
);
3404 return STATUS_INSUFFICIENT_RESOURCES
;
3406 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3410 /* Get the device object */
3411 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3413 /* Clear File Object event */
3414 KeClearEvent(&FileObject
->Event
);
3416 /* Allocate the IRP */
3417 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3418 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3420 /* Set up the IRP */
3421 Irp
->RequestorMode
= PreviousMode
;
3422 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3423 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3424 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3425 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3426 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3427 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3428 Irp
->UserBuffer
= FsInformation
;
3429 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3430 Irp
->MdlAddress
= NULL
;
3432 /* Set up Stack Data */
3433 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3434 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3435 StackPtr
->FileObject
= FileObject
;
3440 /* Allocate a buffer */
3441 Irp
->AssociatedIrp
.SystemBuffer
=
3442 ExAllocatePoolWithTag(NonPagedPool
,
3446 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3448 /* Allocating failed, clean up and return the exception code */
3449 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3450 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3454 /* Set the flags for this buffered + deferred I/O */
3455 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3456 IRP_DEALLOCATE_BUFFER
|
3457 IRP_INPUT_OPERATION
|
3458 IRP_DEFER_IO_COMPLETION
);
3460 /* Set Parameters */
3461 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3462 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3464 /* Call the Driver */
3465 Status
= IopPerformSynchronousRequest(DeviceObject
,
3473 /* Check if this was async I/O */
3476 /* It was, finalize this request */
3477 Status
= IopFinalizeAsynchronousIo(Status
,
3494 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3495 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3496 IN PVOID FsInformation
,
3498 IN FS_INFORMATION_CLASS FsInformationClass
)
3500 PFILE_OBJECT FileObject
;
3502 PIO_STACK_LOCATION StackPtr
;
3503 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3504 PKEVENT Event
= NULL
;
3505 BOOLEAN LocalEvent
= FALSE
;
3506 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3508 IO_STATUS_BLOCK KernelIosb
;
3509 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3511 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3513 /* Check if we're called from user mode */
3514 if (PreviousMode
!= KernelMode
)
3516 /* Validate the information class */
3517 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3518 !(IopSetFsOperationLength
[FsInformationClass
]))
3521 return STATUS_INVALID_INFO_CLASS
;
3524 /* Validate the length */
3525 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3527 /* Invalid length */
3528 return STATUS_INFO_LENGTH_MISMATCH
;
3531 /* Enter SEH for probing */
3534 /* Probe the I/O Status block */
3535 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3537 /* Probe the information */
3538 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3540 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3542 /* Return the exception code */
3543 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3548 /* Get File Object */
3549 Status
= ObReferenceObjectByHandle(FileHandle
,
3550 IopSetFsOperationAccess
3551 [FsInformationClass
],
3554 (PVOID
*)&FileObject
,
3556 if (!NT_SUCCESS(Status
)) return Status
;
3558 /* Get target device for notification */
3559 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
3560 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
3562 /* Check if we should use Sync IO or not */
3563 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3566 IopLockFileObject(FileObject
);
3570 /* Use local event */
3571 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3574 ObDereferenceObject(FileObject
);
3575 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3576 return STATUS_INSUFFICIENT_RESOURCES
;
3578 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3582 /* Get the device object */
3583 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3585 /* Clear File Object event */
3586 KeClearEvent(&FileObject
->Event
);
3588 /* Allocate the IRP */
3589 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3592 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3593 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3596 /* Set up the IRP */
3597 Irp
->RequestorMode
= PreviousMode
;
3598 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3599 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3600 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3601 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3602 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3603 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3604 Irp
->UserBuffer
= FsInformation
;
3605 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3606 Irp
->MdlAddress
= NULL
;
3608 /* Set up Stack Data */
3609 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3610 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3611 StackPtr
->FileObject
= FileObject
;
3616 /* Allocate a buffer */
3617 Irp
->AssociatedIrp
.SystemBuffer
=
3618 ExAllocatePoolWithTag(NonPagedPool
,
3622 /* Copy the data into it */
3623 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3625 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3627 /* Allocating failed, clean up and return the exception code */
3628 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3629 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3630 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3634 /* Set the flags for this buffered + deferred I/O */
3635 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3637 /* Set Parameters */
3638 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3639 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3641 /* Call the Driver */
3642 Status
= IopPerformSynchronousRequest(DeviceObject
,
3650 /* Check if this was async I/O */
3653 /* It was, finalize this request */
3654 Status
= IopFinalizeAsynchronousIo(Status
,
3662 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
3664 /* Time to report change */
3665 NotificationStructure
.Version
= 1;
3666 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
3667 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
3668 NotificationStructure
.FileObject
= NULL
;
3669 NotificationStructure
.NameBufferOffset
= - 1;
3670 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
3682 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3685 return STATUS_NOT_IMPLEMENTED
;
3693 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3696 return STATUS_NOT_IMPLEMENTED
;