contentmgmt/contentaccessfwfordrm/source/caf/resolver.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     1 /*
       
     2 * Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32debug.h>
       
    20 #include <ecom/ecom.h>
       
    21 
       
    22 #include "resolver.h"
       
    23 #include "agentfactory.h"
       
    24 #include "agentinterface.h"
       
    25 #include "agentinfo.h"
       
    26 #include "agent.h"
       
    27 #include "cafpanic.h"
       
    28 #include "caferr.h"
       
    29 #include "patchdata.h"
       
    30 
       
    31 
       
    32 using namespace ContentAccess;
       
    33 
       
    34 // Constants for the F32 agent
       
    35 _LIT(KF32Agent,"F32 CA Agent");
       
    36 
       
    37 
       
    38 _LIT(KParentDir, "..\\");
       
    39 _LIT(KPrivateDir, "\\private\\");
       
    40 const TInt KPrivateDirLength = 9;   // "\\private\\"
       
    41 const TInt KPrivateDirAndDriveLength = 11;   // "x:\\private\\"
       
    42 const TInt KPrivateDirOffset = 2; // "x:\\"
       
    43 
       
    44 
       
    45 EXPORT_C CAgentResolver* CAgentResolver::NewLC(const TBool aDynamicAgentUpdate)
       
    46 	{
       
    47 	CAgentResolver* self = new (ELeave) CAgentResolver(aDynamicAgentUpdate);
       
    48 	CleanupStack::PushL(self);
       
    49 	self->ConstructL();
       
    50 	return self;
       
    51 	}
       
    52 
       
    53 EXPORT_C CAgentResolver* CAgentResolver::NewL(const TBool aDynamicAgentUpdate)
       
    54 	{
       
    55 	CAgentResolver* self = CAgentResolver::NewLC(aDynamicAgentUpdate);
       
    56 	CleanupStack::Pop(self);
       
    57 	return self;
       
    58 	}
       
    59 
       
    60 CAgentResolver::CAgentResolver(const TBool aDynamicAgentUpdate) : CActive(EPriorityStandard), iDynamicAgentUpdate(aDynamicAgentUpdate)
       
    61 	{
       
    62 	}
       
    63 
       
    64 CAgentResolver::~CAgentResolver()
       
    65 	{
       
    66 	// remove ourselves from the ActiveScheduler
       
    67 	if(IsAdded())
       
    68 		{
       
    69 		Deque();
       
    70 		}
       
    71 	
       
    72 	// Unload all the agents
       
    73 	DestroyListOfAgents();
       
    74 	
       
    75 	// Close our ECOM session
       
    76 	if(iEcomSession)
       
    77 		{
       
    78 		if(iDynamicAgentUpdate)
       
    79 			{
       
    80 			iEcomSession->CancelNotifyOnChange(iStatus);
       
    81 			}
       
    82 		iEcomSession->Close();
       
    83 		REComSession::FinalClose();
       
    84 		}
       
    85 
       
    86 	iSupplierMimeTypes.Close();
       
    87 	iConsumerMimeTypes.Close();
       
    88 	iAgentInfos.Close();
       
    89 	}
       
    90 
       
    91 void CAgentResolver::ConstructL()
       
    92 	{
       
    93 	if(iDynamicAgentUpdate)
       
    94 		{
       
    95 		// Add ourselves to the current active scheduler so we can get dynamic 
       
    96 		// updates when agents are removed or new agents are added
       
    97 		CActiveScheduler::Add(this);
       
    98 		}
       
    99 
       
   100 	iEcomSession = &REComSession::OpenL();
       
   101 	
       
   102 	// find all the agents
       
   103 	BuildListOfAgentsL();
       
   104 
       
   105 	if(iDynamicAgentUpdate)
       
   106 		{
       
   107 		// register for ECOM update notifications in case a new agent appears
       
   108 		SetActive();
       
   109 		iEcomSession->NotifyOnChange(iStatus);
       
   110 		}
       
   111 	}
       
   112 
       
   113 void CAgentResolver::BuildListOfAgentsL()
       
   114 	{
       
   115 	TInt err = KErrNone;
       
   116 
       
   117 	// Get all plugins which implement the agent interface
       
   118 	RImplInfoPtrArray implArray;
       
   119 	CleanupStack::PushL(TCleanupItem(CleanImplArray, &implArray));
       
   120 	REComSession::ListImplementationsL(KCAAgentInterfaceUid, implArray);
       
   121 
       
   122 	for (TInt i = 0; i < implArray.Count(); ++i)
       
   123 		{
       
   124 #ifdef __EPOC32__
       
   125 		// On hardware - to load agents from sources other than ROM the patch 
       
   126 		// data KCafLoadPostProductionAgents must be set to True (non-zero).
       
   127 		// Default SymbianOS behavior is to only load agents from ROM
       
   128 		if ((KCafLoadPostProductionAgents == 0) &&
       
   129             !implArray[i]->RomBased())
       
   130 			{
       
   131 			// If the agent is not in ROM, don't load it because it might
       
   132 			// be a security risk.
       
   133 			continue;
       
   134 			}
       
   135 #endif
       
   136 
       
   137 		// Construct all the agent infos from these implementations
       
   138 		TRAP(err, AddAgentL(*implArray[i]));
       
   139 
       
   140 		// If we ran out of memory proagate the leave to the caller
       
   141 		// otherwise don't let a dodgy agent affect the construction of the other
       
   142 		// agents
       
   143 		if(err == KErrNoMemory)
       
   144 			{
       
   145 			User::Leave(KErrNoMemory);
       
   146 			}
       
   147 		}
       
   148 	CleanupStack::PopAndDestroy(&implArray);  
       
   149 
       
   150 
       
   151 	if (!iDefaultAgent)
       
   152 		{
       
   153 		// If we didn't find a default agent, we have a big problem so panic
       
   154 		User::Panic(KCafPanicString, ECafPanicNoF32Agent);
       
   155 		}
       
   156 	}
       
   157 
       
   158 void CAgentResolver::AddAgentL(const CImplementationInformation& aImplInfo)
       
   159 	{
       
   160 	// Create a CAgentInfo instance
       
   161 	CAgentInfo* agentInfo = CAgentInfo::NewLC(aImplInfo);
       
   162 
       
   163 
       
   164 	if(IsF32Agent(*agentInfo))
       
   165 		{
       
   166 		// It's the F32 Agent
       
   167 		if(iDefaultAgent)
       
   168 			{
       
   169 			// If we already have a default agent something is seriously wrong
       
   170 			User::Panic(KCafPanicString, ECafPanicDuplicateF32Agent);
       
   171 			}
       
   172 
       
   173 		// Note that the default agent is NOT stored in the agents list, it is a special case
       
   174 		iDefaultAgent = agentInfo;
       
   175 		CleanupStack::Pop(agentInfo);
       
   176 		}
       
   177 	else
       
   178 		{
       
   179 		// All other agents go in the agent list
       
   180 		User::LeaveIfError(iAgentInfos.Append(agentInfo));
       
   181 		CleanupStack::Pop(agentInfo);
       
   182 
       
   183 		TInt mimeIndex=0;
       
   184 
       
   185 		// Update our list of all supplier mime types supported by CAF
       
   186 		for(mimeIndex=0;mimeIndex < agentInfo->SupplierMimeTypes().Count(); mimeIndex++) 
       
   187 			{
       
   188 			User::LeaveIfError(iSupplierMimeTypes.Append(*agentInfo->SupplierMimeTypes()[mimeIndex]));
       
   189 			}
       
   190 
       
   191 		// Update our list of all consumer mime types supported by CAF
       
   192 		for(mimeIndex=0;mimeIndex < agentInfo->ConsumerMimeTypes().Count(); mimeIndex++) 
       
   193 			{
       
   194 			User::LeaveIfError(iConsumerMimeTypes.Append(*agentInfo->ConsumerMimeTypes()[mimeIndex]));
       
   195 			}
       
   196 		}
       
   197 	}
       
   198 
       
   199 void CAgentResolver::DestroyListOfAgents()
       
   200 	{
       
   201 	iSupplierMimeTypes.Reset();
       
   202 	iConsumerMimeTypes.Reset();
       
   203 
       
   204 	// cant forget to delete the default agent
       
   205 	delete iDefaultAgent;
       
   206 	iDefaultAgent = NULL;
       
   207 
       
   208 	// Free memory assocated with the iAgentInfos array 
       
   209 	iAgentInfos.ResetAndDestroy();
       
   210 	}
       
   211 
       
   212 void CAgentResolver::DoCancel()
       
   213 	{
       
   214 	// Abort any update notification 
       
   215 	iEcomSession->CancelNotifyOnChange(iStatus);
       
   216 	}
       
   217 
       
   218 void CAgentResolver::RunL()
       
   219 	{
       
   220 	// Called by the ECOM framework if a new agent appears
       
   221 
       
   222 	// remove the existing list of agents and build a new one
       
   223 	DestroyListOfAgents();
       
   224 	BuildListOfAgentsL();
       
   225 
       
   226 	// request notification of any further changes
       
   227 	iEcomSession->NotifyOnChange(iStatus);
       
   228 	SetActive();
       
   229 	}	
       
   230 
       
   231 TBool CAgentResolver::IsF32Agent(CAgentInfo& aAgentInfo)
       
   232 	{
       
   233 	// Check if the agent has no consumer or supplier mime types
       
   234 	// and that it has the correct name and Uid
       
   235 	if (aAgentInfo.Agent().ImplementationUid() == KF32AgentImplUid
       
   236 		&& aAgentInfo.Agent().Name().Compare(KF32Agent()) == 0 
       
   237 		&& aAgentInfo.ConsumerMimeTypes().Count() == 0 
       
   238 		&& aAgentInfo.SupplierMimeTypes().Count() == 0)
       
   239 		{
       
   240 		return ETrue;
       
   241 		}
       
   242 	else
       
   243 		{
       
   244 		return EFalse;
       
   245 		}
       
   246 	}
       
   247 
       
   248 CAgentInfo& CAgentResolver::ResolveSupplierMimeL(const TDesC8& aMimeType) const
       
   249 	{
       
   250 	// Go through all the agents and return the one which supports the
       
   251 	// required supplier mime type
       
   252 	CAgentInfo* retVal=NULL;
       
   253 
       
   254 	for (TInt i = 0; i < iAgentInfos.Count(); ++i)
       
   255 		{
       
   256 		if (iAgentInfos[i]->IsSupportedSupplier(aMimeType))
       
   257 			{
       
   258 			retVal = iAgentInfos[i];
       
   259 			break;
       
   260 			}
       
   261 		}
       
   262 	
       
   263 	if (!retVal)
       
   264 		{
       
   265 		User::Leave(KErrCANoAgent);
       
   266 		}
       
   267 	return *retVal;
       
   268 	}
       
   269 
       
   270 CAgentInfo& CAgentResolver::ResolveConsumerMime(const TDesC8& aMimeType) const
       
   271 	{
       
   272 	// By default, set the return value to be the default agent. If we find
       
   273 	// anything better, then we change it
       
   274 	CAgentInfo* retVal = iDefaultAgent;
       
   275 
       
   276 	for (TInt i = 0; i < iAgentInfos.Count(); ++i)
       
   277 		{
       
   278 		if (iAgentInfos[i]->IsSupportedConsumer(aMimeType))
       
   279 			{
       
   280 			retVal = iAgentInfos[i];
       
   281 			break;
       
   282 			}
       
   283 		}
       
   284 
       
   285 	ASSERT(retVal);
       
   286 	return *retVal;
       
   287 	}
       
   288 
       
   289 CAgentInfo& CAgentResolver::ResolveFileL(const TDesC& aURI, TDes& aActualUri, TContentShareMode aShareMode) const
       
   290 	{
       
   291 	// Go through all the agents and return the one which supports the file at the given URI	
       
   292 	TBool thePrivateDir = EFalse;	
       
   293 	TUid agentUid = ResolveDirectory(aURI, aActualUri, thePrivateDir);
       
   294 	
       
   295 	if(agentUid != iDefaultAgent->Agent().ImplementationUid())
       
   296 		{
       
   297 		// this file must be living in a private server directory
       
   298 		// return the agent who owns the directory
       
   299 		return AgentInfoL(agentUid);
       
   300 		}
       
   301 	else
       
   302 		{
       
   303 		TInt agentsCount(iAgentInfos.Count());
       
   304 		CAgentManager* agentManager = NULL;
       
   305 		for (TInt i = 0; i < agentsCount; ++i)
       
   306 			{
       
   307 			TRAPD(result, agentManager = &iAgentInfos[i]->AgentManagerL());
       
   308 			if(result != KErrNone)
       
   309 				{
       
   310 				if(KErrNoMemory == result)
       
   311 					{
       
   312 					User::Leave(result);
       
   313 					}
       
   314 				else
       
   315 					{
       
   316 					continue;	
       
   317 					}
       
   318 				}
       
   319 			if (agentManager->IsRecognizedL(aURI, aShareMode))
       
   320 				{
       
   321 				return *iAgentInfos[i];
       
   322 				}
       
   323 			}
       
   324 		}
       
   325 	return *iDefaultAgent;
       
   326 	}
       
   327 
       
   328 CAgentInfo& CAgentResolver::ResolveFileL(RFile& aFile) const
       
   329 	{
       
   330 	// Go through all the agents and return the one which supports the file
       
   331 
       
   332 	TInt agentsCount(iAgentInfos.Count());
       
   333 	CAgentManager* agentManager = NULL;
       
   334 	for (TInt i = 0; i < agentsCount; ++i)
       
   335 		{
       
   336 		TRAPD(result, agentManager = &iAgentInfos[i]->AgentManagerL());
       
   337 		if(result != KErrNone)
       
   338 			{
       
   339 			if(KErrNoMemory == result)
       
   340 				{
       
   341 				User::Leave(result);
       
   342 				}
       
   343 			else
       
   344 				{
       
   345 				continue;	
       
   346 				}
       
   347 			}
       
   348 		if (agentManager->IsRecognizedL(aFile))
       
   349 			{
       
   350 			return *iAgentInfos[i];
       
   351 			}
       
   352 		}
       
   353 	return *iDefaultAgent;
       
   354 	}
       
   355 	
       
   356 TUid CAgentResolver::ResolveDirectory(const TDesC& aPath, TDes& aActualPath, TBool& aThePrivateDir) const
       
   357 	{
       
   358 	TInt i = 0;
       
   359 	TInt pathLength = 0;
       
   360 	TBuf <KPrivateDirAndDriveLength> pathLowerCase;
       
   361 	
       
   362 	// Assume it's a publicly accessable path
       
   363 	aThePrivateDir = EFalse;
       
   364 	
       
   365 	// Find the length of the path and private directory
       
   366 	pathLength = aPath.Length();
       
   367 
       
   368 	// Check that the path is long enough to be within a private directory
       
   369 	// and does not include "..\\".The  "..\\" sequence could be a security risk
       
   370 	if(aPath.Find(KParentDir()) == KErrNotFound && pathLength >= KPrivateDirAndDriveLength)
       
   371 		{
       
   372 		// Create a lower case copy of the left hand side of the path
       
   373 		TPtrC lowerCasePtr = aPath.Mid(KPrivateDirOffset, KPrivateDirLength);
       
   374 		pathLowerCase.Copy(lowerCasePtr);
       
   375 		pathLowerCase.LowerCase();
       
   376 	
       
   377 		// Compare the first directory in the path to \\private\\ 
       
   378 		if(KPrivateDir() == pathLowerCase)
       
   379 			{
       
   380 			// It is a private directory of some sort
       
   381 			if(pathLength > KPrivateDirAndDriveLength)
       
   382 				{
       
   383 				// It must be a server private directory data cage
       
   384 				TPtrC serverDirectoryPath = aPath.Right(pathLength - KPrivateDirAndDriveLength);
       
   385 				for(i = 0; i < AgentInfoCount(); i++)
       
   386 					{
       
   387 					// See if the part after \\private\\ matches the agent name
       
   388 					TPtrC privateDirectoryName = AgentInfo(i).PrivateDirectoryName();
       
   389 					TPtrC agentName = AgentInfo(i).Agent().Name();
       
   390 					if(privateDirectoryName.Length() && agentName.Length() && agentName == serverDirectoryPath.Left(agentName.Length()))
       
   391 						{
       
   392 						// It must be this agent's private directory
       
   393 						// Convert \\private\\agentName\\... to \\private\\SID\\...
       
   394 						aActualPath.Copy(aPath.Left(KPrivateDirAndDriveLength));
       
   395 						aActualPath.Append(privateDirectoryName);
       
   396 						aActualPath.Append(aPath.Right(pathLength - KPrivateDirAndDriveLength - agentName.Length()));
       
   397 						return AgentInfo(i).Agent().ImplementationUid();
       
   398 						}
       
   399 					}
       
   400 				}
       
   401 			else
       
   402 				{
       
   403 				// It's just the c:\\private\\ directory
       
   404 				// Use the default agent, any calls will just fail
       
   405 				aThePrivateDir = ETrue;
       
   406 				}
       
   407 			}
       
   408 		}
       
   409 	
       
   410 	// Not an agent private directory so just return the default agent
       
   411 	aActualPath.Copy(aPath);
       
   412 	return iDefaultAgent->Agent().ImplementationUid();
       
   413 	}
       
   414 
       
   415 HBufC* CAgentResolver::ConvertAgentFileNameL(const TDesC& aFileName) const
       
   416 	{
       
   417 	TInt i = 0;
       
   418 	TInt fileNameLength = 0;
       
   419 	TBuf <KPrivateDirAndDriveLength> pathLowerCase;
       
   420 	
       
   421 	fileNameLength = aFileName.Length();
       
   422 	
       
   423 	// If the path is shorter than the x:\\private\\ it must be a F32 file
       
   424 	if(fileNameLength  > KPrivateDirAndDriveLength)
       
   425 		{
       
   426 		// Create a lower case copy of the left hand side of the path
       
   427 		TPtrC lowerCasePtr = aFileName.Mid(KPrivateDirOffset, KPrivateDirLength);
       
   428 		pathLowerCase.Copy(lowerCasePtr);
       
   429 		pathLowerCase.LowerCase();
       
   430 	
       
   431 		// Compare the first directory in the path to \\private\\ 
       
   432 		if(KPrivateDir() == pathLowerCase)
       
   433 			{
       
   434 			// It is a private directory of some sort
       
   435 			if(fileNameLength > KPrivateDirAndDriveLength)
       
   436 				{
       
   437 				// It must be a server private directory data cage
       
   438 				TPtrC serverDirectoryPath = aFileName.Right(fileNameLength - KPrivateDirAndDriveLength);
       
   439 				for(i = 0; i < AgentInfoCount(); i++)
       
   440 					{
       
   441 					// See if the part after \\private\\ matches the agent name
       
   442 					TPtrC privateDirectoryName = AgentInfo(i).PrivateDirectoryName();
       
   443 					TPtrC agentName = AgentInfo(i).Agent().Name();
       
   444 					if(privateDirectoryName.Length() && agentName.Length() && privateDirectoryName == serverDirectoryPath.Left(privateDirectoryName.Length()))
       
   445 						{
       
   446 						// It is this agent's private directory
       
   447 						// Convert \\private\\SID\\... \\private\\agentName\\... 
       
   448 						HBufC* buffer = HBufC::NewL(fileNameLength - privateDirectoryName.Length() + agentName.Length());
       
   449 						TPtr ptr = buffer->Des();
       
   450 						ptr.Copy(aFileName.Left(KPrivateDirAndDriveLength));
       
   451 						ptr.Append(agentName);
       
   452 						ptr.Append(aFileName.Right(fileNameLength - KPrivateDirAndDriveLength - privateDirectoryName.Length()));
       
   453 						return buffer;
       
   454 						}
       
   455 					}
       
   456 				}
       
   457 			}
       
   458 		}
       
   459 	return aFileName.AllocL();
       
   460 	}
       
   461 
       
   462 EXPORT_C TBool CAgentResolver::DoRecognizeL(const TDesC& aName, const TDesC8& aBuffer, TDes8& aFileMimeType, TDes8& aContentMimeType)
       
   463 	{
       
   464 
       
   465 	// Given the filename and buffer from apparc, ask the agents in turn if they recognize the file
       
   466 	// Note this will not call the DefaultAgent (F32) because it won't be able to recognize anything
       
   467 
       
   468 	TInt agentsCount(iAgentInfos.Count());
       
   469 	CAgentManager* agentManager = NULL;
       
   470 	for (TInt i = 0; i < agentsCount; ++i)
       
   471 		{
       
   472 		TRAPD(result, agentManager = &iAgentInfos[i]->AgentManagerL());
       
   473 		if(result != KErrNone)
       
   474 			{
       
   475 			if(KErrNoMemory == result)
       
   476 				{
       
   477 				User::Leave(result);
       
   478 				}
       
   479 			else
       
   480 				{
       
   481 				continue;	
       
   482 				}
       
   483 			}
       
   484 		if (agentManager->RecognizeFileL(aName, aBuffer, aFileMimeType, aContentMimeType))
       
   485 			{
       
   486 			// force to lower case to ensure that chosen lower case scheme for mime types is maintained
       
   487 			aFileMimeType.LowerCase();
       
   488 			aContentMimeType.LowerCase();			
       
   489 			return ETrue;
       
   490 			}
       
   491 		}
       
   492 	return EFalse;
       
   493 	}
       
   494 	
       
   495 
       
   496 void CAgentResolver::CleanImplArray(TAny* aArray)
       
   497 	{
       
   498 	static_cast<RImplInfoPtrArray*>(aArray)->ResetAndDestroy();
       
   499 	}
       
   500 
       
   501 EXPORT_C TInt CAgentResolver::PreferredBufferSize()
       
   502 	{
       
   503 	TInt size=0;
       
   504 
       
   505 	if(iDefaultAgent != NULL)
       
   506 		{
       
   507 		size = iDefaultAgent->PreferredBufferSize();
       
   508 		}
       
   509 
       
   510 	// Find out the maximum buffer requested by any agent
       
   511 	for (TInt i = 0; i < iAgentInfos.Count(); ++i)
       
   512 			{
       
   513 			if(iAgentInfos[i]->PreferredBufferSize() > size)
       
   514 				{
       
   515 				size = iAgentInfos[i]->PreferredBufferSize();
       
   516 				}
       
   517 			}
       
   518 	return size;
       
   519 	}
       
   520 
       
   521 
       
   522 EXPORT_C const RArray<TPtrC8>& CAgentResolver::ConsumerMimeTypes() const
       
   523 	{
       
   524 	return iConsumerMimeTypes;
       
   525 	}
       
   526 
       
   527 
       
   528 EXPORT_C const RArray<TPtrC8>& CAgentResolver::SupplierMimeTypes() const
       
   529 	{
       
   530 	return iSupplierMimeTypes;
       
   531 	}
       
   532 
       
   533 
       
   534 CAgentInfo& CAgentResolver::AgentInfoL(const TDesC& aAgentName) const
       
   535 	{
       
   536 	TBool found = EFalse;
       
   537 	TInt i = 0;
       
   538 	for(i = 0; i < iAgentInfos.Count(); i++)
       
   539 		{
       
   540 		if(iAgentInfos[i]->Agent().Name() == aAgentName)
       
   541 			{
       
   542 			found = ETrue;
       
   543 			break;
       
   544 			}
       
   545 		}
       
   546 	
       
   547 	if(!found)
       
   548 		{
       
   549 		// Can't find the agent so leave
       
   550 		User::Leave(KErrNotFound);
       
   551 		}
       
   552 	
       
   553 	return *iAgentInfos[i];
       
   554 	}
       
   555 
       
   556 CAgentInfo& CAgentResolver::AgentInfoL(const TUid& aUid) const
       
   557 	{
       
   558 	TInt i = 0;
       
   559 	TBool found = EFalse;
       
   560 	
       
   561 	// See if it's the F32 agent
       
   562 	if(aUid == DefaultAgentUid())
       
   563 		{
       
   564 		return *iDefaultAgent;
       
   565 		}
       
   566 	
       
   567 	for(i = 0; i < iAgentInfos.Count(); i++)
       
   568 		{
       
   569 		if(iAgentInfos[i]->Agent().ImplementationUid() == aUid)
       
   570 			{
       
   571 			found = ETrue;
       
   572 			break;			
       
   573 			}
       
   574 		}
       
   575 	
       
   576 	if(!found)
       
   577 		{
       
   578 		// couldn't find the agent so leave
       
   579 		User::Leave(KErrNotFound);
       
   580 		}
       
   581 	
       
   582 	return *iAgentInfos[i];
       
   583 	}
       
   584 
       
   585 CAgentInfo& CAgentResolver::AgentInfo(TInt aIndex) const
       
   586 		{
       
   587 		return *iAgentInfos[aIndex];		
       
   588 		}
       
   589 
       
   590 TInt CAgentResolver::AgentInfoCount() const
       
   591 	{
       
   592 	return iAgentInfos.Count();	
       
   593 	}
       
   594 
       
   595 TUid CAgentResolver::DefaultAgentUid() const
       
   596 	{
       
   597 	return iDefaultAgent->Agent().ImplementationUid();
       
   598 	}