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
, EventObject
, 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
;
2258 PFAST_IO_DISPATCH FastIoDispatch
;
2259 IO_STATUS_BLOCK KernelIosb
;
2263 CapturedByteOffset
.QuadPart
= 0;
2264 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2266 /* Validate User-Mode Buffers */
2267 if (PreviousMode
!= KernelMode
)
2271 /* Probe the status block */
2272 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2274 /* Probe the read buffer */
2275 ProbeForWrite(Buffer
, Length
, 1);
2277 /* Check if we got a byte offset */
2280 /* Capture and probe it */
2281 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
2284 /* Capture and probe the key */
2285 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
2287 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2289 /* Return the exception code */
2290 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2296 /* Kernel mode: capture directly */
2297 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
2298 if (Key
) CapturedKey
= *Key
;
2301 /* Get File Object */
2302 Status
= ObReferenceObjectByHandle(FileHandle
,
2306 (PVOID
*)&FileObject
,
2308 if (!NT_SUCCESS(Status
)) return Status
;
2310 /* Check for event */
2314 Status
= ObReferenceObjectByHandle(Event
,
2318 (PVOID
*)&EventObject
,
2320 if (!NT_SUCCESS(Status
))
2323 ObDereferenceObject(FileObject
);
2327 /* Otherwise reset the event */
2328 KeClearEvent(EventObject
);
2331 /* Get the device object */
2332 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2334 /* Check if we should use Sync IO or not */
2335 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2337 /* Lock the file object */
2338 IopLockFileObject(FileObject
);
2340 /* Check if we don't have a byte offset available */
2341 if (!(ByteOffset
) ||
2342 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
2343 (CapturedByteOffset
.u
.HighPart
== -1)))
2345 /* Use the Current Byte Offset instead */
2346 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
2349 /* If the file is cached, try fast I/O */
2350 if (FileObject
->PrivateCacheMap
)
2352 /* Perform fast write */
2353 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
2354 Success
= FastIoDispatch
->FastIoRead(FileObject
,
2355 &CapturedByteOffset
,
2363 /* Only accept the result if we got a straightforward status */
2365 (KernelIosb
.Status
== STATUS_SUCCESS
||
2366 KernelIosb
.Status
== STATUS_BUFFER_OVERFLOW
||
2367 KernelIosb
.Status
== STATUS_END_OF_FILE
))
2369 /* Fast path -- update transfer & operation counts */
2370 IopUpdateOperationCount(IopReadTransfer
);
2371 IopUpdateTransferCount(IopReadTransfer
,
2372 (ULONG
)KernelIosb
.Information
);
2374 /* Enter SEH to write the IOSB back */
2377 /* Write it back to the caller */
2378 *IoStatusBlock
= KernelIosb
;
2380 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2382 /* The caller's IOSB was invalid, so fail */
2383 if (EventObject
) ObDereferenceObject(EventObject
);
2384 IopUnlockFileObject(FileObject
);
2385 ObDereferenceObject(FileObject
);
2386 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2390 /* Signal the completion event */
2393 KeSetEvent(EventObject
, 0, FALSE
);
2394 ObDereferenceObject(EventObject
);
2398 IopUnlockFileObject(FileObject
);
2399 ObDereferenceObject(FileObject
);
2400 return KernelIosb
.Status
;
2404 /* Remember we are sync */
2407 else if (!(ByteOffset
) &&
2408 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
2410 /* Otherwise, this was async I/O without a byte offset, so fail */
2411 if (EventObject
) ObDereferenceObject(EventObject
);
2412 ObDereferenceObject(FileObject
);
2413 return STATUS_INVALID_PARAMETER
;
2416 /* Clear the File Object's event */
2417 KeClearEvent(&FileObject
->Event
);
2419 /* Allocate the IRP */
2420 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
2421 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
2424 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2425 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2426 Irp
->RequestorMode
= PreviousMode
;
2427 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
2428 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
2429 Irp
->UserIosb
= IoStatusBlock
;
2430 Irp
->UserEvent
= EventObject
;
2431 Irp
->PendingReturned
= FALSE
;
2432 Irp
->Cancel
= FALSE
;
2433 Irp
->CancelRoutine
= NULL
;
2434 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2435 Irp
->MdlAddress
= NULL
;
2437 /* Set the Stack Data */
2438 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2439 StackPtr
->MajorFunction
= IRP_MJ_READ
;
2440 StackPtr
->FileObject
= FileObject
;
2441 StackPtr
->Parameters
.Read
.Key
= CapturedKey
;
2442 StackPtr
->Parameters
.Read
.Length
= Length
;
2443 StackPtr
->Parameters
.Read
.ByteOffset
= CapturedByteOffset
;
2445 /* Check if this is buffered I/O */
2446 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
2448 /* Check if we have a buffer length */
2454 /* Allocate a buffer */
2455 Irp
->AssociatedIrp
.SystemBuffer
=
2456 ExAllocatePoolWithTag(NonPagedPool
,
2460 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2462 /* Allocating failed, clean up and return the exception code */
2463 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2464 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2468 /* Set the buffer and flags */
2469 Irp
->UserBuffer
= Buffer
;
2470 Irp
->Flags
= (IRP_BUFFERED_IO
|
2471 IRP_DEALLOCATE_BUFFER
|
2472 IRP_INPUT_OPERATION
);
2476 /* Not reading anything */
2477 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_INPUT_OPERATION
;
2480 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
2482 /* Check if we have a buffer length */
2487 /* Allocate an MDL */
2488 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
2490 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
2491 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
2493 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2495 /* Allocating failed, clean up and return the exception code */
2496 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
2497 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2503 /* No allocation flags */
2508 /* No allocation flags, and use the buffer directly */
2510 Irp
->UserBuffer
= Buffer
;
2513 /* Now set the deferred read flags */
2514 Irp
->Flags
|= (IRP_READ_OPERATION
| IRP_DEFER_IO_COMPLETION
);
2516 /* FIXME: VFAT SUCKS */
2517 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
2520 /* Perform the call */
2521 return IopPerformSynchronousRequest(DeviceObject
,
2535 NtReadFileScatter(IN HANDLE FileHandle
,
2536 IN HANDLE Event OPTIONAL
,
2537 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
2538 IN PVOID UserApcContext OPTIONAL
,
2539 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
2540 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
2541 IN ULONG BufferLength
,
2542 IN PLARGE_INTEGER ByteOffset
,
2543 IN PULONG Key OPTIONAL
)
2546 return STATUS_NOT_IMPLEMENTED
;
2554 NtSetEaFile(IN HANDLE FileHandle
,
2555 IN PIO_STATUS_BLOCK IoStatusBlock
,
2557 IN ULONG EaBufferSize
)
2560 return STATUS_NOT_IMPLEMENTED
;
2568 NtSetInformationFile(IN HANDLE FileHandle
,
2569 OUT PIO_STATUS_BLOCK IoStatusBlock
,
2570 IN PVOID FileInformation
,
2572 IN FILE_INFORMATION_CLASS FileInformationClass
)
2574 PFILE_OBJECT FileObject
;
2577 PDEVICE_OBJECT DeviceObject
;
2578 PIO_STACK_LOCATION StackPtr
;
2579 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2580 PKEVENT Event
= NULL
;
2581 BOOLEAN LocalEvent
= FALSE
;
2582 PKNORMAL_ROUTINE NormalRoutine
;
2583 PVOID NormalContext
;
2585 IO_STATUS_BLOCK KernelIosb
;
2587 PFILE_COMPLETION_INFORMATION CompletionInfo
= FileInformation
;
2588 PIO_COMPLETION_CONTEXT Context
;
2589 PFILE_RENAME_INFORMATION RenameInfo
;
2590 HANDLE TargetHandle
= NULL
;
2592 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
2594 /* Check if we're called from user mode */
2595 if (PreviousMode
!= KernelMode
)
2597 /* Validate the information class */
2598 if ((FileInformationClass
>= FileMaximumInformation
) ||
2599 !(IopSetOperationLength
[FileInformationClass
]))
2602 return STATUS_INVALID_INFO_CLASS
;
2605 /* Validate the length */
2606 if (Length
< IopSetOperationLength
[FileInformationClass
])
2608 /* Invalid length */
2609 return STATUS_INFO_LENGTH_MISMATCH
;
2612 /* Enter SEH for probing */
2615 /* Probe the I/O Status block */
2616 ProbeForWriteIoStatusBlock(IoStatusBlock
);
2618 /* Probe the information */
2619 ProbeForRead(FileInformation
,
2621 (Length
== sizeof(BOOLEAN
)) ?
2622 sizeof(BOOLEAN
) : sizeof(ULONG
));
2624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2626 /* Return the exception code */
2627 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2633 /* Validate the information class */
2634 if ((FileInformationClass
>= FileMaximumInformation
) ||
2635 !(IopSetOperationLength
[FileInformationClass
]))
2638 return STATUS_INVALID_INFO_CLASS
;
2641 /* Validate the length */
2642 if (Length
< IopSetOperationLength
[FileInformationClass
])
2644 /* Invalid length */
2645 return STATUS_INFO_LENGTH_MISMATCH
;
2649 /* Reference the Handle */
2650 Status
= ObReferenceObjectByHandle(FileHandle
,
2651 IopSetOperationAccess
2652 [FileInformationClass
],
2655 (PVOID
*)&FileObject
,
2657 if (!NT_SUCCESS(Status
)) return Status
;
2659 /* Check if this is a direct open or not */
2660 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
2662 /* Get the device object */
2663 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
2667 /* Get the device object */
2668 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
2671 /* Check if this is a file that was opened for Synch I/O */
2672 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
2675 IopLockFileObject(FileObject
);
2677 /* Check if the caller just wants the position */
2678 if (FileInformationClass
== FilePositionInformation
)
2680 /* Protect write in SEH */
2683 /* Write the offset */
2684 FileObject
->CurrentByteOffset
=
2685 ((PFILE_POSITION_INFORMATION
)FileInformation
)->
2688 /* Fill out the I/O Status Block */
2689 IoStatusBlock
->Information
= 0;
2690 Status
= IoStatusBlock
->Status
= STATUS_SUCCESS
;
2692 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2694 /* Get the exception code */
2695 Status
= _SEH2_GetExceptionCode();
2699 /* Update transfer count */
2700 IopUpdateTransferCount(IopOtherTransfer
, Length
);
2702 /* Release the file lock, dereference the file and return */
2703 IopUnlockFileObject(FileObject
);
2704 ObDereferenceObject(FileObject
);
2710 /* Use local event */
2711 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
2714 ObDereferenceObject(FileObject
);
2715 return STATUS_INSUFFICIENT_RESOURCES
;
2718 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
2722 /* Clear the File Object event */
2723 KeClearEvent(&FileObject
->Event
);
2725 /* Allocate the IRP */
2726 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, TRUE
);
2727 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
2730 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
2731 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
2732 Irp
->RequestorMode
= PreviousMode
;
2733 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
2734 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
2735 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
2736 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
2737 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
2738 Irp
->MdlAddress
= NULL
;
2739 Irp
->UserBuffer
= FileInformation
;
2741 /* Set the Stack Data */
2742 StackPtr
= IoGetNextIrpStackLocation(Irp
);
2743 StackPtr
->MajorFunction
= IRP_MJ_SET_INFORMATION
;
2744 StackPtr
->FileObject
= FileObject
;
2749 /* Allocate a buffer */
2750 Irp
->AssociatedIrp
.SystemBuffer
=
2751 ExAllocatePoolWithTag(NonPagedPool
,
2755 /* Copy the data into it */
2756 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
2760 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2762 /* Allocating failed, clean up and return the exception code */
2763 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
2764 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2769 Irp
->Flags
|= (IRP_BUFFERED_IO
|
2770 IRP_DEALLOCATE_BUFFER
|
2771 IRP_DEFER_IO_COMPLETION
);
2773 /* Set the Parameters */
2774 StackPtr
->Parameters
.SetFile
.FileInformationClass
= FileInformationClass
;
2775 StackPtr
->Parameters
.SetFile
.Length
= Length
;
2778 IopQueueIrpToThread(Irp
);
2780 /* Update operation counts */
2781 IopUpdateOperationCount(IopOtherTransfer
);
2783 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2784 /* Handle IO Completion Port quickly */
2785 if (FileInformationClass
== FileCompletionInformation
)
2787 /* Check if the file object already has a completion port */
2788 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
2789 (FileObject
->CompletionContext
))
2792 Status
= STATUS_INVALID_PARAMETER
;
2796 /* Reference the Port */
2797 CompletionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2798 Status
= ObReferenceObjectByHandle(CompletionInfo
->Port
,
2799 IO_COMPLETION_MODIFY_STATE
,
2804 if (NT_SUCCESS(Status
))
2806 /* Allocate the Context */
2807 Context
= ExAllocatePoolWithTag(PagedPool
,
2808 sizeof(IO_COMPLETION_CONTEXT
),
2813 Context
->Key
= CompletionInfo
->Key
;
2814 Context
->Port
= Queue
;
2815 if (InterlockedCompareExchangePointer((PVOID
*)&FileObject
->
2821 * Someone else set the completion port in the
2822 * meanwhile, so dereference the port and fail.
2824 ExFreePoolWithTag(Context
, IOC_TAG
);
2825 ObDereferenceObject(Queue
);
2826 Status
= STATUS_INVALID_PARAMETER
;
2831 /* Dereference the Port now */
2832 ObDereferenceObject(Queue
);
2833 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2838 /* Set the IRP Status */
2839 Irp
->IoStatus
.Status
= Status
;
2840 Irp
->IoStatus
.Information
= 0;
2842 else if (FileInformationClass
== FileRenameInformation
||
2843 FileInformationClass
== FileLinkInformation
||
2844 FileInformationClass
== FileMoveClusterInformation
)
2846 /* Get associated information */
2847 RenameInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
2852 * -> sizes are valid
2854 if (RenameInfo
->FileNameLength
!= 0 &&
2855 !(RenameInfo
->FileNameLength
& 1) &&
2856 (Length
- FIELD_OFFSET(FILE_RENAME_INFORMATION
, FileName
) >= RenameInfo
->FileNameLength
))
2858 /* Properly set information received */
2859 if (FileInformationClass
== FileMoveClusterInformation
)
2861 StackPtr
->Parameters
.SetFile
.ClusterCount
= ((PFILE_MOVE_CLUSTER_INFORMATION
)RenameInfo
)->ClusterCount
;
2865 StackPtr
->Parameters
.SetFile
.ReplaceIfExists
= RenameInfo
->ReplaceIfExists
;
2868 /* If we got fully path OR relative target, attempt a parent directory open */
2869 if (RenameInfo
->FileName
[0] == OBJ_NAME_PATH_SEPARATOR
|| RenameInfo
->RootDirectory
)
2871 Status
= IopOpenLinkOrRenameTarget(&TargetHandle
, Irp
, RenameInfo
, FileObject
);
2872 if (!NT_SUCCESS(Status
))
2874 Irp
->IoStatus
.Status
= Status
;
2878 /* Call the Driver */
2879 Status
= IoCallDriver(DeviceObject
, Irp
);
2884 /* Call the Driver */
2885 Status
= IoCallDriver(DeviceObject
, Irp
);
2890 Status
= STATUS_INVALID_PARAMETER
;
2891 Irp
->IoStatus
.Status
= Status
;
2896 /* Call the Driver */
2897 Status
= IoCallDriver(DeviceObject
, Irp
);
2900 /* Check if we're waiting for the IRP to complete */
2901 if (Status
== STATUS_PENDING
)
2903 /* Check if this was async I/O */
2906 /* Then to a non-alertable wait */
2907 Status
= KeWaitForSingleObject(Event
,
2912 if (Status
== STATUS_USER_APC
)
2914 /* Abort the request */
2915 IopAbortInterruptedIrp(Event
, Irp
);
2918 /* Set the final status */
2919 Status
= KernelIosb
.Status
;
2921 /* Enter SEH to write the IOSB back */
2924 /* Write it back to the caller */
2925 *IoStatusBlock
= KernelIosb
;
2927 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2929 /* Get the exception code */
2930 Status
= _SEH2_GetExceptionCode();
2934 /* Free the event */
2935 ExFreePoolWithTag(Event
, TAG_IO
);
2939 /* Wait for the IRP */
2940 Status
= KeWaitForSingleObject(&FileObject
->Event
,
2943 (FileObject
->Flags
&
2944 FO_ALERTABLE_IO
) != 0,
2946 if ((Status
== STATUS_USER_APC
) || (Status
== STATUS_ALERTED
))
2948 /* Abort the request */
2949 IopAbortInterruptedIrp(&FileObject
->Event
, Irp
);
2952 /* Set the final status */
2953 Status
= FileObject
->FinalStatus
;
2955 /* Release the file lock */
2956 IopUnlockFileObject(FileObject
);
2961 /* Free the event if we had one */
2964 /* Clear it in the IRP for completion */
2965 Irp
->UserEvent
= NULL
;
2966 ExFreePoolWithTag(Event
, TAG_IO
);
2969 /* Set the caller IOSB */
2970 Irp
->UserIosb
= IoStatusBlock
;
2972 /* The IRP wasn't completed, complete it ourselves */
2973 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2974 IopCompleteRequest(&Irp
->Tail
.Apc
,
2977 (PVOID
*)&FileObject
,
2979 KeLowerIrql(OldIrql
);
2981 /* Release the file object if we had locked it*/
2982 if (!LocalEvent
) IopUnlockFileObject(FileObject
);
2985 if (TargetHandle
!= NULL
)
2987 ObCloseHandle(TargetHandle
, KernelMode
);
2990 /* Return the Status */
2999 NtSetQuotaInformationFile(IN HANDLE FileHandle
,
3000 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3002 IN ULONG BufferLength
)
3005 return STATUS_NOT_IMPLEMENTED
;
3013 NtUnlockFile(IN HANDLE FileHandle
,
3014 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3015 IN PLARGE_INTEGER ByteOffset
,
3016 IN PLARGE_INTEGER Length
,
3017 IN ULONG Key OPTIONAL
)
3019 PFILE_OBJECT FileObject
;
3020 PLARGE_INTEGER LocalLength
= NULL
;
3022 PIO_STACK_LOCATION StackPtr
;
3023 PDEVICE_OBJECT DeviceObject
;
3024 PKEVENT Event
= NULL
;
3025 BOOLEAN LocalEvent
= FALSE
;
3026 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3027 LARGE_INTEGER CapturedByteOffset
, CapturedLength
;
3029 OBJECT_HANDLE_INFORMATION HandleInformation
;
3030 IO_STATUS_BLOCK KernelIosb
;
3032 CapturedByteOffset
.QuadPart
= 0;
3033 CapturedLength
.QuadPart
= 0;
3034 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3036 /* Get File Object */
3037 Status
= ObReferenceObjectByHandle(FileHandle
,
3041 (PVOID
*)&FileObject
,
3042 &HandleInformation
);
3043 if (!NT_SUCCESS(Status
)) return Status
;
3045 /* Check if we're called from user mode */
3046 if (PreviousMode
!= KernelMode
)
3048 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3049 if (!(HandleInformation
.GrantedAccess
&
3050 (FILE_WRITE_DATA
| FILE_READ_DATA
)))
3052 ObDereferenceObject(FileObject
);
3053 return STATUS_ACCESS_DENIED
;
3056 /* Enter SEH for probing */
3059 /* Probe the I/O Status block */
3060 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3062 /* Probe and capture the large integers */
3063 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3064 CapturedLength
= ProbeForReadLargeInteger(Length
);
3066 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3068 /* Dereference the object and return exception code */
3069 ObDereferenceObject(FileObject
);
3070 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3076 /* Otherwise, capture them directly */
3077 CapturedByteOffset
= *ByteOffset
;
3078 CapturedLength
= *Length
;
3081 /* Check if this is a direct open or not */
3082 if (FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
)
3084 DeviceObject
= IoGetAttachedDevice(FileObject
->DeviceObject
);
3088 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3091 /* Check if we should use Sync IO or not */
3092 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3095 IopLockFileObject(FileObject
);
3099 /* Use local event */
3100 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3103 ObDereferenceObject(FileObject
);
3104 return STATUS_INSUFFICIENT_RESOURCES
;
3106 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3110 /* Clear File Object event */
3111 KeClearEvent(&FileObject
->Event
);
3113 /* Allocate the IRP */
3114 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3115 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3117 /* Set up the IRP */
3118 Irp
->RequestorMode
= PreviousMode
;
3119 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3120 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3121 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3122 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3123 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3124 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3126 /* Set up Stack Data */
3127 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3128 StackPtr
->MajorFunction
= IRP_MJ_LOCK_CONTROL
;
3129 StackPtr
->MinorFunction
= IRP_MN_UNLOCK_SINGLE
;
3130 StackPtr
->FileObject
= FileObject
;
3135 /* Allocate a buffer */
3136 LocalLength
= ExAllocatePoolWithTag(NonPagedPool
,
3137 sizeof(LARGE_INTEGER
),
3140 /* Set the length */
3141 *LocalLength
= CapturedLength
;
3142 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PVOID
)LocalLength
;
3143 StackPtr
->Parameters
.LockControl
.Length
= LocalLength
;
3145 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3147 /* Allocating failed, clean up and return the exception code */
3148 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3149 if (LocalLength
) ExFreePoolWithTag(LocalLength
, TAG_LOCK
);
3151 /* Return the exception code */
3152 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3156 /* Set Parameters */
3157 StackPtr
->Parameters
.LockControl
.ByteOffset
= CapturedByteOffset
;
3158 StackPtr
->Parameters
.LockControl
.Key
= Key
;
3160 /* Call the Driver */
3161 Status
= IopPerformSynchronousRequest(DeviceObject
,
3169 /* Check if this was async I/O */
3172 /* It was, finalize this request */
3173 Status
= IopFinalizeAsynchronousIo(Status
,
3190 NtWriteFile(IN HANDLE FileHandle
,
3191 IN HANDLE Event OPTIONAL
,
3192 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
3193 IN PVOID ApcContext OPTIONAL
,
3194 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3197 IN PLARGE_INTEGER ByteOffset OPTIONAL
,
3198 IN PULONG Key OPTIONAL
)
3201 PFILE_OBJECT FileObject
;
3203 PDEVICE_OBJECT DeviceObject
;
3204 PIO_STACK_LOCATION StackPtr
;
3205 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3206 PKEVENT EventObject
= NULL
;
3207 LARGE_INTEGER CapturedByteOffset
;
3208 ULONG CapturedKey
= 0;
3209 BOOLEAN Synchronous
= FALSE
;
3211 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
3212 PFAST_IO_DISPATCH FastIoDispatch
;
3213 IO_STATUS_BLOCK KernelIosb
;
3217 CapturedByteOffset
.QuadPart
= 0;
3218 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3220 /* Get File Object */
3221 Status
= ObReferenceObjectByHandle(FileHandle
,
3225 (PVOID
*)&FileObject
,
3227 if (!NT_SUCCESS(Status
)) return Status
;
3229 /* Validate User-Mode Buffers */
3230 if (PreviousMode
!= KernelMode
)
3235 * Check if the handle has either FILE_WRITE_DATA or
3236 * FILE_APPEND_DATA granted. However, if this is a named pipe,
3237 * make sure we don't ask for FILE_APPEND_DATA as it interferes
3238 * with the FILE_CREATE_PIPE_INSTANCE access right!
3240 if (!(ObjectHandleInfo
.GrantedAccess
&
3241 ((!(FileObject
->Flags
& FO_NAMED_PIPE
) ?
3242 FILE_APPEND_DATA
: 0) | FILE_WRITE_DATA
)))
3245 ObDereferenceObject(FileObject
);
3246 _SEH2_YIELD(return STATUS_ACCESS_DENIED
);
3249 /* Probe the status block */
3250 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3252 /* Probe the read buffer */
3253 ProbeForRead(Buffer
, Length
, 1);
3255 /* Check if we got a byte offset */
3258 /* Capture and probe it */
3259 CapturedByteOffset
= ProbeForReadLargeInteger(ByteOffset
);
3262 /* Capture and probe the key */
3263 if (Key
) CapturedKey
= ProbeForReadUlong(Key
);
3265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3267 /* Release the file object and return the exception code */
3268 ObDereferenceObject(FileObject
);
3269 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3275 /* Kernel mode: capture directly */
3276 if (ByteOffset
) CapturedByteOffset
= *ByteOffset
;
3277 if (Key
) CapturedKey
= *Key
;
3280 /* Check if this is an append operation */
3281 if ((ObjectHandleInfo
.GrantedAccess
&
3282 (FILE_APPEND_DATA
| FILE_WRITE_DATA
)) == FILE_APPEND_DATA
)
3284 /* Give the drivers something to understand */
3285 CapturedByteOffset
.u
.LowPart
= FILE_WRITE_TO_END_OF_FILE
;
3286 CapturedByteOffset
.u
.HighPart
= -1;
3289 /* Check for event */
3293 Status
= ObReferenceObjectByHandle(Event
,
3297 (PVOID
*)&EventObject
,
3299 if (!NT_SUCCESS(Status
))
3302 ObDereferenceObject(FileObject
);
3306 /* Otherwise reset the event */
3307 KeClearEvent(EventObject
);
3310 /* Get the device object */
3311 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3313 /* Check if we should use Sync IO or not */
3314 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3316 /* Lock the file object */
3317 IopLockFileObject(FileObject
);
3319 /* Check if we don't have a byte offset available */
3320 if (!(ByteOffset
) ||
3321 ((CapturedByteOffset
.u
.LowPart
== FILE_USE_FILE_POINTER_POSITION
) &&
3322 (CapturedByteOffset
.u
.HighPart
== -1)))
3324 /* Use the Current Byte Offset instead */
3325 CapturedByteOffset
= FileObject
->CurrentByteOffset
;
3328 /* If the file is cached, try fast I/O */
3329 if (FileObject
->PrivateCacheMap
)
3331 /* Perform fast read */
3332 FastIoDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
3333 Success
= FastIoDispatch
->FastIoWrite(FileObject
,
3334 &CapturedByteOffset
,
3342 /* Only accept the result if it was successful */
3344 KernelIosb
.Status
== STATUS_SUCCESS
)
3346 /* Fast path -- update transfer & operation counts */
3347 IopUpdateOperationCount(IopWriteTransfer
);
3348 IopUpdateTransferCount(IopWriteTransfer
,
3349 (ULONG
)KernelIosb
.Information
);
3351 /* Enter SEH to write the IOSB back */
3354 /* Write it back to the caller */
3355 *IoStatusBlock
= KernelIosb
;
3357 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3359 /* The caller's IOSB was invalid, so fail */
3360 if (EventObject
) ObDereferenceObject(EventObject
);
3361 IopUnlockFileObject(FileObject
);
3362 ObDereferenceObject(FileObject
);
3363 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3367 /* Signal the completion event */
3370 KeSetEvent(EventObject
, 0, FALSE
);
3371 ObDereferenceObject(EventObject
);
3375 IopUnlockFileObject(FileObject
);
3376 ObDereferenceObject(FileObject
);
3377 return KernelIosb
.Status
;
3381 /* Remember we are sync */
3384 else if (!(ByteOffset
) &&
3385 !(FileObject
->Flags
& (FO_NAMED_PIPE
| FO_MAILSLOT
)))
3387 /* Otherwise, this was async I/O without a byte offset, so fail */
3388 if (EventObject
) ObDereferenceObject(EventObject
);
3389 ObDereferenceObject(FileObject
);
3390 return STATUS_INVALID_PARAMETER
;
3393 /* Clear the File Object's event */
3394 KeClearEvent(&FileObject
->Event
);
3396 /* Allocate the IRP */
3397 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3398 if (!Irp
) return IopCleanupFailedIrp(FileObject
, EventObject
, NULL
);
3401 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3402 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3403 Irp
->RequestorMode
= PreviousMode
;
3404 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= ApcRoutine
;
3405 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= ApcContext
;
3406 Irp
->UserIosb
= IoStatusBlock
;
3407 Irp
->UserEvent
= EventObject
;
3408 Irp
->PendingReturned
= FALSE
;
3409 Irp
->Cancel
= FALSE
;
3410 Irp
->CancelRoutine
= NULL
;
3411 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3412 Irp
->MdlAddress
= NULL
;
3414 /* Set the Stack Data */
3415 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3416 StackPtr
->MajorFunction
= IRP_MJ_WRITE
;
3417 StackPtr
->FileObject
= FileObject
;
3418 StackPtr
->Flags
= FileObject
->Flags
& FO_WRITE_THROUGH
?
3419 SL_WRITE_THROUGH
: 0;
3420 StackPtr
->Parameters
.Write
.Key
= CapturedKey
;
3421 StackPtr
->Parameters
.Write
.Length
= Length
;
3422 StackPtr
->Parameters
.Write
.ByteOffset
= CapturedByteOffset
;
3424 /* Check if this is buffered I/O */
3425 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
3427 /* Check if we have a buffer length */
3433 /* Allocate a buffer */
3434 Irp
->AssociatedIrp
.SystemBuffer
=
3435 ExAllocatePoolWithTag(NonPagedPool
,
3439 /* Copy the data into it */
3440 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
3442 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3444 /* Allocating failed, clean up and return the exception code */
3445 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3446 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3451 Irp
->Flags
= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3455 /* Not writing anything */
3456 Irp
->Flags
= IRP_BUFFERED_IO
;
3459 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
3461 /* Check if we have a buffer length */
3466 /* Allocate an MDL */
3467 Mdl
= IoAllocateMdl(Buffer
, Length
, FALSE
, TRUE
, Irp
);
3469 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
3470 MmProbeAndLockPages(Mdl
, PreviousMode
, IoReadAccess
);
3472 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3474 /* Allocating failed, clean up and return the exception code */
3475 IopCleanupAfterException(FileObject
, Irp
, EventObject
, NULL
);
3476 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3481 /* No allocation flags */
3486 /* No allocation flags, and use the buffer directly */
3488 Irp
->UserBuffer
= Buffer
;
3491 /* Now set the deferred read flags */
3492 Irp
->Flags
|= (IRP_WRITE_OPERATION
| IRP_DEFER_IO_COMPLETION
);
3494 /* FIXME: VFAT SUCKS */
3495 if (FileObject
->Flags
& FO_NO_INTERMEDIATE_BUFFERING
) Irp
->Flags
|= IRP_NOCACHE
;
3498 /* Perform the call */
3499 return IopPerformSynchronousRequest(DeviceObject
,
3510 NtWriteFileGather(IN HANDLE FileHandle
,
3511 IN HANDLE Event OPTIONAL
,
3512 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
3513 IN PVOID UserApcContext OPTIONAL
,
3514 OUT PIO_STATUS_BLOCK UserIoStatusBlock
,
3515 IN FILE_SEGMENT_ELEMENT BufferDescription
[],
3516 IN ULONG BufferLength
,
3517 IN PLARGE_INTEGER ByteOffset
,
3518 IN PULONG Key OPTIONAL
)
3521 return STATUS_NOT_IMPLEMENTED
;
3529 NtQueryVolumeInformationFile(IN HANDLE FileHandle
,
3530 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3531 OUT PVOID FsInformation
,
3533 IN FS_INFORMATION_CLASS FsInformationClass
)
3535 PFILE_OBJECT FileObject
;
3537 PIO_STACK_LOCATION StackPtr
;
3538 PDEVICE_OBJECT DeviceObject
;
3539 PKEVENT Event
= NULL
;
3540 BOOLEAN LocalEvent
= FALSE
;
3541 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3543 IO_STATUS_BLOCK KernelIosb
;
3545 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3547 /* Check if we're called from user mode */
3548 if (PreviousMode
!= KernelMode
)
3550 /* Validate the information class */
3551 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3552 !(IopQueryFsOperationLength
[FsInformationClass
]))
3555 return STATUS_INVALID_INFO_CLASS
;
3558 /* Validate the length */
3559 if (Length
< IopQueryFsOperationLength
[FsInformationClass
])
3561 /* Invalid length */
3562 return STATUS_INFO_LENGTH_MISMATCH
;
3565 /* Enter SEH for probing */
3568 /* Probe the I/O Status block */
3569 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3571 /* Probe the information */
3572 ProbeForWrite(FsInformation
, Length
, sizeof(ULONG
));
3574 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3576 /* Return the exception code */
3577 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3582 /* Get File Object */
3583 Status
= ObReferenceObjectByHandle(FileHandle
,
3584 IopQueryFsOperationAccess
3585 [FsInformationClass
],
3588 (PVOID
*)&FileObject
,
3590 if (!NT_SUCCESS(Status
)) return Status
;
3592 /* Check if we should use Sync IO or not */
3593 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3596 IopLockFileObject(FileObject
);
3600 /* Use local event */
3601 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3604 ObDereferenceObject(FileObject
);
3605 return STATUS_INSUFFICIENT_RESOURCES
;
3607 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3611 /* Get the device object */
3612 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3614 /* Clear File Object event */
3615 KeClearEvent(&FileObject
->Event
);
3617 /* Allocate the IRP */
3618 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3619 if (!Irp
) return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3621 /* Set up the IRP */
3622 Irp
->RequestorMode
= PreviousMode
;
3623 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3624 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3625 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3626 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3627 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3628 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3629 Irp
->UserBuffer
= FsInformation
;
3630 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3631 Irp
->MdlAddress
= NULL
;
3633 /* Set up Stack Data */
3634 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3635 StackPtr
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
3636 StackPtr
->FileObject
= FileObject
;
3641 /* Allocate a buffer */
3642 Irp
->AssociatedIrp
.SystemBuffer
=
3643 ExAllocatePoolWithTag(NonPagedPool
,
3647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3649 /* Allocating failed, clean up and return the exception code */
3650 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3651 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3655 /* Set the flags for this buffered + deferred I/O */
3656 Irp
->Flags
|= (IRP_BUFFERED_IO
|
3657 IRP_DEALLOCATE_BUFFER
|
3658 IRP_INPUT_OPERATION
|
3659 IRP_DEFER_IO_COMPLETION
);
3661 /* Set Parameters */
3662 StackPtr
->Parameters
.QueryVolume
.Length
= Length
;
3663 StackPtr
->Parameters
.QueryVolume
.FsInformationClass
= FsInformationClass
;
3665 /* Call the Driver */
3666 Status
= IopPerformSynchronousRequest(DeviceObject
,
3674 /* Check if this was async I/O */
3677 /* It was, finalize this request */
3678 Status
= IopFinalizeAsynchronousIo(Status
,
3695 NtSetVolumeInformationFile(IN HANDLE FileHandle
,
3696 OUT PIO_STATUS_BLOCK IoStatusBlock
,
3697 IN PVOID FsInformation
,
3699 IN FS_INFORMATION_CLASS FsInformationClass
)
3701 PFILE_OBJECT FileObject
;
3703 PIO_STACK_LOCATION StackPtr
;
3704 PDEVICE_OBJECT DeviceObject
, TargetDeviceObject
;
3705 PKEVENT Event
= NULL
;
3706 BOOLEAN LocalEvent
= FALSE
;
3707 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
3709 IO_STATUS_BLOCK KernelIosb
;
3710 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure
;
3712 IOTRACE(IO_API_DEBUG
, "FileHandle: %p\n", FileHandle
);
3714 /* Check if we're called from user mode */
3715 if (PreviousMode
!= KernelMode
)
3717 /* Validate the information class */
3718 if ((FsInformationClass
>= FileFsMaximumInformation
) ||
3719 !(IopSetFsOperationLength
[FsInformationClass
]))
3722 return STATUS_INVALID_INFO_CLASS
;
3725 /* Validate the length */
3726 if (Length
< IopSetFsOperationLength
[FsInformationClass
])
3728 /* Invalid length */
3729 return STATUS_INFO_LENGTH_MISMATCH
;
3732 /* Enter SEH for probing */
3735 /* Probe the I/O Status block */
3736 ProbeForWriteIoStatusBlock(IoStatusBlock
);
3738 /* Probe the information */
3739 ProbeForRead(FsInformation
, Length
, sizeof(ULONG
));
3741 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3743 /* Return the exception code */
3744 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3749 /* Get File Object */
3750 Status
= ObReferenceObjectByHandle(FileHandle
,
3751 IopSetFsOperationAccess
3752 [FsInformationClass
],
3755 (PVOID
*)&FileObject
,
3757 if (!NT_SUCCESS(Status
)) return Status
;
3759 /* Get target device for notification */
3760 Status
= IoGetRelatedTargetDevice(FileObject
, &TargetDeviceObject
);
3761 if (!NT_SUCCESS(Status
)) TargetDeviceObject
= NULL
;
3763 /* Check if we should use Sync IO or not */
3764 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
3767 IopLockFileObject(FileObject
);
3771 /* Use local event */
3772 Event
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(KEVENT
), TAG_IO
);
3775 ObDereferenceObject(FileObject
);
3776 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3777 return STATUS_INSUFFICIENT_RESOURCES
;
3779 KeInitializeEvent(Event
, SynchronizationEvent
, FALSE
);
3783 /* Get the device object */
3784 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
3786 /* Clear File Object event */
3787 KeClearEvent(&FileObject
->Event
);
3789 /* Allocate the IRP */
3790 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
3793 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3794 return IopCleanupFailedIrp(FileObject
, NULL
, Event
);
3797 /* Set up the IRP */
3798 Irp
->RequestorMode
= PreviousMode
;
3799 Irp
->Flags
= (LocalEvent
) ? IRP_SYNCHRONOUS_API
: 0;
3800 Irp
->UserIosb
= (LocalEvent
) ? &KernelIosb
: IoStatusBlock
;
3801 Irp
->UserEvent
= (LocalEvent
) ? Event
: NULL
;
3802 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
3803 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
3804 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
3805 Irp
->UserBuffer
= FsInformation
;
3806 Irp
->AssociatedIrp
.SystemBuffer
= NULL
;
3807 Irp
->MdlAddress
= NULL
;
3809 /* Set up Stack Data */
3810 StackPtr
= IoGetNextIrpStackLocation(Irp
);
3811 StackPtr
->MajorFunction
= IRP_MJ_SET_VOLUME_INFORMATION
;
3812 StackPtr
->FileObject
= FileObject
;
3817 /* Allocate a buffer */
3818 Irp
->AssociatedIrp
.SystemBuffer
=
3819 ExAllocatePoolWithTag(NonPagedPool
,
3823 /* Copy the data into it */
3824 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, FsInformation
, Length
);
3826 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3828 /* Allocating failed, clean up and return the exception code */
3829 IopCleanupAfterException(FileObject
, Irp
, NULL
, Event
);
3830 if (TargetDeviceObject
) ObDereferenceObject(TargetDeviceObject
);
3831 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3835 /* Set the flags for this buffered + deferred I/O */
3836 Irp
->Flags
|= (IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
3838 /* Set Parameters */
3839 StackPtr
->Parameters
.SetVolume
.Length
= Length
;
3840 StackPtr
->Parameters
.SetVolume
.FsInformationClass
= FsInformationClass
;
3842 /* Call the Driver */
3843 Status
= IopPerformSynchronousRequest(DeviceObject
,
3851 /* Check if this was async I/O */
3854 /* It was, finalize this request */
3855 Status
= IopFinalizeAsynchronousIo(Status
,
3863 if (TargetDeviceObject
&& NT_SUCCESS(Status
))
3865 /* Time to report change */
3866 NotificationStructure
.Version
= 1;
3867 NotificationStructure
.Size
= sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION
);
3868 NotificationStructure
.Event
= GUID_IO_VOLUME_NAME_CHANGE
;
3869 NotificationStructure
.FileObject
= NULL
;
3870 NotificationStructure
.NameBufferOffset
= - 1;
3871 Status
= IoReportTargetDeviceChange(TargetDeviceObject
, &NotificationStructure
);
3883 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle
)
3886 return STATUS_NOT_IMPLEMENTED
;
3894 NtRequestDeviceWakeup(IN HANDLE DeviceHandle
)
3897 return STATUS_NOT_IMPLEMENTED
;