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