harvester/monitorplugins/mdsfileserverplugin/src/mdsfileserverplugin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 19 Aug 2010 10:20:41 +0300
branchRCL_3
changeset 19 b73252188534
parent 14 3e156c80c15d
permissions -rw-r--r--
Revision: 201031 Kit: 201033

/*
* Copyright (c) 2006-2009 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:  Monitors file creations, modifications and deletions.*
*/


#include <f32pluginutils.h>
#include "mdsfileserverplugin.h"
#include "harvesterlog.h"
#include "mdsutils.h"

_LIT( KMdsFileServerPlugin, "MdsFileServerPlugin" );
_LIT( KExludedThumbPath, "\\_PAlbTN\\");
_LIT( KExludedMediaArtPath, "\\.mediaartlocal\\");

/* Server name */
_LIT( KHarvesterServerName, "HarvesterServer" );

const TInt KCleanQueueTreshold( 1000 );

//-----------------------------------------------------------------------------
// CMdsFileServerPlugin implementation
//-----------------------------------------------------------------------------
//
CMdsFileServerPlugin::CMdsFileServerPlugin()
: iFormatOldMediaId( 0 ), iFormatDriveNumber( -1 ), iConnectionCount( 0 )
	{
	WRITELOG( "CMdsFileServerPlugin::CMdsFileServerPlugin()" );
	}
	
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
CMdsFileServerPlugin::~CMdsFileServerPlugin()
    {
    WRITELOG( "CMdsFileServerPlugin::~CMdsFileServerPlugin()" );
    
#ifdef _DEBUG
    TRAPD( error, DisableL() );
    _LIT( KPanicCategory,"CMdsFileServerPlugin" );
    __ASSERT_DEBUG( error == KErrNone, User::Panic( KPanicCategory,  error ) );
#else
    TRAP_IGNORE( DisableL() );    
#endif
    
    iCreatedFiles.ResetAndDestroy();
    iCreatedFiles.Close();
    
    iModifiedFiles.ResetAndDestroy();
    iModifiedFiles.Close();
  
    iPaths.ResetAndDestroy();
    iPaths.Close();
    
    iIgnorePaths.ResetAndDestroy();
    iIgnorePaths.Close();
        
    iQueue.ResetAndDestroy();
    iQueue.Close();
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
CMdsFileServerPlugin* CMdsFileServerPlugin::NewL()
    {
    WRITELOG( "CMdsFileServerPlugin::NewL()" );
    return new (ELeave) CMdsFileServerPlugin;
    }

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
void CMdsFileServerPlugin::InitialiseL()
    {
    WRITELOG( "CMdsFileServerPlugin::InitializeL()" );
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
void CMdsFileServerPlugin::EnableL()
    {
    WRITELOG( "CMdsFileServerPlugin::EnableL()" );
    User::LeaveIfError( RegisterIntercept(EFsFileCreate, EPostIntercept) );
    User::LeaveIfError( RegisterIntercept(EFsFileRename, EPostIntercept) );
    User::LeaveIfError( RegisterIntercept(EFsRename, EPostIntercept) );
    User::LeaveIfError( RegisterIntercept(EFsDelete, EPostIntercept) );
    User::LeaveIfError( RegisterIntercept(EFsFileReplace, EPostIntercept) );
    User::LeaveIfError( RegisterIntercept(EFsReplace, EPostIntercept) );
    User::LeaveIfError( RegisterIntercept(EFsFileSetModified, EPostIntercept) );
    User::LeaveIfError( RegisterIntercept(EFsFileSubClose, EPostIntercept) );
    User::LeaveIfError( RegisterIntercept(EFsSetEntry, EPostIntercept) );
	// format events
	User::LeaveIfError( RegisterIntercept(EFsFormatSubClose, EPostIntercept) );
	User::LeaveIfError( RegisterIntercept(EFsFormatOpen, EPreIntercept) );

#ifdef _DEBUG_EVENTS
    RegisterDebugEventsL();
#endif
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
void CMdsFileServerPlugin::DisableL()
    {
    WRITELOG( "CMdsFileServerPlugin::DisableL()" );
    User::LeaveIfError( UnregisterIntercept(EFsFileCreate, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept(EFsFileRename, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept(EFsRename, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept(EFsDelete, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept(EFsFileReplace, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept(EFsReplace, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept(EFsFileSetModified, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept(EFsFileSubClose, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept(EFsSetEntry, EPrePostIntercept) );
	// format events
	User::LeaveIfError( UnregisterIntercept(EFsFormatSubClose, EPostIntercept) );
	User::LeaveIfError( UnregisterIntercept(EFsFormatOpen, EPreIntercept) );

#ifdef _DEBUG_EVENTS
    UnregisterDebugEventsL();
#endif
    }
    
//-----------------------------------------------------------------------------
// AddConnection
//-----------------------------------------------------------------------------
//
void CMdsFileServerPlugin::AddConnection()
    {
    WRITELOG( "CMdsFileServerPlugin::AddConnection()" );
    
    ++iConnectionCount;
    iPendingEvents = 0;
    }

//-----------------------------------------------------------------------------
// RemoveConnection
//-----------------------------------------------------------------------------
//
void CMdsFileServerPlugin::RemoveConnection()
    {
    WRITELOG( "CMdsFileServerPlugin::RemoveConnection()" );

    --iConnectionCount;

    // remove notification request if this was last connection
    if( iConnectionCount <= 0 )
    	{
    	WRITELOG( "CMdsFileServerPlugin::RemoveConnection() last connection" );
    	
    	iNotification = NULL;
    	iPendingEvents = 0;
    	iQueue.ResetAndDestroy();
    	iQueue.Compress();
    	}
    }

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
TInt CMdsFileServerPlugin::DoRequestL( TFsPluginRequest& aRequest )
	{
	// ignore event if there are not any clients listening
	if( iConnectionCount <= 0 )
		{
		WRITELOG( "CMdsFileServerPlugin::DoRequestL() - no clients -> ignore event" );
		return KErrNone;
		}
	
	TInt function = aRequest.Function();
	
	iFileName.Zero();
    iNewFileName.Zero();
	
#ifdef _DEBUG_EVENTS
    PrintDebugEvents( function );
#endif
    
    if ( function == EFsFileSubClose && iCreatedFiles.Count() == 0 )
        {
#ifdef _DEBUG_EVENTS
        if( GetName( &aRequest, iFileName ) == KErrNone && iFileName.Length() <= KMaxFileName )
            {
            WRITELOG1("Dropping subclose %S",&iFileName);
            }
#endif
        return KErrNone;
        }
    
    const TBool formatFunction( function == EFsFormatOpen || function == EFsFormatSubClose );
        
    WRITELOG1( "----- CMdsFileServerPlugin::DoRequestL() - plugin function: %d -----", function );

	if ( !formatFunction )
		{
		if( GetName( &aRequest, iFileName ) != KErrNone || iFileName.Length() > KMaxFileName )
		    {
		    return KErrNone;
		    }
		else
		    {
		    WRITELOG1( "CMdsFileServerPlugin::DoRequestL() - fileName: %S", &iFileName );
		    }
		}

    // get process id
	TUid processId = aRequest.Message().SecureId();

	TBool isDirectory = EFalse;
	
    // if rename, check destination path
    if ( function == EFsRename  || function == EFsFileRename || 
    	 function == EFsReplace || function == EFsFileReplace  ||
    	 function == EFsSetEntry )
        {
        const TInt newNameErr = GetNewName( &aRequest, iNewFileName );
        if ( iNewFileName.Length() > KMaxFileName )
        	{
        	return KErrNone;
        	}
        WRITELOG2( "CMdsFileServerPlugin::DoRequestL() - newFileName: '%S' %d", &iNewFileName, newNameErr );
        TBool setToBeDeleted( EFalse );
        if ( newNameErr == KErrNone )
            {
            if ( !CheckPath(iNewFileName) )
                {
                WRITELOG( "CMdsFileServerPlugin::DoRequestL() - new path not supported" );
                if( !CheckPath(iFileName) )
                    {
                    WRITELOG( "CMdsFileServerPlugin::DoRequestL() - old path not supported" );
                    WRITELOG( "CMdsFileServerPlugin::DoRequestL() - ignore file" );
                    return KErrNone;
                    }
                // file moved to ignored path, delete from db
                function = EFsDelete;
                setToBeDeleted = ETrue;
                }
            
            if( !setToBeDeleted )
                {
                RFsPlugin fsPlugin( aRequest ); 
                const TInt rfsPluginErr = fsPlugin.Connect();
            
                if ( ( rfsPluginErr == KErrNone ) && !CheckAttribs( iNewFileName, isDirectory, fsPlugin, EFalse ) )
                    {
                    WRITELOG( "CMdsFileServerPlugin::DoRequestL() - new path attribute check failed" );
                    if( !CheckAttribs(iFileName, isDirectory, fsPlugin, EFalse) )
                        {
                        WRITELOG( "CMdsFileServerPlugin::DoRequestL() - old path attribute check failed" );
                        WRITELOG( "CMdsFileServerPlugin::DoRequestL() - ignore file" );
                        fsPlugin.Close();
                        return KErrNone;
                        }
                    // file set to hidden, delete from db
                    function = EFsDelete;
                    }
                fsPlugin.Close();
                }
            }
        else
        	{
            if( !CheckIfValidFile(iFileName, isDirectory, aRequest, EFalse)  )
                {
                return KErrNone;
                }
        	}
        }
    else if ( !formatFunction )
        {
        const TBool deleteFunction( function == EFsDelete );
        if( !CheckIfValidFile(iFileName, isDirectory, aRequest, deleteFunction)  )
            {
            return KErrNone;
            }
        }

    TInt fileEventType = EMdsFileUnknown;
    TInt drvNumber = aRequest.DriveNumber();
    TVolumeInfo volInfo;

    WRITELOG1( "CMdsFileServerPlugin::DoRequestL() - drive number: %d", drvNumber );

    TInt err( KErrNone );
    
    switch( function )
        {
        case EFsFileCreate:
            {
#ifdef _DEBUG            
            if (function == EFsFileCreate)
                {
            	WRITELOG( "CMdsFileServerPlugin::DoRequestL() - EFsFileCreate" );
                }
#endif            
            
            HBufC* createdFileName = iFileName.Alloc();
            if( createdFileName )
                {
                // Ownership transferred if succeeded
                const TInt appendError( iCreatedFiles.Append( createdFileName ) );
                if( appendError != KErrNone )
                    {
                    delete createdFileName;
                    createdFileName = NULL;
                    }
                }
            return KErrNone;
            }

        case EFsFileSubClose:
            {
            WRITELOG( "CMdsFileServerPlugin::DoRequestL() - EFsFileSubClose" );

            TBool found = EFalse;

           	for ( TInt i = iCreatedFiles.Count(); --i >= 0; )
            		{
           			if ( MdsUtils::Compare( iFileName, *(iCreatedFiles[i]) ) == 0 )
            		  {
            			fileEventType = EMdsFileCreated;
            			delete iCreatedFiles[i];
            			iCreatedFiles[i] = NULL;
            			iCreatedFiles.Remove( i );
            			
						//Have to check whether file has been hidden          			
            	        RFsPlugin fsPlugin( aRequest ); 
            	        const TInt rfsPluginError( fsPlugin.Connect() );
            	        if( (rfsPluginError == KErrNone) && CheckAttribs( iFileName, isDirectory, fsPlugin, EFalse ) )
            	            {
            	            found = ETrue;
            	            }
            	        else if( rfsPluginError != KErrNone )
            	            {
            	            found = ETrue;
            	            }
            	        fsPlugin.Close();
            			}
            		}
           	
           	if( iCreatedFiles.Count() == 0 )
				{
				iCreatedFiles.GranularCompress();
				}
            
            if ( !found )
                {
                return KErrNone;
                }
            }
            break;

        case EFsRename:
            {
            WRITELOG1( "CMdsFileServerPlugin::DoRequestL() - EFsRename, new file: %S", &iNewFileName );
            
            if ( isDirectory )
            	{
				WRITELOG( "CMdsFileServerPlugin::DoRequestL() - it is directory!" );			
				fileEventType = EMdsDirRenamed;
				AddBackslashIfNeeded( iNewFileName ); // new file name 
				AddBackslashIfNeeded( iFileName ); // old file name
            	}
            else
            	{
            	fileEventType = EMdsFileRenamed;
            	}
            }
            break;

        case EFsFileRename:
            WRITELOG1( "CMdsFileServerPlugin::DoRequestL() - EFsFileRename, new file: %S", &iNewFileName );
            fileEventType = EMdsFileRenamed;
            break;

        case EFsFileSetModified:
            {
            WRITELOG( "CMdsFileServerPlugin::DoRequestL() - EFsFileSetModified" );
            
            for ( TInt i = iCreatedFiles.Count(); --i >= 0; )
                {
                // If file has been created but not closed, do not handle modified events
                // for that file before the application that has created the file is done with writing 
                // it to the disk.
                if ( MdsUtils::Compare( iFileName, *(iCreatedFiles[i]) ) == 0 )
                    {
                    return KErrNone;
                    }
                } 

            HBufC* modifiedFileName = iFileName.Alloc();
            if( modifiedFileName )
                {
                // Ownership transferred if succeeded
                const TInt appendError( iModifiedFiles.Append( modifiedFileName ) );
                if( appendError != KErrNone )
                    {
                    delete modifiedFileName;
                    modifiedFileName = NULL;
                    }
                }
            
            fileEventType = EMdsFileModified;
            }
            break;

        case EFsSetEntry:
            {
            WRITELOG( "CMdsFileServerPlugin::DoRequestL() - EFsSetEntry" );

            TBool found = EFalse;

            for ( TInt i = iModifiedFiles.Count(); --i >= 0; )
                    {
                    if ( MdsUtils::Compare( iFileName, *(iModifiedFiles[i]) ) == 0 )
                      {
                        delete iModifiedFiles[i];
                        iModifiedFiles[i] = NULL;
                        iModifiedFiles.Remove( i );
                        found = ETrue;
                        }
                    }
            
            if( iModifiedFiles.Count() == 0 )
                {
                iModifiedFiles.GranularCompress();
                }
            
            if ( found )
                {
                return KErrNone;
                }
            
            fileEventType = EMdsFileAttribsChanged;
            }
            break;            
            
        case EFsFileReplace:
        case EFsReplace:
            WRITELOG1( "CMdsFileServerPlugin::DoRequestL() - EFsReplace/EFsFileReplace, new file: %S", &iNewFileName );
            fileEventType = EMdsFileReplaced;
            break;

        case EFsDelete:
            WRITELOG( "CMdsFileServerPlugin::DoRequestL() - EFsDelete" );
            fileEventType = EMdsFileDeleted;
            break;

		case EFsFormatOpen:
		    {
			WRITELOG( "CMdsFileServerPlugin::DoRequestL() - EFsFormatOpen" );
			// get the drive letter
		    RFsPlugin fsPlugin( aRequest ); 
		    err = fsPlugin.Connect();
	        if( err == KErrNone )
	            {
	            err = fsPlugin.Volume( volInfo, drvNumber );
	            }
	        fsPlugin.Close();
	        
			if( KErrNone == err )
				{
				iFormatOldMediaId = volInfo.iUniqueID;
				iFormatDriveNumber = drvNumber;
				fileEventType = EMdsDriveFormatted;
				processId.iUid = 0;
				}
			else
				{
				iFormatDriveNumber = -1;
				}
			return KErrNone;
		    }

		case EFsFormatSubClose:
			WRITELOG( "CMdsFileServerPlugin::DoRequestL() - EFsFormatSubClose" );
			if ( iFormatDriveNumber < 0 )
				{
				return KErrNone;
				}
			drvNumber = iFormatOldMediaId;
			volInfo.iUniqueID = iFormatOldMediaId;
			iFormatOldMediaId = 0;
			iFormatDriveNumber = -1;
			fileEventType = EMdsDriveFormatted;
			if ( processId.iUid == 0 )
				{
				processId.iUid = 1;
				}
			break;

        default:
            WRITELOG( "CMdsFileServerPlugin::DoRequestL() - Unknown function" );
            return KErrNone;
        }

    if ( iNotification )
        {
        WRITELOG( "CMdsFileServerPlugin::DoRequestL() - iNotification found" );
        TMdsFSPStatusPckg clientStatusBuf;
        TMdsFSPStatus& clientStatus = clientStatusBuf();
        clientStatus.iDriveNumber = drvNumber;
        clientStatus.iDriveMediaId = volInfo.iUniqueID;
        clientStatus.iFileName.Copy( iFileName );
        clientStatus.iNewFileName.Copy( iNewFileName );
        clientStatus.iFileEventType = fileEventType;
        clientStatus.iProcessId = processId;

        TRAP( err, iNotification->WriteParam1L(clientStatusBuf) );
        iNotification->Complete( err );
        iNotification = NULL;
        WRITELOG( "CMdsFileServerPlugin::DoRequestL() - iNotification complete" );
        }
    else // no notification ready, put in the queue
        {
        WRITELOG( "CMdsFileServerPlugin::DoRequestL() - iNotification not found. Put in the queue" );

        // Check if harvester is still alive
        if( CheckHarvesterStatus() )
            {
            CMdsFSPQueueItem* queueItem = CMdsFSPQueueItem::NewL();
            CleanupStack::PushL( queueItem );
            queueItem->iDriveNumber = drvNumber;
            queueItem->iDriveMediaId = volInfo.iUniqueID;
            queueItem->iFileName = iFileName.AllocL();
            queueItem->iNewFileName = iNewFileName.AllocL();
            queueItem->iFileEventType = fileEventType;
            queueItem->iProcessId = processId;

            iQueue.AppendL( queueItem ); // owenership is transferred
            CleanupStack::Pop( queueItem );
            err = KErrNone;
            iPendingEvents++;
            WRITELOG( "CMdsFileServerPlugin::DoRequestL() - added to queue" );
            }
        else
            {
            WRITELOG( "CMdsFileServerPlugin::DoRequestL() - Harvester process not detected" );
            iConnectionCount = 0;
            iPendingEvents = 0;
            iQueue.ResetAndDestroy();
            iQueue.Compress();
            }
        }
    
    WRITELOG( "CMdsFileServerPlugin::DoRequestL() - return" );
    return err;
    }

//-----------------------------------------------------------------------------
// CMdsFileServerPluginConn implementation
//-----------------------------------------------------------------------------
class CMdsFileServerPluginConn : public CFsPluginConn
    {
    public:
        static CMdsFileServerPluginConn* NewL( CMdsFileServerPlugin& aPlugin );
        virtual ~CMdsFileServerPluginConn();

        virtual TInt DoControl( CFsPluginConnRequest& aRequest );
        virtual void DoRequest( CFsPluginConnRequest& aRequest );
        virtual void DoCancel( TInt aReqMask );

    private:
    	CMdsFileServerPluginConn( CMdsFileServerPlugin& aPlugin );

    	CMdsFileServerPlugin& iPlugin;

        RMessage2* iMessage;
    };
    
/**
* Leaving New function for the plugin
* @internalComponent
*/
CMdsFileServerPluginConn* CMdsFileServerPluginConn::NewL( 
		CMdsFileServerPlugin& aPlugin )
    {
    WRITELOG( "CMdsFileServerPluginConn::NewL()" );
    return new (ELeave) CMdsFileServerPluginConn( aPlugin );
    }


/**
* Constructor for the plugin
* @internalComponent
*/
CMdsFileServerPluginConn::CMdsFileServerPluginConn( 
		CMdsFileServerPlugin& aPlugin ) : 
		iPlugin( aPlugin )
    {
    WRITELOG( "CMdsFileServerPluginConn::CMdsFileServerPluginConn()" );
    
    iPlugin.AddConnection();
    }


/**
* The destructor.
* @internalComponent
*/
CMdsFileServerPluginConn::~CMdsFileServerPluginConn()
    {
    WRITELOG( "CMdsFileServerPluginConn::~CMdsFileServerPluginConn()" );
    
    iPlugin.RemoveConnection();
    }

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
TInt CMdsFileServerPluginConn::DoControl( CFsPluginConnRequest& aRequest )
    {
    WRITELOG( "CMdsFileServerPluginConn::DoControl()" );
    TInt err = KErrNotSupported;
    
    CMdsFileServerPlugin& myPlugin = *(CMdsFileServerPlugin*)Plugin();
    
    switch( aRequest.Function() )
        {
        case EMdsFSPOpEnable:
            {
            WRITELOG( "CMdsFileServerPluginConn::DoControl() - EMdsFSPOpEnable" );
            TRAP( err, myPlugin.EnableL() );
            break;
            }
        
        case EMdsFSPOpDisable:
            {
            WRITELOG( "CMdsFileServerPluginConn::DoControl() - EMdsFSPOpDisable" );
            TRAP( err, myPlugin.DisableL() );
            break;
            }
        
        default:
            {
            WRITELOG( "CMdsFileServerPluginConn::DoControl() - Unknown Control" );
            break;            
            }
        }

    return err;
    }
    

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
void CMdsFileServerPluginConn::DoRequest( CFsPluginConnRequest& aRequest )
    {
    WRITELOG( "CMdsFileServerPluginConn::DoRequest()" );
    CMdsFileServerPlugin& myPlugin = *(CMdsFileServerPlugin*)Plugin();
    
    switch( aRequest.Function() )
        {
        case EMdsFSPOpRegisterNotification:
            {
            WRITELOG( "CMdsFileServerPluginConn::DoControl() - EMdsFSPOpRegisterNotification" );
            const TInt err = myPlugin.RegisterNotification( aRequest );
            
            if ( err != KErrNone )
                {
                aRequest.Complete( err );
                }
            break;
            }
            
        case EMdsFSPOpAddNotificationPath:
            {
            WRITELOG( "CMdsFileServerPluginConn::DoControl() - EMdsFSPOpAddNotificationPath" );
            const TInt err = myPlugin.AddNotificationPath( aRequest );
            aRequest.Complete( err );
            break;
            }
            
        case EMdsFSPOpRemoveNotificationPath:
            {
            WRITELOG( "CMdsFileServerPluginConn::DoControl() - EMdsFSPOpRemoveNotificationPath" );
            const TInt err = myPlugin.RemoveNotificationPath( aRequest );
            aRequest.Complete( err );
            break;
            }
            
        case EMdsFSPOpAddIgnorePath:
            {
            WRITELOG( "CMdsFileServerPluginConn::DoControl() - EMdsFSPOpAddIgnorePath" );
            const TInt err = myPlugin.AddIgnorePath( aRequest );
            aRequest.Complete( err );
            break;
            }
            
        case EMdsFSPOpRemoveIgnorePath:
            {
            WRITELOG( "CMdsFileServerPluginConn::DoControl() - EMdsFSPOpRemoveIgnorePath" );
            const TInt err = myPlugin.RemoveIgnorePath( aRequest );
            aRequest.Complete( err );
            break;
            }
        default:
            break;
        }
    }

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
void CMdsFileServerPluginConn::DoCancel( TInt /*aReqMask*/ )
    {
    WRITELOG( "CMdsFileServerPluginConn::DoCancel()" );
    iRequestQue.DoCancelAll( KErrCancel );
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
CFsPluginConn* CMdsFileServerPlugin::NewPluginConnL()
    {
    WRITELOG( "CMdsFileServerPluginConn::NewPluginConnL()" );
    return CMdsFileServerPluginConn::NewL( *this );
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
TInt CMdsFileServerPlugin::RegisterNotification( CFsPluginConnRequest& aRequest )
    {
    WRITELOG( "CMdsFileServerPlugin::RegisterNotification()" );
    
    if ( iNotification )
        {
        return KErrInUse;
        }
    
    iNotification = &aRequest;
    
    if ( iQueue.Count() > 0 )
        {
        WRITELOG( "CMdsFileServerPlugin::RegisterNotification() - item in queue" );
        
        CMdsFSPQueueItem* queueItem = iQueue[0];
        
        TMdsFSPStatusPckg pckg;
        TMdsFSPStatus& status = pckg();
        
        queueItem->GetAsFspStatus( status );

        TRAPD( err, iNotification->WriteParam1L(pckg) );
        iNotification->Complete( err );
        iNotification = NULL;
        
        delete queueItem;
        queueItem = NULL;
        iQueue.Remove( 0 );
        }
    else
    	{
    	iQueue.GranularCompress();
    	}
    
    return KErrNone;
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
TInt CMdsFileServerPlugin::AddNotificationPath( const CFsPluginConnRequest& aRequest )
    {
    WRITELOG( "CMdsFileServerPlugin::AddNotificationPath()" );
    TInt err( KErrNone );
    
    TMdsFSPStatusPckg pckg;
    TRAP( err, aRequest.ReadParam1L(pckg) );
    
    if ( err != KErrNone )
        {
        return err;
        }
    
    TMdsFSPStatus& status = pckg();
    
    if ( status.iFileName.Length() > 0 )
        {
        // check if already exist
        const TInt ret = iPaths.FindInOrder(&status.iFileName,
                                     TLinearOrder<TDesC>(CMdsFileServerPlugin::Compare));

        if( ret >= 0 )
            {
            return KErrNone;
            }     

        WRITELOG1( "CMdsFileServerPlugin::AddNotificationPath() - add path: %S", &status.iFileName );
        HBufC* fn = status.iFileName.Alloc();
        if ( fn )
            {
            const TInt insertError( iPaths.InsertInOrder(fn, TLinearOrder<TDesC>(CMdsFileServerPlugin::Compare)));
            if( insertError != KErrNone )
                {
                delete fn;
                fn = NULL;
                }
            }
        else
            {
            err = KErrNoMemory;
            }
        }
    else
        {
        err = KErrNotFound;
        }
        
    return err;
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
TInt CMdsFileServerPlugin::RemoveNotificationPath( const CFsPluginConnRequest& aRequest )
    {
    WRITELOG( "CMdsFileServerPlugin::RemoveNotificationPath()" );
    TInt err( KErrNone );
    
    TMdsFSPStatusPckg pckg;
    TRAP( err, aRequest.ReadParam1L(pckg) );
    
    if ( err != KErrNone )
        {
        return err;
        }
    
    TMdsFSPStatus& status = pckg();
    
    if ( status.iFileName.Length() > 0 )
        {
        const TInt ret = iPaths.FindInOrder(&status.iFileName,
                                     TLinearOrder<TDesC>(CMdsFileServerPlugin::Compare));

        if( ret >= 0 )
            {
            WRITELOG1( "CMdsFileServerPlugin::RemoveNotificationPath() - remove path: %S", &status.iFileName );
            delete iPaths[ret];
            iPaths[ret] = NULL;
            iPaths.Remove( ret );
            }    
        iPaths.Compress();
        }
    else
        {
        err = KErrNotFound;
        }
        
    return err;
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
TInt CMdsFileServerPlugin::AddIgnorePath( const CFsPluginConnRequest& aRequest )
    {
    WRITELOG( "CMdsFileServerPlugin::AddIgnorePath()" );
    TInt err( KErrNone );
    
    TMdsFSPStatusPckg pckg;
    TRAP( err, aRequest.ReadParam1L(pckg) );
    
    if ( err != KErrNone )
        {
        return err;
        }
    
    TMdsFSPStatus& status = pckg();
    
    if ( status.iFileName.Length() > 0 )
        {
        // check if already exist
        const TInt ret = iIgnorePaths.FindInOrder(&status.iFileName,
                                     TLinearOrder<TDesC>(CMdsFileServerPlugin::Compare));
    
        if( ret >= 0 )
            {
            return KErrNone;
            }
            
        WRITELOG1( "CMdsFileServerPlugin::AddIgnorePath() - add path: %S", &status.iFileName );
        HBufC* fn = status.iFileName.Alloc();
        if ( fn )
            {
            const TInt insertError( iIgnorePaths.InsertInOrder(fn, TLinearOrder<TDesC>(CMdsFileServerPlugin::Compare))); 
            if( insertError != KErrNone )
                {
                delete fn;
                fn = NULL;
                }
            }
        else
            {
            err = KErrNoMemory;
            }
        }
    else
        {
        err = KErrNotFound;
        }
        
    return err;
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
TInt CMdsFileServerPlugin::RemoveIgnorePath( const CFsPluginConnRequest& aRequest )
    {
    WRITELOG( "CMdsFileServerPlugin::RemoveIgnorePath()" );
    TInt err( KErrNone );
    
    TMdsFSPStatusPckg pckg;
    TRAP( err, aRequest.ReadParam1L(pckg) );
    
    if ( err != KErrNone )
        {
        return err;
        }
    
    TMdsFSPStatus& status = pckg();
    
    if ( status.iFileName.Length() > 0 )
        {
        const TInt ret = iIgnorePaths.FindInOrder(&status.iFileName,
                                     TLinearOrder<TDesC>(CMdsFileServerPlugin::Compare));

        if( ret >= 0 )
            {
            WRITELOG1( "CMdsFileServerPlugin::RemoveIgnorePath() - remove path: %S", &status.iFileName );
            delete iIgnorePaths[ret];
            iIgnorePaths[ret] = NULL;
            iIgnorePaths.Remove( ret );
            }    
        iIgnorePaths.Compress();
        }
    else
        {
        err = KErrNotFound;
        }
        
    return err;
    }
    
//-----------------------------------------------------------------------------
// CheckPath
//-----------------------------------------------------------------------------
//
TBool CMdsFileServerPlugin::CheckPath( const TDesC& aFilename ) const
    {
    // check if ignored pathlist   
#ifdef __WINSCW__
    // start checking from beginning of list as if the path is ignored, there
    // is higher possibility that it is located on beginning side of the list
    const TInt count( iIgnorePaths.Count() );
    for ( TInt i = 0; i < count; i++ )   
#else    
    for ( TInt i = iIgnorePaths.Count(); --i >= 0; )    
#endif
        {    
        TDesC* pathName = iIgnorePaths[i];
        if ( MdsUtils::Find( aFilename, *pathName ) != KErrNotFound )
            {
            return EFalse;
            }
        else if( MdsUtils::Find( aFilename, KExludedThumbPath ) != KErrNotFound )
            {
            return EFalse;
            }
        else if( MdsUtils::Find( aFilename, KExludedMediaArtPath ) != KErrNotFound )
            {
            return EFalse;
            }
        }

    // check if notification path
    if ( iPaths.Count() > 0 )
        {
#ifdef __WINSCW__
        // start checking from beginning of list as if the path is supported, there
        // is higher possibility that it is located on beginning side of the list
        const TInt count( iPaths.Count() );
        for ( TInt i = 0; i < count; i++ )   
#else            
        for ( TInt i = iPaths.Count(); --i >= 0; )
#endif
            {
            TDesC* pathName = iPaths[i];
            if ( MdsUtils::Find( aFilename, *pathName ) != KErrNotFound )
                {
                return ETrue;
                }
            }
        }
    else
        {
        return ETrue;
        }

    return EFalse;
    }

//-----------------------------------------------------------------------------
// CheckAttribs
//-----------------------------------------------------------------------------
//
TBool CMdsFileServerPlugin::CheckAttribs( const TDesC& aFilename, 
		TBool& aIsDirectory, RFsPlugin& aFsPlugin, TBool aDelete ) const
	{
	// find last backslash from filename and 
    // take drive and path from filename including last backslash
    const TChar KBackslashChar( '\\' );
    TInt pos = aFilename.LocateReverse( KBackslashChar );
    if ( KErrNotFound == pos )
    	{
    	return ETrue;
    	}
    TPtrC path( aFilename.Left( pos + 1 ) );

    TEntry entry;

    // check if path is hidden 
    TInt err = aFsPlugin.Entry( path, entry );
    if ( err == KErrNone )
        {      
        if ( entry.iAtt & KEntryAttHidden )
            {
            return EFalse;
            }
        }

    if( !aDelete )
        {
        // check if the file hidden or system file
        err = aFsPlugin.Entry( aFilename, entry );
        if ( err == KErrNone )
            {
            if ( entry.iAtt & KEntryAttHidden || entry.iAtt & KEntryAttSystem )
                {
                return EFalse;
                }
        
            aIsDirectory = entry.iAtt & KEntryAttDir ? ETrue : EFalse;
            }    
        }

    return ETrue;
    }

//-----------------------------------------------------------------------------
// AddBackslashIfNeeded
//-----------------------------------------------------------------------------
//
void CMdsFileServerPlugin::AddBackslashIfNeeded( TDes& aDirName ) const
	{
	WRITELOG1( "CMdsFileServerPlugin::AddBackslashIfNeeded() - begin, dirName: %S", &aDirName );

	const TChar KBackslashChar( '\\' );
	
	const TInt lastChar = aDirName.Length() - 1;
	
	// If it is directory which not contain backslash. 
	if ( KBackslashChar != aDirName[lastChar] )
		{		
		aDirName.Append( KBackslashChar );
		}

	WRITELOG1( "CMdsFileServerPlugin::AddBackslashIfNeeded() - end, dirName: %S", &aDirName );
	}

//-----------------------------------------------------------------------------
// CheckHarvesterStatus
//-----------------------------------------------------------------------------
//
TBool CMdsFileServerPlugin::CheckHarvesterStatus()
    {
    WRITELOG( "CMdsFileServerPlugin::CheckHarvesterStatus() - begin" );

    if( iPendingEvents <= KCleanQueueTreshold )
        {
        WRITELOG( "CMdsFileServerPlugin::CheckHarvesterStatus() - end" );
        return ETrue;
        }
    
    TFindServer findHarvesterServer( KHarvesterServerName );
    TFullName name;

    TInt result = findHarvesterServer.Next( name );
    if ( result == KErrNone )
        {
        WRITELOG( "CMdsFileServerPlugin::CheckHarvesterStatus() - HarvesterServer running" );
        WRITELOG( "CMdsFileServerPlugin::CheckHarvesterStatus() - end" );
        
        iPendingEvents = 0;
        return ETrue;
        }
    
    WRITELOG( "CMdsFileServerPlugin::CheckHarvesterStatus() - end" );
    return EFalse;
    }

//-----------------------------------------------------------------------------
// CheckIfValidFile
//-----------------------------------------------------------------------------
//
TBool CMdsFileServerPlugin::CheckIfValidFile( const TDesC& aFilename, 
        TBool& aIsDirectory, TFsPluginRequest& aRequest, TBool aDelete )
    {
    if ( !CheckPath(aFilename) )
        {
        WRITELOG( "CMdsFileServerPlugin::CheckIfValidFile() - path not supported" );
        return EFalse;
        }

    RFsPlugin fsPlugin( aRequest ); 
    const TInt rfsPluginErr = fsPlugin.Connect();
    
    if( rfsPluginErr == KErrNone )
        {
        if ( !CheckAttribs(aFilename, aIsDirectory, fsPlugin, aDelete) )
            {
            WRITELOG( "CMdsFileServerPlugin::CheckIfValidFile() - attribute check failed" );
            return EFalse;
            }
        }
    fsPlugin.Close(); 
    
    return ETrue;
    }

//-----------------------------------------------------------------------------
// CMdsFileServerPluginFactory implementation
//-----------------------------------------------------------------------------
//
class CMdsFileServerPluginFactory : public CFsPluginFactory
    {
    public:
        CMdsFileServerPluginFactory();
        virtual TInt Install();            
        virtual CFsPlugin* NewPluginL();
        virtual TInt UniquePosition();
    };
    
// Constructor for the plugin factory
// @internalComponent
CMdsFileServerPluginFactory::CMdsFileServerPluginFactory()
    {
    WRITELOG( "CMdsFileServerPluginFactory::CMdsFileServerPluginFactory()" );
    }

// Install function for the plugin factory
// @internalComponent
TInt CMdsFileServerPluginFactory::Install()
    {
    WRITELOG( "CMdsFileServerPluginFactory::Install()" );
    iSupportedDrives = KPluginAutoAttach;
    
    return( SetName(&KMdsFileServerPlugin) );
    }

// @internalComponent
TInt CMdsFileServerPluginFactory::UniquePosition()
    {
    WRITELOG( "CMdsFileServerPluginFactory::UniquePosition()" );
    return( KMdsFSPluginPosition );
    }

// Plugin factory function
// @internalComponent
CFsPlugin* CMdsFileServerPluginFactory::NewPluginL()
    {
    WRITELOG( "CMdsFileServerPluginFactory::NewPluginL()" );
    return CMdsFileServerPlugin::NewL();
    }

// Create a new Plugin
// @internalComponent
extern "C"
    {
    EXPORT_C CFsPluginFactory* CreateFileSystem()
        {
        WRITELOG( "CMdsFileServerPluginFactory::CreateFileSystem" );
        return( new CMdsFileServerPluginFactory() );
        }
    }

#ifdef _DEBUG_EVENTS

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
void CMdsFileServerPlugin::RegisterDebugEventsL()
    {
    User::LeaveIfError( RegisterIntercept( EFsFileDuplicate, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileCreate, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileWrite, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileFlush, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileSetAtt, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileChangeMode, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsDelete, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileAdopt, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileLock, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileSize, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileRename, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsRename, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileOpen, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileTemp,    EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileUnLock, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileSetSize, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileDrive, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsReplace, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileSubClose, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileRead, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileSeek, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileAtt, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileSet, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsFileName, EPreIntercept) );
    User::LeaveIfError( RegisterIntercept( EFsDirOpen, EPreIntercept) );
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
void CMdsFileServerPlugin::UnregisterDebugEventsL()
    {
    User::LeaveIfError( UnregisterIntercept( EFsFileDuplicate, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileCreate, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileWrite, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileFlush, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileSetAtt, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileChangeMode, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsDelete, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileAdopt, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileLock, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileSize, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileRename, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsRename, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileOpen, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileTemp, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileUnLock, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileSetSize, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileDrive, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsReplace, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileSubClose, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileRead, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileSeek, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileAtt, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileSet, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsFileName, EPrePostIntercept) );
    User::LeaveIfError( UnregisterIntercept( EFsDirOpen, EPrePostIntercept) );
    }
    
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
void CMdsFileServerPlugin::PrintDebugEvents( TInt aFunction )
    {
    switch ( aFunction )
        {
        case EFsFileDuplicate:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileDuplicate" );
            break;
            
        case EFsFileCreate:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileCreate" );
            break;
        case EFsFileWrite:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileWrite" );
            break;
        case EFsFileFlush:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileFlush" );
            break;
        case EFsFileSetAtt:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileSetAtt" );
            break;
        case EFsFileChangeMode:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileChangeMode" );
            break;    
        case EFsDelete:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsDelete" );
            break;    
        case EFsFileAdopt:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileAdopt" );
            break;    
        case EFsFileReplace:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileReplace" );
            break;    
        case EFsFileLock:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileLock" );
            break;    
        case EFsFileSize:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileSize" );
            break;    
        case EFsFileModified:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileModified" );
            break;    
        case EFsFileRename:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileRename" );
            break;    
        case EFsRename:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsRename" );
            break;    
        case EFsFileOpen:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileOpen" );
            break;    
        case EFsFileTemp:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileTemp" );
            break;    
        case EFsFileUnLock:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileUnLock" );
            break;    
        case EFsFileSetSize:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileSetSize" );
            break;    
        case EFsFileSetModified:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileSetModified" );
            break;
        case EFsFileDrive:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileDrive" );
            break;    
        case EFsReplace:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsReplace" );
            break;    
        case EFsFileSubClose:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileSubClose" );
            break;    
        case EFsFileRead:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileRead" );
            break;
        case EFsFileSeek:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileSeek" );
            break;    
        case EFsFileAtt:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileAtt" );
            break;    
        case EFsFileSet:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileSet" );
            break;    
        case EFsFileName:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsFileName" );
            break;    
        case EFsDirOpen:
            WRITELOG( "CMdsFileServerPlugin::PrintDebugEvents() - EFsDirOpen" );
            break;    
        default:
        break;
        }
    }
#endif

TInt CMdsFileServerPlugin::Compare(const TDesC& aFirst, const TDesC& aSecond)
    {
    return aFirst.CompareF( aSecond );
    }