memspy/Engine/Source/Helpers/MemSpyEngineHelperFileSystem.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:57:15 +0200
changeset 0 a03f92240627
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 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:
*
*/

#include <memspy/engine/memspyenginehelperfilesystem.h>

// System includes
#include <f32file.h>

// Driver includes
#include <memspy/driver/memspydriverclient.h>

// User includes
#include <memspy/engine/memspyengine.h>
#include <memspy/engine/memspyengineobjectthread.h>
#include <memspy/engine/memspyengineobjectprocess.h>
#include <memspy/engine/memspyengineutils.h>
#include <memspy/engine/memspyenginehelperchunk.h>
#include <memspy/engine/memspyengineoutputsink.h>
#include <memspy/engine/memspyengineoutputlist.h>
#include "MemSpyEngineOutputListItem.h"

// Remap of E32 constant since this value only exists in recent v9.3 builds and MemSpy needs to build on v9.1
const TUint KMemSpyDriveAttPageable = 0x100; // KDriveAttPageable
const TUint KMemSpyMediaAttPageable = 0x200; // KMediaAttPageable

// Literal constants
_LIT( KMemSpyVolumeLabelNotSet, "None" );


CMemSpyEngineHelperFileSystem::CMemSpyEngineHelperFileSystem( CMemSpyEngine& aEngine )
:   iEngine( aEngine )
    {
    }

    
CMemSpyEngineHelperFileSystem::~CMemSpyEngineHelperFileSystem()
    {
    }


void CMemSpyEngineHelperFileSystem::ConstructL()
    {
    iFileServerProcessId = MemSpyEngineUtils::IdentifyFileServerProcessIdL();
    }


CMemSpyEngineHelperFileSystem* CMemSpyEngineHelperFileSystem::NewL( CMemSpyEngine& aEngine )
    {
    CMemSpyEngineHelperFileSystem* self = new(ELeave) CMemSpyEngineHelperFileSystem( aEngine );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }


EXPORT_C CMemSpyEngineDriveList* CMemSpyEngineHelperFileSystem::DriveListL()
    {
    CMemSpyEngineDriveList* list = CMemSpyEngineDriveList::NewLC( iEngine.FsSession() );
    CleanupStack::Pop( list );
    return list;
    }


EXPORT_C TDriveNumber CMemSpyEngineHelperFileSystem::GetSystemDrive()
    {
    TDriveNumber ret = EDriveC;
#ifndef __WINS__
    const TInt KRFsGetSystemDriveOrdinal = 336;
    typedef TDriveNumber(*TRFsGetSystemDriveFunc)();
    //
    RLibrary lib;
    const TInt loadErr = lib.Load( _L("EFSRV.DLL") );
#ifdef _DEBUG
    RDebug::Printf( "CMemSpyEngineHelperFileSystem::GetSystemDrive() - dll load: %d", loadErr );
#endif
    if  ( loadErr == KErrNone )
        {
        TLibraryFunction ordinal = lib.Lookup( KRFsGetSystemDriveOrdinal );
#ifdef _DEBUG
        RDebug::Printf( "CMemSpyEngineHelperFileSystem::GetSystemDrive() - ordinal: 0x%08x", ordinal );
#endif
        //
        if  ( ordinal )
            {
            TRFsGetSystemDriveFunc func = (TRFsGetSystemDriveFunc) ordinal;
            ret = (*func)();
#ifdef _DEBUG
            RDebug::Printf( "CMemSpyEngineHelperFileSystem::GetSystemDrive() - drive: %c:\\", 'A' + ret);
#endif
            }
        //
        lib.Close();
        }
#endif
    //
    return ret;
    }


