filemanager/Engine/src/CFileManagerRemovableDriveHandler.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Feb 2010 22:41:53 +0200
branchRCL_3
changeset 5 1e73d2d04cbc
parent 0 6a9f87576119
child 19 5181328fad28
permissions -rw-r--r--
Revision: 201003 Kit: 201007

/*
* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0""
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Wraps removable drive functionality
*
*/



// INCLUDE FILES
#include <FileManagerEngine.rsg>
#include "CFileManagerRemovableDriveHandler.h"
#include "MFileManagerProcessObserver.h"
#include "CFileManagerUtils.h"
#include "CFileManagerEngine.h"
#include <coreapplicationuisdomainpskeys.h>
#include <coemain.h>
#include <apgwgnam.h>
#include <apgtask.h>
#include <bautils.h>
#include <tz.h>
#include <babackup.h>
#include <pathinfo.h>
#include <sysutil.h>
#ifdef RD_MULTIPLE_DRIVE
#include <driveinfo.h>
#endif // RD_MULTIPLE_DRIVE
#include <e32property.h>
#include <centralrepository.h>
#include "CMMCScBkupEngine.h"
#include "MMCScBkupOperations.h"
#include "CMMCScBkupOperationParameters.h"
#include "CFileManagerItemProperties.h"
#include "CFileManagerBackupSettings.h"
#include "FileManagerPrivateCRKeys.h"
#include "BkupEngine.hrh"
#include "FileManagerDebug.h"
#include "CFileManagerCommonDefinitions.h"
#include "FileManagerUID.h"
#include "filemanagerprivatepskeys.h"


// CONSTANTS
const TInt KEjectScanInterval = 1000000; // 1 second
const TInt KEjectScanRoundsMax = 7;
NONSHARABLE_CLASS(TMaskLookup)
    {
    public:
        TUint32 iBkupMask;
        TUint32 iFmgrMask;
    };

const TMaskLookup KMaskLookup[] = {
    { EBUCatSettings,  EFileManagerBackupContentSettings  },
    { EBUCatMessages,  EFileManagerBackupContentMessages  },
    { EBUCatContacts,  EFileManagerBackupContentContacts  },
    { EBUCatCalendar,  EFileManagerBackupContentCalendar  },
    { EBUCatBookmarks, EFileManagerBackupContentBookmarks },
    { EBUCatUserFiles, EFileManagerBackupContentUserFiles }
};
const TUint32 KMaskLookupLen =
    sizeof( KMaskLookup ) / sizeof( KMaskLookup[ 0 ] );

const TInt KForcedFormatTimeout = 1000000;
const TInt KAppCloseTimeout = 1000000;
const TInt KFileManagerAppUid = 0x101F84EB;

NONSHARABLE_CLASS(TFileManagerVolumeNameStore)
    {
public:
    inline TFileManagerVolumeNameStore() : iDrive( KErrNotFound ), iName( KNullDesC ) {};

    TInt iDrive; // The drive using the store
    TFileName iName; // Use the same length than TVolumeInfo
    };

typedef TPckg< TFileManagerVolumeNameStore > TFileManagerVolumeNameStorePckg;


