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 }
}