lowlevellibsandfws/apputils/bsul/src/clientmessage.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "clientmessagecmn.h"
       
    17 
       
    18 using namespace BSUL;
       
    19 
       
    20 /**
       
    21 Base 64 decoding table
       
    22 */
       
    23 const TInt8 AsciiToBase64[80]=
       
    24 	{
       
    25 	 62, -1, -1, -1, 63, 52, 53, 54, 55, 56,
       
    26 	 57, 58, 59, 60, 61, -1, -1, -1, 64, -1,
       
    27 	 -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,
       
    28 	  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
       
    29 	 18, 19, 20, 21, 22, 23, 24, 25, -1, -1,
       
    30 	 -1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
       
    31 	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
       
    32 	 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
       
    33 	};
       
    34 
       
    35 /**
       
    36 Base 64 encoding table
       
    37 */	
       
    38 const TInt8 Base64ToAscii[65]=
       
    39 	{
       
    40 	 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
       
    41 	 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
       
    42 	 85, 86, 87, 88, 89, 90, 97, 98, 99,100,
       
    43 	101,102,103,104,105,106,107,108,109,110,
       
    44 	111,112,113,114,115,116,117,118,119,120,
       
    45 	121,122, 48, 49, 50, 51, 52, 53, 54, 55,
       
    46 	 56, 57, 43, 47, 61 
       
    47 	};
       
    48 	
       
    49 const TInt8 KImcvLookUpStartOffset = 43;
       
    50 const TUint8 KImcvConvEquals = '=';
       
    51 /**
       
    52 The maximum number of US ASCII characters per line that are before the CRLF line
       
    53 terminator when sending emails.  RFC 2822 recommends that each line SHOULD not exceed
       
    54 80 characters including the CRLF terminator, and MUST not exceed 1000.
       
    55 */
       
    56 const TInt KMaxB64EncodedCharsPerLine = 60; // Could be increased to 75 characters for every encoded line if KDecodeLineLength = 675.  60 was chosen to maintain existing behaviour.
       
    57 
       
    58 /**
       
    59 Parameter factory function lookup table.  This is used to instantiate a 
       
    60 CMessageParameterBase derived object based on a TParamType enum value
       
    61 */
       
    62 const TMessageParameterFactoryFn KParameterFactoryFunctions[] = {NULL,
       
    63 															CIntParameter::NewL,
       
    64 															CDes8ReadParameter::NewL,
       
    65 															CDes8Parameter::NewL,
       
    66 															CPckgParameter::NewL,
       
    67 															CDes16ReadParameter::NewL,
       
    68 															CDes16Parameter::NewL,
       
    69 															CPtrParameter::NewL};
       
    70 
       
    71 /**
       
    72 Panic string for client message framework panic
       
    73 */
       
    74 #ifdef _DEBUG
       
    75 _LIT(KPanicCategory,"BSUL::ClientMsg");
       
    76 #endif
       
    77 
       
    78 const TInt KMaxServerNameLength = 32;
       
    79 
       
    80 /**
       
    81 This static function is used to panic the server in case of
       
    82 incorrect use of CMessageParameterBase APIs or a badly formed
       
    83 message schema
       
    84 @param 	aPanic The Panic value
       
    85 */
       
    86 void PanicServer(TInt aPanic)
       
    87 	{
       
    88 	_LIT(KUnknownServer, "Unknown");
       
    89 	TBuf<KMaxServerNameLength> serverName(KUnknownServer);
       
    90 	
       
    91 	//Get the TLS data for this thread
       
    92 	TClientMessageServerData* serverData = static_cast<TClientMessageServerData*>(Dll::Tls());
       
    93 	
       
    94 	if(serverData != NULL)
       
    95 		{
       
    96 		TPtrC8 name(serverData->iServerName);
       
    97 		serverName.Copy(name);
       
    98 		}
       
    99 	
       
   100 	User::Panic(serverName, aPanic);
       
   101 	}
       
   102 
       
   103 /**
       
   104 Static initialisation function for ClientMessage Framework
       
   105 @param 	aServerData The initialisation data for the server using the library
       
   106 @leave Any system wide error code
       
   107 */
       
   108 EXPORT_C void CClientMessage::InitialiseFrameworkL(const TClientMessageServerData& aServerData)
       
   109 	{
       
   110 	__ASSERT_DEBUG(User::StringLength(aServerData.iServerName) <= KMaxServerNameLength, User::Invariant());
       
   111 	Dll::SetTls((TAny*)&aServerData);
       
   112 	}
       
   113 
       
   114 /**
       
   115 Static factory function for CClientMessage class
       
   116 @param 	aMessage The message that this object encapsulates
       
   117 @return Pointer to a fully constructed CClientMessage object.
       
   118 @leave  KErrNotInitialised if the framework has not been initialised by a 
       
   119 		call to InitialiseFrameworkL.
       
   120 */
       
   121 EXPORT_C CClientMessage* CClientMessage::NewL(const RMessage2& aMessage)
       
   122 	{
       
   123 	const TClientMessageServerData* serverData = static_cast<const TClientMessageServerData*>(Dll::Tls());
       
   124 	if(serverData == NULL)
       
   125 		{
       
   126 		User::Leave(KErrNotInitialised);
       
   127 		}
       
   128 	
       
   129 	CClientMessage* self = new(ELeave) CClientMessage(aMessage,*serverData);
       
   130 	CleanupStack::PushL(self);
       
   131 	self->ConstructL();
       
   132 	CleanupStack::Pop(self);
       
   133 
       
   134 	return self;
       
   135 	}
       
   136 
       
   137 
       
   138 /**
       
   139 Second phase constructor of CClientMessage Object
       
   140 Finds the schema for this message and checks the caller against the security
       
   141 policy defined for this message.  Traverses the array of message parameters
       
   142 and instantiates a CMessageParameterBase object for each parameter and adds these
       
   143 to its internal array.
       
   144 @leave  KErrInvalidFunction If the message function is not found in the message table
       
   145 @leave  KErrBadHandle if the message handle is Null
       
   146 @leave KErrPermissionDenied if the security policy for this message is not satisfied
       
   147 */
       
   148 void CClientMessage::ConstructL()
       
   149 	{
       
   150 	if(!iMessage.IsNull())
       
   151 		{
       
   152 		
       
   153 		//Find the message schema for this message.
       
   154 		const TClientMessageSchema* messageSchema = FindMessageSchema();
       
   155 		
       
   156 		if(!messageSchema)
       
   157 			{
       
   158 			LogBadMessageL(KErrInvalidFunction);
       
   159 			User::Leave(KErrInvalidFunction);
       
   160 			}
       
   161 				
       
   162 		//Check message against security policy
       
   163 		CheckSecurityPolicyL(messageSchema->iPolicy);
       
   164 				
       
   165 		//iterate through message parameters and instantiate all parameter objects
       
   166 		for(int index = 0;index < messageSchema->iParamCount;index++)
       
   167 			{	
       
   168 			CMessageParameterBase* parameter = 
       
   169 					CMessageParameterBase::CreateL(messageSchema->iParams[index], index, iMessage);		
       
   170 			
       
   171 			//Some parameter types are defined to be ignored.  These
       
   172 			//should not be added to the list of parameters
       
   173 			if(parameter != NULL)
       
   174 				{
       
   175 				//AppendL can leave so use cleanupstack to ensure that memory is not
       
   176 				//leaked if AppendL leaves.
       
   177 				CleanupStack::PushL(parameter);
       
   178 				iParameters.AppendL(parameter);
       
   179 				CleanupStack::Pop(parameter);
       
   180 				}
       
   181 			}
       
   182 		}
       
   183 	else
       
   184 		{
       
   185 		LogBadMessageL(KErrBadHandle);
       
   186 		User::Leave(KErrBadHandle);
       
   187 		}
       
   188 	}
       
   189 
       
   190 /**
       
   191 Constructor for CClientMessage Object
       
   192 @param aMessage The RMessage2 to be represented by this object
       
   193 @param aServerData The Initialisation data for the server creating this object
       
   194 */
       
   195 EXPORT_C CClientMessage::CClientMessage(const RMessage2& aMessage, 
       
   196 						const TClientMessageServerData& aServerData) 
       
   197 		: iParameters(KMaxParameters), iMessage(aMessage),
       
   198 		iServerData(aServerData),iFlags(aServerData.iFlags & 0xFFFF0000)
       
   199 
       
   200 	{	
       
   201 	
       
   202 	}
       
   203 
       
   204 /**
       
   205 Destructor for CClientMessageObject
       
   206 */
       
   207 EXPORT_C CClientMessage::~CClientMessage()
       
   208 	{
       
   209 	for(int i = 0; i < iParameters.Count();i++)
       
   210 		{
       
   211 		delete iParameters[i];
       
   212 		}
       
   213 	iParameters.Reset();
       
   214 	}
       
   215 
       
   216 EXPORT_C const RMessage2& CClientMessage::Message()
       
   217 	{
       
   218 	return iMessage;
       
   219 	}
       
   220 
       
   221 /**
       
   222 Panics the client through the message object
       
   223 set an internal flag to indicate that the RMessage reference handle is now NULL
       
   224 due to the client thread being tidied up.
       
   225 @param 	aServer The Panic category
       
   226 @param 	aPanic The Panic value
       
   227 */
       
   228 EXPORT_C void CClientMessage::PanicClient(const TDesC& aServer, TInt aPanic)
       
   229 	{
       
   230 	iMessage.Panic(aServer, aPanic);
       
   231 	iFlags.Set(EFlagPanicClient);
       
   232 	}
       
   233 
       
   234 /**
       
   235 Checks a message against the security policy defined for the server
       
   236 @param aPolicy The security policy to check this message against
       
   237 @leave	KErrPermissionDenied if the message does not fulfil the security policy
       
   238 */
       
   239 void CClientMessage::CheckSecurityPolicyL(const TSecurityPolicy& aPolicy)
       
   240 	{
       
   241 	if(!(aPolicy.CheckPolicy(iMessage,
       
   242 				"Client failed security policy check for this server")))
       
   243 		{
       
   244 		User::Leave(KErrPermissionDenied);
       
   245 		}
       
   246 	return;
       
   247 	}
       
   248 	
       
   249 /**
       
   250 Finds a message schema in the message table for this server.
       
   251 Does a binary search on the function number to pull the correct
       
   252 message from the table.  Note that this assumes that the table
       
   253 is sorted.
       
   254 @return	A pointer to a TClientMessageSchema object in the message table, or Null if 
       
   255 		the message does not correpsond to a message in the message table
       
   256 */
       
   257 const TClientMessageSchema* CClientMessage::FindMessageSchema()
       
   258 	{
       
   259 	//This should always be less than KNumClientMessages 
       
   260 	TInt function = iMessage.Function();
       
   261 	TInt beg = 0;
       
   262 	TInt end = iServerData.iMessageCount - 1;
       
   263 	TInt mid = 0;
       
   264 	TInt midFn = 0;
       
   265 	
       
   266 	while(beg <= end)
       
   267 		{
       
   268 		mid = (end + beg)/2;
       
   269 		
       
   270 		midFn = iServerData.iMessageSchema[mid].iFunction;
       
   271 		if(midFn > function)
       
   272 			{
       
   273 			end = mid - 1;
       
   274 			}	
       
   275 		else if(midFn < function)
       
   276 			{
       
   277 			beg = mid + 1;
       
   278 			}	
       
   279 		else
       
   280 			{
       
   281 			return &iServerData.iMessageSchema[mid];
       
   282 			}
       
   283 		}
       
   284 	return NULL;
       
   285 	}
       
   286 
       
   287 
       
   288 
       
   289 
       
   290 /**
       
   291 Validates the message parameters against the constraints provided 
       
   292 in the message table
       
   293 @leave	KErrBadMessage if the message fails validation against the criteria supplied in the 
       
   294 		message table
       
   295 @leave	Any system-wide error code
       
   296 */
       
   297 EXPORT_C void CClientMessage::ValidateL()
       
   298 	{
       
   299 	
       
   300 	for(int i = 0; i < iParameters.Count();i++)
       
   301 		{
       
   302 		iParameters[i]->ValidateL();
       
   303 		iFlags.Set(i);
       
   304 		}
       
   305 	}
       
   306 
       
   307 /**
       
   308 Validates a single message argument against the constraints provided 
       
   309 in the message table
       
   310 @param aParam The index value identifying the argument to validate
       
   311 @leave	KErrBadMessage if the message fails validation against the criteria supplied in the 
       
   312 		message table for the requested argument
       
   313 @leave	KErrArgument if aParam is negative or is greater than the number of parameters for
       
   314 		this message
       
   315 @leave	Any system-wide error code
       
   316 */
       
   317 EXPORT_C void CClientMessage::ValidateL(TInt aParam)
       
   318 	{
       
   319 	
       
   320 	if(( aParam >= 0) && (aParam < iParameters.Count()))
       
   321 		{	
       
   322 		iParameters[aParam]->ValidateL();
       
   323 		iFlags.Set(aParam);
       
   324 		}
       
   325 	else
       
   326 		{
       
   327 		User::Leave(KErrArgument);
       
   328 		}
       
   329 	}
       
   330 
       
   331 /**
       
   332 Checks if a given parameter has been validated
       
   333 @param aParam The index value identifying the paramater to check
       
   334 @leave	KErrArgument if aParam is not a valid parameter value
       
   335 @leave	KErrNotValidated if the parameter has not been validated
       
   336 */
       
   337 void CClientMessage::CheckValidatedL(TInt aParam)
       
   338 	{
       
   339 	if((aParam < EFlagParam0Validated) || (aParam > EFlagParam3Validated))
       
   340 		{
       
   341 		User::Leave(KErrArgument);
       
   342 		}
       
   343 	
       
   344 	if(!iFlags.IsSet(aParam))
       
   345 		{
       
   346 		User::Leave(KErrNotValidated);
       
   347 		}
       
   348 	}
       
   349 
       
   350 
       
   351 /**
       
   352 Checks if a bad messages should be logged
       
   353 @return True if bad messages should be logged
       
   354 */
       
   355 TBool CClientMessage::LogBadMessages()
       
   356 	{
       
   357 	return iFlags.IsSet(EFlagLogBadMessages);
       
   358 	}
       
   359 
       
   360 /**
       
   361 Checks if a bad messages should be logged
       
   362 @param aError The error code to log
       
   363 */
       
   364 void CClientMessage::LogBadMessageL(TInt aError)
       
   365 	{
       
   366 	//Check if logging of bad messages is enabled
       
   367 	if(LogBadMessages())
       
   368 		{
       
   369 
       
   370 		TUid sid = TUid(iMessage.SecureId());
       
   371 		TUidName clientSid = sid.Name();
       
   372 		
       
   373 		TInt function = Function();
       
   374 		
       
   375 		TBuf<KMaxServerNameLength> serverName;
       
   376 		TPtrC8 name(iServerData.iServerName);
       
   377 		serverName.Copy(name);
       
   378 		
       
   379 		switch(aError)
       
   380 			{			
       
   381 	#ifdef _DEBUG	
       
   382 	
       
   383 				
       
   384 			case KErrInvalidFunction:
       
   385 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Unknown function request from client %S.\n"),
       
   386 								&serverName,aError,function, &clientSid);
       
   387 				break;
       
   388 				
       
   389 			case KErrBadParameter:
       
   390 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Bad argument in IPC request from client %S.\n"),
       
   391 								&serverName,aError,function, &clientSid);
       
   392 				break;
       
   393 				
       
   394 			case KErrBadMessageSchema:
       
   395 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Message schema incotrectly defined for this function %S.\n"),
       
   396 								&serverName,aError,function, &clientSid);
       
   397 				break;
       
   398 				
       
   399 			case KErrBadDescriptor:
       
   400 			case KErrOverflow:
       
   401 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Bad descriptor argument in IPC request from client %S.\n"),
       
   402 								&serverName,aError,function, &clientSid);
       
   403 				break;
       
   404 				
       
   405 			case KErrNotValidated:
       
   406 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Message parameter not validated before use %S.\n"),
       
   407 								&serverName,aError,function, &clientSid);
       
   408 				break;
       
   409 				
       
   410 			default:
       
   411 				RDebug::Print(_L("%S - CClientMessage Error: %d, Function %d. Bad message received from client %S.\n"),
       
   412 										&serverName,aError,function, &clientSid);
       
   413 			break;
       
   414 	#else	
       
   415 			default:
       
   416 				break;
       
   417 	#endif
       
   418 			}
       
   419 		}
       
   420 	
       
   421 
       
   422 	}
       
   423 
       
   424 /**
       
   425 Completes the message request or Panics the client if a
       
   426 message error has occured.
       
   427 @param aError The error value to complete the message with
       
   428 */
       
   429 EXPORT_C void CClientMessage::CompleteRequestL(TInt aError)
       
   430 	{
       
   431 	//If server panics client 
       
   432 	//then iMessage will be NULL
       
   433 	if(!iFlags.IsSet(EFlagPanicClient))
       
   434 		{
       
   435 		if(aError != KErrNone)
       
   436 			{
       
   437 			LogBadMessageL(aError);
       
   438 			}
       
   439 		
       
   440 		switch(aError)
       
   441 			{
       
   442 			case KErrInvalidFunction:
       
   443 			case KErrBadDescriptor:
       
   444 			case KErrOverflow:
       
   445 				{
       
   446 				//Check if Panic is disabled
       
   447 				if( iFlags.IsClear(EFlagDoNotPanicClientOnBadMessageErrors) )
       
   448 					{
       
   449 					TBuf<KMaxServerNameLength> serverName;
       
   450 					TPtrC8 name(iServerData.iServerName);
       
   451 					serverName.Copy(name);
       
   452 					PanicClient(serverName, aError);
       
   453 					break;
       
   454 					}
       
   455 				}
       
   456 			default:
       
   457 				{	
       
   458 				iMessage.Complete(aError);
       
   459 				break;
       
   460 				}
       
   461 			}//switch
       
   462 			
       
   463 		}//if
       
   464 	}
       
   465 
       
   466 /**
       
   467 Gets the function number of this message
       
   468 @return The function number of this message
       
   469 */
       
   470 EXPORT_C TInt CClientMessage::Function()
       
   471 	{
       
   472 	return iMessage.Function();
       
   473 	}
       
   474 
       
   475 /**
       
   476 Gets the requested message argument as an integer value
       
   477 @param aParam The parameter number to retrieve
       
   478 @return The Int value for the requested parameter
       
   479 @leave	KErrNotValidated if the message parameter has not been validated
       
   480 		KErrWrongParameterType in UREL is the parameter requested is not an integer type
       
   481 		Any other system wide error code
       
   482 @panic ECMPanicWrongParameterType If this function is called for a parameter 
       
   483 type that is not CIntParameter.
       
   484 */
       
   485 EXPORT_C TInt CClientMessage::GetIntL(TInt aParam)
       
   486 	{	
       
   487 	CheckValidatedL(aParam);
       
   488 
       
   489 	return iParameters[aParam]->GetIntL();
       
   490 	}
       
   491 
       
   492 /**
       
   493 Gets the requested message argument as an TAny*
       
   494 @param aParam The parameter number to retrieve
       
   495 @return The TAny* for the requested parameter
       
   496 @leave	KErrNotValidated if the message parameter has not been validated
       
   497 		KErrWrongParameterType in UREL is the parameter requested is not an Ptr type
       
   498 		Any other system wide error code
       
   499 @panic ECMPanicWrongParameterType If this function is called for a parameter 
       
   500 type that is not CPtrParameter.
       
   501 */
       
   502 EXPORT_C const TAny* CClientMessage::GetPtrL(TInt aParam)
       
   503 	{	
       
   504 	CheckValidatedL(aParam);
       
   505 	
       
   506 	return iParameters[aParam]->GetPtrL();
       
   507 	}
       
   508 
       
   509 /**
       
   510 Gets a reference to the local copy of the descriptor read from the message
       
   511 @param aParam The parameter number of the descriptor to retrieve
       
   512 @leave	KErrNotValidated if the message parameter has not been validated
       
   513 		KErrWrongParameterType in UREL is the parameter requested is not a readable
       
   514 		TDes8 type
       
   515 		Any other system wide error code
       
   516 @panic ECMPanicWrongParameterType If this function is called for a parameter 
       
   517 type that is not CDes8ReadParameter.
       
   518 */
       
   519 EXPORT_C const TDesC8& CClientMessage::GetDes8L(TInt aParam)
       
   520 	{
       
   521 	CheckValidatedL(aParam);
       
   522 	
       
   523 	return iParameters[aParam]->GetDes8L();
       
   524 	}
       
   525 
       
   526 /**
       
   527 Gets a reference to the local copy of the descriptor read from the message
       
   528 @param aParam The parameter number of the descriptor to retrieve
       
   529 @leave	KErrNotValidated if the message parameter has not been validated
       
   530 		KErrWrongParameterType in UREL is the parameter requested is not a readable
       
   531 		TDes16 type
       
   532 		Any other system wide error code
       
   533 @panic ECMPanicWrongParameterType If this function is called for a parameter 
       
   534 type that is not CDes16ReadParameter.
       
   535 */
       
   536 EXPORT_C const TDesC& CClientMessage::GetDes16L(TInt aParam)
       
   537 	{
       
   538 	CheckValidatedL(aParam);
       
   539 	
       
   540 	return iParameters[aParam]->GetDes16L();
       
   541 	}
       
   542 
       
   543 
       
   544 
       
   545 /**
       
   546 Gets a descriptor value read from the message
       
   547 @param aParam The parameter number of the descriptor to retrieve
       
   548 @param aDes On exit contains the descriptor value requested
       
   549 @param aOffset The desired offset from which to read the descriptor
       
   550 @leave	KErrNotValidated if the message parameter has not been validated
       
   551 		KErrWrongParameterType in UREL is the parameter requested is not a readable
       
   552 		TDes8 type
       
   553 		Any other system wide error code
       
   554 @panic ECMPanicWrongParameterType If this function is called for a parameter 
       
   555 type that is not CDes8Parameter or CDes8ReadParameter.
       
   556 */
       
   557 EXPORT_C void CClientMessage::ReadL(TInt aParam, TDes8& aDes, TInt aOffset)
       
   558 	{
       
   559 	CheckValidatedL(aParam);
       
   560 
       
   561 	iParameters[aParam]->ReadL(aDes, aOffset);
       
   562 	}
       
   563 
       
   564 /**
       
   565 Gets a descriptor value read from the message
       
   566 @param aParam The parameter number of the descriptor to retrieve
       
   567 @param aDes On exit contains the descriptor value requested
       
   568 @param aOffset The desired offset from which to read the descriptor
       
   569 @leave	KErrNotValidated if the message parameter has not been validated
       
   570 		KErrWrongParameterType in UREL is the parameter requested is not a readable 
       
   571 		TDes16 type
       
   572 		Any other system wide error code
       
   573 @panic ECMPanicWrongParameterType If this function is called for a parameter 
       
   574 type that is not CDes16Parameter or CDes16ReadParameter.
       
   575 */
       
   576 EXPORT_C void CClientMessage::ReadL(TInt aParam, TDes16& aDes, TInt aOffset)
       
   577 	{
       
   578 	CheckValidatedL(aParam);
       
   579 	
       
   580 	iParameters[aParam]->ReadL(aDes, aOffset);
       
   581 	}
       
   582 
       
   583 /**
       
   584 Writes to a descriptor field in the message
       
   585 @param aParam The parameter number of the descriptor to write
       
   586 @param aDes The descriptor to write to the message
       
   587 @param aOffset The desired offset at which to write the descriptor
       
   588 @leave	KErrNotValidated if the message parameter has not been validated
       
   589 		KErrWrongParameterType in UREL is the parameter requested is not a writable 
       
   590 		TDes8 type
       
   591 		Any other system wide error code
       
   592 @panic ECMPanicWrongParameterType If this function is called for a parameter 
       
   593 type that is not CDes8Parameter
       
   594 */
       
   595 EXPORT_C void CClientMessage::WriteL(TInt aParam, const TDesC8& aDes, TInt aOffset)
       
   596 	{
       
   597 	CheckValidatedL(aParam);
       
   598 	
       
   599 	iParameters[aParam]->WriteL(aDes, aOffset);
       
   600 	}
       
   601 
       
   602 /**
       
   603 Writes to a descriptor field in the message
       
   604 @param aParam The parameter number of the descriptor to write
       
   605 @param aDes The descriptor to write to the message
       
   606 @param aOffset The desired offset at which to write the descriptor
       
   607 @leave	KErrNotValidated if the message parameter has not been validated
       
   608 		KErrWrongParameterType in UREL is the parameter requested is not a writable 
       
   609 		TDes16 type
       
   610 		Any other system wide error code
       
   611 @panic ECMPanicWrongParameterType If this function is called for a parameter 
       
   612 type that is notCDes16Parameter
       
   613 */
       
   614 EXPORT_C void CClientMessage::WriteL(TInt aParam, const TDesC16& aDes, TInt aOffset)
       
   615 	{	
       
   616 	CheckValidatedL(aParam);
       
   617 	
       
   618 	iParameters[aParam]->WriteL(aDes, aOffset);
       
   619 	}
       
   620 
       
   621 /**
       
   622 Gets the length of the requested descriptor message argument
       
   623 @param aParam The parameter number to retrieve
       
   624 @return The Length of the descriptor in the client process
       
   625 @leave	KErrNotValidated if the message parameter has not been validated
       
   626 		KErrWrongParameterType in UREL is the parameter requested is not a descriptor type
       
   627 		Any other system wide error code
       
   628 @panic ECMPanicWrongParameterType If this function is called for a parameter 
       
   629 type that is not a descriptor type.
       
   630 */
       
   631 EXPORT_C TInt CClientMessage::GetDesLengthL(TInt aParam)
       
   632 	{
       
   633 	CheckValidatedL(aParam);
       
   634 	
       
   635 	return iParameters[aParam]->GetDesLengthL();
       
   636 	}
       
   637 
       
   638 /**
       
   639 Gets the max length of the requested descriptor message argument
       
   640 @param aParam The parameter number to retrieve
       
   641 @return The Max length of the descriptor in the client process
       
   642 @leave	KErrNotValidated if the message parameter has not been validated
       
   643 		KErrWrongParameterType in UREL is the parameter requested is not a descriptor type
       
   644 		Any other system wide error code
       
   645 @panic ECMPanicWrongParameterType If this function is called for a parameter type 
       
   646 that is not a descriptor type.
       
   647 */
       
   648 EXPORT_C TInt CClientMessage::GetDesMaxLengthL(TInt aParam)
       
   649 	{
       
   650 	CheckValidatedL(aParam);
       
   651 	
       
   652 	return iParameters[aParam]->GetDesMaxLengthL();
       
   653 	}
       
   654 
       
   655 /********************************************************************************
       
   656  * 			CMessageParameterBase and Derived Class Definitions
       
   657  *******************************************************************************/
       
   658 
       
   659 
       
   660 /**
       
   661 Factory function for instantiating derived Parameter classes.
       
   662 Uses factory lookup table to instantiate approptiate parameter 
       
   663 object based on parameter details passed in
       
   664 @param aParam Parameter details object used to instantiate an appropriate
       
   665 			implementation of CMessageParameterBase.
       
   666 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
   667 @param aMessage The RMessage2 object containing the parameter represented by 
       
   668 			this object
       
   669 @return A fully constructed CMessageParameterBase derived object deterimined by 
       
   670 		aParam.
       
   671 @leave	KErrBadMessageSchema in UREL if if the schema for this parameter is 
       
   672 		incorrectly defined
       
   673 @leave	Any system-wide error code.
       
   674 @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
       
   675 		incorrectly defined
       
   676 */
       
   677 CMessageParameterBase* CMessageParameterBase::CreateL(const TParameterDetails& aParam, 
       
   678 			TInt aParamIndex, const RMessage2& aMessage)
       
   679 	{
       
   680 	
       
   681 	//The parameter type is the bottom 16 bits of the param type
       
   682 	TInt paramType = (aParam.iType & KParamTypeMask);
       
   683 	
       
   684 	__ASSERT_DEBUG((paramType > 0), PanicServer(ECMPanicBadMessageSchema));
       
   685 	
       
   686 	CMessageParameterBase* newParam = NULL;
       
   687 	
       
   688 	switch(paramType)
       
   689 		{
       
   690 		case EParamInt:
       
   691 		case EParamDes8Read:
       
   692 		case EParamDes8:
       
   693 		case EParamDes16Read:
       
   694 		case EParamDes16:
       
   695 		case EParamPtr:
       
   696 		case EParamPckg:
       
   697 			{	
       
   698 			//Create the new parameter object
       
   699 			newParam = (KParameterFactoryFunctions[paramType])(aParam, aParamIndex, 
       
   700 							aMessage, GetValidationFunctionL(aParam));
       
   701 			break;
       
   702 			}
       
   703 			
       
   704 		default:
       
   705 			{
       
   706 #ifdef _DEBUG
       
   707 			PanicServer(ECMPanicBadMessageSchema);
       
   708 #else
       
   709 			User::Leave(KErrBadMessageSchema);
       
   710 #endif
       
   711 			}
       
   712 	}
       
   713 
       
   714 	return newParam;
       
   715 	}
       
   716 
       
   717 /**
       
   718 Constructor for CMessageParameterBase object
       
   719 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
   720 @param aMessage The RMessage2 object containing the parameter represented by 
       
   721 			this object
       
   722 */
       
   723 CMessageParameterBase::CMessageParameterBase(const TParameterDetails& aParam, 
       
   724 		TInt aParamIndex,const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
   725 	: iIndex(aParamIndex), iMessage(aMessage), iParamDetails(aParam), iValidationFn(aValidationFn)
       
   726 	{
       
   727 
       
   728 	}
       
   729 
       
   730 /**
       
   731 Gets the validation function for this parameter from the 
       
   732 TClientMessageServerData structure
       
   733 @param aParam Parameter object used to find the validation function
       
   734 @return The validation function for this parameter type
       
   735 @leave	KErrBadMessageSchema in UREL if if the schema for this parameter is 
       
   736 		incorrectly defined
       
   737 @leave	Any other system wide error code
       
   738 @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
       
   739 		incorrectly defined
       
   740 */
       
   741 TCustomValidationFn CMessageParameterBase::GetValidationFunctionL(const TParameterDetails& aParam)
       
   742 	{
       
   743 	//Get the TLS data for this thread - this will never be null at this point 
       
   744 	//as it is checked in CClientMessage::NewL
       
   745 	TClientMessageServerData* serverData = static_cast<TClientMessageServerData*>(Dll::Tls());
       
   746 	
       
   747 	//The index of the validation function for this parameter is held in 
       
   748 	//the upper 16 bits of aParam.iType. Mask this out and shift down to 
       
   749 	//get the index.
       
   750 	TInt fnIndex = (aParam.iType & KValidationFnIndexMask) >> KShift16Bit;
       
   751 	
       
   752 	
       
   753 	if(fnIndex >= serverData->iValidationFnCount)
       
   754 		{
       
   755 #ifdef _DEBUG
       
   756 			PanicServer(ECMPanicBadMessageSchema);
       
   757 #else
       
   758 			User::Leave(KErrBadMessageSchema);
       
   759 #endif
       
   760 		}
       
   761 	
       
   762 	//Return the validation function
       
   763 	return serverData->iCustomValidationFns[fnIndex];
       
   764 	}
       
   765 
       
   766 /**
       
   767 Default implementation of GetIntL for CMessageParameterBase object.
       
   768 This is only called if this API is not defined for the given parameter type.
       
   769 @return KErrNone - A Dummy return value
       
   770 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   771 		given parameter type
       
   772 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   773 		given parameter type
       
   774 */
       
   775 TInt CMessageParameterBase::GetIntL()
       
   776 	{
       
   777 #ifdef _DEBUG
       
   778 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   779 #else
       
   780 	User::Leave(KErrWrongParameterType);
       
   781 #endif
       
   782 	return KErrNone;
       
   783 	}
       
   784 
       
   785 /**
       
   786 Default implementation of GetPtrL for CMessageParameterBase object.
       
   787 This is only called if this API is not defined for the given parameter type.
       
   788 @return NULL - A Dummy return value
       
   789 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   790 		given parameter type
       
   791 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   792 		given parameter type
       
   793 */
       
   794 const TAny* CMessageParameterBase::GetPtrL()
       
   795 	{
       
   796 #ifdef _DEBUG
       
   797 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   798 #else
       
   799 	User::Leave(KErrWrongParameterType);
       
   800 #endif
       
   801 	return NULL;
       
   802 	}
       
   803 
       
   804 /**
       
   805 Default implementation of WriteL for CMessageParameterBase object.
       
   806 This is only called if this API is not defined for the given parameter type.
       
   807 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   808 		given parameter type
       
   809 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   810 		given parameter type
       
   811 */
       
   812 void CMessageParameterBase::WriteL(const TDesC8& /*aDes*/, TInt /*aOffset*/)
       
   813 	{
       
   814 #ifdef _DEBUG
       
   815 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   816 #else
       
   817 	User::Leave(KErrWrongParameterType);
       
   818 #endif
       
   819 	}
       
   820 
       
   821 /**
       
   822 Default implementation of WriteL for CMessageParameterBase object.
       
   823 This is only called if this API is not defined for the given parameter type.
       
   824 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   825 		given parameter type
       
   826 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   827 		given parameter type
       
   828 */
       
   829 void CMessageParameterBase::WriteL(const TDesC& /*aDes*/, TInt /*aOffset*/)
       
   830 	{
       
   831 #ifdef _DEBUG
       
   832 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   833 #else
       
   834 	User::Leave(KErrWrongParameterType);
       
   835 #endif
       
   836 	}
       
   837 
       
   838 /**
       
   839 Default implementation of ReadL for CMessageParameterBase object.
       
   840 This is only called if this API is not defined for the given parameter type.
       
   841 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   842 		given parameter type
       
   843 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   844 		given parameter type
       
   845 */
       
   846 void CMessageParameterBase::ReadL(TDes8& /*aDes*/,TInt /*aOffset*/)
       
   847 	{
       
   848 #ifdef _DEBUG
       
   849 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   850 #else
       
   851 	User::Leave(KErrWrongParameterType);
       
   852 #endif
       
   853 	}
       
   854 
       
   855 /**
       
   856 Default implementation of ReadL for CMessageParameterBase object.
       
   857 This is only called if this API is not defined for the given parameter type.
       
   858 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   859 		given parameter type
       
   860 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   861 		given parameter type
       
   862 */
       
   863 void CMessageParameterBase::ReadL(TDes& /*aDes*/, TInt /*aOffset*/)
       
   864 	{
       
   865 #ifdef _DEBUG
       
   866 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   867 #else
       
   868 	User::Leave(KErrWrongParameterType);
       
   869 #endif
       
   870 	}
       
   871 
       
   872 /**
       
   873 Default implementation of GetDesLengthL for CMessageParameterBase object.
       
   874 This is only called if this API is not defined for the given parameter type.
       
   875 @return KErrNone - A Dummy return
       
   876 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   877 		given parameter type
       
   878 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   879 		given parameter type
       
   880 */
       
   881 TInt CMessageParameterBase::GetDesLengthL()
       
   882 	{
       
   883 #ifdef _DEBUG
       
   884 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   885 #else
       
   886 	User::Leave(KErrWrongParameterType);
       
   887 #endif
       
   888 	return KErrNone;
       
   889 	}
       
   890 
       
   891 /**
       
   892 Default implementation of GetDesMaxLengthL for CMessageParameterBase object.
       
   893 This is only called if this API is not defined for the given parameter type.
       
   894 @return KErrNone - A Dummy return
       
   895 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   896 		given parameter type
       
   897 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   898 		given parameter type
       
   899 */
       
   900 TInt CMessageParameterBase::GetDesMaxLengthL()
       
   901 	{
       
   902 #ifdef _DEBUG
       
   903 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   904 #else
       
   905 	User::Leave(KErrWrongParameterType);
       
   906 #endif
       
   907 	return KErrNone;
       
   908 	}
       
   909 
       
   910 /**
       
   911 Default implementation of GetDes8L for CMessageParameterBase object.
       
   912 This is only called if this API is not defined for the given parameter type.
       
   913 @return KErrNone - A Dummy return
       
   914 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   915 		given parameter type
       
   916 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   917 		given parameter type
       
   918 */
       
   919 
       
   920 const TDesC8& CMessageParameterBase::GetDes8L()
       
   921 	{
       
   922 #ifdef _DEBUG
       
   923 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   924 #else
       
   925 	User::Leave(KErrWrongParameterType);
       
   926 #endif	
       
   927 	_LIT8(KDummy,"");
       
   928 	return KDummy;
       
   929 	}
       
   930 
       
   931 /**
       
   932 Default implementation of GetDes16L for CMessageParameterBase object.
       
   933 This is only called if this API is not defined for the given parameter type.
       
   934 @return KErrNone - A Dummy return
       
   935 @leave KErrWrongParameterType in UREL if this function is not defined for the 
       
   936 		given parameter type
       
   937 @panic ECMPanicWrongParameterType in UDEB if this function is not defined for the 
       
   938 		given parameter type
       
   939 */
       
   940 const TDesC& CMessageParameterBase::GetDes16L()
       
   941 	{
       
   942 #ifdef _DEBUG
       
   943 	User::Panic(KPanicCategory,ECMPanicWrongParameterType);
       
   944 #else
       
   945 	User::Leave(KErrWrongParameterType);
       
   946 #endif	
       
   947 	
       
   948 	_LIT(KDummy,"");
       
   949 	return KDummy;
       
   950 	}
       
   951 
       
   952 /**
       
   953 Returns the value of iMin defined in the schema for this parameter
       
   954 @return The Min constraint for this parameter
       
   955 */
       
   956 TInt CMessageParameterBase::Min()
       
   957 	{
       
   958 	return iParamDetails.iMin;
       
   959 	}
       
   960 
       
   961 /**
       
   962 Returns the value of iMax defined in the schema for this parameter
       
   963 @return The max constraint for this parameter
       
   964 */
       
   965 TInt CMessageParameterBase::Max()
       
   966 	{
       
   967 	return iParamDetails.iMax;
       
   968 	}
       
   969 
       
   970 
       
   971 /**
       
   972 Factory function for instantiating CIntParameter objects
       
   973 @param aParam Parameter details object used to construct object.
       
   974 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
   975 @param aMessage The RMessage2 object containing the parameter represented by 
       
   976 @return A fully constructed CIntParameter object.
       
   977 @leave	Any system-wide error code.
       
   978 */
       
   979 CMessageParameterBase* CIntParameter::NewL(const TParameterDetails& aParam, 
       
   980 				TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
   981 	{
       
   982 	CIntParameter* self = new(ELeave) CIntParameter(aParam, aParamIndex, aMessage, aValidationFn);
       
   983 	return self;
       
   984 	}
       
   985 
       
   986 /**
       
   987 Constructor for CIntParameter class.
       
   988 @param aParam Parameter details to be encapsulated by object
       
   989 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
   990 @param aMessage The RMessage2 object containing the parameter to be represented
       
   991 @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
       
   992 		incorrectly defined
       
   993 */
       
   994 CIntParameter::CIntParameter(const TParameterDetails& aParam, TInt aParamIndex,
       
   995 			const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
   996 		: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
       
   997 		
       
   998 	{	
       
   999 	__ASSERT_DEBUG((iParamDetails.iMax >= iParamDetails.iMin), 
       
  1000 			PanicServer(ECMPanicBadMessageSchema));
       
  1001 	}
       
  1002 
       
  1003 /**
       
  1004 Destructor for CIntParameter class.
       
  1005 */
       
  1006 CIntParameter::~CIntParameter()
       
  1007 	{
       
  1008 
       
  1009 	}
       
  1010 
       
  1011 /**
       
  1012 Validates given message parameter agains constraints
       
  1013 represented by this object. Stores the Int value from the message
       
  1014  to allow for simple retrieval when required.
       
  1015 @leave	KErrBadParameter if the message parameter does not conform
       
  1016 		to the constraints represented by this object
       
  1017 @leave	Any system-wide error code
       
  1018 */
       
  1019 void CIntParameter::ValidateL()
       
  1020 	{
       
  1021 	
       
  1022 	switch(iIndex)
       
  1023 		{
       
  1024 	
       
  1025 		case 0:
       
  1026 			iValue = iMessage.Int0();
       
  1027 			break;
       
  1028 		
       
  1029 		case 1:
       
  1030 			iValue = iMessage.Int1();
       
  1031 			break;
       
  1032 		
       
  1033 		case 2:
       
  1034 			iValue = iMessage.Int2();
       
  1035 			break;
       
  1036 			
       
  1037 		case 3:
       
  1038 			iValue = iMessage.Int3();
       
  1039 			break;
       
  1040 		
       
  1041 		default:
       
  1042 			User::Leave(KErrArgument);
       
  1043 			break;
       
  1044 		}
       
  1045 	
       
  1046 	if(iValidationFn != NULL)
       
  1047 		{
       
  1048 		iValidationFn(this);	
       
  1049 		}
       
  1050 	
       
  1051 	else
       
  1052 		{	
       
  1053 		if((iValue < iParamDetails.iMin)||(iValue > iParamDetails.iMax))
       
  1054 			{
       
  1055 			User::Leave(KErrBadParameter);
       
  1056 			}
       
  1057 		}
       
  1058 	}
       
  1059 
       
  1060 /**
       
  1061 Retrieves the TInt value read from the clients message during validation
       
  1062 @return The TInt value read from the client message
       
  1063 */
       
  1064 TInt CIntParameter::GetIntL()
       
  1065 	{
       
  1066 	return iValue;
       
  1067 	}
       
  1068 
       
  1069 /**
       
  1070 Factory function for instantiating CDes8ReadParameter objects
       
  1071 @param aParam Parameter details object used to construct object.
       
  1072 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1073 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1074 @return A fully constructed CDes8ReadParameter object.
       
  1075 @leave	Any system-wide error code.
       
  1076 */
       
  1077 CMessageParameterBase* CDes8ReadParameter::NewL(const TParameterDetails& aParam, 
       
  1078 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1079 	{
       
  1080 	CDes8ReadParameter* self = 
       
  1081 		new(ELeave) CDes8ReadParameter(aParam, aParamIndex, aMessage, aValidationFn);
       
  1082 	
       
  1083 	return self;
       
  1084 	}
       
  1085 
       
  1086 /**
       
  1087 Constructor for CDes8ReadParameter class.
       
  1088 @param aParam Parameter details to be encapsulated by object
       
  1089 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1090 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1091 @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
       
  1092 		incorrectly defined
       
  1093 */
       
  1094 CDes8ReadParameter::CDes8ReadParameter(const TParameterDetails& aParam, TInt aParamIndex,
       
  1095 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1096 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
       
  1097 	{	
       
  1098 	__ASSERT_DEBUG((iParamDetails.iMin >= 0), 
       
  1099 			PanicServer(ECMPanicBadMessageSchema));
       
  1100 	
       
  1101 	__ASSERT_DEBUG((iParamDetails.iMax > 0), 
       
  1102 			PanicServer(ECMPanicBadMessageSchema));
       
  1103 	
       
  1104 	__ASSERT_DEBUG((iParamDetails.iMax >= iParamDetails.iMin), 
       
  1105 			PanicServer(ECMPanicBadMessageSchema));
       
  1106 	}
       
  1107 
       
  1108 /**
       
  1109 Destructor for CDes8ReadParameter class.
       
  1110 */
       
  1111 CDes8ReadParameter::~CDes8ReadParameter()
       
  1112 	{
       
  1113 	delete iValue;
       
  1114 	}
       
  1115 
       
  1116 /**
       
  1117 Validates given message argument against constraints
       
  1118 represented by this object. Reads in the descriptor from the 
       
  1119 clients message to enable simple retrival when required.
       
  1120 @leave	KErrBadDescriptor if the message parameter does not conform
       
  1121 		to the constraints represented by this object
       
  1122 @leave	Any system-wide error code
       
  1123 */
       
  1124 void CDes8ReadParameter::ValidateL()
       
  1125 	{
       
  1126 	TInt length = iMessage.GetDesLengthL(iIndex);
       
  1127 	
       
  1128 	//if there is a supplied custom validation function, call that now
       
  1129 	if(iValidationFn != NULL)
       
  1130 		{
       
  1131 		iValidationFn(this);
       
  1132 		}
       
  1133 	
       
  1134 	else
       
  1135 		{		
       
  1136 		if((length < iParamDetails.iMin) || (length > iParamDetails.iMax))
       
  1137 			{
       
  1138 			User::Leave(KErrBadDescriptor);
       
  1139 			}
       
  1140 		}
       
  1141 	
       
  1142 	iValue = HBufC8::NewL(length);
       
  1143 	TPtr8 ptr = iValue->Des();
       
  1144 	ReadL(ptr,0);
       
  1145 	}
       
  1146 
       
  1147 /**
       
  1148 Gets the descriptor read from the clients message during validation
       
  1149 @return	const reference to the local descriptor copy
       
  1150 */
       
  1151 const TDesC8& CDes8ReadParameter::GetDes8L()
       
  1152 	{
       
  1153 	return *iValue;
       
  1154 	}
       
  1155 
       
  1156 /**
       
  1157 Gets the length of the descriptor in the client message
       
  1158 @return	The length of the descriptor
       
  1159 @leave	KErrBadDescriptor if the message argument is not a descriptor type
       
  1160 		Any other system wide error code
       
  1161 */
       
  1162 TInt CDes8ReadParameter::GetDesLengthL()
       
  1163 	{
       
  1164 	return iMessage.GetDesLengthL(iIndex);
       
  1165 	}
       
  1166 
       
  1167 /**
       
  1168 Retrieves the descriptor value read from the clients 
       
  1169 message during validation
       
  1170 @param aDes The target descriptor.
       
  1171 @param aOffset The offset from the start of the clients descriptor
       
  1172 @leave KErrArgument if iIndex has a value outside the valid range, or if aOffset is negative.
       
  1173 @panic ECMPanicBadDescriptor in UDEB if the supplied descriptor is too small. 
       
  1174 if the schema for this parameter is incorrectly defined
       
  1175 */
       
  1176 void CDes8ReadParameter::ReadL(TDes8& aDes, TInt aOffset)
       
  1177 	{
       
  1178 	__ASSERT_DEBUG((aDes.MaxLength() >= (iMessage.GetDesLengthL(iIndex) - aOffset)), 
       
  1179 			PanicServer(ECMPanicBadDescriptor));
       
  1180 	
       
  1181 	iMessage.ReadL(iIndex,aDes,aOffset);
       
  1182 	}
       
  1183 
       
  1184 /**
       
  1185 Factory function for instantiating CDes8WriteParameter objects
       
  1186 @param aParam Parameter details object used to construct object.
       
  1187 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1188 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1189 @return A fully constructed CDes8WriteParameter object.
       
  1190 @leave	Any system-wide error code.
       
  1191 */
       
  1192 CMessageParameterBase* CDes8Parameter::NewL(const TParameterDetails& aParam, 
       
  1193 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1194 	{
       
  1195 	CDes8Parameter* self = 
       
  1196 		new(ELeave) CDes8Parameter(aParam, aParamIndex, aMessage, aValidationFn);
       
  1197 	
       
  1198 	return self;
       
  1199 	}
       
  1200 
       
  1201 /**
       
  1202 Constructor for CDes8WriteParameter class.
       
  1203 @param aParam Parameter details to be encapsulated by object
       
  1204 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1205 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1206 @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
       
  1207 		incorrectly defined
       
  1208 */
       
  1209 CDes8Parameter::CDes8Parameter(const TParameterDetails& aParam, TInt aParamIndex,
       
  1210 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1211 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
       
  1212 		
       
  1213 	{
       
  1214 	__ASSERT_DEBUG((iParamDetails.iMin >= 0), 
       
  1215 			PanicServer(ECMPanicBadMessageSchema));
       
  1216 	
       
  1217 	__ASSERT_DEBUG((iParamDetails.iMax >= 0), 
       
  1218 			PanicServer(ECMPanicBadMessageSchema));
       
  1219 	}
       
  1220 
       
  1221 /**
       
  1222 Destructor for CDes8WriteParameter class.
       
  1223 */
       
  1224 CDes8Parameter::~CDes8Parameter()
       
  1225 	{
       
  1226 	}
       
  1227 
       
  1228 /**
       
  1229 Validates given message argument against constraints
       
  1230 represented by this object.
       
  1231 @leave	KErrBadDescriptor if the message parameter does not conform
       
  1232 		to the constraints represented by this object
       
  1233 @leave	Any system-wide error code
       
  1234 */
       
  1235 void CDes8Parameter::ValidateL()
       
  1236 	{
       
  1237 	
       
  1238 	//if there is a supplied custom validation function, call that now
       
  1239 	if(iValidationFn != NULL)
       
  1240 		{
       
  1241 		iValidationFn(this);
       
  1242 		}
       
  1243 	
       
  1244 	else
       
  1245 		{
       
  1246 		TInt length = iMessage.GetDesLengthL(iIndex);
       
  1247 		TInt maxLength = iMessage.GetDesMaxLengthL(iIndex);
       
  1248 		
       
  1249 		if((maxLength < iParamDetails.iMin)||(length > iParamDetails.iMax))
       
  1250 			{
       
  1251 			User::Leave(KErrBadDescriptor);
       
  1252 			}
       
  1253 		}
       
  1254 	}
       
  1255 
       
  1256 /**
       
  1257 Gets the length of the descriptor in the client message
       
  1258 @return	The length of the descriptor
       
  1259 @leave	KErrBadDescriptor if the message argument is not a descriptor type
       
  1260 		Any other system wide error code
       
  1261 */
       
  1262 TInt CDes8Parameter::GetDesLengthL()
       
  1263 	{
       
  1264 	return iMessage.GetDesLengthL(iIndex);
       
  1265 	}
       
  1266 
       
  1267 /**
       
  1268 Gets the max length of the descriptor in the client message
       
  1269 @return	The max length of the descriptor
       
  1270 @leave	KErrBadDescriptor if the message argument is not a descriptor type
       
  1271 		Any other system wide error code
       
  1272 */
       
  1273 TInt CDes8Parameter::GetDesMaxLengthL()
       
  1274 	{
       
  1275 	return iMessage.GetDesMaxLengthL(iIndex);
       
  1276 	}
       
  1277 
       
  1278 
       
  1279 /**
       
  1280 Reads a descriptor from the requested message argument
       
  1281 @param aDes The target descriptor.
       
  1282 @param aOffset The offset from the start of the clients descriptor
       
  1283 @leave	Any system wide error code.
       
  1284 @panic ECMPanicBadDescriptor in UDEB if the supplied descriptor is too small. 
       
  1285 */
       
  1286 void CDes8Parameter::ReadL(TDes8& aDes, TInt aOffset)
       
  1287 	{
       
  1288 	__ASSERT_DEBUG((aDes.MaxLength() >= (iMessage.GetDesLengthL(iIndex) - aOffset)), 
       
  1289 			PanicServer(ECMPanicBadDescriptor));
       
  1290 	
       
  1291 	iMessage.ReadL(iIndex,aDes,aOffset);
       
  1292 	}
       
  1293 
       
  1294 /**
       
  1295 Validates and writes a descriptor to the requested 
       
  1296 message argument
       
  1297 @param aDes The source descriptor containing the data to be written.
       
  1298 @param aOffset The offset from the start of the clients descriptor
       
  1299 @leave	   Any system wide error code.
       
  1300 */
       
  1301 void CDes8Parameter::WriteL(const TDesC8& aDes, TInt aOffset)
       
  1302 	{
       
  1303 	iMessage.WriteL(iIndex,aDes,aOffset);
       
  1304 	}
       
  1305 
       
  1306 /**
       
  1307 Factory function for instantiating CIntParameter objects
       
  1308 @param aParam Parameter details object used to construct object.
       
  1309 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1310 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1311 @return A fully constructed CIntParameter object.
       
  1312 @leave	Any system-wide error code.
       
  1313 */
       
  1314 CMessageParameterBase* CDes16ReadParameter::NewL(const TParameterDetails& aParam, 
       
  1315 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1316 	{
       
  1317 	CDes16ReadParameter* self = 
       
  1318 		new(ELeave) CDes16ReadParameter(aParam, aParamIndex, aMessage, aValidationFn);
       
  1319 	
       
  1320 	return self;
       
  1321 	}
       
  1322 
       
  1323 /**
       
  1324 Constructor for CDes8ReadParameter class.
       
  1325 @param aParam Parameter details to be encapsulated by object
       
  1326 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1327 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1328 @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
       
  1329 		incorrectly defined
       
  1330 */
       
  1331 CDes16ReadParameter::CDes16ReadParameter(const TParameterDetails& aParam, TInt aParamIndex,
       
  1332 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1333 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
       
  1334 	{
       
  1335 	__ASSERT_DEBUG((iParamDetails.iMin >= 0), 
       
  1336 			PanicServer(ECMPanicBadMessageSchema));
       
  1337 	
       
  1338 	__ASSERT_DEBUG((iParamDetails.iMax > 0), 
       
  1339 			PanicServer(ECMPanicBadMessageSchema));
       
  1340 	
       
  1341 	__ASSERT_DEBUG((iParamDetails.iMax >= iParamDetails.iMin), 
       
  1342 			PanicServer(ECMPanicBadMessageSchema));
       
  1343 	}
       
  1344 
       
  1345 /**
       
  1346 Destructor for CDes16ReadParameter class.
       
  1347 */
       
  1348 CDes16ReadParameter::~CDes16ReadParameter()
       
  1349 	{
       
  1350 	delete iValue;
       
  1351 	}
       
  1352 
       
  1353 /**
       
  1354 Validates given message argument against constraints
       
  1355 represented by this object. Reads in the descriptor from the 
       
  1356 clients message to enable simple retrival when required.
       
  1357 @leave	KErrBadDescriptor if the message parameter does not conform
       
  1358 		to the constraints represented by this object
       
  1359 @leave	Any system-wide error code
       
  1360 */
       
  1361 void CDes16ReadParameter::ValidateL()
       
  1362 	{
       
  1363 	TInt length = iMessage.GetDesLengthL(iIndex);
       
  1364 	
       
  1365 	//if there is a supplied custom validation function, call that now
       
  1366 	if(iValidationFn != NULL)
       
  1367 		{
       
  1368 		iValidationFn(this);
       
  1369 		}
       
  1370 	
       
  1371 	else
       
  1372 		{		
       
  1373 		if((length < iParamDetails.iMin) || (length > iParamDetails.iMax))
       
  1374 			{
       
  1375 			User::Leave(KErrBadDescriptor);
       
  1376 			}
       
  1377 		}
       
  1378 
       
  1379 	iValue = HBufC::NewL(length);
       
  1380 	TPtr ptr = iValue->Des();
       
  1381 	ReadL(ptr,0);
       
  1382 	}
       
  1383 
       
  1384 /**
       
  1385 Gets the descriptor read from the clients message during validation
       
  1386 @return	const reference to the local descriptor copy
       
  1387 */
       
  1388 const TDesC& CDes16ReadParameter::GetDes16L()
       
  1389 	{
       
  1390 	return *iValue;
       
  1391 	}
       
  1392 
       
  1393 /**
       
  1394 Gets the length of the descriptor in the client message
       
  1395 @return	The length of the descriptor
       
  1396 @leave	KErrBadDescriptor if the message argument is not a descriptor type
       
  1397 		Any other system wide error code
       
  1398 */
       
  1399 TInt CDes16ReadParameter::GetDesLengthL()
       
  1400 	{
       
  1401 	return iMessage.GetDesLengthL(iIndex);
       
  1402 	}
       
  1403 
       
  1404 /**
       
  1405 Retrieves the descriptor value read from the clients 
       
  1406 message during validation
       
  1407 @param aDes The target descriptor.
       
  1408 @param aOffset The offset from the start of the clients descriptor
       
  1409 @leave	KErrArgument if the suplied descriptor is too small or an invalid
       
  1410 		offset is supplied
       
  1411 @panic ECMPanicBadDescriptor in UDEB if the supplied descriptor is too small. 
       
  1412 */
       
  1413 void CDes16ReadParameter::ReadL(TDes& aDes, TInt aOffset)
       
  1414 	{
       
  1415 	__ASSERT_DEBUG((aDes.MaxLength() >= (iMessage.GetDesLengthL(iIndex) - aOffset)), 
       
  1416 			PanicServer(ECMPanicBadDescriptor));
       
  1417 	
       
  1418 	iMessage.ReadL(iIndex,aDes,aOffset);
       
  1419 	}
       
  1420 
       
  1421 /**
       
  1422 Factory function for instantiating CDes16WriteParameter objects
       
  1423 @param aParam Parameter details object used to construct object.
       
  1424 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1425 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1426 @return A fully constructed CDes16WriteParameter object.
       
  1427 @leave	Any system-wide error code.
       
  1428 */
       
  1429 CMessageParameterBase* CDes16Parameter::NewL(const TParameterDetails& aParam,
       
  1430 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1431 	{
       
  1432 	CDes16Parameter* self = 
       
  1433 		new(ELeave) CDes16Parameter(aParam, aParamIndex, aMessage, aValidationFn);
       
  1434 	
       
  1435 	return self;
       
  1436 	}
       
  1437 
       
  1438 /**
       
  1439 Constructor for CDes16WriteParameter class.
       
  1440 @param aParam Parameter details to be encapsulated by object
       
  1441 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1442 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1443 @panic ECMPanicBadMessageSchema in UDEB if the schema for this parameter is 
       
  1444 		incorrectly defined
       
  1445 */
       
  1446 CDes16Parameter::CDes16Parameter(const TParameterDetails& aParam, TInt aParamIndex,
       
  1447 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1448 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
       
  1449 	{
       
  1450 	__ASSERT_DEBUG((iParamDetails.iMin >= 0), 
       
  1451 			PanicServer(ECMPanicBadMessageSchema));
       
  1452 	__ASSERT_DEBUG((iParamDetails.iMax >= 0), 
       
  1453 			PanicServer(ECMPanicBadMessageSchema));
       
  1454 	}
       
  1455 
       
  1456 /**
       
  1457 Destructor for CDes16WriteParameter class.
       
  1458 */
       
  1459 CDes16Parameter::~CDes16Parameter()
       
  1460 	{
       
  1461 	
       
  1462 	}
       
  1463 
       
  1464 /**
       
  1465 Validates given message argument against constraints
       
  1466 represented by this object.
       
  1467 @leave	KErrBadDescriptor if the message parameter does not conform
       
  1468 		to the constraints represented by this object
       
  1469 @leave	Any system-wide error code
       
  1470 */
       
  1471 void CDes16Parameter::ValidateL()
       
  1472 	{	
       
  1473 	
       
  1474 	//if there is a supplied custom validation function, call that now
       
  1475 	if(iValidationFn != NULL)
       
  1476 		{
       
  1477 		iValidationFn(this);
       
  1478 		}	
       
  1479 	else
       
  1480 		{		
       
  1481 		TInt length = iMessage.GetDesLengthL(iIndex);
       
  1482 		TInt maxLength = iMessage.GetDesMaxLengthL(iIndex);
       
  1483 		
       
  1484 		if((maxLength < iParamDetails.iMin)||(length > iParamDetails.iMax))
       
  1485 			{
       
  1486 			User::Leave(KErrBadDescriptor);
       
  1487 			}
       
  1488 		}
       
  1489 	}
       
  1490 
       
  1491 /**
       
  1492 Gets the length of the descriptor in the client message
       
  1493 @return	The length of the descriptor
       
  1494 @leave	KErrBadDescriptor if the message argument is not a descriptor type
       
  1495 		Any other system wide error code
       
  1496 */
       
  1497 TInt CDes16Parameter::GetDesLengthL()
       
  1498 	{
       
  1499 	return iMessage.GetDesLengthL(iIndex);
       
  1500 	}
       
  1501 
       
  1502 /**
       
  1503 Gets the max length of the descriptor in the client message
       
  1504 @return	The max length of the descriptor
       
  1505 @leave	KErrBadDescriptor if the message argument is not a descriptor type
       
  1506 		Any other system wide error code
       
  1507 */
       
  1508 TInt CDes16Parameter::GetDesMaxLengthL()
       
  1509 	{
       
  1510 	return iMessage.GetDesMaxLengthL(iIndex);
       
  1511 	}
       
  1512 
       
  1513 /**
       
  1514 Reads a descriptor from the requested message argument
       
  1515 @param aDes The target descriptor.
       
  1516 @param aOffset The offset from the start of the clients descriptor
       
  1517 @leave	Any system wide error code.
       
  1518 @panic ECMPanicBadDescriptor in UDEB if the supplied descriptor is too small. 
       
  1519 */
       
  1520 void CDes16Parameter::ReadL(TDes& aDes,	TInt aOffset)
       
  1521 	{
       
  1522 	__ASSERT_DEBUG((aDes.MaxLength() >= (iMessage.GetDesLengthL(iIndex) - aOffset)), 
       
  1523 			PanicServer(ECMPanicBadDescriptor));
       
  1524 	
       
  1525 	iMessage.ReadL(iIndex,aDes,aOffset);
       
  1526 	}
       
  1527 
       
  1528 /**
       
  1529 Writes a descriptor to the requested message argument
       
  1530 @param aDes The source descriptor containing the data to be written.
       
  1531 @param aOffset The offset from the start of the clients descriptor
       
  1532 @leave	Any system wide error code.
       
  1533 */
       
  1534 void CDes16Parameter::WriteL(const TDesC& aDes,	TInt aOffset)
       
  1535 	{
       
  1536 	iMessage.WriteL(iIndex,aDes,aOffset);
       
  1537 	}
       
  1538 
       
  1539 /**
       
  1540 Factory function for instantiating CPckgParameter objects
       
  1541 @param aParam Parameter details object used to construct object.
       
  1542 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1543 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1544 @return A fully constructed CPckgParameter object.
       
  1545 @leave	Any system-wide error code.
       
  1546 */
       
  1547 CMessageParameterBase* CPckgParameter::NewL(const TParameterDetails& aParam, 
       
  1548 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn )
       
  1549 	{
       
  1550 	CPckgParameter* self = 
       
  1551 		new(ELeave) CPckgParameter(aParam, aParamIndex, aMessage, aValidationFn);
       
  1552 	
       
  1553 	return self;
       
  1554 	}
       
  1555 
       
  1556 /**
       
  1557 Constructor for CPckgParameter class.
       
  1558 @param aParam Parameter details to be encapsulated by object
       
  1559 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1560 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1561 */
       
  1562 CPckgParameter::CPckgParameter(const TParameterDetails& aParam, TInt aParamIndex,
       
  1563 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1564 	: CDes8Parameter(aParam, aParamIndex, aMessage, aValidationFn)
       
  1565 		
       
  1566 	{
       
  1567 
       
  1568 	}
       
  1569 
       
  1570 /**
       
  1571 Destructor for CPckgParameter class.
       
  1572 */
       
  1573 CPckgParameter::~CPckgParameter()
       
  1574 	{
       
  1575 	}
       
  1576 
       
  1577 /**
       
  1578 Validates given message argument against constraints
       
  1579 represented by this object.
       
  1580 @leave	KErrBadDescriptor if the message parameter does not conform
       
  1581 		to the constraints represented by this object
       
  1582 @leave	Any system-wide error code
       
  1583 */
       
  1584 void CPckgParameter::ValidateL()
       
  1585 	{
       
  1586 	
       
  1587 	//if there is a supplied custom validation function, call that now
       
  1588 	if(iValidationFn != NULL)
       
  1589 		{
       
  1590 		iValidationFn(this);
       
  1591 		}
       
  1592 	
       
  1593 	else
       
  1594 		{
       
  1595 		TInt length = iMessage.GetDesLengthL(iIndex);
       
  1596 		
       
  1597 		if((length < iParamDetails.iMin)||(length > iParamDetails.iMax))
       
  1598 			{
       
  1599 			User::Leave(KErrBadDescriptor);
       
  1600 			}
       
  1601 		}
       
  1602 	}
       
  1603 
       
  1604 /**
       
  1605 Factory function for instantiating CPtrParameter objects
       
  1606 @param aParam Parameter details object used to construct object.
       
  1607 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1608 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1609 @return A fully constructed CPtrParameter object.
       
  1610 @leave	Any system-wide error code.
       
  1611 */
       
  1612 CMessageParameterBase* CPtrParameter::NewL(const TParameterDetails& aParam, 
       
  1613 		TInt aParamIndex, const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1614 	{
       
  1615 	CPtrParameter* self = new(ELeave) CPtrParameter(aParam, aParamIndex, aMessage, aValidationFn);
       
  1616 	return self;
       
  1617 	}
       
  1618 
       
  1619 /**
       
  1620 Constructor for CPtrParameter class.
       
  1621 @param aParamIndex The Index of this parameter within the RMessage2 arguments
       
  1622 @param aMessage The RMessage2 object containing the parameter to be represented
       
  1623 */
       
  1624 CPtrParameter::CPtrParameter(const TParameterDetails& aParam, TInt aParamIndex,
       
  1625 		const RMessage2& aMessage, TCustomValidationFn aValidationFn)
       
  1626 	: CMessageParameterBase(aParam, aParamIndex, aMessage, aValidationFn)
       
  1627 	{
       
  1628 	
       
  1629 	}
       
  1630 
       
  1631 /**
       
  1632 Validates given message argument against constraints
       
  1633 represented by this object. Stores the TAny* from the 
       
  1634 clients message to enable simple retrival when required.
       
  1635 @leave	KErrArgument if the argument index is invalid
       
  1636 @leave	Any system-wide error code
       
  1637 */
       
  1638 void CPtrParameter::ValidateL()
       
  1639 	{
       
  1640 
       
  1641 	switch(iIndex)
       
  1642 		{
       
  1643 	
       
  1644 		case 0:
       
  1645 			iValue = iMessage.Ptr0();
       
  1646 			break;
       
  1647 		
       
  1648 		case 1:
       
  1649 			iValue = iMessage.Ptr1();
       
  1650 			break;
       
  1651 		
       
  1652 		case 2:
       
  1653 			iValue = iMessage.Ptr2();
       
  1654 			break;
       
  1655 			
       
  1656 		case 3:
       
  1657 			iValue = iMessage.Ptr3();
       
  1658 			break;
       
  1659 		
       
  1660 		default:
       
  1661 			User::Leave(KErrArgument);
       
  1662 			break;
       
  1663 		}
       
  1664 	
       
  1665 	//if there is a supplied custom validation function, call that now
       
  1666 	if(iValidationFn != NULL)
       
  1667 		{
       
  1668 		iValidationFn(this);
       
  1669 		}
       
  1670 	}
       
  1671 
       
  1672 /**
       
  1673 Retrieves the TAny pointer read from the clients message during validation
       
  1674 @return The TAny pointer read from the client message
       
  1675 */
       
  1676 const TAny* CPtrParameter::GetPtrL()
       
  1677 	{
       
  1678 	return iValue;
       
  1679 	}
       
  1680 
       
  1681 /**
       
  1682 Decode the string
       
  1683 @param aSrcString Source string
       
  1684 @param rDestString Destination string
       
  1685 @return  1 if aSrcString is not long enough to decode fully, resulting in the storage of
       
  1686 	the last character and requiring another aSrcString (poss 0 length) to be passed to it to 
       
  1687 	clear this character. 
       
  1688 @return 0 if the line was decoded OK or the end of the encoded file is reached ie "="
       
  1689 */
       
  1690 
       
  1691 EXPORT_C  TInt Base64Codec::Decode(const TDesC8& aSrcString, TDes8& rDestString)
       
  1692 	{
       
  1693 	TInt shiftStored = 0;
       
  1694 	TInt maskShiftStored = ESix;
       
  1695 	
       
  1696 	TInt decodedInt=0;
       
  1697 	TInt8 offsetChar=0;
       
  1698 	TUint8 decodedChar=0;
       
  1699 	 
       
  1700 	// Clears the destination string
       
  1701 	rDestString.Zero();
       
  1702 
       
  1703 	// Initialise variables
       
  1704 	const TUint8* srcStringPtr=aSrcString.Ptr();
       
  1705 	const TUint8* srcStringEnd=aSrcString.Length()+srcStringPtr;
       
  1706 	TUint8* destStringPtr=(TUint8*)rDestString.Ptr();
       
  1707 	TUint8* destStringPtrBase=destStringPtr;
       
  1708 
       
  1709 	TInt maskShift=maskShiftStored;
       
  1710 	TInt shiftStorage=shiftStored;
       
  1711 	
       
  1712 	// Main character process loop
       
  1713 	while(srcStringPtr<srcStringEnd)	
       
  1714 		{
       
  1715 		offsetChar=(TInt8)(*srcStringPtr-KImcvLookUpStartOffset);
       
  1716 		srcStringPtr++;
       
  1717 
       
  1718 		// Check for valid B64 character		
       
  1719 		if((offsetChar>=0)&&(offsetChar<80))
       
  1720 			{
       
  1721 			// Read in next character and B64 decode
       
  1722 			decodedInt=AsciiToBase64[offsetChar];
       
  1723 
       
  1724 			// Exits when a PAD char is reached
       
  1725 			if(decodedInt==EPadChar)
       
  1726 				{
       
  1727 				rDestString.SetLength((TInt)(destStringPtr-destStringPtrBase));
       
  1728 				return EFalse;
       
  1729 				}
       
  1730 
       
  1731 			// Ensures the first 2 chars of 4 are received before processing
       
  1732 			if(maskShift==ESix)
       
  1733 				maskShift=EFour;
       
  1734 			else
       
  1735 				{
       
  1736 				shiftStorage=shiftStorage<<ESix;
       
  1737 				shiftStorage=shiftStorage|decodedInt;
       
  1738 				decodedChar=(TUint8)((shiftStorage>>maskShift)&EEightBitMask);
       
  1739 				
       
  1740 				if((maskShift-=ETwo)<EZero)
       
  1741 					maskShift=ESix; 
       
  1742 				
       
  1743 				*destStringPtr++=decodedChar;
       
  1744 				}
       
  1745 			shiftStorage=decodedInt;
       
  1746 			}
       
  1747 		}
       
  1748 	shiftStored=shiftStorage;
       
  1749 	maskShiftStored=maskShift;
       
  1750 	
       
  1751 	rDestString.SetLength((TInt)(destStringPtr-destStringPtrBase));
       
  1752 	
       
  1753 	return maskShift<ESix;
       
  1754 	}
       
  1755 
       
  1756 /**
       
  1757 Encode the string
       
  1758 @param aSrcString Source string
       
  1759 @param rDestString Destination string
       
  1760 @return  1 if aSrcString is not long enough to encode fully
       
  1761 @return 0 if the line was encoded OK
       
  1762 */
       
  1763 EXPORT_C TInt Base64Codec::Encode(const TDesC8& aSrcString, TDes8& rDestString)
       
  1764 	{
       
  1765 	// Clears the destination string
       
  1766 	rDestString.Zero();
       
  1767 	
       
  1768 	// Initialise variables
       
  1769 	const TUint8* srcStringPtr=aSrcString.Ptr();
       
  1770 	const TUint8* srcStringEnd=aSrcString.Length()+srcStringPtr;
       
  1771 	TUint8* destStringPtr=(TUint8*)rDestString.Ptr();
       
  1772 	TUint8* destStringPtrBase=destStringPtr;
       
  1773 
       
  1774 	TInt character=0;
       
  1775 	TUint8 encodedChar=0;
       
  1776 	TInt charStorage=0;
       
  1777  	TInt maskShift=EZero;
       
  1778 	TInt destStringCharNum = 0;
       
  1779 
       
  1780 	while(srcStringPtr<=srcStringEnd)
       
  1781 		{
       
  1782 		// maskShift is used as a char read counter
       
  1783 		if(maskShift==ESix)
       
  1784 			{
       
  1785 			// If the 3rd char read is also the last char then the while loop
       
  1786 			// is broken on the next check.
       
  1787 			if(srcStringPtr==srcStringEnd)
       
  1788 				srcStringPtr++;
       
  1789 			maskShift=EZero;
       
  1790 			character=0;   
       
  1791 			}
       
  1792 		else
       
  1793 			{
       
  1794 			if(srcStringPtr==srcStringEnd)
       
  1795 				character=0;
       
  1796 			else
       
  1797 				character=*srcStringPtr;
       
  1798 
       
  1799 			srcStringPtr++;
       
  1800 			// Shifts charStorage ready for the next char
       
  1801 			charStorage=charStorage<<8;
       
  1802 			maskShift+=ETwo;
       
  1803 			}
       
  1804 		charStorage=charStorage|character;
       
  1805 		// Shifts the mask to the correct bit location
       
  1806 		// Masks (AND's) the valid bits from charStorage
       
  1807 		// Shifts the valid bits into the low order 8bits
       
  1808 		// Converts to BASE64 char, Casts the result to an unsigned char (which it should be ?....I hope)
       
  1809 		encodedChar=(TUint8)Base64ToAscii[((charStorage>>maskShift)&ESixBitMask)];
       
  1810 
       
  1811 		*destStringPtr++=encodedChar;
       
  1812 		destStringCharNum++;
       
  1813 
       
  1814 		// Add a CRLF every KMaxB64EncodedCharsPerLine characters so as not to exceed the line length
       
  1815 		// limitation specified in RFC 2822.
       
  1816 		if (destStringCharNum == KMaxB64EncodedCharsPerLine)
       
  1817 			{
       
  1818 			destStringCharNum = 0;
       
  1819 			*destStringPtr++ = '\r';
       
  1820 			*destStringPtr++ = '\n';
       
  1821 			}
       
  1822 		}
       
  1823 	
       
  1824 	// Check for not enough chars and pad if required
       
  1825 	if (maskShift==EFour)
       
  1826 		{
       
  1827 		*destStringPtr++=KImcvConvEquals;
       
  1828 		*destStringPtr++=KImcvConvEquals;
       
  1829 		}
       
  1830 	else
       
  1831 		if(maskShift==ESix)
       
  1832 			*destStringPtr++=KImcvConvEquals;	
       
  1833 			
       
  1834 	rDestString.SetLength((TInt)(destStringPtr-destStringPtrBase));
       
  1835 	return ((TInt)(srcStringPtr-srcStringEnd));
       
  1836 	}