mtpdataproviders/mtpimagedp/src/cmtpimagedpsendobjectinfo.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:56 +0100
branchRCL_3
changeset 20 4a793f564d72
parent 19 0aa8cc770c8a
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201032 Kit: 201035

// 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:
//

/**
 @file
 @internalTechnology
*/

#include <f32file.h>
#include <bautils.h>
#include <e32const.h>

#include <mtp/mmtpdataproviderframework.h>
#include <mtp/cmtpobjectmetadata.h>
#include <mtp/cmtptypefile.h>
#include <mtp/cmtptypeobjectinfo.h>
#include <mtp/cmtptypeobjectproplist.h>
#include <mtp/cmtptypestring.h>
#include <mtp/mmtpobjectmgr.h>
#include <mtp/mmtpstoragemgr.h>
#include <mtp/mtpprotocolconstants.h>
#include <mtp/mmtpconnection.h>
#include <mtp/tmtptyperequest.h>

#include "mtpdebug.h"
#include "cmtpimagedpobjectpropertymgr.h"
#include "cmtpimagedpsendobjectinfo.h"
#include "mtpimagedppanic.h"
#include "mtpimagedpconst.h"
#include "cmtpimagedpthumbnailcreator.h"
#include "mtpimagedputilits.h"
#include "cmtpimagedp.h"

// Class constants.
__FLOG_STMT(_LIT8(KComponent, "ImageDPSendObjectInfo");)

const TInt RollbackFuncCnt = 3;

const TMTPRequestElementInfo KMTPSendObjectPropListPolicy[] = 
    {
        {TMTPTypeRequest::ERequestParameter1, EMTPElementTypeStorageId, EMTPElementAttrWrite, 1, 0, 0}, 
        {TMTPTypeRequest::ERequestParameter2, EMTPElementTypeObjectHandle, EMTPElementAttrDir, 2, KMTPHandleAll, KMTPHandleNone}
    };
/**
Two-phase construction method
@param aFramework  The data provider framework
@param aConnection The connection from which the request comes
@return a pointer to the created request processor object
*/ 
MMTPRequestProcessor* CMTPImageDpSendObjectInfo::NewL(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection,CMTPImageDataProvider& aDataProvider)
    {
    CMTPImageDpSendObjectInfo* self = new (ELeave) CMTPImageDpSendObjectInfo(aFramework, aConnection,aDataProvider);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }

/**
Destructor
*/    
CMTPImageDpSendObjectInfo::~CMTPImageDpSendObjectInfo()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::~CMTPImageDpSendObjectInfo - Entry"));   
        
    Rollback();
    iRollbackList.Close();

    delete iDateMod;
    delete iDateCreated;
    delete iFileReceived;
    delete iParentSuid;    
    delete iReceivedObject;
    delete iObjectInfo;
    delete iObjectPropList;
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::~CMTPImageDpSendObjectInfo - Exit"));
    __FLOG_CLOSE; 
    }

/**
Standard c++ constructor
@param aFramework    The data provider framework
@param aConnection    The connection from which the request comes
*/    
CMTPImageDpSendObjectInfo::CMTPImageDpSendObjectInfo(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection, CMTPImageDataProvider& aDataProvider) :
    CMTPRequestProcessor(aFramework, aConnection, 0, NULL),
    iDataProvider(aDataProvider),
    iObjectPropertyMgr(aDataProvider.PropertyMgr())
    {

    }

#define ADD_FSM_ENTRY(currentstate, event, nextstate, failedstate, action)   \
    iStateMachine[currentstate][event].iNextSuccessState = nextstate;        \
    iStateMachine[currentstate][event].iNextFailedState  = failedstate;      \
    iStateMachine[currentstate][event].iFsmAction        = action

/**
Second-phase construction
*/        
void CMTPImageDpSendObjectInfo::ConstructL()
    {
    __FLOG_OPEN(KMTPSubsystem, KComponent);
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ConstructL - Entry"));   
         
    iRollbackList.ReserveL(RollbackFuncCnt);
    iExpectedSendObjectRequest.SetUint16(TMTPTypeRequest::ERequestOperationCode, EMTPOpCodeSendObject);
    iReceivedObject = CMTPObjectMetaData::NewL();
    iReceivedObject->SetUint(CMTPObjectMetaData::EDataProviderId, iFramework.DataProviderId());
    
    // build FSM matrix    
    // process sendobjectinfo/sendobjectproplist operation
    ADD_FSM_ENTRY(EStateIdle, EObjectInfoEvent,     EObjectInfoCheck, EStateIdle, FsmCheckObjectInfoParamsL);
    ADD_FSM_ENTRY(EStateIdle, EObjectPropListEvent, EObjectInfoCheck, EStateIdle, FsmCheckObjectPropListParamsL);
    ADD_FSM_ENTRY(EStateIdle, EObjectEvent,         EStateIdle,       EStateIdle, FsmCheckObjectParams);
    
    ADD_FSM_ENTRY(EObjectInfoCheck, EObjectInfoEvent,     EObjectInfoServ, EStateIdle, FsmServiceSendObjectInfoL);
    ADD_FSM_ENTRY(EObjectInfoCheck, EObjectPropListEvent, EObjectInfoServ, EStateIdle, FsmServiceSendObjectPropListL);
    ADD_FSM_ENTRY(EObjectInfoCheck, EObjectEvent,         EStateEnd,       EStateEnd,  NULL);
    
    ADD_FSM_ENTRY(EObjectInfoServ, EObjectInfoEvent,     EObjectInfoSucceed, EStateIdle, FsmDoHandleSendObjectInfoCompleteL);
    ADD_FSM_ENTRY(EObjectInfoServ, EObjectPropListEvent, EObjectInfoSucceed, EStateIdle, FsmDoHandleSendObjectPropListCompleteL);
    ADD_FSM_ENTRY(EObjectInfoServ, EObjectEvent,         EStateEnd,          EStateEnd,  NULL);
    
    // process sendobject operation
    ADD_FSM_ENTRY(EObjectInfoSucceed, EObjectInfoEvent,     EObjectInfoCheck, EStateIdle,          FsmCheckObjectInfoParamsL);
    ADD_FSM_ENTRY(EObjectInfoSucceed, EObjectPropListEvent, EObjectInfoCheck, EStateIdle,          FsmCheckObjectPropListParamsL);
    ADD_FSM_ENTRY(EObjectInfoSucceed, EObjectEvent,         EObjectCheck,     EObjectInfoSucceed,  FsmCheckObjectParams);
    
    ADD_FSM_ENTRY(EObjectCheck, EObjectInfoEvent,     EStateEnd,   EStateEnd,  NULL);
    ADD_FSM_ENTRY(EObjectCheck, EObjectPropListEvent, EStateEnd,   EStateEnd,  NULL);
    ADD_FSM_ENTRY(EObjectCheck, EObjectEvent,         EObjectServ, EObjectInfoSucceed, FsmServiceSendObjectL);
    
    ADD_FSM_ENTRY(EObjectServ, EObjectInfoEvent,     EStateEnd,   EStateEnd,  NULL);
    ADD_FSM_ENTRY(EObjectServ, EObjectPropListEvent, EStateEnd,   EStateEnd,  NULL);
    ADD_FSM_ENTRY(EObjectServ, EObjectEvent,         EStateIdle,  EObjectInfoSucceed, FsmDoHandleSendObjectCompleteL);
    
    __FLOG(_L8("CMTPImageEnumerator::ConstructL - Exit"));  
    }