// ======== MEMBER FUNCTIONS ========

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::CFileManagerRemovableDriveHandler
// ---------------------------------------------------------------------------
//
CFileManagerRemovableDriveHandler::CFileManagerRemovableDriveHandler(
        RFs& aFs,
        CFileManagerUtils& aUtils,
        CFileManagerEngine& aEngine ) :
    CActive( CActive::EPriorityStandard ),
    iFs( aFs ),
    iUtils( aUtils ),
    iEngine( aEngine )
    {
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::ConstructL
// ---------------------------------------------------------------------------
//
void CFileManagerRemovableDriveHandler::ConstructL()
    {
    CActiveScheduler::Add( this );
    iBkupEngine = CMMCScBkupEngine::NewL( iFs );
    PublishBurStatus( EFileManagerBkupStatusUnset );
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::NewL
// ---------------------------------------------------------------------------
//
CFileManagerRemovableDriveHandler* CFileManagerRemovableDriveHandler::NewL(
        RFs& aFs,
        CFileManagerUtils& aUtils,
        CFileManagerEngine& aEngine )
    {
    CFileManagerRemovableDriveHandler* self =
        new( ELeave ) CFileManagerRemovableDriveHandler(
            aFs, aUtils, aEngine );

    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );

    return self;
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::~CFileManagerRemovableDriveHandler
// ---------------------------------------------------------------------------
// 
CFileManagerRemovableDriveHandler::~CFileManagerRemovableDriveHandler()
    {
    Cancel();
    delete iBSWrapper;
    delete iEjectScanPeriodic;
    delete iBkupEngine;
    iFormatter.Close();
    PublishBurStatus( EFileManagerBkupStatusUnset );
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::EjectScanAndShutdownApps
// ---------------------------------------------------------------------------
//
TInt CFileManagerRemovableDriveHandler::EjectScanAndShutdownApps( TAny* ptr )
    {
    CFileManagerRemovableDriveHandler* self = 
        static_cast< CFileManagerRemovableDriveHandler* >( ptr );
    TRAPD( err, self->DoEjectScanAndShutdownL() );
    if ( err != KErrNone )
        {
        self->EjectComplete( err );
        }
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::DoEjectScanAndShutdownL
// ---------------------------------------------------------------------------
//
void CFileManagerRemovableDriveHandler::DoEjectScanAndShutdownL()
    {
    RWsSession wsSession;
    User::LeaveIfError( wsSession.Connect() );
    CleanupClosePushL( wsSession );

    const TInt KDefaultWgIdArraySize = 4;
    CArrayFixFlat<TInt>* wgIds = new( ELeave ) CArrayFixFlat< TInt >(
        KDefaultWgIdArraySize );
    CleanupStack::PushL( wgIds );
    User::LeaveIfError( wsSession.WindowGroupList( 0, wgIds ) );
    TInt last( wgIds->Count() - 1 );
    TInt appsToShutDown( 0 );

    for ( TInt i( last ); i >= 0; i-- )
        {
        CApaWindowGroupName* doomedApp =
            CApaWindowGroupName::NewLC( wsSession, wgIds->At( i ) );
        TBool systemApp( doomedApp->IsSystem() );
        TBool hiddenApp( doomedApp->Hidden() );

        if ( !systemApp && !hiddenApp && doomedApp->AppUid().iUid != KFileManagerAppUid  )
            {
            appsToShutDown++;
            TApaTask* task = new (ELeave) TApaTask( wsSession );
            CleanupDeletePushL( task );
            task->SetWgId( wgIds->At( i ) );

            if ( !iEjectScanRounds )
                {
                 // applications are kindly requested to close themselves
                 // on the first round
                task->EndTask();
                }
            else if ( iEjectScanRounds >= KEjectScanRoundsMax )
                {
                task->KillTask();
                }
            CleanupStack::PopAndDestroy( task );
            }
        CleanupStack::PopAndDestroy( doomedApp );
        }
    CleanupStack::PopAndDestroy( wgIds );

    if ( !appsToShutDown || iEjectScanRounds >= KEjectScanRoundsMax )
        {
        EjectComplete( KErrNone );
        }
    iEjectScanRounds++;
    
    CleanupStack::PopAndDestroy( &wsSession );
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::EjectComplete
// ---------------------------------------------------------------------------
//
void CFileManagerRemovableDriveHandler::EjectComplete( TInt aErr )
    {
    delete iEjectScanPeriodic;
    iEjectScanPeriodic = NULL;
    iLastError = aErr;

    TRAP_IGNORE( InformFinishL() );

    RProperty::Set(
        KPSUidCoreApplicationUIs,
        KCoreAppUIsMmcRemovedWithoutEject,
        ECoreAppUIsEjectCommandNotUsed );
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::InformStartL
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::InformStartL( TInt aTotalCount )
    {
    iLastError = KErrNone;
    if ( iObserver )
        {
        iObserver->ProcessStartedL( iProcess,  aTotalCount );
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::InformUpdateL
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::InformUpdateL( TInt aCount )
    {
    if ( iObserver )
        {
        iObserver->ProcessAdvanceL( aCount );
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::InformFinishL
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::InformFinishL()
    {
    iEngine.ClearDriveInfo();
    PublishBurStatus( EFileManagerBkupStatusUnset );
    iProcess = MFileManagerProcessObserver::ENoProcess;
    if ( iObserver )
        {
        iObserver->ProcessFinishedL( iLastError, KNullDesC );
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::InformError
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::InformError( TInt aErr )
    {
    iLastError = aErr;
    if ( iObserver )
        {
        iObserver->Error( aErr );
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::HandleBkupEngineEventL
// ---------------------------------------------------------------------------
// 
TInt CFileManagerRemovableDriveHandler::HandleBkupEngineEventL(
        MMMCScBkupEngineObserver::TEvent aEvent, TInt aAssociatedData )
    {
    TInt ret( KErrNone );
    switch( aEvent )
        {
        case MMMCScBkupEngineObserver::ECommonOperationStarting:
            {
            iFinalValue = KMaxTInt;
            InformStartL( KMaxTInt );
            break;
            }
        case MMMCScBkupEngineObserver::ECommonSizeOfTaskUnderstood:
            {
            iFinalValue = aAssociatedData;
            InformStartL( aAssociatedData );
            break;
            }
        case MMMCScBkupEngineObserver::ECommonOperationPrepareEnded:
            {
            PublishBurStatus( EFileManagerBkupStatusUnset );
            // In order to show finished dialog prior SysAp's note,
            // inform observer already at prepare-ended state.
            if( iProcess == MFileManagerProcessObserver::ERestoreProcess )
                {
                if ( iFinalValue )
                    {
                    InformUpdateL( iFinalValue );
                    }
                InformFinishL();
                }
            break;
            }
        case MMMCScBkupEngineObserver::ECommonOperationEnded:
            {
            PublishBurStatus( EFileManagerBkupStatusUnset );
            if( iProcess != MFileManagerProcessObserver::ERestoreProcess )
                {
                if ( iFinalValue )
                    {
                    InformUpdateL( iFinalValue );
                    }
                InformFinishL();
                }
            break;
            }
        case MMMCScBkupEngineObserver::ECommonOperationError:
            {
            iLastError = aAssociatedData;
            break;
            }
        case MMMCScBkupEngineObserver::ECommonProgress:
            {
            InformUpdateL( aAssociatedData );
            break;
            }
        case MMMCScBkupEngineObserver::EBackupAnalysingData:
            {
            if ( iObserver &&
                iProcess == MFileManagerProcessObserver::EBackupProcess )
                {
                ret = iObserver->NotifyL(
                    MFileManagerProcessObserver::ENotifyBackupMemoryLow,
                    aAssociatedData );
                }
            break;
            }
        default:
            {
            break;
            }
        }
    return ret;
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::SetObserver
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::SetObserver(
        MFileManagerProcessObserver* aObserver )
    {
    iObserver = aObserver;
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::BackupFileNameLC
// ---------------------------------------------------------------------------
// 
HBufC* CFileManagerRemovableDriveHandler::BackupFileNameLC(
        TBool aFullPath ) const
    {
    HBufC* file = CCoeEnv::Static()->AllocReadResourceLC(
        R_TEXT_MMC_BACKUP_FILE );
    if ( !aFullPath )
        {
        return file; // Get just name
        }
    // Get full path
#ifdef RD_MULTIPLE_DRIVE
    TInt drive( 0 );
    User::LeaveIfError( DriveInfo::GetDefaultDrive(
        DriveInfo::EDefaultRemovableMassStorage, drive ) );
    TDriveUnit driveUnit( drive );
#else // RD_MULTIPLE_DRIVE
    TDriveUnit driveUnit( PathInfo::MemoryCardRootPath() );
#endif // RD_MULTIPLE_DRIVE
    HBufC* fileAndPath = HBufC::NewLC( KMaxFileName );
    TPtr ptr( fileAndPath->Des() );
    TPtr filePtr( file->Des() );
    ptr.Copy( driveUnit.Name() );
    ptr.Append( filePtr );
    CleanupStack::Pop( fileAndPath );
    CleanupStack::PopAndDestroy( file );
    CleanupStack::PushL( fileAndPath );
    return fileAndPath;
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::StartFormatL()
// ---------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::StartFormatL(
        const TInt aDrive )
    {
    TInt err( KErrNone );

    iDrive = aDrive;
    iProcess = MFileManagerProcessObserver::EFormatProcess;
    iFinalValue = 0;

    TRAP( err, InformStartL( 0 ) );
    if ( err == KErrNone )
        {
        // Close apps and then start format
        TRAP( err, CloseAppsL() );
        }
    if ( err != KErrNone )
        {
        EndFormatProcessL( err );
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::StartEjectL()
// ---------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::StartEjectL()
    {
    TRAPD( err, StartEjectScanL() );
    if ( err != KErrNone )
        {
        iProcess = MFileManagerProcessObserver::ENoProcess;
        User::Leave( err );
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::StartEjectScanL()
// ---------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::StartEjectScanL()
    {
    iProcess = MFileManagerProcessObserver::EEjectProcess;
    InformStartL( 0 );

    RProperty::Set(
        KPSUidCoreApplicationUIs,
        KCoreAppUIsMmcRemovedWithoutEject,
        ECoreAppUIsEjectCommandUsed );

    iEjectScanRounds = 0;
    iEjectScanPeriodic = CPeriodic::NewL( CActive::EPriorityLow );
    iEjectScanPeriodic->Start(
        KEjectScanInterval,
        KEjectScanInterval,
        TCallBack( EjectScanAndShutdownApps, this ) );
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::CancelProcess()
// ---------------------------------------------------------------------------
//    
void CFileManagerRemovableDriveHandler::CancelProcess()
    {
    switch( iProcess )
        {
        case MFileManagerProcessObserver::EFormatProcess:
            {
            Cancel();
            break;
            }
        case MFileManagerProcessObserver::EBackupProcess: // FALLTHROUGH
        case MFileManagerProcessObserver::ERestoreProcess:
        case MFileManagerProcessObserver::ESchBackupProcess:
            {
            PublishBurStatus( EFileManagerBkupStatusUnset );
            iBkupEngine->CancelOperation();
            break;
            }
        default:
            {
            break;
            }
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::BackupFileExistsL()
// ---------------------------------------------------------------------------
//   
TBool CFileManagerRemovableDriveHandler::BackupFileExistsL(
        const TInt /*aDrive*/ )
    {
    HBufC* backupFile = BackupFileNameLC( ETrue );
    TBool ret( iBkupEngine->ValidArchiveForRestore( *backupFile ) );
    CleanupStack::PopAndDestroy( backupFile );
    return ret;
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::StartBackupL()
// ---------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::StartBackupL(
        MFileManagerProcessObserver::TFileManagerProcess aProcess )
    {
    if ( aProcess != MFileManagerProcessObserver::EBackupProcess &&
        aProcess != MFileManagerProcessObserver::ESchBackupProcess )
        {
        User::Leave( KErrNotSupported );
        }

    CCoeEnv* coeEnv = CCoeEnv::Static();

    // Create backup params - ownership is transferred to
    // secure backup engine
    TResourceReader driveReader;
    coeEnv->CreateResourceReaderLC(
        driveReader,
        R_FILEMANAGER_BACKUP_RESTORE_DRIVES_AND_OPERATIONS );
    TResourceReader categoryReader;
    coeEnv->CreateResourceReaderLC(
        categoryReader,
        R_FILEMANAGER_BACKUP_CATEGORIES );

#ifdef RD_FILE_MANAGER_BACKUP

    CFileManagerBackupSettings& settings( iEngine.BackupSettingsL() );
    TUint32 bkupContent( FmgrToBkupMask( settings.Content() ) );
    TInt drive( settings.TargetDrive() );

    CMMCScBkupOpParamsBackupFull* params =
        CMMCScBkupOpParamsBackupFull::NewL(
            driveReader,
            categoryReader,
            TDriveNumber( drive ),
            bkupContent );

#else // RD_FILE_MANAGER_BACKUP

    HBufC* backupFile = BackupFileNameLC( ETrue );
    TInt drive = TDriveUnit( *backupFile );
    CleanupStack::PopAndDestroy( backupFile );

    CMMCScBkupOpParamsBackupFull* params =
        CMMCScBkupOpParamsBackupFull::NewL( driveReader,
            categoryReader,
            TDriveNumber( drive ),
            EBUCatAllInOne );

#endif // RD_FILE_MANAGER_BACKUP

    CleanupStack::PopAndDestroy(); // categoryReader
    CleanupStack::PopAndDestroy(); // driveReader

    CleanupStack::PushL( params );
    TBool diskFull( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, 0, drive ) );
    CleanupStack::Pop( params );

    if ( diskFull )
        {
        iProcess = aProcess;
        TRAP_IGNORE( InformStartL( KMaxTInt ) );
        iLastError = KErrDiskFull;
        TRAP_IGNORE( InformFinishL() );
        iProcess = MFileManagerProcessObserver::ENoProcess;
        delete params;
        }
    else
        {
        // Start the process - engine owns the parameters immediately
        iProcess = aProcess;
        
        PublishBurStatus( EFileManagerBkupStatusBackup );
        TRAPD( err, iBkupEngine->StartOperationL(
            EMMCScBkupOperationTypeFullBackup, *this, params ) );
        if ( err != KErrNone )
            {
            PublishBurStatus( EFileManagerBkupStatusUnset );
            iProcess = MFileManagerProcessObserver::ENoProcess;
            User::Leave( err );
            }
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::StartRestoreL()
// ---------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::StartRestoreL()
    {
    TBool diskFull( SysUtil::DiskSpaceBelowCriticalLevelL(
        &iFs, 0, KFmgrSystemDrive ) );
    if ( diskFull )
        {
        iProcess = MFileManagerProcessObserver::ERestoreProcess;
        TRAP_IGNORE( InformStartL( KMaxTInt ) );
        iLastError = KErrDiskFull;
        TRAP_IGNORE( InformFinishL() );
        iProcess = MFileManagerProcessObserver::ENoProcess;
        return;
        }

    CFileManagerBackupSettings& bkupSettings( iEngine.BackupSettingsL() );

    // Create restore params - ownership is transferred to
    // secure backup engine
    TResourceReader driveReader;
    CCoeEnv::Static()->CreateResourceReaderLC(
        driveReader,
        R_FILEMANAGER_BACKUP_RESTORE_DRIVES_AND_OPERATIONS );

#ifdef RD_FILE_MANAGER_BACKUP

    CMMCScBkupOpParamsRestoreFull* params =
        CMMCScBkupOpParamsRestoreFull::NewL(
            driveReader,
            EBUCatAllSeparately );
    CleanupStack::PopAndDestroy(); // driveReader
    CleanupStack::PushL( params );

    // Get list of all archives
    RPointerArray< CMMCScBkupArchiveInfo > archives;
    TCleanupItem cleanupItem( ResetAndDestroyArchives, &archives );
    CleanupStack::PushL( cleanupItem );
    iBkupEngine->ListArchivesL(
        archives,
        params,
        bkupSettings.AllowedDriveAttMatchMask() );

    // Get user set restore selection
    RArray< CFileManagerRestoreSettings::TInfo > selection;
    CleanupClosePushL( selection );
    CFileManagerRestoreSettings& rstSettings( iEngine.RestoreSettingsL() );
    rstSettings.GetSelectionL( selection );

    // Remove non user selected archives
    TInt i( 0 );
    while ( i < archives.Count() )
        {
        TBool remove( ETrue );

        // Compare archives category and drive
        CMMCScBkupArchiveInfo* archiveInfo = archives[ i ];
        TUint32 fmgrContent(
            BkupToFmgrMask( archiveInfo->Category().iFlags ) );
        TInt drive( archiveInfo->Drive() );

        TInt count( selection.Count() );
        for( TInt j( 0 ); j < count; ++j )
            {
            const CFileManagerRestoreSettings::TInfo& info( selection[ j ] );
            if ( ( drive == info.iDrive ) && ( fmgrContent & info.iContent ) )
                {
                // Found user selected archive
                // Do not check this archive again
                selection.Remove( j );
                remove = EFalse;
                break;
                }
            }
        if ( remove )
            {
            // Remove non selected archive
            archives.Remove( i );
            delete archiveInfo;
            }
        else
            {
            // Move to next archive
            ++i;
            }
        }

    CleanupStack::PopAndDestroy( &selection );
    params->SetArchiveInfosL( archives );
    CleanupStack::Pop( &archives );
    archives.Close();
    CleanupStack::Pop( params );

#else // RD_FILE_MANAGER_BACKUP

    CMMCScBkupOpParamsRestoreFull* params =
        CMMCScBkupOpParamsRestoreFull::NewL( driveReader, EBUCatAllInOne );
    CleanupStack::PopAndDestroy(); // driveReader

    // Get list of all archives
    RPointerArray< CMMCScBkupArchiveInfo > archives;
    TCleanupItem cleanupItem( ResetAndDestroyArchives, &archives );
    CleanupStack::PushL( cleanupItem );
    iBkupEngine->ListArchivesL(
        archives,
        params,
        bkupSettings.AllowedDriveAttMatchMask() );
    params->SetArchiveInfosL( archives );
    CleanupStack::Pop( &archives );

#endif // RD_FILE_MANAGER_BACKUP

    // Start the process - engine owns the parameters immediately
    iProcess = MFileManagerProcessObserver::ERestoreProcess;
    PublishBurStatus( EFileManagerBkupStatusRestore );
    TRAPD( err, iBkupEngine->StartOperationL(
        EMMCScBkupOperationTypeFullRestore, *this, params ) );
    if ( err != KErrNone )
        {
        PublishBurStatus( EFileManagerBkupStatusUnset );
        iProcess = MFileManagerProcessObserver::ENoProcess;
        User::Leave( err );
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::GetRestoreInfoArrayL
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::GetRestoreInfoArrayL(
        RArray< CFileManagerRestoreSettings::TInfo >& aArray,
        const TInt aDrive )
    {
    CFileManagerBackupSettings& settings( iEngine.BackupSettingsL() );

    aArray.Reset();

    TResourceReader driveReader;
    CCoeEnv::Static()->CreateResourceReaderLC(
        driveReader,
        R_FILEMANAGER_BACKUP_RESTORE_DRIVES_AND_OPERATIONS );

    CMMCScBkupOpParamsRestoreFull* params =
        CMMCScBkupOpParamsRestoreFull::NewL(
            driveReader, EBUCatAllSeparately );
    CleanupStack::PopAndDestroy(); // driveReader
    CleanupStack::PushL( params );

    // Get list of all archives
    RPointerArray< CMMCScBkupArchiveInfo > archives;
    TCleanupItem cleanupItem( ResetAndDestroyArchives, &archives );
    CleanupStack::PushL( cleanupItem );
    iBkupEngine->ListArchivesL(
        archives,
        params,
        settings.AllowedDriveAttMatchMask(),
        aDrive );

    // Prepare time zone conversion
    RTz tz;
    User::LeaveIfError( tz.Connect() );
    CleanupClosePushL( tz );

    // Fill restore info
    CFileManagerRestoreSettings::TInfo info;
    TInt count( archives.Count() );
    aArray.ReserveL( count );

    for( TInt i( 0 ); i < count; ++i )
        {
        // Content
        CMMCScBkupArchiveInfo& archiveInfo( *archives[ i ] );
        info.iContent = BkupToFmgrMask( archiveInfo.Category().iFlags );

        // Local time
        info.iTime = archiveInfo.DateTime();
        User::LeaveIfError( tz.ConvertToLocalTime( info.iTime ) );

        // Drive
        info.iDrive = archiveInfo.Drive();

        aArray.AppendL( info );
        }

    CleanupStack::PopAndDestroy( &tz );
    CleanupStack::PopAndDestroy( &archives );
    CleanupStack::PopAndDestroy( params );
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::DoCancel
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::DoCancel()
    {
    switch( iProcess )
        {
        case MFileManagerProcessObserver::EFormatProcess:
            {
            TRAP_IGNORE( EndFormatProcessL( KErrCancel ) );
            break;
            }
        default:
            {
            break;
            }
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::RunL
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::RunL()
    {
    TInt err( iStatus.Int() );
    switch( iProcess )
        {
        case MFileManagerProcessObserver::EFormatProcess:
            {
            if( err != KErrNone )
                {
                if ( !iFinalValue && err == KErrInUse )
                    {
                    // Some app remained open, try still to start format
                    StartFormatProcessL();
                    }
                else
                    {
                    // Format failed
                    EndFormatProcessL( err );
                    }
                }
            else if( !iFinalValue )
                {
                // Apps have been closed. Start format.
                StartFormatProcessL();
                }
            else if( iFormatCountBuf() > 0 )
                {
                // Update observer and format next track
                InformUpdateL( iFinalValue - iFormatCountBuf() );
                iFormatter.Next( iFormatCountBuf, iStatus );
                SetActive( );
                }
            else
                {
                // Format complete
                EndFormatProcessL( KErrNone );
                }
            break;
            }
        default:
            {
            break;
            }
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::RunError
// ---------------------------------------------------------------------------
// 
TInt CFileManagerRemovableDriveHandler::RunError( TInt aError )
    {
    switch( iProcess )
        {
        case MFileManagerProcessObserver::EFormatProcess:
            {
            TRAP_IGNORE( EndFormatProcessL( aError ) );
            break;
            }
        default:
            {
            break;
            }
        }
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::EndFormatProcessL
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::EndFormatProcessL( TInt aErr )
    {
    iFormatter.Close();
    iLastError = aErr;
    if( aErr == KErrNone )
        {
        // Restore the volume name stored before format operation.
        TRAPD( err, RestoreVolumeNameL( iDrive ) );
        LOG_IF_ERROR1( err,
            "FileManagerRemovableDriveHandler::EndFormatProcessL-RestoreVolumeName %d",
            err );
        iUtils.CreateDefaultFolders( iDrive );
        }
    else if ( aErr != KErrCancel )
        {
        InformError( aErr );
        }
    TRAPD( err,  RestartAppsL() );
      LOG_IF_ERROR1( err,
         "FileManagerRemovableDriveHandler::EndFormatProcessL-Restart apps %d",
         err );
    InformFinishL();

    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::StartFormatProcessL
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::StartFormatProcessL()
    {
    // Store the current volume name over format operation.
    TRAPD( err, StoreVolumeNameL( iDrive ) );
    LOG_IF_ERROR1(
        err,
        "FileManagerRemovableDriveHandler::StartFormatProcessL-StoreVolumeName %d",
        err );
    TDriveName driveName( TDriveUnit( iDrive ).Name() );
    // Resolve drive character and open formatter
    iFormatter.Close();
    err = iFormatter.Open(
        iFs, driveName, EFullFormat, iFinalValue );
    // Forced format for locked card
    if ( err == KErrLocked )
        {
        // Erase password and try again
        err = iFs.ErasePassword( iDrive );
        if (err == KErrNone)
        	{
        	err = iFormatter.Open(iFs, driveName, EFullFormat , iFinalValue );        
        	}
        }
    if (err == KErrInUse)
    	{    
    	TBool reallyFormat = ETrue;
    	if (reallyFormat)
    		{    	
    		err = iFormatter.Open(
    				iFs, driveName, EFullFormat | EForceFormat, iFinalValue );    		
    		}
    	}
   TFullName fsName;
   if (err == KErrNone)
	   {
	   err = iFs.FileSystemName( fsName, iDrive );			  

	   if ( err == KErrNone && fsName.Length() > 0 )
		   {
		   // Prevent SysAp shutting down applications
		   RProperty::Set(
				   KPSUidCoreApplicationUIs,
				   KCoreAppUIsMmcRemovedWithoutEject,
				   ECoreAppUIsEjectCommandUsed );
		   }
	   else
		   {
		   // Don't continue with format if there is no file system name
		   // or file system name could not be obtained.
		   err = KErrCancel;
		   }
	   }

    // On successful open of RFormat::Open(), iFinalValue contains the number of
    // tracks to be formatted

    if ( iFinalValue && err == KErrNone )
        {
        TRAP( err, InformStartL( iFinalValue ) );
        if ( err == KErrNone )
            {           
            iFormatCountBuf = iFinalValue;
            iFormatter.Next( iFormatCountBuf, iStatus );
            SetActive();
            }
        }
    if ( !iFinalValue || err != KErrNone )
        {   
        EndFormatProcessL( err );     
        }
    }
// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::CloseAppsL
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::CloseAppsL()
    {
    delete iBSWrapper;
    iBSWrapper = NULL;

    iBSWrapper = CBaBackupSessionWrapper::NewL();

    TBackupOperationAttributes atts(
        MBackupObserver::EReleaseLockNoAccess,
        MBackupOperationObserver::EStart );
    iBSWrapper->NotifyBackupOperationL( atts );
    iBSWrapper->CloseAll( MBackupObserver::EReleaseLockNoAccess, iStatus );
    SetActive();

    // Memory card formatting cannot be executed if there are open files on it.
    // It has been detected, that in some cases memory card using applications 
    // have no time to close file handles before formatting is tried to be executed. 
    // To address this issue, we need to add a delay here after client-notification 
    // about pending format and real formatting procedure.
    User::After( KAppCloseTimeout );
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::RestartAppsL
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::RestartAppsL()
    {
    if ( !iBSWrapper )
        {
        return;
        }

    TBackupOperationAttributes atts(
        MBackupObserver::ETakeLock, MBackupOperationObserver::EEnd );
    iBSWrapper->NotifyBackupOperationL( atts );
    iBSWrapper->RestartAll();

    // Get rid of the wrapper instance
    delete iBSWrapper;
    iBSWrapper = NULL;
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::ResetAndDestroyArchives
// ---------------------------------------------------------------------------
// 
void CFileManagerRemovableDriveHandler::ResetAndDestroyArchives( TAny* aPtr )
    {
    RPointerArray< CMMCScBkupArchiveInfo >* archive = 
        static_cast< RPointerArray< CMMCScBkupArchiveInfo >* >( aPtr );
    archive->ResetAndDestroy();
    archive->Close();
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::BkupToFmgrMask
// ---------------------------------------------------------------------------
// 
TUint32 CFileManagerRemovableDriveHandler::BkupToFmgrMask(
        const TUint32 aBkupMask )
    {
    TUint32 ret( 0 );

    for( TInt i( 0 ); i < KMaskLookupLen; ++i )
        {
        if ( aBkupMask & KMaskLookup[ i ].iBkupMask )
            {
            ret |= KMaskLookup[ i ].iFmgrMask;
            }
        }
    return ret;
    }

#ifdef RD_FILE_MANAGER_BACKUP
// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::FmgrToBkupMask
// ---------------------------------------------------------------------------
// 
TUint32 CFileManagerRemovableDriveHandler::FmgrToBkupMask(
        const TUint32 aFmrgMask )
    {
    TUint32 ret( 0 );

    for( TInt i( 0 ); i < KMaskLookupLen; ++i )
        {
        if ( ( aFmrgMask & EFileManagerBackupContentAll ) ||
            ( aFmrgMask & KMaskLookup[ i ].iFmgrMask ) )
            {
            ret |= KMaskLookup[ i ].iBkupMask;
            }
        }
    return ret;
    }
#endif // RD_FILE_MANAGER_BACKUP

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::IsProcessOngoing
// ---------------------------------------------------------------------------
// 
TBool CFileManagerRemovableDriveHandler::IsProcessOngoing() const
    {
    return iProcess != MFileManagerProcessObserver::ENoProcess;
    }

// -----------------------------------------------------------------------------
// CFileManagerEngine::PublishBurStatus()
//
// -----------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::PublishBurStatus( TInt aType )
	{
   _LIT_SECURITY_POLICY_S0( KFileManagerBkupWritePolicy, KFileManagerUID3 );
   _LIT_SECURITY_POLICY_PASS( KFileManagerBkupReadPolicy );

	TInt err( RProperty::Set(
	    KPSUidFileManagerStatus, KFileManagerBkupStatus, aType ) );
	if ( err != KErrNone )
		{
		err = RProperty::Define(
		    KPSUidFileManagerStatus, KFileManagerBkupStatus,
		    RProperty::EInt, KFileManagerBkupReadPolicy,
		    KFileManagerBkupWritePolicy );
		if ( err == KErrNone || err == KErrAlreadyExists )
		    {
		    err = RProperty::Set(
		        KPSUidFileManagerStatus, KFileManagerBkupStatus, aType );
		    }
		}
    LOG_IF_ERROR1(
        err, "FileManagerRemovableDriveHandler::PublishBurStatus-err=%d", err )
	}

// -----------------------------------------------------------------------------
// CFileManagerEngine::IsMassStorageDrive()
//
// -----------------------------------------------------------------------------
//  
#ifdef RD_MULTIPLE_DRIVE

TBool CFileManagerRemovableDriveHandler::IsInternalMassStorage( TInt aDrive )
	{
    FUNC_LOG;

    TBool ret( EFalse );
    TUint driveStatus( 0 );
    DriveInfo::GetDriveStatus( iFs, aDrive, driveStatus );
    if ( ( driveStatus & DriveInfo::EDriveInternal ) &&
         ( driveStatus & DriveInfo::EDriveExternallyMountable ) )
        {
        ret = ETrue;
        }
    INFO_LOG2(
        "FileManagerRemovableDriveHandler::IsInternalMassStorage-drive=%d,ret=%d",
        aDrive, ret );
    return ret;
    }

#else // RD_MULTIPLE_DRIVE

TBool CFileManagerRemovableDriveHandler::IsInternalMassStorage( TInt /*aDrive*/ )
	{
    FUNC_LOG;

    TInt ret( EFalse );
    return ret;
    }

#endif // RD_MULTIPLE_DRIVE

// -----------------------------------------------------------------------------
// CFileManagerEngine::StoreVolumeNameL()
//
// -----------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::StoreVolumeNameL( TInt aDrive )
	{
    FUNC_LOG;

    if ( IsInternalMassStorage( aDrive ) )
        {
        TVolumeInfo volumeInfo;
        User::LeaveIfError( iFs.Volume( volumeInfo, aDrive ) );
        CRepository* cenRep = CRepository::NewLC( KCRUidFileManagerSettings );
        TFileManagerVolumeNameStore volumeStore;
        TFileManagerVolumeNameStorePckg volumeStorePckg( volumeStore );
        volumeStore.iDrive = aDrive;
        volumeStore.iName.Copy( volumeInfo.iName );
        User::LeaveIfError( cenRep->Set(
            KFileManagerStoredInternalMassStorageVolumeName, volumeStorePckg ) );
        CleanupStack::PopAndDestroy( cenRep );
        INFO_LOG2(
            "FileManagerRemovableDriveHandler::StoreVolumeNameL-drive=%d,name=%S",
            aDrive, &volumeStore.iName );
        }
    }

// -----------------------------------------------------------------------------
// CFileManagerEngine::RestoreVolumeNameL()
//
// -----------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::RestoreVolumeNameL( TInt aDrive )
	{
    FUNC_LOG;

    if ( IsInternalMassStorage( aDrive ) )
        {
        TFileName volumeName;
        CRepository* cenRep = CRepository::NewLC( KCRUidFileManagerSettings );
        TFileManagerVolumeNameStore volumeStore;
        TFileManagerVolumeNameStorePckg volumeStorePckg( volumeStore );
        TInt err( cenRep->Get(
            KFileManagerStoredInternalMassStorageVolumeName, volumeStorePckg ) );
        if ( err == KErrNone && volumeStore.iDrive == aDrive )
            {
            volumeName.Copy( volumeStore.iName );
            }
        if ( !volumeName.Length() )
            {
            User::LeaveIfError( cenRep->Get(
                KFileManagerDefaultInternalMassStorageVolumeName, volumeName ) );
            }
        if ( volumeName.Length() > 0 )
            {
            User::LeaveIfError( iFs.SetVolumeLabel( volumeName, aDrive ) );
            }
        CleanupStack::PopAndDestroy( cenRep );
        INFO_LOG2(
            "FileManagerRemovableDriveHandler::RestoreVolumeNameL-drive=%d,name=%S",
            aDrive, &volumeName );
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::ListArchivesL
// ---------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::ListArchivesL(
        RPointerArray< CMMCScBkupArchiveInfo >& aArchives,
        const CFileManagerBackupSettings& aBackupSettings )
    {
    aArchives.ResetAndDestroy();
    TResourceReader driveReader;
    CCoeEnv::Static()->CreateResourceReaderLC(
        driveReader,
        R_FILEMANAGER_BACKUP_RESTORE_DRIVES_AND_OPERATIONS );
    CMMCScBkupOpParamsRestoreFull* params =
        CMMCScBkupOpParamsRestoreFull::NewL(
            driveReader, EBUCatAllSeparately );
    CleanupStack::PopAndDestroy(); // driveReader
    CleanupStack::PushL( params );
    iBkupEngine->ListArchivesL(
        aArchives, params, aBackupSettings.AllowedDriveAttMatchMask() );
    CleanupStack::PopAndDestroy( params );
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::LatestBackupTimeL
// ---------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::LatestBackupTimeL(
        TTime& aBackupTime )
    {
    aBackupTime = 0;
    CFileManagerBackupSettings& bkupSettings( iEngine.BackupSettingsL() );
    RPointerArray< CMMCScBkupArchiveInfo > archives;
    TCleanupItem cleanupItem( ResetAndDestroyArchives, &archives );
    CleanupStack::PushL( cleanupItem );
    ListArchivesL( archives, bkupSettings );

    // Find the latest archive
    TBool found( EFalse );
    TInt count( archives.Count() );
    for( TInt i( 0 ); i < count; ++i )
        {
        TTime time( archives[ i ]->DateTime() );
        if ( time > aBackupTime )
            {
            aBackupTime = time;
            found = ETrue;
            }
        }
    CleanupStack::PopAndDestroy( &archives );
    if ( !found )
        {
        User::Leave( KErrNotFound );
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerRemovableDriveHandler::DeleteBackupsL
// ---------------------------------------------------------------------------
//  
void CFileManagerRemovableDriveHandler::DeleteBackupsL()
    {
    CFileManagerBackupSettings& bkupSettings( iEngine.BackupSettingsL() );
    RPointerArray< CMMCScBkupArchiveInfo > archives;
    TCleanupItem cleanupItem( ResetAndDestroyArchives, &archives );
    CleanupStack::PushL( cleanupItem );
    ListArchivesL( archives, bkupSettings );

    // Get the user set selection
    RArray< CFileManagerRestoreSettings::TInfo > selection;
    CleanupClosePushL( selection );
    CFileManagerRestoreSettings& rstSettings( iEngine.RestoreSettingsL() );
    rstSettings.GetSelectionL( selection );

    // Delete selected archives
    TInt archivesCount( archives.Count() );
    for ( TInt i( 0 ); i < archivesCount; ++i )
        {
        CMMCScBkupArchiveInfo* archiveInfo = archives[ i ];
        TUint32 fmgrContent(
            BkupToFmgrMask( archiveInfo->Category().iFlags ) );
        TInt drive( archiveInfo->Drive() );
        TInt selectionCount( selection.Count() );
        for( TInt j( 0 ); j < selectionCount; ++j )
            {
            const CFileManagerRestoreSettings::TInfo& info( selection[ j ] );
            if ( ( drive == info.iDrive ) && ( fmgrContent & info.iContent ) )
                {
                TPtrC fullPath( archiveInfo->FileName() );
                User::LeaveIfError(
                    CFileManagerUtils::RemoveReadOnlyAttribute(
                        iFs, fullPath ) );
                User::LeaveIfError( iFs.Delete( fullPath ) );
                selection.Remove( j ); // Do not check again
                break;
                }
            }
        }
    CleanupStack::PopAndDestroy( &selection );
    CleanupStack::PopAndDestroy( &archives );
    }


//  End of File