EXPORT_C void CMemSpyEngineHelperFileSystem::ListOpenFilesL()
    {
    TOpenFileScan scanner( iEngine.FsSession() );

    _LIT( KMemSpyContext, "Open File Listing" );
    _LIT( KMemSpyFolder, "OpenFiles" );
    iEngine.Sink().DataStreamBeginL( KMemSpyContext, KMemSpyFolder );

    _LIT(KHeading, "OPEN FILES");
    iEngine.Sink().OutputSectionHeadingL( KHeading, '=' );
    
    // Set prefix for overall listing
    _LIT(KOverallPrefix, "OpenFiles - ");
    iEngine.Sink().OutputPrefixSetLC( KOverallPrefix );

    CFileList* list = NULL;
    scanner.NextL( list );
    while( list != NULL )
        {
        CleanupStack::PushL( list );
        ListOpenFilesL( *list, scanner.ThreadId() );
        CleanupStack::PopAndDestroy( list );
        //
        list = NULL;
        scanner.NextL( list );
        }

    CleanupStack::PopAndDestroy(); // prefix
    iEngine.Sink().DataStreamEndL();
    }


EXPORT_C void CMemSpyEngineHelperFileSystem::ListOpenFilesL( const TThreadId& aThreadId )
    {
    TOpenFileScan scanner( iEngine.FsSession() );

    _LIT( KMemSpyContext, "Open File Listing" );
    _LIT( KMemSpyFolder, "OpenFiles" );
    iEngine.Sink().DataStreamBeginL( KMemSpyContext, KMemSpyFolder );

    _LIT(KHeading, "OPEN FILES");
    iEngine.Sink().OutputSectionHeadingL( KHeading, '=' );
    
    // Set prefix for overall listing
    _LIT(KOverallPrefix, "OpenFiles - ");
    iEngine.Sink().OutputPrefixSetLC( KOverallPrefix );

    CFileList* list = NULL;
    scanner.NextL( list );
    while( list != NULL )
        {
        if  ( scanner.ThreadId() == aThreadId )
            {
            CleanupStack::PushL( list );
            ListOpenFilesL( *list, scanner.ThreadId() );
            CleanupStack::Pop( list );
            }
        //
        delete list;
        list = NULL;
        scanner.NextL( list );
        }

    CleanupStack::PopAndDestroy(); // prefix
    iEngine.Sink().DataStreamEndL();
    }


void CMemSpyEngineHelperFileSystem::GetDriveNumberText( TDriveNumber aDriveNumber, TDes& aText )
    {
    const TInt offset = aDriveNumber - EDriveA;
    const TChar driveChar = 'A' + offset;
    aText.Copy( _L("EDrive") );
    aText.Append( driveChar );
    }


void CMemSpyEngineHelperFileSystem::ListOpenFilesL( const CFileList& aList, const TThreadId& aThreadId )
    {
    _LIT( KLineFormatSpec, "%d %S %S %S %S" );
    TBuf<64> timeBuf;
    TMemSpySizeText valueBuf;

    HBufC* itemBuf = HBufC::NewLC( 3 * KMaxFullName );
    TPtr item( itemBuf->Des() );

    TFullName threadName;
    RThread thread;
    if  ( iEngine.Driver().OpenThread( aThreadId, thread ) == KErrNone )
        {
        threadName = thread.FullName();
        thread.Close();
        }

    const TInt entryCount = aList.Count();
    for(TInt i=0; i<entryCount; i++)
        {
        const TEntry& entry = aList[ i ];

        // Get time and size format strings
        valueBuf = MemSpyEngineUtils::FormatSizeText( entry.iSize );
        MemSpyEngineUtils::FormatTimeL( timeBuf, entry.iModified );

        // Create item 
        item.Format( KLineFormatSpec, 0, &entry.iName, &valueBuf, &timeBuf, &threadName );
        iEngine.Sink().OutputLineL( item );
        }

    CleanupStack::PopAndDestroy( itemBuf );
    }


CMemSpyEngineOpenFileList* CMemSpyEngineHelperFileSystem::ListOpenFilesLC()
    {
    CMemSpyEngineOpenFileList* list = CMemSpyEngineOpenFileList::NewLC( iEngine );
    return list;
    }


TProcessId CMemSpyEngineHelperFileSystem::FileServerProcessId() const
    {
    return iFileServerProcessId;
    }