TBool CMTPImageDpSendObjectInfo::FsmCheckObjectInfoParamsL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr)
    {
    return aObject->CheckObjectInfoParamsL(aPtr);
    }

TBool CMTPImageDpSendObjectInfo::FsmCheckObjectPropListParamsL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr)
    {
    return aObject->CheckObjectPropListParamsL(aPtr);
    }

TBool CMTPImageDpSendObjectInfo::FsmCheckObjectParams(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr)
    {
    return aObject->CheckObjectParams(aPtr);
    }

TBool CMTPImageDpSendObjectInfo::FsmServiceSendObjectInfoL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr)
    {
    return aObject->ServiceSendObjectInfoL(aPtr);
    }

TBool CMTPImageDpSendObjectInfo::FsmServiceSendObjectPropListL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr)
    {
    return aObject->ServiceSendObjectPropListL(aPtr);
    }

TBool CMTPImageDpSendObjectInfo::FsmServiceSendObjectL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr)
    {
    return aObject->ServiceSendObjectL(aPtr);
    }

TBool CMTPImageDpSendObjectInfo::FsmDoHandleSendObjectInfoCompleteL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr)
    {
    return aObject->DoHandleSendObjectInfoCompleteL(aPtr);
    }

TBool CMTPImageDpSendObjectInfo::FsmDoHandleSendObjectPropListCompleteL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr)
    {
    return aObject->DoHandleSendObjectPropListCompleteL(aPtr);
    }

TBool CMTPImageDpSendObjectInfo::FsmDoHandleSendObjectCompleteL(CMTPImageDpSendObjectInfo* aObject, TAny *aPtr)
    {
    return aObject->DoHandleSendObjectCompleteL(aPtr);
    }

/**
Verify the request
@return EMTPRespCodeOK if request is verified, otherwise one of the error response codes
*/    
TMTPResponseCode CMTPImageDpSendObjectInfo::CheckRequestL()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckRequestL - Entry"));
    
    iOperationCode = Request().Uint16(TMTPTypeRequest::ERequestOperationCode);
    
    switch (iOperationCode)
        {      
    case EMTPOpCodeSendObjectInfo:
        iEvent = EObjectInfoEvent;
        iElementCount = sizeof(KMTPSendObjectPropListPolicy) / sizeof(TMTPRequestElementInfo); //for the checker
        iElements = KMTPSendObjectPropListPolicy;            
        break;
        
    case EMTPOpCodeSendObjectPropList:
        iEvent = EObjectPropListEvent;
        iElementCount = sizeof(KMTPSendObjectPropListPolicy) / sizeof(TMTPRequestElementInfo); //for the checker
        iElements = KMTPSendObjectPropListPolicy;
        break;
        
    case EMTPOpCodeSendObject:
    	  //In ParseRouter everytime SendObject gets resolved then will be removed from Registry
    	  //Right away therefore we need reRegister it here again in case possible cancelRequest
    	  //Against this SendObject being raised.
    	  iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId);
    	  iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection);
        iEvent = EObjectEvent;
        iElementCount = 0; //for the checker
        iElements = NULL;
        break;
        
    default:
        // Nothing to do
        break;
        }
    
    FsmAction pCheck = iStateMachine[iCurrentState][iEvent].iFsmAction;
    __ASSERT_ALWAYS((pCheck != NULL), Panic(EMTPImageDpNoMatchingProcessor));

    //coverity[var_deref_model]
    TMTPResponseCode result = CMTPRequestProcessor::CheckRequestL();
    if(EMTPRespCodeOK == result)
        {
        TBool ret = EFalse;
        TRAPD(err, ret = (*pCheck)(this, &result));
        if (ret)
            {
            iCurrentState = iStateMachine[iCurrentState][iEvent].iNextSuccessState;
            }
        else
            {
            iCurrentState = iStateMachine[iCurrentState][iEvent].iNextFailedState;
            }
        User::LeaveIfError(err);
        }
    __FLOG_1(_L8("CheckRequestL - Result: 0x%04x"), result);
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckRequestL - Exit"));
    
    return result;    
    }
    
TBool CMTPImageDpSendObjectInfo::HasDataphase() const
    {
    return ETrue;
    }

