mtpfws/mtpfw/dataproviders/dputility/src/cmtpsvccompoundprocessor.cpp
changeset 0 d0791faffa3f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtpfws/mtpfw/dataproviders/dputility/src/cmtpsvccompoundprocessor.cpp	Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,945 @@
+// Copyright (c) 2008-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:
+// mw/remoteconn/mtpfws/mtpfw/dataproviders/dputility/src/cmtpsvccompoundprocessor.cpp
+
+#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/tmtptypeint128.h>
+
+#include "cmtpsvccompoundprocessor.h"
+#include "mmtpservicedataprovider.h"
+#include "mmtpsvcobjecthandler.h"
+
+#include "cmtpconnection.h"
+#include "cmtpconnectionmgr.h"
+#include "mtpsvcdpconst.h"
+
+// Class constants.
+__FLOG_STMT(_LIT8(KComponent,"SvcCompound");)
+
+EXPORT_C MMTPRequestProcessor* CMTPSvcCompoundProcessor::NewL(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection, MMTPServiceDataProvider& aDataProvider)
+	{
+	CMTPSvcCompoundProcessor* self = new (ELeave) CMTPSvcCompoundProcessor(aFramework, aConnection, aDataProvider);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+EXPORT_C CMTPSvcCompoundProcessor::~CMTPSvcCompoundProcessor()
+	{
+	__FLOG(_L8("~CMTPSvcCompoundProcessor - Entry"));
+	delete iReceivedObjectMetaData;
+	delete iObjectInfo;
+	delete iObjectPropList;
+	__FLOG(_L8("~CMTPSvcCompoundProcessor - Exit"));
+	__FLOG_CLOSE; 
+	}
+
+CMTPSvcCompoundProcessor::CMTPSvcCompoundProcessor(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection, MMTPServiceDataProvider& aDataProvider) :
+	CMTPRequestProcessor(aFramework, aConnection, 0, NULL),
+	iDataProvider(aDataProvider), iState(EIdle), iIsCommited(EFalse), iIsRollBackHandlerObject(EFalse)
+	{
+	}
+
+void CMTPSvcCompoundProcessor::ConstructL()
+	{
+	__FLOG_OPEN(KMTPSubsystem, KComponent);
+	__FLOG(_L8("ConstructL - Entry"));
+	iExpectedSendObjectRequest.SetUint16(TMTPTypeRequest::ERequestOperationCode, EMTPOpCodeSendObject);
+	iReceivedObjectMetaData = CMTPObjectMetaData::NewL();
+	iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EDataProviderId, iFramework.DataProviderId());
+	__FLOG(_L8("ConstructL - Exit"));
+	}
+
+/**
+Override to match both the SendObjectInfo/SendObjectPropList/UpdateObjectPropList 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 CMTPSvcCompoundProcessor::Match(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection) const
+	{
+	__FLOG(_L8("Match - Entry"));
+	TBool result = EFalse;
+	TUint16 operationCode = aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode);
+	if ((&iConnection == &aConnection) && 
+		(operationCode == EMTPOpCodeSendObjectInfo || 
+		operationCode == EMTPOpCodeSendObject ||
+		operationCode == EMTPOpCodeUpdateObjectPropList ||
+		operationCode == EMTPOpCodeSendObjectPropList))
+		{
+		result = ETrue;
+		}
+	__FLOG(_L8("Match - Exit"));
+	return result;
+	}
+
+TBool CMTPSvcCompoundProcessor::HasDataphase() const
+	{
+	return ETrue;
+	}
+
+/**
+Verify the request
+@return EMTPRespCodeOK if request is verified, otherwise one of the error response codes
+*/
+TMTPResponseCode CMTPSvcCompoundProcessor::CheckRequestL()
+	{
+	__FLOG(_L8("CheckRequestL - Entry"));
+	TMTPResponseCode responseCode = CMTPRequestProcessor::CheckRequestL();
+	if (EMTPRespCodeOK == responseCode)
+		{
+		responseCode = CheckSendingStateL();
+		if (EMTPRespCodeOK == responseCode)
+			{
+			responseCode = CheckRequestParametersL();
+			}
+		}
+	__FLOG_VA((_L8("CheckRequestL - Exit with code: 0x%04X"), responseCode));
+	return responseCode;
+	}
+
+/**
+Verify if the SendObject request comes after SendObjectInfo/SendObjectPropList request
+@return EMTPRespCodeOK if SendObject request comes after a valid SendObjectInfo request, otherwise
+EMTPRespCodeNoValidObjectInfo
+*/
+TMTPResponseCode CMTPSvcCompoundProcessor::CheckSendingStateL()
+	{
+	__FLOG(_L8("CheckSendingStateL - Entry"));
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	iOperationCode = Request().Uint16(TMTPTypeRequest::ERequestOperationCode);
+	
+	if (iOperationCode == 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);
+		}
+
+	switch (iState)
+		{
+		case EIdle:
+			// Received an orphan SendObject
+			if (iOperationCode == EMTPOpCodeSendObject)
+				{
+				responseCode = EMTPRespCodeNoValidObjectInfo;
+				__FLOG(_L8("EIdle: Received an orphan SendObject request"));
+				}
+			break;
+		case EObjectInfoSucceed:
+			// If another SendObjectInfo or SendObjectPropList operation occurs before a SendObject
+			// operation, the new ObjectInfo or ObjectPropList shall replace the previously held one. 
+			// If this occurs, any storage or memory space reserved for the object described in the 
+			// overwritten ObjectInfo or ObjectPropList dataset should be freed before overwriting and 
+			// allocating the resources for the new data. 
+			
+			// Here is for the processor received another SendObjectInfo or SendObjectPropList 
+			// before a SendObject or process SendObject failed,
+			if (iOperationCode == EMTPOpCodeSendObjectInfo ||
+				iOperationCode == EMTPOpCodeSendObjectPropList ||
+				iOperationCode == EMTPOpCodeUpdateObjectPropList)
+				{
+				iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);
+				if (!iIsCommited)
+					{
+					// Object Size != 0, need roll back all resource for the new SendInfo request
+					CMTPSvcCompoundProcessor::RollBackObject(this);
+					iFramework.ObjectMgr().UnreserveObjectHandleL(*iReceivedObjectMetaData);
+					}
+				delete iObjectInfo;
+				iObjectInfo = NULL;
+				delete iObjectPropList;
+				iObjectPropList = NULL;
+				delete iReceivedObjectMetaData;
+				iReceivedObjectMetaData = NULL;
+				iReceivedObjectMetaData = CMTPObjectMetaData::NewL();
+				iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EDataProviderId, iFramework.DataProviderId());
+				iObjectHandler = NULL;
+				iState = EIdle;
+				// Reset commit state to false
+				iIsCommited = EFalse;
+				__FLOG(_L8("EObjectInfoSucceed: Receive send obj info request again, return to EIdle"));
+				}
+			break;
+		default:
+			User::Leave(KErrGeneral);
+		}
+	__FLOG_VA((_L8("CheckSendingStateL - Exit with code: 0x%04X, state: %u"), responseCode, iState));
+	return responseCode;
+	}
+
+/**
+Validates the data type for a given property code.
+@return EMTPRespCodeOK if the parent handle matches the store id, or another MTP response code if not
+*/
+TMTPResponseCode CMTPSvcCompoundProcessor::CheckRequestParametersL()
+	{
+	__FLOG(_L8("CheckRequestParametersL - Entry"));
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	
+	switch (iOperationCode)
+		{
+		case EMTPOpCodeSendObject:
+			{
+			__FLOG(_L8("Check SendObject request parameters"));
+			// Check SendObject's session ID
+			if (iSessionId != iLastSessionID)
+				{
+				responseCode = EMTPRespCodeNoValidObjectInfo;
+				}
+			else if ((iLastTransactionID + 1) != iTransactionCode)
+				{
+				// Check SendObject's transaction ID
+				responseCode = EMTPRespCodeInvalidTransactionID;
+				}
+			break;
+			}
+
+		case EMTPOpCodeSendObjectInfo:
+			{
+			__FLOG(_L8("Check SendObjectInfo request parameters"));
+			responseCode = CheckStoreAndParent();
+			break;
+			}
+			
+		case EMTPOpCodeSendObjectPropList:
+			{
+			__FLOG(_L8("Check SendObjectPropList request parameters"));
+			responseCode = CheckStoreAndParent();
+			if (EMTPRespCodeOK == responseCode)
+				{
+				// SendObjectPropList need check format code and size in the request
+				TUint32 objectSizeHigh = Request().Uint32(TMTPTypeRequest::ERequestParameter4);
+				TUint32 objectSizeLow  = Request().Uint32(TMTPTypeRequest::ERequestParameter5);
+				iObjectSize = MAKE_TUINT64(objectSizeHigh, objectSizeLow);
+				
+				iFormatCode = Request().Uint32(TMTPTypeRequest::ERequestParameter3);
+				responseCode = CheckFmtAndSetHandler(iFormatCode);
+				iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EFormatCode, iFormatCode);
+				}
+			break;
+			}
+
+		case EMTPOpCodeUpdateObjectPropList:
+			{
+			__FLOG(_L8("Check UpdateObjectPropList request parameters"));
+			TUint32 objectHandle = Request().Uint32(TMTPTypeRequest::ERequestParameter1);
+			if (objectHandle != KMTPHandleNone)
+				{
+				// Find the updating object information
+				MMTPObjectMgr& objects(iFramework.ObjectMgr());
+				if (objects.ObjectL(objectHandle, *iReceivedObjectMetaData))
+					{
+					iFormatCode = iReceivedObjectMetaData->Uint(CMTPObjectMetaData::EFormatCode);
+					if (iReceivedObjectMetaData->Uint(CMTPObjectMetaData::EDataProviderId) != iFramework.DataProviderId())
+						{
+						responseCode = EMTPRespCodeInvalidObjectHandle;
+						}
+					else
+						{
+						responseCode = CheckFmtAndSetHandler(iFormatCode);
+						}
+					}
+				else
+					{
+					responseCode = EMTPRespCodeInvalidObjectHandle;
+					}
+				}
+			else
+				{
+				responseCode = EMTPRespCodeInvalidObjectHandle;
+				}
+			break;
+			}
+			
+		default:
+			// Unexpected operation code
+			responseCode = EMTPRespCodeOperationNotSupported;
+			break;
+		}
+	__FLOG_VA((_L8("CheckRequestParametersL exit with code: 0x%x"), responseCode));
+	return responseCode;
+	}
+
+/**
+Validates the data type for a given property code.
+@return EMTPRespCodeOK if the parent handle matches the store id, or another MTP response code if not
+*/
+TMTPResponseCode CMTPSvcCompoundProcessor::CheckStoreAndParent()
+	{
+	__FLOG(_L8("CheckStoreAndParent - Entry"));
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	iStorageId = Request().Uint32(TMTPTypeRequest::ERequestParameter1);
+	iParentHandle = Request().Uint32(TMTPTypeRequest::ERequestParameter2);
+	
+	// If the first parameter is unused, it should be set to 0x00000000, and the responder should decide
+	// in which store to place the object
+	if (iStorageId == KMTPStorageDefault)
+		{
+		// If the second parameter is used, the first parameter must also be used.
+		// If the second parameter is unused, it should be set to 0x00000000
+		if (iParentHandle != KMTPHandleNone)
+			{
+			responseCode = EMTPRespCodeInvalidParentObject;
+			}
+		else
+			{
+			// Set storage id as service dp's logical storage id.
+			iStorageId = iDataProvider.StorageId();
+			}
+		}
+	else
+		{
+		// Check logical storage id.
+		if (iStorageId != iDataProvider.StorageId())
+			{
+			responseCode = EMTPRespCodeInvalidStorageID;
+			}
+		}
+	
+	__FLOG_VA((_L8("CheckStoreAndParent - Exit with code: 0x%x"), responseCode));
+	return responseCode;
+	}
+
+/**
+SendObjectInfo/SendObjectPropList/UpdateObjectPropList/SendObject request handler
+To maintain the state information between the two requests, the two requests are 
+combined together in one request processor.
+*/
+void CMTPSvcCompoundProcessor::ServiceL()
+	{
+	__FLOG(_L8("ServiceL - Entry"));
+	switch (iState)
+		{
+		case EIdle:
+			ServiceObjectPropertiesL();
+			break;
+		case EObjectInfoSucceed:
+			ServiceSendObjectL();
+			break;
+		default:
+			__FLOG(_L8("Wrong state in ServiceL"));
+			break;
+		}
+	__FLOG(_L8("ServiceL - Exit"));
+	}
+
+void CMTPSvcCompoundProcessor::ServiceObjectPropertiesL()
+	{
+	__FLOG(_L8("ServiceObjectPropertiesL - Entry"));
+	switch (iOperationCode)
+		{
+		case EMTPOpCodeSendObjectInfo:
+			ServiceSendObjectInfoL();
+			break;
+		
+		case EMTPOpCodeSendObjectPropList:
+		case EMTPOpCodeUpdateObjectPropList:
+			ServiceSendObjectPropListL();
+			break;
+		default:
+			break;
+		}
+	__FLOG(_L8("ServiceObjectPropertiesL - Exit"));
+	}
+
+/**
+SendObject request handler
+*/
+void CMTPSvcCompoundProcessor::ServiceSendObjectL()
+	{
+	__FLOG(_L8("ServiceSendObjectL - Entry"));
+	MMTPSvcObjectHandler* pHandler = iDataProvider.ObjectHandler(iFormatCode);
+	if (pHandler)
+		{
+		pHandler->GetBufferForSendObjectL(*iReceivedObjectMetaData, &iObjectContent);
+		}
+	else
+		{
+		User::Leave(KErrGeneral);
+		}
+	ReceiveDataL(*iObjectContent);
+	iState = EObjectSendProcessing;
+	__FLOG(_L8("ServiceSendObjectL - Exit"));
+	}
+
+/**
+SendObjectInfo request handler
+*/
+void CMTPSvcCompoundProcessor::ServiceSendObjectInfoL()
+	{
+	__FLOG(_L8("ServiceSendObjectInfoL - Entry"));
+	delete iObjectInfo;
+	iObjectInfo = NULL;
+	iObjectInfo = CMTPTypeObjectInfo::NewL();
+	ReceiveDataL(*iObjectInfo);
+	iState = EObjectInfoProcessing;
+	__FLOG(_L8("ServiceSendObjectInfoL - Exit"));
+	}
+
+/**
+SendObjectPropList request handler
+*/
+void CMTPSvcCompoundProcessor::ServiceSendObjectPropListL()
+	{
+	__FLOG(_L8("ServiceSendObjectPropListL - Entry"));
+	delete iObjectPropList;
+	iObjectPropList = NULL;
+	iObjectPropList = CMTPTypeObjectPropList::NewL();
+	ReceiveDataL(*iObjectPropList);
+	iState = EObjectInfoProcessing;
+	__FLOG(_L8("ServiceSendObjectPropListL - Exit"));
+	}
+
+/**
+Override to handle the response phase of SendObjectInfo/SendObjectPropList and SendObject requests
+@return EFalse
+*/
+TBool CMTPSvcCompoundProcessor::DoHandleResponsePhaseL()
+	{
+	__FLOG(_L8("DoHandleResponsePhaseL - Entry"));
+	TBool successful = !iCancelled;
+	switch (iState)
+		{
+		case EObjectInfoProcessing:
+			{
+			if (iOperationCode == EMTPOpCodeSendObjectInfo)
+				{
+				successful = DoHandleResponseSendObjectInfoL();
+				}
+			else if (iOperationCode == EMTPOpCodeSendObjectPropList)
+				{
+				successful = DoHandleResponseSendObjectPropListL();
+				}
+			else if (iOperationCode == EMTPOpCodeUpdateObjectPropList)
+				{
+				successful = DoHandleResponseUpdateObjectPropListL();
+				}
+			iState = (successful ? EObjectInfoSucceed : EIdle);
+			break;
+			}
+		case EObjectSendProcessing:
+			{
+			successful = DoHandleResponseSendObjectL();
+			iState = (successful ? EObjectSendSucceed : EObjectSendFail);
+			break;
+			}
+		default:
+			// Wrong State value.
+			__FLOG_VA((_L8("DoHandleResponsePhaseL enter an abnormal state %d"), iState));
+			break;
+		}
+	__FLOG(_L8("DoHandleResponsePhaseL - Exit"));
+	return EFalse;
+	}
+
+/**
+Override to handle the completing phase of SendObjectInfo/SendObjectPropList and SendObject requests
+@return ETrue if succesfully received the object content, otherwise EFalse
+*/
+TBool CMTPSvcCompoundProcessor::DoHandleCompletingPhaseL()
+	{
+	__FLOG(_L8("DoHandleCompletingPhaseL - Entry"));
+	TBool result = ETrue;
+	CMTPRequestProcessor::DoHandleCompletingPhaseL();
+	
+	__FLOG_VA((_L8("DoHandleCompletingPhaseL - Progress State: %u"), iState));
+	switch (iState)
+		{
+		case EObjectInfoSucceed:
+			{
+			// Two cases will come here:
+			// 1. SendObjInfo OK, Store ID for next SendObject checking;
+			// 2. SendObject check request fail, such as wrong transaction id or wrong session id.
+			//    needn't change transaction id.
+			if (iOperationCode == EMTPOpCodeSendObjectInfo || 
+				iOperationCode == EMTPOpCodeUpdateObjectPropList ||
+				iOperationCode == EMTPOpCodeSendObjectPropList)
+				{
+				// Reset transaction id for new SendObjInfo request, but ignore wrong SendObject.
+				iLastTransactionID = iTransactionCode;
+				iLastSessionID = iSessionId;
+				iLastInfoOperationCode = iOperationCode;
+				}
+			result = EFalse;
+			__FLOG_VA((_L8("EObjectInfoSucceed: Save send info transaction id: %u, operation: 0x%x"), iLastTransactionID, iOperationCode));
+			break;
+			}
+		case EObjectSendFail:
+			{
+			// When process SendObject fail, such as received size is wrong.
+			iLastTransactionID++;
+			iState = EObjectInfoSucceed;
+			result = EFalse;
+			break;
+			}
+		default:
+			// The other cases will delete the processor:
+			// 1. SendObject OK
+			// 2. Framework error and call complete with error state.
+			// 3. SendObjInfo fail
+			// 4. First request is orphan SendObject, state is Idle
+			break;
+		}
+	__FLOG(_L8("DoHandleCompletingPhaseL - Exit"));
+	return result;
+	}
+
+/**
+Handling the completing phase of SendObjectInfo request
+@return ETrue if the specified object can be saved on the specified location, otherwise, EFalse
+*/
+TBool CMTPSvcCompoundProcessor::DoHandleResponseSendObjectInfoL()
+	{
+	__FLOG(_L8("DoHandleResponseSendObjectInfoL - Entry"));
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	TBool result(ETrue);
+	iFormatCode = iObjectInfo->Uint16L(CMTPTypeObjectInfo::EObjectFormat);
+	// Check format code and set object handler
+	responseCode = CheckFmtAndSetHandler(iFormatCode);
+	if (responseCode != EMTPRespCodeOK)
+		{
+		SendResponseL(responseCode);
+		}
+	else
+		{
+		iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EFormatCode, iFormatCode);
+		iObjectSize = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EObjectCompressedSize);
+		
+		TBuf<KMaxSUIDLength> suid;
+		// Object mgr process dataset and create a temp object.
+		responseCode = iObjectHandler->SendObjectInfoL(*iObjectInfo, iParentHandle, suid);
+		if (responseCode != EMTPRespCodeOK)
+			{
+			SendResponseL(responseCode);
+			}
+		else
+			{
+			//if object size is zero, then directly store object without waiting for sendobject operation.
+			if (iObjectSize == 0)
+				{
+				__FLOG(_L8("CommitReservedObject because object size is 0 and register for SendObject"));
+				// Commit new temp object to object mgr, if leave, CleanupStack will rollback new temp object. 
+				TCleanupItem rollBackTempObject(RollBackObject, this);
+				CleanupStack::PushL(rollBackTempObject);
+				// Commit prop to obj mgr
+				iObjectHandler->CommitForNewObjectL(suid);
+				CleanupStack::Pop(this);
+	
+				// Prepare to store the created object to framework
+				iIsRollBackHandlerObject = ETrue;
+				TCleanupItem rollBackTempObjectAndSuid(RollBackObject, this);
+				CleanupStack::PushL(rollBackTempObjectAndSuid);
+				// Set the created suid to meta
+				iReceivedObjectMetaData->SetDesCL(CMTPObjectMetaData::ESuid, suid);
+				// An object handle issued during a successful SendObjectInfo or SendObjectPropList operation should 
+				// be reserved for the duration of the MTP session
+				ReserveObjectL();
+				// Commit the created object to framework, if leave, then framework will return General Error
+				// CleanupStack will rollback the new created object via delete object operation.
+				iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObjectMetaData);
+				CleanupStack::Pop(this);
+				iIsRollBackHandlerObject = EFalse;
+				iIsCommited = ETrue;
+				RegisterRequestAndSendResponseL(responseCode);
+				}
+			else
+				{
+				// An object handle issued during a successful SendObjectInfo or SendObjectPropList operation should 
+				// be reserved for the duration of the MTP session
+				ReserveObjectL();
+				RegisterRequestAndSendResponseL(responseCode);
+				}
+			}
+		}
+	result = (responseCode == EMTPRespCodeOK) ? ETrue : EFalse;
+	__FLOG_VA((_L8("DoHandleResponseSendObjectInfoL exit with code: 0x%x"), responseCode));
+	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 CMTPSvcCompoundProcessor::DoHandleResponseSendObjectPropListL()
+	{
+	__FLOG(_L8("DoHandleResponseSendObjectPropListL - Entry"));
+	TBool result = ETrue;
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	
+	TBuf<KMaxSUIDLength> suid;
+	TUint32 parameter = 0;
+	responseCode = SendObjectPropListL(*iObjectPropList, iParentHandle, parameter, suid, iObjectSize);
+	if (responseCode != EMTPRespCodeOK)
+		{
+		SendResponseL(responseCode, 4, &parameter);
+		}
+	else
+		{
+		//if object size is zero, then directly store object without waiting for sendobject operation.
+		if (iObjectSize == 0)
+			{
+			__FLOG(_L8("CommitReservedObject because object size is 0 and register for SendObject"));
+			// Commit new temp object to object mgr, if leave, CleanupStack will rollback new temp object. 
+			TCleanupItem rollBackTempObject(RollBackObject, this);
+			CleanupStack::PushL(rollBackTempObject);
+			// Commit prop to obj mgr
+			iObjectHandler->CommitForNewObjectL(suid);
+			CleanupStack::Pop(this);
+
+			// Prepare to store the created object to framework
+			iIsRollBackHandlerObject = ETrue;
+			TCleanupItem rollBackTempObjectAndSuid(RollBackObject, this);
+			CleanupStack::PushL(rollBackTempObjectAndSuid);
+			// Set the created suid to meta
+			iReceivedObjectMetaData->SetDesCL(CMTPObjectMetaData::ESuid, suid);
+			// An object handle issued during a successful SendObjectInfo or SendObjectPropList operation should 
+			// be reserved for the duration of the MTP session
+			ReserveObjectL();
+			// Commit the created object to framework, if leave, then framework will return General Error
+			// CleanupStack will rollback the new created object via delete object operation.
+			iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObjectMetaData);
+			CleanupStack::Pop(this);
+			iIsRollBackHandlerObject = EFalse;
+			iIsCommited = ETrue;
+			RegisterRequestAndSendResponseL(responseCode);
+			}
+		else
+			{
+			// An object handle issued during a successful SendObjectInfo or SendObjectPropList operation should 
+			// be reserved for the duration of the MTP session
+			ReserveObjectL();
+			RegisterRequestAndSendResponseL(responseCode);
+			}
+		}
+
+	result = (responseCode == EMTPRespCodeOK) ? ETrue : EFalse;
+	__FLOG_VA((_L8("DoHandleResponseSendObjectPropListL exit with code = 0x%x"), responseCode));
+	return result;
+	}
+
+/**
+Handling the completing phase of UpdateObjectPropList request
+@return ETrue if the specified object can be saved on the specified location, otherwise, EFalse
+*/
+TBool CMTPSvcCompoundProcessor::DoHandleResponseUpdateObjectPropListL()
+	{
+	__FLOG(_L8("DoHandleResponseUpdateObjectPropListL - Entry"));
+	TBool result = ETrue;
+	TUint32 parameter = 0;
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	// Check object size property with format
+	responseCode = ExtractObjectSizeL();
+	if (responseCode == EMTPRespCodeOK)
+		{
+		responseCode = UpdateObjectPropListL(*iReceivedObjectMetaData, *iObjectPropList, parameter);
+		}
+
+	if (responseCode == EMTPRespCodeOK)
+		{
+		if (iObjectSize == 0)
+			{
+			// If commit leave, roll back the temp object.
+			TCleanupItem rollBackTempObject(RollBackObject, this);
+			CleanupStack::PushL(rollBackTempObject);
+			// Commit prop to obj mgr
+			iObjectHandler->CommitL();
+			CleanupStack::Pop(this);
+			// Commit to obj mgr is ok
+			iIsCommited = ETrue;
+			// Update operation needn't change framework property so far.
+			iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId);
+			iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection);
+			}
+		else
+			{
+			iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId);
+			iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection);
+			}
+		}
+	SendResponseL(responseCode, 1, &parameter);
+	result = (responseCode == EMTPRespCodeOK) ? ETrue: EFalse;
+	__FLOG_VA((_L8("DoHandleResponseUpdateObjectPropListL exit with code: 0x%x"), responseCode));
+	return result;
+	}
+
+/**
+Handling the completing phase of SendObject request
+@return ETrue if the object has been successfully saved on the device, otherwise, EFalse
+*/
+TBool CMTPSvcCompoundProcessor::DoHandleResponseSendObjectL()
+	{
+	__FLOG(_L8("DoHandleResponseSendObjectL - Entry"));
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	TBool result = ETrue;
+
+	if (iCancelled)
+		{
+		iObjectHandler->RollBack();
+		responseCode = EMTPRespCodeTransactionCancelled;
+		}
+	else if (iObjectSize != 0)
+		{
+		// For 0 sized object, ignore the object content verify
+		TUint64 receiveSize = iObjectContent->Size();
+		if (iObjectSize < receiveSize)
+			{
+			// If the object sent in the data phase of this operation is larger than 
+			// the size indicated in the ObjectInfo dataset sent in the SendObjectInfo 
+			// which precedes this operation, this operation should fail and a response 
+			// code of Store_Full should be returned.
+			responseCode = EMTPRespCodeStoreFull;
+			}
+		else if (iObjectSize > receiveSize)
+			{
+			responseCode = EMTPRespCodeIncompleteTransfer;
+			}
+		// If size is ok, then just need commit the object to data store.
+		}
+	
+	// Commit or Unreserver from framework if object size is not 0.
+	if (responseCode == EMTPRespCodeOK && iObjectSize != 0)
+		{
+		// For create new object, need commit the reserved handle to framework, but update needn't do that
+		if (iLastInfoOperationCode != EMTPOpCodeUpdateObjectPropList)
+			{
+			TBuf<KMaxSUIDLength> suid;
+			// Commit new temp object to object mgr, if leave, CleanupStack will rollback new temp object. 
+			TCleanupItem rollBackTempObject(RollBackObject, this);
+			CleanupStack::PushL(rollBackTempObject);
+			// Commit prop to obj mgr
+			iObjectHandler->CommitForNewObjectL(suid);
+			CleanupStack::Pop(this);
+
+			// Prepare to store the created object to framework
+			iIsRollBackHandlerObject = ETrue;
+			TCleanupItem rollBackTempObjectAndSuid(RollBackObject, this);
+			CleanupStack::PushL(rollBackTempObjectAndSuid);
+			// Set the created suid to meta
+			iReceivedObjectMetaData->SetDesCL(CMTPObjectMetaData::ESuid, suid);
+			// Commit the created object to framework, if leave, then framework will return General Error
+			// CleanupStack will rollback the new created object via delete object operation.
+			iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObjectMetaData);
+			CleanupStack::Pop(this);
+			iIsRollBackHandlerObject = EFalse;
+			iIsCommited = ETrue;
+			}
+		else
+			{
+			// If commit leave, roll back the temp object.
+			TCleanupItem rollBackNewObject(RollBackObject, this);
+			CleanupStack::PushL(rollBackNewObject);
+			// Commit prop to obj mgr
+			iObjectHandler->CommitL();
+			CleanupStack::Pop(this);
+			// Commit to obj mgr is ok
+			iIsCommited = ETrue;
+			}
+		}
+
+	SendResponseL(responseCode);
+	// Release the processor when SendObject or Transaction Canceled and unregister SendObject.
+	result = (responseCode == EMTPRespCodeOK || responseCode == EMTPRespCodeTransactionCancelled) ? ETrue : EFalse;
+	if (result)
+		{
+		iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection);
+		}
+	__FLOG_VA((_L8("DoHandleResponseSendObjectL exit with code = 0x%x"), responseCode));
+	return result;
+	}
+
+TMTPResponseCode CMTPSvcCompoundProcessor::ExtractObjectSizeL()
+	{
+	__FLOG(_L8("ExtractObjectSizeL - Entry"));
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	TBool foundSizeProp  = EFalse;
+	const TUint KCount(iObjectPropList->NumberOfElements());
+	iObjectPropList->ResetCursor();
+	for (TUint i = 0; i < KCount; i++)
+		{
+		const CMTPTypeObjectPropListElement& KElement = iObjectPropList->GetNextElementL();
+		if (EMTPObjectPropCodeObjectSize == KElement.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode))
+			{
+			iObjectSize = KElement.Uint64L(CMTPTypeObjectPropListElement::EValue);
+			foundSizeProp = ETrue;
+			break;
+			}
+		}
+	
+	if (!foundSizeProp)
+		{
+		// Object size in data set is not available, get the corresponding object's current size property.
+		const TDesC& suid = iReceivedObjectMetaData->DesC(CMTPObjectMetaData::ESuid);
+		responseCode = iObjectHandler->GetObjectSizeL(suid, iObjectSize);
+		if (iObjectSize == KObjectSizeNotAvaiable)
+			{
+			responseCode = EMTPRespCodeGeneralError;
+			}
+		}
+
+	__FLOG(_L8("ExtractObjectSizeL - Exit"));
+	return responseCode;
+	}
+
+/**
+Reserves space for and assigns an object handle to the received object, then
+sends a success response.
+*/
+void CMTPSvcCompoundProcessor::ReserveObjectL()
+	{
+	__FLOG(_L8("ReserveObjectL - Entry"));
+	iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EStorageId, iStorageId);
+	iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EParentHandle, iParentHandle);
+	iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EFormatCode, iFormatCode);
+	iFramework.ObjectMgr().ReserveObjectHandleL(*iReceivedObjectMetaData, iObjectSize);
+	__FLOG_VA((_L8("ReserveObjectL Exit Storage:%u, ParentHandle:%u, FormatCode:%u, Size:%u "), iStorageId, iParentHandle, iFormatCode, iObjectSize));
+	}
+
+void CMTPSvcCompoundProcessor::RegisterRequestAndSendResponseL(TMTPResponseCode aResponseCode)
+	{
+	__FLOG(_L8("RegisterRequestAndSendResponseL - Entry"));
+	// Register to framework for handle the next sendobj request
+	iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId);
+	iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection);
+	TUint32 parameters[3];
+	parameters[0] = iStorageId;
+	parameters[1] = iParentHandle;
+	// Responder’s reserved ObjectHandle for the incoming object
+	parameters[2] = iReceivedObjectMetaData->Uint(CMTPObjectMetaData::EHandle);
+	SendResponseL(aResponseCode, 3, parameters);
+	__FLOG(_L8("RegisterRequestAndSendResponseL - Exit"));
+	}
+
+void CMTPSvcCompoundProcessor::RollBackObject(TAny* aObject)
+	{
+	reinterpret_cast<CMTPSvcCompoundProcessor*>(aObject)->RollBack();
+	}
+
+void CMTPSvcCompoundProcessor::RollBack()
+	{
+	iObjectHandler->RollBack();
+	if (iIsRollBackHandlerObject)
+		{
+		TRAP_IGNORE(iObjectHandler->DeleteObjectL(*iReceivedObjectMetaData));
+		iIsRollBackHandlerObject = EFalse;
+		}
+	}
+
+TMTPResponseCode CMTPSvcCompoundProcessor::CheckFmtAndSetHandler(TUint32 aFormatCode)
+	{
+	__FLOG(_L8("CheckFmtAndSetHandler - Entry")); 
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	iObjectHandler = iDataProvider.ObjectHandler(aFormatCode);
+	if (!iObjectHandler)
+		{
+		responseCode = EMTPRespCodeInvalidObjectFormatCode;
+		}
+	__FLOG(_L8("CheckFmtAndSetHandler - Exit"));
+	return responseCode;
+	}
+
+TMTPResponseCode CMTPSvcCompoundProcessor::SendObjectPropListL(const CMTPTypeObjectPropList& aObjectPropList, TUint32& aParentHandle, 
+														TUint32& aParameter, TDes& aSuid, TUint64 aObjectSize)
+	{
+	__FLOG(_L8("SendObjectPropListL - Entry"));
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	aParameter = 0;
+
+	responseCode = iObjectHandler->SendObjectPropListL(aObjectSize, aObjectPropList, aParentHandle, aSuid);
+	// If handler cache an entry in SendObjectPropList, then it should never return error code. Processor will 
+	// not rollback in this case
+	if (EMTPRespCodeOK == responseCode)
+		{
+		// Parse elements and set property for the object.
+		const TUint count(aObjectPropList.NumberOfElements());
+		aObjectPropList.ResetCursor();
+		for (TUint i = 0; i < count && responseCode == EMTPRespCodeOK; i++)
+			{
+			CMTPTypeObjectPropListElement& element = aObjectPropList.GetNextElementL();
+			TUint32 handle = element.Uint32L(CMTPTypeObjectPropListElement::EObjectHandle);
+			// All ObjectHandle fields must contain the value 0x00000000, and all properties that are defined in 
+			// this operation will be applied to the object, need check every handle value and keep all properties is atomic.
+			if (handle != KMTPHandleNone)
+				{
+				responseCode = EMTPRespCodeInvalidDataset;
+				aParameter = i;
+				break;
+				}
+			else
+				{
+				// Create a new object, don't commit, it will be done in processor.
+				responseCode = iObjectHandler->SetObjectPropertyL(aSuid, element, EMTPOpCodeSendObjectPropList);
+				}
+			if (responseCode != EMTPRespCodeOK)
+				{
+				aParameter = i;
+				break;
+				}
+			}
+		// Roll back the temp object
+		if (EMTPRespCodeOK != responseCode)
+			{
+			iObjectHandler->RollBack();
+			}
+		}
+	__FLOG_VA((_L8("SendObjectPropListL - Exit with responseCode = 0x%04X"), responseCode));
+	return responseCode;
+	}
+
+// All object handlers current don't support partial update, so once update one parameter failed,
+// all updated will be reverted.
+TMTPResponseCode CMTPSvcCompoundProcessor::UpdateObjectPropListL(CMTPObjectMetaData& aObjectMetaData, 
+														const CMTPTypeObjectPropList& aObjectPropList, 
+														TUint32& /*aParameter*/)
+	{
+	__FLOG(_L8("UpdateObjectPropList - Entry")); 
+	TMTPResponseCode responseCode = EMTPRespCodeOK;
+	const TUint count = aObjectPropList.NumberOfElements();
+	aObjectPropList.ResetCursor();
+	for (TUint i = 0; i < count; i++)
+		{
+		CMTPTypeObjectPropListElement& element = aObjectPropList.GetNextElementL();
+		TUint32 handle = element.Uint32L(CMTPTypeObjectPropListElement::EObjectHandle);
+		// All object handle in dataset must contain either 0x00000000 or match with the parameter 1
+		if (handle != aObjectMetaData.Uint(CMTPObjectMetaData::EHandle) && handle != KMTPHandleNone)
+			{
+			responseCode = EMTPRespCodeInvalidObjectHandle;
+			}
+		else
+			{
+			const TDesC& suid = aObjectMetaData.DesC(CMTPObjectMetaData::ESuid);
+			// Update will be treated as adding a new object for RO object property.
+			responseCode = iObjectHandler->SetObjectPropertyL(suid, element, EMTPOpCodeUpdateObjectPropList);
+			}
+		if(EMTPRespCodeOK != responseCode)
+			{
+			iObjectHandler->RollBack();
+			break;
+			}
+		}
+	__FLOG_VA((_L8("UpdateObjectPropListL - Exit with responseCode = 0x%04X"), responseCode));
+	return responseCode;
+	}