const CMemSpyEngineChunkEntry* CMemSpyEngineHelperFileSystem::IdentifyCacheChunk( const CMemSpyEngineChunkList& aList, TInt& aIndex ) const
    {
    aIndex = KErrNotFound;
    const CMemSpyEngineChunkEntry* ret = NULL;
    //
    const TInt count = aList.Count();
    for( TInt i=0; i<count; i++ )
        {
        const CMemSpyEngineChunkEntry& entry = aList.At( i );
        const TMemSpyDriverChunkInfo& info = entry.Info();
        //
        if  ( info.iType == EMemSpyDriverChunkTypeLocal )
            {
#ifdef _DEBUG
            RDebug::Print( _L("CMemSpyEngineHelperFileSystem::IdentifyCacheChunk() - name: %S, pid: 0x%04x, f32Pid: 0x%04x, size: %d, max: %d, attribs: %d"), &info.iName, info.iOwnerId, (TUint) iFileServerProcessId, info.iSize, info.iMaxSize, info.iAttributes );
#endif

            if ( info.iOwnerId == FileServerProcessId() )
                {
                // Additionally, the chunk is disconnected.
                const TBool isDisconnected = ( info.iAttributes & EMemSpyChunkAttributesDisconnected );
#ifdef _DEBUG
                RDebug::Printf( "CMemSpyEngineHelperFileSystem::IdentifyCacheChunk() - it is an f32 local chunk... isDisconnected: %d", isDisconnected );
#endif

                if  ( info.iSize > 0 && info.iMaxSize > 0 && isDisconnected )
                    {
                    aIndex = i;
                    ret = &entry;
#ifdef _DEBUG
                    RDebug::Print( _L("CMemSpyEngineHelperFileSystem::IdentifyCacheChunk() - FOUND: %S, size: %d"), &info.iName, info.iSize );
#endif
                    break;
                    }
                }
            }
        }
    //
#ifdef _DEBUG
    RDebug::Printf( "CMemSpyEngineHelperFileSystem::IdentifyCacheChunk() - END - ret: 0x%08x", ret );
#endif
    return ret;
    }





















CMemSpyEngineDriveList::CMemSpyEngineDriveList( RFs& aFsSession )
:   CActive( EPriorityStandard ), iFsSession( aFsSession )
    {
    CActiveScheduler::Add( this );
    }


EXPORT_C CMemSpyEngineDriveList::~CMemSpyEngineDriveList()
    {
    Cancel();
    //
    iItems.ResetAndDestroy();
    iItems.Close();
    }


void CMemSpyEngineDriveList::ConstructL()
    {
    TDriveList drives;
    if  ( iFsSession.DriveList( drives ) == KErrNone )
        {
        for( TInt i=EDriveA; i<=EDriveZ; i++ )
            {
            const TDriveNumber drive = static_cast< TDriveNumber >( i );
            if  ( drives[ i ] != KDriveAbsent )
                {
                TRAP_IGNORE( 
                    CMemSpyEngineDriveEntry* driveEntry = CMemSpyEngineDriveEntry::NewLC( *this, drive );
                    iItems.AppendL( driveEntry );
                    CleanupStack::Pop( driveEntry );
                    );
                }
            }
        }

    iFsSession.NotifyChange( ENotifyDisk, iStatus );
    SetActive();
    }


CMemSpyEngineDriveList* CMemSpyEngineDriveList::NewLC( RFs& aFsSession )
    {
    CMemSpyEngineDriveList* self = new(ELeave) CMemSpyEngineDriveList( aFsSession );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }


void CMemSpyEngineDriveList::RunL()
    {
    iFsSession.NotifyChange( ENotifyDisk, iStatus );
    SetActive();
    //
    NotifyListChangedL();
    }


void CMemSpyEngineDriveList::DoCancel()
    {
    iFsSession.NotifyChangeCancel();
    }


EXPORT_C void CMemSpyEngineDriveList::SetObserver( MMemSpyEngineDriveListObserver* aObserver )
    {
    iObserver = aObserver;
    }


EXPORT_C TInt CMemSpyEngineDriveList::Count() const
    {
    return iItems.Count();
    }


EXPORT_C CMemSpyEngineDriveEntry& CMemSpyEngineDriveList::At( TInt aIndex )
    {
    return *iItems[ aIndex ];
    }


EXPORT_C const CMemSpyEngineDriveEntry& CMemSpyEngineDriveList::At( TInt aIndex ) const
    {
    return *iItems[ aIndex ];
    }