TBool CMTPImageDpSendObjectInfo::CheckObjectInfoParamsL(TAny *aPtr)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectInfoParamsL - Entry"));
    
    TMTPResponseCode* ret = static_cast<TMTPResponseCode*>(aPtr);
    *ret = EMTPRespCodeOK;
    
    const TUint32 storeId(Request().Uint32(TMTPTypeRequest::ERequestParameter1));
    const TUint32 parentHandle(Request().Uint32(TMTPTypeRequest::ERequestParameter2));
    
    // this checking is only valid when the second parameter is not a special value.
    if (parentHandle != KMTPHandleAll && parentHandle != KMTPHandleNone)
        {
        //does not take owernship
        CMTPObjectMetaData* parentObjInfo = CMTPObjectMetaData::NewLC();        
        if (iFramework.ObjectMgr().ObjectL(parentHandle, *parentObjInfo))
            {
            TUint32 storageId = parentObjInfo->Uint(CMTPObjectMetaData::EStorageId);   
            if (storeId != storageId)        
                {
                *ret = EMTPRespCodeInvalidObjectHandle;
                }
            }
        else
            {
            *ret = EMTPRespCodeInvalidObjectHandle;            
            }        
        CleanupStack::PopAndDestroy(parentObjInfo);
        }
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectInfoParamsL - Exit"));
    return (*ret == EMTPRespCodeOK) ? ETrue : EFalse;
    }

TBool CMTPImageDpSendObjectInfo::CheckObjectPropListParamsL(TAny *aPtr)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectPropListParamsL - Entry"));
    TMTPResponseCode* ret = static_cast<TMTPResponseCode*>(aPtr);
    *ret = EMTPRespCodeOK;
    
    TMTPFormatCode formatCode = static_cast<TMTPFormatCode>(Request().Uint32(TMTPTypeRequest::ERequestParameter3));
    if (!IsFormatValid(formatCode))
        {
        *ret = EMTPRespCodeInvalidObjectFormatCode;
        }
    else
        {
        iStorageId = Request().Uint32(TMTPTypeRequest::ERequestParameter1);
        TUint32 objectSizeHigh = Request().Uint32(TMTPTypeRequest::ERequestParameter4);
        TUint32 objectSizeLow = Request().Uint32(TMTPTypeRequest::ERequestParameter5);
        iObjectSize = MAKE_TUINT64(objectSizeHigh, objectSizeLow);
        
        if (iStorageId == KMTPStorageDefault)
            {
            iStorageId = iFramework.StorageMgr().DefaultStorageId();
            }
        
        if(IsTooLarge(iObjectSize))
            {
            *ret = EMTPRespCodeObjectTooLarge;
            }
        }
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectPropListParamsL - Exit"));
    return (*ret == EMTPRespCodeOK) ? ETrue : EFalse;
    }

TBool CMTPImageDpSendObjectInfo::CheckObjectParams(TAny *aPtr)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectParamsL - Entry"));
    TMTPResponseCode* ret = static_cast<TMTPResponseCode*>(aPtr);
    *ret = EMTPRespCodeOK;
    
    /**
    * If the previous request is not the SendObjectInfo/SendObjectPropList/UpdateObjectPropList operation,
    * the SendObject operation should failed.
    */
    if ( (iPreviousTransactionID + 1) != Request().Uint32(TMTPTypeRequest::ERequestTransactionID))
        {
        *ret = EMTPRespCodeNoValidObjectInfo;
        }
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckObjectParamsL - Exit"));
    return (*ret == EMTPRespCodeOK) ? ETrue : EFalse;    
    }

/**
SendObjectInfo/SendObject request handler
NOTE: SendObjectInfo has to be comes before SendObject requests.  To maintain the state information
between the two requests, the two requests are combined together in one request processor.
*/    
void CMTPImageDpSendObjectInfo::ServiceL()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceL - Entry"));

    FsmAction pService = iStateMachine[iCurrentState][iEvent].iFsmAction;
    __ASSERT_DEBUG(pService, Panic(EMTPImageDpNoMatchingProcessor));
    
    TBool ret = EFalse;
    TRAPD(err, ret = (*pService)(this, NULL));
    if (ret)
        {
        iCurrentState = iStateMachine[iCurrentState][iEvent].iNextSuccessState;
        }
    else
        {
        iCurrentState = iStateMachine[iCurrentState][iEvent].iNextFailedState;
        }    
    
    if (err != KErrNone)
        {
        Rollback();
        }
    User::LeaveIfError(err);
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceL - Exit"));  
    }

/**
Override to match both the SendObjectInfo and SendObject requests
@param aRequest    The request to match
@param aConnection The connection from which the request comes
@return ETrue if the processor can handle the request, otherwise EFalse
*/        
TBool CMTPImageDpSendObjectInfo::Match(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection) const
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::Match - Entry"));
    TBool result = EFalse;
    TUint16 operationCode = aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode);
    if ((operationCode == EMTPOpCodeSendObjectInfo || 
        operationCode == EMTPOpCodeSendObject ||
        operationCode == EMTPOpCodeSendObjectPropList) &&
        &iConnection == &aConnection)
        {
        result = ETrue;
        }
    __FLOG(_L8("CMTPImageDpSendObjectInfo::Match - Exit"));  
    return result;    
    }

/**
Override to handle the response phase of SendObjectInfo and SendObject requests
@return EFalse
*/
TBool CMTPImageDpSendObjectInfo::DoHandleResponsePhaseL()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleResponsePhaseL - Entry"));

    //to check if the sending/receiving data is successful
    iSuccessful = !iCancelled;
 
    FsmAction pResponse = iStateMachine[iCurrentState][iEvent].iFsmAction;
    __ASSERT_DEBUG(pResponse, Panic(EMTPImageDpNoMatchingProcessor));
    
    TBool ret = EFalse;
    TRAPD(err, ret = (*pResponse)(this, &iSuccessful))
    if (ret)
        {
        iCurrentState = iStateMachine[iCurrentState][iEvent].iNextSuccessState;
        }
    else
        {
        iCurrentState = iStateMachine[iCurrentState][iEvent].iNextFailedState;
        }          
    
    if (err != KErrNone)
        {
        Rollback();
        }
    User::LeaveIfError(err);
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleResponsePhaseL - Exit"));   
    return EFalse;
    }

