sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include "clientmessagecmn.h"
sl@0: 
sl@0: using namespace BSUL;
sl@0: 
sl@0: /**
sl@0: Base 64 decoding table
sl@0: */
sl@0: const TInt8 AsciiToBase64[80]=
sl@0: 	{
sl@0: 	 62, -1, -1, -1, 63, 52, 53, 54, 55, 56,
sl@0: 	 57, 58, 59, 60, 61, -1, -1, -1, 64, -1,
sl@0: 	 -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,
sl@0: 	  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
sl@0: 	 18, 19, 20, 21, 22, 23, 24, 25, -1, -1,
sl@0: 	 -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
sl@0: 	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
sl@0: 	 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
sl@0: 	};
sl@0: 
sl@0: /**
sl@0: Base 64 encoding table
sl@0: */	
sl@0: const TInt8 Base64ToAscii[65]=
sl@0: 	{
sl@0: 	 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
sl@0: 	 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
sl@0: 	 85, 86, 87, 88, 89, 90, 97, 98, 99,100,
sl@0: 	101,102,103,104,105,106,107,108,109,110,
sl@0: 	111,112,113,114,115,116,117,118,119,120,
sl@0: 	121,122, 48, 49, 50, 51, 52, 53, 54, 55,
sl@0: 	 56, 57, 43, 47, 61 
sl@0: 	};
sl@0: 	
sl@0: const TInt8 KImcvLookUpStartOffset = 43;
sl@0: const TUint8 KImcvConvEquals = '=';
sl@0: /**
sl@0: The maximum number of US ASCII characters per line that are before the CRLF line
sl@0: terminator when sending emails.  RFC 2822 recommends that each line SHOULD not exceed
sl@0: 80 characters including the CRLF terminator, and MUST not exceed 1000.
sl@0: */
sl@0: const TInt KMaxB64EncodedCharsPerLine = 60; // Could be increased to 75 characters for every encoded line if KDecodeLineLength = 675.  60 was chosen to maintain existing behaviour.
sl@0: 
sl@0: /**
sl@0: Parameter factory function lookup table.  This is used to instantiate a 
sl@0: CMessageParameterBase derived object based on a TParamType enum value
sl@0: */
sl@0: const TMessageParameterFactoryFn KParameterFactoryFunctions[] = {NULL,
sl@0: 															CIntParameter::NewL,
sl@0: 															CDes8ReadParameter::NewL,
sl@0: 															CDes8Parameter::NewL,
sl@0: 															CPckgParameter::NewL,
sl@0: 															CDes16ReadParameter::NewL,
sl@0: 															CDes16Parameter::NewL,
sl@0: 															CPtrParameter::NewL};
sl@0: 
sl@0: /**
sl@0: Panic string for client message framework panic
sl@0: */
sl@0: #ifdef _DEBUG
sl@0: _LIT(KPanicCategory,"BSUL::ClientMsg");
sl@0: #endif
sl@0: 
sl@0: const TInt KMaxServerNameLength = 32;
sl@0: 
sl@0: /**
sl@0: This static function is used to panic the server in case of
sl@0: incorrect use of CMessageParameterBase APIs or a badly formed
sl@0: message schema
sl@0: @param 	aPanic The Panic value
sl@0: */
sl@0: void PanicServer(TInt aPanic)
sl@0: 	{
sl@0: 	_LIT(KUnknownServer, "Unknown");
sl@0: 	TBuf<KMaxServerNameLength> serverName(KUnknownServer);
sl@0: 	
sl@0: 	//Get the TLS data for this thread
sl@0: 	TClientMessageServerData* serverData = static_cast<TClientMessageServerData*>(Dll::Tls());
sl@0: 	
sl@0: 	if(serverData != NULL)
sl@0: 		{
sl@0: 		TPtrC8 name(serverData->iServerName);
sl@0: 		serverName.Copy(name);
sl@0: 		}
sl@0: 	
sl@0: 	User::Panic(serverName, aPanic);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Static initialisation function for ClientMessage Framework
sl@0: @param 	aServerData The initialisation data for the server using the library
sl@0: @leave Any system wide error code
sl@0: */
sl@0: EXPORT_C void CClientMessage::InitialiseFrameworkL(const TClientMessageServerData& aServerData)
sl@0: 	{
sl@0: 	__ASSERT_DEBUG(User::StringLength(aServerData.iServerName) <= KMaxServerNameLength, User::Invariant());
sl@0: 	Dll::SetTls((TAny*)&aServerData);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Static factory function for CClientMessage class
sl@0: @param 	aMessage The message that this object encapsulates
sl@0: @return Pointer to a fully constructed CClientMessage object.
sl@0: @leave  KErrNotInitialised if the framework has not been initialised by a 
sl@0: 		call to InitialiseFrameworkL.
sl@0: */
sl@0: EXPORT_C CClientMessage* CClientMessage::NewL(const RMessage2& aMessage)
sl@0: 	{
sl@0: 	const TClientMessageServerData* serverData = static_cast<const TClientMessageServerData*>(Dll::Tls());
sl@0: 	if(serverData == NULL)
sl@0: 		{
sl@0: 		User::Leave(KErrNotInitialised);
sl@0: 		}
sl@0: 	
sl@0: 	CClientMessage* self = new(ELeave) CClientMessage(aMessage,*serverData);
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop(self);
sl@0: 
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: /**
sl@0: Second phase constructor of CClientMessage Object
sl@0: Finds the schema for this message and checks the caller against the security
sl@0: policy defined for this message.  Traverses the array of message parameters
sl@0: and instantiates a CMessageParameterBase object for each parameter and adds these
sl@0: to its internal array.
sl@0: @leave  KErrInvalidFunction If the message function is not found in the message table
sl@0: @leave  KErrBadHandle if the message handle is Null
sl@0: @leave KErrPermissionDenied if the security policy for this message is not satisfied
sl@0: */
sl@0: void CClientMessage::ConstructL()
sl@0: 	{
sl@0: 	if(!iMessage.IsNull())
sl@0: 		{
sl@0: 		
sl@0: 		//Find the message schema for this message.
sl@0: 		const TClientMessageSchema* messageSchema = FindMessageSchema();
sl@0: 		
sl@0: 		if(!messageSchema)
sl@0: 			{
sl@0: 			LogBadMessageL(KErrInvalidFunction);
sl@0: 			User::Leave(KErrInvalidFunction);
sl@0: 			}
sl@0: 				
sl@0: 		//Check message against security policy
sl@0: 		CheckSecurityPolicyL(messageSchema->iPolicy);
sl@0: 				
sl@0: 		//iterate through message parameters and instantiate all parameter objects
sl@0: 		for(int index = 0;index < messageSchema->iParamCount;index++)
sl@0: 			{	
sl@0: 			CMessageParameterBase* parameter = 
sl@0: 					CMessageParameterBase::CreateL(messageSchema->iParams[index], index, iMessage);		
sl@0: 			
sl@0: 			//Some parameter types are defined to be ignored.  These
sl@0: 			//should not be added to the list of parameters
sl@0: 			if(parameter != NULL)
sl@0: 				{
sl@0: 				//AppendL can leave so use cleanupstack to ensure that memory is not
sl@0: 				//leaked if AppendL leaves.
sl@0: 				CleanupStack::PushL(parameter);
sl@0: 				iParameters.AppendL(parameter);
sl@0: 				CleanupStack::Pop(parameter);
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		LogBadMessageL(KErrBadHandle);
sl@0: 		User::Leave(KErrBadHandle);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Constructor for CClientMessage Object
sl@0: @param aMessage The RMessage2 to be represented by this object
sl@0: @param aServerData The Initialisation data for the server creating this object
sl@0: */
sl@0: EXPORT_C CClientMessage::CClientMessage(const RMessage2& aMessage, 
sl@0: 						const TClientMessageServerData& aServerData) 
sl@0: 		: iParameters(KMaxParameters), iMessage(aMessage),
sl@0: 		iServerData(aServerData),iFlags(aServerData.iFlags & 0xFFFF0000)
sl@0: 
sl@0: 	{	
sl@0: 	
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Destructor for CClientMessageObject
sl@0: */
sl@0: EXPORT_C CClientMessage::~CClientMessage()
sl@0: 	{
sl@0: 	for(int i = 0; i < iParameters.Count();i++)
sl@0: 		{
sl@0: 		delete iParameters[i];
sl@0: 		}
sl@0: 	iParameters.Reset();
sl@0: 	}
sl@0: 
sl@0: EXPORT_C const RMessage2& CClientMessage::Message()
sl@0: 	{
sl@0: 	return iMessage;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Panics the client through the message object
sl@0: set an internal flag to indicate that the RMessage reference handle is now NULL
sl@0: due to the client thread being tidied up.
sl@0: @param 	aServer The Panic category
sl@0: @param 	aPanic The Panic value
sl@0: */
sl@0: EXPORT_C void CClientMessage::PanicClient(const TDesC& aServer, TInt aPanic)
sl@0: 	{
sl@0: 	iMessage.Panic(aServer, aPanic);
sl@0: 	iFlags.Set(EFlagPanicClient);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Checks a message against the security policy defined for the server
sl@0: @param aPolicy The security policy to check this message against
sl@0: @leave	KErrPermissionDenied if the message does not fulfil the security policy
sl@0: */
sl@0: void CClientMessage::CheckSecurityPolicyL(const TSecurityPolicy& aPolicy)
sl@0: 	{
sl@0: 	if(!(aPolicy.CheckPolicy(iMessage,
sl@0: 				"Client failed security policy check for this server")))
sl@0: 		{
sl@0: 		User::Leave(KErrPermissionDenied);
sl@0: 		}
sl@0: 	return;
sl@0: 	}
sl@0: 	
sl@0: /**
sl@0: Finds a message schema in the message table for this server.
sl@0: Does a binary search on the function number to pull the correct
sl@0: message from the table.  Note that this assumes that the table
sl@0: is sorted.
sl@0: @return	A pointer to a TClientMessageSchema object in the message table, or Null if 
sl@0: 		the message does not correpsond to a message in the message table
sl@0: */
sl@0: const TClientMessageSchema* CClientMessage::FindMessageSchema()
sl@0: 	{
sl@0: 	//This should always be less than KNumClientMessages 
sl@0: 	TInt function = iMessage.Function();
sl@0: 	TInt beg = 0;
sl@0: 	TInt end = iServerData.iMessageCount - 1;
sl@0: 	TInt mid = 0;
sl@0: 	TInt midFn = 0;
sl@0: 	
sl@0: 	while(beg <= end)
sl@0: 		{
sl@0: 		mid = (end + beg)/2;
sl@0: 		
sl@0: 		midFn = iServerData.iMessageSchema[mid].iFunction;
sl@0: 		if(midFn > function)
sl@0: 			{
sl@0: 			end = mid - 1;
sl@0: 			}	
sl@0: 		else if(midFn < function)
sl@0: 			{
sl@0: 			beg = mid + 1;
sl@0: 			}	
sl@0: 		else
sl@0: 			{
sl@0: 			return &iServerData.iMessageSchema[mid];
sl@0: 			}
sl@0: 		}
sl@0: 	return NULL;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: /**
sl@0: Validates the message parameters against the constraints provided 
sl@0: in the message table
sl@0: @leave	KErrBadMessage if the message fails validation against the criteria supplied in the 
sl@0: 		message table
sl@0: @leave	Any system-wide error code
sl@0: */
sl@0: EXPORT_C void CClientMessage::ValidateL()
sl@0: 	{
sl@0: 	
sl@0: 	for(int i = 0; i < iParameters.Count();i++)
sl@0: 		{
sl@0: 		iParameters[i]->ValidateL();
sl@0: 		iFlags.Set(i);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Validates a single message argument against the constraints provided 
sl@0: in the message table
sl@0: @param aParam The index value identifying the argument to validate
sl@0: @leave	KErrBadMessage if the message fails validation against the criteria supplied in the 
sl@0: 		message table for the requested argument
sl@0: @leave	KErrArgument if aParam is negative or is greater than the number of parameters for
sl@0: 		this message
sl@0: @leave	Any system-wide error code
sl@0: */
sl@0: EXPORT_C void CClientMessage::ValidateL(TInt aParam)
sl@0: 	{
sl@0: 	
sl@0: 	if(( aParam >= 0) && (aParam < iParameters.Count()))
sl@0: 		{	
sl@0: 		iParameters[aParam]->ValidateL();
sl@0: 		iFlags.Set(aParam);
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		User::Leave(KErrArgument);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Checks if a given parameter has been validated
sl@0: @param aParam The index value identifying the paramater to check
sl@0: @leave	KErrArgument if aParam is not a valid parameter value
sl@0: @leave	KErrNotValidated if the parameter has not been validated
sl@0: */
sl@0: void CClientMessage::CheckValidatedL(TInt aParam)
sl@0: 	{
sl@0: 	if((aParam < EFlagParam0Validated) || (aParam > EFlagParam3Validated))
sl@0: 		{
sl@0: 		User::Leave(KErrArgument);
sl@0: 		}
sl@0: 	
sl@0: 	if(!iFlags.IsSet(aParam))
sl@0: 		{
sl@0: 		User::Leave(KErrNotValidated);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: 
sl@0: /**
sl@0: Checks if a bad messages should be logged
sl@0: @return True if bad messages should be logged
sl@0: */
sl@0: TBool CClientMessage::LogBadMessages()
sl@0: 	{
sl@0: 	return iFlags.IsSet(EFlagLogBadMessages);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Checks if a bad messages should be logged
sl@0: @param aError The error code to log
sl@0: */
sl@0: void CClientMessage::LogBadMessageL(TInt aError)
sl@0: 	{
sl@0: 	//Check if logging of bad messages is enabled
sl@0: 	if(LogBadMessages())
sl@0: 		{
sl@0: 
sl@0: 		TUid sid = TUid(iMessage.SecureId());
sl@0: 		TUidName clientSid = sid.Name();
sl@0: 		
sl@0: 		TInt function = Function();
sl@0: 		
sl@0: 		TBuf<KMaxServerNameLength> serverName;
sl@0: 		TPtrC8 name(iServerData.iServerName);
sl@0: 		serverName.Copy(name);
sl@0: 		
sl@0: 		switch(aError)
sl@0: 			{			
sl@0: 	#ifdef _DEBUG	
sl@0: 	
sl@0: 				
sl@0: 			case KErrInvalidFunction:
sl@0: 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Unknown function request from client %S.\n"),
sl@0: 								&serverName,aError,function, &clientSid);
sl@0: 				break;
sl@0: 				
sl@0: 			case KErrBadParameter:
sl@0: 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Bad argument in IPC request from client %S.\n"),
sl@0: 								&serverName,aError,function, &clientSid);
sl@0: 				break;
sl@0: 				
sl@0: 			case KErrBadMessageSchema:
sl@0: 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Message schema incotrectly defined for this function %S.\n"),
sl@0: 								&serverName,aError,function, &clientSid);
sl@0: 				break;
sl@0: 				
sl@0: 			case KErrBadDescriptor:
sl@0: 			case KErrOverflow:
sl@0: 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Bad descriptor argument in IPC request from client %S.\n"),
sl@0: 								&serverName,aError,function, &clientSid);
sl@0: 				break;
sl@0: 				
sl@0: 			case KErrNotValidated:
sl@0: 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Message parameter not validated before use %S.\n"),
sl@0: 								&serverName,aError,function, &clientSid);
sl@0: 				break;
sl@0: 				
sl@0: 			default:
sl@0: 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Bad message received from client %S.\n"),
sl@0: 										&serverName,aError,function, &clientSid);
sl@0: 			break;
sl@0: 	#else	
sl@0: 			default:
sl@0: 				break;
sl@0: 	#endif
sl@0: 			}
sl@0: 		}
sl@0: 	
sl@0: 
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Completes the message request or Panics the client if a
sl@0: message error has occured.
sl@0: @param aError The error value to complete the message with
sl@0: */
sl@0: EXPORT_C void CClientMessage::CompleteRequestL(TInt aError)
sl@0: 	{
sl@0: 	//If server panics client 
sl@0: 	//then iMessage will be NULL
sl@0: 	if(!iFlags.IsSet(EFlagPanicClient))
sl@0: 		{
sl@0: 		if(aError != KErrNone)
sl@0: 			{
sl@0: 			LogBadMessageL(aError);
sl@0: 			}
sl@0: 		
sl@0: 		switch(aError)
sl@0: 			{
sl@0: 			case KErrInvalidFunction:
sl@0: 			case KErrBadDescriptor:
sl@0: 			case KErrOverflow:
sl@0: 				{
sl@0: 				//Check if Panic is disabled
sl@0: 				if( iFlags.IsClear(EFlagDoNotPanicClientOnBadMessageErrors) )
sl@0: 					{
sl@0: 					TBuf<KMaxServerNameLength> serverName;
sl@0: 					TPtrC8 name(iServerData.iServerName);
sl@0: 					serverName.Copy(name);
sl@0: 					PanicClient(serverName, aError);
sl@0: 					break;
sl@0: 					}
sl@0: 				}
sl@0: 			default:
sl@0: 				{	
sl@0: 				iMessage.Complete(aError);
sl@0: 				break;
sl@0: 				}
sl@0: 			}//switch
sl@0: 			
sl@0: 		}//if
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the function number of this message
sl@0: @return The function number of this message
sl@0: */
sl@0: EXPORT_C TInt CClientMessage::Function()
sl@0: 	{
sl@0: 	return iMessage.Function();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the requested message argument as an integer value
sl@0: @param aParam The parameter number to retrieve
sl@0: @return The Int value for the requested parameter
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not an integer type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter 
sl@0: type that is not CIntParameter.
sl@0: */
sl@0: EXPORT_C TInt CClientMessage::GetIntL(TInt aParam)
sl@0: 	{	
sl@0: 	CheckValidatedL(aParam);
sl@0: 
sl@0: 	return iParameters[aParam]->GetIntL();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the requested message argument as an TAny*
sl@0: @param aParam The parameter number to retrieve
sl@0: @return The TAny* for the requested parameter
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not an Ptr type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter 
sl@0: type that is not CPtrParameter.
sl@0: */
sl@0: EXPORT_C const TAny* CClientMessage::GetPtrL(TInt aParam)
sl@0: 	{	
sl@0: 	CheckValidatedL(aParam);
sl@0: 	
sl@0: 	return iParameters[aParam]->GetPtrL();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets a reference to the local copy of the descriptor read from the message
sl@0: @param aParam The parameter number of the descriptor to retrieve
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not a readable
sl@0: 		TDes8 type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter 
sl@0: type that is not CDes8ReadParameter.
sl@0: */
sl@0: EXPORT_C const TDesC8& CClientMessage::GetDes8L(TInt aParam)
sl@0: 	{
sl@0: 	CheckValidatedL(aParam);
sl@0: 	
sl@0: 	return iParameters[aParam]->GetDes8L();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets a reference to the local copy of the descriptor read from the message
sl@0: @param aParam The parameter number of the descriptor to retrieve
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not a readable
sl@0: 		TDes16 type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter 
sl@0: type that is not CDes16ReadParameter.
sl@0: */
sl@0: EXPORT_C const TDesC& CClientMessage::GetDes16L(TInt aParam)
sl@0: 	{
sl@0: 	CheckValidatedL(aParam);
sl@0: 	
sl@0: 	return iParameters[aParam]->GetDes16L();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: /**
sl@0: Gets a descriptor value read from the message
sl@0: @param aParam The parameter number of the descriptor to retrieve
sl@0: @param aDes On exit contains the descriptor value requested
sl@0: @param aOffset The desired offset from which to read the descriptor
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not a readable
sl@0: 		TDes8 type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter 
sl@0: type that is not CDes8Parameter or CDes8ReadParameter.
sl@0: */
sl@0: EXPORT_C void CClientMessage::ReadL(TInt aParam, TDes8& aDes, TInt aOffset)
sl@0: 	{
sl@0: 	CheckValidatedL(aParam);
sl@0: 
sl@0: 	iParameters[aParam]->ReadL(aDes, aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets a descriptor value read from the message
sl@0: @param aParam The parameter number of the descriptor to retrieve
sl@0: @param aDes On exit contains the descriptor value requested
sl@0: @param aOffset The desired offset from which to read the descriptor
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not a readable 
sl@0: 		TDes16 type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter 
sl@0: type that is not CDes16Parameter or CDes16ReadParameter.
sl@0: */
sl@0: EXPORT_C void CClientMessage::ReadL(TInt aParam, TDes16& aDes, TInt aOffset)
sl@0: 	{
sl@0: 	CheckValidatedL(aParam);
sl@0: 	
sl@0: 	iParameters[aParam]->ReadL(aDes, aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Writes to a descriptor field in the message
sl@0: @param aParam The parameter number of the descriptor to write
sl@0: @param aDes The descriptor to write to the message
sl@0: @param aOffset The desired offset at which to write the descriptor
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not a writable 
sl@0: 		TDes8 type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter 
sl@0: type that is not CDes8Parameter
sl@0: */
sl@0: EXPORT_C void CClientMessage::WriteL(TInt aParam, const TDesC8& aDes, TInt aOffset)
sl@0: 	{
sl@0: 	CheckValidatedL(aParam);
sl@0: 	
sl@0: 	iParameters[aParam]->WriteL(aDes, aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Writes to a descriptor field in the message
sl@0: @param aParam The parameter number of the descriptor to write
sl@0: @param aDes The descriptor to write to the message
sl@0: @param aOffset The desired offset at which to write the descriptor
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not a writable 
sl@0: 		TDes16 type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter 
sl@0: type that is notCDes16Parameter
sl@0: */
sl@0: EXPORT_C void CClientMessage::WriteL(TInt aParam, const TDesC16& aDes, TInt aOffset)
sl@0: 	{	
sl@0: 	CheckValidatedL(aParam);
sl@0: 	
sl@0: 	iParameters[aParam]->WriteL(aDes, aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the length of the requested descriptor message argument
sl@0: @param aParam The parameter number to retrieve
sl@0: @return The Length of the descriptor in the client process
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not a descriptor type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter 
sl@0: type that is not a descriptor type.
sl@0: */
sl@0: EXPORT_C TInt CClientMessage::GetDesLengthL(TInt aParam)
sl@0: 	{
sl@0: 	CheckValidatedL(aParam);
sl@0: 	
sl@0: 	return iParameters[aParam]->GetDesLengthL();
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the max length of the requested descriptor message argument
sl@0: @param aParam The parameter number to retrieve
sl@0: @return The Max length of the descriptor in the client process
sl@0: @leave	KErrNotValidated if the message parameter has not been validated
sl@0: 		KErrWrongParameterType in UREL is the parameter requested is not a descriptor type
sl@0: 		Any other system wide error code
sl@0: @panic ECMPanicWrongParameterType If this function is called for a parameter type 
sl@0: that is not a descriptor type.
sl@0: */
sl@0: EXPORT_C TInt CClientMessage::GetDesMaxLengthL(TInt aParam)
sl@0: 	{
sl@0: 	CheckValidatedL(aParam);
sl@0: 	
sl@0: 	return iParameters[aParam]->GetDesMaxLengthL();
sl@0: 	}
sl@0: 
sl@0: /********************************************************************************
sl@0:  * 			CMessageParameterBase and Derived Class Definitions
sl@0:  *******************************************************************************/
sl@0: 
sl@0: 
sl@0: /**
sl@0: Factory function for instantiating derived Parameter classes.
sl@0: Uses factory lookup table to instantiate approptiate parameter 
sl@0: object based on parameter details passed in
sl@0: @param aParam Parameter details object used to instantiate an appropriate
sl@0: 			implementation of CMessageParameterBase.
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter represented by 
sl@0: 			this object
sl@0: @return A fully constructed CMessageParameterBase derived object deterimined by 
sl@0: 		aParam.
sl@0: @leave	KErrBadMessageSchema in UREL if if the schema for this parameter is 
sl@0: 		incorrectly defined
sl@0: @leave	Any system-wide error code.
sl@0: @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
sl@0: 		incorrectly defined
sl@0: */
sl@0: CMessageParameterBase* CMessageParameterBase::CreateL(const TParameterDetails& aParam, 
sl@0: 			TInt aParamIndex, const RMessage2& aMessage)
sl@0: 	{
sl@0: 	
sl@0: 	//The parameter type is the bottom 16 bits of the param type
sl@0: 	TInt paramType = (aParam.iType & KParamTypeMask);
sl@0: 	
sl@0: 	__ASSERT_DEBUG((paramType > 0), PanicServer(ECMPanicBadMessageSchema));
sl@0: 	
sl@0: 	CMessageParameterBase* newParam = NULL;
sl@0: 	
sl@0: 	switch(paramType)
sl@0: 		{
sl@0: 		case EParamInt:
sl@0: 		case EParamDes8Read:
sl@0: 		case EParamDes8:
sl@0: 		case EParamDes16Read:
sl@0: 		case EParamDes16:
sl@0: 		case EParamPtr:
sl@0: 		case EParamPckg:
sl@0: 			{	
sl@0: 			//Create the new parameter object
sl@0: 			newParam = (KParameterFactoryFunctions[paramType])(aParam, aParamIndex, 
sl@0: 							aMessage, GetValidationFunctionL(aParam));
sl@0: 			break;
sl@0: 			}
sl@0: 			
sl@0: 		default:
sl@0: 			{
sl@0: #ifdef _DEBUG
sl@0: 			PanicServer(ECMPanicBadMessageSchema);
sl@0: #else
sl@0: 			User::Leave(KErrBadMessageSchema);
sl@0: #endif
sl@0: 			}
sl@0: 	}
sl@0: 
sl@0: 	return newParam;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Constructor for CMessageParameterBase object
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter represented by 
sl@0: 			this object
sl@0: */
sl@0: CMessageParameterBase::CMessageParameterBase(const TParameterDetails& aParam, 
sl@0: 		TInt aParamIndex,const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	: iIndex(aParamIndex), iMessage(aMessage), iParamDetails(aParam), iValidationFn(aValidationFn)
sl@0: 	{
sl@0: 
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the validation function for this parameter from the 
sl@0: TClientMessageServerData structure
sl@0: @param aParam Parameter object used to find the validation function
sl@0: @return The validation function for this parameter type
sl@0: @leave	KErrBadMessageSchema in UREL if if the schema for this parameter is 
sl@0: 		incorrectly defined
sl@0: @leave	Any other system wide error code
sl@0: @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
sl@0: 		incorrectly defined
sl@0: */
sl@0: TCustomValidationFn CMessageParameterBase::GetValidationFunctionL(const TParameterDetails& aParam)
sl@0: 	{
sl@0: 	//Get the TLS data for this thread - this will never be null at this point 
sl@0: 	//as it is checked in CClientMessage::NewL
sl@0: 	TClientMessageServerData* serverData = static_cast<TClientMessageServerData*>(Dll::Tls());
sl@0: 	
sl@0: 	//The index of the validation function for this parameter is held in 
sl@0: 	//the upper 16 bits of aParam.iType. Mask this out and shift down to 
sl@0: 	//get the index.
sl@0: 	TInt fnIndex = (aParam.iType & KValidationFnIndexMask) >> KShift16Bit;
sl@0: 	
sl@0: 	
sl@0: 	if(fnIndex >= serverData->iValidationFnCount)
sl@0: 		{
sl@0: #ifdef _DEBUG
sl@0: 			PanicServer(ECMPanicBadMessageSchema);
sl@0: #else
sl@0: 			User::Leave(KErrBadMessageSchema);
sl@0: #endif
sl@0: 		}
sl@0: 	
sl@0: 	//Return the validation function
sl@0: 	return serverData->iCustomValidationFns[fnIndex];
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of GetIntL for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @return KErrNone - A Dummy return value
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: TInt CMessageParameterBase::GetIntL()
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of GetPtrL for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @return NULL - A Dummy return value
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: const TAny* CMessageParameterBase::GetPtrL()
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif
sl@0: 	return NULL;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of WriteL for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: void CMessageParameterBase::WriteL(const TDesC8& /*aDes*/, TInt /*aOffset*/)
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of WriteL for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: void CMessageParameterBase::WriteL(const TDesC& /*aDes*/, TInt /*aOffset*/)
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of ReadL for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: void CMessageParameterBase::ReadL(TDes8& /*aDes*/,TInt /*aOffset*/)
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of ReadL for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: void CMessageParameterBase::ReadL(TDes& /*aDes*/, TInt /*aOffset*/)
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of GetDesLengthL for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @return KErrNone - A Dummy return
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: TInt CMessageParameterBase::GetDesLengthL()
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of GetDesMaxLengthL for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @return KErrNone - A Dummy return
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: TInt CMessageParameterBase::GetDesMaxLengthL()
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of GetDes8L for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @return KErrNone - A Dummy return
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: 
sl@0: const TDesC8& CMessageParameterBase::GetDes8L()
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif	
sl@0: 	_LIT8(KDummy,"");
sl@0: 	return KDummy;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Default implementation of GetDes16L for CMessageParameterBase object.
sl@0: This is only called if this API is not defined for the given parameter type.
sl@0: @return KErrNone - A Dummy return
sl@0: @leave KErrWrongParameterType in UREL if this function is not defined for the 
sl@0: 		given parameter type
sl@0: @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
sl@0: 		given parameter type
sl@0: */
sl@0: const TDesC& CMessageParameterBase::GetDes16L()
sl@0: 	{
sl@0: #ifdef _DEBUG
sl@0: 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
sl@0: #else
sl@0: 	User::Leave(KErrWrongParameterType);
sl@0: #endif	
sl@0: 	
sl@0: 	_LIT(KDummy,"");
sl@0: 	return KDummy;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Returns the value of iMin defined in the schema for this parameter
sl@0: @return The Min constraint for this parameter
sl@0: */
sl@0: TInt CMessageParameterBase::Min()
sl@0: 	{
sl@0: 	return iParamDetails.iMin;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Returns the value of iMax defined in the schema for this parameter
sl@0: @return The max constraint for this parameter
sl@0: */
sl@0: TInt CMessageParameterBase::Max()
sl@0: 	{
sl@0: 	return iParamDetails.iMax;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: /**
sl@0: Factory function for instantiating CIntParameter objects
sl@0: @param aParam Parameter details object used to construct object.
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter represented by 
sl@0: @return A fully constructed CIntParameter object.
sl@0: @leave	Any system-wide error code.
sl@0: */
sl@0: CMessageParameterBase* CIntParameter::NewL(const TParameterDetails& aParam, 
sl@0: 				TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	{
sl@0: 	CIntParameter* self = new(ELeave) CIntParameter(aParam, aParamIndex, aMessage, aValidationFn);
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Constructor for CIntParameter class.
sl@0: @param aParam Parameter details to be encapsulated by object
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
sl@0: 		incorrectly defined
sl@0: */
sl@0: CIntParameter::CIntParameter(const TParameterDetails& aParam, TInt aParamIndex,
sl@0: 			const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 		: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
sl@0: 		
sl@0: 	{	
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMax >= iParamDetails.iMin), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Destructor for CIntParameter class.
sl@0: */
sl@0: CIntParameter::~CIntParameter()
sl@0: 	{
sl@0: 
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Validates given message parameter agains constraints
sl@0: represented by this object. Stores the Int value from the message
sl@0:  to allow for simple retrieval when required.
sl@0: @leave	KErrBadParameter if the message parameter does not conform
sl@0: 		to the constraints represented by this object
sl@0: @leave	Any system-wide error code
sl@0: */
sl@0: void CIntParameter::ValidateL()
sl@0: 	{
sl@0: 	
sl@0: 	switch(iIndex)
sl@0: 		{
sl@0: 	
sl@0: 		case 0:
sl@0: 			iValue = iMessage.Int0();
sl@0: 			break;
sl@0: 		
sl@0: 		case 1:
sl@0: 			iValue = iMessage.Int1();
sl@0: 			break;
sl@0: 		
sl@0: 		case 2:
sl@0: 			iValue = iMessage.Int2();
sl@0: 			break;
sl@0: 			
sl@0: 		case 3:
sl@0: 			iValue = iMessage.Int3();
sl@0: 			break;
sl@0: 		
sl@0: 		default:
sl@0: 			User::Leave(KErrArgument);
sl@0: 			break;
sl@0: 		}
sl@0: 	
sl@0: 	if(iValidationFn != NULL)
sl@0: 		{
sl@0: 		iValidationFn(this);	
sl@0: 		}
sl@0: 	
sl@0: 	else
sl@0: 		{	
sl@0: 		if((iValue < iParamDetails.iMin)||(iValue > iParamDetails.iMax))
sl@0: 			{
sl@0: 			User::Leave(KErrBadParameter);
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Retrieves the TInt value read from the clients message during validation
sl@0: @return The TInt value read from the client message
sl@0: */
sl@0: TInt CIntParameter::GetIntL()
sl@0: 	{
sl@0: 	return iValue;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Factory function for instantiating CDes8ReadParameter objects
sl@0: @param aParam Parameter details object used to construct object.
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @return A fully constructed CDes8ReadParameter object.
sl@0: @leave	Any system-wide error code.
sl@0: */
sl@0: CMessageParameterBase* CDes8ReadParameter::NewL(const TParameterDetails& aParam, 
sl@0: 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	{
sl@0: 	CDes8ReadParameter* self = 
sl@0: 		new(ELeave) CDes8ReadParameter(aParam, aParamIndex, aMessage, aValidationFn);
sl@0: 	
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Constructor for CDes8ReadParameter class.
sl@0: @param aParam Parameter details to be encapsulated by object
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
sl@0: 		incorrectly defined
sl@0: */
sl@0: CDes8ReadParameter::CDes8ReadParameter(const TParameterDetails& aParam, TInt aParamIndex,
sl@0: 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
sl@0: 	{	
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMin >= 0), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMax > 0), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMax >= iParamDetails.iMin), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Destructor for CDes8ReadParameter class.
sl@0: */
sl@0: CDes8ReadParameter::~CDes8ReadParameter()
sl@0: 	{
sl@0: 	delete iValue;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Validates given message argument against constraints
sl@0: represented by this object. Reads in the descriptor from the 
sl@0: clients message to enable simple retrival when required.
sl@0: @leave	KErrBadDescriptor if the message parameter does not conform
sl@0: 		to the constraints represented by this object
sl@0: @leave	Any system-wide error code
sl@0: */
sl@0: void CDes8ReadParameter::ValidateL()
sl@0: 	{
sl@0: 	TInt length = iMessage.GetDesLengthL(iIndex);
sl@0: 	
sl@0: 	//if there is a supplied custom validation function, call that now
sl@0: 	if(iValidationFn != NULL)
sl@0: 		{
sl@0: 		iValidationFn(this);
sl@0: 		}
sl@0: 	
sl@0: 	else
sl@0: 		{		
sl@0: 		if((length < iParamDetails.iMin) || (length > iParamDetails.iMax))
sl@0: 			{
sl@0: 			User::Leave(KErrBadDescriptor);
sl@0: 			}
sl@0: 		}
sl@0: 	
sl@0: 	iValue = HBufC8::NewL(length);
sl@0: 	TPtr8 ptr = iValue->Des();
sl@0: 	ReadL(ptr,0);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the descriptor read from the clients message during validation
sl@0: @return	const reference to the local descriptor copy
sl@0: */
sl@0: const TDesC8& CDes8ReadParameter::GetDes8L()
sl@0: 	{
sl@0: 	return *iValue;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the length of the descriptor in the client message
sl@0: @return	The length of the descriptor
sl@0: @leave	KErrBadDescriptor if the message argument is not a descriptor type
sl@0: 		Any other system wide error code
sl@0: */
sl@0: TInt CDes8ReadParameter::GetDesLengthL()
sl@0: 	{
sl@0: 	return iMessage.GetDesLengthL(iIndex);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Retrieves the descriptor value read from the clients 
sl@0: message during validation
sl@0: @param aDes The target descriptor.
sl@0: @param aOffset The offset from the start of the clients descriptor
sl@0: @leave KErrArgument if iIndex has a value outside the valid range, or if aOffset is negative.
sl@0: @panic ECMPanicBadDescriptor in UDEB if the supplied descriptor is too small. 
sl@0: if the schema for this parameter is incorrectly defined
sl@0: */
sl@0: void CDes8ReadParameter::ReadL(TDes8& aDes, TInt aOffset)
sl@0: 	{
sl@0: 	__ASSERT_DEBUG((aDes.MaxLength() >= (iMessage.GetDesLengthL(iIndex) - aOffset)), 
sl@0: 			PanicServer(ECMPanicBadDescriptor));
sl@0: 	
sl@0: 	iMessage.ReadL(iIndex,aDes,aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Factory function for instantiating CDes8WriteParameter objects
sl@0: @param aParam Parameter details object used to construct object.
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @return A fully constructed CDes8WriteParameter object.
sl@0: @leave	Any system-wide error code.
sl@0: */
sl@0: CMessageParameterBase* CDes8Parameter::NewL(const TParameterDetails& aParam, 
sl@0: 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	{
sl@0: 	CDes8Parameter* self = 
sl@0: 		new(ELeave) CDes8Parameter(aParam, aParamIndex, aMessage, aValidationFn);
sl@0: 	
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Constructor for CDes8WriteParameter class.
sl@0: @param aParam Parameter details to be encapsulated by object
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
sl@0: 		incorrectly defined
sl@0: */
sl@0: CDes8Parameter::CDes8Parameter(const TParameterDetails& aParam, TInt aParamIndex,
sl@0: 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
sl@0: 		
sl@0: 	{
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMin >= 0), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMax >= 0), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Destructor for CDes8WriteParameter class.
sl@0: */
sl@0: CDes8Parameter::~CDes8Parameter()
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Validates given message argument against constraints
sl@0: represented by this object.
sl@0: @leave	KErrBadDescriptor if the message parameter does not conform
sl@0: 		to the constraints represented by this object
sl@0: @leave	Any system-wide error code
sl@0: */
sl@0: void CDes8Parameter::ValidateL()
sl@0: 	{
sl@0: 	
sl@0: 	//if there is a supplied custom validation function, call that now
sl@0: 	if(iValidationFn != NULL)
sl@0: 		{
sl@0: 		iValidationFn(this);
sl@0: 		}
sl@0: 	
sl@0: 	else
sl@0: 		{
sl@0: 		TInt length = iMessage.GetDesLengthL(iIndex);
sl@0: 		TInt maxLength = iMessage.GetDesMaxLengthL(iIndex);
sl@0: 		
sl@0: 		if((maxLength < iParamDetails.iMin)||(length > iParamDetails.iMax))
sl@0: 			{
sl@0: 			User::Leave(KErrBadDescriptor);
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the length of the descriptor in the client message
sl@0: @return	The length of the descriptor
sl@0: @leave	KErrBadDescriptor if the message argument is not a descriptor type
sl@0: 		Any other system wide error code
sl@0: */
sl@0: TInt CDes8Parameter::GetDesLengthL()
sl@0: 	{
sl@0: 	return iMessage.GetDesLengthL(iIndex);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the max length of the descriptor in the client message
sl@0: @return	The max length of the descriptor
sl@0: @leave	KErrBadDescriptor if the message argument is not a descriptor type
sl@0: 		Any other system wide error code
sl@0: */
sl@0: TInt CDes8Parameter::GetDesMaxLengthL()
sl@0: 	{
sl@0: 	return iMessage.GetDesMaxLengthL(iIndex);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: /**
sl@0: Reads a descriptor from the requested message argument
sl@0: @param aDes The target descriptor.
sl@0: @param aOffset The offset from the start of the clients descriptor
sl@0: @leave	Any system wide error code.
sl@0: @panic ECMPanicBadDescriptor in UDEB if the supplied descriptor is too small. 
sl@0: */
sl@0: void CDes8Parameter::ReadL(TDes8& aDes, TInt aOffset)
sl@0: 	{
sl@0: 	__ASSERT_DEBUG((aDes.MaxLength() >= (iMessage.GetDesLengthL(iIndex) - aOffset)), 
sl@0: 			PanicServer(ECMPanicBadDescriptor));
sl@0: 	
sl@0: 	iMessage.ReadL(iIndex,aDes,aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Validates and writes a descriptor to the requested 
sl@0: message argument
sl@0: @param aDes The source descriptor containing the data to be written.
sl@0: @param aOffset The offset from the start of the clients descriptor
sl@0: @leave	   Any system wide error code.
sl@0: */
sl@0: void CDes8Parameter::WriteL(const TDesC8& aDes, TInt aOffset)
sl@0: 	{
sl@0: 	iMessage.WriteL(iIndex,aDes,aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Factory function for instantiating CIntParameter objects
sl@0: @param aParam Parameter details object used to construct object.
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @return A fully constructed CIntParameter object.
sl@0: @leave	Any system-wide error code.
sl@0: */
sl@0: CMessageParameterBase* CDes16ReadParameter::NewL(const TParameterDetails& aParam, 
sl@0: 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	{
sl@0: 	CDes16ReadParameter* self = 
sl@0: 		new(ELeave) CDes16ReadParameter(aParam, aParamIndex, aMessage, aValidationFn);
sl@0: 	
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Constructor for CDes8ReadParameter class.
sl@0: @param aParam Parameter details to be encapsulated by object
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
sl@0: 		incorrectly defined
sl@0: */
sl@0: CDes16ReadParameter::CDes16ReadParameter(const TParameterDetails& aParam, TInt aParamIndex,
sl@0: 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
sl@0: 	{
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMin >= 0), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMax > 0), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMax >= iParamDetails.iMin), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Destructor for CDes16ReadParameter class.
sl@0: */
sl@0: CDes16ReadParameter::~CDes16ReadParameter()
sl@0: 	{
sl@0: 	delete iValue;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Validates given message argument against constraints
sl@0: represented by this object. Reads in the descriptor from the 
sl@0: clients message to enable simple retrival when required.
sl@0: @leave	KErrBadDescriptor if the message parameter does not conform
sl@0: 		to the constraints represented by this object
sl@0: @leave	Any system-wide error code
sl@0: */
sl@0: void CDes16ReadParameter::ValidateL()
sl@0: 	{
sl@0: 	TInt length = iMessage.GetDesLengthL(iIndex);
sl@0: 	
sl@0: 	//if there is a supplied custom validation function, call that now
sl@0: 	if(iValidationFn != NULL)
sl@0: 		{
sl@0: 		iValidationFn(this);
sl@0: 		}
sl@0: 	
sl@0: 	else
sl@0: 		{		
sl@0: 		if((length < iParamDetails.iMin) || (length > iParamDetails.iMax))
sl@0: 			{
sl@0: 			User::Leave(KErrBadDescriptor);
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	iValue = HBufC::NewL(length);
sl@0: 	TPtr ptr = iValue->Des();
sl@0: 	ReadL(ptr,0);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the descriptor read from the clients message during validation
sl@0: @return	const reference to the local descriptor copy
sl@0: */
sl@0: const TDesC& CDes16ReadParameter::GetDes16L()
sl@0: 	{
sl@0: 	return *iValue;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the length of the descriptor in the client message
sl@0: @return	The length of the descriptor
sl@0: @leave	KErrBadDescriptor if the message argument is not a descriptor type
sl@0: 		Any other system wide error code
sl@0: */
sl@0: TInt CDes16ReadParameter::GetDesLengthL()
sl@0: 	{
sl@0: 	return iMessage.GetDesLengthL(iIndex);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Retrieves the descriptor value read from the clients 
sl@0: message during validation
sl@0: @param aDes The target descriptor.
sl@0: @param aOffset The offset from the start of the clients descriptor
sl@0: @leave	KErrArgument if the suplied descriptor is too small or an invalid
sl@0: 		offset is supplied
sl@0: @panic ECMPanicBadDescriptor in UDEB if the supplied descriptor is too small. 
sl@0: */
sl@0: void CDes16ReadParameter::ReadL(TDes& aDes, TInt aOffset)
sl@0: 	{
sl@0: 	__ASSERT_DEBUG((aDes.MaxLength() >= (iMessage.GetDesLengthL(iIndex) - aOffset)), 
sl@0: 			PanicServer(ECMPanicBadDescriptor));
sl@0: 	
sl@0: 	iMessage.ReadL(iIndex,aDes,aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Factory function for instantiating CDes16WriteParameter objects
sl@0: @param aParam Parameter details object used to construct object.
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @return A fully constructed CDes16WriteParameter object.
sl@0: @leave	Any system-wide error code.
sl@0: */
sl@0: CMessageParameterBase* CDes16Parameter::NewL(const TParameterDetails& aParam,
sl@0: 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	{
sl@0: 	CDes16Parameter* self = 
sl@0: 		new(ELeave) CDes16Parameter(aParam, aParamIndex, aMessage, aValidationFn);
sl@0: 	
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Constructor for CDes16WriteParameter class.
sl@0: @param aParam Parameter details to be encapsulated by object
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
sl@0: 		incorrectly defined
sl@0: */
sl@0: CDes16Parameter::CDes16Parameter(const TParameterDetails& aParam, TInt aParamIndex,
sl@0: 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
sl@0: 	{
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMin >= 0), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	__ASSERT_DEBUG((iParamDetails.iMax >= 0), 
sl@0: 			PanicServer(ECMPanicBadMessageSchema));
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Destructor for CDes16WriteParameter class.
sl@0: */
sl@0: CDes16Parameter::~CDes16Parameter()
sl@0: 	{
sl@0: 	
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Validates given message argument against constraints
sl@0: represented by this object.
sl@0: @leave	KErrBadDescriptor if the message parameter does not conform
sl@0: 		to the constraints represented by this object
sl@0: @leave	Any system-wide error code
sl@0: */
sl@0: void CDes16Parameter::ValidateL()
sl@0: 	{	
sl@0: 	
sl@0: 	//if there is a supplied custom validation function, call that now
sl@0: 	if(iValidationFn != NULL)
sl@0: 		{
sl@0: 		iValidationFn(this);
sl@0: 		}	
sl@0: 	else
sl@0: 		{		
sl@0: 		TInt length = iMessage.GetDesLengthL(iIndex);
sl@0: 		TInt maxLength = iMessage.GetDesMaxLengthL(iIndex);
sl@0: 		
sl@0: 		if((maxLength < iParamDetails.iMin)||(length > iParamDetails.iMax))
sl@0: 			{
sl@0: 			User::Leave(KErrBadDescriptor);
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the length of the descriptor in the client message
sl@0: @return	The length of the descriptor
sl@0: @leave	KErrBadDescriptor if the message argument is not a descriptor type
sl@0: 		Any other system wide error code
sl@0: */
sl@0: TInt CDes16Parameter::GetDesLengthL()
sl@0: 	{
sl@0: 	return iMessage.GetDesLengthL(iIndex);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Gets the max length of the descriptor in the client message
sl@0: @return	The max length of the descriptor
sl@0: @leave	KErrBadDescriptor if the message argument is not a descriptor type
sl@0: 		Any other system wide error code
sl@0: */
sl@0: TInt CDes16Parameter::GetDesMaxLengthL()
sl@0: 	{
sl@0: 	return iMessage.GetDesMaxLengthL(iIndex);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Reads a descriptor from the requested message argument
sl@0: @param aDes The target descriptor.
sl@0: @param aOffset The offset from the start of the clients descriptor
sl@0: @leave	Any system wide error code.
sl@0: @panic ECMPanicBadDescriptor in UDEB if the supplied descriptor is too small. 
sl@0: */
sl@0: void CDes16Parameter::ReadL(TDes& aDes,	TInt aOffset)
sl@0: 	{
sl@0: 	__ASSERT_DEBUG((aDes.MaxLength() >= (iMessage.GetDesLengthL(iIndex) - aOffset)), 
sl@0: 			PanicServer(ECMPanicBadDescriptor));
sl@0: 	
sl@0: 	iMessage.ReadL(iIndex,aDes,aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Writes a descriptor to the requested message argument
sl@0: @param aDes The source descriptor containing the data to be written.
sl@0: @param aOffset The offset from the start of the clients descriptor
sl@0: @leave	Any system wide error code.
sl@0: */
sl@0: void CDes16Parameter::WriteL(const TDesC& aDes,	TInt aOffset)
sl@0: 	{
sl@0: 	iMessage.WriteL(iIndex,aDes,aOffset);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Factory function for instantiating CPckgParameter objects
sl@0: @param aParam Parameter details object used to construct object.
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @return A fully constructed CPckgParameter object.
sl@0: @leave	Any system-wide error code.
sl@0: */
sl@0: CMessageParameterBase* CPckgParameter::NewL(const TParameterDetails& aParam, 
sl@0: 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn )
sl@0: 	{
sl@0: 	CPckgParameter* self = 
sl@0: 		new(ELeave) CPckgParameter(aParam, aParamIndex, aMessage, aValidationFn);
sl@0: 	
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Constructor for CPckgParameter class.
sl@0: @param aParam Parameter details to be encapsulated by object
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: */
sl@0: CPckgParameter::CPckgParameter(const TParameterDetails& aParam, TInt aParamIndex,
sl@0: 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	: CDes8Parameter(aParam, aParamIndex, aMessage, aValidationFn)
sl@0: 		
sl@0: 	{
sl@0: 
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Destructor for CPckgParameter class.
sl@0: */
sl@0: CPckgParameter::~CPckgParameter()
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Validates given message argument against constraints
sl@0: represented by this object.
sl@0: @leave	KErrBadDescriptor if the message parameter does not conform
sl@0: 		to the constraints represented by this object
sl@0: @leave	Any system-wide error code
sl@0: */
sl@0: void CPckgParameter::ValidateL()
sl@0: 	{
sl@0: 	
sl@0: 	//if there is a supplied custom validation function, call that now
sl@0: 	if(iValidationFn != NULL)
sl@0: 		{
sl@0: 		iValidationFn(this);
sl@0: 		}
sl@0: 	
sl@0: 	else
sl@0: 		{
sl@0: 		TInt length = iMessage.GetDesLengthL(iIndex);
sl@0: 		
sl@0: 		if((length < iParamDetails.iMin)||(length > iParamDetails.iMax))
sl@0: 			{
sl@0: 			User::Leave(KErrBadDescriptor);
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Factory function for instantiating CPtrParameter objects
sl@0: @param aParam Parameter details object used to construct object.
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: @return A fully constructed CPtrParameter object.
sl@0: @leave	Any system-wide error code.
sl@0: */
sl@0: CMessageParameterBase* CPtrParameter::NewL(const TParameterDetails& aParam, 
sl@0: 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	{
sl@0: 	CPtrParameter* self = new(ELeave) CPtrParameter(aParam, aParamIndex, aMessage, aValidationFn);
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Constructor for CPtrParameter class.
sl@0: @param aParamIndex The Index of this parameter within the RMessage2 arguments
sl@0: @param aMessage The RMessage2 object containing the parameter to be represented
sl@0: */
sl@0: CPtrParameter::CPtrParameter(const TParameterDetails& aParam, TInt aParamIndex,
sl@0: 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
sl@0: 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
sl@0: 	{
sl@0: 	
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Validates given message argument against constraints
sl@0: represented by this object. Stores the TAny* from the 
sl@0: clients message to enable simple retrival when required.
sl@0: @leave	KErrArgument if the argument index is invalid
sl@0: @leave	Any system-wide error code
sl@0: */
sl@0: void CPtrParameter::ValidateL()
sl@0: 	{
sl@0: 
sl@0: 	switch(iIndex)
sl@0: 		{
sl@0: 	
sl@0: 		case 0:
sl@0: 			iValue = iMessage.Ptr0();
sl@0: 			break;
sl@0: 		
sl@0: 		case 1:
sl@0: 			iValue = iMessage.Ptr1();
sl@0: 			break;
sl@0: 		
sl@0: 		case 2:
sl@0: 			iValue = iMessage.Ptr2();
sl@0: 			break;
sl@0: 			
sl@0: 		case 3:
sl@0: 			iValue = iMessage.Ptr3();
sl@0: 			break;
sl@0: 		
sl@0: 		default:
sl@0: 			User::Leave(KErrArgument);
sl@0: 			break;
sl@0: 		}
sl@0: 	
sl@0: 	//if there is a supplied custom validation function, call that now
sl@0: 	if(iValidationFn != NULL)
sl@0: 		{
sl@0: 		iValidationFn(this);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Retrieves the TAny pointer read from the clients message during validation
sl@0: @return The TAny pointer read from the client message
sl@0: */
sl@0: const TAny* CPtrParameter::GetPtrL()
sl@0: 	{
sl@0: 	return iValue;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Decode the string
sl@0: @param aSrcString Source string
sl@0: @param rDestString Destination string
sl@0: @return  1 if aSrcString is not long enough to decode fully, resulting in the storage of
sl@0: 	the last character and requiring another aSrcString (poss 0 length) to be passed to it to 
sl@0: 	clear this character. 
sl@0: @return 0 if the line was decoded OK or the end of the encoded file is reached ie "="
sl@0: */
sl@0: 
sl@0: EXPORT_C  TInt Base64Codec::Decode(const TDesC8& aSrcString, TDes8& rDestString)
sl@0: 	{
sl@0: 	TInt shiftStored = 0;
sl@0: 	TInt maskShiftStored = ESix;
sl@0: 	
sl@0: 	TInt decodedInt=0;
sl@0: 	TInt8 offsetChar=0;
sl@0: 	TUint8 decodedChar=0;
sl@0: 	 
sl@0: 	// Clears the destination string
sl@0: 	rDestString.Zero();
sl@0: 
sl@0: 	// Initialise variables
sl@0: 	const TUint8* srcStringPtr=aSrcString.Ptr();
sl@0: 	const TUint8* srcStringEnd=aSrcString.Length()+srcStringPtr;
sl@0: 	TUint8* destStringPtr=(TUint8*)rDestString.Ptr();
sl@0: 	TUint8* destStringPtrBase=destStringPtr;
sl@0: 
sl@0: 	TInt maskShift=maskShiftStored;
sl@0: 	TInt shiftStorage=shiftStored;
sl@0: 	
sl@0: 	// Main character process loop
sl@0: 	while(srcStringPtr<srcStringEnd)	
sl@0: 		{
sl@0: 		offsetChar=(TInt8)(*srcStringPtr-KImcvLookUpStartOffset);
sl@0: 		srcStringPtr++;
sl@0: 
sl@0: 		// Check for valid B64 character		
sl@0: 		if((offsetChar>=0)&&(offsetChar<80))
sl@0: 			{
sl@0: 			// Read in next character and B64 decode
sl@0: 			decodedInt=AsciiToBase64[offsetChar];
sl@0: 
sl@0: 			// Exits when a PAD char is reached
sl@0: 			if(decodedInt==EPadChar)
sl@0: 				{
sl@0: 				rDestString.SetLength((TInt)(destStringPtr-destStringPtrBase));
sl@0: 				return EFalse;
sl@0: 				}
sl@0: 
sl@0: 			// Ensures the first 2 chars of 4 are received before processing
sl@0: 			if(maskShift==ESix)
sl@0: 				maskShift=EFour;
sl@0: 			else
sl@0: 				{
sl@0: 				shiftStorage=shiftStorage<<ESix;
sl@0: 				shiftStorage=shiftStorage|decodedInt;
sl@0: 				decodedChar=(TUint8)((shiftStorage>>maskShift)&EEightBitMask);
sl@0: 				
sl@0: 				if((maskShift-=ETwo)<EZero)
sl@0: 					maskShift=ESix; 
sl@0: 				
sl@0: 				*destStringPtr++=decodedChar;
sl@0: 				}
sl@0: 			shiftStorage=decodedInt;
sl@0: 			}
sl@0: 		}
sl@0: 	shiftStored=shiftStorage;
sl@0: 	maskShiftStored=maskShift;
sl@0: 	
sl@0: 	rDestString.SetLength((TInt)(destStringPtr-destStringPtrBase));
sl@0: 	
sl@0: 	return maskShift<ESix;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Encode the string
sl@0: @param aSrcString Source string
sl@0: @param rDestString Destination string
sl@0: @return  1 if aSrcString is not long enough to encode fully
sl@0: @return 0 if the line was encoded OK
sl@0: */
sl@0: EXPORT_C TInt Base64Codec::Encode(const TDesC8& aSrcString, TDes8& rDestString)
sl@0: 	{
sl@0: 	// Clears the destination string
sl@0: 	rDestString.Zero();
sl@0: 	
sl@0: 	// Initialise variables
sl@0: 	const TUint8* srcStringPtr=aSrcString.Ptr();
sl@0: 	const TUint8* srcStringEnd=aSrcString.Length()+srcStringPtr;
sl@0: 	TUint8* destStringPtr=(TUint8*)rDestString.Ptr();
sl@0: 	TUint8* destStringPtrBase=destStringPtr;
sl@0: 
sl@0: 	TInt character=0;
sl@0: 	TUint8 encodedChar=0;
sl@0: 	TInt charStorage=0;
sl@0:  	TInt maskShift=EZero;
sl@0: 	TInt destStringCharNum = 0;
sl@0: 
sl@0: 	while(srcStringPtr<=srcStringEnd)
sl@0: 		{
sl@0: 		// maskShift is used as a char read counter
sl@0: 		if(maskShift==ESix)
sl@0: 			{
sl@0: 			// If the 3rd char read is also the last char then the while loop
sl@0: 			// is broken on the next check.
sl@0: 			if(srcStringPtr==srcStringEnd)
sl@0: 				srcStringPtr++;
sl@0: 			maskShift=EZero;
sl@0: 			character=0;   
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			if(srcStringPtr==srcStringEnd)
sl@0: 				character=0;
sl@0: 			else
sl@0: 				character=*srcStringPtr;
sl@0: 
sl@0: 			srcStringPtr++;
sl@0: 			// Shifts charStorage ready for the next char
sl@0: 			charStorage=charStorage<<8;
sl@0: 			maskShift+=ETwo;
sl@0: 			}
sl@0: 		charStorage=charStorage|character;
sl@0: 		// Shifts the mask to the correct bit location
sl@0: 		// Masks (AND's) the valid bits from charStorage
sl@0: 		// Shifts the valid bits into the low order 8bits
sl@0: 		// Converts to BASE64 char, Casts the result to an unsigned char (which it should be ?....I hope)
sl@0: 		encodedChar=(TUint8)Base64ToAscii[((charStorage>>maskShift)&ESixBitMask)];
sl@0: 
sl@0: 		*destStringPtr++=encodedChar;
sl@0: 		destStringCharNum++;
sl@0: 
sl@0: 		// Add a CRLF every KMaxB64EncodedCharsPerLine characters so as not to exceed the line length
sl@0: 		// limitation specified in RFC 2822.
sl@0: 		if (destStringCharNum == KMaxB64EncodedCharsPerLine)
sl@0: 			{
sl@0: 			destStringCharNum = 0;
sl@0: 			*destStringPtr++ = '\r';
sl@0: 			*destStringPtr++ = '\n';
sl@0: 			}
sl@0: 		}
sl@0: 	
sl@0: 	// Check for not enough chars and pad if required
sl@0: 	if (maskShift==EFour)
sl@0: 		{
sl@0: 		*destStringPtr++=KImcvConvEquals;
sl@0: 		*destStringPtr++=KImcvConvEquals;
sl@0: 		}
sl@0: 	else
sl@0: 		if(maskShift==ESix)
sl@0: 			*destStringPtr++=KImcvConvEquals;	
sl@0: 			
sl@0: 	rDestString.SetLength((TInt)(destStringPtr-destStringPtrBase));
sl@0: 	return ((TInt)(srcStringPtr-srcStringEnd));
sl@0: 	}