EXPORT_C TInt CMemSpyEngineDriveList::ItemIndex( const CMemSpyEngineDriveEntry& aEntry ) const
    {
    TInt ret = KErrNotFound;
    //
    const TInt count = Count();
    for( TInt i=0; i<count; i++ )
        {
        const CMemSpyEngineDriveEntry* item = iItems[ i ];
        //
        if  ( item == &aEntry )
            {
            ret = i;
            break;
            }
        }
    //
    return ret;
    }


EXPORT_C CMemSpyEngineDriveEntry* CMemSpyEngineDriveList::EntryByDriveNumber( TDriveNumber aDrive )
    {
    CMemSpyEngineDriveEntry* ret = NULL;
    //
    const TInt count = Count();
    for( TInt i=0; i<count; i++ )
        {
        CMemSpyEngineDriveEntry* item = iItems[ i ];
        //
        if  ( item->DriveNumber() == aDrive )
            {
            ret = item;
            break;
            }
        }
    //
    return ret;
    }


RFs& CMemSpyEngineDriveList::FsSession()
    {
    return iFsSession;
    }


void CMemSpyEngineDriveList::NotifyListChangedL()
    {
    if  ( iObserver != NULL )
        {
        TRAP_IGNORE( iObserver->HandleDriveListChangedL( *this ) );
        }
    }


EXPORT_C TInt CMemSpyEngineDriveList::MdcaCount() const
    {
    return Count();
    }


EXPORT_C TPtrC CMemSpyEngineDriveList::MdcaPoint( TInt aIndex ) const
    {
    const CMemSpyEngineDriveEntry& item = At( aIndex );
    return TPtrC( item.Caption() );
    }


















CMemSpyEngineDriveEntry::CMemSpyEngineDriveEntry( CMemSpyEngineDriveList& aList, TDriveNumber aDriveNumber )
:   CActive( CActive::EPriorityStandard), iList( aList ), iDriveNumber( aDriveNumber ), iDriveUnit( aDriveNumber )
    {
    CActiveScheduler::Add( this );
    }


EXPORT_C CMemSpyEngineDriveEntry::~CMemSpyEngineDriveEntry()
    {
    Cancel();
    //
    delete iCaption;
    delete iItems;
    }


void CMemSpyEngineDriveEntry::ConstructL()
    {
    RunL();
    }


EXPORT_C void CMemSpyEngineDriveEntry::SetObserver( MMemSpyEngineDriveEntryObserver* aObserver )
    {
    iObserver = aObserver;
    }


