00502 :
00503
00504 This service changes information about
the volume
"mounted" on
the device
00505 specified by
the FileHandle parameter. The information to be changed
is
00506 in
the FsInformation buffer. Its contents are defined by
the FsInformation-
00507 Class parameter, whose values may be as follows:
00508
00509 o FileFsLabelInformation
00510
00511 Arguments:
00512
00513 FileHandle - Supplies a handle to
the volume whose information should be
00514 changed.
00515
00516 IoStatusBlock - Address of
the caller's I/O status block.
00517
00518 FsInformation - Supplies a buffer containing
the information which should
00519 be changed on
the volume.
00520
00521 Length - Supplies
the length, in bytes, of
the FsInformation buffer.
00522
00523 FsInformationClass - Specifies
the type of information which should be
00524 changed about
the volume.
00525
00526 Return Value:
00527
00528 The status returned
is the final completion status of
the operation.
00529 block.
00530
00531 --*/
00532
00533 {
00534
PIRP irp;
00535
NTSTATUS status;
00536
PFILE_OBJECT fileObject;
00537
PDEVICE_OBJECT deviceObject;
00538
PKEVENT event = (
PKEVENT)
NULL;
00539
KPROCESSOR_MODE requestorMode;
00540
PIO_STACK_LOCATION irpSp;
00541 IO_STATUS_BLOCK localIoStatus;
00542 PFILE_FS_LABEL_INFORMATION labelInformation;
00543 BOOLEAN synchronousIo;
00544
PDEVICE_OBJECT targetDeviceObject;
00545
00546
PAGED_CODE();
00547
00548
00549
00550
00551
00552 requestorMode = KeGetPreviousMode();
00553
00554
if (requestorMode !=
KernelMode) {
00555
00556
00557
00558
00559
00560
00561
if ((ULONG) FsInformationClass >= FileFsMaximumInformation ||
00562
IopSetFsOperationLength[FsInformationClass] == 0) {
00563
return STATUS_INVALID_INFO_CLASS;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572
if (Length < (ULONG)
IopSetFsOperationLength[FsInformationClass]) {
00573
return STATUS_INFO_LENGTH_MISMATCH;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
try {
00585
00586
00587
00588
00589
00590
ProbeForWriteIoStatus( IoStatusBlock );
00591
00592
00593
00594
00595
00596
#if defined(_X86_)
00597
ProbeForRead( FsInformation, Length,
sizeof( ULONG ) );
00598
#elif defined(_IA64_)
00599
00600
if (
PsGetCurrentProcess()->Wow64Process) {
00601
ProbeForRead( FsInformation, Length,
sizeof( ULONG ) );
00602 }
00603
else {
00604
ProbeForRead( FsInformation,
00605 Length,
00606 IopQuerySetFsAlignmentRequirement[FsInformationClass] );
00607
00608 }
00609
#else
00610
ProbeForRead( FsInformation,
00611 Length,
00612 IopQuerySetFsAlignmentRequirement[FsInformationClass] );
00613
#endif
00614
00615 } except(EXCEPTION_EXECUTE_HANDLER) {
00616
00617
00618
00619
00620
00621
00622
00623
#if DBG
00624
if (GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT) {
00625 DbgBreakPoint();
00626 }
00627
#endif DBG
00628
00629
return GetExceptionCode();
00630
00631 }
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641 status =
ObReferenceObjectByHandle( FileHandle,
00642 IopSetFsOperationAccess[FsInformationClass],
00643 IoFileObjectType,
00644 requestorMode,
00645 (PVOID *) &fileObject,
00646 NULL );
00647
if (!
NT_SUCCESS( status )) {
00648
return status;
00649 }
00650
00651
00652
00653
00654
00655 status =
IoGetRelatedTargetDevice( fileObject, &targetDeviceObject );
00656
00657
if (
NT_SUCCESS( status )) {
00658
00659
00660
00661
00662
00663
00664
00665
ASSERT(targetDeviceObject);
00666
00667 }
else {
00668 targetDeviceObject =
NULL;
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
if (fileObject->
Flags &
FO_SYNCHRONOUS_IO) {
00680
00681 BOOLEAN interrupted;
00682
00683
if (!
IopAcquireFastLock( fileObject )) {
00684 status =
IopAcquireFileObjectLock( fileObject,
00685 requestorMode,
00686 (BOOLEAN) ((fileObject->
Flags & FO_ALERTABLE_IO) != 0),
00687 &interrupted );
00688
if (interrupted) {
00689
ObDereferenceObject( fileObject );
00690
if (targetDeviceObject !=
NULL) {
00691
ObDereferenceObject( targetDeviceObject );
00692 }
00693
return status;
00694 }
00695 }
00696 synchronousIo =
TRUE;
00697 }
else {
00698
00699
00700
00701
00702
00703
00704
00705
00706 event =
ExAllocatePool( NonPagedPool,
sizeof(
KEVENT ) );
00707
if (event ==
NULL) {
00708
ObDereferenceObject( fileObject );
00709
if (targetDeviceObject !=
NULL) {
00710
ObDereferenceObject( targetDeviceObject );
00711 }
00712
return STATUS_INSUFFICIENT_RESOURCES;
00713 }
00714
KeInitializeEvent( event, SynchronizationEvent, FALSE );
00715 synchronousIo =
FALSE;
00716 }
00717
00718
00719
00720
00721
00722
KeClearEvent( &fileObject->
Event );
00723
00724
00725
00726
00727
00728 deviceObject =
IoGetRelatedDeviceObject( fileObject );
00729
00730
00731
00732
00733
00734
00735 irp =
IoAllocateIrp( deviceObject->
StackSize, TRUE );
00736
if (!irp) {
00737
00738
00739
00740
00741
00742
00743
if (!(fileObject->
Flags &
FO_SYNCHRONOUS_IO)) {
00744
ExFreePool( event );
00745 }
00746
00747
IopAllocateIrpCleanup( fileObject, (
PKEVENT) NULL );
00748
00749
if (targetDeviceObject !=
NULL) {
00750
ObDereferenceObject( targetDeviceObject );
00751 }
00752
00753
return STATUS_INSUFFICIENT_RESOURCES;
00754 }
00755 irp->
Tail.Overlay.OriginalFileObject = fileObject;
00756 irp->
Tail.Overlay.Thread =
PsGetCurrentThread();
00757 irp->
RequestorMode = requestorMode;
00758
00759
00760
00761
00762
00763
if (synchronousIo) {
00764 irp->
UserEvent = (
PKEVENT)
NULL;
00765 irp->
UserIosb = IoStatusBlock;
00766 }
else {
00767 irp->
UserEvent = event;
00768 irp->
UserIosb = &localIoStatus;
00769 irp->
Flags =
IRP_SYNCHRONOUS_API;
00770 }
00771 irp->
Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)
NULL;
00772
00773
00774
00775
00776
00777
00778 irpSp =
IoGetNextIrpStackLocation( irp );
00779 irpSp->
MajorFunction =
IRP_MJ_SET_VOLUME_INFORMATION;
00780 irpSp->
FileObject = fileObject;
00781
00782
00783
00784
00785
00786
00787
00788
00789 irp->
AssociatedIrp.SystemBuffer = (PVOID)
NULL;
00790 irp->
MdlAddress = (
PMDL)
NULL;
00791
00792
try {
00793
00794 irp->
AssociatedIrp.SystemBuffer =
ExAllocatePoolWithQuota( NonPagedPool,
00795 Length );
00796 RtlCopyMemory( irp->
AssociatedIrp.SystemBuffer, FsInformation, Length );
00797
00798 } except(EXCEPTION_EXECUTE_HANDLER) {
00799
00800
00801
00802
00803
00804
00805
00806
00807
IopExceptionCleanup( fileObject,
00808 irp,
00809 (
PKEVENT) NULL,
00810 event );
00811
00812
if (targetDeviceObject !=
NULL) {
00813
ObDereferenceObject( targetDeviceObject );
00814 }
00815
00816
return GetExceptionCode();
00817
00818 }
00819
00820
00821
00822
00823
00824
00825
if (requestorMode !=
KernelMode &&
00826 FsInformationClass == FileFsLabelInformation) {
00827
00828
00829
00830
00831
00832
00833
00834
00835 labelInformation = (PFILE_FS_LABEL_INFORMATION) irp->
AssociatedIrp.SystemBuffer;
00836
00837
if ((LONG) labelInformation->VolumeLabelLength < 0 ||
00838 labelInformation->VolumeLabelLength +
00839 FIELD_OFFSET( FILE_FS_LABEL_INFORMATION, VolumeLabel ) > Length) {
00840
00841
IopExceptionCleanup( fileObject,
00842 irp,
00843 (
PKEVENT) NULL,
00844 event );
00845
00846
if (targetDeviceObject !=
NULL) {
00847
ObDereferenceObject( targetDeviceObject );
00848 }
00849
00850
return STATUS_INVALID_PARAMETER;
00851 }
00852 }
00853
00854 irp->
Flags |= (ULONG) (
IRP_BUFFERED_IO |
IRP_DEALLOCATE_BUFFER);
00855
00856
00857
00858
00859
00860
00861 irpSp->
Parameters.SetVolume.Length = Length;
00862 irpSp->
Parameters.SetVolume.FsInformationClass = FsInformationClass;
00863
00864
00865
00866
00867
00868
00869
00870 status =
IopSynchronousServiceTail( deviceObject,
00871 irp,
00872 fileObject,
00873 FALSE,
00874 requestorMode,
00875 synchronousIo,
00876 OtherTransfer );
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
if (!synchronousIo) {
00887
00888 status =
IopSynchronousApiServiceTail( status,
00889 event,
00890 irp,
00891 requestorMode,
00892 &localIoStatus,
00893 IoStatusBlock );
00894 }
00895
00896
00897
00898
00899
00900
if (targetDeviceObject !=
NULL) {
00901
if (
NT_SUCCESS( status )) {
00902
TARGET_DEVICE_CUSTOM_NOTIFICATION ChangeEvent;
00903
00904 ChangeEvent.
Version = 1;
00905 ChangeEvent.
FileObject =
NULL;
00906 ChangeEvent.
NameBufferOffset = -1;
00907 ChangeEvent.
Size = (
USHORT)FIELD_OFFSET(
TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer );
00908
00909 RtlCopyMemory( &ChangeEvent.
Event, &GUID_IO_VOLUME_CHANGE,
sizeof( GUID_IO_VOLUME_CHANGE ));
00910
00911
IoReportTargetDeviceChange( targetDeviceObject, &ChangeEvent );
00912 }
00913
00914
ObDereferenceObject( targetDeviceObject );
00915 }
00916
00917
return status;
00918 }
}