/**
Override to handle the completing phase of SendObjectInfo and SendObject requests
@return ETrue if succesfully received the file, otherwise EFalse
*/    
TBool CMTPImageDpSendObjectInfo::DoHandleCompletingPhaseL()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleCompletingPhaseL - Entry"));
    TBool result = ETrue;
    CMTPRequestProcessor::DoHandleCompletingPhaseL();

    if (iSuccessful)
        {
        if (iOperationCode == EMTPOpCodeSendObjectInfo || iOperationCode == EMTPOpCodeSendObjectPropList)
            {
            iPreviousTransactionID = Request().Uint32(TMTPTypeRequest::ERequestTransactionID);
            result = EFalse;
            }
        }
    else
        {
        if (iOperationCode == EMTPOpCodeSendObject)
            {
            iPreviousTransactionID++;
            }
        result = EFalse;
        }
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleCompletingPhaseL - Exit"));  
    return result;    
    }

/**
SendObjectInfo request handler
*/
TBool CMTPImageDpSendObjectInfo::ServiceSendObjectInfoL(TAny* /*aPtr*/)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectInfoL - Entry"));
    
    delete iObjectInfo;
    iObjectInfo = NULL;
    iObjectInfo = CMTPTypeObjectInfo::NewL();
    ReceiveDataL(*iObjectInfo);
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectInfoL - Exit"));
    return ETrue;
    }

/**
SendObjectPropList request handler
*/
TBool CMTPImageDpSendObjectInfo::ServiceSendObjectPropListL(TAny* /*aPtr*/)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectPropListL - Entry"));
    
    delete iObjectPropList;
    iObjectPropList = NULL;
    iObjectPropList = CMTPTypeObjectPropList::NewL();
    iReceivedObject->SetUint(CMTPObjectMetaData::EFormatCode, iRequest->Uint32(TMTPTypeRequest::ERequestParameter3));
    ReceiveDataL(*iObjectPropList);
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectPropListL - Exit"));
    return ETrue;
    }
    
/**
SendObject request handler
*/    
TBool CMTPImageDpSendObjectInfo::ServiceSendObjectL(TAny* /*aPtr*/)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectL - Entry"));
         
    iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObject);
    //prepare for rollback
    iRollbackList.AppendL(RemoveObjectFromDb);        
    
    ReceiveDataL(*iFileReceived);
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ServiceSendObjectL - Exit"));
    return ETrue;
    }

/**
Get a default parent object, if the request does not specify a parent object.
*/
void CMTPImageDpSendObjectInfo::GetDefaultParentObjectL()
    {    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::GetDefaultParentObjectL - Entry"));  

    if (iStorageId == KMTPStorageDefault)
        {
        iStorageId = iFramework.StorageMgr().DefaultStorageId();
        }
    TInt drive(static_cast<TDriveNumber>(iFramework.StorageMgr().DriveNumber(iStorageId)));
    User::LeaveIfError(drive);       

    delete iParentSuid;
    iParentSuid = NULL;
    iParentSuid = (iFramework.StorageMgr().StorageL(iStorageId).DesC(CMTPStorageMetaData::EStorageSuid)).AllocL();
    iReceivedObject->SetUint(CMTPObjectMetaData::EParentHandle, KMTPHandleNoParent);
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::GetDefaultParentObjectL - Exit"));                 
    }

/**
Get parent object and storage id
@return EMTPRespCodeOK if successful, otherwise, EMTPRespCodeInvalidParentObject
*/
TMTPResponseCode CMTPImageDpSendObjectInfo::GetParentObjectAndStorageIdL()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::GetParentObjectAndStorageIdL - Entry"));    
    __ASSERT_DEBUG(iRequestChecker, Panic(EMTPImageDpRequestCheckNull));

    iStorageId = Request().Uint32(TMTPTypeRequest::ERequestParameter1);
    iParentHandle = Request().Uint32(TMTPTypeRequest::ERequestParameter2);
    //does not take ownership
    CMTPObjectMetaData* parentObjectInfo = iRequestChecker->GetObjectInfo(iParentHandle);

    if (!parentObjectInfo)
        {
        GetDefaultParentObjectL();    
        }
    else
        {        
        delete iParentSuid;
        iParentSuid = NULL;
        iParentSuid = parentObjectInfo->DesC(CMTPObjectMetaData::ESuid).AllocL();
        iReceivedObject->SetUint(CMTPObjectMetaData::EParentHandle, iParentHandle);
        }

    __FLOG_VA((_L8("ParentSuid = %S"), iParentSuid));
    __FLOG(_L8("CMTPImageDpSendObjectInfo::GetParentObjectAndStorageIdL - Exit"));     
    return EMTPRespCodeOK;
    }