void CMemSpyEngineDriveEntry::RefreshL()
    {
    CMemSpyEngineOutputList* items = CMemSpyEngineOutputList::NewL();
    delete iItems;
    iItems = items;

    /*
	RFs13VolumeIOParamEiR18TVolumeIOParamInfo @ 344 NONAME
	RFs17FileSystemSubTypeEiR6TDes16 @ 345 NONAME
	RFs18QueryVolumeInfoExtEi22TQueryVolumeInfoExtCmdR5TDes8 @ 346 NONAME
    */
    const TInt err1 = FsSession().Drive( iDriveInfo, iDriveNumber );
    const TInt err2 = FsSession().Volume( iVolumeInfo, iDriveNumber );
    if  ( err1 || err2 )
        {
        _LIT( KUnavailable, "Unavailable");
        iItems->AddItemL( KUnavailable );

        // Mostly empty caption
        CreateCaptionL( KNullDesC, KNullDesC );
        }
    else
        {
        // Literal constants
        TBuf<KMaxFileName * 2> temp;
        TBuf<KMaxFileName * 2> item;

        AddStandardFieldsL();

        _LIT( KEntry2a, "Media Type");
        TBuf<20> mediaType;
        GetMediaTypeText( iDriveInfo.iType, mediaType );
        iItems->AddItemL( KEntry2a, mediaType );

        _LIT( KEntry2b, "Battery Status");
        GetBatteryState( iDriveInfo.iBattery, temp );
        iItems->AddItemL( KEntry2b, temp );

        // Now have enough data to create caption
        CreateCaptionL( iVolumeInfo.iName, mediaType );
        
        CreateDriveAttributesL( item );
        CreateMediaAttributesL( item );

        _LIT( KEntry3a, "Volume Name");
        if  ( iVolumeInfo.iName.Length() )
            {
            iItems->AddItemL( KEntry3a, iVolumeInfo.iName );
            }
        else
            {
            iItems->AddItemL( KEntry3a, KMemSpyVolumeLabelNotSet );
            }

        _LIT( KEntry3, "Volume UID");
        iItems->AddItemHexL( KEntry3, iVolumeInfo.iUniqueID );

        _LIT( KEntry4, "Volume Size");
        temp = MemSpyEngineUtils::FormatSizeText( iVolumeInfo.iSize );
        iItems->AddItemL( KEntry4, temp );

        _LIT( KEntry5, "Volume Free");
        temp = MemSpyEngineUtils::FormatSizeText( iVolumeInfo.iFree );
        iItems->AddItemL( KEntry5, temp );

        TMediaSerialNumber serialNum;
        if  ( FsSession().GetMediaSerialNumber( serialNum, iDriveNumber ) == KErrNone )
            {
            _LIT( KEntry6, "Serial Number");
            TBuf<KMaxSerialNumLength> serialNumUnicode;
            serialNumUnicode.Copy( serialNum );
            iItems->AddItemL( KEntry6, serialNumUnicode );
            }

        if  ( FsSession().FileSystemName( temp, iDriveNumber ) == KErrNone )
            {
            _LIT( KEntry7, "File System");
            iItems->AddItemL( KEntry7, temp );
            }
        }
    }


CMemSpyEngineDriveEntry* CMemSpyEngineDriveEntry::NewLC( CMemSpyEngineDriveList& aList, TDriveNumber aDriveNumber )
    {
    CMemSpyEngineDriveEntry* self = new(ELeave) CMemSpyEngineDriveEntry( aList, aDriveNumber );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }


