filemanager/Engine/src/CFileManagerActiveExecute.cpp
branchRCL_3
changeset 21 65326cf895ed
parent 0 6a9f87576119
child 1 d1daf54a55b5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filemanager/Engine/src/CFileManagerActiveExecute.cpp	Wed Sep 01 12:31:07 2010 +0100
@@ -0,0 +1,1178 @@
+/*
+* Copyright (c) 2002-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:  Handles the copy/move operation
+*
+*/
+
+
+// INCLUDE FILES
+#include <bautils.h>
+//#include <cmgxfilemanager.h>
+//#include <mgxfilemanagerfactory.h>
+#include "CFileManagerActiveExecute.h"
+#include "MFileManagerProcessObserver.h"
+#include "CFileManagerEngine.h"
+#include "CFileManagerFileSystemIterator.h"
+#include "Cfilemanagerindexiterator.h"
+#include "CFileManagerCommonDefinitions.h"
+#include "CFileManagerUtils.h"
+#include "FileManagerDebug.h"
+#include "CFileManagerThreadWrapper.h"
+
+// CONSTANTS
+const TInt KFileManagerNotificationArrayGranularity = 64;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::NewL
+// 
+// -----------------------------------------------------------------------------
+// 
+EXPORT_C CFileManagerActiveExecute* CFileManagerActiveExecute::NewL( 
+        CFileManagerEngine& aEngine,
+        MFileManagerProcessObserver::TFileManagerProcess aOperation,
+        MFileManagerProcessObserver& aObserver,
+        CArrayFixFlat<TInt>& aIndexList,
+        const TDesC& aToFolder )
+    {
+    CFileManagerActiveExecute* self = 
+        new( ELeave ) CFileManagerActiveExecute(
+            aEngine,
+            aOperation,
+            aObserver );
+    CleanupStack::PushL( self );
+    self->ConstructL( aIndexList, aToFolder );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::~CFileManagerActiveExecute
+// 
+// -----------------------------------------------------------------------------
+// 
+EXPORT_C CFileManagerActiveExecute::~CFileManagerActiveExecute()
+    {
+    Cancel();
+    delete iThreadWrapper;
+    delete iItemIterator;
+    delete iFullPath;
+    delete iDestination;
+    delete iToFolder;
+    delete iIndexList;
+    delete iChangedSrcItems;
+    delete iChangedDstItems;
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::ExecuteL
+// 
+// -----------------------------------------------------------------------------
+// 
+EXPORT_C void CFileManagerActiveExecute::ExecuteL( TFileManagerSwitch aOverWrite )
+    {
+    TInt error( KErrNone );
+    
+    if ( iCancelled )
+        {
+        TFileName newName;
+        TParsePtrC parse( *iFullPath );
+        if ( parse.NameOrExtPresent() )
+            {
+            newName.Copy( parse.NameAndExt() );
+            }
+        else
+            {
+            TPtrC name( iEngine.LocalizedName( *iFullPath ) );
+            if ( name.Length() > 0 )
+                {
+                newName.Copy( name );
+                }
+            else
+                {
+                newName = BaflUtils::FolderNameFromFullName( *iFullPath );
+                }
+            }
+        iObserver.ProcessFinishedL( iError, newName );
+        return;
+        }
+    
+    if ( aOverWrite == ENoOverWrite )
+        {
+        iItemIterator->CurrentL( &iSrc, &iDst, iItemType );
+        }
+
+    if ( iDst && iDst->Length() > KMaxFileName )
+        {
+        error = KErrBadName;
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete( status, error );              
+        }
+    else if ( iItemType == EFileManagerFile )
+        {
+#ifdef __KEEP_DRM_CONTENT_ON_PHONE
+    if ( iSrc && iDst &&
+        CFileManagerUtils::IsFromInternalToRemovableDrive( iFs, *iSrc, *iDst ) )
+        {
+        TBool protectedFile( EFalse );
+
+        // silently ignore this file if it is protected, or if there
+        // was an error in checking.
+        // Did consider leaving, but what about eg KErrNotFound - eg another
+        // process moving/deleting the file...
+        TInt ret( iEngine.IsDistributableFile( *iSrc, protectedFile ) );
+        if( protectedFile || ret != KErrNone )
+            {
+            TRequestStatus* status = &iStatus;
+            User::RequestComplete( status, KErrNone );
+            SetActive();
+            return;
+            }
+        }
+#endif
+        DoOperation( aOverWrite );
+        return;
+        }
+    else if ( iItemType == EFileManagerFolder )
+        {
+        if ( !iIsDstRemoteDrive && iEngine.IsNameFoundL( *iDst ) )
+            {
+            TRequestStatus* status = &iStatus;
+            User::RequestComplete( status, KErrAlreadyExists );
+            SetActive();
+            return;
+            }
+        DoOperation( aOverWrite );
+        return;
+        }
+    else
+        {
+        // We must complete this
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete( status, error );              
+        }
+    SetActive();
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::CancelExecution
+// 
+// -----------------------------------------------------------------------------
+// 
+EXPORT_C void CFileManagerActiveExecute::CancelExecution()
+    {
+    FUNC_LOG
+
+    iCancelled = ETrue;
+
+    if ( iSrc )
+        {
+        iEngine.CancelTransfer( *iSrc );
+        }
+    if ( iDst )
+        {
+        iEngine.CancelTransfer( *iDst );
+        }
+    delete iThreadWrapper; // Cancel thread
+    iThreadWrapper = NULL;
+    Cancel();
+    TRAP_IGNORE( CompleteL( KErrCancel ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::DoCancel
+// 
+// -----------------------------------------------------------------------------
+// 
+void CFileManagerActiveExecute::DoCancel()
+    {
+    iCancelled = ETrue;
+
+    if ( iSrc )
+        {
+        iEngine.CancelTransfer( *iSrc );
+        }
+    if ( iDst )
+        {
+        iEngine.CancelTransfer( *iDst );
+        }
+    delete iThreadWrapper; // Cancel thread
+    iThreadWrapper = NULL;
+    }
+
+// ------------------------------------------------------------------------------
+// CFileManagerActiveExecute::KErrNoneAction
+//
+// ------------------------------------------------------------------------------
+//
+void CFileManagerActiveExecute::KErrNoneActionL()
+    {
+    UpdateNotifications( EFalse, KErrNone );
+    if ( iItemIterator->NextL() )
+        {
+        ExecuteL( ENoOverWrite );
+        }
+    else
+        {
+        if ( iOperation == MFileManagerProcessObserver::EMoveProcess && 
+            iEngine.IsFolder( iIndexList->At( 0 ) ) )
+            {
+            if ( !iFinalizeMove )
+                {
+                // Finalize move in the thread, the finalizing way take time
+                iFinalizeMove = ETrue;
+                DoOperation( ENoOverWrite );
+                return;
+                }
+            }
+        UpdateNotifications( ETrue, KErrNone );
+        iObserver.ProcessFinishedL( KErrNone );
+        }
+    
+    }
+
+// ------------------------------------------------------------------------------
+// CFileManagerActiveExecute::KErrAlreadyExistsAction
+//
+// ------------------------------------------------------------------------------
+//
+void CFileManagerActiveExecute::KErrAlreadyExistsActionL()
+    {
+    TParsePtrC dstParse( *iDst );
+    HBufC* name = HBufC::NewLC( KMaxFileName );
+    TPtr ptrName( name->Des() );
+    TBool doContinue( EFalse );
+
+    // Depending on target file can it be delete, we ask overwrite or rename.
+    // If source and target is same, then rename is only possible choice.
+    if ( iItemType == EFileManagerFile && iEngine.CanDelete( *iDst ) && iSrc->FindF( *iDst ) )
+        {
+        if ( iObserver.ProcessQueryOverWriteL( *iDst, ptrName, iOperation ) )
+            {
+            ExecuteL( EOverWrite );
+            }
+        else
+            {
+            // user does not want to overwrite item and ptrName should now contain
+            // user given new name
+            if ( ptrName.Length() > 0 )
+                {
+                ptrName.Insert( 0, dstParse.DriveAndPath() );
+                if ( !iDst->CompareF( ptrName ) )
+                    {
+                    DoOperation( ENoOverWrite );
+                    }
+                else
+                    {
+                    iDst->Des().Copy( ptrName );
+                    // Overwrite, because user already queried by overwrite
+                    DoOperation( EOverWrite );
+                    }
+                }
+            else
+                {
+                // User is not willing to rename item, continue current operation
+                doContinue = ETrue;
+                }
+            }
+        }
+    else
+        {
+        // item can't be overwrite
+        if ( iObserver.ProcessQueryRenameL( *iDst, ptrName, iOperation ) )
+            {
+            if ( ptrName.Length() > 0 )
+                {
+                if ( iItemType == EFileManagerFile )
+                    {
+                    ptrName.Insert( 0, dstParse.DriveAndPath() );
+                    iDst->Des().Copy( ptrName );
+                    }
+                else if ( iItemType == EFileManagerFolder )
+                    {
+                    TPtr ptr( iDst->Des() );
+                    AddLastFolder( ptr, ptrName, *iToFolder );
+                    iDestination->Des().Copy( ptr );
+                    }
+                // Overwrite, because user already queried by rename
+                ExecuteL( EOverWrite );
+                }
+            else if ( iItemType == EFileManagerFolder )
+                {
+                iCancelled = ETrue;
+                iError = KErrCancel;
+                ExecuteL( ENoOverWrite );
+                }
+            else
+                {
+                // User is not willing to rename item, continue current operation
+                doContinue = ETrue;
+                }
+            }
+        else if ( iItemType == EFileManagerFolder )
+            {
+            iCancelled = ETrue;
+            iError = KErrCancel;
+            ExecuteL( ENoOverWrite );
+            }
+        else
+            {
+            // User is not willing to rename item, continue current operation
+            doContinue = ETrue;
+            }
+        }
+
+    CleanupStack::PopAndDestroy( name );
+
+    if ( doContinue )
+        {
+        if ( iItemIterator->NextL() )
+            {
+            ExecuteL( ENoOverWrite );
+            }
+        else
+            {
+            UpdateNotifications( ETrue, KErrNone );
+            iObserver.ProcessFinishedL( KErrNone );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::RunL
+// 
+// -----------------------------------------------------------------------------
+// 
+void CFileManagerActiveExecute::RunL()
+    {
+    CompleteL( iStatus.Int() );
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::CompleteL
+// 
+// -----------------------------------------------------------------------------
+// 
+void CFileManagerActiveExecute::CompleteL( TInt aError )
+    {
+    if ( iCancelled || !iItemIterator )
+        {
+        UpdateNotifications( ETrue, iError );
+        TParsePtrC parse( CFileManagerUtils::StripFinalBackslash(
+            *iDestination ) );
+        if ( parse.NameOrExtPresent() )
+            {
+            iObserver.ProcessFinishedL( iError, parse.NameAndExt() );
+            }
+        else if ( parse.DrivePresent() )
+            {
+            iObserver.ProcessFinishedL( iError, parse.Drive() );
+            }
+        else
+            {
+            iObserver.ProcessFinishedL( iError );
+            }
+        return;
+        }
+
+    // Symbian returns KErrNone if source and destination
+    // in moving is same. Here we have to treat it as error.
+    if( iSrc && iDst )
+        {
+        if ( !iSrc->CompareF( *iDst ) && aError == KErrNone )
+            {
+            aError = KErrInUse;
+            }
+        }    
+
+    ERROR_LOG1( "CFileManagerActiveExecute::CompleteL()-aError=%d", aError )
+
+    switch ( aError )
+        {
+        case KErrNone:
+            {
+            KErrNoneActionL();
+            break;
+            }
+        case KErrAlreadyExists:
+            {
+            KErrAlreadyExistsActionL();
+            break;
+            }
+        case KErrCancel: // Suppressed errors
+            {
+            UpdateNotifications( ETrue, KErrNone );
+            iObserver.ProcessFinishedL( KErrNone );
+            break;
+            }
+        default:
+            {
+            if ( iSrc )
+                {
+                // Try rename when moving and the target file exists and is in use
+                if ( iOperation == MFileManagerProcessObserver::EMoveProcess &&
+                    aError == KErrInUse &&
+                    iDst &&
+                    iEngine.CanDelete( *iSrc ) &&
+                    iEngine.IsNameFoundL( *iDst ) )
+                    {
+                    KErrAlreadyExistsActionL();
+                    }
+                else
+                    {
+                    UpdateNotifications( ETrue, aError );
+                    TParsePtrC parse( *iSrc );
+                    iObserver.ProcessFinishedL( aError, parse.NameAndExt() );
+                    }
+                }
+            else
+                {
+                UpdateNotifications( ETrue, aError );
+                iObserver.ProcessFinishedL( aError );
+                }
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::RunError
+// 
+// -----------------------------------------------------------------------------
+// 
+TInt CFileManagerActiveExecute::RunError(TInt aError)
+    {
+    return aError;
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::CFileManagerActiveExecute
+// 
+// -----------------------------------------------------------------------------
+// 
+CFileManagerActiveExecute::CFileManagerActiveExecute( 
+    CFileManagerEngine& aEngine,
+    MFileManagerProcessObserver::TFileManagerProcess aOperation,
+    MFileManagerProcessObserver& aObserver ) :
+        CActive( CActive::EPriorityLow ), // Use low to avoid progress note mess up
+        iEngine( aEngine ),
+        iFs( aEngine.Fs() ),
+        iOperation( aOperation ),
+        iObserver( aObserver )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::ConstructL
+// 
+// -----------------------------------------------------------------------------
+// 
+void CFileManagerActiveExecute::ConstructL( CArrayFixFlat<TInt>& aIndexList,
+                                            const TDesC& aToFolder )
+    {
+    iChangedSrcItems = new( ELeave ) CDesCArrayFlat(
+        KFileManagerNotificationArrayGranularity );
+    iChangedDstItems = new( ELeave ) CDesCArrayFlat(
+        KFileManagerNotificationArrayGranularity );
+    
+    iToFolder = aToFolder.AllocL();
+    TInt count( aIndexList.Count() );
+    iIndexList = new( ELeave ) CArrayFixFlat< TInt >( count );
+    for( TInt i( 0 ); i < count; ++i )
+        {
+        // make own copy of index list because caller may
+        // destroy the original one.
+        iIndexList->AppendL( aIndexList.At( i ) );
+        }
+    
+    TInt index( iIndexList->At( iCurrentIndex ) );
+    
+    iFullPath = iEngine.IndexToFullPathL( index );
+
+    TBool isDirectory( iEngine.IsFolder( index ) );
+
+    iDestination = HBufC::NewL( KFmgrDoubleMaxFileName );
+
+    if ( isDirectory )
+        {
+        TPtr ptr( iDestination->Des() );
+        AddLastFolder( ptr, *iFullPath, *iToFolder );
+        }
+    else
+        {
+        iDestination->Des().Copy( aToFolder );
+        }
+    
+    // Check that we are not copying/moving folder to inside it ( recursive copy )
+    if ( isDirectory && !iDestination->FindF( *iFullPath ) && 
+         iDestination->Length() > iFullPath->Length() )
+        {
+        iCancelled = ETrue;
+        iError = KErrAccessDenied;
+        }
+    // Is destination path too long for file system
+    else if ( iDestination->Length() > KMaxFileName )
+        {
+        iCancelled = ETrue;
+        iError = KErrBadName;
+        }
+    else if ( isDirectory )
+        {
+        iItemIterator = CFileManagerFileSystemIterator::NewL(
+            iFs, *iFullPath, *iDestination, iEngine );
+        }
+    else
+        {
+        iItemIterator = CFileManagerIndexIterator::NewL(
+            iEngine, aIndexList, *iDestination );
+        }
+
+    // MG2 notification object
+    //iMgxFileManager = &iEngine.MGXFileManagerL();
+
+    // Check are operation source and target on the same drive
+    TParsePtrC srcParse( *iFullPath  );
+    TParsePtrC dstParse( *iDestination );
+    TPtrC srcDrv( srcParse.Drive() );
+    TPtrC dstDrv( dstParse.Drive() );
+    iOperationOnSameDrive = !( srcDrv.CompareF( dstDrv ) );
+    iIsSrcRemoteDrive = CFileManagerUtils::IsRemoteDrive( iFs, srcDrv );
+    iIsDstRemoteDrive = CFileManagerUtils::IsRemoteDrive( iFs, dstDrv );
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::AddLastFolder
+// 
+// -----------------------------------------------------------------------------
+// 
+void CFileManagerActiveExecute::AddLastFolder( TDes& aResult,
+                                               const TDesC& aSrc, 
+                                               const TDesC& aDst )
+    {
+    TInt lastBackslash = aSrc.LocateReverse( KFmgrBackslash()[0] );
+    if ( lastBackslash != KErrNotFound )
+        {
+        // source is full path
+        aResult.Copy( aSrc.Left( lastBackslash - 1 ) );
+        // Last backslash is now temporary removed check next last backslash
+        TInt secondLastBackslash( aResult.LocateReverse( KFmgrBackslash()[0] ) );
+        // Now we know the coordinates of the last path
+        aResult.Copy( iEngine.LocalizedName( aSrc ) );
+        if ( aResult.Length() > 0 )
+            {
+            aResult.Insert( 0, aDst );
+            aResult.Append( KFmgrBackslash );
+            }
+        else
+            {
+            aResult.Append( aDst );
+            // Skip '\\'
+            TInt startingPoint( secondLastBackslash + 1 );
+            aResult.Append( aSrc.Mid( startingPoint, 
+                                      lastBackslash - secondLastBackslash ) );
+            }
+        }
+    else
+        {
+        // source is only one folder name
+        aResult.Copy( aDst );
+        aResult.Append( aSrc );
+        aResult.Append( KFmgrBackslash );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::DoOperation
+// 
+// -----------------------------------------------------------------------------
+// 
+TInt CFileManagerActiveExecute::DoOperation( TInt aSwitch )
+    {
+    // Source and destination must be different
+    if ( iSrc && iDst && !iDst->CompareF( *iSrc ) )
+        {
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete( status, KErrAlreadyExists );
+        SetActive();
+        return KErrAlreadyExists;
+        }
+    TInt err( KErrNone );
+
+    iSwitch = aSwitch;
+
+    if ( !iThreadWrapper )
+        {
+        TRAP( err, iThreadWrapper = CFileManagerThreadWrapper::NewL() );
+        if ( err != KErrNone )
+            {
+            TRequestStatus* status = &iStatus;
+            User::RequestComplete( status, err );
+            SetActive();
+            return err;
+            }
+        }
+    if ( iThreadWrapper->IsThreadStarted() )
+        {
+        iThreadWrapper->ResumeThread();
+        }
+    else
+        {
+        err = iThreadWrapper->StartThread(
+            *this, ENotifyStepFinished, EPriorityLess );
+        if ( err != KErrNone )
+            {
+            TRequestStatus* status = &iStatus;
+            User::RequestComplete( status, err );
+            SetActive();
+            return err;
+            }
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::IsEmptyDir
+// 
+// -----------------------------------------------------------------------------
+// 
+TBool CFileManagerActiveExecute::IsEmptyDir( const TDesC& aDir )
+    {
+    return !CFileManagerUtils::HasAny(
+        iFs, aDir, KEntryAttMatchMask | KEntryAttNormal );
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::ThreadCopyOrMoveStepL()
+//
+// -----------------------------------------------------------------------------
+//
+void CFileManagerActiveExecute::ThreadCopyOrMoveStepL()
+    {
+    FUNC_LOG
+
+    INFO_LOG2( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-%S=>%S",
+         iSrc, iDst )
+
+    TInt err( KErrNone );
+    
+    if ( iItemType == EFileManagerFolder )
+        {
+        // Handle folders
+        err = iFs.MkDir( *iDst ); // Try faster way first
+        LOG_IF_ERROR1(
+            err,
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-MkDir,err=%d",
+            err )
+        if ( err != KErrNone && err != KErrCancel )
+            {
+            err = iFs.MkDirAll( *iDst );
+            LOG_IF_ERROR1(
+                err,
+                "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-MkDirAll,err=%d",
+                err )
+            }
+        if ( err == KErrNone )
+            {
+            TEntry entry;
+            err = iFs.Entry( *iSrc, entry );
+            if ( err == KErrNone )
+                {
+                iFs.SetEntry( *iDst, entry.iModified, entry.iAtt, 0 ); // Ignore error
+                }
+            }
+        User::LeaveIfError( err );
+        return;
+        }
+    
+    // Handle files
+    if ( iOperationOnSameDrive &&
+        iOperation == MFileManagerProcessObserver::EMoveProcess )
+        {
+        INFO_LOG(
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-MoveInsideDrive" )
+
+        if ( iSwitch == EOverWrite )
+            {
+            INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Overwrite" )
+
+            err = iFs.Replace( *iSrc, *iDst );
+            }
+        else
+            {
+            INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-NoOverwrite" )
+
+            err = iFs.Rename( *iSrc, *iDst );
+            }
+
+        LOG_IF_ERROR1(
+            err,
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-OnSameDrive,err=%d",
+            err )
+
+        if ( err == KErrNone || err == KErrCancel )
+            {
+            // Optimized move was successful or cancelled
+            User::LeaveIfError( err );
+            // If move the files in the same drive, the application
+            // just calculate the amount of the files, so it should 
+            // notify the observer that how many files have been moved.
+            iBytesTransferredTotal++;
+            TRAP_IGNORE( iObserver.ProcessAdvanceL(
+                iBytesTransferredTotal ) ); 
+            return;
+            }
+        }
+
+    TInt64 fileSize( 0 );
+    RFile64 srcFile;
+
+    // Open source file
+    if ( iOperation == MFileManagerProcessObserver::EMoveProcess )
+        {
+        INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Move" )
+
+        User::LeaveIfError( srcFile.Open(
+            iFs, *iSrc, EFileRead | EFileShareExclusive ) );
+        }
+    else
+        {
+        INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Copy" )
+
+        User::LeaveIfError( srcFile.Open(
+            iFs, *iSrc, EFileRead | EFileShareReadersOnly ) );
+        }
+    CleanupClosePushL( srcFile );
+    User::LeaveIfError( srcFile.Size( fileSize ) );
+
+    // Open destination file
+    RFile64 dstFile;
+    if ( iSwitch == EOverWrite )
+        {
+        INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Overwrite" )
+
+        User::LeaveIfError( dstFile.Replace(
+            iFs, *iDst, EFileWrite | EFileShareExclusive ) );
+        }
+    else
+        {
+        INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-NoOverwrite" )
+
+        User::LeaveIfError( dstFile.Create(
+            iFs, *iDst, EFileWrite | EFileShareExclusive ) );
+        }
+    CleanupClosePushL( dstFile );
+
+    dstFile.SetSize( fileSize ); // Setting the size first speeds up operation
+
+    INFO_LOG1(
+        "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-FileSize=%d",
+         fileSize )
+
+    // Create buffer and copy file data using it. 
+    // Note that buffer size should not be too big to make it is possible 
+    // to cancel the operation in reasonable time from the main thread. 
+
+    // Move these to CenRep to make configuration and fine tuning easier.
+    const TInt64 KBigBufSize = 0x40000; // 256KB
+    const TInt64 KMediumBufSize = 0x10000; // 64KB
+    const TInt64 KSmallBufSize = 0x2000; // 8KB
+
+    HBufC8* buf = HBufC8::New(
+        Max( KSmallBufSize, Min( fileSize, KBigBufSize ) ) );
+    if ( !buf )
+        {
+        buf = HBufC8::New( KMediumBufSize );
+        }
+    if ( !buf )
+        {
+        buf = HBufC8::New( KSmallBufSize );
+        }
+    if ( !buf )
+        {
+        User::Leave( KErrNoMemory );
+        }
+    CleanupStack::PushL( buf );
+
+    TPtr8 block( buf->Des() );
+    
+    INFO_LOG1(
+        "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-BlockSize=%d",
+         block.MaxSize() )
+
+    while ( err == KErrNone && fileSize > 0 )
+        {
+        if ( iThreadWrapper->IsThreadCanceled() )
+            {
+            err = KErrCancel;
+            break;
+            }
+        TInt blockSize( Min( fileSize, static_cast<TInt64>(block.MaxSize() ) ) );
+        err = srcFile.Read( block, blockSize );
+        if ( err == KErrNone )
+            {
+            if ( block.Length() == blockSize )
+                {
+                err = dstFile.Write( block, blockSize );
+                if ( err == KErrNone )
+                    {
+                    fileSize -= blockSize;
+
+                    // Do not update the latest file transfer progress here.
+                    // Flushing file below may take a long time and
+                    // progress indicator should not get full before it.
+                    TRAP_IGNORE( iObserver.ProcessAdvanceL(
+                        iBytesTransferredTotal ) );
+                    iBytesTransferredTotal += blockSize;
+                    }
+                }
+            else
+                {
+                err = KErrCorrupt;
+                }
+            }
+        }
+
+    INFO_LOG2(
+        "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-BytesNotWritten=%d,err=%d",
+         fileSize, err )
+
+    CleanupStack::PopAndDestroy( buf );
+
+    // Copy attributes
+    TTime mod;
+    if ( err == KErrNone )
+        {
+        err = srcFile.Modified( mod );
+
+        INFO_LOG1(
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-ModifiedRead,err=%d",
+            err )
+
+        }
+    if ( err == KErrNone )
+        {
+        err = dstFile.SetModified( mod );
+
+        INFO_LOG1(
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-ModifiedWritten,err=%d",
+            err )
+        }
+    TUint att( 0 );
+    if ( err == KErrNone )
+        {
+        err = srcFile.Att( att );
+
+        INFO_LOG2(
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-AttributesRead,err=%d,att=%d",
+            err, att )
+        }
+    if ( err == KErrNone )
+        {
+        // Ignore fail, because some drives like remote drives
+        // do not support attributes at all
+        dstFile.SetAtt( att, ( ~att ) & KEntryAttMaskSupported );
+
+        INFO_LOG(
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-AttributesWritten" )
+        }
+    // Flush file and finalize transfer progress of this file.
+    // Don't flush if copying failed because it causes save dialog to appear 
+    // when remote drives are involved.
+    if ( err == KErrNone )
+        {
+        err = dstFile.Flush();
+
+        INFO_LOG1(
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Flushed,err=%d",
+            err )
+        }
+    TRAP_IGNORE( iObserver.ProcessAdvanceL( iBytesTransferredTotal ) );
+
+    CleanupStack::PopAndDestroy( &dstFile );
+    CleanupStack::PopAndDestroy( &srcFile );
+
+    // Delete source if move was succesful so far
+    if ( err == KErrNone &&
+        iOperation == MFileManagerProcessObserver::EMoveProcess )
+        {
+        // Ensure that read-only is removed before delete
+        if ( att & KEntryAttReadOnly )
+            {
+            CFileManagerUtils::RemoveReadOnlyAttribute( iFs, *iSrc );
+            }
+        err = iFs.Delete( *iSrc );
+
+        INFO_LOG1(
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-MoveSourceDeleted,err=%d",
+            err )
+        }
+
+    // Delete incomplete destination if error
+    if ( err != KErrNone )
+        {
+        // Ensure that read-only is removed before delete
+        if ( att & KEntryAttReadOnly )
+            {
+            CFileManagerUtils::RemoveReadOnlyAttribute( iFs, *iDst );
+            }
+        iFs.Delete( *iDst );
+
+        ERROR_LOG1(
+            "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-FailedDstDeleted,fail=%d",
+            err )
+        }
+
+    User::LeaveIfError( err );
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::IsThreadDone()
+//
+// -----------------------------------------------------------------------------
+//
+TBool CFileManagerActiveExecute::IsThreadDone()
+    {
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::NotifyThreadClientL()
+//
+// -----------------------------------------------------------------------------
+//
+void CFileManagerActiveExecute::NotifyThreadClientL(
+        TNotifyType aType, TInt aValue )
+    {
+    switch ( aType )
+        {
+        case ENotifyStepFinished:
+            {
+            CompleteL( aValue );
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::AppendArrayIfNotFound()
+//
+// -----------------------------------------------------------------------------
+//
+void CFileManagerActiveExecute::AppendArrayIfNotFound(
+        CDesCArray& aArray, const TDesC& aFullPath )
+    {
+    // Append if not already appended to the last item
+    TBool append( ETrue );
+    TInt count( aArray.MdcaCount() );
+    if ( count > 0 )
+        {
+        TPtrC ptr( aArray.MdcaPoint( count - 1 ) );
+        if ( !ptr.Compare( aFullPath ) )
+            {
+            append = EFalse;
+            }
+        }
+    if ( append )
+        {
+        TRAPD( err, aArray.AppendL( aFullPath ) );
+        if ( err != KErrNone )
+            {
+            ERROR_LOG1(
+                "CFileManagerActiveExecute::AppendArrayIfNotFound-err=%d",
+                err )
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::FlushArray()
+//
+// -----------------------------------------------------------------------------
+//
+void CFileManagerActiveExecute::FlushArray( CDesCArray& aArray )
+    {
+    if ( aArray.MdcaCount() > 0 )
+        {
+//        TRAP_IGNORE( iMgxFileManager->UpdateL( aArray ) );
+        aArray.Reset();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::UpdateNotifications()
+//
+// -----------------------------------------------------------------------------
+//
+void CFileManagerActiveExecute::UpdateNotifications(
+        TBool aFlush, TInt aError )
+    {
+    // Append notification item if operation was successful and 
+    // item does not already exist
+    if ( aError == KErrNone && iSrc && iDst && iItemType == EFileManagerFile )
+        {
+        // Notifications are relevant only for local drives
+        if ( iOperation == MFileManagerProcessObserver::EMoveProcess &&
+             !iIsSrcRemoteDrive )
+            {
+            AppendArrayIfNotFound( *iChangedSrcItems, *iSrc );
+            }
+        if ( !iIsDstRemoteDrive )
+            {
+            AppendArrayIfNotFound( *iChangedDstItems, *iDst );
+            }
+        }
+    if ( aFlush )
+        {
+        FlushArray( *iChangedSrcItems );
+        FlushArray( *iChangedDstItems );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::ThreadFinalizeMoveStepL()
+//
+// -----------------------------------------------------------------------------
+//
+void CFileManagerActiveExecute::ThreadFinalizeMoveStepL()
+    {
+    FUNC_LOG
+
+    HBufC* folderToDelete = HBufC::NewLC( KMaxFileName );
+    TPtr ptrFolderToDelete( folderToDelete->Des() );
+    CDirScan* dirScan = CDirScan::NewLC( iFs );
+    dirScan->SetScanDataL( 
+        *iFullPath, 
+        KEntryAttNormal|KEntryAttHidden|KEntryAttSystem|
+        KEntryAttDir|KEntryAttMatchExclusive, 
+        ESortNone, 
+        CDirScan::EScanUpTree );
+    CDir* dir = NULL;
+    dirScan->NextL( dir );
+    while( dir )
+        {
+        CFileManagerUtils::RemoveReadOnlyAttribute(
+            iFs, dirScan->FullPath() );
+        CleanupStack::PushL( dir );
+        TInt count( dir->Count() );
+        for( TInt i( 0 ); i < count; ++i )
+            {
+            if ( iThreadWrapper->IsThreadCanceled() )
+                {
+                User::Leave( KErrCancel );
+                }
+            TPtrC abbrPath( dirScan->AbbreviatedPath() );
+            const TEntry& entry( ( *dir )[ i ] );
+            ptrFolderToDelete.Copy( *iFullPath );
+            ptrFolderToDelete.Append( 
+                abbrPath.Right( abbrPath.Length() - 1 ) );
+            ptrFolderToDelete.Append( entry.iName );
+            ptrFolderToDelete.Append( KFmgrBackslash );
+#ifdef __KEEP_DRM_CONTENT_ON_PHONE
+            if ( iSrc && iDst &&
+                CFileManagerUtils::IsFromInternalToRemovableDrive( iFs, *iSrc, *iDst ) )
+                {
+                HBufC* targetFolderToDelete = HBufC::NewLC( KMaxFileName );
+                TPtr ptrTargetFolderToDelete( targetFolderToDelete->Des() );
+                ptrTargetFolderToDelete.Append( *iDestination );
+                ptrTargetFolderToDelete.Append( 
+                    abbrPath.Right( abbrPath.Length() - 1 ) );
+                ptrTargetFolderToDelete.Append( entry.iName );
+                ptrTargetFolderToDelete.Append( KFmgrBackslash );
+                
+                if ( IsEmptyDir( ptrFolderToDelete ) )
+                    {
+                    User::LeaveIfError( iFs.RmDir( ptrFolderToDelete ) );
+                    }
+                else if ( IsEmptyDir( ptrTargetFolderToDelete ))
+                    {
+                    User::LeaveIfError( iFs.RmDir( ptrTargetFolderToDelete ) );
+                    }
+                CleanupStack::PopAndDestroy( targetFolderToDelete );    
+                }
+            else
+                {
+                User::LeaveIfError( iFs.RmDir( ptrFolderToDelete ) );   
+                }
+#else
+            User::LeaveIfError( iFs.RmDir( ptrFolderToDelete ) );
+#endif
+            }
+        if ( iThreadWrapper->IsThreadCanceled() )
+            {
+            User::Leave( KErrCancel );
+            }
+        CleanupStack::PopAndDestroy( dir );
+        dir = NULL;
+        dirScan->NextL( dir );
+        }
+    CleanupStack::PopAndDestroy( dirScan );
+    CleanupStack::PopAndDestroy( folderToDelete );
+#ifdef __KEEP_DRM_CONTENT_ON_PHONE
+    if ( iSrc && iDst &&
+        CFileManagerUtils::IsFromInternalToRemovableDrive( iFs, *iSrc, *iDst ) )
+        {
+        if ( IsEmptyDir( *iFullPath ) )
+            {
+            User::LeaveIfError( iFs.RmDir( *iFullPath ) );
+            }   
+        }
+    else
+        {
+        User::LeaveIfError( iFs.RmDir( *iFullPath ) );  
+        }
+#else
+    User::LeaveIfError( iFs.RmDir( *iFullPath ) );
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::ThreadStepL()
+//
+// -----------------------------------------------------------------------------
+//
+void CFileManagerActiveExecute::ThreadStepL()
+    {
+    FUNC_LOG
+
+    if ( !iFinalizeMove )
+        {
+        ThreadCopyOrMoveStepL();
+        }
+    else
+        {
+        ThreadFinalizeMoveStepL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFileManagerActiveExecute::ToFolder()
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC CFileManagerActiveExecute::ToFolder()
+    {
+    if ( iToFolder )
+        {
+        return iToFolder->Des();
+        }
+    return TPtrC( KNullDesC );
+    }
+
+// End of File