/**
Handling the completing phase of SendObjectInfo request
@return ETrue if the specified object can be saved on the specified location, otherwise, EFalse
*/    
TBool CMTPImageDpSendObjectInfo::DoHandleSendObjectInfoCompleteL(TAny* /*aPtr*/)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleSendObjectInfoCompleteL - Entry"));    
  
    TBool result(ETrue);
    TUint16 format(iObjectInfo->Uint16L(CMTPTypeObjectInfo::EObjectFormat));
    
    result = IsFormatValid(TMTPFormatCode(format));
    
    if (result)
        {
        delete iDateMod;
        iDateMod = NULL;
        iDateMod = iObjectInfo->StringCharsL(CMTPTypeObjectInfo::EDateModified).AllocL();
        delete iDateCreated;
        iDateCreated = NULL;
        iDateCreated = iObjectInfo->StringCharsL(CMTPTypeObjectInfo::EDateCreated).AllocL();

        TMTPResponseCode responseCode(GetParentObjectAndStorageIdL());
        if (responseCode != EMTPRespCodeOK)
            {
            SendResponseL(responseCode);
            result = EFalse;
            }
        }
    else
        {
        SendResponseL(EMTPRespCodeInvalidObjectFormatCode);
        }
        
    if (result)
        {
        iObjectSize = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EObjectCompressedSize);
        if(IsTooLarge(iObjectSize))
            {
            SendResponseL(EMTPRespCodeObjectTooLarge);
            result = EFalse;
            }
        }

    if (result)
        {
        iProtectionStatus = iObjectInfo->Uint16L(CMTPTypeObjectInfo::EProtectionStatus);
        if (iProtectionStatus !=  EMTPProtectionNoProtection &&
            iProtectionStatus != EMTPProtectionReadOnly)
            {
            SendResponseL(EMTPRespCodeParameterNotSupported);
            result = EFalse;
            }
        }

    if (result)
        {
        result = GetFullPathName(iObjectInfo->StringCharsL(CMTPTypeObjectInfo::EFilename));
        if (!result)
            {        
            // File and/or parent pathname invalid.
            SendResponseL(EMTPRespCodeInvalidDataset);
            }
        }

    if (result)
        {    
        result = !Exists(iFullPath);
        if (!result)
            {
            SendResponseL(EMTPRespCodeAccessDenied);
            }
        else
            {            
            TRAPD(err,CreateFsObjectL());
            if (err != KErrNone)
                {
                __FLOG_1(_L8("Fail to create fs object %d"),err);
                SendResponseL(ErrorToMTPError(err));
                Rollback();
                result = EFalse;
                }
            else
                {
                ReserveObjectL();            
                imageWidth = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EImagePixWidth);
                imageHeight = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EImagePixHeight);
                imageBitDepth = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EImageBitDepth);            
                iReceivedObject->SetUint(CMTPObjectMetaData::EFormatCode, format);
                SetPropertiesL();                            
                ReturnResponseL();
                }
            }
        }
    
    iSuccessful = result;    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleSendObjectInfoCompleteL - Exit"));
    return result;    
    }

/**
Handling the completing phase of SendObjectPropList request
@return ETrue if the specified object can be saved on the specified location, otherwise, EFalse
*/    
TBool CMTPImageDpSendObjectInfo::DoHandleSendObjectPropListCompleteL(TAny* /*aPtr*/)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleSendObjectPropListCompleteL - Entry"));
    TBool result(ETrue);
    
    TMTPResponseCode responseCode(GetParentObjectAndStorageIdL());
    if (responseCode != EMTPRespCodeOK)
        {
        SendResponseL(responseCode);
        result = EFalse;
        }    

    if (result)
        {
        // Any kind of association is treated as a folder
        const TUint32 formatCode(Request().Uint32(TMTPTypeRequest::ERequestParameter3));

        TInt invalidParameterIndex = KErrNotFound;
        responseCode = VerifyObjectPropListL(invalidParameterIndex);
        result = (responseCode == EMTPRespCodeOK);    
        if (!result)
            {
            TUint32 parameters[4];
            parameters[0] = 0;
            parameters[1] = 0;
            parameters[2] = 0;
            parameters[3] = invalidParameterIndex;
            SendResponseL(responseCode, 4, parameters);
            }
        }
        
    if (result) 
        {
        result = !Exists(iFullPath);
        if (!result)
            {
            // Object with the same name already exists.
            SendResponseL(EMTPRespCodeAccessDenied);
            }
        }    
    
    if (result)
        {
        TRAPD(err,CreateFsObjectL());
        if (err != KErrNone)
            {
            __FLOG_1(_L8("Fail to create fs object %d"),err);
            SendResponseL(ErrorToMTPError(err));
            Rollback();
            result = EFalse;
            }
        else
            {
            //the EFormatCode property has been set in ServiceSendObjectPropListL() function
            ReserveObjectL();
            SetPropertiesL();
            ReturnResponseL();
            }
        }
        
    iSuccessful = result;
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleSendObjectPropListCompleteL - Exit"));
    return result;    
    }
    
/**
Handling the completing phase of SendObject request
@return ETrue if the object has been successfully saved on the device, otherwise, EFalse
*/    
TBool CMTPImageDpSendObjectInfo::DoHandleSendObjectCompleteL(TAny* /*aPtr*/)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleSendObjectCompleteL - Entry"));    
    TBool result(ETrue);
    
#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
    TInt64 objectsize = 0;
#else
    TInt objectsize = 0;
#endif
    
    iFileReceived->File().Size(objectsize);    
    
    if (objectsize != iObjectSize)
        {
        __FLOG_VA((_L8("object sizes differ %lu != %lu"), objectsize, iObjectSize));
        iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);         
        Rollback();
        
        TMTPResponseCode responseCode = EMTPRespCodeObjectTooLarge;
        if (objectsize < iObjectSize)
            {
            responseCode = EMTPRespCodeInvalidDataset;
            }
        SendResponseL(responseCode);
        result = EFalse;
        }
        
    // SendObject is cancelled or connection is dropped.
    if(result && iCancelled)
        {
        __FLOG(_L8("It is a cancel for sendObject."));
        iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);
        Rollback();
        SendResponseL(EMTPRespCodeTransactionCancelled);    
        }
    else if (result && !iCancelled)
	    {	    	    
        if (iProtectionStatus ==  EMTPProtectionNoProtection ||
            iProtectionStatus == EMTPProtectionReadOnly)
            {
            TUint attValue = 0;
            User::LeaveIfError(iFileReceived->File().Att(attValue));
            attValue &= ~(KEntryAttNormal | KEntryAttReadOnly);
            
            if (iProtectionStatus == EMTPProtectionNoProtection)
                {                        
                attValue |= KEntryAttNormal;
                }
            else
                {
                attValue |= KEntryAttReadOnly;
                }
            User::LeaveIfError(iFileReceived->File().SetAtt(attValue, ~attValue));
            }
        TTime modifiedTime;
        //update datemodified property.
        if(iDateMod != NULL && iDateMod->Length())
           {           
           iObjectPropertyMgr.ConvertMTPTimeStr2TTimeL(*iDateMod, modifiedTime);
           User::LeaveIfError(iFileReceived->File().SetModified(modifiedTime));
           }
        else if(iDateCreated != NULL && iDateCreated->Length())
           {
           iObjectPropertyMgr.ConvertMTPTimeStr2TTimeL(*iDateCreated, modifiedTime);
           User::LeaveIfError(iFileReceived->File().SetModified(modifiedTime));
           }
                                   
	     iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);
        
        //The MTP spec states that it is not mandatory for SendObjectInfo/SendObjectPropList
        //to be followed by a SendObject.  An object is reserved in the ObjectStore on 
        //receiving a SendObjectInfo/SendObjectPropList request, but we only commit it 
        //on receiving the corresponding SendObject request.  With Associations however 
        //we commit the object straight away as the SendObject phase is often absent 
        //with folder creation.
		
        CleanUndoList();
        SendResponseL(EMTPRespCodeOK);
	    }        
    
    delete iFileReceived;
    iFileReceived = NULL;  
    
    iSuccessful = result;
    __FLOG(_L8("CMTPImageDpSendObjectInfo::DoHandleSendObjectCompleteL - Exit"));
    return result;
    }

