lowlevellibsandfws/pluginfw/Framework/frame/RegistryData.cpp
changeset 0 e4d67989cc36
child 17 ef2ebc87518f
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 1997-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 // This file contains the implementations of the classes
       
    15 // which manage the internal structure of the registry.
       
    16 // 
       
    17 //
       
    18 
       
    19 #include <e32base.h>
       
    20 #include <e32uid.h>
       
    21 #include <s32stor.h>
       
    22 #include <s32file.h>
       
    23 #include <startup.hrh> // for EStartupStateNonCritical
       
    24 #include <e32ldr.h> // for hash checking
       
    25 #include <e32ldr_private.h> // for RLoader
       
    26 #include <bautils.h> // for BaflUtils::FileExists
       
    27 
       
    28 #include "EComDebug.h"
       
    29 #include <ecom/ecom.h>
       
    30 #include <ecom/ecomerrorcodes.h>
       
    31 #include <ecom/ecomresolverparams.h>
       
    32 #include <ecom/implementationinformation.h>
       
    33 #include "RegistryData.h"
       
    34 #include "DowngradePath.h"
       
    35 #include "DriveInfo.h"
       
    36 #include "FileUtils.h"
       
    37 #include "EComUidCodes.h"
       
    38 #include "EComInternalErrorCodes.h"
       
    39 #define UNUSED_VAR(a) a = a
       
    40 
       
    41 const TInt KRegVersion = -9999;
       
    42 const TInt KDllExtensionLength=4;
       
    43 _LIT(KDllExtension,".dll");
       
    44 //
       
    45 //CRegistryData::TInterfaceStruct
       
    46 
       
    47 /**
       
    48 Constructor for TInterfaceStruct
       
    49 @post			Its member variable is granulated as (1)
       
    50 */
       
    51 CRegistryData::TInterfaceStruct::TInterfaceStruct():
       
    52 	iImpData(1)
       
    53 	{
       
    54 	// Do nothing here
       
    55 	}
       
    56 
       
    57 /**
       
    58 This method determins the order of two TInterfaceIndex objects
       
    59 @param			indexEntry1 first TInterfaceIndex object
       
    60 @param			indexEntry2 second TInterfaceIndex object
       
    61 @return			integer indicating the order of these two
       
    62 @pre			This object is fully constructed
       
    63 */
       
    64 TInt CRegistryData::TInterfaceStruct::CompareInfUid(const TInterfaceIndex& indexEntry1,
       
    65 													const TInterfaceIndex& indexEntry2)
       
    66 	{
       
    67 	return CompareTUidValues(indexEntry1.iInterfaceUid.iUid,indexEntry2.iInterfaceUid.iUid);
       
    68 	}
       
    69 
       
    70 //
       
    71 //CRegistryData::TImplStruct
       
    72 
       
    73 /**
       
    74 Constructor for TImplStruct
       
    75 @post			Its member variables are initialised
       
    76 */
       
    77 CRegistryData::TImplStruct::TImplStruct():
       
    78 	iCurrentImpl(NULL),
       
    79 	iUnusedImpls(1)
       
    80 	{
       
    81 	// Do nothing here
       
    82 	}
       
    83 	
       
    84 /**
       
    85 This method determins the order of two TImplStruct objects
       
    86 @param			aEntry1 first TImplStruct object
       
    87 @param			aEntry2 second TImplStruct object
       
    88 @return			integer indicating the order of these two
       
    89 @pre			This object is fully constructed
       
    90 */
       
    91  TInt CRegistryData::TImplStruct::CompareImplStructUid(const TImplStruct& aEntry1,
       
    92 													const TImplStruct& aEntry2)
       
    93 	{
       
    94 	return CompareTUidValues(aEntry1.iCurrentImpl->iImplInfo->ImplementationUid().iUid,
       
    95 						aEntry2.iCurrentImpl->iImplInfo->ImplementationUid().iUid);
       
    96 	}
       
    97 	
       
    98 /** Comparer to determine the order of a TUid object (implementation UID) in relation to and a TImplStruct object.
       
    99 @param aUid the Implementation UID to compare with.
       
   100 @param aEntry the TImplStruct object to compare aUid against.
       
   101 @return integer indicating the order of the two.
       
   102 */
       
   103 TInt CRegistryData::TImplStruct::CompareUidAgainstImplStruct(
       
   104 	const TUid* aUid,
       
   105 	const TImplStruct& aEntry)
       
   106 	{
       
   107 	return CompareTUidValues(aUid->iUid,aEntry.iCurrentImpl->iImplInfo->ImplementationUid().iUid);
       
   108 	}
       
   109 
       
   110 //
       
   111 // CRegistryData::CImplementationData class
       
   112 
       
   113 /**
       
   114 Creates a new CImplemenatationData object. Note that CImplementationInformation needs to be constructed too,
       
   115 for this object to be fully constructed.
       
   116 @param			aParent A pointer to the parent instance of CInterfaceData
       
   117 @return			A pointer to the newly created object.
       
   118 @post			This object is partly constructed and initialized and is on 
       
   119 				the CleanupStack.
       
   120 */
       
   121 CRegistryData::CImplementationData* CRegistryData::CImplementationData::NewLC(CInterfaceData* aParent)
       
   122 	{
       
   123 	CImplementationData* self=new(ELeave) CImplementationData(aParent);
       
   124 	CleanupStack::PushL(self);
       
   125 	return self;
       
   126 	}
       
   127 
       
   128 /**
       
   129 Creates a new CImplemenatationData object. It takes parameters to create a CImplementationInformation object,
       
   130 during 2nd phase construction and initializes iImplInfo to reference to this CImplementationInformation object.
       
   131 @param			aParent A pointer to the parent instance of CInterfaceData
       
   132 @param			aUid The unique Id of the new implementation
       
   133 @param			aVersion The version number of the new implementation
       
   134 @param			aName The display name of the new implementation
       
   135 @param			aDataType The data type supported by the new implementation
       
   136 @param			aOpaqueData Data for the new implementation which is not used by the ECom framework
       
   137 @param			aDrive The drive that the new implementation is on
       
   138 @param			aRomOnly The flag recording whether the new implementation may be loaded from ROM only
       
   139 @param			aRomBased The flag recording whether the new implementation is on ROM or is a later version of one on ROM
       
   140 @return			A pointer to the newly created object
       
   141 @post			This object is fully constructed and initialized.
       
   142 */
       
   143 CRegistryData::CImplementationData* CRegistryData::CImplementationData::NewL(CInterfaceData* aParent,
       
   144 																				TUid	aUid,
       
   145 																				TInt	aVersion, 
       
   146 																				HBufC*  aName,
       
   147 																				HBufC8* aDataType,
       
   148 																				HBufC8* aOpaqueData,
       
   149 																				TDriveUnit aDrive,
       
   150 																				TBool aRomOnly,
       
   151 																				TBool aRomBased)
       
   152 	{
       
   153 	CImplementationData* self=new(ELeave) CImplementationData(aParent);
       
   154 	CleanupStack::PushL(self);
       
   155 	self->ConstructL(aUid,
       
   156 					aVersion,
       
   157 					aName,
       
   158 					aDataType,
       
   159 					aOpaqueData,
       
   160 					aDrive,
       
   161 					aRomOnly,
       
   162 					aRomBased);
       
   163 	CleanupStack::Pop(self);
       
   164 	return self;
       
   165 	}
       
   166 
       
   167 /**
       
   168 Creates a new CImplemenatationData object. It takes parameters to create a CImplementationInformation object,
       
   169 during 2nd phase construction and initializes iImplInfo to reference to this CImplementationInformation object.
       
   170 @param			aParent A pointer to the parent instance of CInterfaceData
       
   171 @param			aUid The unique Id of the new implementation
       
   172 @param			aVersion The version number of the new implementation
       
   173 @param			aName The display name of the new implementation
       
   174 @param			aDataType The data type supported by the new implementation
       
   175 @param			aOpaqueData Data for the new implementation which is not used by the ECom framework
       
   176 @param			aDrive The drive that the new implementation is on
       
   177 @param			aRomOnly The flag recording whether the new implementation may be loaded from ROM only
       
   178 @param			aRomBased The flag recording whether the new implementation is on ROM or is a later version of one on ROM
       
   179 @param			aExtendedInterfaces The pointer to the array recording the extended interfaces supported by this implementation.
       
   180 				NULL is available for PLUGIN without extended interfaces support.
       
   181 @return			A pointer to the newly created object
       
   182 @post			This object is fully constructed and initialized.
       
   183 */
       
   184 CRegistryData::CImplementationData* CRegistryData::CImplementationData::NewL(CInterfaceData* aParent,
       
   185 																				TUid	aUid,
       
   186 																				TInt	aVersion, 
       
   187 																				HBufC*  aName,
       
   188 																				HBufC8* aDataType,
       
   189 																				HBufC8* aOpaqueData,
       
   190 																				TDriveUnit aDrive,
       
   191 																				TBool aRomOnly,
       
   192 																				TBool aRomBased,
       
   193 																				RExtendedInterfacesArray* aExtendedInterfaces)
       
   194 	{
       
   195 	CImplementationData* self=new(ELeave) CImplementationData(aParent);
       
   196 	CleanupStack::PushL(self);
       
   197 	self->ConstructL(aUid,
       
   198 					aVersion,
       
   199 					aName,
       
   200 					aDataType,
       
   201 					aOpaqueData,
       
   202 					aDrive,
       
   203 					aRomOnly,
       
   204 					aRomBased,
       
   205 					aExtendedInterfaces);
       
   206 	CleanupStack::Pop(self);
       
   207 	return self;
       
   208 	}
       
   209 
       
   210 /**
       
   211 Constructor for CImplementationData
       
   212 @param			aParent The parent interface data of this implementation
       
   213 @post			Its member variables are initialised
       
   214 */
       
   215 CRegistryData::CImplementationData::CImplementationData( CInterfaceData* aParent):
       
   216 	CBase(),
       
   217 	iImplInfo(NULL),
       
   218 	iParent(aParent)
       
   219 	{
       
   220 	// Do nothing here
       
   221 	}
       
   222 	
       
   223 /**
       
   224 Destructor of CImplementationData
       
   225 */	
       
   226 CRegistryData::CImplementationData::~CImplementationData()
       
   227 	{
       
   228 	if(iImplInfo)
       
   229 		{
       
   230 		delete iImplInfo;
       
   231 		iImplInfo = NULL;	
       
   232 		}	
       
   233 	iParent = NULL;		
       
   234 	}
       
   235 
       
   236 /**
       
   237 The object's memory has been allocated.
       
   238 @param			aUid The unique Id of the new implementation
       
   239 @param			aVersion The version number of the new implementation
       
   240 @param			aName The display name of the new implementation
       
   241 @param			aDataType The data type supported by the new implementation
       
   242 @param			aOpaqueData Data for the new implementation which is not used by the ECom framework
       
   243 @param			aDrive The drive that the new implementation is on
       
   244 @param			aRomOnly The flag recording whether the new implementation may be loaded from ROM only
       
   245 @param			aRomBased The flag recording whether the new implementation is on ROM or is a later version of one on ROM
       
   246 @pre 			This object is fully constructed.
       
   247 @post			This object is fully constructed and initialized.
       
   248 */
       
   249 void CRegistryData::CImplementationData::ConstructL(TUid	aUid,
       
   250 													TInt	aVersion, 
       
   251 													HBufC*  aName,
       
   252 													HBufC8* aDataType,
       
   253 													HBufC8* aOpaqueData,
       
   254 													TDriveUnit aDrive,
       
   255 													TBool aRomOnly,
       
   256 													TBool aRomBased)
       
   257 	{
       
   258 	CImplementationInformation* newImpl = CImplementationInformation::NewL(aUid, 
       
   259 													 						aVersion, 
       
   260 													 						aName, 
       
   261 															 				aDataType,
       
   262 																			aOpaqueData,
       
   263 														 					aDrive,
       
   264 														 					aRomOnly,
       
   265 													 						aRomBased);
       
   266 	this->iImplInfo = newImpl;
       
   267 	}
       
   268 
       
   269 /**
       
   270 The object's memory has been allocated.
       
   271 @param			aUid The unique Id of the new implementation
       
   272 @param			aVersion The version number of the new implementation
       
   273 @param			aName The display name of the new implementation
       
   274 @param			aDataType The data type supported by the new implementation
       
   275 @param			aOpaqueData Data for the new implementation which is not used by the ECom framework
       
   276 @param			aDrive The drive that the new implementation is on
       
   277 @param			aRomOnly The flag recording whether the new implementation may be loaded from ROM only
       
   278 @param			aRomBased The flag recording whether the new implementation is on ROM or is a later version of one on ROM
       
   279 @param			aExtendedInterfaces The pointer to the array recording the extended interfaces supported by this implementation.
       
   280 				NULL is available for PLUGIN without extended interfaces support.
       
   281 @pre 			This object is fully constructed.
       
   282 @post			This object is fully constructed and initialized.
       
   283 */
       
   284 void CRegistryData::CImplementationData::ConstructL(TUid	aUid,
       
   285 													TInt	aVersion, 
       
   286 													HBufC*  aName,
       
   287 													HBufC8* aDataType,
       
   288 													HBufC8* aOpaqueData,
       
   289 													TDriveUnit aDrive,
       
   290 													TBool aRomOnly,
       
   291 													TBool aRomBased,
       
   292 													RExtendedInterfacesArray* aExtendedInterfaces)
       
   293 	{
       
   294 	CImplementationInformation* newImpl = CImplementationInformation::NewL(aUid, 
       
   295 													 						aVersion, 
       
   296 													 						aName, 
       
   297 															 				aDataType,
       
   298 																			aOpaqueData,
       
   299 														 					aDrive,
       
   300 														 					aRomOnly,
       
   301 													 						aRomBased,
       
   302 													 						aExtendedInterfaces);
       
   303 	this->iImplInfo = newImpl;
       
   304 	}
       
   305 
       
   306 /**
       
   307 Initialises member variable with the CImplementationInformation state specified in aStore.
       
   308 @param			aStore The stream to read the data from.
       
   309 @pre 			This object is full constructed.
       
   310 @post			This object is set to the state specified in aStore.
       
   311 */
       
   312 void CRegistryData::CImplementationData::InternalizeL(RReadStream& aStore)
       
   313 	{
       
   314 	if (iImplInfo)
       
   315 		{
       
   316 		delete iImplInfo;
       
   317 		iImplInfo = NULL;
       
   318 		}
       
   319 	iImplInfo=CImplementationInformation::NewLC(EFalse,aStore);
       
   320 	//as we never store the drive name we need to get this from the parent
       
   321 	iImplInfo->SetDrive(iParent->iParent->iParent->iDrive);
       
   322 	CleanupStack::Pop(1);	
       
   323 	}
       
   324 
       
   325 
       
   326 /**
       
   327 Writes out the state of this member variable of type CImplementationInformation to aStore.
       
   328 @param			aStore The stream to store the data in.
       
   329 @pre 			This object is fully constructed.
       
   330 */
       
   331 void CRegistryData::CImplementationData::ExternalizeL(RWriteStream& aStore) const
       
   332 	{
       
   333 	iImplInfo->ExternalizeL(EFalse,aStore);
       
   334 	}
       
   335 
       
   336 /**
       
   337 This method determines the order of two CImplementationData objects.
       
   338 For backward compatibility reason, ECom allows different I/Fs using
       
   339 the same implementation UID for when the device has an implementation UID
       
   340 that is not unique. Although this is not a valid or supported situation ECOM 
       
   341 server should be robust.
       
   342 @see FindImplementation
       
   343 @see CompareTUidValues
       
   344 @param			aImpl1 first reference to CImplementationData object 
       
   345 @param			aImpl2 second reference to CImplementationData object
       
   346 @return			integer indicating the order of these two
       
   347 @pre			This object is fully constructed
       
   348 */	
       
   349 TInt CRegistryData::CImplementationData::CompareImplUid(const CImplementationData& aImpl1,
       
   350 													const CImplementationData& aImpl2)
       
   351 	{
       
   352 	TInt ret = CompareTUidValues(aImpl1.iImplInfo->ImplementationUid().iUid, aImpl2.iImplInfo->ImplementationUid().iUid);
       
   353 	if (ret != 0)
       
   354 		{
       
   355 		return ret;
       
   356 		}
       
   357 
       
   358 	// Implementation UIDs are equal, use I/F UID as tie breaker
       
   359 	return CompareTUidValues(aImpl1.iParent->iInterfaceUid.iUid, aImpl2.iParent->iInterfaceUid.iUid);
       
   360 	}
       
   361 	
       
   362 /**
       
   363 Similar to CompareImplUid above. This comparer only compare the Impl UID
       
   364 and ignore the I/F UID part.
       
   365 @param			aImpl1 first reference to CImplementationData object 
       
   366 @param			aImpl2 second reference to CImplementationData object
       
   367 @return			integer indicating the order of these two
       
   368 @pre			This object is fully constructed
       
   369 */	
       
   370 TInt CRegistryData::CImplementationData::CompareImplUidIgnoreIfUid(const CImplementationData& aImpl1,
       
   371 													const CImplementationData& aImpl2)
       
   372 	{
       
   373 	return CompareTUidValues(aImpl1.iImplInfo->ImplementationUid().iUid,
       
   374 						aImpl2.iImplInfo->ImplementationUid().iUid);
       
   375 	}
       
   376 	
       
   377 /**
       
   378 This method determines the order of an CImplementationData object in relation
       
   379 to aUid.
       
   380 @param	aUid is really TUid. Cast it back before compare.
       
   381 @param	aImplData reference to CImplementationData object
       
   382 @return	integer indicating the order of the two.
       
   383 */	
       
   384 TInt CRegistryData::CImplementationData::CompareUidAgainstImplData(
       
   385 											const CImplementationData& aUid,
       
   386 											const CImplementationData& aImplData)
       
   387 	{
       
   388 	// The first argument aUid is really TUid.
       
   389 	const TUid* ImplUid = reinterpret_cast<const TUid*>(&aUid);
       
   390 	return CompareTUidValues(ImplUid->iUid,
       
   391 						aImplData.iImplInfo->ImplementationUid().iUid);
       
   392 	}
       
   393 
       
   394 //
       
   395 // CRegistryData::CInterfaceData class
       
   396 
       
   397 /**
       
   398 Creates a new CInterfaceData object and leave it on the CleanupStack
       
   399 @param			aInterface The unique Id of this interface.
       
   400 @param			aParent A pointer to the parent dll data 
       
   401 @return			A pointer to the newly created class.
       
   402 @post			This object is fully constructed and initialized and is on 
       
   403 				the CleanupStack.
       
   404 */
       
   405 CRegistryData::CInterfaceData* CRegistryData::CInterfaceData::NewLC(TUid aInterfaceUid,CDllData* aParent)
       
   406 	{
       
   407 	CInterfaceData* self=new(ELeave) CInterfaceData(aInterfaceUid,aParent);
       
   408 	CleanupStack::PushL(self);
       
   409 	self->ConstructL();
       
   410 	return self;
       
   411 	}
       
   412 
       
   413 
       
   414 /**
       
   415 Creates a new CInterfaceData object using the supplied interface id 
       
   416 and leave it on the CleanupStack
       
   417 @param			aParent A pointer to the parent dll data
       
   418 @return			A pointer to the newly created class.
       
   419 @post			This object is fully constructed and initialized and is on 
       
   420 				the CleanupStack.
       
   421 */
       
   422 CRegistryData::CInterfaceData* CRegistryData::CInterfaceData::NewLC(CDllData* aParent)
       
   423 	{
       
   424 	CInterfaceData* self=new(ELeave) CInterfaceData(aParent);
       
   425 	CleanupStack::PushL(self);
       
   426 	self->ConstructL();
       
   427 	return self;
       
   428 	}
       
   429 
       
   430 
       
   431 CRegistryData::CInterfaceData::~CInterfaceData()
       
   432 	{
       
   433 	if(iImplementations)
       
   434 		{
       
   435 		iImplementations->ResetAndDestroy();
       
   436 		delete iImplementations;
       
   437 		iImplementations = NULL;
       
   438 		}
       
   439 	iParent = NULL;
       
   440 	}
       
   441 
       
   442 /**
       
   443 Adds the specified implementation to this interface in the registry.
       
   444 @param			aImplementation The implementation to add to this interface.
       
   445 @pre			This object is fully constructed.
       
   446 @post			aImplementation is added to the list of implementations for this interface.
       
   447 */
       
   448 void CRegistryData::CInterfaceData::AddL(const CImplementationData* aImplementation)
       
   449 	{
       
   450 #ifdef ECOM_TRACE
       
   451 	static int counter = 0; counter++;
       
   452 	__ECOM_TRACE6("ECOM: Implementation discovered (%04d) UID:0x%X interfaceUID:0x%X version:%d on drive:%d \"%S\"", counter, aImplementation->iImplInfo->ImplementationUid().iUid, aImplementation->iParent->iInterfaceUid.iUid, aImplementation->iImplInfo->Version(), (TInt)(aImplementation->iImplInfo->Drive()), &(aImplementation->iImplInfo->DisplayName()));
       
   453 
       
   454 #endif
       
   455 
       
   456 	User::LeaveIfError(iImplementations->Append(aImplementation));
       
   457 	}
       
   458 
       
   459 /**
       
   460 Sets the uid of this interface to aInterfaceUid.
       
   461 @param			aInterfaceUid The Uid which this object should take.
       
   462 @pre			This object is fully constructed.
       
   463 @post			The Uid of this interface is set to aInterfaceUid
       
   464 */
       
   465 void CRegistryData::CInterfaceData::SetInterfaceUid(TUid aInterfaceUid)
       
   466 	{
       
   467 	iInterfaceUid = aInterfaceUid;
       
   468 	}
       
   469 
       
   470 /**
       
   471 Writes out this CInterfaceData to aStore.
       
   472 @param			aStore The stream to store the data in.
       
   473 @pre 			The state of this object is stored in the stream aStore.
       
   474 */
       
   475 void CRegistryData::CInterfaceData::ExternalizeL(RWriteStream& aStore) const
       
   476 	{
       
   477 	aStore.WriteInt32L(iInterfaceUid.iUid);
       
   478 
       
   479 	if(iImplementations)
       
   480 		{
       
   481 		const TInt entryCount = iImplementations->Count();
       
   482 		aStore.WriteInt32L(entryCount);
       
   483 		for(TInt i = 0; i < entryCount; ++i)
       
   484 			((*iImplementations)[i])->ExternalizeL(aStore);
       
   485 		}
       
   486 	else
       
   487 		aStore.WriteInt32L(0);
       
   488 	}
       
   489 
       
   490 /**
       
   491 Restores this CInterfaceData to the state specified in aStore.
       
   492 @param			aStore The stream to read the data from.
       
   493 @param			aPresent A boolean indicating whether the dll is still present
       
   494 @pre 			This object is full constructed.
       
   495 @post			This object is set to the state specified in aStore.
       
   496 */
       
   497 void CRegistryData::CInterfaceData::InternalizeL(RReadStream& aStore)
       
   498 	{
       
   499 	iInterfaceUid.iUid = aStore.ReadInt32L();
       
   500 
       
   501 	const TInt entryCount = aStore.ReadInt32L();
       
   502     if(entryCount < 0)
       
   503         {
       
   504         User::Leave(KErrCorrupt);
       
   505         }
       
   506 	
       
   507 	for(TInt i = 0; i < entryCount; ++i)
       
   508 		{
       
   509 		CImplementationData* implementation = CImplementationData::NewLC(this);
       
   510 		implementation->InternalizeL(aStore);
       
   511 		AddL(implementation);
       
   512 		CleanupStack::Pop(implementation);		//now owned by this interface
       
   513 		}
       
   514 	}
       
   515 
       
   516 /**
       
   517 @param			aParent A pointer to the parent dll data
       
   518 */
       
   519 CRegistryData::CInterfaceData::CInterfaceData(CDllData* aParent) :
       
   520 	CBase(),
       
   521 	iParent(aParent)
       
   522 	{
       
   523 	// Do nothing here
       
   524 	}
       
   525 
       
   526 /**
       
   527 @param			aInterfaceUid The unique Id of this interface
       
   528 @param			aParent A pointer to the parent dll data			
       
   529 */
       
   530 CRegistryData::CInterfaceData::CInterfaceData(TUid aInterfaceUid, CDllData* aParent) :
       
   531 	CBase(),
       
   532 	iInterfaceUid(aInterfaceUid),
       
   533 	iParent(aParent)
       
   534 	{
       
   535 	// Do nothing here
       
   536 	}
       
   537 
       
   538 /**
       
   539 Standard second phase construction function
       
   540 @pre 			This object is fully constructed.
       
   541 @post			This object is fully constructed and initialized.
       
   542 */
       
   543 void CRegistryData::CInterfaceData::ConstructL()
       
   544 	{
       
   545 	iImplementations = new(ELeave) RPointerArray<CImplementationData>;
       
   546 	}
       
   547 
       
   548 //
       
   549 // CRegistryData::CDllData class
       
   550 
       
   551 /**
       
   552 Creates a new CDllData object using aEntry and leaves it on the CleanupStack
       
   553 @param			aDllName the name of this dll
       
   554 @param			aDllModTime the modified time of this dll
       
   555 @param 			aSecondUid Identifies type of the DLL. (PLUGIN or PLUGIN3)
       
   556 @param  			aThirdUid Identifies a component uniquely. 	
       
   557 @param			aParent A pointer to the parent drive data
       
   558 @return			A pointer to the newly created object.
       
   559 @post			This object is fully constructed and initialized and on the CleanupStack.
       
   560 */
       
   561 CRegistryData::CDllData* CRegistryData::CDllData::NewLC(const TDesC& aDllName,const TTime& aDllModTime,const TUid& aSecondUid,const TUid& aThirdUid,CDriveData* aParent)
       
   562 	{
       
   563 	CDllData* self=new(ELeave) CDllData(aParent);
       
   564 	CleanupStack::PushL(self);
       
   565 	self->ConstructL(aDllName,aDllModTime,aSecondUid,aThirdUid);
       
   566 	return self;
       
   567 	}
       
   568 
       
   569 /**
       
   570 Creates a new CDllData object using aParent and leaves it on the CleanupStack
       
   571 @param			aParent A pointer to the parent drive data
       
   572 @return			A pointer to the newly created object.
       
   573 @post			This object is fully constructed and initialized and on the CleanupStack.
       
   574 */
       
   575 CRegistryData::CDllData* CRegistryData::CDllData::NewLC( CDriveData* aParent)
       
   576 	{
       
   577 	CDllData* self=new(ELeave) CDllData(aParent);
       
   578 	CleanupStack::PushL(self);
       
   579 	self->ConstructL();
       
   580 	return self;
       
   581 	}
       
   582 	
       
   583 CRegistryData::CDllData::~CDllData()
       
   584 	{
       
   585 	if(iIfList)
       
   586 		{
       
   587 		// Clear the interface list and destroy its objects
       
   588 		iIfList->ResetAndDestroy();
       
   589 		delete iIfList;
       
   590 		iIfList = NULL;
       
   591 		}
       
   592 
       
   593 	// Unload this implementation dll.
       
   594 	delete iDllEntry;
       
   595 	iDllEntry = NULL;
       
   596 	iParent = NULL;
       
   597 	delete iRscFileExtension;
       
   598 	}
       
   599 
       
   600 /**
       
   601 Adds the specified interface to this dll in the registry.
       
   602 @param			aInterface The interface to add to this dll
       
   603 @pre 			This object is fully constructed.
       
   604 @post			aInterface is added to the list of interfaces in this dll.
       
   605 */
       
   606 void CRegistryData::CDllData::AddL(const CInterfaceData* aInterface)
       
   607 	{
       
   608 	User::LeaveIfError(iIfList->Append(aInterface));
       
   609 	}
       
   610 
       
   611 /**
       
   612 Sets the resource extension for the plugin. Not set for read only internal drives.
       
   613 @param			aExt The resource extension to set
       
   614 @pre 			This object is fully constructed.
       
   615 @post			aExt is added to the object.
       
   616 */
       
   617 void CRegistryData::CDllData::SetResourceExtL(const TDesC& aExt)
       
   618 	{
       
   619 	delete iRscFileExtension;
       
   620 	iRscFileExtension = NULL;
       
   621 	iRscFileExtension = aExt.AllocL();
       
   622 	}
       
   623 	
       
   624 /**
       
   625 Set the capability,the VID and do the Security check for this DLL.
       
   626 @pre 			This object is fully constructed.
       
   627 @return			ETrue if the security check is done successfully. Otherwise EFalse is returned. 
       
   628 */
       
   629 TBool CRegistryData::CDllData::SaveSecurityInfoL()
       
   630 	{
       
   631 	iSecurityChecked = EFalse;
       
   632 
       
   633 	//need to construct the full filename i.e. appending with the
       
   634 	//preconstructed drivepath name in CDriveData
       
   635 	TFileName dllFullName;
       
   636 	dllFullName.Append(iParent->iDrive.Name());
       
   637 	dllFullName.Append(_L("\\sys\\bin\\"));
       
   638 	dllFullName.Append(iDllEntry->GetName());
       
   639 	RLibrary::TInfoBuf infoBuf;
       
   640 	TInt ret = RLibrary::GetInfo(dllFullName, infoBuf);
       
   641 	if(ret != KErrNone)
       
   642 		{
       
   643 		return EFalse;
       
   644 		}
       
   645 	// Set the DLL's capability
       
   646 	iCapSet = infoBuf().iSecurityInfo.iCaps;
       
   647 	// Set the DLL's VID
       
   648 	iVid = infoBuf().iSecurityInfo.iVendorId;
       
   649 	// Now verify that SID identified in the resource file matches the SID of the Dll file
       
   650 	TBool match=iDllEntry->GetThirdUid() ==infoBuf().iSecurityInfo.iSecureId;
       
   651 	if (!match)
       
   652 		{
       
   653 #ifdef __ECOM_TRACE 
       
   654 		__ECOM_TRACE1("ERROR: Plugin SID Mismatch ERROR for %S.", &dllFullName);
       
   655 #endif
       
   656 		return EFalse;
       
   657 		}
       
   658 
       
   659 	// Now verify the two DLL's second Uid are of the same Uid type (used for distinguising between collection/collection3)
       
   660 	match=iDllEntry->GetSecondUid() ==infoBuf().iUids[1];
       
   661 	if (!match)
       
   662 		{
       
   663 #ifdef __ECOM_TRACE 
       
   664 		__ECOM_TRACE1("ERROR: Plugin UID2 Mismatch ERROR for %S.", &iDllEntry->GetName());
       
   665 #endif
       
   666 		return EFalse;
       
   667 		}
       
   668 
       
   669 	// On the emulator RLoader::CheckLibraryHash() returns KErrNotSupported.
       
   670 	// Also on the emulator RLoader does no hash checking for DLL's on removable drives.
       
   671 	// Therefore to be consistent ECOM does not do any hash checking itself on the emulator.
       
   672 	// Hence code is removed for emulator builds.
       
   673 #if !defined(__WINSCW__)
       
   674 	// Verify hash is available
       
   675 	if(iParent->iParent->iCachedDriveInfo->DriveIsRemovableL(iParent->iDrive))
       
   676 		{
       
   677 		RLoader loader;
       
   678 		TInt err = loader.Connect();
       
   679 		if(err != KErrNone)
       
   680 			{
       
   681 			return EFalse;
       
   682 			}
       
   683 		err = loader.CheckLibraryHash(dllFullName, ETrue);
       
   684 		if(err != KErrNone)
       
   685 			{
       
   686 #ifdef __ECOM_TRACE 
       
   687 		__ECOM_TRACE2("INFO: Hash Check Failed for %S with error %d.", &dllFullName, err);
       
   688 #endif
       
   689 			return EFalse;
       
   690 			}
       
   691 		}
       
   692 #endif
       
   693 	iSecurityChecked = ETrue;
       
   694 	return ETrue;
       
   695 	}
       
   696 	
       
   697 /**
       
   698 Check whether security check has been performed if not go retrieve it.
       
   699 @pre 			This object is fully constructed.
       
   700 @return			ETrue if the security check is done successfully. Otherwise EFalse is returned. 
       
   701 */
       
   702 TBool CRegistryData::CDllData::ProcessSecurityCheckL()
       
   703 	{
       
   704 	if(iSecurityChecked)
       
   705 		{
       
   706 		return ETrue;
       
   707 		}
       
   708 	return SaveSecurityInfoL();
       
   709 	}
       
   710 
       
   711 
       
   712 /**
       
   713 Writes out the state of this CDllData to aStore.
       
   714 @param			aStore The stream to store the data in.
       
   715 @pre 			This object is fully constructed.
       
   716 */
       
   717 void CRegistryData::CDllData::ExternalizeL(RWriteStream& aStore) const
       
   718    	{
       
   719  	const CEComEntry& dllEntryData = *iDllEntry;
       
   720 	TInt size=dllEntryData.GetName().Length()-KDllExtensionLength;
       
   721  	aStore.WriteUint32L(size);
       
   722 	aStore.WriteL(dllEntryData.GetName(),size);
       
   723 
       
   724 	aStore.WriteInt32L(dllEntryData.GetSecondUid().iUid);	
       
   725   	aStore.WriteInt32L(dllEntryData.GetThirdUid().iUid);
       
   726     TPckg<TTime> modified(dllEntryData.GetModified());	
       
   727  	aStore.WriteL(modified);
       
   728 	
       
   729 	if(!iParent->iParent->iCachedDriveInfo->DriveIsReadOnlyInternalL(iParent->iDrive))
       
   730 		{
       
   731 		if(iRscFileExtension)
       
   732 			{
       
   733 			size = iRscFileExtension->Length();		
       
   734 			aStore.WriteUint32L(size);
       
   735 			aStore.WriteL(iRscFileExtension->Des(),size);
       
   736 			}
       
   737 		else
       
   738 			{
       
   739 			aStore.WriteUint32L(0);		
       
   740 			}
       
   741 		}
       
   742 
       
   743    	if(iIfList)
       
   744    		{
       
   745    		const TInt entryCount = iIfList->Count();
       
   746    		aStore.WriteInt32L(entryCount);
       
   747    		for(TInt i = 0; i < entryCount; ++i)
       
   748    			((*iIfList)[i])->ExternalizeL(aStore);
       
   749    		}
       
   750    	else
       
   751    		aStore.WriteInt32L(0);
       
   752 	}
       
   753 
       
   754 /**
       
   755 Restores this CDllData to the state specified in aStore.
       
   756 @param			aStore The stream to read the data from.
       
   757 @pre 			This object is fully constructed.
       
   758 @post			The state of this object is restored to that specified in aStore.
       
   759 */
       
   760 void CRegistryData::CDllData::InternalizeL(RReadStream& aStore)
       
   761  	{	
       
   762 	TInt size=aStore.ReadUint32L();
       
   763     //The next "if" checks if size < 0 not size <= 0 because it seems the ECOM server externalizes
       
   764     //the last file name as a string with length 0. If the fix is <= 0, then it makes it
       
   765     //incompatible with the existing applications
       
   766     if(size < 0 || size > KMaxFileName)
       
   767         {
       
   768         User::Leave(KErrCorrupt);
       
   769         }
       
   770 	HBufC* name = HBufC::NewLC(size+KDllExtensionLength);
       
   771 	TPtr ptr=name->Des();
       
   772 	aStore.ReadL(ptr,size);
       
   773 	ptr.Append(KDllExtension);
       
   774 
       
   775   	TUid secondUid=TUid::Uid(aStore.ReadInt32L());
       
   776   	TUid thirdUid=TUid::Uid(aStore.ReadInt32L());
       
   777   	TTime dllModifiedTime;  	
       
   778    	TPckg<TTime> modified(dllModifiedTime);	
       
   779  	aStore.ReadL(modified);
       
   780 
       
   781 	if(!iParent->iParent->iCachedDriveInfo->DriveIsReadOnlyInternalL(iParent->iDrive))
       
   782 		{
       
   783 		size = aStore.ReadUint32L();
       
   784 		if(size < 0 || size > KMaxFileName)
       
   785 		        {
       
   786        		 User::Leave(KErrCorrupt);
       
   787        		 }
       
   788 		if(size)
       
   789 			{
       
   790 			iRscFileExtension = HBufC::NewL(size);
       
   791 			TPtr extPtr = iRscFileExtension->Des();
       
   792 			aStore.ReadL(extPtr,size);
       
   793 			}
       
   794 		}
       
   795 	
       
   796    	const TInt entryCount = aStore.ReadInt32L();
       
   797 	if(entryCount < 0)
       
   798 		{
       
   799 		User::Leave(KErrCorrupt);
       
   800 		}
       
   801 	
       
   802    	// Security check is deferred until the DLL is needed.
       
   803 	for(TInt i = 0; i < entryCount; ++i)
       
   804 	   	{
       
   805 	   	CInterfaceData* interface = CInterfaceData::NewLC(this);
       
   806 		interface->InternalizeL(aStore);
       
   807 		AddL(interface);
       
   808 	   	CleanupStack::Pop(interface);	// now owned by dll	
       
   809 		}  	
       
   810 	iDllEntry = CEComEntry::NewL(*name,secondUid,thirdUid);
       
   811 	iDllEntry->SetModified(dllModifiedTime);
       
   812  	CleanupStack::PopAndDestroy(name);
       
   813 	}
       
   814 	
       
   815 /**
       
   816 @param			aParent The parent drive data of this implementation
       
   817 */	
       
   818 CRegistryData::CDllData::CDllData( CDriveData* aParent) :
       
   819 	CBase(),
       
   820 	iParent(aParent)	
       
   821 	{
       
   822 	// Do nothing here
       
   823 	//Initialize empty capabilities here
       
   824 	iCapSet.SetEmpty();
       
   825 	}
       
   826 
       
   827 /**
       
   828 Standard second phase construction function.
       
   829 @pre 			This object is fully constructed.
       
   830 @post			This object is fully constructed and initialized.
       
   831 */
       
   832 void CRegistryData::CDllData::ConstructL()
       
   833 	{
       
   834 	iIfList = new(ELeave) RInterfaceList(2);
       
   835 	}
       
   836 
       
   837 /**
       
   838 Standard second phase construction function with parameter.
       
   839 @param			aDllName the name of this dll
       
   840 @param			aDllModTime the modified time of this dll
       
   841 @param 			aSecondUid Distinguishes between components having the same UID1 (which distinguishes between EXEs and DLLs) 
       
   842 				UID2 identifies Interface Implementation Collections (collection and collection 3)
       
   843 @param			aThirdUid Identifies a component uniquely. In order to ensure that each binary that needs a distinguishing 
       
   844 				UID is assigned a genuinely unique value. Symbian manages UID allocation through central database.	
       
   845 @pre 			This object is fully constructed.
       
   846 @post			This object is fully constructed and initialized.
       
   847 */
       
   848 void CRegistryData::CDllData::ConstructL(const TDesC& aDllName,const TTime& aDllModTime,const TUid& aSecondUid,const TUid& aThirdUid)
       
   849 	{
       
   850 	iIfList = new(ELeave) RInterfaceList(2);
       
   851 	iDllEntry=CEComEntry::NewL(aDllName,aSecondUid,aThirdUid);
       
   852 	iDllEntry->SetModified(aDllModTime);
       
   853 	}
       
   854 	
       
   855 	
       
   856 /**
       
   857 Populate a caller-supplied TEntry instance with the data from this dll.
       
   858 @param			aEntry An entry to be populated (destination)
       
   859 */
       
   860 void CRegistryData::CDllData::PopulateAnEntry(TEntry& aEntry) const
       
   861 	{
       
   862 	TPtr bufPtr=aEntry.iName.Des();
       
   863 	bufPtr.Zero();
       
   864 	bufPtr.Append(iParent->iDrive.Name());
       
   865 	bufPtr.Append(_L("\\sys\\bin\\"));
       
   866 	bufPtr.Append(iDllEntry->GetName());
       
   867 	aEntry.iType	= TUidType(KDynamicLibraryUid,iDllEntry->GetSecondUid(),iDllEntry->GetThirdUid());
       
   868 	aEntry.iModified= iDllEntry->GetModified();
       
   869 	}
       
   870 
       
   871 
       
   872 //
       
   873 // CRegistryData::CDriveData class
       
   874 
       
   875 
       
   876 /**
       
   877 Creates a new CDriveData object and places it on the CleanupStack
       
   878 @param			aDrive Information on this drive
       
   879 @param			aParent A pointer to the parent registry data
       
   880 @return			A pointer to the newly created class.
       
   881 @post			This object is fully constructed and initialized and on the CleanupStack.
       
   882 */
       
   883 CRegistryData::CDriveData* CRegistryData::CDriveData::NewLC(TDriveUnit aDrive, CRegistryData* aParent)
       
   884 	{
       
   885 	CDriveData* self=new(ELeave) CDriveData(aDrive,aParent);  // calls c'tor
       
   886 	CleanupStack::PushL(self);	// Make the construction safe by using the cleanup stack
       
   887 	self->ConstructL(); // Complete the 'construction'.
       
   888 	return self;
       
   889 	}
       
   890 
       
   891 /**
       
   892 Destructor of CDriveData
       
   893 */
       
   894 CRegistryData::CDriveData::~CDriveData()
       
   895 	{
       
   896 	if(iDllList)
       
   897 		{
       
   898 		// Clear the interface list and destroy its objects
       
   899 		iDllList->ResetAndDestroy();
       
   900 		delete iDllList;
       
   901 		iDllList = NULL;
       
   902 		}
       
   903 	iParent=NULL;
       
   904 	}
       
   905 
       
   906 /**
       
   907 Adds the specified CDllData to this drive data in the registry.
       
   908 @param			aDll The Dll to add to this drive
       
   909 @pre 			This object is fully constructed.
       
   910 @post			aDll is added to the list of dll on this drive.
       
   911 */
       
   912 void CRegistryData::CDriveData::AddL(const CDllData* aDll)
       
   913 	{
       
   914 	User::LeaveIfError(iDllList->Append(aDll));
       
   915 	}
       
   916 
       
   917 /**
       
   918 Returns the index of the DLL with this Uid in the Dll list.
       
   919 @param			aDllUid the UID of to be found DLL.
       
   920 @return  		The index of this DLL in the DLL list. KErrNotFound if not found.
       
   921 @pre			This object is fully constructed.
       
   922 */
       
   923 TInt CRegistryData::CDriveData::FindDllIndex(const TUid aDllUid) const
       
   924 	{
       
   925 	const TInt dllCount = iDllList->Count();
       
   926 	for(TInt j = 0; j < dllCount; ++j)
       
   927 		{
       
   928 		// For each dll structure check the dll UID
       
   929 		CDllData* dll = (*iDllList)[j];
       
   930 		if (aDllUid == dll->iDllEntry->GetThirdUid())
       
   931 			{
       
   932 			// it is a match 
       
   933  			return j;	 				
       
   934 			}
       
   935 		}
       
   936 	return KErrNotFound;
       
   937 	}
       
   938 	
       
   939 /**
       
   940 Writes out the state of this CDriveData to file.
       
   941 @param			aFs A handle to an open file server session.
       
   942 @param			aDatFileName the dat file to persist to
       
   943 @pre 			This object is fully constructed.
       
   944 */
       
   945 void CRegistryData::CDriveData::ExternalizeL(RFs& aFs,const TDesC& aDatFileName) 
       
   946 	{
       
   947 	// attempt to create the folders if they don't already exist
       
   948 	TInt mkDirError = aFs.MkDirAll(aDatFileName);
       
   949 		
       
   950 	if((mkDirError == KErrNone) || (mkDirError == KErrAlreadyExists))
       
   951 		{
       
   952 		RFileWriteStream registryStream;
       
   953 		if(registryStream.Replace(aFs,aDatFileName, EFileWrite) == KErrNone)
       
   954 			{
       
   955 			CleanupClosePushL(registryStream);
       
   956 			// Write the version number as the first thing in the file stream.
       
   957 			registryStream.WriteInt32L(KRegVersion);				
       
   958 			if(iDllList)
       
   959 				{
       
   960 				TInt entryCount = iDllList->Count();
       
   961 				registryStream.WriteInt32L(entryCount);
       
   962 				// Now stream out the data
       
   963 				for(TInt i = 0; i < entryCount; ++i)
       
   964 					((*iDllList)[i])->ExternalizeL(registryStream);
       
   965 				}
       
   966 			else
       
   967 				registryStream.WriteInt32L(0);
       
   968 			CleanupStack::PopAndDestroy();	// registryStream
       
   969 			}
       
   970 		}
       
   971 	else
       
   972 		{
       
   973 		User::Leave(mkDirError);
       
   974 		}
       
   975 	}
       
   976 
       
   977 /**
       
   978 Restores the state of this CDriveData from file.
       
   979 @param			aFs A handle to an open file server session.
       
   980 @param			aDatFileName the dat file name to internalize from
       
   981 @pre 			This object is fully constructed.
       
   982 @post			The state of this object is restored to that specified
       
   983 				in the file on this drive.
       
   984 */
       
   985 
       
   986 void CRegistryData::CDriveData::InternalizeL(RFs& aFs,const TDesC& aDatFileName)
       
   987 	{
       
   988 	DoInternalizeL(aFs, aDatFileName);  
       
   989 	}
       
   990 /**
       
   991 The method internalizes the data from aRegistryStream.
       
   992 @param aFileName The ECOM registry file name.
       
   993 @leave KErrNoMemory
       
   994 @leave Some other system-wide error codes as well.
       
   995 */
       
   996 void CRegistryData::CDriveData::DoInternalizeL(RFs& aFs, const TDesC& aFileName)
       
   997 	{
       
   998 	RFileReadStream registryStream;
       
   999 	User::LeaveIfError(registryStream.Open(aFs, aFileName, EFileRead));
       
  1000 	CleanupClosePushL(registryStream);	
       
  1001 	// Read in version number. If its not what expected - the file is treated as corrupted.
       
  1002 	const TInt version = registryStream.ReadInt32L();
       
  1003 	if(version != KRegVersion)
       
  1004 		{
       
  1005 		User::Leave(KErrCorrupt);
       
  1006 		}	
       
  1007 	const TInt entryCount = registryStream.ReadInt32L();
       
  1008     if(entryCount < 0)
       
  1009         {
       
  1010         User::Leave(KErrCorrupt);
       
  1011         }
       
  1012 	for(TInt i = 0; i < entryCount; ++i)
       
  1013 		{
       
  1014 		CDllData* dll = CDllData::NewLC(this);
       
  1015 		dll->InternalizeL(registryStream);
       
  1016 		// always add the DLL, DLL security check will be deferred 
       
  1017 		// until the DLL is needed.		
       
  1018 		AddL(dll);
       
  1019 		CleanupStack::Pop(dll);	// now owned by drive	
       
  1020 		}
       
  1021 	CleanupStack::PopAndDestroy();//registryStream
       
  1022 	}
       
  1023 	
       
  1024 /**	
       
  1025 Constructor for CDriveData
       
  1026 @param			aDrive Information on this drive
       
  1027 @param			aParent A pointer to the parent registry data
       
  1028 */	
       
  1029 CRegistryData::CDriveData::CDriveData(TDriveUnit aDrive, CRegistryData* aParent) :
       
  1030 	CBase(), 
       
  1031 
       
  1032 	iDrive(aDrive),
       
  1033 	iParent(aParent),
       
  1034 	iDriveChanged(ETrue),
       
  1035 	iRegistryChanged(EFalse)
       
  1036 	{
       
  1037 	}
       
  1038 
       
  1039 /**
       
  1040 Standard second phase construction function.
       
  1041 @pre 			This object is fully constructed.
       
  1042 @post			This object is fully constructed and initialized.
       
  1043 */
       
  1044 void CRegistryData::CDriveData::ConstructL()
       
  1045 	{
       
  1046 	iDllList = new(ELeave)TDll;
       
  1047 	}
       
  1048 	
       
  1049 //
       
  1050 // CRegistryData class
       
  1051 
       
  1052 /**
       
  1053 Standardized safe construction which leaves nothing on the cleanup stack.
       
  1054 This overload is used by CEComImplIndexPerfTest which plots 
       
  1055 discovery time vs. granularity settings.
       
  1056 @leave 			KErrNoMemory.	
       
  1057 @param 			aFs The open file session.
       
  1058 @param			aInterfaceImplIndexGranularity granularity of main index.
       
  1059 @param			aImplIndexGranularity granularity of auxiliary index.
       
  1060 @return			The newly created instance of the registry data.
       
  1061 @post			CRegistryData is fully constructed, and initialized.
       
  1062 */
       
  1063 CRegistryData* CRegistryData::NewL(RFs& aFs, TInt aInterfaceImplIndexGranularity, TInt aImplIndexGranularity)
       
  1064 	{
       
  1065 	CRegistryData* self=new(ELeave) CRegistryData(aFs, aInterfaceImplIndexGranularity, aImplIndexGranularity);  // calls c'tor
       
  1066 	CleanupStack::PushL(self);	// Make the construction safe by using the cleanup stack
       
  1067 	self->ConstructL(); // Complete the 'construction'.
       
  1068 	CleanupStack::Pop(self);
       
  1069 	return self;
       
  1070 	}
       
  1071 
       
  1072 /**
       
  1073 Standardized safe construction which leaves nothing on the cleanup stack.
       
  1074 This overload uses default granularities for the two indexes. These
       
  1075 default values were found to provide reasonably good performance at
       
  1076 the time of testing.
       
  1077 @leave 			KErrNoMemory.	
       
  1078 @param 			aFs The open file session.
       
  1079 @return			The newly created instance of the registry data.
       
  1080 @post			CRegistryData is fully constructed, and initialized.
       
  1081 */
       
  1082 CRegistryData* CRegistryData::NewL(RFs& aFs)
       
  1083 	{
       
  1084 	return NewL(aFs, KDefaultInterfaceImplIndexGranularity, KDefaultImplIndexGranularity);
       
  1085 	}
       
  1086 
       
  1087 CRegistryData::~CRegistryData()
       
  1088 	{
       
  1089 	for(TInt index = 0; index < iInterfaceImplIndex.Count(); ++index)
       
  1090 		{
       
  1091 		iInterfaceImplIndex[index].Reset();
       
  1092 		}
       
  1093 	iInterfaceImplIndex.Reset();
       
  1094 	
       
  1095 	// Reset only. It does not own the pointers!
       
  1096 	iImplIndex.Reset();
       
  1097 
       
  1098 	if(iRegistrations)
       
  1099 		{
       
  1100 		iRegistrations->ResetAndDestroy();
       
  1101 		delete iRegistrations;
       
  1102 		iRegistrations = NULL;
       
  1103 		}
       
  1104 	// reset the cached language settings
       
  1105 	RDowngradePath::Reset();
       
  1106 
       
  1107 	delete iCachedDriveInfo;
       
  1108 	}
       
  1109 
       
  1110 /**
       
  1111 Lists the implementations given the interface UID. The filtered list is returned in the client provided
       
  1112 RImplDataArray parameter.
       
  1113 @param			aInterfaceUid The Uid of the interface which the implementations should provide
       
  1114 @param			aImplementationData Return value. The filtered list.
       
  1115 */
       
  1116 void CRegistryData::ListImplementationsL(TUid aInterfaceUid,
       
  1117 										 RImplDataArray& aImplementationData) const
       
  1118 	{
       
  1119 	// If discoveries are taking place then the index is invalid so we cannot do
       
  1120 	// this request
       
  1121 	if(iCurrentlyDiscovering)
       
  1122 		User::Leave(KEComErrListCurrentlyUnavailable);
       
  1123     
       
  1124 	TBool securityPassed = EFalse;
       
  1125 	//Do the security check
       
  1126 	TInt index = 0;
       
  1127 	while (!securityPassed)
       
  1128 		{
       
  1129 		aImplementationData.Reset();
       
  1130 		index = IndexedFind(aInterfaceUid);
       
  1131 		if(index == KErrNotFound)
       
  1132 			{
       
  1133 			User::Leave(KEComErrNoInterfaceIdentified);
       
  1134 			}
       
  1135 		User::LeaveIfError(index);
       
  1136 	
       
  1137 		TImplContainerArray& implementationList = iInterfaceImplIndex[index].iImpData;
       
  1138 		for (TInt j = 0; j < implementationList.Count(); j++)
       
  1139 			{
       
  1140 			CImplementationData* currentImplementation = implementationList[j].iCurrentImpl;
       
  1141 			CDllData* dll = currentImplementation->iParent->iParent;
       
  1142 			
       
  1143 			securityPassed = dll->ProcessSecurityCheckL();
       
  1144 			if(!securityPassed)
       
  1145 				{
       
  1146 				// remove the implementations of the DLL from iInterfaceImplIndex
       
  1147 				// and remove the DLL from its parent DLL list.
       
  1148 				DeleteDllL(dll);
       
  1149 				delete dll;
       
  1150 				dll = NULL;
       
  1151 				// don't continue processing implementations after we have deleted the DLL
       
  1152 				// because the implementations list will have changed, so we need to 
       
  1153 				// re-do the IndexedFind
       
  1154 				break;	
       
  1155 				}
       
  1156 			else
       
  1157 				{
       
  1158 				User::LeaveIfError(aImplementationData.Append(currentImplementation));
       
  1159 				}	
       
  1160 			}
       
  1161 		}
       
  1162 	}
       
  1163 
       
  1164 /**
       
  1165 Enables or disables the specified interface implementation within the registry.
       
  1166 @param			aImplementationUid The interface implementation to change.
       
  1167 @param			aState ETrue to enable the implementation, EFalse to disable it
       
  1168 @return			KErrNone, KEComErrEnableFailed or KEComErrDisableFailed
       
  1169 @pre 			CRegistry is fully constructed,
       
  1170 @post			The implementation is now enabled or disabled as described 
       
  1171 				by aState.
       
  1172 */
       
  1173 TInt CRegistryData::SetEnabledState(TUid aImplementationUid, TBool aState)
       
  1174 	{
       
  1175 	CImplementationData* impData = NULL;
       
  1176 	TUid dummy={0x00000000};
       
  1177 	
       
  1178 	(void)FindImplementation(aImplementationUid, dummy, impData);
       
  1179 
       
  1180 	if(impData != NULL)
       
  1181 		{
       
  1182 		impData->iImplInfo->SetDisabled((aState) ? EFalse : ETrue);
       
  1183 		return KErrNone;
       
  1184 		}
       
  1185 
       
  1186     return (aState) ? KEComErrEnableFailed : KEComErrDisableFailed;
       
  1187 	}
       
  1188 
       
  1189 
       
  1190 /**
       
  1191 Temporarily uninstalls the interface implementation groups upon the specified drive.
       
  1192 (ie this can be undone later).
       
  1193 @param			aDrive	The identifier of the drive to uninstall.
       
  1194 @pre 			CRegistry is fully constructed
       
  1195 @post			The registered implementation groupings
       
  1196 				stored upon the specified drive are no 
       
  1197 				longer available for use.
       
  1198 */
       
  1199 void CRegistryData::TemporaryUninstallL(const TDriveUnit& aDrive)
       
  1200 	{
       
  1201 	// Find the appropriate drive entry and remove it...
       
  1202 	// Note : the drive may have already been taken offline, so no save is possible!
       
  1203 	CDriveData* drive = NULL;
       
  1204 	TInt driveIndex = FindDriveL(aDrive, drive);
       
  1205 	if(driveIndex != KErrNotFound)
       
  1206 		{
       
  1207     	TInt dllIndex = drive->iDllList->Count();
       
  1208 		while(dllIndex > 0)
       
  1209 			{
       
  1210 			--dllIndex;
       
  1211 			RemoveFromIndexL((*drive->iDllList)[dllIndex]);
       
  1212 			}       
       
  1213 		iRegistrations->Remove(driveIndex);
       
  1214 		delete drive;
       
  1215 
       
  1216 		DriveChanged(aDrive, ETrue);
       
  1217 		}
       
  1218 	// The flag iRegistryChanged has been moved to each drive.
       
  1219 	}
       
  1220 
       
  1221 /**
       
  1222 Undoes a temporary uninstall of the interface 
       
  1223 implementation groups upon the specified drive.
       
  1224 (ie this can be undone later).
       
  1225 @leave			KErrNoMemory, KErrReinstallFailed.
       
  1226 @param			aDrive	The identifier of the drive to reinstate.
       
  1227 @pre 			CRegistry is fully constructed
       
  1228 @post			The registered implementation groupings
       
  1229 				stored upon the specified drive are again 
       
  1230 				made available for use.
       
  1231 */
       
  1232 void CRegistryData::UndoTemporaryUninstallL(const TDriveUnit& aDrive)
       
  1233 	{
       
  1234 	CDriveData* driveData = NULL;
       
  1235 	// If the drive was not found then install it, otherwise do nothing because it
       
  1236 	// is already there.  NB. We could leave here but the problem with that is the 
       
  1237 	// use case where the drive has been mounted during registry load but the registrar 
       
  1238 	// is started afterwards, and makes calls to this method as it discovers drives 
       
  1239 	// for the first time. 
       
  1240 	if(FindDriveL(aDrive, driveData) == KErrNotFound)
       
  1241 		{
       
  1242 		// Add the drive entry
       
  1243 		CDriveData* drive = CDriveData::NewLC(aDrive,this);
       
  1244 		AddImplDataL(drive);
       
  1245 		User::LeaveIfError(iRegistrations->Append(drive));
       
  1246 		CleanupStack::Pop(drive);		// now owned by iRegistrations
       
  1247 
       
  1248 		DriveChanged(aDrive, EFalse);
       
  1249 
       
  1250 		// NB We DO need to set iRegistryChanged = ETrue because the idx file needs to be
       
  1251 		// rewritten to include the reinstalled drive
       
  1252 		}
       
  1253 	}
       
  1254 	
       
  1255 /** 
       
  1256 Update the staus of drives in the system
       
  1257 @param 	aDrive The drive that has changed
       
  1258 @param 	aDriveRemoved Indicates whether a drive has been removed or added
       
  1259 @pre 	CRegistry is fully constructed.
       
  1260 @post	The state of the drive has been stored
       
  1261 */
       
  1262 void CRegistryData::DriveChanged(const TDriveUnit& aDrive, TBool aDriveRemoved)
       
  1263 	{
       
  1264 	if(aDriveRemoved)
       
  1265 		{
       
  1266 		iRemovedDrives |= (0x1 << aDrive);
       
  1267 		}
       
  1268 	else
       
  1269 		{
       
  1270 		iRemovedDrives &= ~(0x1 << aDrive);
       
  1271 		}
       
  1272 	}
       
  1273 
       
  1274 /** 
       
  1275 Find if any Dll is regsitered in the drive unit.
       
  1276 @param aDrive The identifier of the drive to find if any Dll is registered.
       
  1277 @return ETrue if any Dll is registered in the drive, otherwise EFalse.
       
  1278 @pre 			CRegistry is fully constructed.
       
  1279 @post			If any Dll is registered in the drive is returned if successfully.
       
  1280 */
       
  1281 TBool CRegistryData::IsAnyDllRegisteredWithDriveL(const TDriveUnit& aDrive)const
       
  1282 	{
       
  1283 	CDriveData* driveData = NULL;
       
  1284 	if(FindDriveL(aDrive, driveData) == KErrNotFound)
       
  1285 		{
       
  1286 		User::Leave(KEComErrDriveNotFound);	
       
  1287 		}
       
  1288 	return driveData->iDllList->Count() > 0;
       
  1289 	}
       
  1290 	
       
  1291 /**
       
  1292 Determine if the specified implementation grouping already registered, but needs an update.
       
  1293 @param			aDllUid The interface implementation collection data to add. 
       
  1294 				CRegistryData takes ownership of this object
       
  1295 				so it should not be on the CleanupStack.
       
  1296 @param			aModified The date of the last modification of the Interface 
       
  1297 				Implementation Collection. 
       
  1298 @param			aUpdate An output to indicate if the registry entry requires an update. 
       
  1299 				(Only valid if the return is ETrue).
       
  1300 @param			aDriveData The drive data used to find DLL.
       
  1301 @return			ETrue if the Interface Implementation Collection already has a registry entry.
       
  1302 				EFalse otherwise.
       
  1303 @pre 			This object is fully constructed and there is also a valid drive entry
       
  1304 				in the registry for aDrive
       
  1305 @post			The new data is added to the registry
       
  1306 */
       
  1307 TBool CRegistryData::IsRegisteredWithDate (TUid aDllUid, 
       
  1308 										   	const TTime& aModified, 
       
  1309 										   	TBool& aUpdate, 
       
  1310 										   	CDriveData* aDriveData)
       
  1311 	{
       
  1312 	// Find the appropriate drive entry for this 
       
  1313 	// Interface Implementation Collection
       
  1314 	TBool found = EFalse;
       
  1315 	TInt index = aDriveData->FindDllIndex(aDllUid);
       
  1316 	if(index != KErrNotFound)
       
  1317 		{
       
  1318 		TDll* dllList = aDriveData->iDllList;
       
  1319 		CDllData* dll = (*dllList)[index];
       
  1320 		const CEComEntry& dllEntry =*(dll->iDllEntry);	
       
  1321 		aUpdate = dllEntry.GetModified().Int64() < aModified.Int64(); 
       
  1322 		found = ETrue;
       
  1323 		}
       
  1324 	return found;
       
  1325 	}
       
  1326 
       
  1327 /**
       
  1328 Adds data on a specific dll to the registry. The data to be added
       
  1329 is parsed by CRegistryParser.
       
  1330 @leave			KErrNoMemory If the item could not be appended to the registry
       
  1331 @leave			KEComErrDriveNotFound If aDrive is not a valid drive
       
  1332 @param			aDrive The drive the registry data has been found on 
       
  1333 @param			aFoundDriveIndex The index of the registry data for the drive 
       
  1334 				the interface implementation collection data has been found on.
       
  1335 @param			aDllData The dll data to add. CRegistryData takes ownership of this object
       
  1336 				so it should not be on the CleanupStack.
       
  1337 @pre 			This object is fully constructed and there is also a valid drive entry
       
  1338 				in the registry for aDrive
       
  1339 @post			The new data is added to the registry
       
  1340 */
       
  1341 void CRegistryData::AddDllDataL(const TDriveUnit& aDrive, TInt aFoundDriveIndex, CRegistryData::CDllData* aDllData)
       
  1342 	{
       
  1343 	const TInt regCount = iRegistrations->Count();
       
  1344 	if(regCount == 0)
       
  1345 		User::Leave(KEComErrDriveNotFound);
       
  1346 
       
  1347 	// Find the appropriate drive entry
       
  1348 	CDriveData* drive = NULL;
       
  1349 	if(aFoundDriveIndex == KErrNotFound)
       
  1350 		{
       
  1351 		if(FindDriveL(aDrive, drive) == KErrNotFound)
       
  1352 			User::Leave(KEComErrDriveNotFound);
       
  1353 		}
       
  1354 	else
       
  1355 		drive = (*iRegistrations)[aFoundDriveIndex];
       
  1356 	
       
  1357 	// Append the new data to the list
       
  1358 	TDll* dllList = drive->iDllList;
       
  1359 	
       
  1360 	// NOTE : This function MUST NOT leave after the following line because 
       
  1361 	// aDllData will potentially be 'owned' in two places (dllList and the caller) 
       
  1362 	// until we return and the caller can Pop.
       
  1363 	TBool checkNeeded = ETrue;
       
  1364 	TInt ifListCount=aDllData->iIfList->Count();
       
  1365 	for(TInt ifListCounter=0; ifListCounter < ifListCount; ifListCounter++)
       
  1366 		{
       
  1367 		// For each interface structure
       
  1368 		CInterfaceData* interface = (*aDllData->iIfList)[ifListCounter];
       
  1369 		for(TInt impNum = 0; impNum < interface->iImplementations->Count(); ++impNum)
       
  1370 			{
       
  1371 			CImplementationData* implData = (*interface->iImplementations)[impNum];
       
  1372 			if(!InsertIntoIndexL(implData,checkNeeded))
       
  1373 				{
       
  1374 				interface->iImplementations->Remove(impNum); //remove from implementation array
       
  1375 				delete implData; //delete object
       
  1376 				}	
       
  1377 			}
       
  1378 		}
       
  1379 	//add filtered list for legitimate implementations into registry
       
  1380 	User::LeaveIfError(dllList->Append(aDllData)); 
       
  1381 		
       
  1382 	drive->iRegistryChanged = ETrue;	
       
  1383 	}
       
  1384 
       
  1385 /**
       
  1386 Updates the data for a dll in the registry.
       
  1387 @leave			KErrNoMemory If the indexes cannot be rebuilt
       
  1388 @param			aFoundDriveIndex The index of the registry data for the drive 
       
  1389 				the interface implementation collection data has been found on.
       
  1390 @param			aDllData The updated interface implementation collection data. 
       
  1391 				CRegistryData takes ownership of this object
       
  1392 				so it should not be on the CleanupStack.
       
  1393 @pre 			This object is fully constructed
       
  1394 @post			The dll data is updated in the registry
       
  1395 */
       
  1396 void CRegistryData::UpdateDllDataL(const TDriveUnit& aDrive,TInt aFoundDriveIndex, CDllData* aDllData)
       
  1397 	{
       
  1398 	const TInt regCount = iRegistrations->Count();
       
  1399 	if(regCount == 0)
       
  1400 		User::Leave(KEComErrDriveNotFound);
       
  1401 
       
  1402 	// Find the appropriate drive entry
       
  1403 	CDriveData* drive = (*iRegistrations)[aFoundDriveIndex];
       
  1404 	
       
  1405 	TInt index = drive->FindDllIndex(aDllData->iDllEntry->GetThirdUid());
       
  1406 	
       
  1407 	// find the dll entry and clear that too
       
  1408 	if(index != KErrNotFound)
       
  1409 		{
       
  1410 		// Ok its a match, so remove this registry entry and call AddDllData()
       
  1411 		//to add the new dll
       
  1412 		TDll* dllList = drive->iDllList;
       
  1413 		CDllData* olddll = (*dllList)[index];
       
  1414 		//remove 'old'implementations from iInterfaceImplIndex
       
  1415  		RemoveFromIndexL(olddll);
       
  1416  		//now remove old dll from the array and registry
       
  1417  		dllList->Remove(index);
       
  1418    		delete olddll;
       
  1419    		AddDllDataL(aDrive,aFoundDriveIndex,aDllData);
       
  1420    		drive->iRegistryChanged = ETrue;
       
  1421 
       
  1422 		}
       
  1423 	if (index == KErrNotFound)
       
  1424 	    {
       
  1425         __ECOM_TRACE("ECOM: PANIC in CRegistryData::UpdateDllDataL(), expected DLL data missing from ECOM registry");
       
  1426 	    __ASSERT_DEBUG(EFalse, User::Panic (KEComServerPanicCategory, EEComPanic_CRegistryData_UpdateDllDataL_DllRegistrationMissing));
       
  1427 	    }
       
  1428 	}
       
  1429 
       
  1430 /**
       
  1431 The cue that newly discovered Dlls are about to be registered, 
       
  1432 and, therefore, the registry index will be out of date until 
       
  1433 DiscoveriesCompleteL is called.
       
  1434 @pre 			CRegistrar is fully constructed
       
  1435 @post			iCurrentlyDiscovering is set and the index list is cleared.
       
  1436 */
       
  1437 void CRegistryData::DiscoveriesBeginning() const
       
  1438 	{
       
  1439 	iCurrentlyDiscovering = ETrue;
       
  1440 	// The registry is about to start changing so the index is now invalid
       
  1441 	}
       
  1442 
       
  1443 /**
       
  1444 The cue to rebuild the registry indexes
       
  1445 @leave			KErrNoMemory
       
  1446 @see 			CStore
       
  1447 @param			aSuccessful Indicates whether discovery completed fully or not
       
  1448 @param			aProcessingType indicates the type of processing for plugins
       
  1449 				for ensuring that plugins are not processed multiple times
       
  1450 				during start-up phase
       
  1451 @param			aHasRegistryChanged The flag to indicate whether registry data has been changed 
       
  1452 @pre 			CRegistrar is fully constructed
       
  1453 @post			The internal access indexes have been rebuilt
       
  1454 */
       
  1455 void CRegistryData::DiscoveriesCompleteL(TBool aSuccessful, TPluginProcessingTypeIdentifier aProcessingType, TBool& aHasRegistryChanged)
       
  1456 	{
       
  1457 	iCurrentlyDiscovering = EFalse;
       
  1458 	if (!aSuccessful)
       
  1459 		{
       
  1460 		return;
       
  1461 		}
       
  1462 	//if the rediscovery is a result of iLanguageChanged, we should reset it to false
       
  1463 	iLanguageChanged=EFalse;		
       
  1464 	// Warning: this method may be called from the CEComServer destructor.
       
  1465 	// E.g. ecomservertest running OOM test on CEComServer::NewLC.
       
  1466 	// The call stack: 
       
  1467 	// ~CEComServer delete iRegistrar, ~CRegistrar delete iDiscoverer,
       
  1468 	// ~CDiscoverer calls CRegistrar::DiscoveriesComplete,
       
  1469 	// then here.
       
  1470     // Hence if ! aSuccessful do not validate.
       
  1471 
       
  1472 	if(aProcessingType != EPluginProcessingTypeCriticalOnly)
       
  1473 		{
       
  1474 		ValidateRegistryL();
       
  1475 		}
       
  1476 	if(aProcessingType==EPluginProcessingTypeNonCriticalOnly || aProcessingType==EPluginProcessingTypeAll)
       
  1477 		{
       
  1478 		//first find whether there is any registry data changed
       
  1479 		TInt regCount=iRegistrations->Count();
       
  1480 		for(TInt i = 0; i <regCount; i++)
       
  1481 			{
       
  1482 			if ((*iRegistrations)[i]->iRegistryChanged)
       
  1483 				{
       
  1484 	 			aHasRegistryChanged = ETrue;
       
  1485 	 			//now having cached that the registry has changed we need
       
  1486 	 			//to reset this flag in ALL the CDriveData, note that it is
       
  1487 	 			//possible that more than one drive will have the flag set
       
  1488 	 			(*iRegistrations)[i]->iRegistryChanged=EFalse;
       
  1489 				}
       
  1490 			}
       
  1491 			//Also indicate registry change if any drives have been removed
       
  1492 			aHasRegistryChanged |= (iRemovedDrives != 0);
       
  1493 			iRemovedDrives = 0;
       
  1494 		}
       
  1495 	}
       
  1496 
       
  1497 /**
       
  1498 	@fn 			SetDiscoveryFlag(const TDriveUnit aDrive)
       
  1499 	Intended Usage	: Set the flag to indicate the drive has change(s)
       
  1500 	Error Condition	: None.
       
  1501 	@param 			aDrive The identifier of the drive changed.
       
  1502 	@pre 			The CRegistrar must be fully constructed
       
  1503 	@post			The flag is set.				 
       
  1504 */
       
  1505 
       
  1506 void CRegistryData::SetDiscoveryFlagL(const TDriveUnit& aDriveUnit)
       
  1507 	{
       
  1508 	CDriveData* drive = NULL;
       
  1509 	TInt driveIndex = FindDriveL(aDriveUnit, drive);
       
  1510 	if(driveIndex != KErrNotFound)
       
  1511 		{
       
  1512 		drive->iDriveChanged = ETrue;
       
  1513 		}
       
  1514 	
       
  1515 	}
       
  1516 /**
       
  1517 Indicates whether the registry index is currently valid.  The 
       
  1518 index will not be valid if discoveries are currently taking place.
       
  1519 If the index is not currently valid then calls to 
       
  1520 ListImplementationsL() cannot be serviced.
       
  1521 @return			ETrue if the index is currently valid, EFalse otherwise.
       
  1522 @pre 			CRegistrar is fully constructed
       
  1523 */
       
  1524 TBool CRegistryData::IndexValid() const
       
  1525 	{
       
  1526 	return !iCurrentlyDiscovering;
       
  1527 	}
       
  1528 
       
  1529 /**
       
  1530 @param			aCapabilitySet A capability set
       
  1531 @param			aImplUid The Uid of the implementation for which info is required
       
  1532 @param			aInterfaceUid The uid of the interface associated with aImplUid to find or less than
       
  1533 				0 if uid is unknown.
       
  1534 @param			aEntry Output parameter which will contain the dll information
       
  1535 @param			aImplInfo An output parameter. If the call succeeds it will point to the found implementation information,
       
  1536 				NULL otherwise.
       
  1537 @param			aIsOnRWDrive an output parameter. If the call is successful, this will
       
  1538 				be set to ETrue if the implementation is on RW drive. EFalse if the
       
  1539 				implementation is on ReadOnly drive.
       
  1540 @return			KErrNone if the call succeeds, KErrNotFound - no implementation found, 
       
  1541 				KErrPermissionDenied - the caller has not enough capabilities to load the plugin.
       
  1542 @pre			CRegistrar is fully constructed
       
  1543 */
       
  1544 TInt CRegistryData::GetImplementationDllInfoForServer(
       
  1545 	const TCapabilitySet& /*aCapabilitySet*/,
       
  1546 	const TUid aImplUid,
       
  1547 	const TUid aInterfaceUid,	
       
  1548 	TEntry& aEntry,
       
  1549 	CImplementationInformation*& aImplInfo,
       
  1550 	TBool& aIsOnRWDrive) const
       
  1551 	{
       
  1552 	aImplInfo = NULL;
       
  1553 	CImplementationData* implData;
       
  1554 	
       
  1555 	TInt res = FindImplementation(aImplUid, aInterfaceUid, implData);
       
  1556 	if (KErrNone != res)
       
  1557 		{
       
  1558 		return res;
       
  1559 		}
       
  1560 	
       
  1561 	aImplInfo = implData->iImplInfo;
       
  1562 	const CDllData* dll = implData->iParent->iParent;
       
  1563 	dll->PopulateAnEntry(aEntry);
       
  1564 
       
  1565 	TEComCachedDriveInfoIterator iter(*iCachedDriveInfo);
       
  1566 	if (! iter.SetPos(dll->iParent->iDrive))
       
  1567 		{
       
  1568 		res = KErrNotFound;
       
  1569 		}
       
  1570 	else
       
  1571 		{
       
  1572 		aIsOnRWDrive = iter.DriveIsWritable();
       
  1573 		}
       
  1574 	return res;
       
  1575 	}
       
  1576 
       
  1577 /**
       
  1578 @param			aClientRequest A client request
       
  1579 @param			aImplUid The Uid of the implementation for which info is required
       
  1580 @param			aInterfaceUid The uid of the interface associated with aImplUid to find or less than
       
  1581 				0 if uid is unknown.
       
  1582 @param			aEntry Output parameter which will contain the dll information
       
  1583 @param			aImplInfo An output parameter. If the call succeeds it will point to the found implementation information,
       
  1584 				NULL otherwise.
       
  1585 @param			aSecurityCheckNeeded The bool value to identify whether the security check is needed here. The default value is false.				
       
  1586 @return			KErrNone if the call succeeds, KErrNotFound - no implementation found,
       
  1587 				KErrPermissionDenied - the caller has not enough capabilities to load the plugin.
       
  1588 @pre			CRegistrar is fully constructed
       
  1589 */
       
  1590 TInt CRegistryData::GetImplementationDllInfoForClientL(
       
  1591 	const TClientRequest& aClientRequest,
       
  1592 	const TUid aImplUid,
       
  1593 	const TUid aInterfaceUid,	
       
  1594 	TEntry& aEntry,
       
  1595 	CImplementationInformation*& aImplInfo,
       
  1596 	TBool aSecurityCheckNeeded)const
       
  1597 	{
       
  1598 	aImplInfo = NULL;
       
  1599 	TInt res = KErrNotFound;
       
  1600 	CImplementationData* implData;
       
  1601 	if (!aSecurityCheckNeeded)
       
  1602 		{
       
  1603 		//The security check has been done already. All the invalid dll have been removed.
       
  1604 		res = FindImplementation(aImplUid, aInterfaceUid, implData);
       
  1605 		if (KErrNone != res)
       
  1606 			{
       
  1607 			return res;
       
  1608 			}
       
  1609 		CDllData* dll = implData->iParent->iParent;
       
  1610 		dll->PopulateAnEntry(aEntry);
       
  1611 		aImplInfo = implData->iImplInfo;
       
  1612 		}
       
  1613 	else
       
  1614 		{
       
  1615 		TBool securityPassed = EFalse;
       
  1616 		while(!securityPassed) // go out of this loop either Security check is passed or no DLL found.
       
  1617 			{
       
  1618 			res = FindImplementation(aImplUid, aInterfaceUid, implData);
       
  1619 			if (KErrNone != res)
       
  1620 				{
       
  1621 				return res;
       
  1622 				}
       
  1623 			CDllData* dll = implData->iParent->iParent;
       
  1624 			// security check is deferred to here.
       
  1625 			securityPassed = dll->ProcessSecurityCheckL();
       
  1626 			if(securityPassed)
       
  1627 				{
       
  1628 				if (!aClientRequest.CheckCapability(dll->iCapSet, *(implData->iImplInfo)))
       
  1629 					{
       
  1630 					return KErrPermissionDenied;
       
  1631 					}
       
  1632 				dll->PopulateAnEntry(aEntry);
       
  1633 				aImplInfo = implData->iImplInfo;
       
  1634 				}
       
  1635 			else
       
  1636 				{
       
  1637 				// remove the implementations of the DLL from iInterfaceImplIndex
       
  1638 				// and remove the DLL from its parent DLL list.
       
  1639 				DeleteDllL(dll);
       
  1640 				delete dll;
       
  1641 				dll = NULL;
       
  1642 				}
       
  1643 			}
       
  1644 		}
       
  1645 	return res;
       
  1646 	}
       
  1647 
       
  1648 /**
       
  1649 This method removes all implementations of This Dll from the iInterfaceImplIndex,
       
  1650 then delete this Dll from its parent Dll list.
       
  1651 @param	aDllData the Dll to be cleaned.
       
  1652 @pre	CRegistrar is fully constructed	
       
  1653 */
       
  1654 void CRegistryData::DeleteDllL(CDllData* aDllData) const
       
  1655 	{
       
  1656 	// find the index of the passed aDllData in its parent's Dll list.
       
  1657 	TInt index = aDllData->iParent->FindDllIndex(aDllData->iDllEntry->GetThirdUid());
       
  1658 	
       
  1659 	//removes all implementations of This Dll from the iInterfaceImplIndex
       
  1660 	RemoveFromIndexL(aDllData);
       
  1661 	if(index != KErrNotFound)
       
  1662 		{
       
  1663 		//now remove the dll from the array and registry
       
  1664 		TDll* dllList = aDllData->iParent->iDllList;
       
  1665 		dllList->Remove(index);
       
  1666 		}
       
  1667 	}
       
  1668 
       
  1669 
       
  1670 /**
       
  1671 Indicates whether the language downgrade path has changed.
       
  1672 This means we need to call NearestLanguageFile again
       
  1673 @return			ETrue if the language downgrade path has changed, EFalse otherwise.
       
  1674 @pre 			CRegistrar is fully constructed
       
  1675 */
       
  1676 TBool CRegistryData::HasLanguageChanged() const
       
  1677 	{
       
  1678 	return iLanguageChanged;
       
  1679 	}
       
  1680 
       
  1681 	
       
  1682 /**
       
  1683 @param 			aFs A handle to a connected file server.
       
  1684 */
       
  1685 CRegistryData::CRegistryData(RFs& aFs,
       
  1686 							 TInt aInterfaceImplIndexGranularity,
       
  1687 							 TInt aImplIndexGranularity) :
       
  1688 	CBase(), 
       
  1689 	iFs(aFs),
       
  1690 	iInterfaceImplIndex(aInterfaceImplIndexGranularity),
       
  1691 	iImplIndex(aImplIndexGranularity)
       
  1692 	{
       
  1693 	}
       
  1694 
       
  1695 
       
  1696 /**
       
  1697 Completes the safe construction of the CRegistryData object.
       
  1698 @leave 			KErrNoMemory.
       
  1699 @pre 			This object is constructed
       
  1700 @post			This object is fully initialized
       
  1701 */
       
  1702 void CRegistryData::ConstructL()
       
  1703 	{
       
  1704 	iCachedDriveInfo = CEComCachedDriveInfo::NewL(iFs);
       
  1705 
       
  1706 	// Construction of the empty registration data structure here
       
  1707 	iRegistrations = new(ELeave)TRegistration;
       
  1708 	iSystemDrive=iFs.GetSystemDrive();	
       
  1709 	// during construction we always need to call this function in
       
  1710 	// order to initialise and store the language settings at boot time
       
  1711 	TRAPD(err,iLanguageChanged=RDowngradePath::HasChangedL(iFs))
       
  1712 	if (err==KErrNoMemory)
       
  1713 		{
       
  1714 		User::LeaveNoMemory();
       
  1715 		}
       
  1716 	}
       
  1717 
       
  1718 /**
       
  1719 To find the index entry for aImplementationUid.
       
  1720 @return			The index of the item or KErrIndexEntryNotFound. 
       
  1721 @pre 			This object is fully constructed
       
  1722 */
       
  1723 TInt CRegistryData::IndexedFind(TUid aInterfaceUid) const
       
  1724 	{
       
  1725 	// Find the correct implementation
       
  1726 	TInterfaceIndex key;
       
  1727 	key.iInterfaceUid = aInterfaceUid;
       
  1728 	return iInterfaceImplIndex.FindInOrder(key,TLinearOrder<TInterfaceIndex>(TInterfaceStruct::CompareInfUid));
       
  1729 	}
       
  1730 
       
  1731 /**
       
  1732 Used by a TIdentityRelation to decide if two CDriveData match.
       
  1733 @return 		ETrue if the TDriveUnit inside the indexes match.
       
  1734 @param			aIndexOne The first CDriveData to compare
       
  1735 @param			aIndexTwo The second CDriveData to compare
       
  1736 */
       
  1737 TBool CRegistryData::MatchOnDrive(const CRegistryData::CDriveData& aIndexOne, 
       
  1738 								  const CRegistryData::CDriveData& aIndexTwo)
       
  1739 	{
       
  1740 	return aIndexOne.iDrive == aIndexTwo.iDrive;
       
  1741 	}
       
  1742 
       
  1743 TInt CRegistryData::FindDriveL(const TDriveUnit& aDrive,
       
  1744 							   CRegistryData::CDriveData*& aDriveData)const 
       
  1745 	{
       
  1746 	TInt index = KErrNotFound;
       
  1747 
       
  1748 	// Set up the find parameters
       
  1749 	TIdentityRelation<CRegistryData::CDriveData> identity(MatchOnDrive);
       
  1750     CDriveData* driveToMatch = CDriveData::NewLC(aDrive,const_cast<CRegistryData*>(this));
       
  1751 
       
  1752 	index = iRegistrations->Find(driveToMatch, identity);
       
  1753 	
       
  1754 	CleanupStack::PopAndDestroy(driveToMatch);
       
  1755 
       
  1756 	if(index != KErrNotFound)
       
  1757 		aDriveData = (*iRegistrations)[index];
       
  1758 	else
       
  1759 		aDriveData = NULL;
       
  1760 
       
  1761 	return index;
       
  1762 	}
       
  1763 
       
  1764 /**
       
  1765 Finds the instance of CImplementationData for given impl uid and interface uid if known.
       
  1766 @return			KErrNone if impl found, otherwise KErrNotFound.
       
  1767 @param			aImplUid The uid of the impl to find
       
  1768 @param			aInterfaceUid The uid of the interface associated with the impl to find or less than
       
  1769 				0 if uid is unknown
       
  1770 @param			aImplData Set to the instance CImplementationData found in the index or if
       
  1771 				not found set to NULL. This argument is always overwritten.
       
  1772 */
       
  1773 TInt CRegistryData::FindImplementation(const TUid aImplUid, const TUid aInterfaceUid, 
       
  1774 												CImplementationData*& aImplData) const
       
  1775 	{
       
  1776 	aImplData = NULL;
       
  1777 	TInt i;
       
  1778 	// Index is kept up to date even when discoveries are occurring
       
  1779 	// therefore always search index for implementation
       
  1780 
       
  1781 	// if aInterfaceUid is non zero use it to find position in index list
       
  1782 	if(aInterfaceUid.iUid != 0)
       
  1783 		{
       
  1784 		i = IndexedFind(aInterfaceUid);
       
  1785 		if(i == KErrNotFound)
       
  1786 			{
       
  1787 			return KErrNotFound;
       
  1788 			}
       
  1789 		
       
  1790 		TInterfaceIndex listItem = iInterfaceImplIndex[i];
       
  1791 		i = listItem.iImpData.FindInOrder(aImplUid,
       
  1792 			TImplStruct::CompareUidAgainstImplStruct);
       
  1793 		if (i >= 0)
       
  1794 			{
       
  1795 			aImplData = listItem.iImpData[i].iCurrentImpl;
       
  1796 			return KErrNone;
       
  1797 			}
       
  1798 		}
       
  1799 	else // not given I/F UID. Use the iImplIndex.
       
  1800 		{
       
  1801 		// NB: 1. Impl UID should be globally unique. It is an error if impls
       
  1802 		// have same Impl UID but different i/f UIDs. It means one of the 
       
  1803 		// plug-in supplier made an error in the .RSS file or it could be a
       
  1804 		// deliberate attach. But to maintain backward compatibility, ECOM
       
  1805 		// allows this error.
       
  1806 		// (Multiple impls can have same i/f UID and same Impl UID. That is
       
  1807 		//  the upgrade situation and only one of them get stored in iImplIndex.)
       
  1808 
       
  1809 		// 2. Entries in iImplIndex are ordered by Impl UID, and if duplicated,
       
  1810 		// ordered by i/f UID. Here i/f UID is wild card. The situation is 
       
  1811 		// analogous to the array was built with InsertInOrderAllowRepeats.
       
  1812 		// RPointerArray::SpecificFindInOrder is for ordered search in array
       
  1813 		// with duplicates. Note: it is very expensive to instantiate
       
  1814 		// a CImplementationData* just for binary search. Hence reinterpret
       
  1815 		// cast the TUid* as CImplementationData*. CompareUidAgainstImplData
       
  1816 		// knows to cast the first argument back to TUid.
       
  1817 		i = iImplIndex.SpecificFindInOrder(
       
  1818 			reinterpret_cast<const CImplementationData*>(&aImplUid), 
       
  1819 			TLinearOrder<CImplementationData>(CImplementationData::CompareUidAgainstImplData),
       
  1820 			EArrayFindMode_First);
       
  1821 		if (i == KErrNotFound)
       
  1822 			{
       
  1823 			return KErrNotFound;
       
  1824 			}
       
  1825 
       
  1826 		aImplData = iImplIndex[i];
       
  1827 
       
  1828 		// If duplicates exist, they are sorted according to i/f UID
       
  1829 		// but we cannot take advantage of this order. To miniize risk
       
  1830 		// of malware using duplicate Impl UID as DOS attack, ECOM applies
       
  1831 		// the rule that ROMBased plug-in preferred over non-ROMBased,
       
  1832 		// higher drive letter preferred over lower drive letter, and 
       
  1833 		// lastly lower i/f UID preferred over higher i/f UID. Must visit
       
  1834 		// every duplicate to compare their ROMBasedness and driver letter
       
  1835 
       
  1836 		TInt count = iImplIndex.Count();
       
  1837 		for (TInt j = i + 1; j < count; j++)
       
  1838 			{
       
  1839 			if ( iImplIndex[j]->iImplInfo->ImplementationUid().iUid != aImplUid.iUid )
       
  1840 				{
       
  1841 				break;
       
  1842 				}
       
  1843 
       
  1844 			aImplData = SelectDuplicatedImpl(aImplData, iImplIndex[j]);
       
  1845 			}
       
  1846 
       
  1847 		return KErrNone;
       
  1848 		}
       
  1849 		
       
  1850 	return KErrNotFound;
       
  1851 	}
       
  1852 
       
  1853 /**
       
  1854 This function helps FindImplementation() to decide which of two
       
  1855 implementations with duplicated implementation UID to choose.
       
  1856 The selection rules are:
       
  1857 1. ROM based plugins > non-ROM based.
       
  1858 2. Higher drive letter > lower drive letter
       
  1859 3. Lower I/F UID > Higher I/F UID (for backward compatibility reason)
       
  1860 
       
  1861 @param aImpl1 - one of the two implementations to compare.
       
  1862 @param aImpl2 - the other implementation to compare.
       
  1863 @return the preferred implementation.
       
  1864 */
       
  1865 CRegistryData::CImplementationData* CRegistryData::SelectDuplicatedImpl(
       
  1866 	const CImplementationData* aImpl1, 
       
  1867 	const CImplementationData* aImpl2) const
       
  1868 	{
       
  1869 
       
  1870 #ifdef ECOM_TRACE
       
  1871 	TPtrC oldName = aImpl1->iImplInfo->DisplayName().Left(60);
       
  1872 	TPtrC newName = aImpl2->iImplInfo->DisplayName().Left(60);
       
  1873 	TPtrC oldDll = aImpl1->iParent->iParent->iDllEntry->GetName();
       
  1874 	TPtrC newDll = aImpl2->iParent->iParent->iDllEntry->GetName();
       
  1875 #endif
       
  1876 
       
  1877 	const TInt KRomBasedFactor = 0x100;
       
  1878 
       
  1879 	TInt drive1 = aImpl1->iImplInfo->Drive();
       
  1880 	if (aImpl1->iImplInfo->RomBased())
       
  1881 		{
       
  1882 		drive1 |= KRomBasedFactor;
       
  1883 		}
       
  1884 
       
  1885 	TInt drive2 = aImpl2->iImplInfo->Drive();
       
  1886 	if (aImpl2->iImplInfo->RomBased())
       
  1887 		{
       
  1888 		drive2 |= KRomBasedFactor;
       
  1889 		}
       
  1890 
       
  1891 	if (drive1 > drive2)
       
  1892 		{
       
  1893 #ifdef ECOM_TRACE
       
  1894 		if ((drive1 & KRomBasedFactor) && !(drive2 & KRomBasedFactor))
       
  1895 			{
       
  1896 			__ECOM_TRACE5("ECOM dup impl UID resolution: rejected \"%S\" i/f UID 0x%X impl UID 0x%X, select ROM based %S over R/W %S", &newName, aImpl2->iParent->iInterfaceUid.iUid, aImpl2->iImplInfo->ImplementationUid().iUid, &oldDll, &newDll);
       
  1897 			}
       
  1898 		else
       
  1899 			{
       
  1900 			__ECOM_TRACE5("ECOM dup impl UID resolution: rejected \"%S\" i/f UID 0x%X impl UID 0x%X, select higher drive %S over %S", &newName, aImpl2->iParent->iInterfaceUid.iUid, aImpl2->iImplInfo->ImplementationUid().iUid, &oldDll, &newDll);
       
  1901 			}
       
  1902 #endif
       
  1903 
       
  1904 		return const_cast<CImplementationData*>(aImpl1);
       
  1905 		}
       
  1906 	else if (drive1 < drive2)
       
  1907 		{
       
  1908 #ifdef ECOM_TRACE
       
  1909 		if ((drive2 & KRomBasedFactor) && !(drive1 & KRomBasedFactor))
       
  1910 			{
       
  1911 			__ECOM_TRACE5("ECOM dup impl UID resolution: rejected \"%S\" i/f UID 0x%X impl UID 0x%X, select ROM based %S over R/W %S", &oldName, aImpl1->iParent->iInterfaceUid.iUid, aImpl1->iImplInfo->ImplementationUid().iUid, &newDll, &oldDll);
       
  1912 			}
       
  1913 		else
       
  1914 			{
       
  1915 			__ECOM_TRACE5("ECOM dup impl UID resolution: rejected \"%S\" i/f UID 0x%X impl UID 0x%X, select higher drive %S over %S", &oldName, aImpl1->iParent->iInterfaceUid.iUid, aImpl1->iImplInfo->ImplementationUid().iUid, &newDll, &oldDll);
       
  1916 			}
       
  1917 #endif
       
  1918 
       
  1919 		return const_cast<CImplementationData*>(aImpl2);
       
  1920 		}
       
  1921 	// They are on the same drive. Choose the one with lower I/F UID.
       
  1922 	else if (aImpl2->iParent->iInterfaceUid.iUid < aImpl1->iParent->iInterfaceUid.iUid) 
       
  1923 		{
       
  1924 #ifdef ECOM_TRACE
       
  1925 		__ECOM_TRACE5("ECOM dup impl UID resolution: rejected \"%S\" i/f UID 0x%X impl UID 0x%X, select %S with lower i/f UID 0x%X", &oldName, aImpl1->iParent->iInterfaceUid.iUid, aImpl1->iImplInfo->ImplementationUid().iUid, &newDll, aImpl2->iParent->iInterfaceUid.iUid);
       
  1926 #endif
       
  1927 
       
  1928 		return const_cast<CImplementationData*>(aImpl2);
       
  1929 		}
       
  1930 
       
  1931 #ifdef ECOM_TRACE
       
  1932 	__ECOM_TRACE5("ECOM dup impl UID resolution: rejected \"%S\" i/f UID 0x%X impl UID 0x%X, select %S with lower i/f UID 0x%X", &newName, aImpl2->iParent->iInterfaceUid.iUid, aImpl2->iImplInfo->ImplementationUid().iUid, &oldDll, aImpl1->iParent->iInterfaceUid.iUid);
       
  1933 #endif
       
  1934 
       
  1935 	return const_cast<CImplementationData*>(aImpl1);
       
  1936 	}
       
  1937 
       
  1938 /**
       
  1939 Checks each entry in the registry to ensure that both the RSC file and the 
       
  1940 corresponding dll exist.  If not the dll branch is removed
       
  1941 from the tree.  If a drive branch is found which contains no dlls
       
  1942 it is also removed.
       
  1943 @pre 			This object is fully constructed.
       
  1944 @post			Any out of date registry entries are removed from the tree.
       
  1945 */
       
  1946 void CRegistryData::ValidateRegistryL()
       
  1947 	{
       
  1948 	TInt driveIndex = iRegistrations->Count();
       
  1949 	TFileName rscFileName;
       
  1950 	while(driveIndex > 0)
       
  1951 		{
       
  1952 		--driveIndex;
       
  1953 		CDriveData* drive = (*iRegistrations)[driveIndex];
       
  1954 		
       
  1955 		if( !iCachedDriveInfo->DriveIsReadOnlyInternalL(drive->iDrive) &&
       
  1956 			drive->iDriveChanged)
       
  1957 			{
       
  1958 			TInt dllIndex = drive->iDllList->Count();	
       
  1959 			while(dllIndex > 0)
       
  1960 				{
       
  1961 				--dllIndex;
       
  1962 				CDllData* dll = (*drive->iDllList)[dllIndex];
       
  1963 				//reset the buffer first			
       
  1964 				rscFileName.Zero();
       
  1965 				rscFileName.Append(dll->iParent->iDrive.Name());
       
  1966 				rscFileName.Append(KEComResourceFilePath);
       
  1967 				rscFileName.Append(dll->iDllEntry->GetName().Left(dll->iDllEntry->GetName().Length()-4));
       
  1968 				if(dll->iRscFileExtension)
       
  1969 					{
       
  1970 					rscFileName.Append(dll->iRscFileExtension->Des());
       
  1971 					}
       
  1972 			
       
  1973 					// check the existence of RSC file in resource\plugins\ directory.
       
  1974 					// RSC filename is already a full name here.
       
  1975 				TBool rscFileExistence = BaflUtils::FileExists(iFs, rscFileName);
       
  1976 
       
  1977   				//save the security info, this will both check existence of the dll
       
  1978   				//and cache the information for future use
       
  1979   				TBool success=dll->SaveSecurityInfoL();
       
  1980 				// If this dll is not found or the corresponding RSC file is not found, then remove it from the registry
       
  1981 				if(!success || !rscFileExistence)
       
  1982 					{
       
  1983 					//remove all implementations of this dll from iInterfaceImplIndex
       
  1984 					RemoveFromIndexL(dll);
       
  1985 					drive->iDllList->Remove(dllIndex);
       
  1986 					//set flag to indicate registry data has been changed
       
  1987 					drive->iRegistryChanged = ETrue;
       
  1988 					delete dll;
       
  1989 					}
       
  1990 				}
       
  1991 			}
       
  1992 		}
       
  1993 	}
       
  1994 
       
  1995 /**
       
  1996 Determines whether the new implmentation should be preferred over the existing implementation.
       
  1997 Validates later version implementations from R/W drives.
       
  1998 @param		aOldImpl The array to append to
       
  1999 @param		aNewImpl The item to append
       
  2000 @param		aLegitimateImpl Flag, indicating whether current implementation is secure
       
  2001 @return		The preferred implementation
       
  2002 @pre		This object is fully constructed.
       
  2003 */
       
  2004 CRegistryData::CImplementationData* CRegistryData::SelectPreferredImplL(CImplementationData* aOldImpl,
       
  2005 																CImplementationData* aNewImpl,
       
  2006 																TBool& aLegitimateImpl,
       
  2007 																TBool aCheckIsNeeded) const
       
  2008 	{
       
  2009 	aLegitimateImpl = ETrue;
       
  2010 
       
  2011 	TBool newIsRomOnly = aNewImpl->iImplInfo->RomOnly();
       
  2012 	TBool oldIsRomOnly = aOldImpl->iImplInfo->RomOnly();
       
  2013 		
       
  2014 	/* 	In addition to selecting the highest version of an 
       
  2015 		implementation this check takes care of the following special 
       
  2016 		cases:
       
  2017 		1. Ensure that a higher-versioned RAM-based implementation 
       
  2018 		   cannot override a ROM-based version
       
  2019 		2. Allows for the case where there are two versions of the 
       
  2020 		   same ROM-only implementation on ROM,	thus ensuring the 
       
  2021 		   higher of the two versions is used.
       
  2022 	*/
       
  2023 	if(newIsRomOnly && !oldIsRomOnly)
       
  2024 		{
       
  2025 		return aNewImpl;
       
  2026 		}
       
  2027 	else if((newIsRomOnly && oldIsRomOnly))
       
  2028 		{
       
  2029 		if(aNewImpl->iImplInfo->Version() > aOldImpl->iImplInfo->Version())
       
  2030 			{
       
  2031 			return aNewImpl;
       
  2032 			}
       
  2033 		else if(aNewImpl->iImplInfo->Version() == aOldImpl->iImplInfo->Version())
       
  2034 			{
       
  2035 			//any drive from Y-A has higher priority than Z drive
       
  2036             //any drive with a letter alphabetically greater has higher priority
       
  2037             if((aNewImpl->iImplInfo->Drive() != EDriveZ) &&
       
  2038                 (aOldImpl->iImplInfo->Drive() == EDriveZ || aNewImpl->iImplInfo->Drive() > aOldImpl->iImplInfo->Drive()))
       
  2039                 {
       
  2040 				return aNewImpl;
       
  2041 				}
       
  2042 			}
       
  2043 		}
       
  2044 	//all new implementations which are not flagged'RomOnly'
       
  2045 	else if(!newIsRomOnly && !oldIsRomOnly)
       
  2046 		{
       
  2047 		TBool newIsReadOnly = iCachedDriveInfo->DriveIsReadOnlyInternalL(aNewImpl->iParent->iParent->iParent->iDrive);
       
  2048 		TBool oldIsReadOnly = iCachedDriveInfo->DriveIsReadOnlyInternalL(aOldImpl->iParent->iParent->iParent->iDrive);
       
  2049 			
       
  2050 		if(aNewImpl->iImplInfo->Version() > aOldImpl->iImplInfo->Version())
       
  2051 			{
       
  2052 			//filter for implementations on R/W drive trying to upgrade implementations on R/O drive
       
  2053 			if((!newIsReadOnly && oldIsReadOnly) && aCheckIsNeeded)
       
  2054 				{						
       
  2055 				//test if a later implementation version on R/W drive has the same filename as the current one before upgrading.
       
  2056 				//If not,...
       
  2057 				if(aOldImpl->iParent->iParent->iDllEntry->GetName().CompareF(aNewImpl->iParent->iParent->iDllEntry->GetName()) == 0)
       
  2058 					{
       
  2059 					return aNewImpl;
       
  2060 					}
       
  2061 				else
       
  2062 					{
       
  2063 					aLegitimateImpl = EFalse; //not secure
       
  2064 					return aOldImpl;
       
  2065 					}
       
  2066 				}
       
  2067 			else
       
  2068 				{
       
  2069 				return aNewImpl;
       
  2070 				}
       
  2071 			}
       
  2072 		else if(aNewImpl->iImplInfo->Version() == aOldImpl->iImplInfo->Version())
       
  2073 			{
       
  2074 			//any drive from Y-A has higher priority than Z drive OR
       
  2075 			//any drive with a letter alphabetically greater has higher priority
       
  2076 			if((aNewImpl->iImplInfo->Drive() != EDriveZ) &&
       
  2077                 (aOldImpl->iImplInfo->Drive() == EDriveZ || aNewImpl->iImplInfo->Drive() > aOldImpl->iImplInfo->Drive()))                 
       
  2078 				{
       
  2079 				//filename check needs to performed on implementation from R/W drives, trying to 
       
  2080 				//upgrade implementations on R/O drive    
       
  2081 				if((!newIsReadOnly && oldIsReadOnly) && aCheckIsNeeded)
       
  2082 					{							
       
  2083 					//test if a later implementation version on R/W drive has the same filename as the current one before upgrading.
       
  2084 					//If not,...
       
  2085 					if(aOldImpl->iParent->iParent->iDllEntry->GetName().CompareF(aNewImpl->iParent->iParent->iDllEntry->GetName()) == 0)
       
  2086 						{
       
  2087 						return aNewImpl;
       
  2088 						}
       
  2089 					else
       
  2090 						{
       
  2091 						aLegitimateImpl = EFalse; //not secure
       
  2092 						return aOldImpl;
       
  2093 						}		
       
  2094 					}
       
  2095 				else
       
  2096 					{
       
  2097 					return aNewImpl;
       
  2098 					}
       
  2099 				}						
       
  2100 			}
       
  2101 		}
       
  2102 	return aOldImpl;
       
  2103 	}
       
  2104 
       
  2105 /**
       
  2106 This functions checks if a given implementation already exists in
       
  2107 the indexes. If it does exist, determine if the given implementation
       
  2108 should replace the existing one or not.
       
  2109 @param  aIdxArray The container array of the interface to hold the implementation.
       
  2110 @param  aNewImpl The implementation to filter.
       
  2111 @param  aInsertMode whether aNewIMpl is a newcomer of the interface, or an 
       
  2112 		update of an existing implementation, or a older version of an
       
  2113 		existing implementation.
       
  2114 @param  aPosOfImplInArray return the index of aNewImpl in aIdxArray,
       
  2115 @param  aLegitimateImpl Flag,indicating whether current implementation is secure
       
  2116 @pre    This object is fully constructed.
       
  2117 @post   none
       
  2118 */
       
  2119 void
       
  2120 CRegistryData::FilterForLatestLegitimateImplL(TImplContainerArray& aIdxArray,
       
  2121 											  CImplementationData* aNewImpl,
       
  2122 											  TInsertImplMode& aInsertMode,
       
  2123 											  TInt&  aPosOfImplInArray,
       
  2124 											  TBool& aLegitimateImpl,
       
  2125 											  TBool aCheckIsNeeded)
       
  2126 	{
       
  2127 	aInsertMode = EInsertImplUndefinedMode;
       
  2128 	aLegitimateImpl = ETrue;
       
  2129 	TImplStruct newImplStruct;
       
  2130 	newImplStruct.iCurrentImpl = aNewImpl;
       
  2131 
       
  2132 	TInt idxPos = aIdxArray.FindInOrder(newImplStruct, TLinearOrder<TImplStruct> (TImplStruct::CompareImplStructUid));
       
  2133 
       
  2134 	aPosOfImplInArray = idxPos;
       
  2135 
       
  2136 	if(idxPos != KErrNotFound)
       
  2137 		{
       
  2138 		if(aNewImpl != SelectPreferredImplL(aIdxArray[idxPos].iCurrentImpl,
       
  2139 											aNewImpl,
       
  2140 											aLegitimateImpl,
       
  2141 											aCheckIsNeeded))
       
  2142 			{
       
  2143 			aInsertMode = EInsertImplAsUnusedImpl;
       
  2144 			}
       
  2145 		else
       
  2146 			{
       
  2147 			aInsertMode = EInsertImplAsUpgradeOfExistingImpl;
       
  2148 			} 
       
  2149 		}
       
  2150 	else
       
  2151 		{
       
  2152 		aInsertMode = EInsertImplAsNewcomerOfInterface;
       
  2153 		}
       
  2154 	}
       
  2155 
       
  2156 void CRegistryData::ResetTInterfaceIndex(TAny* aObject)
       
  2157 	{
       
  2158 	TInterfaceIndex* index=reinterpret_cast<TInterfaceIndex*>(aObject);
       
  2159 	index->Reset();
       
  2160 	}
       
  2161 
       
  2162 /**
       
  2163 This method retrieves the data for security checks from the iInterfaceImplIndex
       
  2164 @param          aImplPtr The new item to be checked
       
  2165 @param			aCheckIsNeeded	Boolean indicating, whether a filename check is needed
       
  2166 @pre            This object is fully constructed.
       
  2167 @post           aImplPtr has been checked and added to the index, or not, depending on the 
       
  2168 				outcome of the checks.
       
  2169 */
       
  2170 TBool CRegistryData::InsertIntoIndexL(CImplementationData* aImplPtr, TBool aCheckIsNeeded)
       
  2171 	{
       
  2172 	TBool legitimateImpl = ETrue;
       
  2173 
       
  2174 	TInterfaceIndex newIndexEl;
       
  2175 	TInterfaceIndex* newElPtr;
       
  2176 	//initialise
       
  2177 	newIndexEl.iInterfaceUid = aImplPtr->iParent->iInterfaceUid;
       
  2178 	CleanupStack::PushL(TCleanupItem(ResetTInterfaceIndex,&newIndexEl));
       
  2179 	
       
  2180 	TInt indexPos = iInterfaceImplIndex.FindInOrder(newIndexEl,TLinearOrder<TInterfaceIndex>(TInterfaceStruct::CompareInfUid));
       
  2181 
       
  2182 	
       
  2183 	if(indexPos!=KErrNotFound)
       
  2184 		newElPtr = &(iInterfaceImplIndex[indexPos]);
       
  2185 	else		
       
  2186 		newElPtr = &newIndexEl;	
       
  2187 
       
  2188 	// For each implementation make sure we only have the latest version
       
  2189 	TInt implIdxInContainerArray(KErrNotFound);
       
  2190 	TInsertImplMode insertMode;
       
  2191 	FilterForLatestLegitimateImplL(newElPtr->iImpData,
       
  2192 									aImplPtr,
       
  2193 									insertMode,
       
  2194 									implIdxInContainerArray,
       
  2195 									legitimateImpl,
       
  2196 									aCheckIsNeeded);
       
  2197 	
       
  2198 	InsertImplInIndexesL(insertMode, 
       
  2199 						 indexPos,
       
  2200 						 *newElPtr,
       
  2201 						 implIdxInContainerArray,
       
  2202 						 aImplPtr,
       
  2203 						 legitimateImpl);
       
  2204 
       
  2205 	CleanupStack::Pop();
       
  2206 
       
  2207 	if (insertMode == EInsertImplAsUpgradeOfExistingImpl)
       
  2208 		{
       
  2209 	    TUid ImplUid = aImplPtr->iImplInfo->ImplementationUid();
       
  2210 		iImplUpgradeCallBack.CallBack(ECallBackId_ImplUpgrade, &ImplUid);
       
  2211 		}
       
  2212 
       
  2213 	return legitimateImpl;
       
  2214 	}
       
  2215 
       
  2216 /** Handle inserting a CImplementationData in iInterfaceImplIndex and
       
  2217 iImplIndex.
       
  2218 
       
  2219 @param aNewImpl the implementation to add to the indexes.
       
  2220 @param aInsertMode indicates whether the implementation is a newcover
       
  2221 			of the interface, or is an update of existing implementation
       
  2222 			or is an older version of an existing implementation.
       
  2223 @param aIfPosInInterfaceImplIndex is the index of the interface in
       
  2224 		iInterfaceImplIndex.
       
  2225 @param aNewIfIndexEl the TInterfaceIndex object containing the implementation.
       
  2226 @param aImplPosInContainerArray is the index of the implementation in
       
  2227 		the iImpData member of aNewIfIndexEl.
       
  2228 @param aLegitimateImpl indicate if the implementation passed security check or not.
       
  2229 @leave KErrNoMemory operation fails because the system is out of memory.
       
  2230 @leave KErrGeneral any non-specific programming error.
       
  2231 @leave KErrAlreadyExists the indexes already have an entry with the same
       
  2232 		Impl. UID and Interface UID.
       
  2233 */
       
  2234 void CRegistryData::InsertImplInIndexesL(TInsertImplMode aInsertMode,
       
  2235 										TInt aIfPosInInterfaceImplIndex,
       
  2236 										TInterfaceIndex& aNewIfIndexEl,
       
  2237 										TInt aImplPosInContainerArray,
       
  2238 								   		CImplementationData* aNewImpl,
       
  2239 								   		TBool aLegitimateImpl)
       
  2240 	{
       
  2241 	if(aInsertMode == EInsertImplUndefinedMode)
       
  2242 		{
       
  2243 		// Will not happen because if FilterForLatestLegitimateImplL
       
  2244 		// does not leave then insertMode is set to one of the valid
       
  2245 		// values. If FilterForLatestLegitimateImplL leaves ecomserver exits.
       
  2246 		User::Leave(KErrGeneral);
       
  2247 		}
       
  2248 
       
  2249 	// If not a legitimate implementation, aNewImpl will be deleted.
       
  2250 	// Do not add it to the two indexes.
       
  2251 
       
  2252 	if (!aLegitimateImpl)
       
  2253 		{
       
  2254 		return;
       
  2255 		}
       
  2256 
       
  2257 	TImplContainerArray& implContainerArray = aNewIfIndexEl.iImpData;
       
  2258 
       
  2259 	if(aInsertMode == EInsertImplAsNewcomerOfInterface)
       
  2260 		{
       
  2261 		TImplStruct newImplStruct;
       
  2262 		newImplStruct.iCurrentImpl = aNewImpl;
       
  2263 		implContainerArray.InsertInOrderL(newImplStruct, TLinearOrder<TImplStruct> (TImplStruct::CompareImplStructUid));
       
  2264 
       
  2265 #ifdef _DEBUG
       
  2266 		// on debug build, check for duplicated implementation UID
       
  2267 		// owned by different interfaces.
       
  2268 
       
  2269 		TInt ii = iImplIndex.SpecificFindInOrder(
       
  2270 			aNewImpl,
       
  2271 			CImplementationData::CompareImplUidIgnoreIfUid,
       
  2272 			EArrayFindMode_Any);
       
  2273 		if (ii != KErrNotFound)
       
  2274 			{
       
  2275 			CImplementationData* otherImpl = iImplIndex[ii];
       
  2276 			TPtrC oldName = otherImpl->iImplInfo->DisplayName().Left(60);
       
  2277 			TPtrC newName = aNewImpl->iImplInfo->DisplayName().Left(60);
       
  2278 			__ECOM_TRACE5("** ECOM: error Impl UID %X, I/F UID %X DLL %S duplicating I/F %X DLL %S",\\ 
       
  2279 				aNewImpl->iImplInfo->ImplementationUid().iUid, \\
       
  2280 				aNewImpl->iParent->iInterfaceUid.iUid, &newName,\\
       
  2281 				otherImpl->iParent->iInterfaceUid.iUid, &oldName);
       
  2282 			}
       
  2283 #endif
       
  2284 		}
       
  2285 	else if(aInsertMode == EInsertImplAsUpgradeOfExistingImpl)
       
  2286 		{
       
  2287 		TImplContainer& implContainer = implContainerArray[aImplPosInContainerArray];
       
  2288 		CImplementationData* oldImpl =  implContainer.iCurrentImpl;
       
  2289 		implContainer.iUnusedImpls.AppendL(oldImpl);
       
  2290 		RemoveImplFromImplIndex(oldImpl); // ignore return code
       
  2291 		implContainer.iCurrentImpl = aNewImpl;
       
  2292 
       
  2293 		// We are replacing existing impl with aNewImpl.  If existing  
       
  2294 		// corresponds to a ROM-based plug-in then aNewImpl is an 
       
  2295 		// update and qualifies as ROM-based under current policy.
       
  2296 		if(oldImpl->iImplInfo->RomBased())
       
  2297 			{
       
  2298 			aNewImpl->iImplInfo->SetRomBased(ETrue);
       
  2299 			}
       
  2300 		__ECOM_TRACE5("ECOM: Removed old implementation: UID:0x%X interfaceUID:0x%X version:%d on drive:%d \"%S\"", oldImpl->iImplInfo->ImplementationUid().iUid, oldImpl->iParent->iInterfaceUid.iUid, oldImpl->iImplInfo->Version(), (TInt)(oldImpl->iImplInfo->Drive()), &(oldImpl->iImplInfo->DisplayName()));
       
  2301 		__ECOM_TRACE5("ECOM: Loaded new implementation: UID:0x%X interfaceUID:0x%X version:%d on drive:%d \"%S\"", aNewImpl->iImplInfo->ImplementationUid().iUid, aNewImpl->iParent->iInterfaceUid.iUid, aNewImpl->iImplInfo->Version(), (TInt)(aNewImpl->iImplInfo->Drive()), &(aNewImpl->iImplInfo->DisplayName()));
       
  2302 		}
       
  2303 	else if (aInsertMode == EInsertImplAsUnusedImpl)
       
  2304 		{
       
  2305 		TImplContainer& implContainer = implContainerArray[aImplPosInContainerArray];
       
  2306 		implContainer.iUnusedImpls.AppendL(aNewImpl);
       
  2307 
       
  2308 		CImplementationData* currImpl =  implContainer.iCurrentImpl;
       
  2309 		__ECOM_TRACE5("ECOM: Kept old implementation: UID:0x%X interfaceUID:0x%X version:%d on drive:%d \"%S\"", currImpl->iImplInfo->ImplementationUid().iUid, currImpl->iParent->iInterfaceUid.iUid, currImpl->iImplInfo->Version(), (TInt)(currImpl->iImplInfo->Drive()), &(currImpl->iImplInfo->DisplayName()));
       
  2310 		__ECOM_TRACE5("ECOM: Not loaded new implementation: UID:0x%X interfaceUID:0x%X version:%d on drive:%d \"%S\"", aNewImpl->iImplInfo->ImplementationUid().iUid, aNewImpl->iParent->iInterfaceUid.iUid, aNewImpl->iImplInfo->Version(), (TInt)(aNewImpl->iImplInfo->Drive()), &(aNewImpl->iImplInfo->DisplayName()));
       
  2311 		// We are not replacing existing with aNewImpl.  However, 
       
  2312 		// if aNewImpl corresponds to a ROM-based plug-in then the 
       
  2313 		// existing impl is an update and qualifies as ROM-based 
       
  2314 		// under current policy.
       
  2315 		if(aNewImpl->iImplInfo->RomBased())
       
  2316 			{
       
  2317 			currImpl->iImplInfo->SetRomBased(ETrue);
       
  2318 			}
       
  2319 
       
  2320 		return; // the trailing steps not applicable to downgrade situation
       
  2321 		}
       
  2322 
       
  2323 	User::LeaveIfError( InsertImplIntoImplIndex(aNewImpl) );
       
  2324 	
       
  2325 	if(aIfPosInInterfaceImplIndex==KErrNotFound)
       
  2326 		{		
       
  2327 		iInterfaceImplIndex.InsertInOrderL(aNewIfIndexEl, TLinearOrder<TInterfaceIndex>(TInterfaceStruct::CompareInfUid));		
       
  2328 		}
       
  2329 	}
       
  2330 
       
  2331 /**
       
  2332 This method takes removes all implementations of a plugin from the iInterfaceImplIndex
       
  2333 @param			aDllData Reference to a fully constructed CDllData object 
       
  2334 @pre			This object is constructed
       
  2335 @post			All implementations of the CDllData object, have been removed from the index
       
  2336 */
       
  2337 void CRegistryData::RemoveFromIndexL(CDllData* aDllData) const
       
  2338 	{
       
  2339 	//remove 'old' implementations from iInterfaceImplIndex
       
  2340 	TInt counter=0;
       
  2341 	TImplStruct implStruct;
       
  2342 	TInt ifListCount=aDllData->iIfList->Count();
       
  2343 	while(counter < ifListCount)
       
  2344 		{
       
  2345 		CInterfaceData* interface = (*aDllData->iIfList)[counter];
       
  2346 		TInterfaceIndex index;
       
  2347 		index.iInterfaceUid = interface->iInterfaceUid;
       
  2348 		
       
  2349 		TInt indexPos = iInterfaceImplIndex.FindInOrder(index,TLinearOrder<TInterfaceIndex>(TInterfaceStruct::CompareInfUid));
       
  2350 
       
  2351 		if(indexPos!=KErrNotFound)
       
  2352 			{
       
  2353 			TImplContainerArray* impDataArray = &(iInterfaceImplIndex[indexPos].iImpData);
       
  2354 			TInt implCount=interface->iImplementations->Count();
       
  2355 			for(TInt i=0; i<implCount; i++)
       
  2356 				{
       
  2357 				implStruct.iCurrentImpl = (*interface->iImplementations)[i];
       
  2358 				TInt impPos = impDataArray->FindInOrder(implStruct, TLinearOrder<CRegistryData::TImplStruct> (TImplStruct::CompareImplStructUid));
       
  2359 				if(impPos!=KErrNotFound)
       
  2360 					{
       
  2361 					TImplContainer& implContainer = (*impDataArray)[impPos];
       
  2362 					// remove from unused list if exists
       
  2363 					TInt count = implContainer.iUnusedImpls.Count();
       
  2364 					while(count > 0)
       
  2365 						{
       
  2366 						--count;
       
  2367 						if(implContainer.iUnusedImpls[count]->iParent->iParent == aDllData)
       
  2368 							{
       
  2369 							implContainer.iUnusedImpls.Remove(count);
       
  2370 							}
       
  2371 						}
       
  2372 
       
  2373 					// update current entry
       
  2374 					if(implContainer.iCurrentImpl->iParent->iParent == aDllData)
       
  2375 						{
       
  2376 						// do not care about the return code.
       
  2377 						RemoveImplFromImplIndex(implContainer.iCurrentImpl);
       
  2378 						
       
  2379 						TInt implContainerUnusedImplCount=implContainer.iUnusedImpls.Count();
       
  2380 						// no unused impl's therefore no rollback and remove entry
       
  2381 						if(implContainerUnusedImplCount == 0)
       
  2382 							{
       
  2383 							implContainer.Reset();
       
  2384 							impDataArray->Remove(impPos);
       
  2385 							}
       
  2386 						else
       
  2387 							{
       
  2388 							// Rollback to implementation from unused array
       
  2389 							// copy first from unused array
       
  2390 							TInt selectedPos = 0;
       
  2391 							implContainer.iCurrentImpl = implContainer.iUnusedImpls[selectedPos];
       
  2392 							
       
  2393 							// now check if any others in list should be preferred
       
  2394 							for(count = 1;count < implContainerUnusedImplCount; count++)
       
  2395 								{
       
  2396 								// determine which implementation should be used.
       
  2397 								// no security check required as this will have already been done when impl was
       
  2398 								// first added to unused list.
       
  2399 								TBool dummLegitimateImpl;
       
  2400 								implContainer.iCurrentImpl = SelectPreferredImplL(implContainer.iCurrentImpl,
       
  2401 																implContainer.iUnusedImpls[count],
       
  2402 																dummLegitimateImpl,
       
  2403 																EFalse);
       
  2404 								if(implContainer.iCurrentImpl == implContainer.iUnusedImpls[count])
       
  2405 									{
       
  2406 									selectedPos = count;
       
  2407 									}
       
  2408 								}
       
  2409 							implContainer.iUnusedImpls.Remove(selectedPos);
       
  2410 							User::LeaveIfError(InsertImplIntoImplIndex(implContainer.iCurrentImpl));
       
  2411 #ifdef ECOM_TRACE
       
  2412 							{
       
  2413 							CImplementationData* p = implContainer.iCurrentImpl;
       
  2414 							__ECOM_TRACE5("ECOM: unused implementation restored UID:0x%X interfaceUID:0x%X version:%d on drive:%d \"%S\"", p->iImplInfo->ImplementationUid().iUid, p->iParent->iInterfaceUid.iUid, p->iImplInfo->Version(), (TInt)(p->iImplInfo->Drive()), &(p->iImplInfo->DisplayName()));
       
  2415 							}
       
  2416 #endif
       
  2417 							}
       
  2418 						}
       
  2419 					}
       
  2420 				}
       
  2421 			if(impDataArray->Count() == 0)
       
  2422 				{
       
  2423 				iInterfaceImplIndex[indexPos].Reset();
       
  2424 				iInterfaceImplIndex.Remove(indexPos);
       
  2425 				}
       
  2426 			}
       
  2427 		counter++;
       
  2428 		}
       
  2429 	}
       
  2430 
       
  2431 /**
       
  2432 This method inserts implementations into the index
       
  2433 @param          aDriveData Drive data in which we are searching the implementations
       
  2434 @pre            This object is fully constructed.
       
  2435 @post           all implemementations found, have been inserted into the index.
       
  2436 */
       
  2437 void CRegistryData::AddImplDataL(CDriveData* aDriveData)
       
  2438 	{
       
  2439  	TBool checkIsNeeded = EFalse;
       
  2440  	TInt dllCount=aDriveData->iDllList->Count();
       
  2441  	for(TInt dllCounter=0; dllCounter < dllCount;dllCounter++)
       
  2442  		{
       
  2443  		CDllData* aDllData = (*aDriveData->iDllList)[dllCounter];
       
  2444  		TInt interfaceCount=aDllData->iIfList->Count();
       
  2445  		for(TInt ifListCounter=0; ifListCounter < interfaceCount; ifListCounter++)
       
  2446  			{
       
  2447  			// For each interface structure
       
  2448  			CInterfaceData* interface = (*aDllData->iIfList)[ifListCounter];
       
  2449  			TInt implementationCount=interface->iImplementations->Count();
       
  2450  			for(TInt impNum = 0; impNum < implementationCount; ++impNum)
       
  2451  				{
       
  2452  				CImplementationData* implData = (*interface->iImplementations)[impNum];
       
  2453  				TInt retValue = InsertIntoIndexL(implData, checkIsNeeded);
       
  2454  				//we know that during internalize, all implementations are legitimate,
       
  2455  				//as the check was already performed during discovery. No check is 
       
  2456  				//performed at this stage, therefore ignore return value, as it will always
       
  2457  				//KErrNone
       
  2458  				}
       
  2459  			}	
       
  2460  		}	
       
  2461  	}
       
  2462 
       
  2463 /** This method removes the specified entry from iImplIndex.
       
  2464 
       
  2465 @param	aPtr is the entry to remove
       
  2466 @return True if aPtr is removed from iImplIndex. False if aPtr is not
       
  2467 		in iImplIndex, i.e. nothing is removed.
       
  2468 */
       
  2469 TBool CRegistryData::RemoveImplFromImplIndex(CImplementationData* aPtr) const
       
  2470 	{
       
  2471 	TInt i = iImplIndex.FindInOrder(aPtr, TLinearOrder<CImplementationData>(CImplementationData::CompareImplUid));
       
  2472 	if (i != KErrNotFound)
       
  2473 		{
       
  2474 		// The array does not own the pointer. Do not delete!
       
  2475 		iImplIndex.Remove(i);
       
  2476 		}
       
  2477 	return (i != KErrNotFound);
       
  2478 	}
       
  2479 
       
  2480 /** This method inserts the entry aNewImpl into iImplIndex.
       
  2481 
       
  2482 @param aNewImpl the item to add to iImplIndex.
       
  2483 @return KErrNone aNewImpl is successfully added to the index.
       
  2484 		KErrAlreadyExists iImplIndex has an entry with the same 
       
  2485 		implementation UID and same parent Interface UID.
       
  2486 		KErrNoMemory fail to insert due to out of memory.
       
  2487 		Other system wide errors.
       
  2488 @pre    aNewImpl is fully constructed.
       
  2489 */
       
  2490 TInt CRegistryData::InsertImplIntoImplIndex(CImplementationData* aNewImpl) const
       
  2491 	{
       
  2492 	TLinearOrder<CImplementationData> ImplUidComparator(CImplementationData::CompareImplUid);
       
  2493 
       
  2494 	return iImplIndex.InsertInOrder(aNewImpl, ImplUidComparator);
       
  2495 	}
       
  2496 
       
  2497 /** This method checks whether the language downgrade path has been changed.
       
  2498 If it is, save language downgrade path information and set related flag true.
       
  2499 
       
  2500 @param aLanguageChanged the returned value to indicate language changed.
       
  2501 */
       
  2502 void CRegistryData::LanguageChangedL(TBool& aLanguageChanged)
       
  2503 	{
       
  2504 	iLanguageChanged = RDowngradePath::HasChangedL(iFs);
       
  2505 	aLanguageChanged = iLanguageChanged;
       
  2506 	}
       
  2507 
       
  2508 /** setter
       
  2509 If need to unset the callback, use a TCallBackWithArg constructed with no
       
  2510 arguments.
       
  2511 */
       
  2512 void CRegistryData::SetImplUpgradeCallBack(const TCallBackWithArg& aCallBack)
       
  2513 	{
       
  2514 	iImplUpgradeCallBack = aCallBack;
       
  2515 	}
       
  2516 
       
  2517 #ifdef __ECOM_SERVER_PERFORMANCE__
       
  2518 /**
       
  2519 This method calculates the drive, plugins, interfaces, implementations counts for the drive
       
  2520 type set
       
  2521 @param			aType The drive type for which the counts should be calculated 
       
  2522 @param			aCounts Holds the calculated counts
       
  2523 @pre			This object is constructed
       
  2524 */
       
  2525 void CRegistryData::GetRegistryCountsL(TInt aType, RegistryCounts::TRegistryCounts& aCounts) const
       
  2526 	{
       
  2527 	aCounts.iDrives = 0;
       
  2528 	aCounts.iImplementations = 0;
       
  2529 	aCounts.iInterfaces = 0;
       
  2530 	aCounts.iDlls = 0;
       
  2531 	
       
  2532 	for(TInt driveIndex = 0; driveIndex< iRegistrations->Count(); driveIndex++)
       
  2533 		{
       
  2534 		CDriveData* drive = (*iRegistrations)[driveIndex];
       
  2535 		TBool isReadOnly = iCachedDriveInfo->DriveIsReadOnlyInternalL(drive->iDrive);
       
  2536 
       
  2537 		if((aType == RegistryCounts::TRegistryCounts::EAll) ||
       
  2538 			(aType == RegistryCounts::TRegistryCounts::ERoInternal && isReadOnly) ||
       
  2539 			(aType == RegistryCounts::TRegistryCounts::ENonRoInternal && !isReadOnly))
       
  2540 			{
       
  2541 			aCounts.iDrives++;
       
  2542 			aCounts.iDlls += drive->iDllList->Count();
       
  2543 			for(TInt dllIndex = 0; dllIndex < drive->iDllList->Count(); dllIndex++)
       
  2544 				{
       
  2545 				CDllData* dllList = (*drive->iDllList)[dllIndex];
       
  2546 				aCounts.iInterfaces += dllList->iIfList->Count();
       
  2547 				for(TInt ifIndex = 0; ifIndex < dllList->iIfList->Count(); ifIndex++)
       
  2548 					{
       
  2549 					CInterfaceData* ifList = (*dllList->iIfList)[ifIndex];
       
  2550 					aCounts.iImplementations += ifList->iImplementations->Count();
       
  2551 					}
       
  2552 				}
       
  2553 			}
       
  2554 		}
       
  2555 	}
       
  2556 
       
  2557 #endif // __ECOM_SERVER_PERFORMANCE__