示例#1
0
BOOLEAN
RawCheckForDismount (
    PVCB Vcb,
    BOOLEAN CalledFromCreate
    )

/*++

Routine Description:

    This routine determines if a volume is ready for deletion.  It
    correctly synchronizes with creates en-route to the file system.
    On exit if the vcb is deleted the mutex is released
    
Arguments:

    Vcb - Supplies the value to examine

    CalledFromCreate - Tells us if we should allow 0 or 1 in VpbRefCount

Return Value:

    BOOLEAN - TRUE if the volume was deleted, FALSE otherwise.

--*/

{

    KIRQL SavedIrql;
    ULONG ReferenceCount = 0;
    BOOLEAN DeleteVolume = FALSE;

    //
    //  We must enter with the vcb mutex acquired
    //  

    ASSERT( KeReadStateMutant( &Vcb->Mutex ) == 0 );

    IoAcquireVpbSpinLock( &SavedIrql );

    ReferenceCount = Vcb->Vpb->ReferenceCount;

    {
        PVPB Vpb;

        Vpb = Vcb->Vpb;

        //
        //  If a create is in progress on this volume, don't
        //  delete it.
        //

        if ( ReferenceCount != (ULONG)(CalledFromCreate ? 1 : 0) ) {

            //
            //  Cleanup the vpb on a forced dismount even if we can't delete the vcb if
            //  we haven't already done so
            //   

            if ((Vcb->SpareVpb != NULL) && 
                FlagOn( Vcb->VcbState,  VCB_STATE_FLAG_DISMOUNTED )) {

                //
                //  Setup the spare vpb and put it on the real device
                //  

                RtlZeroMemory( Vcb->SpareVpb, sizeof( VPB ) );

                Vcb->SpareVpb->Type = IO_TYPE_VPB;
                Vcb->SpareVpb->Size = sizeof( VPB );
                Vcb->SpareVpb->RealDevice = Vcb->Vpb->RealDevice;
                Vcb->SpareVpb->DeviceObject = NULL;
                Vcb->SpareVpb->Flags = FlagOn( Vcb->Vpb->Flags, VPB_REMOVE_PENDING );

                Vcb->Vpb->RealDevice->Vpb = Vcb->SpareVpb;

                //
                //  The spare vpb now belongs to the iosubsys and we own the original one
                //  

                Vcb->SpareVpb = NULL;
                Vcb->Vpb->Flags |=  VPB_PERSISTENT;

            }

            DeleteVolume = FALSE;

        } else {

            DeleteVolume = TRUE;

            if ( Vpb->RealDevice->Vpb == Vpb ) {

                Vpb->DeviceObject = NULL;

                Vpb->Flags &= ~VPB_MOUNTED;
            }
        }
    }
    IoReleaseVpbSpinLock( SavedIrql );

    if (DeleteVolume) {

        (VOID)KeReleaseMutex( &Vcb->Mutex, FALSE );

        //
        //  Free the spare vpb if we didn't use it or the original one if 
        //  we did use it and there are no more reference counts. Otherwise i/o
        //  subsystem still has a ref and will free the vpb itself
        // 

        if (Vcb->SpareVpb) {
            ExFreePool( Vcb->SpareVpb );
        } else if (ReferenceCount == 0) {
            ExFreePool( Vcb->Vpb );
        }
        
        ObDereferenceObject( Vcb->TargetDeviceObject );
        IoDeleteDevice( (PDEVICE_OBJECT)CONTAINING_RECORD( Vcb,
                                                           VOLUME_DEVICE_OBJECT,
                                                           Vcb));
    }
    
    return DeleteVolume;
}
示例#2
0
NTSTATUS
NtQueryMutant (
    IN HANDLE MutantHandle,
    IN MUTANT_INFORMATION_CLASS MutantInformationClass,
    OUT PVOID MutantInformation,
    IN ULONG MutantInformationLength,
    OUT PULONG ReturnLength OPTIONAL
    )

/*++

Routine Description:

    This function queries the state of a mutant object and returns the
    requested information in the specified record structure.

Arguments:

    MutantHandle - Supplies a handle to a mutant object.

    MutantInformationClass - Supplies the class of information being
        requested.

    MutantInformation - Supplies a pointer to a record that is to receive
        the requested information.

    MutantInformationLength - Supplies the length of the record that is
        to receive the requested information.

    ReturnLength - Supplies an optional pointer to a variable that will
        receive the actual length of the information that is returned.

Return Value:

    TBS

--*/

{

    BOOLEAN Abandoned;
    BOOLEAN OwnedByCaller;
    LONG Count;
    PVOID Mutant;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    //
    // Establish an exception handler, probe the output arguments, reference
    // the mutant object, and return the specified information. If the probe
    // fails, then return the exception code as the service status. Otherwise
    // return the status value returned by the reference object by handle
    // routine.
    //

    try {

        //
        // Get previous processor mode and probe output arguments if necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if (PreviousMode != KernelMode) {
            ProbeForWrite(MutantInformation,
                          sizeof(MUTANT_BASIC_INFORMATION),
                          sizeof(ULONG));

            if (ARGUMENT_PRESENT(ReturnLength)) {
                ProbeForWriteUlong(ReturnLength);
            }
        }

        //
        // Check argument validity.
        //

        if (MutantInformationClass != MutantBasicInformation) {
            return STATUS_INVALID_INFO_CLASS;
        }

        if (MutantInformationLength != sizeof(MUTANT_BASIC_INFORMATION)) {
            return STATUS_INFO_LENGTH_MISMATCH;
        }

        //
        // Reference mutant object by handle.
        //

        Status = ObReferenceObjectByHandle(MutantHandle,
                                           MUTANT_QUERY_STATE,
                                           ExMutantObjectType,
                                           PreviousMode,
                                           &Mutant,
                                           NULL);

        //
        // If the reference was successful, then read the current state and
        // abandoned status of the mutant object, dereference mutant object,
        // fill in the information structure, and return the length of the
        // information structure if specified. If the write of the mutant
        // information or the return length fails, then do not report an error.
        // When the caller accesses the information structure or length an
        // access violation will occur.
        //

        if (NT_SUCCESS(Status)) {
            Count = KeReadStateMutant((PKMUTANT)Mutant);
            Abandoned = ((PKMUTANT)Mutant)->Abandoned;
            OwnedByCaller = (BOOLEAN)((((PKMUTANT)Mutant)->OwnerThread ==
                                                         KeGetCurrentThread()));

            ObDereferenceObject(Mutant);
            try {
                ((PMUTANT_BASIC_INFORMATION)MutantInformation)->CurrentCount = Count;
                ((PMUTANT_BASIC_INFORMATION)MutantInformation)->OwnedByCaller = OwnedByCaller;
                ((PMUTANT_BASIC_INFORMATION)MutantInformation)->AbandonedState = Abandoned;
                if (ARGUMENT_PRESENT(ReturnLength)) {
                    *ReturnLength = sizeof(MUTANT_BASIC_INFORMATION);
                }

            } except(ExSystemExceptionFilter()) {
            }
        }

    //
    // If an exception occurs during the probe of the output arguments, then
    // always handle the exception and return the exception code as the status
    // value.
    //

    } except(ExSystemExceptionFilter()) {
        return GetExceptionCode();
    }

    //
    // Return service status.
    //

    return Status;
}