void CMTPImageDpSendObjectInfo::UnreserveObject(CMTPImageDpSendObjectInfo* aObject)
    {
    aObject->UnreserveObject();
    }

void CMTPImageDpSendObjectInfo::RemoveObjectFromFs(CMTPImageDpSendObjectInfo* aObject)
    {
    aObject->RemoveObjectFromFs();
    }

void CMTPImageDpSendObjectInfo::RemoveObjectFromDb(CMTPImageDpSendObjectInfo* aObject)
    {
    aObject->RemoveObjectFromDb();
    }

void CMTPImageDpSendObjectInfo::UnreserveObject()
    {    
    __ASSERT_DEBUG(iReceivedObject, Panic(EMTPImageDpObjectNull));
    TRAP_IGNORE(iFramework.ObjectMgr().UnreserveObjectHandleL(*iReceivedObject));
    }

void CMTPImageDpSendObjectInfo::RemoveObjectFromFs()
    {  
    __FLOG(_L8("RemoveObjectFromFs"));
    delete iFileReceived;
    iFileReceived = NULL;
    TInt err = iFramework.Fs().Delete(iFullPath);
    if (err != KErrNone)
        {
        //add Suid to deleteobjectlist
        TRAP_IGNORE(iDataProvider.AppendDeleteObjectsArrayL(iFullPath));
        }
    }

void CMTPImageDpSendObjectInfo::RemoveObjectFromDb()
    {    
    /**
     * remove all cached properties if rollback occured.
     */
    TRAP_IGNORE(
            iFramework.ObjectMgr().RemoveObjectL(iReceivedObject->Uint(CMTPObjectMetaData::EHandle));
            iObjectPropertyMgr.ClearCache(iReceivedObject->Uint(CMTPObjectMetaData::EHandle));            
            );
    }

void CMTPImageDpSendObjectInfo::ReturnResponseL()
    {
    iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId);
    iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection);
    
    TUint32 parameters[3];
    parameters[0] = iStorageId;
    parameters[1] = iParentHandle;
    parameters[2] = iReceivedObject->Uint(CMTPObjectMetaData::EHandle);
    SendResponseL(EMTPRespCodeOK, (sizeof(parameters) / sizeof(parameters[0])), parameters);       
    }

/**
*/
TBool CMTPImageDpSendObjectInfo::IsFormatValid(TMTPFormatCode aFormat) const
    {
    __FLOG_1(_L8("CMTPImageDpSendObjectInfo::IsFormatValid - Format: 0x%04x"), aFormat);
    TInt count(sizeof(KMTPValidCodeExtensionMappings) / sizeof(KMTPValidCodeExtensionMappings[0]));        
    for(TInt i=0; i < count; i++)
        {
        if (KMTPValidCodeExtensionMappings[i].iFormatCode == aFormat)
            {
            return ETrue;
            }
        }
    __FLOG(_L8("CMTPImageDpSendObjectInfo::IsFormatValid - Exit"));
    return EFalse;
    }

/**
Get the full path name of the object to be saved
@param aFileName, on entry, contains the file name of the object,
on return, contains the full path name of the object to be saved
@return ETrue if the name is valid, EFalse otherwise
*/
TBool CMTPImageDpSendObjectInfo::GetFullPathName(const TDesC& aFileName)
    {
    __FLOG_1(_L8("CMTPImageDpSendObjectInfo::GetFullPathNameL - FileName: %S"), &aFileName);
    TBool result(EFalse);
    if (aFileName.Length() > 0)
        {
        iFullPath = *iParentSuid;
        if (iFullPath.Length() + aFileName.Length() < iFullPath.MaxLength())
            {
            iFullPath.Append(aFileName);
            result = iFramework.Fs().IsValidName(iFullPath);
            }
        __FLOG_1(_L16("FullPath: %S"), &iFullPath);
        }

    __FLOG(_L8("CMTPImageDpSendObjectInfo::GetFullPathNameL - Exit"));
    return result;
    }

/**
Check if the file already exists on the storage.
@return ETrue if file is exists, otherwise EFalse
*/
TBool CMTPImageDpSendObjectInfo::Exists(const TDesC& aName) const
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::Exists - Entry")); 
    // This detects both files and folders
    TBool ret(EFalse); 
    ret = BaflUtils::FileExists(iFramework.Fs(), aName);
    __FLOG_VA((_L16("Exists: %S (%d)"), &aName, ret));
    __FLOG(_L8("CMTPImageDpSendObjectInfo::IsTooLarge - Exit"));
    return ret;
    }