void CMemSpyEngineDriveEntry::CreateDriveAttributesL( TDes& aItemBuf )
    {
    TInt driveAttribIndex = 0;
    _LIT( KEntryText, "Drive Attribute %d");

    if  ( iDriveInfo.iDriveAtt & KDriveAttLocal )
        {
        _LIT( KAttribName, "Local" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iDriveAtt & KDriveAttRom )
        {
        _LIT( KAttribName, "ROM" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iDriveAtt & KDriveAttRedirected )
        {
        _LIT( KAttribName, "Redirected" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iDriveAtt & KDriveAttSubsted )
        {
        _LIT( KAttribName, "Substed" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iDriveAtt & KDriveAttInternal )
        {
        _LIT( KAttribName, "Internal" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iDriveAtt & KDriveAttRemovable )
        {
        _LIT( KAttribName, "Removable" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iDriveAtt & KDriveAttRemote )
        {
        _LIT( KAttribName, "Remote" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iDriveAtt & KDriveAttTransaction )
        {
        _LIT( KAttribName, "Transaction" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iDriveAtt & KMemSpyDriveAttPageable )
        {
        _LIT( KAttribName, "Pageable" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iDriveAtt & KDriveAttRemovable )
        {
        _LIT( KAttribName, "Removable" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    }


void CMemSpyEngineDriveEntry::CreateMediaAttributesL( TDes& aItemBuf )
    {
    TInt driveAttribIndex = 0;
    _LIT( KEntryText, "Media Attribute %d");

    if  ( iDriveInfo.iMediaAtt & KMediaAttVariableSize )
        {
        _LIT( KAttribName, "Variable Size" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iMediaAtt & KMediaAttDualDensity )
        {
        _LIT( KAttribName, "Dual Density" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iMediaAtt & KMediaAttFormattable )
        {
        _LIT( KAttribName, "Formattable" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iMediaAtt & KMediaAttWriteProtected )
        {
        _LIT( KAttribName, "Write Protected" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iMediaAtt & KMediaAttLockable )
        {
        _LIT( KAttribName, "Lockable" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iMediaAtt & KMediaAttLocked )
        {
        _LIT( KAttribName, "Locked" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iMediaAtt & KMediaAttHasPassword )
        {
        _LIT( KAttribName, "Has Password" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iMediaAtt & KMediaAttReadWhileWrite )
        {
        _LIT( KAttribName, "Read-while-Write" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iMediaAtt & KMediaAttDeleteNotify )
        {
        _LIT( KAttribName, "Delete Notify" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    if  ( iDriveInfo.iMediaAtt & KMemSpyMediaAttPageable )
        {
        _LIT( KAttribName, "Pageable" );
        aItemBuf.Format( KEntryText, ++driveAttribIndex );
        iItems->AddItemL( aItemBuf, KAttribName );
        }
    }


void CMemSpyEngineDriveEntry::AddStandardFieldsL()
    {
    _LIT( KEntry1, "Unit Name");
    const TDriveName driveUnitName = iDriveUnit.Name();
    iItems->AddItemL( KEntry1, driveUnitName );

    _LIT( KEntry2, "Unit Number");
    TBuf<30> temp;
    CMemSpyEngineHelperFileSystem::GetDriveNumberText( iDriveNumber, temp );
    iItems->AddItemL( KEntry2, temp );

    const TDriveNumber sysDrive = GetSystemDrive();
    if  ( sysDrive == iDriveNumber )
        {
        _LIT( KEntry3, "System Drive");
        iItems->AddItemYesNoL( KEntry3, ETrue );
        }
    }


void CMemSpyEngineDriveEntry::CreateCaptionL( const TDesC& aVolumeName, const TDesC& aMediaType )
    {
    TBuf<256 * 2> caption;

    // Always include drive unit name
    const TDriveName driveUnitName = iDriveUnit.Name();
    caption.AppendFormat( _L("\t%S"), &driveUnitName );

    // If we have a volume name, then include that too
    if  ( aVolumeName.Length() )
        {
        caption.AppendFormat( _L(" [%S]"), &aVolumeName );
        }
    
    // New line
    caption.Append( _L("\t\t") );

    // Include media type if known, or unknown otherwise
    if  ( aMediaType.Length() )
        {
        caption.Append( aMediaType );
        }
    else
        {
        _LIT( KUnknownMediaType, "Unknown" );
        caption.Append( KUnknownMediaType );
        }

    HBufC* finalCaption = caption.AllocL();
    delete iCaption;
    iCaption = finalCaption;
    }

void CMemSpyEngineDriveEntry::GetMediaTypeText( TMediaType aType, TDes& aText )
    {
    switch( aType )
        {
    case EMediaNotPresent:
        aText.Copy( _L("Not Present") );
        break;
    case EMediaFloppy:
        aText.Copy( _L("Floppy") );
        break;
    case EMediaHardDisk:
        aText.Copy( _L("Hard Disk") );
        break;
    case EMediaCdRom:
        aText.Copy( _L("CD-ROM") );
        break;
    case EMediaRam:
        aText.Copy( _L("RAM") );
        break;
    case EMediaFlash:
        aText.Copy( _L("Flash") );
        break;
    case EMediaRom:
        aText.Copy( _L("ROM") );
        break;
    case EMediaRemote:
        aText.Copy( _L("Remote") );
        break;
    case EMediaNANDFlash:
        aText.Copy( _L("NAND Flash") );
        break;
    default:
    case EMediaUnknown:
        aText.Copy( _L("Unknown") );
        break;
        }
    }


void CMemSpyEngineDriveEntry::GetBatteryState( TBatteryState aBatteryState, TDes& aText )
    {
    switch( aBatteryState )
        {
    case EBatNotSupported:
        aText.Copy( _L("Not Supported") );
        break;
    case EBatGood:
        aText.Copy( _L("Good") );
        break;
    case EBatLow:
        aText.Copy( _L("Low") );
        break;
    default:
        aText.Copy( _L("Unknown") );
        break;
        }
    }


TDriveNumber CMemSpyEngineDriveEntry::GetSystemDrive()
    {
    return CMemSpyEngineHelperFileSystem::GetSystemDrive();
    }


EXPORT_C TInt CMemSpyEngineDriveEntry::MdcaCount() const
    {
    return iItems->Count();
    }


EXPORT_C TPtrC CMemSpyEngineDriveEntry::MdcaPoint( TInt aIndex ) const
    {
    return iItems->MdcaPoint( aIndex );
    }


void CMemSpyEngineDriveEntry::RunL()
    {
    FsSession().NotifyChange( ENotifyDisk, iStatus );
    SetActive();
    //
    TRAP_IGNORE( RefreshL() );
    //
    if ( iObserver != NULL )
        {
        TRAP_IGNORE( iObserver->HandleDriveEntryChangedL( *this ) );
        }
    }


void CMemSpyEngineDriveEntry::DoCancel()
    {
    FsSession().NotifyChangeCancel();
    }


RFs& CMemSpyEngineDriveEntry::FsSession()
    {
    return iList.FsSession();
    }



































CMemSpyEngineOpenFileListEntry::CMemSpyEngineOpenFileListEntry()
    {
    }


CMemSpyEngineOpenFileListEntry::~CMemSpyEngineOpenFileListEntry()
    {
    delete iFileName;
    }


void CMemSpyEngineOpenFileListEntry::ConstructL( const TEntry& aEntry )
    {
    iFileName = aEntry.iName.AllocL();
    iAtt = aEntry.iAtt;
    iType = aEntry.iType;
    iSize = aEntry.iSize;
    iModified = aEntry.iModified;
    }


CMemSpyEngineOpenFileListEntry* CMemSpyEngineOpenFileListEntry::NewLC( const TEntry& aEntry )
    {
    CMemSpyEngineOpenFileListEntry* self = new(ELeave) CMemSpyEngineOpenFileListEntry();
    CleanupStack::PushL( self );
    self->ConstructL( aEntry );
    return self;
    }


EXPORT_C const TDesC& CMemSpyEngineOpenFileListEntry::FileName() const
    {
    return *iFileName;
    }


EXPORT_C TInt CMemSpyEngineOpenFileListEntry::Size() const
    {
    return iSize;
    }


TInt CMemSpyEngineOpenFileListEntry::UniqueFileId() const
    {
    return iUniqueFileIdentifier;
    }


void CMemSpyEngineOpenFileListEntry::SetUniqueFileId( TInt aValue )
    {
    iUniqueFileIdentifier = aValue;
    }

























CMemSpyEngineOpenFileListForThread::CMemSpyEngineOpenFileListForThread( const TThreadId& aThreadId, const TProcessId& aProcessId )
:   iThreadId( aThreadId ), iProcessId( aProcessId )
    {
    }


CMemSpyEngineOpenFileListForThread::~CMemSpyEngineOpenFileListForThread()
    {
    iItems.ResetAndDestroy();
    iItems.Close();
    delete iThreadName;
    }


void CMemSpyEngineOpenFileListForThread::ConstructL( const TDesC& aThreadName, const CFileList& aList )
    {
    iThreadName = aThreadName.AllocL();

    // Create fs entries
    const TInt entryCount = aList.Count();
    for(TInt i=0; i<entryCount; i++)
        {
        const TEntry& fsEntry = (aList)[ i ];
        //
        CMemSpyEngineOpenFileListEntry* entry = CMemSpyEngineOpenFileListEntry::NewLC( fsEntry );
        AddL( entry );
        CleanupStack::Pop( entry );
        }
    }


CMemSpyEngineOpenFileListForThread* CMemSpyEngineOpenFileListForThread::NewLC( const TDesC& aThreadName, const TThreadId& aThreadId, const TProcessId& aProcessId, const CFileList& aList )
    {
    CMemSpyEngineOpenFileListForThread* self = new(ELeave) CMemSpyEngineOpenFileListForThread( aThreadId, aProcessId );
    CleanupStack::PushL( self );
    self->ConstructL( aThreadName, aList );
    return self;
    }


EXPORT_C const TDesC& CMemSpyEngineOpenFileListForThread::ThreadName() const
    {
    return *iThreadName;
    }


EXPORT_C const TThreadId& CMemSpyEngineOpenFileListForThread::ThreadId() const
    {
    return iThreadId;
    }


EXPORT_C const TProcessId& CMemSpyEngineOpenFileListForThread::ProcessId() const
    {
    return iProcessId;
    }


EXPORT_C TInt CMemSpyEngineOpenFileListForThread::Count() const
    {
    return iItems.Count();
    }


EXPORT_C const CMemSpyEngineOpenFileListEntry& CMemSpyEngineOpenFileListForThread::At( TInt aIndex ) const
    {
    return *iItems[ aIndex ];
    }
 

void CMemSpyEngineOpenFileListForThread::AddL( CMemSpyEngineOpenFileListEntry* aEntry )
    {
    // Ensure we increment the unique filename counter if adding an entry where the same filename
    // already is registered with the list.
    CMemSpyEngineOpenFileListEntry* existingEntry = EntryByFileName( aEntry->FileName() );
    if  ( existingEntry )
        {
        // EntryByFileName() always returns the most recent entry with the same name. The list
        // itself is not sorted as entries are always appended to it.
        const TInt lastUID = existingEntry->UniqueFileId();
#ifdef _DEBUG
        RDebug::Print( _L("CMemSpyEngineOpenFileListForThread::AddL() - searched for %S and found existing entry with UID: %d"), &aEntry->FileName(), lastUID );
#endif

        aEntry->SetUniqueFileId( lastUID + 1 );
        }

    iItems.AppendL( aEntry );
    }


CMemSpyEngineOpenFileListEntry* CMemSpyEngineOpenFileListForThread::EntryByFileName( const TDesC& aFileName )
    {
    CMemSpyEngineOpenFileListEntry* ret = NULL;
    //
    const TInt count = iItems.Count();
    for( TInt i=count-1; i>=0; i-- )
        {
        CMemSpyEngineOpenFileListEntry* item = iItems[ i ];
        if  ( item->FileName().CompareF( aFileName ) == 0 )
            {
            ret = item;
            break;
            }
        }
    //
    return ret;
    }










CMemSpyEngineOpenFileList::CMemSpyEngineOpenFileList()
    {
    }


EXPORT_C CMemSpyEngineOpenFileList::~CMemSpyEngineOpenFileList()
    {
    iItems.ResetAndDestroy();
    iItems.Close();
    }


void CMemSpyEngineOpenFileList::ConstructL( CMemSpyEngine& aEngine )
    {
    _LIT( KUnknownThread, "Unknown Thread" );
    TFullName threadName;
    TOpenFileScan scanner( aEngine.FsSession() );
    //
    CFileList* list = NULL;
    scanner.NextL( list );
    while( list != NULL )
        {
        CleanupStack::PushL( list );

        // Reset name
        threadName = KUnknownThread;
        
        // Try to get real thread name
        TProcessId procId;
        RThread thread;
        if  ( aEngine.Driver().OpenThread( scanner.ThreadId(), thread ) == KErrNone )
            {
            RProcess process;
            if ( thread.Process( process ) == KErrNone )
                {
                procId = process.Id();
                process.Close();
                }
            //
            thread.FullName( threadName );
            thread.Close();
            }

        // Create thread entry
        CMemSpyEngineOpenFileListForThread* threadEntry = CMemSpyEngineOpenFileListForThread::NewLC( threadName, scanner.ThreadId(), procId, *list );
        iItems.AppendL( threadEntry );
        CleanupStack::Pop( threadEntry );

        // Destroy list and move on to next thread.
        CleanupStack::PopAndDestroy( list );
        list = NULL;
        scanner.NextL( list );
        }
    }


CMemSpyEngineOpenFileList* CMemSpyEngineOpenFileList::NewLC( CMemSpyEngine& aEngine )
    {
    CMemSpyEngineOpenFileList* self = new(ELeave) CMemSpyEngineOpenFileList();
    CleanupStack::PushL( self );
    self->ConstructL( aEngine );
    return self;
    }


EXPORT_C TInt CMemSpyEngineOpenFileList::Count() const
    {
    return iItems.Count();
    }


EXPORT_C const CMemSpyEngineOpenFileListForThread& CMemSpyEngineOpenFileList::At( TInt aIndex ) const
    {
    return *iItems[ aIndex ];
    }