mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/cgetobjectproplist.cpp
changeset 0 a2952bb97e68
child 9 bee149131e4b
child 25 d881023c13eb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/cgetobjectproplist.cpp	Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,863 @@
+/*
+* 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:  Implement the operation: GetObjectPropList
+*
+*/
+
+
+#include <bautils.h>
+#include <e32std.h>
+#include <mtp/mmtpdataproviderframework.h>
+#include <mtp/mmtpobjectmgr.h>
+#include <mtp/cmtptypeobjectproplist.h>
+#include <mtp/cmtptypestring.h>
+#include <mtp/cmtptypearray.h>
+#include <mtp/cmtpobjectmetadata.h>
+
+#include "tobjectdescription.h"
+#include "cgetobjectproplist.h"
+#include "tmmmtpdppanic.h"
+#include "mmmtpdplogger.h"
+#include "mmmtpdpconfig.h"
+#include "mmmtpdputility.h"
+#include "cmmmtpdpmetadataaccesswrapper.h"
+
+static const TUint32 KMTPAll = 0xffffffff;
+_LIT( KMtpDateTimeFormat, "%F%Y%M%DT%H%T%S" );
+const TInt KMtpMaxDateTimeStringLength = 15;
+
+#if defined(_DEBUG) || defined(MMMTPDP_PERFLOG)
+_LIT( KSubFormatParse, "SubFormatParse" );
+#endif
+
+// Verification data for the getObjectPropList request
+const TMTPRequestElementInfo KMTPGetObjectPropListPolicy[] =
+    {
+        {
+        TMTPTypeRequest::ERequestParameter1,
+        EMTPElementTypeObjectHandle,
+        EMTPElementAttrNone,
+        2,
+        KMTPHandleAll,
+        KMTPHandleNone
+        }
+    };
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::~CGetObjectPropList
+// Destructor
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CGetObjectPropList::~CGetObjectPropList()
+    {
+    Cancel();
+
+    delete iObject;
+    delete iPropertyList;
+    delete iPropertyElement;
+    iHandles.Close();
+    iPropertyArray.Close();
+
+#if defined(_DEBUG) || defined(MMMTPDP_PERFLOG)
+    delete iPerfLog;
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::CGetObjectPropList
+// Standard C++ Constructor
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CGetObjectPropList::CGetObjectPropList( MMTPDataProviderFramework& aFramework,
+    MMTPConnection& aConnection,
+    MMmMtpDpConfig& aDpConfig ) :
+    CRequestProcessor( aFramework,
+        aConnection,
+        sizeof ( KMTPGetObjectPropListPolicy ) / sizeof( TMTPRequestElementInfo ),
+        KMTPGetObjectPropListPolicy ),
+    iHandles ( KMmMtpRArrayGranularity ),
+    iDpConfig( aDpConfig ),
+    iPropertyArray( KMmMtpRArrayGranularity )
+    {
+    PRINT( _L( "Operation: GetObjectPropList(0x9805)" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::ConstructL
+// 2nd Phase Constructor
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CGetObjectPropList::ConstructL()
+    {
+    CActiveScheduler::Add( this );
+
+    iPropertyList = CMTPTypeObjectPropList::NewL();
+
+    SetPSStatus();
+
+#if defined(_DEBUG) || defined(MMMTPDP_PERFLOG)
+    iPerfLog = CMmMtpDpPerfLog::NewL( _L( "MediaMtpDataProviderEnumerator" ) );
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::CheckRequestL
+// Verify the reqeust and returns it
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TMTPResponseCode CGetObjectPropList::CheckRequestL()
+    {
+    PRINT( _L( "MM MTP => CGetObjectPropList::CheckRequestL" ) );
+
+    TMTPResponseCode result = CRequestProcessor::CheckRequestL();
+
+    if ( result == EMTPRespCodeOK )
+        {
+        result = CheckFormatL();
+        }
+
+    if ( result == EMTPRespCodeOK )
+        {
+        result = CheckDepth();
+        }
+
+    if ( result == EMTPRespCodeOK )
+        {
+        result = CheckPropCodeL();
+        }
+
+    PRINT1( _L("MM MTP <= CGetObjectPropList::CheckRequestL, response 0x%x"), result );
+
+    return result;
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::ServiceL
+// service a request at request phase
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CGetObjectPropList::ServiceL()
+    {
+    GetObjectHandlesL();
+    TInt numOfObjects = iHandles.Count();
+    PRINT2( _L( "MM MTP <> CGetObjectPropList::ServiceL, numOfObjects = %d, iPropCode = 0x%x" ),
+        numOfObjects,
+        iPropCode );
+    if ( numOfObjects > 0
+        && ( iPropCode == KMTPAll || iPropCode == EMTPObjectPropCodeUndefined ) )
+        {
+        // iFirstUnprocessed = 0;
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete( status, iStatus.Int() );
+        SetActive();
+        }
+    else
+        {
+        TInt err = KErrNone;
+        for ( TInt i = 0; i < numOfObjects; i++ )
+            {
+            TUint32 handle = iHandles[i ];
+
+            if ( iFramework.ObjectMgr().ObjectOwnerId( handle )
+                == iFramework.DataProviderId() )
+                {
+                delete iObject;
+                iObject = NULL;
+                iObject = CMTPObjectMetaData::NewL();
+
+                if ( iFramework.ObjectMgr().ObjectL( handle, *iObject ) ) // Populate the object meta data
+                    {
+                    SetSubFormatCodeL();
+
+                    err = ServiceOneObjectPropertyL( handle, iPropCode );
+                    if ( err != KErrNone && err != KErrNotSupported )
+                        break;
+                    }
+                }
+            }
+        PRINT1( _L( "MM MTP <> CGetObjectPropList::ServiceL, one property was queried, Send data to PC! err = %d" ), err );
+        if ( err == KErrNone  || err == KErrNotSupported )
+            SendDataL( *iPropertyList );
+        else if ( err == KErrNotFound )
+            SendResponseL( EMTPRespCodeAccessDenied );
+        else
+            SendResponseL( EMTPRespCodeGeneralError );
+        }
+
+    PRINT( _L( "MM MTP <= CGetObjectPropList::ServiceL" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::CheckFormatL
+// Ensures the object format operation parameter is valid
+// -----------------------------------------------------------------------------
+//
+TMTPResponseCode CGetObjectPropList::CheckFormatL() const
+    {
+    TMTPResponseCode response = EMTPRespCodeOK;
+
+    PRINT( _L( "MM MTP => CGetObjectPropList::CheckFormatL" ) );
+
+    TUint32 formatCode = Request().Uint32( TMTPTypeRequest::ERequestParameter2 );
+    iFormatCode = formatCode;
+
+    PRINT1( _L( "MM MTP <> CGetObjectPropList::CheckFormatL formatCode = 0x%x" ), formatCode );
+
+    if ( formatCode != 0 )
+        {
+        response = EMTPRespCodeInvalidObjectFormatCode;
+
+        const RArray<TUint>* format = iDpConfig.GetSupportedFormat();
+        TInt count = format->Count();
+
+        for ( TInt i = 0; i < count; i++ )
+            {
+            if ( formatCode == (*format)[i ] )
+                {
+                response = EMTPRespCodeOK;
+                break;
+                }
+            }
+        }
+
+    PRINT1( _L( "MM MTP <= CGetObjectPropList::CheckFormatL, response 0x%x" ), response );
+
+    return response;
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::CheckPropCodeL
+// Ensures the object prop code operation parameter is valid
+// -----------------------------------------------------------------------------
+//
+TMTPResponseCode CGetObjectPropList::CheckPropCodeL() const
+    {
+    PRINT( _L( "MM MTP => CGetObjectPropList::CheckPropCode" ) );
+
+    TMTPResponseCode response = EMTPRespCodeOK;
+
+    TUint32 formatCode = Request().Uint32( TMTPTypeRequest::ERequestParameter2 );
+    iPropCode = Request().Uint32( TMTPTypeRequest::ERequestParameter3 );
+    PRINT1( _L( "MM MTP <> CGetObjectPropList::CheckPropCode, iPropCode = 0x%x" ), iPropCode );
+
+    iPropertyArray.Reset();
+    if ( iPropCode == EMTPObjectPropCodeUndefined )
+        {
+        // Get group code
+        TUint32 groupCode = Request().Uint32( TMTPTypeRequest::ERequestParameter4 );
+        PRINT1( _L( "MM MTP <> CGetObjectPropList::CheckPropCode, Group Code = 0x%x" ), groupCode );
+
+        // check if groupCode is supported
+        TInt count = sizeof ( KSupportedGroupCode )
+            / sizeof ( KSupportedGroupCode[0] );
+        TInt i = 0;
+        for ( ; i < count; i++ )
+            {
+            if ( groupCode == KSupportedGroupCode[i ] )
+                break;
+            }
+        if ( i == count )
+            response = EMTPRespCodeSpecificationByGroupUnsupported;
+
+        }
+    else if ( iPropCode != KMTPAll )
+        {
+        PRINT1( _L( "MM MTP <> CGetObjectPropList::CheckPropCode, Property(0x%x) was queried." ), iPropCode );
+
+        TInt err = KErrNone;
+        const RArray<TUint>* properties = NULL;
+        if ( formatCode == KMTPFormatsAll )
+            properties = iDpConfig.GetAllSupportedProperties();
+        else
+            properties = iDpConfig.GetSupportedPropertiesL( formatCode );
+
+        User::LeaveIfError( err );
+
+        const TInt count = properties->Count();
+        TInt i = 0;
+        for ( i = 0; i < count; i++ )
+            {
+            if ( (*properties)[i] == iPropCode )
+                {
+                iPropertyArray.Append( iPropCode );
+                break;
+                }
+            }
+
+        if ( iPropertyArray.Count() == 0 )
+            {
+            response = EMTPRespCodeInvalidObjectPropCode;
+            }
+        }
+    else
+        {
+        PRINT( _L( "MM MTP <> CGetObjectPropList::CheckPropCode, All properties were queried." ) );
+        }
+
+    PRINT1( _L( "MM MTP <= CGetObjectPropList::CheckPropCode, response 0x%x" ), response );
+
+    return response;
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::CheckDepth
+// Ensures the depth operation parameter is valid
+// -----------------------------------------------------------------------------
+//
+TMTPResponseCode CGetObjectPropList::CheckDepth() const
+    {
+    TMTPResponseCode response = EMTPRespCodeSpecificationByDepthUnsupported;
+
+    PRINT( _L( "MM MTP => CGetObjectPropList::CheckDepth" ) );
+
+    // We either support no depth at all, or 1 depth or (0xFFFFFFFF) with objecthandle as 0x00000000
+    iHandle = Request().Uint32( TMTPTypeRequest::ERequestParameter1 );
+    PRINT1( _L( "MM MTP <> CGetObjectPropList::CheckDepth iHandle = 0x%x" ), iHandle );
+    iDepth = Request().Uint32( TMTPTypeRequest::ERequestParameter5 );
+    PRINT1( _L( "MM MTP <> CGetObjectPropList::CheckDepth iDepth = 0x%x" ), iDepth );
+
+    if ( ( iDepth == 0 )
+        || ( iDepth == 1 )
+        || ( iDepth == KMTPAll && iHandle == KMTPHandleNone ) )
+        {
+        response = EMTPRespCodeOK;
+        }
+
+    PRINT1( _L( "MM MTP <= CGetObjectPropList::CheckDepth, response 0x%x" ), response );
+
+    return response;
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::GetObjectHandlesL
+// Gets the handles for the objects that we want the properties for
+// -----------------------------------------------------------------------------
+//
+void CGetObjectPropList::GetObjectHandlesL()
+    {
+    PRINT( _L( "MM MTP => CGetObjectPropList::GetObjectHandlesL" ) );
+
+    iHandles.Reset();
+
+    if ( iHandle == KMTPHandleAll )
+        {
+        GetObjectHandlesL( KMTPStorageAll, KMTPHandleNone );
+        }
+    else if ( iHandle == KMTPHandleNone )
+        {
+        GetRootObjectHandlesL( iDepth, iFormatCode );
+        }
+    else
+        {
+        CMTPObjectMetaData* meta( iRequestChecker->GetObjectInfo( iHandle ) );
+        TPtrC suid( meta->DesC( CMTPObjectMetaData::ESuid ) );
+        TParsePtrC parse( suid );
+        iDpConfig.GetWrapperL().SetStorageRootL( parse.Drive() );
+
+        __ASSERT_DEBUG( meta, Panic( EMmMTPDpObjectNull ) );
+
+        if ( ( meta->Uint( CMTPObjectMetaData::EFormatCode ) == EMTPFormatCodeAssociation )
+            && ( meta->Uint( CMTPObjectMetaData::EFormatSubCode ) == EMTPAssociationTypeGenericFolder ) )
+            {
+            GetFolderObjectHandlesL( iDepth, iHandle );
+            }
+        else
+            {
+            iHandles.Append( iHandle );
+            }
+        }
+
+    PRINT( _L( "MM MTP <= CGetObjectPropList::GetObjectHandlesL" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::GetObjectHandlesL
+// Gets all object handles (for GetObjectHandlesL)
+// -----------------------------------------------------------------------------
+//
+void CGetObjectPropList::GetObjectHandlesL( TUint32 aStorageId,
+    TUint32 aParentHandle,
+    TUint16 aFormat /*= 0x0000*/)
+    {
+    PRINT2( _L( "MM MTP => CGetObjectPropList::GetObjectHandlesL, aStorageId = 0x%x, aParentHandle = 0x%x" ),
+        aStorageId,
+        aParentHandle );
+
+    RMTPObjectMgrQueryContext context;
+    CleanupClosePushL( context ); // + context
+
+    iHandles.Reset();
+
+    if ( aFormat )
+        {
+        TMTPObjectMgrQueryParams params( aStorageId, aFormat, aParentHandle );
+
+        do
+            {
+            iFramework.ObjectMgr().GetObjectHandlesL( params, context, iHandles );
+            }
+        while ( !context.QueryComplete() );
+        }
+    else
+        {
+        TMTPObjectMgrQueryParams params( aStorageId,
+            KMTPFormatsAll,
+            aParentHandle );
+
+        do
+            {
+            RArray<TUint> handles;
+            CleanupClosePushL( handles ); // + handles
+            iFramework.ObjectMgr().GetObjectHandlesL( params, context, handles );
+
+            for ( TInt i = 0; i < handles.Count(); i++ )
+                {
+                if ( iFramework.ObjectMgr().ObjectOwnerId( handles[i ] )
+                    == iFramework.DataProviderId() )
+                    iHandles.Append( handles[i ] );
+                }
+            CleanupStack::PopAndDestroy( &handles ); // - handles
+            }
+        while ( !context.QueryComplete() );
+        }
+
+    CleanupStack::PopAndDestroy( &context ); // - context
+
+    PRINT( _L( "MM MTP <= CGetObjectPropList::GetObjectHandlesL" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::GetFolderObjectHandlesL
+// Gets a folder object handle
+// -----------------------------------------------------------------------------
+//
+void CGetObjectPropList::GetFolderObjectHandlesL( TUint32 aDepth,
+    TUint32 aParentHandle )
+    {
+    PRINT2( _L( "MM MTP => CGetObjectPropList::GetFolderObjectHandlesL aDepth = 0x%x, aParentHandle = 0x%x" ),
+        aDepth,
+        aParentHandle );
+
+    if ( aDepth == 0 )
+        {
+        // Do Nothing!!!
+        }
+    else //if(aDepth ==1)
+        {
+        GetObjectHandlesL( KMTPStorageAll, aParentHandle, iFormatCode );
+        }
+
+    PRINT( _L( "MM MTP <= CGetObjectPropList::GetFolderObjectHandlesL" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::GetRootObjectHandlesL
+// Gets the handles of all objects on the root
+// -----------------------------------------------------------------------------
+//
+void CGetObjectPropList::GetRootObjectHandlesL( TUint32 aDepth, TUint16 aFormat )
+    {
+    PRINT2( _L( "MM MTP => CGetObjectPropList::GetRootObjectHandlesL aDepth = 0x%x, aFormat = 0x%x" ), aDepth , aFormat);
+
+    if ( aDepth == KMaxTUint )
+        {
+        GetObjectHandlesL( KMTPStorageAll, KMTPHandleNone, aFormat );
+        }
+    else if ( aDepth == 0 )
+        {
+        // Return empty set to PC according to spec 0.96, folder is handled by device dp
+        iHandles.Reset();
+        }
+    else
+        {
+        GetObjectHandlesL( KMTPStorageAll, KMTPHandleNoParent, aFormat );
+        }
+
+    PRINT( _L( "MM MTP <= CGetObjectPropList::GetRootObjectHandlesL" ) );
+    }
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::ServiceAllPropertiesL
+//  Gets a list of all the properties supported
+// -----------------------------------------------------------------------------
+//
+TInt CGetObjectPropList::ServiceAllPropertiesL( TUint32 aHandle )
+    {
+    PRINT1( _L( "MM MTP => CGetObjectPropList::ServiceAllPropertiesL aHandle = 0x%x" ), aHandle );
+
+    // Append the current object info onto our list
+    TFileName fileName( iObject->DesC( CMTPObjectMetaData::ESuid ) );
+    TUint32 formatCode = iObject->Uint( CMTPObjectMetaData::EFormatCode );
+
+    PRINT2( _L( "MM MTP <> CGetObjectPropList::ServiceAllPropertiesL, fileName = %S, formatCode = 0x%x" ),
+        &fileName,
+        formatCode );
+
+    const RArray<TUint>* properties = NULL;
+    if ( formatCode == KMTPFormatsAll )
+        properties = iDpConfig.GetAllSupportedProperties();
+    else
+        properties = iDpConfig.GetSupportedPropertiesL( formatCode );
+
+    const TInt count = properties->Count();
+
+    TInt err = KErrNone;
+    for ( TInt i = 0; i < count; i++ )
+        {
+        // no need to do the trap anymore, this is being handle internally in Media DP's ServiceSpecificObjectPropertyL, also, this base class should not know too much of different handling between different formats
+        err = ServiceOneObjectPropertyL( aHandle, (*properties)[i] );
+        if ( err == KErrNotSupported )  // Skip
+            err = KErrNone;
+        if ( err != KErrNone )
+            break;
+        }
+
+    PRINT1( _L( "MM MTP <= CGetObjectPropList::ServiceAllPropertiesL err = %d" ), err );
+    return err;
+    }
+
+TInt CGetObjectPropList::ServiceGroupPropertiesL( TUint32 aHandle )
+    {
+    PRINT1( _L( "MM MTP => CGetObjectPropList::ServiceGroupPropertiesL aHandle = 0x%x" ), aHandle );
+
+    TFileName fileName( iObject->DesC( CMTPObjectMetaData::ESuid ) );
+    TUint32 formatCode = iObject->Uint( CMTPObjectMetaData::EFormatCode );
+
+    PRINT2( _L( "MM MTP <> CGetObjectPropList::ServiceGroupPropertiesL, fileName = %S, formatCode = 0x%x" ),
+        &fileName,
+        formatCode );
+
+    // Get property codes according to group code, put those into array
+    TUint32 groupCode = Request().Uint32( TMTPTypeRequest::ERequestParameter4 );
+    iPropertyArray.Reset();
+    GetPropertiesL( iPropertyArray, groupCode, formatCode );
+
+    const TInt count = iPropertyArray.Count();
+
+    TInt err = KErrNone;
+    for ( TInt i = 0; i < count; i++ )
+        {
+        err = ServiceOneObjectPropertyL( aHandle, iPropertyArray[i] );
+        if ( err == KErrNotSupported )  // Skip
+            err = KErrNone;
+        if ( err != KErrNone )
+            break;
+        }
+
+    PRINT1( _L( "MM MTP <= CGetObjectPropList::ServiceGroupPropertiesL err = %d" ), err );
+
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::ServiceOneObjectPropertyL
+//  Gets the object property information for the required object
+// -----------------------------------------------------------------------------
+//
+TInt CGetObjectPropList::ServiceOneObjectPropertyL( TUint32 aHandle,
+    TUint16 aPropCode )
+    {
+    PRINT2( _L( "MM MTP => CGetObjectPropList::ServiceOneObjectPropertyL aHandle = 0x%x, aPropCode = 0x%x" ),
+        aHandle,
+        aPropCode );
+    CMTPTypeString* textData = NULL;
+    TInt err = KErrNone;
+
+    if ( iPropertyElement != NULL )
+        {
+        delete iPropertyElement;
+        iPropertyElement = NULL;
+        }
+
+    switch ( aPropCode )
+        {
+        // Storage ID
+        case EMTPObjectPropCodeStorageID:
+            {
+            TMTPTypeUint32 storageId( iObject->Uint( CMTPObjectMetaData::EStorageId ) );
+            iPropertyElement = &(iPropertyList->ReservePropElemL(aHandle, aPropCode));
+            iPropertyElement->SetUint32L(CMTPTypeObjectPropListElement::EValue, storageId.Value());
+            }
+            break;
+
+        // Format Code
+        case EMTPObjectPropCodeObjectFormat:
+            {
+            TMTPTypeUint16 objectFormat( iObject->Uint( CMTPObjectMetaData::EFormatCode ) );
+            iPropertyElement = &(iPropertyList->ReservePropElemL(aHandle, aPropCode));
+            iPropertyElement->SetUint16L(CMTPTypeObjectPropListElement::EValue, objectFormat.Value());
+            }
+            break;
+
+        // Protection Status
+        case EMTPObjectPropCodeProtectionStatus:
+            {
+            TMTPTypeUint16 protectionStatus( MmMtpDpUtility::GetProtectionStatusL( iFramework.Fs(),
+                iObject->DesC( CMTPObjectMetaData::ESuid ) ) );
+            iPropertyElement = &(iPropertyList->ReservePropElemL(aHandle, aPropCode));
+            iPropertyElement->SetUint16L(CMTPTypeObjectPropListElement::EValue,  protectionStatus.Value());
+            }
+            break;
+
+        // Object Size
+        case EMTPObjectPropCodeObjectSize:
+            {
+            TMTPTypeUint64 objectSize( MmMtpDpUtility::GetObjectSizeL( iFramework.Fs(),
+                iObject->DesC( CMTPObjectMetaData::ESuid ) ) );
+            iPropertyElement = &( iPropertyList->ReservePropElemL( aHandle, aPropCode ) );
+            iPropertyElement->SetUint64L( CMTPTypeObjectPropListElement::EValue, objectSize.Value() );
+            }
+            break;
+
+        // Filename
+        case EMTPObjectPropCodeObjectFileName:
+            {
+#ifdef  _DEBUG
+            HBufC* log = iObject->DesC( CMTPObjectMetaData::ESuid ).Alloc();
+            PRINT1( _L( "MM MTP <> CGetObjectPropList::ServiceOneObjectPropertyL FileName = %S" ), log );
+            delete log;
+            log = NULL;
+#endif // _DEBUG
+            TParsePtrC parse( iObject->DesC( CMTPObjectMetaData::ESuid ) );
+            textData = CMTPTypeString::NewLC( parse.NameAndExt() );    // + textData
+            iPropertyElement = &(iPropertyList->ReservePropElemL(aHandle, aPropCode));
+            iPropertyElement->SetStringL(CMTPTypeObjectPropListElement::EValue, textData->StringChars());
+            CleanupStack::PopAndDestroy( textData );    // - textData
+            }
+            break;
+
+        // Parent Object
+        case EMTPObjectPropCodeParentObject:
+            {
+            iPropertyElement = &(iPropertyList->ReservePropElemL(aHandle, aPropCode));
+            iPropertyElement->SetUint32L(CMTPTypeObjectPropListElement::EValue, iObject->Uint( CMTPObjectMetaData::EParentHandle ));
+            }
+            break;
+
+        // PUID
+        case EMTPObjectPropCodePersistentUniqueObjectIdentifier:
+            {
+            TMTPTypeUint128 puid = iFramework.ObjectMgr().PuidL( aHandle );
+            iPropertyElement = &(iPropertyList->ReservePropElemL(aHandle, aPropCode));
+            iPropertyElement->SetUint128L(CMTPTypeObjectPropListElement::EValue,puid.UpperValue(), puid.LowerValue() );
+            }
+            break;
+
+        case EMTPObjectPropCodeName:
+        case EMTPObjectPropCodeDateAdded:
+            {
+            if ( ( aPropCode == EMTPObjectPropCodeName )
+                || ( ( !MmMtpDpUtility::IsVideoL( iObject->DesC( CMTPObjectMetaData::ESuid ), iFramework ) )
+                && ( aPropCode == EMTPObjectPropCodeDateAdded ) ) )
+                {
+                textData = CMTPTypeString::NewLC();   // + textData
+
+                TRAP( err, iDpConfig.GetWrapperL().GetObjectMetadataValueL( aPropCode,
+                    *textData,
+                    *iObject ) );
+
+                PRINT1( _L( "MM MTP <> CGetObjectPropList::ServiceOneObjectPropertyL err = %d" ), err );
+
+                if ( err == KErrNone )
+                    {
+                    iPropertyElement = &(iPropertyList->ReservePropElemL( aHandle, aPropCode ) );
+                    iPropertyElement->SetStringL(CMTPTypeObjectPropListElement::EValue, textData->StringChars());
+                    }
+
+                CleanupStack::PopAndDestroy( textData );  // - textData
+                }
+            }
+            break;
+
+        case EMTPObjectPropCodeDateCreated:
+        case EMTPObjectPropCodeDateModified:
+            {
+            TTime dataModified;
+            dataModified = MmMtpDpUtility::GetObjectDateModifiedL( iFramework.Fs(),
+                iObject->DesC( CMTPObjectMetaData::ESuid ) );
+
+            TBuf<KMtpMaxDateTimeStringLength> timeStr;
+            dataModified.FormatL( timeStr, KMtpDateTimeFormat );
+            PRINT1( _L( "MM MTP <> CGetObjectPropList::ServiceOneObjectPropertyL Date time %S" ), &timeStr );
+            CMTPTypeString* datastring = CMTPTypeString::NewLC( timeStr );  // + datastring
+
+            iPropertyElement = &(iPropertyList->ReservePropElemL(aHandle, aPropCode));
+            iPropertyElement->SetStringL(CMTPTypeObjectPropListElement::EValue, datastring->StringChars());
+            CleanupStack::PopAndDestroy( datastring );  // - datastring
+            }
+            break;
+
+        // Consumable Value
+        case EMTPObjectPropCodeNonConsumable:
+            {
+            iPropertyElement = &(iPropertyList->ReservePropElemL(aHandle, aPropCode));
+            iPropertyElement->SetUint8L(CMTPTypeObjectPropListElement::EValue,0);
+            }
+            break;
+
+        default:
+            {
+            err = ServiceSpecificObjectPropertyL( aPropCode, aHandle );
+            }
+            break;
+        }
+
+    if ( iPropertyElement != NULL )
+        {
+        iPropertyList->CommitPropElemL( *iPropertyElement );
+        iPropertyElement = NULL;
+        }
+
+    PRINT( _L( "MM MTP <= CGetObjectPropList::ServiceOneObjectPropertyL" ) );
+
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::RunL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CGetObjectPropList::RunL()
+    {
+    if ( iHandles.Count() > 0 )
+        {
+        TInt err = KErrNone;
+        TUint32 handle = iHandles[0];
+        PRINT1( _L( "MM MTP <> CGetObjectPropList::RunL, handle = 0x%x" ), handle );
+        if ( iFramework.ObjectMgr().ObjectOwnerId( handle )
+            == iFramework.DataProviderId() )
+            {
+            delete iObject;
+            iObject = NULL;
+            iObject = CMTPObjectMetaData::NewL();
+
+            if ( iFramework.ObjectMgr().ObjectL( handle, *iObject ) ) // Populate the object meta data
+                {
+                SetSubFormatCodeL();
+
+                if ( iPropCode == KMTPAll )
+                    err = ServiceAllPropertiesL( handle );
+                else if ( iPropCode == EMTPObjectPropCodeUndefined )
+                    {
+                    err = ServiceGroupPropertiesL( handle );
+                    }
+                if ( err == KErrNotFound )
+                    SendResponseL( EMTPRespCodeAccessDenied );
+                else if ( err != KErrNone )
+                    SendResponseL( EMTPRespCodeGeneralError );
+                }
+            }
+
+        // Complete ourselves with current TRequestStatus
+        // Increase index to process next handle on next round
+        // iFirstUnprocessed++;
+        iHandles.Remove( 0 );
+
+        if ( err == KErrNone )
+            {
+            TRequestStatus* status = &iStatus;
+            User::RequestComplete( status, iStatus.Int() );
+            SetActive();
+            }
+        }
+    else // all handles processed, can send data
+        {
+        PRINT( _L( "MM MTP <> CGetObjectPropList::RunL, Finished, Send data to PC!" ) );
+        SendDataL( *iPropertyList );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::RunError
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CGetObjectPropList::RunError( TInt aError )
+    {
+    PRINT1( _L( "MM MTP <> CGetObjectPropList::RunError aError = %d" ), aError );
+        TRAP_IGNORE( SendResponseL( EMTPRespCodeGeneralError ) );
+
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CGetObjectPropList::DoCancel()
+// Cancel the process
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CGetObjectPropList::DoCancel()
+    {
+    // TODO: need to send the data here?
+    // SendDataL( *iPropertyList );
+    }
+
+void CGetObjectPropList::GetPropertiesL( RArray<TUint>& aPropArray,
+    TUint32 aGroupCode,
+    TUint16 aFormatCode ) const
+    {
+    aPropArray.Reset();
+
+    const RArray<TUint>* properties = NULL;
+    if ( aFormatCode == KMTPFormatsAll )
+        properties = iDpConfig.GetAllSupportedProperties();
+    else
+        properties = iDpConfig.GetSupportedPropertiesL( aFormatCode );
+
+    TInt count = sizeof ( KPropGroupMapTable ) / sizeof ( KPropGroupMapTable[0] );
+    for ( TInt i = 0; i < properties->Count(); i++ )
+        {
+        for ( TInt j = 0; j < count; j++ )
+            {
+            if( KPropGroupMapTable[j].iPropCode == (*properties)[i]
+                && KPropGroupMapTable[j].iGroupCode == aGroupCode )
+                {
+                aPropArray.Append( (*properties)[i] );
+                break;
+                }
+            }
+        }
+    }
+
+void CGetObjectPropList::SetSubFormatCodeL()
+    {
+    __ASSERT_DEBUG( iObject, Panic( EMmMTPDpObjectNull ) );
+
+    // Note: Parsing out subformat code in external enumeration phase.
+    //       This process was delayed in internal phase to avoid time-out.
+    TUint16 formatCode = iObject->Uint( CMTPObjectMetaData::EFormatCode );
+    TUint subFormatCode = iObject->Uint( CMTPObjectMetaData::EFormatSubCode );
+    PRINT2( _L( "MM MTP <> CGetObjectPropList::SetSubFormatCode, formatCode = 0x%x, subFormatCode = 0x%x" ),
+        formatCode,
+        subFormatCode );
+
+    TBool ifNeedParse = ( ( formatCode == EMTPFormatCodeMP4Container )
+        || ( formatCode == EMTPFormatCode3GPContainer )
+        || ( formatCode== EMTPFormatCodeASF ) )
+        && ( subFormatCode == EMTPSubFormatCodeUnknown );
+    if ( ifNeedParse )
+        {
+        PERFLOGSTART( KSubFormatParse );
+
+        if ( MmMtpDpUtility::IsVideoL( iObject->DesC( CMTPObjectMetaData::ESuid ) ) )
+            subFormatCode = EMTPSubFormatCodeVideo;
+        else
+            subFormatCode = EMTPSubFormatCodeAudio;
+
+        PERFLOGSTOP( KSubFormatParse );
+
+        iObject->SetUint( CMTPObjectMetaData::EFormatSubCode, subFormatCode );
+        }
+    }
+
+// end of file