/**
Check if the property list is valid and extract properties (file name)
@param aInvalidParameterIndex if invalid, contains the index of the property.  Undefined, if it is valid.
@return if error, one of the error response code; otherwise EMTPRespCodeOK
*/
TMTPResponseCode CMTPImageDpSendObjectInfo::VerifyObjectPropListL(TInt& aInvalidParameterIndex)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::VerifyObjectPropListL - Entry"));
    
    TMTPResponseCode responseCode(EMTPRespCodeOK);
    const TUint KCount(iObjectPropList->NumberOfElements());
    iObjectPropList->ResetCursor();
    for (TUint i(0); (i < KCount); i++)
        {
        CMTPTypeObjectPropListElement& KElement=iObjectPropList->GetNextElementL();
        const TUint32 KHandle(KElement.Uint32L(CMTPTypeObjectPropListElement::EObjectHandle));
        aInvalidParameterIndex = i;
        if (KHandle != KMTPHandleNone)
            {
            responseCode = EMTPRespCodeInvalidObjectHandle;            
            break;
            }
            
        responseCode = CheckPropCodeL(KElement);
        if (responseCode != EMTPRespCodeOK)
            {
            break;
            }
        responseCode = ExtractPropertyL(KElement);
        if (responseCode != EMTPRespCodeOK)
            {
            break;
            }        
        }
    __FLOG_VA((_L8("Result = 0x%04X"), responseCode));
    __FLOG(_L8("CMTPImageDpSendObjectInfo::VerifyObjectPropListL - Exit"));
    return responseCode;        
    }

/**
Extracts the file information from the object property list element
@param aElement an object property list element
@param aPropertyCode MTP property code for the element
@return MTP response code
*/
TMTPResponseCode CMTPImageDpSendObjectInfo::ExtractPropertyL(const CMTPTypeObjectPropListElement& aElement)
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ExtractPropertyL - Entry"));
    TMTPResponseCode responseCode(EMTPRespCodeOK);
    switch (aElement.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode))
        {       
    case EMTPObjectPropCodeObjectFileName:
        {
        const TDesC& KFileName = aElement.StringL(CMTPTypeObjectPropListElement::EValue);
        if (!GetFullPathName(KFileName))
            {
            responseCode = EMTPRespCodeInvalidDataset;
            }
        }
        break;

    case EMTPObjectPropCodeProtectionStatus:
        {
        iProtectionStatus = aElement.Uint16L(CMTPTypeObjectPropListElement::EValue);
        if (iProtectionStatus !=  EMTPProtectionNoProtection &&
            iProtectionStatus != EMTPProtectionReadOnly)
            {
            responseCode = EMTPRespCodeParameterNotSupported;
            }
        }
        break;

    case EMTPObjectPropCodeDateModified:
        delete iDateMod;
        iDateMod = NULL;
        iDateMod = aElement.StringL(CMTPTypeObjectPropListElement::EValue).AllocL();
        break;
        
    case EMTPObjectPropCodeDateCreated:
        delete iDateCreated;
        iDateCreated = NULL;
        iDateCreated = aElement.StringL(CMTPTypeObjectPropListElement::EValue).AllocL();
        break;
        
	case EMTPObjectPropCodeName:
    	iName = aElement.StringL(CMTPTypeObjectPropListElement::EValue);
    	break;
        
    case EMTPObjectPropCodeObjectFormat:
        iFormatCode = aElement.Uint16L(CMTPTypeObjectPropListElement::EValue);
        if (iFormatCode != EMTPFormatCodeEXIFJPEG)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }
        break;
        
    case EMTPObjectPropCodeWidth:
        imageWidth = aElement.Uint32L(CMTPTypeObjectPropListElement::EValue);
        break;
        
    case EMTPObjectPropCodeHeight:
        imageHeight = aElement.Uint32L(CMTPTypeObjectPropListElement::EValue);
        break;
        
    case EMTPObjectPropCodeImageBitDepth:
        imageBitDepth = aElement.Uint32L(CMTPTypeObjectPropListElement::EValue);
        break;
        
    case EMTPObjectPropCodeNonConsumable:
        iNonConsumable = aElement.Uint8L(CMTPTypeObjectPropListElement::EValue);       
        break;
        
    default:
        break;
        }
    __FLOG_VA((_L8("Result = 0x%04X"), responseCode));
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ExtractPropertyL - Exit"));
    return responseCode;    
    }

/**
Validates the data type for a given property code.
@param aElement an object property list element
@param aPropertyCode MTP property code for the element
@return EMTPRespCodeOK if the combination is valid, or another MTP response code if not
*/
TMTPResponseCode CMTPImageDpSendObjectInfo::CheckPropCodeL(const CMTPTypeObjectPropListElement& aElement) const
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckPropCode - Entry"));
    TMTPResponseCode responseCode(EMTPRespCodeOK);
    switch(aElement.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode))
        {
    case EMTPObjectPropCodeStorageID:
        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT32)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }
        else if (iStorageId != aElement.Uint32L(CMTPTypeObjectPropListElement::EValue))
            {
            responseCode = EMTPRespCodeInvalidDataset;
            }
        break;
    
    case EMTPObjectPropCodeObjectFormat:
        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT16)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }
        else if (Request().Uint32(TMTPTypeRequest::ERequestParameter3) != aElement.Uint16L(CMTPTypeObjectPropListElement::EValue))
            {
            responseCode = EMTPRespCodeInvalidDataset;
            }
        break;
       
    case EMTPObjectPropCodeObjectSize:
        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT64)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }
        else if (iObjectSize != aElement.Uint64L(CMTPTypeObjectPropListElement::EValue))
            {
            responseCode = EMTPRespCodeInvalidDataset;
            }
        break;
         
    case EMTPObjectPropCodeParentObject:
        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT32)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }
        else if (Request().Uint32(TMTPTypeRequest::ERequestParameter2) != aElement.Uint32L(CMTPTypeObjectPropListElement::EValue))
            {
            responseCode = EMTPRespCodeInvalidDataset;
            }
        break;

    case EMTPObjectPropCodePersistentUniqueObjectIdentifier:
        responseCode =     EMTPRespCodeAccessDenied;
        break;

    case EMTPObjectPropCodeRepresentativeSampleFormat:
    case EMTPObjectPropCodeProtectionStatus:
        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT16)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }                        
        break;
        
    case EMTPObjectPropCodeDateCreated:
    case EMTPObjectPropCodeDateModified:                    
    case EMTPObjectPropCodeObjectFileName:    
    case EMTPObjectPropCodeName:
        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeString)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }
        break;
        
    case EMTPObjectPropCodeWidth:
    case EMTPObjectPropCodeHeight:
    case EMTPObjectPropCodeImageBitDepth:
    case EMTPObjectPropCodeRepresentativeSampleSize:
    case EMTPObjectPropCodeRepresentativeSampleHeight:
    case EMTPObjectPropCodeRepresentativeSampleWidth:
        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT32)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }
        break;
    case EMTPObjectPropCodeRepresentativeSampleData:
        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeAUINT8)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }        
        break;
    case EMTPObjectPropCodeNonConsumable:
        if (aElement.Uint16L(CMTPTypeObjectPropListElement::EDatatype) != EMTPTypeUINT8)
            {
            responseCode = EMTPRespCodeInvalidObjectPropFormat;
            }
        break;        
    default:
        responseCode = EMTPRespCodeInvalidObjectPropCode;
        break;
        }
    __FLOG_VA((_L8("Result = 0x%04X"), responseCode));
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CheckPropCode - Exit"));
    return responseCode;    
    }

/**
Reserves space for and assigns an object handle to the received object, then
sends a success response.
*/
void CMTPImageDpSendObjectInfo::ReserveObjectL()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ReserveObjectL - Entry"));
    const TInt objectStatusBitmask = 0x8000;//the most significant bit represents importing flag
    
    iReceivedObject->SetUint(CMTPObjectMetaData::EFormatSubCode, objectStatusBitmask);//mark object imported due to it sent by PC
    iReceivedObject->SetUint(CMTPObjectMetaData::EStorageId, iStorageId);    
    iFramework.ObjectMgr().ReserveObjectHandleL(*iReceivedObject, iObjectSize);    
    
    // prepare for rollback
    iRollbackList.AppendL(UnreserveObject);    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::ReserveObjectL - Exit"));   
    }

/**
Sets the read only status on the current file to match the sent object.
*/
void CMTPImageDpSendObjectInfo::SetPropertiesL()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::SetPropertiesL - Entry"));
    
    iObjectPropertyMgr.SetCurrentObjectL(*iReceivedObject, ETrue, ETrue);
    iReceivedObject->SetDesCL(CMTPObjectMetaData::ESuid, iFullPath);
    if (iName.Length() == 0)
        {
        TParsePtrC pathParser(iFullPath);
        iName = pathParser.Name();
        }
    iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeName, iName);
    iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeProtectionStatus, iProtectionStatus);
    iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeWidth, imageWidth);
    iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeHeight, imageHeight);
    iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeImageBitDepth, imageBitDepth);    
    iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeNonConsumable, iNonConsumable);
  
    if(iDateCreated != NULL && iDateCreated->Length())
        {//currently image dp can not support this property
        iObjectPropertyMgr.SetPropertyL(EMTPObjectPropCodeDateCreated, *iDateCreated);
        }
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::SetPropertiesL - Exit"));
    }
    
void CMTPImageDpSendObjectInfo::Rollback()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::Rollback - Entry"));  
    
    TInt count = iRollbackList.Count();
    while(--count >= 0)
        {
        TRAP_IGNORE((*iRollbackList[count])(this));
        }
    iRollbackList.Reset();
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::Rollback - Exit"));  
    }
    
void CMTPImageDpSendObjectInfo::CleanUndoList()
    {
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CleanUndoList - Entry")); 
    
    iRollbackList.Reset();
    
    __FLOG(_L8("CMTPImageDpSendObjectInfo::CleanUndoList - Exit"));  
    }

void CMTPImageDpSendObjectInfo::CreateFsObjectL()
    {
    delete iFileReceived;
    iFileReceived = NULL;
    //prepare for rollback
    iRollbackList.AppendL(RemoveObjectFromFs);
        
    iFileReceived = CMTPTypeFile::NewL(iFramework.Fs(), iFullPath, EFileWrite);
    iFileReceived->SetSizeL(iObjectSize);
    }

TMTPResponseCode CMTPImageDpSendObjectInfo::ErrorToMTPError(TInt aError) const
    {
    TMTPResponseCode resp = EMTPRespCodeGeneralError;
    
    switch (aError)
        {
    case KErrNone:
        resp = EMTPRespCodeOK;
        break;
        
    case KErrAccessDenied:
        resp = EMTPRespCodeAccessDenied;
        break;
        
    case KErrDiskFull:
        resp = EMTPRespCodeStoreFull;
        break;
        
    default:
        break;
        }
        
    return resp;
    }

/**
Check if the object is too large
@return ETrue if yes, otherwise EFalse
*/
TBool CMTPImageDpSendObjectInfo::IsTooLarge(TUint64 aObjectSize) const
    {
    __FLOG(_L8("IsTooLarge - Entry"));
    TBool ret(aObjectSize > KMaxTInt64);
    
    if(!ret)
        {
        TBuf<255> fsname;
        TUint32 storageId = iStorageId;
        if (storageId == KMTPStorageDefault)
            {
            storageId = iFramework.StorageMgr().DefaultStorageId();
            }
        TInt drive( iFramework.StorageMgr().DriveNumber(storageId) );
        if(drive != KErrNotFound)
            {
            iFramework.Fs().FileSystemSubType(drive, fsname);        
        
            const TUint64 KMaxFatFileSize = 0xFFFFFFFF; //Maximal file size supported by all FAT filesystems (4GB-1)
            _LIT(KFsFAT16, "FAT16");
            _LIT(KFsFAT32, "FAT32");
        
            if((fsname.CompareF(KFsFAT16) == 0 || fsname.CompareF(KFsFAT32) == 0) && aObjectSize > KMaxFatFileSize)
                {
                ret = ETrue;
                }
            }
        }
    __FLOG_VA((_L8("Result = %d"), ret));
    __FLOG(_L8("IsTooLarge - Exit"));
    return ret;
    }