os/ossrv/lowlevellibsandfws/pluginfw/Framework/frame/RegistryData.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/lowlevellibsandfws/pluginfw/Framework/frame/RegistryData.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,2582 @@
     1.4 +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// This file contains the implementations of the classes
    1.18 +// which manage the internal structure of the registry.
    1.19 +// 
    1.20 +//
    1.21 +
    1.22 +#include <e32base.h>
    1.23 +#include <e32uid.h>
    1.24 +#include <s32stor.h>
    1.25 +#include <s32file.h>
    1.26 +#include <startup.hrh> // for EStartupStateNonCritical
    1.27 +#include <e32ldr.h> // for hash checking
    1.28 +#include <e32ldr_private.h> // for RLoader
    1.29 +#include <bautils.h> // for BaflUtils::FileExists
    1.30 +
    1.31 +#include "EComDebug.h"
    1.32 +#include <ecom/ecom.h>
    1.33 +#include <ecom/ecomerrorcodes.h>
    1.34 +#include <ecom/ecomresolverparams.h>
    1.35 +#include <ecom/implementationinformation.h>
    1.36 +#include "RegistryData.h"
    1.37 +#include "DowngradePath.h"
    1.38 +#include "DriveInfo.h"
    1.39 +#include "FileUtils.h"
    1.40 +#include "EComUidCodes.h"
    1.41 +#include "EComInternalErrorCodes.h"
    1.42 +#define UNUSED_VAR(a) a = a
    1.43 +
    1.44 +const TInt KRegVersion = -9999;
    1.45 +const TInt KDllExtensionLength=4;
    1.46 +_LIT(KDllExtension,".dll");
    1.47 +//
    1.48 +//CRegistryData::TInterfaceStruct
    1.49 +
    1.50 +/**
    1.51 +Constructor for TInterfaceStruct
    1.52 +@post			Its member variable is granulated as (1)
    1.53 +*/
    1.54 +CRegistryData::TInterfaceStruct::TInterfaceStruct():
    1.55 +	iImpData(1)
    1.56 +	{
    1.57 +	// Do nothing here
    1.58 +	}
    1.59 +
    1.60 +/**
    1.61 +This method determins the order of two TInterfaceIndex objects
    1.62 +@param			indexEntry1 first TInterfaceIndex object
    1.63 +@param			indexEntry2 second TInterfaceIndex object
    1.64 +@return			integer indicating the order of these two
    1.65 +@pre			This object is fully constructed
    1.66 +*/
    1.67 +TInt CRegistryData::TInterfaceStruct::CompareInfUid(const TInterfaceIndex& indexEntry1,
    1.68 +													const TInterfaceIndex& indexEntry2)
    1.69 +	{
    1.70 +	return CompareTUidValues(indexEntry1.iInterfaceUid.iUid,indexEntry2.iInterfaceUid.iUid);
    1.71 +	}
    1.72 +
    1.73 +//
    1.74 +//CRegistryData::TImplStruct
    1.75 +
    1.76 +/**
    1.77 +Constructor for TImplStruct
    1.78 +@post			Its member variables are initialised
    1.79 +*/
    1.80 +CRegistryData::TImplStruct::TImplStruct():
    1.81 +	iCurrentImpl(NULL),
    1.82 +	iUnusedImpls(1)
    1.83 +	{
    1.84 +	// Do nothing here
    1.85 +	}
    1.86 +	
    1.87 +/**
    1.88 +This method determins the order of two TImplStruct objects
    1.89 +@param			aEntry1 first TImplStruct object
    1.90 +@param			aEntry2 second TImplStruct object
    1.91 +@return			integer indicating the order of these two
    1.92 +@pre			This object is fully constructed
    1.93 +*/
    1.94 + TInt CRegistryData::TImplStruct::CompareImplStructUid(const TImplStruct& aEntry1,
    1.95 +													const TImplStruct& aEntry2)
    1.96 +	{
    1.97 +	return CompareTUidValues(aEntry1.iCurrentImpl->iImplInfo->ImplementationUid().iUid,
    1.98 +						aEntry2.iCurrentImpl->iImplInfo->ImplementationUid().iUid);
    1.99 +	}
   1.100 +	
   1.101 +/** Comparer to determine the order of a TUid object (implementation UID) in relation to and a TImplStruct object.
   1.102 +@param aUid the Implementation UID to compare with.
   1.103 +@param aEntry the TImplStruct object to compare aUid against.
   1.104 +@return integer indicating the order of the two.
   1.105 +*/
   1.106 +TInt CRegistryData::TImplStruct::CompareUidAgainstImplStruct(
   1.107 +	const TUid* aUid,
   1.108 +	const TImplStruct& aEntry)
   1.109 +	{
   1.110 +	return CompareTUidValues(aUid->iUid,aEntry.iCurrentImpl->iImplInfo->ImplementationUid().iUid);
   1.111 +	}
   1.112 +
   1.113 +//
   1.114 +// CRegistryData::CImplementationData class
   1.115 +
   1.116 +/**
   1.117 +Creates a new CImplemenatationData object. Note that CImplementationInformation needs to be constructed too,
   1.118 +for this object to be fully constructed.
   1.119 +@param			aParent A pointer to the parent instance of CInterfaceData
   1.120 +@return			A pointer to the newly created object.
   1.121 +@post			This object is partly constructed and initialized and is on 
   1.122 +				the CleanupStack.
   1.123 +*/
   1.124 +CRegistryData::CImplementationData* CRegistryData::CImplementationData::NewLC(CInterfaceData* aParent)
   1.125 +	{
   1.126 +	CImplementationData* self=new(ELeave) CImplementationData(aParent);
   1.127 +	CleanupStack::PushL(self);
   1.128 +	return self;
   1.129 +	}
   1.130 +
   1.131 +/**
   1.132 +Creates a new CImplemenatationData object. It takes parameters to create a CImplementationInformation object,
   1.133 +during 2nd phase construction and initializes iImplInfo to reference to this CImplementationInformation object.
   1.134 +@param			aParent A pointer to the parent instance of CInterfaceData
   1.135 +@param			aUid The unique Id of the new implementation
   1.136 +@param			aVersion The version number of the new implementation
   1.137 +@param			aName The display name of the new implementation
   1.138 +@param			aDataType The data type supported by the new implementation
   1.139 +@param			aOpaqueData Data for the new implementation which is not used by the ECom framework
   1.140 +@param			aDrive The drive that the new implementation is on
   1.141 +@param			aRomOnly The flag recording whether the new implementation may be loaded from ROM only
   1.142 +@param			aRomBased The flag recording whether the new implementation is on ROM or is a later version of one on ROM
   1.143 +@return			A pointer to the newly created object
   1.144 +@post			This object is fully constructed and initialized.
   1.145 +*/
   1.146 +CRegistryData::CImplementationData* CRegistryData::CImplementationData::NewL(CInterfaceData* aParent,
   1.147 +																				TUid	aUid,
   1.148 +																				TInt	aVersion, 
   1.149 +																				HBufC*  aName,
   1.150 +																				HBufC8* aDataType,
   1.151 +																				HBufC8* aOpaqueData,
   1.152 +																				TDriveUnit aDrive,
   1.153 +																				TBool aRomOnly,
   1.154 +																				TBool aRomBased)
   1.155 +	{
   1.156 +	CImplementationData* self=new(ELeave) CImplementationData(aParent);
   1.157 +	CleanupStack::PushL(self);
   1.158 +	self->ConstructL(aUid,
   1.159 +					aVersion,
   1.160 +					aName,
   1.161 +					aDataType,
   1.162 +					aOpaqueData,
   1.163 +					aDrive,
   1.164 +					aRomOnly,
   1.165 +					aRomBased);
   1.166 +	CleanupStack::Pop(self);
   1.167 +	return self;
   1.168 +	}
   1.169 +
   1.170 +/**
   1.171 +Creates a new CImplemenatationData object. It takes parameters to create a CImplementationInformation object,
   1.172 +during 2nd phase construction and initializes iImplInfo to reference to this CImplementationInformation object.
   1.173 +@param			aParent A pointer to the parent instance of CInterfaceData
   1.174 +@param			aUid The unique Id of the new implementation
   1.175 +@param			aVersion The version number of the new implementation
   1.176 +@param			aName The display name of the new implementation
   1.177 +@param			aDataType The data type supported by the new implementation
   1.178 +@param			aOpaqueData Data for the new implementation which is not used by the ECom framework
   1.179 +@param			aDrive The drive that the new implementation is on
   1.180 +@param			aRomOnly The flag recording whether the new implementation may be loaded from ROM only
   1.181 +@param			aRomBased The flag recording whether the new implementation is on ROM or is a later version of one on ROM
   1.182 +@param			aExtendedInterfaces The pointer to the array recording the extended interfaces supported by this implementation.
   1.183 +				NULL is available for PLUGIN without extended interfaces support.
   1.184 +@return			A pointer to the newly created object
   1.185 +@post			This object is fully constructed and initialized.
   1.186 +*/
   1.187 +CRegistryData::CImplementationData* CRegistryData::CImplementationData::NewL(CInterfaceData* aParent,
   1.188 +																				TUid	aUid,
   1.189 +																				TInt	aVersion, 
   1.190 +																				HBufC*  aName,
   1.191 +																				HBufC8* aDataType,
   1.192 +																				HBufC8* aOpaqueData,
   1.193 +																				TDriveUnit aDrive,
   1.194 +																				TBool aRomOnly,
   1.195 +																				TBool aRomBased,
   1.196 +																				RExtendedInterfacesArray* aExtendedInterfaces)
   1.197 +	{
   1.198 +	CImplementationData* self=new(ELeave) CImplementationData(aParent);
   1.199 +	CleanupStack::PushL(self);
   1.200 +	self->ConstructL(aUid,
   1.201 +					aVersion,
   1.202 +					aName,
   1.203 +					aDataType,
   1.204 +					aOpaqueData,
   1.205 +					aDrive,
   1.206 +					aRomOnly,
   1.207 +					aRomBased,
   1.208 +					aExtendedInterfaces);
   1.209 +	CleanupStack::Pop(self);
   1.210 +	return self;
   1.211 +	}
   1.212 +
   1.213 +/**
   1.214 +Constructor for CImplementationData
   1.215 +@param			aParent The parent interface data of this implementation
   1.216 +@post			Its member variables are initialised
   1.217 +*/
   1.218 +CRegistryData::CImplementationData::CImplementationData( CInterfaceData* aParent):
   1.219 +	CBase(),
   1.220 +	iImplInfo(NULL),
   1.221 +	iParent(aParent)
   1.222 +	{
   1.223 +	// Do nothing here
   1.224 +	}
   1.225 +	
   1.226 +/**
   1.227 +Destructor of CImplementationData
   1.228 +*/	
   1.229 +CRegistryData::CImplementationData::~CImplementationData()
   1.230 +	{
   1.231 +	if(iImplInfo)
   1.232 +		{
   1.233 +		delete iImplInfo;
   1.234 +		iImplInfo = NULL;	
   1.235 +		}	
   1.236 +	iParent = NULL;		
   1.237 +	}
   1.238 +
   1.239 +/**
   1.240 +The object's memory has been allocated.
   1.241 +@param			aUid The unique Id of the new implementation
   1.242 +@param			aVersion The version number of the new implementation
   1.243 +@param			aName The display name of the new implementation
   1.244 +@param			aDataType The data type supported by the new implementation
   1.245 +@param			aOpaqueData Data for the new implementation which is not used by the ECom framework
   1.246 +@param			aDrive The drive that the new implementation is on
   1.247 +@param			aRomOnly The flag recording whether the new implementation may be loaded from ROM only
   1.248 +@param			aRomBased The flag recording whether the new implementation is on ROM or is a later version of one on ROM
   1.249 +@pre 			This object is fully constructed.
   1.250 +@post			This object is fully constructed and initialized.
   1.251 +*/
   1.252 +void CRegistryData::CImplementationData::ConstructL(TUid	aUid,
   1.253 +													TInt	aVersion, 
   1.254 +													HBufC*  aName,
   1.255 +													HBufC8* aDataType,
   1.256 +													HBufC8* aOpaqueData,
   1.257 +													TDriveUnit aDrive,
   1.258 +													TBool aRomOnly,
   1.259 +													TBool aRomBased)
   1.260 +	{
   1.261 +	CImplementationInformation* newImpl = CImplementationInformation::NewL(aUid, 
   1.262 +													 						aVersion, 
   1.263 +													 						aName, 
   1.264 +															 				aDataType,
   1.265 +																			aOpaqueData,
   1.266 +														 					aDrive,
   1.267 +														 					aRomOnly,
   1.268 +													 						aRomBased);
   1.269 +	this->iImplInfo = newImpl;
   1.270 +	}
   1.271 +
   1.272 +/**
   1.273 +The object's memory has been allocated.
   1.274 +@param			aUid The unique Id of the new implementation
   1.275 +@param			aVersion The version number of the new implementation
   1.276 +@param			aName The display name of the new implementation
   1.277 +@param			aDataType The data type supported by the new implementation
   1.278 +@param			aOpaqueData Data for the new implementation which is not used by the ECom framework
   1.279 +@param			aDrive The drive that the new implementation is on
   1.280 +@param			aRomOnly The flag recording whether the new implementation may be loaded from ROM only
   1.281 +@param			aRomBased The flag recording whether the new implementation is on ROM or is a later version of one on ROM
   1.282 +@param			aExtendedInterfaces The pointer to the array recording the extended interfaces supported by this implementation.
   1.283 +				NULL is available for PLUGIN without extended interfaces support.
   1.284 +@pre 			This object is fully constructed.
   1.285 +@post			This object is fully constructed and initialized.
   1.286 +*/
   1.287 +void CRegistryData::CImplementationData::ConstructL(TUid	aUid,
   1.288 +													TInt	aVersion, 
   1.289 +													HBufC*  aName,
   1.290 +													HBufC8* aDataType,
   1.291 +													HBufC8* aOpaqueData,
   1.292 +													TDriveUnit aDrive,
   1.293 +													TBool aRomOnly,
   1.294 +													TBool aRomBased,
   1.295 +													RExtendedInterfacesArray* aExtendedInterfaces)
   1.296 +	{
   1.297 +	CImplementationInformation* newImpl = CImplementationInformation::NewL(aUid, 
   1.298 +													 						aVersion, 
   1.299 +													 						aName, 
   1.300 +															 				aDataType,
   1.301 +																			aOpaqueData,
   1.302 +														 					aDrive,
   1.303 +														 					aRomOnly,
   1.304 +													 						aRomBased,
   1.305 +													 						aExtendedInterfaces);
   1.306 +	this->iImplInfo = newImpl;
   1.307 +	}
   1.308 +
   1.309 +/**
   1.310 +Initialises member variable with the CImplementationInformation state specified in aStore.
   1.311 +@param			aStore The stream to read the data from.
   1.312 +@pre 			This object is full constructed.
   1.313 +@post			This object is set to the state specified in aStore.
   1.314 +*/
   1.315 +void CRegistryData::CImplementationData::InternalizeL(RReadStream& aStore)
   1.316 +	{
   1.317 +	if (iImplInfo)
   1.318 +		{
   1.319 +		delete iImplInfo;
   1.320 +		iImplInfo = NULL;
   1.321 +		}
   1.322 +	CImplementationInformation* implInfo = 0;
   1.323 +	implInfo=CImplementationInformation::NewLC(EFalse,aStore);
   1.324 +	//as we never store the drive name we need to get this from the parent
   1.325 +	implInfo->SetDrive(iParent->iParent->iParent->iDrive);
   1.326 +	CleanupStack::Pop(1);
   1.327 +	iImplInfo = implInfo;
   1.328 +	implInfo = 0;
   1.329 +	}
   1.330 +
   1.331 +
   1.332 +/**
   1.333 +Writes out the state of this member variable of type CImplementationInformation to aStore.
   1.334 +@param			aStore The stream to store the data in.
   1.335 +@pre 			This object is fully constructed.
   1.336 +*/
   1.337 +void CRegistryData::CImplementationData::ExternalizeL(RWriteStream& aStore) const
   1.338 +	{
   1.339 +	iImplInfo->ExternalizeL(EFalse,aStore);
   1.340 +	}
   1.341 +
   1.342 +/**
   1.343 +This method determines the order of two CImplementationData objects.
   1.344 +For backward compatibility reason, ECom allows different I/Fs using
   1.345 +the same implementation UID for when the device has an implementation UID
   1.346 +that is not unique. Although this is not a valid or supported situation ECOM 
   1.347 +server should be robust.
   1.348 +@see FindImplementation
   1.349 +@see CompareTUidValues
   1.350 +@param			aImpl1 first reference to CImplementationData object 
   1.351 +@param			aImpl2 second reference to CImplementationData object
   1.352 +@return			integer indicating the order of these two
   1.353 +@pre			This object is fully constructed
   1.354 +*/	
   1.355 +TInt CRegistryData::CImplementationData::CompareImplUid(const CImplementationData& aImpl1,
   1.356 +													const CImplementationData& aImpl2)
   1.357 +	{
   1.358 +	TInt ret = CompareTUidValues(aImpl1.iImplInfo->ImplementationUid().iUid, aImpl2.iImplInfo->ImplementationUid().iUid);
   1.359 +	if (ret != 0)
   1.360 +		{
   1.361 +		return ret;
   1.362 +		}
   1.363 +
   1.364 +	// Implementation UIDs are equal, use I/F UID as tie breaker
   1.365 +	return CompareTUidValues(aImpl1.iParent->iInterfaceUid.iUid, aImpl2.iParent->iInterfaceUid.iUid);
   1.366 +	}
   1.367 +	
   1.368 +/**
   1.369 +Similar to CompareImplUid above. This comparer only compare the Impl UID
   1.370 +and ignore the I/F UID part.
   1.371 +@param			aImpl1 first reference to CImplementationData object 
   1.372 +@param			aImpl2 second reference to CImplementationData object
   1.373 +@return			integer indicating the order of these two
   1.374 +@pre			This object is fully constructed
   1.375 +*/	
   1.376 +TInt CRegistryData::CImplementationData::CompareImplUidIgnoreIfUid(const CImplementationData& aImpl1,
   1.377 +													const CImplementationData& aImpl2)
   1.378 +	{
   1.379 +	return CompareTUidValues(aImpl1.iImplInfo->ImplementationUid().iUid,
   1.380 +						aImpl2.iImplInfo->ImplementationUid().iUid);
   1.381 +	}
   1.382 +	
   1.383 +/**
   1.384 +This method determines the order of an CImplementationData object in relation
   1.385 +to aUid.
   1.386 +@param	aUid is really TUid. Cast it back before compare.
   1.387 +@param	aImplData reference to CImplementationData object
   1.388 +@return	integer indicating the order of the two.
   1.389 +*/	
   1.390 +TInt CRegistryData::CImplementationData::CompareUidAgainstImplData(
   1.391 +											const CImplementationData& aUid,
   1.392 +											const CImplementationData& aImplData)
   1.393 +	{
   1.394 +	// The first argument aUid is really TUid.
   1.395 +	const TUid* ImplUid = reinterpret_cast<const TUid*>(&aUid);
   1.396 +	return CompareTUidValues(ImplUid->iUid,
   1.397 +						aImplData.iImplInfo->ImplementationUid().iUid);
   1.398 +	}
   1.399 +
   1.400 +//
   1.401 +// CRegistryData::CInterfaceData class
   1.402 +
   1.403 +/**
   1.404 +Creates a new CInterfaceData object and leave it on the CleanupStack
   1.405 +@param			aInterface The unique Id of this interface.
   1.406 +@param			aParent A pointer to the parent dll data 
   1.407 +@return			A pointer to the newly created class.
   1.408 +@post			This object is fully constructed and initialized and is on 
   1.409 +				the CleanupStack.
   1.410 +*/
   1.411 +CRegistryData::CInterfaceData* CRegistryData::CInterfaceData::NewLC(TUid aInterfaceUid,CDllData* aParent)
   1.412 +	{
   1.413 +	CInterfaceData* self=new(ELeave) CInterfaceData(aInterfaceUid,aParent);
   1.414 +	CleanupStack::PushL(self);
   1.415 +	self->ConstructL();
   1.416 +	return self;
   1.417 +	}
   1.418 +
   1.419 +
   1.420 +/**
   1.421 +Creates a new CInterfaceData object using the supplied interface id 
   1.422 +and leave it on the CleanupStack
   1.423 +@param			aParent A pointer to the parent dll data
   1.424 +@return			A pointer to the newly created class.
   1.425 +@post			This object is fully constructed and initialized and is on 
   1.426 +				the CleanupStack.
   1.427 +*/
   1.428 +CRegistryData::CInterfaceData* CRegistryData::CInterfaceData::NewLC(CDllData* aParent)
   1.429 +	{
   1.430 +	CInterfaceData* self=new(ELeave) CInterfaceData(aParent);
   1.431 +	CleanupStack::PushL(self);
   1.432 +	self->ConstructL();
   1.433 +	return self;
   1.434 +	}
   1.435 +
   1.436 +
   1.437 +CRegistryData::CInterfaceData::~CInterfaceData()
   1.438 +	{
   1.439 +	if(iImplementations)
   1.440 +		{
   1.441 +		iImplementations->ResetAndDestroy();
   1.442 +		delete iImplementations;
   1.443 +		iImplementations = NULL;
   1.444 +		}
   1.445 +	iParent = NULL;
   1.446 +	}
   1.447 +
   1.448 +/**
   1.449 +Adds the specified implementation to this interface in the registry.
   1.450 +@param			aImplementation The implementation to add to this interface.
   1.451 +@pre			This object is fully constructed.
   1.452 +@post			aImplementation is added to the list of implementations for this interface.
   1.453 +*/
   1.454 +void CRegistryData::CInterfaceData::AddL(const CImplementationData* aImplementation)
   1.455 +	{
   1.456 +#ifdef ECOM_TRACE
   1.457 +	static int counter = 0; counter++;
   1.458 +	__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()));
   1.459 +
   1.460 +#endif
   1.461 +
   1.462 +	User::LeaveIfError(iImplementations->Append(aImplementation));
   1.463 +	}
   1.464 +
   1.465 +/**
   1.466 +Sets the uid of this interface to aInterfaceUid.
   1.467 +@param			aInterfaceUid The Uid which this object should take.
   1.468 +@pre			This object is fully constructed.
   1.469 +@post			The Uid of this interface is set to aInterfaceUid
   1.470 +*/
   1.471 +void CRegistryData::CInterfaceData::SetInterfaceUid(TUid aInterfaceUid)
   1.472 +	{
   1.473 +	iInterfaceUid = aInterfaceUid;
   1.474 +	}
   1.475 +
   1.476 +/**
   1.477 +Writes out this CInterfaceData to aStore.
   1.478 +@param			aStore The stream to store the data in.
   1.479 +@pre 			The state of this object is stored in the stream aStore.
   1.480 +*/
   1.481 +void CRegistryData::CInterfaceData::ExternalizeL(RWriteStream& aStore) const
   1.482 +	{
   1.483 +	aStore.WriteInt32L(iInterfaceUid.iUid);
   1.484 +
   1.485 +	if(iImplementations)
   1.486 +		{
   1.487 +		const TInt entryCount = iImplementations->Count();
   1.488 +		aStore.WriteInt32L(entryCount);
   1.489 +		for(TInt i = 0; i < entryCount; ++i)
   1.490 +			((*iImplementations)[i])->ExternalizeL(aStore);
   1.491 +		}
   1.492 +	else
   1.493 +		aStore.WriteInt32L(0);
   1.494 +	}
   1.495 +
   1.496 +/**
   1.497 +Restores this CInterfaceData to the state specified in aStore.
   1.498 +@param			aStore The stream to read the data from.
   1.499 +@param			aPresent A boolean indicating whether the dll is still present
   1.500 +@pre 			This object is full constructed.
   1.501 +@post			This object is set to the state specified in aStore.
   1.502 +*/
   1.503 +void CRegistryData::CInterfaceData::InternalizeL(RReadStream& aStore)
   1.504 +	{
   1.505 +	iInterfaceUid.iUid = aStore.ReadInt32L();
   1.506 +
   1.507 +	const TInt entryCount = aStore.ReadInt32L();
   1.508 +    if(entryCount < 0)
   1.509 +        {
   1.510 +        User::Leave(KErrCorrupt);
   1.511 +        }
   1.512 +	
   1.513 +	for(TInt i = 0; i < entryCount; ++i)
   1.514 +		{
   1.515 +		CImplementationData* implementation = CImplementationData::NewLC(this);
   1.516 +		implementation->InternalizeL(aStore);
   1.517 +		AddL(implementation);
   1.518 +		CleanupStack::Pop(implementation);		//now owned by this interface
   1.519 +		}
   1.520 +	}
   1.521 +
   1.522 +/**
   1.523 +@param			aParent A pointer to the parent dll data
   1.524 +*/
   1.525 +CRegistryData::CInterfaceData::CInterfaceData(CDllData* aParent) :
   1.526 +	CBase(),
   1.527 +	iParent(aParent)
   1.528 +	{
   1.529 +	// Do nothing here
   1.530 +	}
   1.531 +
   1.532 +/**
   1.533 +@param			aInterfaceUid The unique Id of this interface
   1.534 +@param			aParent A pointer to the parent dll data			
   1.535 +*/
   1.536 +CRegistryData::CInterfaceData::CInterfaceData(TUid aInterfaceUid, CDllData* aParent) :
   1.537 +	CBase(),
   1.538 +	iInterfaceUid(aInterfaceUid),
   1.539 +	iParent(aParent)
   1.540 +	{
   1.541 +	// Do nothing here
   1.542 +	}
   1.543 +
   1.544 +/**
   1.545 +Standard second phase construction function
   1.546 +@pre 			This object is fully constructed.
   1.547 +@post			This object is fully constructed and initialized.
   1.548 +*/
   1.549 +void CRegistryData::CInterfaceData::ConstructL()
   1.550 +	{
   1.551 +	iImplementations = new(ELeave) RPointerArray<CImplementationData>;
   1.552 +	}
   1.553 +
   1.554 +//
   1.555 +// CRegistryData::CDllData class
   1.556 +
   1.557 +/**
   1.558 +Creates a new CDllData object using aEntry and leaves it on the CleanupStack
   1.559 +@param			aDllName the name of this dll
   1.560 +@param			aDllModTime the modified time of this dll
   1.561 +@param 			aSecondUid Identifies type of the DLL. (PLUGIN or PLUGIN3)
   1.562 +@param  			aThirdUid Identifies a component uniquely. 	
   1.563 +@param			aParent A pointer to the parent drive data
   1.564 +@return			A pointer to the newly created object.
   1.565 +@post			This object is fully constructed and initialized and on the CleanupStack.
   1.566 +*/
   1.567 +CRegistryData::CDllData* CRegistryData::CDllData::NewLC(const TDesC& aDllName,const TTime& aDllModTime,const TUid& aSecondUid,const TUid& aThirdUid,CDriveData* aParent)
   1.568 +	{
   1.569 +	CDllData* self=new(ELeave) CDllData(aParent);
   1.570 +	CleanupStack::PushL(self);
   1.571 +	self->ConstructL(aDllName,aDllModTime,aSecondUid,aThirdUid);
   1.572 +	return self;
   1.573 +	}
   1.574 +
   1.575 +/**
   1.576 +Creates a new CDllData object using aParent and leaves it on the CleanupStack
   1.577 +@param			aParent A pointer to the parent drive data
   1.578 +@return			A pointer to the newly created object.
   1.579 +@post			This object is fully constructed and initialized and on the CleanupStack.
   1.580 +*/
   1.581 +CRegistryData::CDllData* CRegistryData::CDllData::NewLC( CDriveData* aParent)
   1.582 +	{
   1.583 +	CDllData* self=new(ELeave) CDllData(aParent);
   1.584 +	CleanupStack::PushL(self);
   1.585 +	self->ConstructL();
   1.586 +	return self;
   1.587 +	}
   1.588 +	
   1.589 +CRegistryData::CDllData::~CDllData()
   1.590 +	{
   1.591 +	if(iIfList)
   1.592 +		{
   1.593 +		// Clear the interface list and destroy its objects
   1.594 +		iIfList->ResetAndDestroy();
   1.595 +		delete iIfList;
   1.596 +		iIfList = NULL;
   1.597 +		}
   1.598 +
   1.599 +	// Unload this implementation dll.
   1.600 +	delete iDllEntry;
   1.601 +	iDllEntry = NULL;
   1.602 +	iParent = NULL;
   1.603 +	delete iRscFileExtension;
   1.604 +	}
   1.605 +
   1.606 +/**
   1.607 +Adds the specified interface to this dll in the registry.
   1.608 +@param			aInterface The interface to add to this dll
   1.609 +@pre 			This object is fully constructed.
   1.610 +@post			aInterface is added to the list of interfaces in this dll.
   1.611 +*/
   1.612 +void CRegistryData::CDllData::AddL(const CInterfaceData* aInterface)
   1.613 +	{
   1.614 +	User::LeaveIfError(iIfList->Append(aInterface));
   1.615 +	}
   1.616 +
   1.617 +/**
   1.618 +Sets the resource extension for the plugin. Not set for read only internal drives.
   1.619 +@param			aExt The resource extension to set
   1.620 +@pre 			This object is fully constructed.
   1.621 +@post			aExt is added to the object.
   1.622 +*/
   1.623 +void CRegistryData::CDllData::SetResourceExtL(const TDesC& aExt)
   1.624 +	{
   1.625 +	delete iRscFileExtension;
   1.626 +	iRscFileExtension = NULL;
   1.627 +	iRscFileExtension = aExt.AllocL();
   1.628 +	}
   1.629 +	
   1.630 +/**
   1.631 +Set the capability,the VID and do the Security check for this DLL.
   1.632 +@pre 			This object is fully constructed.
   1.633 +@return			ETrue if the security check is done successfully. Otherwise EFalse is returned. 
   1.634 +*/
   1.635 +TBool CRegistryData::CDllData::SaveSecurityInfoL()
   1.636 +	{
   1.637 +	iSecurityChecked = EFalse;
   1.638 +
   1.639 +	//need to construct the full filename i.e. appending with the
   1.640 +	//preconstructed drivepath name in CDriveData
   1.641 +	TFileName dllFullName;
   1.642 +	dllFullName.Append(iParent->iDrive.Name());
   1.643 +	dllFullName.Append(_L("\\sys\\bin\\"));
   1.644 +	dllFullName.Append(iDllEntry->GetName());
   1.645 +	RLibrary::TInfoBuf infoBuf;
   1.646 +	TInt ret = RLibrary::GetInfo(dllFullName, infoBuf);
   1.647 +	if(ret != KErrNone)
   1.648 +		{
   1.649 +		return EFalse;
   1.650 +		}
   1.651 +	// Set the DLL's capability
   1.652 +	iCapSet = infoBuf().iSecurityInfo.iCaps;
   1.653 +	// Set the DLL's VID
   1.654 +	iVid = infoBuf().iSecurityInfo.iVendorId;
   1.655 +	// Now verify that SID identified in the resource file matches the SID of the Dll file
   1.656 +	TBool match=iDllEntry->GetThirdUid() ==infoBuf().iSecurityInfo.iSecureId;
   1.657 +	if (!match)
   1.658 +		{
   1.659 +#ifdef __ECOM_TRACE 
   1.660 +		__ECOM_TRACE1("ERROR: Plugin SID Mismatch ERROR for %S.", &dllFullName);
   1.661 +#endif
   1.662 +		return EFalse;
   1.663 +		}
   1.664 +
   1.665 +	// Now verify the two DLL's second Uid are of the same Uid type (used for distinguising between collection/collection3)
   1.666 +	match=iDllEntry->GetSecondUid() ==infoBuf().iUids[1];
   1.667 +	if (!match)
   1.668 +		{
   1.669 +#ifdef __ECOM_TRACE 
   1.670 +		__ECOM_TRACE1("ERROR: Plugin UID2 Mismatch ERROR for %S.", &iDllEntry->GetName());
   1.671 +#endif
   1.672 +		return EFalse;
   1.673 +		}
   1.674 +
   1.675 +	// On the emulator RLoader::CheckLibraryHash() returns KErrNotSupported.
   1.676 +	// Also on the emulator RLoader does no hash checking for DLL's on removable drives.
   1.677 +	// Therefore to be consistent ECOM does not do any hash checking itself on the emulator.
   1.678 +	// Hence code is removed for emulator builds.
   1.679 +#if !defined(__WINSCW__)
   1.680 +	// Verify hash is available
   1.681 +	if(iParent->iParent->iCachedDriveInfo->DriveIsRemovableL(iParent->iDrive))
   1.682 +		{
   1.683 +		RLoader loader;
   1.684 +		TInt err = loader.Connect();
   1.685 +		if(err != KErrNone)
   1.686 +			{
   1.687 +			return EFalse;
   1.688 +			}
   1.689 +		err = loader.CheckLibraryHash(dllFullName, ETrue);
   1.690 +		loader.Close();
   1.691 +		if(err != KErrNone)
   1.692 +			{
   1.693 +#ifdef __ECOM_TRACE 
   1.694 +		__ECOM_TRACE2("INFO: Hash Check Failed for %S with error %d.", &dllFullName, err);
   1.695 +#endif
   1.696 +			return EFalse;
   1.697 +			}
   1.698 +		}
   1.699 +#endif
   1.700 +	iSecurityChecked = ETrue;
   1.701 +	return ETrue;
   1.702 +	}
   1.703 +	
   1.704 +/**
   1.705 +Check whether security check has been performed if not go retrieve it.
   1.706 +@pre 			This object is fully constructed.
   1.707 +@return			ETrue if the security check is done successfully. Otherwise EFalse is returned. 
   1.708 +*/
   1.709 +TBool CRegistryData::CDllData::ProcessSecurityCheckL()
   1.710 +	{
   1.711 +	if(iSecurityChecked)
   1.712 +		{
   1.713 +		return ETrue;
   1.714 +		}
   1.715 +	return SaveSecurityInfoL();
   1.716 +	}
   1.717 +
   1.718 +
   1.719 +/**
   1.720 +Writes out the state of this CDllData to aStore.
   1.721 +@param			aStore The stream to store the data in.
   1.722 +@pre 			This object is fully constructed.
   1.723 +*/
   1.724 +void CRegistryData::CDllData::ExternalizeL(RWriteStream& aStore) const
   1.725 +   	{
   1.726 + 	const CEComEntry& dllEntryData = *iDllEntry;
   1.727 +	TInt size=dllEntryData.GetName().Length()-KDllExtensionLength;
   1.728 + 	aStore.WriteUint32L(size);
   1.729 +	aStore.WriteL(dllEntryData.GetName(),size);
   1.730 +
   1.731 +	aStore.WriteInt32L(dllEntryData.GetSecondUid().iUid);	
   1.732 +  	aStore.WriteInt32L(dllEntryData.GetThirdUid().iUid);
   1.733 +    TPckg<TTime> modified(dllEntryData.GetModified());	
   1.734 + 	aStore.WriteL(modified);
   1.735 +	
   1.736 +	if(!iParent->iParent->iCachedDriveInfo->DriveIsReadOnlyInternalL(iParent->iDrive))
   1.737 +		{
   1.738 +		if(iRscFileExtension)
   1.739 +			{
   1.740 +			size = iRscFileExtension->Length();		
   1.741 +			aStore.WriteUint32L(size);
   1.742 +			aStore.WriteL(iRscFileExtension->Des(),size);
   1.743 +			}
   1.744 +		else
   1.745 +			{
   1.746 +			aStore.WriteUint32L(0);		
   1.747 +			}
   1.748 +		}
   1.749 +
   1.750 +   	if(iIfList)
   1.751 +   		{
   1.752 +   		const TInt entryCount = iIfList->Count();
   1.753 +   		aStore.WriteInt32L(entryCount);
   1.754 +   		for(TInt i = 0; i < entryCount; ++i)
   1.755 +   			((*iIfList)[i])->ExternalizeL(aStore);
   1.756 +   		}
   1.757 +   	else
   1.758 +   		aStore.WriteInt32L(0);
   1.759 +	}
   1.760 +
   1.761 +/**
   1.762 +Restores this CDllData to the state specified in aStore.
   1.763 +@param			aStore The stream to read the data from.
   1.764 +@pre 			This object is fully constructed.
   1.765 +@post			The state of this object is restored to that specified in aStore.
   1.766 +*/
   1.767 +void CRegistryData::CDllData::InternalizeL(RReadStream& aStore)
   1.768 + 	{	
   1.769 +	TInt size=aStore.ReadUint32L();
   1.770 +    //The next "if" checks if size < 0 not size <= 0 because it seems the ECOM server externalizes
   1.771 +    //the last file name as a string with length 0. If the fix is <= 0, then it makes it
   1.772 +    //incompatible with the existing applications
   1.773 +    if(size < 0 || size > KMaxFileName)
   1.774 +        {
   1.775 +        User::Leave(KErrCorrupt);
   1.776 +        }
   1.777 +	HBufC* name = HBufC::NewLC(size+KDllExtensionLength);
   1.778 +	TPtr ptr=name->Des();
   1.779 +	aStore.ReadL(ptr,size);
   1.780 +	ptr.Append(KDllExtension);
   1.781 +
   1.782 +  	TUid secondUid=TUid::Uid(aStore.ReadInt32L());
   1.783 +  	TUid thirdUid=TUid::Uid(aStore.ReadInt32L());
   1.784 +  	TTime dllModifiedTime;  	
   1.785 +   	TPckg<TTime> modified(dllModifiedTime);	
   1.786 + 	aStore.ReadL(modified);
   1.787 +
   1.788 +	if(!iParent->iParent->iCachedDriveInfo->DriveIsReadOnlyInternalL(iParent->iDrive))
   1.789 +		{
   1.790 +		size = aStore.ReadUint32L();
   1.791 +		if(size < 0 || size > KMaxFileName)
   1.792 +		        {
   1.793 +       		 User::Leave(KErrCorrupt);
   1.794 +       		 }
   1.795 +		if(size)
   1.796 +			{
   1.797 +			iRscFileExtension = HBufC::NewL(size);
   1.798 +			TPtr extPtr = iRscFileExtension->Des();
   1.799 +			aStore.ReadL(extPtr,size);
   1.800 +			}
   1.801 +		}
   1.802 +	
   1.803 +   	const TInt entryCount = aStore.ReadInt32L();
   1.804 +	if(entryCount < 0)
   1.805 +		{
   1.806 +		User::Leave(KErrCorrupt);
   1.807 +		}
   1.808 +	
   1.809 +   	// Security check is deferred until the DLL is needed.
   1.810 +	for(TInt i = 0; i < entryCount; ++i)
   1.811 +	   	{
   1.812 +	   	CInterfaceData* interface = CInterfaceData::NewLC(this);
   1.813 +		interface->InternalizeL(aStore);
   1.814 +		AddL(interface);
   1.815 +	   	CleanupStack::Pop(interface);	// now owned by dll	
   1.816 +		}  	
   1.817 +	iDllEntry = CEComEntry::NewL(*name,secondUid,thirdUid);
   1.818 +	iDllEntry->SetModified(dllModifiedTime);
   1.819 + 	CleanupStack::PopAndDestroy(name);
   1.820 +	}
   1.821 +	
   1.822 +/**
   1.823 +@param			aParent The parent drive data of this implementation
   1.824 +*/	
   1.825 +CRegistryData::CDllData::CDllData( CDriveData* aParent) :
   1.826 +	CBase(),
   1.827 +	iParent(aParent)	
   1.828 +	{
   1.829 +	// Do nothing here
   1.830 +	//Initialize empty capabilities here
   1.831 +	iCapSet.SetEmpty();
   1.832 +	}
   1.833 +
   1.834 +/**
   1.835 +Standard second phase construction function.
   1.836 +@pre 			This object is fully constructed.
   1.837 +@post			This object is fully constructed and initialized.
   1.838 +*/
   1.839 +void CRegistryData::CDllData::ConstructL()
   1.840 +	{
   1.841 +	iIfList = new(ELeave) RInterfaceList(2);
   1.842 +	}
   1.843 +
   1.844 +/**
   1.845 +Standard second phase construction function with parameter.
   1.846 +@param			aDllName the name of this dll
   1.847 +@param			aDllModTime the modified time of this dll
   1.848 +@param 			aSecondUid Distinguishes between components having the same UID1 (which distinguishes between EXEs and DLLs) 
   1.849 +				UID2 identifies Interface Implementation Collections (collection and collection 3)
   1.850 +@param			aThirdUid Identifies a component uniquely. In order to ensure that each binary that needs a distinguishing 
   1.851 +				UID is assigned a genuinely unique value. Symbian manages UID allocation through central database.	
   1.852 +@pre 			This object is fully constructed.
   1.853 +@post			This object is fully constructed and initialized.
   1.854 +*/
   1.855 +void CRegistryData::CDllData::ConstructL(const TDesC& aDllName,const TTime& aDllModTime,const TUid& aSecondUid,const TUid& aThirdUid)
   1.856 +	{
   1.857 +	iIfList = new(ELeave) RInterfaceList(2);
   1.858 +	iDllEntry=CEComEntry::NewL(aDllName,aSecondUid,aThirdUid);
   1.859 +	iDllEntry->SetModified(aDllModTime);
   1.860 +	}
   1.861 +	
   1.862 +	
   1.863 +/**
   1.864 +Populate a caller-supplied TEntry instance with the data from this dll.
   1.865 +@param			aEntry An entry to be populated (destination)
   1.866 +*/
   1.867 +void CRegistryData::CDllData::PopulateAnEntry(TEntry& aEntry) const
   1.868 +	{
   1.869 +	TPtr bufPtr=aEntry.iName.Des();
   1.870 +	bufPtr.Zero();
   1.871 +	bufPtr.Append(iParent->iDrive.Name());
   1.872 +	bufPtr.Append(_L("\\sys\\bin\\"));
   1.873 +	bufPtr.Append(iDllEntry->GetName());
   1.874 +	aEntry.iType	= TUidType(KDynamicLibraryUid,iDllEntry->GetSecondUid(),iDllEntry->GetThirdUid());
   1.875 +	aEntry.iModified= iDllEntry->GetModified();
   1.876 +	}
   1.877 +
   1.878 +
   1.879 +//
   1.880 +// CRegistryData::CDriveData class
   1.881 +
   1.882 +
   1.883 +/**
   1.884 +Creates a new CDriveData object and places it on the CleanupStack
   1.885 +@param			aDrive Information on this drive
   1.886 +@param			aParent A pointer to the parent registry data
   1.887 +@return			A pointer to the newly created class.
   1.888 +@post			This object is fully constructed and initialized and on the CleanupStack.
   1.889 +*/
   1.890 +CRegistryData::CDriveData* CRegistryData::CDriveData::NewLC(TDriveUnit aDrive, CRegistryData* aParent)
   1.891 +	{
   1.892 +	CDriveData* self=new(ELeave) CDriveData(aDrive,aParent);  // calls c'tor
   1.893 +	CleanupStack::PushL(self);	// Make the construction safe by using the cleanup stack
   1.894 +	self->ConstructL(); // Complete the 'construction'.
   1.895 +	return self;
   1.896 +	}
   1.897 +
   1.898 +/**
   1.899 +Destructor of CDriveData
   1.900 +*/
   1.901 +CRegistryData::CDriveData::~CDriveData()
   1.902 +	{
   1.903 +	if(iDllList)
   1.904 +		{
   1.905 +		// Clear the interface list and destroy its objects
   1.906 +		iDllList->ResetAndDestroy();
   1.907 +		delete iDllList;
   1.908 +		iDllList = NULL;
   1.909 +		}
   1.910 +	iParent=NULL;
   1.911 +	}
   1.912 +
   1.913 +/**
   1.914 +Adds the specified CDllData to this drive data in the registry.
   1.915 +@param			aDll The Dll to add to this drive
   1.916 +@pre 			This object is fully constructed.
   1.917 +@post			aDll is added to the list of dll on this drive.
   1.918 +*/
   1.919 +void CRegistryData::CDriveData::AddL(const CDllData* aDll)
   1.920 +	{
   1.921 +	User::LeaveIfError(iDllList->Append(aDll));
   1.922 +	}
   1.923 +
   1.924 +/**
   1.925 +Returns the index of the DLL with this Uid in the Dll list.
   1.926 +@param			aDllUid the UID of to be found DLL.
   1.927 +@return  		The index of this DLL in the DLL list. KErrNotFound if not found.
   1.928 +@pre			This object is fully constructed.
   1.929 +*/
   1.930 +TInt CRegistryData::CDriveData::FindDllIndex(const TUid aDllUid) const
   1.931 +	{
   1.932 +	const TInt dllCount = iDllList->Count();
   1.933 +	for(TInt j = 0; j < dllCount; ++j)
   1.934 +		{
   1.935 +		// For each dll structure check the dll UID
   1.936 +		CDllData* dll = (*iDllList)[j];
   1.937 +		if (aDllUid == dll->iDllEntry->GetThirdUid())
   1.938 +			{
   1.939 +			// it is a match 
   1.940 + 			return j;	 				
   1.941 +			}
   1.942 +		}
   1.943 +	return KErrNotFound;
   1.944 +	}
   1.945 +	
   1.946 +/**
   1.947 +Writes out the state of this CDriveData to file.
   1.948 +@param			aFs A handle to an open file server session.
   1.949 +@param			aDatFileName the dat file to persist to
   1.950 +@pre 			This object is fully constructed.
   1.951 +*/
   1.952 +void CRegistryData::CDriveData::ExternalizeL(RFs& aFs,const TDesC& aDatFileName) 
   1.953 +	{
   1.954 +	// attempt to create the folders if they don't already exist
   1.955 +	TInt mkDirError = aFs.MkDirAll(aDatFileName);
   1.956 +		
   1.957 +	if((mkDirError == KErrNone) || (mkDirError == KErrAlreadyExists))
   1.958 +		{
   1.959 +		RFileWriteStream registryStream;
   1.960 +		if(registryStream.Replace(aFs,aDatFileName, EFileWrite) == KErrNone)
   1.961 +			{
   1.962 +			CleanupClosePushL(registryStream);
   1.963 +			// Write the version number as the first thing in the file stream.
   1.964 +			registryStream.WriteInt32L(KRegVersion);				
   1.965 +			if(iDllList)
   1.966 +				{
   1.967 +				TInt entryCount = iDllList->Count();
   1.968 +				registryStream.WriteInt32L(entryCount);
   1.969 +				// Now stream out the data
   1.970 +				for(TInt i = 0; i < entryCount; ++i)
   1.971 +					((*iDllList)[i])->ExternalizeL(registryStream);
   1.972 +				}
   1.973 +			else
   1.974 +				registryStream.WriteInt32L(0);
   1.975 +			CleanupStack::PopAndDestroy();	// registryStream
   1.976 +			}
   1.977 +		}
   1.978 +	else
   1.979 +		{
   1.980 +		User::Leave(mkDirError);
   1.981 +		}
   1.982 +	}
   1.983 +
   1.984 +/**
   1.985 +Restores the state of this CDriveData from file.
   1.986 +@param			aFs A handle to an open file server session.
   1.987 +@param			aDatFileName the dat file name to internalize from
   1.988 +@pre 			This object is fully constructed.
   1.989 +@post			The state of this object is restored to that specified
   1.990 +				in the file on this drive.
   1.991 +*/
   1.992 +
   1.993 +void CRegistryData::CDriveData::InternalizeL(RFs& aFs,const TDesC& aDatFileName)
   1.994 +	{
   1.995 +	DoInternalizeL(aFs, aDatFileName);  
   1.996 +	}
   1.997 +/**
   1.998 +The method internalizes the data from aRegistryStream.
   1.999 +@param aFileName The ECOM registry file name.
  1.1000 +@leave KErrNoMemory
  1.1001 +@leave Some other system-wide error codes as well.
  1.1002 +*/
  1.1003 +void CRegistryData::CDriveData::DoInternalizeL(RFs& aFs, const TDesC& aFileName)
  1.1004 +	{
  1.1005 +	RFileReadStream registryStream;
  1.1006 +	User::LeaveIfError(registryStream.Open(aFs, aFileName, EFileRead));
  1.1007 +	CleanupClosePushL(registryStream);	
  1.1008 +	// Read in version number. If its not what expected - the file is treated as corrupted.
  1.1009 +	const TInt version = registryStream.ReadInt32L();
  1.1010 +	if(version != KRegVersion)
  1.1011 +		{
  1.1012 +		User::Leave(KErrCorrupt);
  1.1013 +		}	
  1.1014 +	const TInt entryCount = registryStream.ReadInt32L();
  1.1015 +    if(entryCount < 0)
  1.1016 +        {
  1.1017 +        User::Leave(KErrCorrupt);
  1.1018 +        }
  1.1019 +	for(TInt i = 0; i < entryCount; ++i)
  1.1020 +		{
  1.1021 +		CDllData* dll = CDllData::NewLC(this);
  1.1022 +		dll->InternalizeL(registryStream);
  1.1023 +		// always add the DLL, DLL security check will be deferred 
  1.1024 +		// until the DLL is needed.		
  1.1025 +		AddL(dll);
  1.1026 +		CleanupStack::Pop(dll);	// now owned by drive	
  1.1027 +		}
  1.1028 +	CleanupStack::PopAndDestroy();//registryStream
  1.1029 +	}
  1.1030 +	
  1.1031 +/**	
  1.1032 +Constructor for CDriveData
  1.1033 +@param			aDrive Information on this drive
  1.1034 +@param			aParent A pointer to the parent registry data
  1.1035 +*/	
  1.1036 +CRegistryData::CDriveData::CDriveData(TDriveUnit aDrive, CRegistryData* aParent) :
  1.1037 +	CBase(), 
  1.1038 +
  1.1039 +	iDrive(aDrive),
  1.1040 +	iParent(aParent),
  1.1041 +	iDriveChanged(ETrue),
  1.1042 +	iRegistryChanged(EFalse)
  1.1043 +	{
  1.1044 +	}
  1.1045 +
  1.1046 +/**
  1.1047 +Standard second phase construction function.
  1.1048 +@pre 			This object is fully constructed.
  1.1049 +@post			This object is fully constructed and initialized.
  1.1050 +*/
  1.1051 +void CRegistryData::CDriveData::ConstructL()
  1.1052 +	{
  1.1053 +	iDllList = new(ELeave)TDll;
  1.1054 +	}
  1.1055 +	
  1.1056 +//
  1.1057 +// CRegistryData class
  1.1058 +
  1.1059 +/**
  1.1060 +Standardized safe construction which leaves nothing on the cleanup stack.
  1.1061 +This overload is used by CEComImplIndexPerfTest which plots 
  1.1062 +discovery time vs. granularity settings.
  1.1063 +@leave 			KErrNoMemory.	
  1.1064 +@param 			aFs The open file session.
  1.1065 +@param			aInterfaceImplIndexGranularity granularity of main index.
  1.1066 +@param			aImplIndexGranularity granularity of auxiliary index.
  1.1067 +@return			The newly created instance of the registry data.
  1.1068 +@post			CRegistryData is fully constructed, and initialized.
  1.1069 +*/
  1.1070 +CRegistryData* CRegistryData::NewL(RFs& aFs, TInt aInterfaceImplIndexGranularity, TInt aImplIndexGranularity)
  1.1071 +	{
  1.1072 +	CRegistryData* self=new(ELeave) CRegistryData(aFs, aInterfaceImplIndexGranularity, aImplIndexGranularity);  // calls c'tor
  1.1073 +	CleanupStack::PushL(self);	// Make the construction safe by using the cleanup stack
  1.1074 +	self->ConstructL(); // Complete the 'construction'.
  1.1075 +	CleanupStack::Pop(self);
  1.1076 +	return self;
  1.1077 +	}
  1.1078 +
  1.1079 +/**
  1.1080 +Standardized safe construction which leaves nothing on the cleanup stack.
  1.1081 +This overload uses default granularities for the two indexes. These
  1.1082 +default values were found to provide reasonably good performance at
  1.1083 +the time of testing.
  1.1084 +@leave 			KErrNoMemory.	
  1.1085 +@param 			aFs The open file session.
  1.1086 +@return			The newly created instance of the registry data.
  1.1087 +@post			CRegistryData is fully constructed, and initialized.
  1.1088 +*/
  1.1089 +CRegistryData* CRegistryData::NewL(RFs& aFs)
  1.1090 +	{
  1.1091 +	return NewL(aFs, KDefaultInterfaceImplIndexGranularity, KDefaultImplIndexGranularity);
  1.1092 +	}
  1.1093 +
  1.1094 +CRegistryData::~CRegistryData()
  1.1095 +	{
  1.1096 +	for(TInt index = 0; index < iInterfaceImplIndex.Count(); ++index)
  1.1097 +		{
  1.1098 +		iInterfaceImplIndex[index].Reset();
  1.1099 +		}
  1.1100 +	iInterfaceImplIndex.Reset();
  1.1101 +	
  1.1102 +	// Reset only. It does not own the pointers!
  1.1103 +	iImplIndex.Reset();
  1.1104 +
  1.1105 +	if(iRegistrations)
  1.1106 +		{
  1.1107 +		iRegistrations->ResetAndDestroy();
  1.1108 +		delete iRegistrations;
  1.1109 +		iRegistrations = NULL;
  1.1110 +		}
  1.1111 +	// reset the cached language settings
  1.1112 +	RDowngradePath::Reset();
  1.1113 +
  1.1114 +	delete iCachedDriveInfo;
  1.1115 +	}
  1.1116 +
  1.1117 +/**
  1.1118 +Lists the implementations given the interface UID. The filtered list is returned in the client provided
  1.1119 +RImplDataArray parameter.
  1.1120 +@param			aInterfaceUid The Uid of the interface which the implementations should provide
  1.1121 +@param			aImplementationData Return value. The filtered list.
  1.1122 +*/
  1.1123 +void CRegistryData::ListImplementationsL(TUid aInterfaceUid,
  1.1124 +										 RImplDataArray& aImplementationData) const
  1.1125 +	{
  1.1126 +	// If discoveries are taking place then the index is invalid so we cannot do
  1.1127 +	// this request
  1.1128 +	if(iCurrentlyDiscovering)
  1.1129 +		User::Leave(KEComErrListCurrentlyUnavailable);
  1.1130 +    
  1.1131 +	TBool securityPassed = EFalse;
  1.1132 +	//Do the security check
  1.1133 +	TInt index = 0;
  1.1134 +	while (!securityPassed)
  1.1135 +		{
  1.1136 +		aImplementationData.Reset();
  1.1137 +		index = IndexedFind(aInterfaceUid);
  1.1138 +		if(index == KErrNotFound)
  1.1139 +			{
  1.1140 +			User::Leave(KEComErrNoInterfaceIdentified);
  1.1141 +			}
  1.1142 +		User::LeaveIfError(index);
  1.1143 +	
  1.1144 +		TImplContainerArray& implementationList = iInterfaceImplIndex[index].iImpData;
  1.1145 +		for (TInt j = 0; j < implementationList.Count(); j++)
  1.1146 +			{
  1.1147 +			CImplementationData* currentImplementation = implementationList[j].iCurrentImpl;
  1.1148 +			CDllData* dll = currentImplementation->iParent->iParent;
  1.1149 +			
  1.1150 +			securityPassed = dll->ProcessSecurityCheckL();
  1.1151 +			if(!securityPassed)
  1.1152 +				{
  1.1153 +				// remove the implementations of the DLL from iInterfaceImplIndex
  1.1154 +				// and remove the DLL from its parent DLL list.
  1.1155 +				DeleteDllL(dll);
  1.1156 +				delete dll;
  1.1157 +				dll = NULL;
  1.1158 +				// don't continue processing implementations after we have deleted the DLL
  1.1159 +				// because the implementations list will have changed, so we need to 
  1.1160 +				// re-do the IndexedFind
  1.1161 +				break;	
  1.1162 +				}
  1.1163 +			else
  1.1164 +				{
  1.1165 +				User::LeaveIfError(aImplementationData.Append(currentImplementation));
  1.1166 +				}	
  1.1167 +			}
  1.1168 +		}
  1.1169 +	}
  1.1170 +
  1.1171 +/**
  1.1172 +Enables or disables the specified interface implementation within the registry.
  1.1173 +@param			aImplementationUid The interface implementation to change.
  1.1174 +@param			aState ETrue to enable the implementation, EFalse to disable it
  1.1175 +@return			KErrNone, KEComErrEnableFailed or KEComErrDisableFailed
  1.1176 +@pre 			CRegistry is fully constructed,
  1.1177 +@post			The implementation is now enabled or disabled as described 
  1.1178 +				by aState.
  1.1179 +*/
  1.1180 +TInt CRegistryData::SetEnabledState(TUid aImplementationUid, TBool aState)
  1.1181 +	{
  1.1182 +	CImplementationData* impData = NULL;
  1.1183 +	TUid dummy={0x00000000};
  1.1184 +	
  1.1185 +	(void)FindImplementation(aImplementationUid, dummy, impData);
  1.1186 +
  1.1187 +	if(impData != NULL)
  1.1188 +		{
  1.1189 +		impData->iImplInfo->SetDisabled((aState) ? EFalse : ETrue);
  1.1190 +		return KErrNone;
  1.1191 +		}
  1.1192 +
  1.1193 +    return (aState) ? KEComErrEnableFailed : KEComErrDisableFailed;
  1.1194 +	}
  1.1195 +
  1.1196 +
  1.1197 +/**
  1.1198 +Temporarily uninstalls the interface implementation groups upon the specified drive.
  1.1199 +(ie this can be undone later).
  1.1200 +@param			aDrive	The identifier of the drive to uninstall.
  1.1201 +@pre 			CRegistry is fully constructed
  1.1202 +@post			The registered implementation groupings
  1.1203 +				stored upon the specified drive are no 
  1.1204 +				longer available for use.
  1.1205 +*/
  1.1206 +void CRegistryData::TemporaryUninstallL(const TDriveUnit& aDrive)
  1.1207 +	{
  1.1208 +	// Find the appropriate drive entry and remove it...
  1.1209 +	// Note : the drive may have already been taken offline, so no save is possible!
  1.1210 +	CDriveData* drive = NULL;
  1.1211 +	TInt driveIndex = FindDriveL(aDrive, drive);
  1.1212 +	if(driveIndex != KErrNotFound)
  1.1213 +		{
  1.1214 +    	TInt dllIndex = drive->iDllList->Count();
  1.1215 +		while(dllIndex > 0)
  1.1216 +			{
  1.1217 +			--dllIndex;
  1.1218 +			RemoveFromIndexL((*drive->iDllList)[dllIndex]);
  1.1219 +			}       
  1.1220 +		iRegistrations->Remove(driveIndex);
  1.1221 +		delete drive;
  1.1222 +
  1.1223 +		DriveChanged(aDrive, ETrue);
  1.1224 +		}
  1.1225 +	// The flag iRegistryChanged has been moved to each drive.
  1.1226 +	}
  1.1227 +
  1.1228 +/**
  1.1229 +Undoes a temporary uninstall of the interface 
  1.1230 +implementation groups upon the specified drive.
  1.1231 +(ie this can be undone later).
  1.1232 +@leave			KErrNoMemory, KErrReinstallFailed.
  1.1233 +@param			aDrive	The identifier of the drive to reinstate.
  1.1234 +@pre 			CRegistry is fully constructed
  1.1235 +@post			The registered implementation groupings
  1.1236 +				stored upon the specified drive are again 
  1.1237 +				made available for use.
  1.1238 +*/
  1.1239 +void CRegistryData::UndoTemporaryUninstallL(const TDriveUnit& aDrive)
  1.1240 +	{
  1.1241 +	CDriveData* driveData = NULL;
  1.1242 +	// If the drive was not found then install it, otherwise do nothing because it
  1.1243 +	// is already there.  NB. We could leave here but the problem with that is the 
  1.1244 +	// use case where the drive has been mounted during registry load but the registrar 
  1.1245 +	// is started afterwards, and makes calls to this method as it discovers drives 
  1.1246 +	// for the first time. 
  1.1247 +	if(FindDriveL(aDrive, driveData) == KErrNotFound)
  1.1248 +		{
  1.1249 +		// Add the drive entry
  1.1250 +		CDriveData* drive = CDriveData::NewLC(aDrive,this);
  1.1251 +		AddImplDataL(drive);
  1.1252 +		User::LeaveIfError(iRegistrations->Append(drive));
  1.1253 +		CleanupStack::Pop(drive);		// now owned by iRegistrations
  1.1254 +
  1.1255 +		DriveChanged(aDrive, EFalse);
  1.1256 +
  1.1257 +		// NB We DO need to set iRegistryChanged = ETrue because the idx file needs to be
  1.1258 +		// rewritten to include the reinstalled drive
  1.1259 +		}
  1.1260 +	}
  1.1261 +	
  1.1262 +/** 
  1.1263 +Update the staus of drives in the system
  1.1264 +@param 	aDrive The drive that has changed
  1.1265 +@param 	aDriveRemoved Indicates whether a drive has been removed or added
  1.1266 +@pre 	CRegistry is fully constructed.
  1.1267 +@post	The state of the drive has been stored
  1.1268 +*/
  1.1269 +void CRegistryData::DriveChanged(const TDriveUnit& aDrive, TBool aDriveRemoved)
  1.1270 +	{
  1.1271 +	if(aDriveRemoved)
  1.1272 +		{
  1.1273 +		iRemovedDrives |= (0x1 << aDrive);
  1.1274 +		}
  1.1275 +	else
  1.1276 +		{
  1.1277 +		iRemovedDrives &= ~(0x1 << aDrive);
  1.1278 +		}
  1.1279 +	}
  1.1280 +
  1.1281 +/** 
  1.1282 +Find if any Dll is regsitered in the drive unit.
  1.1283 +@param aDrive The identifier of the drive to find if any Dll is registered.
  1.1284 +@return ETrue if any Dll is registered in the drive, otherwise EFalse.
  1.1285 +@pre 			CRegistry is fully constructed.
  1.1286 +@post			If any Dll is registered in the drive is returned if successfully.
  1.1287 +*/
  1.1288 +TBool CRegistryData::IsAnyDllRegisteredWithDriveL(const TDriveUnit& aDrive)const
  1.1289 +	{
  1.1290 +	CDriveData* driveData = NULL;
  1.1291 +	if(FindDriveL(aDrive, driveData) == KErrNotFound)
  1.1292 +		{
  1.1293 +		User::Leave(KEComErrDriveNotFound);	
  1.1294 +		}
  1.1295 +	return driveData->iDllList->Count() > 0;
  1.1296 +	}
  1.1297 +	
  1.1298 +/**
  1.1299 +Determine if the specified implementation grouping already registered, but needs an update.
  1.1300 +@param			aDllUid The interface implementation collection data to add. 
  1.1301 +				CRegistryData takes ownership of this object
  1.1302 +				so it should not be on the CleanupStack.
  1.1303 +@param			aModified The date of the last modification of the Interface 
  1.1304 +				Implementation Collection. 
  1.1305 +@param			aUpdate An output to indicate if the registry entry requires an update. 
  1.1306 +				(Only valid if the return is ETrue).
  1.1307 +@param			aDriveData The drive data used to find DLL.
  1.1308 +@return			ETrue if the Interface Implementation Collection already has a registry entry.
  1.1309 +				EFalse otherwise.
  1.1310 +@pre 			This object is fully constructed and there is also a valid drive entry
  1.1311 +				in the registry for aDrive
  1.1312 +@post			The new data is added to the registry
  1.1313 +*/
  1.1314 +TBool CRegistryData::IsRegisteredWithDate (TUid aDllUid, 
  1.1315 +										   	const TTime& aModified, 
  1.1316 +										   	TBool& aUpdate, 
  1.1317 +										   	CDriveData* aDriveData)
  1.1318 +	{
  1.1319 +	// Find the appropriate drive entry for this 
  1.1320 +	// Interface Implementation Collection
  1.1321 +	TBool found = EFalse;
  1.1322 +	TInt index = aDriveData->FindDllIndex(aDllUid);
  1.1323 +	if(index != KErrNotFound)
  1.1324 +		{
  1.1325 +		TDll* dllList = aDriveData->iDllList;
  1.1326 +		CDllData* dll = (*dllList)[index];
  1.1327 +		const CEComEntry& dllEntry =*(dll->iDllEntry);	
  1.1328 +		aUpdate = dllEntry.GetModified().Int64() < aModified.Int64(); 
  1.1329 +		found = ETrue;
  1.1330 +		}
  1.1331 +	return found;
  1.1332 +	}
  1.1333 +
  1.1334 +/**
  1.1335 +Adds data on a specific dll to the registry. The data to be added
  1.1336 +is parsed by CRegistryParser.
  1.1337 +@leave			KErrNoMemory If the item could not be appended to the registry
  1.1338 +@leave			KEComErrDriveNotFound If aDrive is not a valid drive
  1.1339 +@param			aDrive The drive the registry data has been found on 
  1.1340 +@param			aFoundDriveIndex The index of the registry data for the drive 
  1.1341 +				the interface implementation collection data has been found on.
  1.1342 +@param			aDllData The dll data to add. CRegistryData takes ownership of this object
  1.1343 +				so it should not be on the CleanupStack.
  1.1344 +@pre 			This object is fully constructed and there is also a valid drive entry
  1.1345 +				in the registry for aDrive
  1.1346 +@post			The new data is added to the registry
  1.1347 +*/
  1.1348 +void CRegistryData::AddDllDataL(const TDriveUnit& aDrive, TInt aFoundDriveIndex, CRegistryData::CDllData* aDllData)
  1.1349 +	{
  1.1350 +	const TInt regCount = iRegistrations->Count();
  1.1351 +	if(regCount == 0)
  1.1352 +		User::Leave(KEComErrDriveNotFound);
  1.1353 +
  1.1354 +	// Find the appropriate drive entry
  1.1355 +	CDriveData* drive = NULL;
  1.1356 +	if(aFoundDriveIndex == KErrNotFound)
  1.1357 +		{
  1.1358 +		if(FindDriveL(aDrive, drive) == KErrNotFound)
  1.1359 +			User::Leave(KEComErrDriveNotFound);
  1.1360 +		}
  1.1361 +	else
  1.1362 +		drive = (*iRegistrations)[aFoundDriveIndex];
  1.1363 +	
  1.1364 +	// Append the new data to the list
  1.1365 +	TDll* dllList = drive->iDllList;
  1.1366 +	
  1.1367 +	// NOTE : This function MUST NOT leave after the following line because 
  1.1368 +	// aDllData will potentially be 'owned' in two places (dllList and the caller) 
  1.1369 +	// until we return and the caller can Pop.
  1.1370 +	TBool checkNeeded = ETrue;
  1.1371 +	TInt ifListCount=aDllData->iIfList->Count();
  1.1372 +	for(TInt ifListCounter=0; ifListCounter < ifListCount; ifListCounter++)
  1.1373 +		{
  1.1374 +		// For each interface structure
  1.1375 +		CInterfaceData* interface = (*aDllData->iIfList)[ifListCounter];
  1.1376 +		for(TInt impNum = 0; impNum < interface->iImplementations->Count(); ++impNum)
  1.1377 +			{
  1.1378 +			CImplementationData* implData = (*interface->iImplementations)[impNum];
  1.1379 +			if(!InsertIntoIndexL(implData,checkNeeded))
  1.1380 +				{
  1.1381 +				interface->iImplementations->Remove(impNum); //remove from implementation array
  1.1382 +				delete implData; //delete object
  1.1383 +				}	
  1.1384 +			}
  1.1385 +		}
  1.1386 +	//add filtered list for legitimate implementations into registry
  1.1387 +	User::LeaveIfError(dllList->Append(aDllData)); 
  1.1388 +		
  1.1389 +	drive->iRegistryChanged = ETrue;	
  1.1390 +	}
  1.1391 +
  1.1392 +/**
  1.1393 +Updates the data for a dll in the registry.
  1.1394 +@leave			KErrNoMemory If the indexes cannot be rebuilt
  1.1395 +@param			aFoundDriveIndex The index of the registry data for the drive 
  1.1396 +				the interface implementation collection data has been found on.
  1.1397 +@param			aDllData The updated interface implementation collection data. 
  1.1398 +				CRegistryData takes ownership of this object
  1.1399 +				so it should not be on the CleanupStack.
  1.1400 +@pre 			This object is fully constructed
  1.1401 +@post			The dll data is updated in the registry
  1.1402 +*/
  1.1403 +void CRegistryData::UpdateDllDataL(const TDriveUnit& aDrive,TInt aFoundDriveIndex, CDllData* aDllData)
  1.1404 +	{
  1.1405 +	const TInt regCount = iRegistrations->Count();
  1.1406 +	if(regCount == 0)
  1.1407 +		User::Leave(KEComErrDriveNotFound);
  1.1408 +
  1.1409 +	// Find the appropriate drive entry
  1.1410 +	CDriveData* drive = (*iRegistrations)[aFoundDriveIndex];
  1.1411 +	
  1.1412 +	TInt index = drive->FindDllIndex(aDllData->iDllEntry->GetThirdUid());
  1.1413 +	
  1.1414 +	// find the dll entry and clear that too
  1.1415 +	if(index != KErrNotFound)
  1.1416 +		{
  1.1417 +		// Ok its a match, so remove this registry entry and call AddDllData()
  1.1418 +		//to add the new dll
  1.1419 +		TDll* dllList = drive->iDllList;
  1.1420 +		CDllData* olddll = (*dllList)[index];
  1.1421 +		//remove 'old'implementations from iInterfaceImplIndex
  1.1422 + 		RemoveFromIndexL(olddll);
  1.1423 + 		//now remove old dll from the array and registry
  1.1424 + 		dllList->Remove(index);
  1.1425 +   		delete olddll;
  1.1426 +   		AddDllDataL(aDrive,aFoundDriveIndex,aDllData);
  1.1427 +   		drive->iRegistryChanged = ETrue;
  1.1428 +
  1.1429 +		}
  1.1430 +	if (index == KErrNotFound)
  1.1431 +	    {
  1.1432 +        __ECOM_TRACE("ECOM: PANIC in CRegistryData::UpdateDllDataL(), expected DLL data missing from ECOM registry");
  1.1433 +	    __ASSERT_DEBUG(EFalse, User::Panic (KEComServerPanicCategory, EEComPanic_CRegistryData_UpdateDllDataL_DllRegistrationMissing));
  1.1434 +	    }
  1.1435 +	}
  1.1436 +
  1.1437 +/**
  1.1438 +The cue that newly discovered Dlls are about to be registered, 
  1.1439 +and, therefore, the registry index will be out of date until 
  1.1440 +DiscoveriesCompleteL is called.
  1.1441 +@pre 			CRegistrar is fully constructed
  1.1442 +@post			iCurrentlyDiscovering is set and the index list is cleared.
  1.1443 +*/
  1.1444 +void CRegistryData::DiscoveriesBeginning() const
  1.1445 +	{
  1.1446 +	iCurrentlyDiscovering = ETrue;
  1.1447 +	// The registry is about to start changing so the index is now invalid
  1.1448 +	}
  1.1449 +
  1.1450 +/**
  1.1451 +The cue to rebuild the registry indexes
  1.1452 +@leave			KErrNoMemory
  1.1453 +@see 			CStore
  1.1454 +@param			aSuccessful Indicates whether discovery completed fully or not
  1.1455 +@param			aProcessingType indicates the type of processing for plugins
  1.1456 +				for ensuring that plugins are not processed multiple times
  1.1457 +				during start-up phase
  1.1458 +@param			aHasRegistryChanged The flag to indicate whether registry data has been changed 
  1.1459 +@pre 			CRegistrar is fully constructed
  1.1460 +@post			The internal access indexes have been rebuilt
  1.1461 +*/
  1.1462 +void CRegistryData::DiscoveriesCompleteL(TBool aSuccessful, TPluginProcessingTypeIdentifier aProcessingType, TBool& aHasRegistryChanged)
  1.1463 +	{
  1.1464 +	iCurrentlyDiscovering = EFalse;
  1.1465 +	if (!aSuccessful)
  1.1466 +		{
  1.1467 +		return;
  1.1468 +		}
  1.1469 +	//if the rediscovery is a result of iLanguageChanged, we should reset it to false
  1.1470 +	iLanguageChanged=EFalse;		
  1.1471 +	// Warning: this method may be called from the CEComServer destructor.
  1.1472 +	// E.g. ecomservertest running OOM test on CEComServer::NewLC.
  1.1473 +	// The call stack: 
  1.1474 +	// ~CEComServer delete iRegistrar, ~CRegistrar delete iDiscoverer,
  1.1475 +	// ~CDiscoverer calls CRegistrar::DiscoveriesComplete,
  1.1476 +	// then here.
  1.1477 +    // Hence if ! aSuccessful do not validate.
  1.1478 +
  1.1479 +	if(aProcessingType != EPluginProcessingTypeCriticalOnly)
  1.1480 +		{
  1.1481 +		ValidateRegistryL();
  1.1482 +		}
  1.1483 +	if(aProcessingType==EPluginProcessingTypeNonCriticalOnly || aProcessingType==EPluginProcessingTypeAll)
  1.1484 +		{
  1.1485 +		//first find whether there is any registry data changed
  1.1486 +		TInt regCount=iRegistrations->Count();
  1.1487 +		for(TInt i = 0; i <regCount; i++)
  1.1488 +			{
  1.1489 +			if ((*iRegistrations)[i]->iRegistryChanged)
  1.1490 +				{
  1.1491 +	 			aHasRegistryChanged = ETrue;
  1.1492 +	 			//now having cached that the registry has changed we need
  1.1493 +	 			//to reset this flag in ALL the CDriveData, note that it is
  1.1494 +	 			//possible that more than one drive will have the flag set
  1.1495 +	 			(*iRegistrations)[i]->iRegistryChanged=EFalse;
  1.1496 +				}
  1.1497 +			}
  1.1498 +			//Also indicate registry change if any drives have been removed
  1.1499 +			aHasRegistryChanged |= (iRemovedDrives != 0);
  1.1500 +			iRemovedDrives = 0;
  1.1501 +		}
  1.1502 +	}
  1.1503 +
  1.1504 +/**
  1.1505 +	@fn 			SetDiscoveryFlag(const TDriveUnit aDrive)
  1.1506 +	Intended Usage	: Set the flag to indicate the drive has change(s)
  1.1507 +	Error Condition	: None.
  1.1508 +	@param 			aDrive The identifier of the drive changed.
  1.1509 +	@pre 			The CRegistrar must be fully constructed
  1.1510 +	@post			The flag is set.				 
  1.1511 +*/
  1.1512 +
  1.1513 +void CRegistryData::SetDiscoveryFlagL(const TDriveUnit& aDriveUnit)
  1.1514 +	{
  1.1515 +	CDriveData* drive = NULL;
  1.1516 +	TInt driveIndex = FindDriveL(aDriveUnit, drive);
  1.1517 +	if(driveIndex != KErrNotFound)
  1.1518 +		{
  1.1519 +		drive->iDriveChanged = ETrue;
  1.1520 +		}
  1.1521 +	
  1.1522 +	}
  1.1523 +/**
  1.1524 +Indicates whether the registry index is currently valid.  The 
  1.1525 +index will not be valid if discoveries are currently taking place.
  1.1526 +If the index is not currently valid then calls to 
  1.1527 +ListImplementationsL() cannot be serviced.
  1.1528 +@return			ETrue if the index is currently valid, EFalse otherwise.
  1.1529 +@pre 			CRegistrar is fully constructed
  1.1530 +*/
  1.1531 +TBool CRegistryData::IndexValid() const
  1.1532 +	{
  1.1533 +	return !iCurrentlyDiscovering;
  1.1534 +	}
  1.1535 +
  1.1536 +/**
  1.1537 +@param			aCapabilitySet A capability set
  1.1538 +@param			aImplUid The Uid of the implementation for which info is required
  1.1539 +@param			aInterfaceUid The uid of the interface associated with aImplUid to find or less than
  1.1540 +				0 if uid is unknown.
  1.1541 +@param			aEntry Output parameter which will contain the dll information
  1.1542 +@param			aImplInfo An output parameter. If the call succeeds it will point to the found implementation information,
  1.1543 +				NULL otherwise.
  1.1544 +@param			aIsOnRWDrive an output parameter. If the call is successful, this will
  1.1545 +				be set to ETrue if the implementation is on RW drive. EFalse if the
  1.1546 +				implementation is on ReadOnly drive.
  1.1547 +@return			KErrNone if the call succeeds, KErrNotFound - no implementation found, 
  1.1548 +				KErrPermissionDenied - the caller has not enough capabilities to load the plugin.
  1.1549 +@pre			CRegistrar is fully constructed
  1.1550 +*/
  1.1551 +TInt CRegistryData::GetImplementationDllInfoForServer(
  1.1552 +	const TCapabilitySet& /*aCapabilitySet*/,
  1.1553 +	const TUid aImplUid,
  1.1554 +	const TUid aInterfaceUid,	
  1.1555 +	TEntry& aEntry,
  1.1556 +	CImplementationInformation*& aImplInfo,
  1.1557 +	TBool& aIsOnRWDrive) const
  1.1558 +	{
  1.1559 +	aImplInfo = NULL;
  1.1560 +	CImplementationData* implData;
  1.1561 +	
  1.1562 +	TInt res = FindImplementation(aImplUid, aInterfaceUid, implData);
  1.1563 +	if (KErrNone != res)
  1.1564 +		{
  1.1565 +		return res;
  1.1566 +		}
  1.1567 +	
  1.1568 +	aImplInfo = implData->iImplInfo;
  1.1569 +	const CDllData* dll = implData->iParent->iParent;
  1.1570 +	dll->PopulateAnEntry(aEntry);
  1.1571 +
  1.1572 +	TEComCachedDriveInfoIterator iter(*iCachedDriveInfo);
  1.1573 +	if (! iter.SetPos(dll->iParent->iDrive))
  1.1574 +		{
  1.1575 +		res = KErrNotFound;
  1.1576 +		}
  1.1577 +	else
  1.1578 +		{
  1.1579 +		aIsOnRWDrive = iter.DriveIsWritable();
  1.1580 +		}
  1.1581 +	return res;
  1.1582 +	}
  1.1583 +
  1.1584 +/**
  1.1585 +@param			aClientRequest A client request
  1.1586 +@param			aImplUid The Uid of the implementation for which info is required
  1.1587 +@param			aInterfaceUid The uid of the interface associated with aImplUid to find or less than
  1.1588 +				0 if uid is unknown.
  1.1589 +@param			aEntry Output parameter which will contain the dll information
  1.1590 +@param			aImplInfo An output parameter. If the call succeeds it will point to the found implementation information,
  1.1591 +				NULL otherwise.
  1.1592 +@param			aSecurityCheckNeeded The bool value to identify whether the security check is needed here. The default value is false.				
  1.1593 +@return			KErrNone if the call succeeds, KErrNotFound - no implementation found,
  1.1594 +				KErrPermissionDenied - the caller has not enough capabilities to load the plugin.
  1.1595 +@pre			CRegistrar is fully constructed
  1.1596 +*/
  1.1597 +TInt CRegistryData::GetImplementationDllInfoForClientL(
  1.1598 +	const TClientRequest& aClientRequest,
  1.1599 +	const TUid aImplUid,
  1.1600 +	const TUid aInterfaceUid,	
  1.1601 +	TEntry& aEntry,
  1.1602 +	CImplementationInformation*& aImplInfo,
  1.1603 +	TBool aSecurityCheckNeeded)const
  1.1604 +	{
  1.1605 +	aImplInfo = NULL;
  1.1606 +	TInt res = KErrNotFound;
  1.1607 +	CImplementationData* implData;
  1.1608 +	if (!aSecurityCheckNeeded)
  1.1609 +		{
  1.1610 +		//The security check has been done already. All the invalid dll have been removed.
  1.1611 +		res = FindImplementation(aImplUid, aInterfaceUid, implData);
  1.1612 +		if (KErrNone != res)
  1.1613 +			{
  1.1614 +			return res;
  1.1615 +			}
  1.1616 +		CDllData* dll = implData->iParent->iParent;
  1.1617 +		dll->PopulateAnEntry(aEntry);
  1.1618 +		aImplInfo = implData->iImplInfo;
  1.1619 +		}
  1.1620 +	else
  1.1621 +		{
  1.1622 +		TBool securityPassed = EFalse;
  1.1623 +		while(!securityPassed) // go out of this loop either Security check is passed or no DLL found.
  1.1624 +			{
  1.1625 +			res = FindImplementation(aImplUid, aInterfaceUid, implData);
  1.1626 +			if (KErrNone != res)
  1.1627 +				{
  1.1628 +				return res;
  1.1629 +				}
  1.1630 +			CDllData* dll = implData->iParent->iParent;
  1.1631 +			// security check is deferred to here.
  1.1632 +			securityPassed = dll->ProcessSecurityCheckL();
  1.1633 +			if(securityPassed)
  1.1634 +				{
  1.1635 +				if (!aClientRequest.CheckCapability(dll->iCapSet, *(implData->iImplInfo)))
  1.1636 +					{
  1.1637 +					return KErrPermissionDenied;
  1.1638 +					}
  1.1639 +				dll->PopulateAnEntry(aEntry);
  1.1640 +				aImplInfo = implData->iImplInfo;
  1.1641 +				}
  1.1642 +			else
  1.1643 +				{
  1.1644 +				// remove the implementations of the DLL from iInterfaceImplIndex
  1.1645 +				// and remove the DLL from its parent DLL list.
  1.1646 +				DeleteDllL(dll);
  1.1647 +				delete dll;
  1.1648 +				dll = NULL;
  1.1649 +				}
  1.1650 +			}
  1.1651 +		}
  1.1652 +	return res;
  1.1653 +	}
  1.1654 +
  1.1655 +/**
  1.1656 +This method removes all implementations of This Dll from the iInterfaceImplIndex,
  1.1657 +then delete this Dll from its parent Dll list.
  1.1658 +@param	aDllData the Dll to be cleaned.
  1.1659 +@pre	CRegistrar is fully constructed	
  1.1660 +*/
  1.1661 +void CRegistryData::DeleteDllL(CDllData* aDllData) const
  1.1662 +	{
  1.1663 +	// find the index of the passed aDllData in its parent's Dll list.
  1.1664 +	TInt index = aDllData->iParent->FindDllIndex(aDllData->iDllEntry->GetThirdUid());
  1.1665 +	
  1.1666 +	//removes all implementations of This Dll from the iInterfaceImplIndex
  1.1667 +	RemoveFromIndexL(aDllData);
  1.1668 +	if(index != KErrNotFound)
  1.1669 +		{
  1.1670 +		//now remove the dll from the array and registry
  1.1671 +		TDll* dllList = aDllData->iParent->iDllList;
  1.1672 +		dllList->Remove(index);
  1.1673 +		}
  1.1674 +	}
  1.1675 +
  1.1676 +
  1.1677 +/**
  1.1678 +Indicates whether the language downgrade path has changed.
  1.1679 +This means we need to call NearestLanguageFile again
  1.1680 +@return			ETrue if the language downgrade path has changed, EFalse otherwise.
  1.1681 +@pre 			CRegistrar is fully constructed
  1.1682 +*/
  1.1683 +TBool CRegistryData::HasLanguageChanged() const
  1.1684 +	{
  1.1685 +	return iLanguageChanged;
  1.1686 +	}
  1.1687 +
  1.1688 +	
  1.1689 +/**
  1.1690 +@param 			aFs A handle to a connected file server.
  1.1691 +*/
  1.1692 +CRegistryData::CRegistryData(RFs& aFs,
  1.1693 +							 TInt aInterfaceImplIndexGranularity,
  1.1694 +							 TInt aImplIndexGranularity) :
  1.1695 +	CBase(), 
  1.1696 +	iFs(aFs),
  1.1697 +	iInterfaceImplIndex(aInterfaceImplIndexGranularity),
  1.1698 +	iImplIndex(aImplIndexGranularity)
  1.1699 +	{
  1.1700 +	}
  1.1701 +
  1.1702 +
  1.1703 +/**
  1.1704 +Completes the safe construction of the CRegistryData object.
  1.1705 +@leave 			KErrNoMemory.
  1.1706 +@pre 			This object is constructed
  1.1707 +@post			This object is fully initialized
  1.1708 +*/
  1.1709 +void CRegistryData::ConstructL()
  1.1710 +	{
  1.1711 +	iCachedDriveInfo = CEComCachedDriveInfo::NewL(iFs);
  1.1712 +
  1.1713 +	// Construction of the empty registration data structure here
  1.1714 +	iRegistrations = new(ELeave)TRegistration;
  1.1715 +	iSystemDrive=iFs.GetSystemDrive();	
  1.1716 +	// during construction we always need to call this function in
  1.1717 +	// order to initialise and store the language settings at boot time
  1.1718 +	TRAPD(err,iLanguageChanged=RDowngradePath::HasChangedL(iFs))
  1.1719 +	if (err==KErrNoMemory)
  1.1720 +		{
  1.1721 +		User::LeaveNoMemory();
  1.1722 +		}
  1.1723 +	}
  1.1724 +
  1.1725 +/**
  1.1726 +To find the index entry for aImplementationUid.
  1.1727 +@return			The index of the item or KErrIndexEntryNotFound. 
  1.1728 +@pre 			This object is fully constructed
  1.1729 +*/
  1.1730 +TInt CRegistryData::IndexedFind(TUid aInterfaceUid) const
  1.1731 +	{
  1.1732 +	// Find the correct implementation
  1.1733 +	TInterfaceIndex key;
  1.1734 +	key.iInterfaceUid = aInterfaceUid;
  1.1735 +	return iInterfaceImplIndex.FindInOrder(key,TLinearOrder<TInterfaceIndex>(TInterfaceStruct::CompareInfUid));
  1.1736 +	}
  1.1737 +
  1.1738 +/**
  1.1739 +Used by a TIdentityRelation to decide if two CDriveData match.
  1.1740 +@return 		ETrue if the TDriveUnit inside the indexes match.
  1.1741 +@param			aIndexOne The first CDriveData to compare
  1.1742 +@param			aIndexTwo The second CDriveData to compare
  1.1743 +*/
  1.1744 +TBool CRegistryData::MatchOnDrive(const CRegistryData::CDriveData& aIndexOne, 
  1.1745 +								  const CRegistryData::CDriveData& aIndexTwo)
  1.1746 +	{
  1.1747 +	return aIndexOne.iDrive == aIndexTwo.iDrive;
  1.1748 +	}
  1.1749 +
  1.1750 +TInt CRegistryData::FindDriveL(const TDriveUnit& aDrive,
  1.1751 +							   CRegistryData::CDriveData*& aDriveData)const 
  1.1752 +	{
  1.1753 +	TInt index = KErrNotFound;
  1.1754 +
  1.1755 +	// Set up the find parameters
  1.1756 +	TIdentityRelation<CRegistryData::CDriveData> identity(MatchOnDrive);
  1.1757 +    CDriveData* driveToMatch = CDriveData::NewLC(aDrive,const_cast<CRegistryData*>(this));
  1.1758 +
  1.1759 +	index = iRegistrations->Find(driveToMatch, identity);
  1.1760 +	
  1.1761 +	CleanupStack::PopAndDestroy(driveToMatch);
  1.1762 +
  1.1763 +	if(index != KErrNotFound)
  1.1764 +		aDriveData = (*iRegistrations)[index];
  1.1765 +	else
  1.1766 +		aDriveData = NULL;
  1.1767 +
  1.1768 +	return index;
  1.1769 +	}
  1.1770 +
  1.1771 +/**
  1.1772 +Finds the instance of CImplementationData for given impl uid and interface uid if known.
  1.1773 +@return			KErrNone if impl found, otherwise KErrNotFound.
  1.1774 +@param			aImplUid The uid of the impl to find
  1.1775 +@param			aInterfaceUid The uid of the interface associated with the impl to find or less than
  1.1776 +				0 if uid is unknown
  1.1777 +@param			aImplData Set to the instance CImplementationData found in the index or if
  1.1778 +				not found set to NULL. This argument is always overwritten.
  1.1779 +*/
  1.1780 +TInt CRegistryData::FindImplementation(const TUid aImplUid, const TUid aInterfaceUid, 
  1.1781 +												CImplementationData*& aImplData) const
  1.1782 +	{
  1.1783 +	aImplData = NULL;
  1.1784 +	TInt i;
  1.1785 +	// Index is kept up to date even when discoveries are occurring
  1.1786 +	// therefore always search index for implementation
  1.1787 +
  1.1788 +	// if aInterfaceUid is non zero use it to find position in index list
  1.1789 +	if(aInterfaceUid.iUid != 0)
  1.1790 +		{
  1.1791 +		i = IndexedFind(aInterfaceUid);
  1.1792 +		if(i == KErrNotFound)
  1.1793 +			{
  1.1794 +			return KErrNotFound;
  1.1795 +			}
  1.1796 +		
  1.1797 +		TInterfaceIndex listItem = iInterfaceImplIndex[i];
  1.1798 +		i = listItem.iImpData.FindInOrder(aImplUid,
  1.1799 +			TImplStruct::CompareUidAgainstImplStruct);
  1.1800 +		if (i >= 0)
  1.1801 +			{
  1.1802 +			aImplData = listItem.iImpData[i].iCurrentImpl;
  1.1803 +			return KErrNone;
  1.1804 +			}
  1.1805 +		}
  1.1806 +	else // not given I/F UID. Use the iImplIndex.
  1.1807 +		{
  1.1808 +		// NB: 1. Impl UID should be globally unique. It is an error if impls
  1.1809 +		// have same Impl UID but different i/f UIDs. It means one of the 
  1.1810 +		// plug-in supplier made an error in the .RSS file or it could be a
  1.1811 +		// deliberate attach. But to maintain backward compatibility, ECOM
  1.1812 +		// allows this error.
  1.1813 +		// (Multiple impls can have same i/f UID and same Impl UID. That is
  1.1814 +		//  the upgrade situation and only one of them get stored in iImplIndex.)
  1.1815 +
  1.1816 +		// 2. Entries in iImplIndex are ordered by Impl UID, and if duplicated,
  1.1817 +		// ordered by i/f UID. Here i/f UID is wild card. The situation is 
  1.1818 +		// analogous to the array was built with InsertInOrderAllowRepeats.
  1.1819 +		// RPointerArray::SpecificFindInOrder is for ordered search in array
  1.1820 +		// with duplicates. Note: it is very expensive to instantiate
  1.1821 +		// a CImplementationData* just for binary search. Hence reinterpret
  1.1822 +		// cast the TUid* as CImplementationData*. CompareUidAgainstImplData
  1.1823 +		// knows to cast the first argument back to TUid.
  1.1824 +		i = iImplIndex.SpecificFindInOrder(
  1.1825 +			reinterpret_cast<const CImplementationData*>(&aImplUid), 
  1.1826 +			TLinearOrder<CImplementationData>(CImplementationData::CompareUidAgainstImplData),
  1.1827 +			EArrayFindMode_First);
  1.1828 +		if (i == KErrNotFound)
  1.1829 +			{
  1.1830 +			return KErrNotFound;
  1.1831 +			}
  1.1832 +
  1.1833 +		aImplData = iImplIndex[i];
  1.1834 +
  1.1835 +		// If duplicates exist, they are sorted according to i/f UID
  1.1836 +		// but we cannot take advantage of this order. To miniize risk
  1.1837 +		// of malware using duplicate Impl UID as DOS attack, ECOM applies
  1.1838 +		// the rule that ROMBased plug-in preferred over non-ROMBased,
  1.1839 +		// higher drive letter preferred over lower drive letter, and 
  1.1840 +		// lastly lower i/f UID preferred over higher i/f UID. Must visit
  1.1841 +		// every duplicate to compare their ROMBasedness and driver letter
  1.1842 +
  1.1843 +		TInt count = iImplIndex.Count();
  1.1844 +		for (TInt j = i + 1; j < count; j++)
  1.1845 +			{
  1.1846 +			if ( iImplIndex[j]->iImplInfo->ImplementationUid().iUid != aImplUid.iUid )
  1.1847 +				{
  1.1848 +				break;
  1.1849 +				}
  1.1850 +
  1.1851 +			aImplData = SelectDuplicatedImpl(aImplData, iImplIndex[j]);
  1.1852 +			}
  1.1853 +
  1.1854 +		return KErrNone;
  1.1855 +		}
  1.1856 +		
  1.1857 +	return KErrNotFound;
  1.1858 +	}
  1.1859 +
  1.1860 +/**
  1.1861 +This function helps FindImplementation() to decide which of two
  1.1862 +implementations with duplicated implementation UID to choose.
  1.1863 +The selection rules are:
  1.1864 +1. ROM based plugins > non-ROM based.
  1.1865 +2. Higher drive letter > lower drive letter
  1.1866 +3. Lower I/F UID > Higher I/F UID (for backward compatibility reason)
  1.1867 +
  1.1868 +@param aImpl1 - one of the two implementations to compare.
  1.1869 +@param aImpl2 - the other implementation to compare.
  1.1870 +@return the preferred implementation.
  1.1871 +*/
  1.1872 +CRegistryData::CImplementationData* CRegistryData::SelectDuplicatedImpl(
  1.1873 +	const CImplementationData* aImpl1, 
  1.1874 +	const CImplementationData* aImpl2) const
  1.1875 +	{
  1.1876 +
  1.1877 +#ifdef ECOM_TRACE
  1.1878 +	TPtrC oldName = aImpl1->iImplInfo->DisplayName().Left(60);
  1.1879 +	TPtrC newName = aImpl2->iImplInfo->DisplayName().Left(60);
  1.1880 +	TPtrC oldDll = aImpl1->iParent->iParent->iDllEntry->GetName();
  1.1881 +	TPtrC newDll = aImpl2->iParent->iParent->iDllEntry->GetName();
  1.1882 +#endif
  1.1883 +
  1.1884 +	const TInt KRomBasedFactor = 0x100;
  1.1885 +
  1.1886 +	TInt drive1 = aImpl1->iImplInfo->Drive();
  1.1887 +	if (aImpl1->iImplInfo->RomBased())
  1.1888 +		{
  1.1889 +		drive1 |= KRomBasedFactor;
  1.1890 +		}
  1.1891 +
  1.1892 +	TInt drive2 = aImpl2->iImplInfo->Drive();
  1.1893 +	if (aImpl2->iImplInfo->RomBased())
  1.1894 +		{
  1.1895 +		drive2 |= KRomBasedFactor;
  1.1896 +		}
  1.1897 +
  1.1898 +	if (drive1 > drive2)
  1.1899 +		{
  1.1900 +#ifdef ECOM_TRACE
  1.1901 +		if ((drive1 & KRomBasedFactor) && !(drive2 & KRomBasedFactor))
  1.1902 +			{
  1.1903 +			__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);
  1.1904 +			}
  1.1905 +		else
  1.1906 +			{
  1.1907 +			__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);
  1.1908 +			}
  1.1909 +#endif
  1.1910 +
  1.1911 +		return const_cast<CImplementationData*>(aImpl1);
  1.1912 +		}
  1.1913 +	else if (drive1 < drive2)
  1.1914 +		{
  1.1915 +#ifdef ECOM_TRACE
  1.1916 +		if ((drive2 & KRomBasedFactor) && !(drive1 & KRomBasedFactor))
  1.1917 +			{
  1.1918 +			__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);
  1.1919 +			}
  1.1920 +		else
  1.1921 +			{
  1.1922 +			__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);
  1.1923 +			}
  1.1924 +#endif
  1.1925 +
  1.1926 +		return const_cast<CImplementationData*>(aImpl2);
  1.1927 +		}
  1.1928 +	// They are on the same drive. Choose the one with lower I/F UID.
  1.1929 +	else if (aImpl2->iParent->iInterfaceUid.iUid < aImpl1->iParent->iInterfaceUid.iUid) 
  1.1930 +		{
  1.1931 +#ifdef ECOM_TRACE
  1.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", &oldName, aImpl1->iParent->iInterfaceUid.iUid, aImpl1->iImplInfo->ImplementationUid().iUid, &newDll, aImpl2->iParent->iInterfaceUid.iUid);
  1.1933 +#endif
  1.1934 +
  1.1935 +		return const_cast<CImplementationData*>(aImpl2);
  1.1936 +		}
  1.1937 +
  1.1938 +#ifdef ECOM_TRACE
  1.1939 +	__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);
  1.1940 +#endif
  1.1941 +
  1.1942 +	return const_cast<CImplementationData*>(aImpl1);
  1.1943 +	}
  1.1944 +
  1.1945 +/**
  1.1946 +Checks each entry in the registry to ensure that both the RSC file and the 
  1.1947 +corresponding dll exist.  If not the dll branch is removed
  1.1948 +from the tree.  If a drive branch is found which contains no dlls
  1.1949 +it is also removed.
  1.1950 +@pre 			This object is fully constructed.
  1.1951 +@post			Any out of date registry entries are removed from the tree.
  1.1952 +*/
  1.1953 +void CRegistryData::ValidateRegistryL()
  1.1954 +	{
  1.1955 +	TInt driveIndex = iRegistrations->Count();
  1.1956 +	TFileName rscFileName;
  1.1957 +	while(driveIndex > 0)
  1.1958 +		{
  1.1959 +		--driveIndex;
  1.1960 +		CDriveData* drive = (*iRegistrations)[driveIndex];
  1.1961 +		
  1.1962 +		if( !iCachedDriveInfo->DriveIsReadOnlyInternalL(drive->iDrive) &&
  1.1963 +			drive->iDriveChanged)
  1.1964 +			{
  1.1965 +			TInt dllIndex = drive->iDllList->Count();	
  1.1966 +			while(dllIndex > 0)
  1.1967 +				{
  1.1968 +				--dllIndex;
  1.1969 +				CDllData* dll = (*drive->iDllList)[dllIndex];
  1.1970 +				//reset the buffer first			
  1.1971 +				rscFileName.Zero();
  1.1972 +				rscFileName.Append(dll->iParent->iDrive.Name());
  1.1973 +				rscFileName.Append(KEComResourceFilePath);
  1.1974 +				rscFileName.Append(dll->iDllEntry->GetName().Left(dll->iDllEntry->GetName().Length()-4));
  1.1975 +				if(dll->iRscFileExtension)
  1.1976 +					{
  1.1977 +					rscFileName.Append(dll->iRscFileExtension->Des());
  1.1978 +					}
  1.1979 +			
  1.1980 +					// check the existence of RSC file in resource\plugins\ directory.
  1.1981 +					// RSC filename is already a full name here.
  1.1982 +				TBool rscFileExistence = BaflUtils::FileExists(iFs, rscFileName);
  1.1983 +
  1.1984 +  				//save the security info, this will both check existence of the dll
  1.1985 +  				//and cache the information for future use
  1.1986 +  				TBool success=dll->SaveSecurityInfoL();
  1.1987 +				// If this dll is not found or the corresponding RSC file is not found, then remove it from the registry
  1.1988 +				if(!success || !rscFileExistence)
  1.1989 +					{
  1.1990 +					//remove all implementations of this dll from iInterfaceImplIndex
  1.1991 +					RemoveFromIndexL(dll);
  1.1992 +					drive->iDllList->Remove(dllIndex);
  1.1993 +					//set flag to indicate registry data has been changed
  1.1994 +					drive->iRegistryChanged = ETrue;
  1.1995 +					delete dll;
  1.1996 +					}
  1.1997 +				}
  1.1998 +			}
  1.1999 +		}
  1.2000 +	}
  1.2001 +
  1.2002 +/**
  1.2003 +Determines whether the new implmentation should be preferred over the existing implementation.
  1.2004 +Validates later version implementations from R/W drives.
  1.2005 +@param		aOldImpl The array to append to
  1.2006 +@param		aNewImpl The item to append
  1.2007 +@param		aLegitimateImpl Flag, indicating whether current implementation is secure
  1.2008 +@return		The preferred implementation
  1.2009 +@pre		This object is fully constructed.
  1.2010 +*/
  1.2011 +CRegistryData::CImplementationData* CRegistryData::SelectPreferredImplL(CImplementationData* aOldImpl,
  1.2012 +																CImplementationData* aNewImpl,
  1.2013 +																TBool& aLegitimateImpl,
  1.2014 +																TBool aCheckIsNeeded) const
  1.2015 +	{
  1.2016 +	aLegitimateImpl = ETrue;
  1.2017 +
  1.2018 +	TBool newIsRomOnly = aNewImpl->iImplInfo->RomOnly();
  1.2019 +	TBool oldIsRomOnly = aOldImpl->iImplInfo->RomOnly();
  1.2020 +		
  1.2021 +	/* 	In addition to selecting the highest version of an 
  1.2022 +		implementation this check takes care of the following special 
  1.2023 +		cases:
  1.2024 +		1. Ensure that a higher-versioned RAM-based implementation 
  1.2025 +		   cannot override a ROM-based version
  1.2026 +		2. Allows for the case where there are two versions of the 
  1.2027 +		   same ROM-only implementation on ROM,	thus ensuring the 
  1.2028 +		   higher of the two versions is used.
  1.2029 +	*/
  1.2030 +	if(newIsRomOnly && !oldIsRomOnly)
  1.2031 +		{
  1.2032 +		return aNewImpl;
  1.2033 +		}
  1.2034 +	else if((newIsRomOnly && oldIsRomOnly))
  1.2035 +		{
  1.2036 +		if(aNewImpl->iImplInfo->Version() > aOldImpl->iImplInfo->Version())
  1.2037 +			{
  1.2038 +			return aNewImpl;
  1.2039 +			}
  1.2040 +		else if(aNewImpl->iImplInfo->Version() == aOldImpl->iImplInfo->Version())
  1.2041 +			{
  1.2042 +			//any drive from Y-A has higher priority than Z drive
  1.2043 +            //any drive with a letter alphabetically greater has higher priority
  1.2044 +            if((aNewImpl->iImplInfo->Drive() != EDriveZ) &&
  1.2045 +                (aOldImpl->iImplInfo->Drive() == EDriveZ || aNewImpl->iImplInfo->Drive() > aOldImpl->iImplInfo->Drive()))
  1.2046 +                {
  1.2047 +				return aNewImpl;
  1.2048 +				}
  1.2049 +			}
  1.2050 +		}
  1.2051 +	//all new implementations which are not flagged'RomOnly'
  1.2052 +	else if(!newIsRomOnly && !oldIsRomOnly)
  1.2053 +		{
  1.2054 +		TBool newIsReadOnly = iCachedDriveInfo->DriveIsReadOnlyInternalL(aNewImpl->iParent->iParent->iParent->iDrive);
  1.2055 +		TBool oldIsReadOnly = iCachedDriveInfo->DriveIsReadOnlyInternalL(aOldImpl->iParent->iParent->iParent->iDrive);
  1.2056 +			
  1.2057 +		if(aNewImpl->iImplInfo->Version() > aOldImpl->iImplInfo->Version())
  1.2058 +			{
  1.2059 +			//filter for implementations on R/W drive trying to upgrade implementations on R/O drive
  1.2060 +			if((!newIsReadOnly && oldIsReadOnly) && aCheckIsNeeded)
  1.2061 +				{						
  1.2062 +				//test if a later implementation version on R/W drive has the same filename as the current one before upgrading.
  1.2063 +				//If not,...
  1.2064 +				if(aOldImpl->iParent->iParent->iDllEntry->GetName().CompareF(aNewImpl->iParent->iParent->iDllEntry->GetName()) == 0)
  1.2065 +					{
  1.2066 +					return aNewImpl;
  1.2067 +					}
  1.2068 +				else
  1.2069 +					{
  1.2070 +					aLegitimateImpl = EFalse; //not secure
  1.2071 +					return aOldImpl;
  1.2072 +					}
  1.2073 +				}
  1.2074 +			else
  1.2075 +				{
  1.2076 +				return aNewImpl;
  1.2077 +				}
  1.2078 +			}
  1.2079 +		else if(aNewImpl->iImplInfo->Version() == aOldImpl->iImplInfo->Version())
  1.2080 +			{
  1.2081 +			//any drive from Y-A has higher priority than Z drive OR
  1.2082 +			//any drive with a letter alphabetically greater has higher priority
  1.2083 +			if((aNewImpl->iImplInfo->Drive() != EDriveZ) &&
  1.2084 +                (aOldImpl->iImplInfo->Drive() == EDriveZ || aNewImpl->iImplInfo->Drive() > aOldImpl->iImplInfo->Drive()))                 
  1.2085 +				{
  1.2086 +				//filename check needs to performed on implementation from R/W drives, trying to 
  1.2087 +				//upgrade implementations on R/O drive    
  1.2088 +				if((!newIsReadOnly && oldIsReadOnly) && aCheckIsNeeded)
  1.2089 +					{							
  1.2090 +					//test if a later implementation version on R/W drive has the same filename as the current one before upgrading.
  1.2091 +					//If not,...
  1.2092 +					if(aOldImpl->iParent->iParent->iDllEntry->GetName().CompareF(aNewImpl->iParent->iParent->iDllEntry->GetName()) == 0)
  1.2093 +						{
  1.2094 +						return aNewImpl;
  1.2095 +						}
  1.2096 +					else
  1.2097 +						{
  1.2098 +						aLegitimateImpl = EFalse; //not secure
  1.2099 +						return aOldImpl;
  1.2100 +						}		
  1.2101 +					}
  1.2102 +				else
  1.2103 +					{
  1.2104 +					return aNewImpl;
  1.2105 +					}
  1.2106 +				}						
  1.2107 +			}
  1.2108 +		}
  1.2109 +	return aOldImpl;
  1.2110 +	}
  1.2111 +
  1.2112 +/**
  1.2113 +This functions checks if a given implementation already exists in
  1.2114 +the indexes. If it does exist, determine if the given implementation
  1.2115 +should replace the existing one or not.
  1.2116 +@param  aIdxArray The container array of the interface to hold the implementation.
  1.2117 +@param  aNewImpl The implementation to filter.
  1.2118 +@param  aInsertMode whether aNewIMpl is a newcomer of the interface, or an 
  1.2119 +		update of an existing implementation, or a older version of an
  1.2120 +		existing implementation.
  1.2121 +@param  aPosOfImplInArray return the index of aNewImpl in aIdxArray,
  1.2122 +@param  aLegitimateImpl Flag,indicating whether current implementation is secure
  1.2123 +@pre    This object is fully constructed.
  1.2124 +@post   none
  1.2125 +*/
  1.2126 +void
  1.2127 +CRegistryData::FilterForLatestLegitimateImplL(TImplContainerArray& aIdxArray,
  1.2128 +											  CImplementationData* aNewImpl,
  1.2129 +											  TInsertImplMode& aInsertMode,
  1.2130 +											  TInt&  aPosOfImplInArray,
  1.2131 +											  TBool& aLegitimateImpl,
  1.2132 +											  TBool aCheckIsNeeded)
  1.2133 +	{
  1.2134 +	aInsertMode = EInsertImplUndefinedMode;
  1.2135 +	aLegitimateImpl = ETrue;
  1.2136 +	TImplStruct newImplStruct;
  1.2137 +	newImplStruct.iCurrentImpl = aNewImpl;
  1.2138 +
  1.2139 +	TInt idxPos = aIdxArray.FindInOrder(newImplStruct, TLinearOrder<TImplStruct> (TImplStruct::CompareImplStructUid));
  1.2140 +
  1.2141 +	aPosOfImplInArray = idxPos;
  1.2142 +
  1.2143 +	if(idxPos != KErrNotFound)
  1.2144 +		{
  1.2145 +		if(aNewImpl != SelectPreferredImplL(aIdxArray[idxPos].iCurrentImpl,
  1.2146 +											aNewImpl,
  1.2147 +											aLegitimateImpl,
  1.2148 +											aCheckIsNeeded))
  1.2149 +			{
  1.2150 +			aInsertMode = EInsertImplAsUnusedImpl;
  1.2151 +			}
  1.2152 +		else
  1.2153 +			{
  1.2154 +			aInsertMode = EInsertImplAsUpgradeOfExistingImpl;
  1.2155 +			} 
  1.2156 +		}
  1.2157 +	else
  1.2158 +		{
  1.2159 +		aInsertMode = EInsertImplAsNewcomerOfInterface;
  1.2160 +		}
  1.2161 +	}
  1.2162 +
  1.2163 +void CRegistryData::ResetTInterfaceIndex(TAny* aObject)
  1.2164 +	{
  1.2165 +	TInterfaceIndex* index=reinterpret_cast<TInterfaceIndex*>(aObject);
  1.2166 +	index->Reset();
  1.2167 +	}
  1.2168 +void CRegistryData::RemoveImplFromImplIndexCleanUp(TAny* aPtr)
  1.2169 +    {
  1.2170 +    TCleanupImplIndexEntry *aCleanup = (TCleanupImplIndexEntry*)aPtr;
  1.2171 +    aCleanup->iRegistryData->RemoveImplByAddrFromImplIndex(aCleanup->iImplEntry);
  1.2172 +    }
  1.2173 +
  1.2174 +/**
  1.2175 +This method retrieves the data for security checks from the iInterfaceImplIndex
  1.2176 +@param          aImplPtr The new item to be checked
  1.2177 +@param			aCheckIsNeeded	Boolean indicating, whether a filename check is needed
  1.2178 +@pre            This object is fully constructed.
  1.2179 +@post           aImplPtr has been checked and added to the index, or not, depending on the 
  1.2180 +				outcome of the checks.
  1.2181 +*/
  1.2182 +TBool CRegistryData::InsertIntoIndexL(CImplementationData* aImplPtr, TBool aCheckIsNeeded)
  1.2183 +	{
  1.2184 +	TBool legitimateImpl = ETrue;
  1.2185 +
  1.2186 +	TInterfaceIndex newIndexEl;
  1.2187 +	TInterfaceIndex* newElPtr;
  1.2188 +	//initialise
  1.2189 +	newIndexEl.iInterfaceUid = aImplPtr->iParent->iInterfaceUid;
  1.2190 +	CleanupStack::PushL(TCleanupItem(ResetTInterfaceIndex,&newIndexEl));
  1.2191 +	
  1.2192 +	TInt indexPos = iInterfaceImplIndex.FindInOrder(newIndexEl,TLinearOrder<TInterfaceIndex>(TInterfaceStruct::CompareInfUid));
  1.2193 +
  1.2194 +	
  1.2195 +	if(indexPos!=KErrNotFound)
  1.2196 +		newElPtr = &(iInterfaceImplIndex[indexPos]);
  1.2197 +	else		
  1.2198 +		newElPtr = &newIndexEl;	
  1.2199 +
  1.2200 +	// For each implementation make sure we only have the latest version
  1.2201 +	TInt implIdxInContainerArray(KErrNotFound);
  1.2202 +	TInsertImplMode insertMode;
  1.2203 +	FilterForLatestLegitimateImplL(newElPtr->iImpData,
  1.2204 +									aImplPtr,
  1.2205 +									insertMode,
  1.2206 +									implIdxInContainerArray,
  1.2207 +									legitimateImpl,
  1.2208 +									aCheckIsNeeded);
  1.2209 +	
  1.2210 +	InsertImplInIndexesL(insertMode, 
  1.2211 +						 indexPos,
  1.2212 +						 *newElPtr,
  1.2213 +						 implIdxInContainerArray,
  1.2214 +						 aImplPtr,
  1.2215 +						 legitimateImpl);
  1.2216 +
  1.2217 +	CleanupStack::Pop();
  1.2218 +
  1.2219 +	if (insertMode == EInsertImplAsUpgradeOfExistingImpl)
  1.2220 +		{
  1.2221 +	    TUid ImplUid = aImplPtr->iImplInfo->ImplementationUid();
  1.2222 +		iImplUpgradeCallBack.CallBack(ECallBackId_ImplUpgrade, &ImplUid);
  1.2223 +		}
  1.2224 +
  1.2225 +	return legitimateImpl;
  1.2226 +	}
  1.2227 +
  1.2228 +/** Handle inserting a CImplementationData in iInterfaceImplIndex and
  1.2229 +iImplIndex.
  1.2230 +
  1.2231 +@param aNewImpl the implementation to add to the indexes.
  1.2232 +@param aInsertMode indicates whether the implementation is a newcover
  1.2233 +			of the interface, or is an update of existing implementation
  1.2234 +			or is an older version of an existing implementation.
  1.2235 +@param aIfPosInInterfaceImplIndex is the index of the interface in
  1.2236 +		iInterfaceImplIndex.
  1.2237 +@param aNewIfIndexEl the TInterfaceIndex object containing the implementation.
  1.2238 +@param aImplPosInContainerArray is the index of the implementation in
  1.2239 +		the iImpData member of aNewIfIndexEl.
  1.2240 +@param aLegitimateImpl indicate if the implementation passed security check or not.
  1.2241 +@leave KErrNoMemory operation fails because the system is out of memory.
  1.2242 +@leave KErrGeneral any non-specific programming error.
  1.2243 +@leave KErrAlreadyExists the indexes already have an entry with the same
  1.2244 +		Impl. UID and Interface UID.
  1.2245 +*/
  1.2246 +void CRegistryData::InsertImplInIndexesL(TInsertImplMode aInsertMode,
  1.2247 +										TInt aIfPosInInterfaceImplIndex,
  1.2248 +										TInterfaceIndex& aNewIfIndexEl,
  1.2249 +										TInt aImplPosInContainerArray,
  1.2250 +								   		CImplementationData* aNewImpl,
  1.2251 +								   		TBool aLegitimateImpl)
  1.2252 +	{
  1.2253 +	if(aInsertMode == EInsertImplUndefinedMode)
  1.2254 +		{
  1.2255 +		// Will not happen because if FilterForLatestLegitimateImplL
  1.2256 +		// does not leave then insertMode is set to one of the valid
  1.2257 +		// values. If FilterForLatestLegitimateImplL leaves ecomserver exits.
  1.2258 +		User::Leave(KErrGeneral);
  1.2259 +		}
  1.2260 +
  1.2261 +	// If not a legitimate implementation, aNewImpl will be deleted.
  1.2262 +	// Do not add it to the two indexes.
  1.2263 +
  1.2264 +	if (!aLegitimateImpl)
  1.2265 +		{
  1.2266 +		return;
  1.2267 +		}
  1.2268 +
  1.2269 +	TImplContainerArray& implContainerArray = aNewIfIndexEl.iImpData;
  1.2270 +
  1.2271 +	if(aInsertMode == EInsertImplAsNewcomerOfInterface)
  1.2272 +		{
  1.2273 +		TImplStruct newImplStruct;
  1.2274 +		newImplStruct.iCurrentImpl = aNewImpl;
  1.2275 +		implContainerArray.InsertInOrderL(newImplStruct, TLinearOrder<TImplStruct> (TImplStruct::CompareImplStructUid));
  1.2276 +
  1.2277 +#ifdef _DEBUG
  1.2278 +		// on debug build, check for duplicated implementation UID
  1.2279 +		// owned by different interfaces.
  1.2280 +
  1.2281 +		TInt ii = iImplIndex.SpecificFindInOrder(
  1.2282 +			aNewImpl,
  1.2283 +			CImplementationData::CompareImplUidIgnoreIfUid,
  1.2284 +			EArrayFindMode_Any);
  1.2285 +		if (ii != KErrNotFound)
  1.2286 +			{
  1.2287 +			CImplementationData* otherImpl = iImplIndex[ii];
  1.2288 +			TPtrC oldName = otherImpl->iImplInfo->DisplayName().Left(60);
  1.2289 +			TPtrC newName = aNewImpl->iImplInfo->DisplayName().Left(60);
  1.2290 +			__ECOM_TRACE5("** ECOM: error Impl UID %X, I/F UID %X DLL %S duplicating I/F %X DLL %S",\\ 
  1.2291 +				aNewImpl->iImplInfo->ImplementationUid().iUid, \\
  1.2292 +				aNewImpl->iParent->iInterfaceUid.iUid, &newName,\\
  1.2293 +				otherImpl->iParent->iInterfaceUid.iUid, &oldName);
  1.2294 +			}
  1.2295 +#endif
  1.2296 +		}
  1.2297 +	else if(aInsertMode == EInsertImplAsUpgradeOfExistingImpl)
  1.2298 +		{
  1.2299 +		TImplContainer& implContainer = implContainerArray[aImplPosInContainerArray];
  1.2300 +		CImplementationData* oldImpl =  implContainer.iCurrentImpl;
  1.2301 +		implContainer.iUnusedImpls.AppendL(oldImpl);
  1.2302 +		RemoveImplByAddrFromImplIndex(oldImpl); // ignore return code
  1.2303 +		implContainer.iCurrentImpl = aNewImpl;
  1.2304 +
  1.2305 +		// We are replacing existing impl with aNewImpl.  If existing  
  1.2306 +		// corresponds to a ROM-based plug-in then aNewImpl is an 
  1.2307 +		// update and qualifies as ROM-based under current policy.
  1.2308 +		if(oldImpl->iImplInfo->RomBased())
  1.2309 +			{
  1.2310 +			aNewImpl->iImplInfo->SetRomBased(ETrue);
  1.2311 +			}
  1.2312 +		__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()));
  1.2313 +		__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()));
  1.2314 +		}
  1.2315 +	else if (aInsertMode == EInsertImplAsUnusedImpl)
  1.2316 +		{
  1.2317 +		TImplContainer& implContainer = implContainerArray[aImplPosInContainerArray];
  1.2318 +		implContainer.iUnusedImpls.AppendL(aNewImpl);
  1.2319 +
  1.2320 +		CImplementationData* currImpl =  implContainer.iCurrentImpl;
  1.2321 +		__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()));
  1.2322 +		__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()));
  1.2323 +		// We are not replacing existing with aNewImpl.  However, 
  1.2324 +		// if aNewImpl corresponds to a ROM-based plug-in then the 
  1.2325 +		// existing impl is an update and qualifies as ROM-based 
  1.2326 +		// under current policy.
  1.2327 +		if(aNewImpl->iImplInfo->RomBased())
  1.2328 +			{
  1.2329 +			currImpl->iImplInfo->SetRomBased(ETrue);
  1.2330 +			}
  1.2331 +
  1.2332 +		return; // the trailing steps not applicable to downgrade situation
  1.2333 +		}
  1.2334 +
  1.2335 +	User::LeaveIfError( InsertImplIntoImplIndex(aNewImpl) );
  1.2336 +	
  1.2337 +	if(aIfPosInInterfaceImplIndex==KErrNotFound)
  1.2338 +		{		
  1.2339 +        TCleanupImplIndexEntry aCleanup(this, aNewImpl);
  1.2340 +        CleanupStack::PushL(TCleanupItem(RemoveImplFromImplIndexCleanUp,&aCleanup));
  1.2341 +		iInterfaceImplIndex.InsertInOrderL(aNewIfIndexEl, TLinearOrder<TInterfaceIndex>(TInterfaceStruct::CompareInfUid));
  1.2342 +		CleanupStack::Pop();
  1.2343 +		}
  1.2344 +	}
  1.2345 +
  1.2346 +/**
  1.2347 +This method takes removes all implementations of a plugin from the iInterfaceImplIndex
  1.2348 +@param			aDllData Reference to a fully constructed CDllData object 
  1.2349 +@pre			This object is constructed
  1.2350 +@post			All implementations of the CDllData object, have been removed from the index
  1.2351 +*/
  1.2352 +void CRegistryData::RemoveFromIndexL(CDllData* aDllData) const
  1.2353 +	{
  1.2354 +	//remove 'old' implementations from iInterfaceImplIndex
  1.2355 +	TInt counter=0;
  1.2356 +	TImplStruct implStruct;
  1.2357 +	TInt ifListCount=aDllData->iIfList->Count();
  1.2358 +	while(counter < ifListCount)
  1.2359 +		{
  1.2360 +		CInterfaceData* interface = (*aDllData->iIfList)[counter];
  1.2361 +		TInterfaceIndex index;
  1.2362 +		index.iInterfaceUid = interface->iInterfaceUid;
  1.2363 +		
  1.2364 +		TInt indexPos = iInterfaceImplIndex.FindInOrder(index,TLinearOrder<TInterfaceIndex>(TInterfaceStruct::CompareInfUid));
  1.2365 +        TImplContainerArray* impDataArray = NULL;
  1.2366 +		TInt implCount=0;
  1.2367 +		
  1.2368 +		if(indexPos!=KErrNotFound)
  1.2369 +			{
  1.2370 +            impDataArray = &(iInterfaceImplIndex[indexPos].iImpData);
  1.2371 +            implCount=interface->iImplementations->Count();
  1.2372 +			for(TInt i=0; i<implCount; i++)
  1.2373 +				{
  1.2374 +				implStruct.iCurrentImpl = (*interface->iImplementations)[i];
  1.2375 +				TInt impPos = impDataArray->FindInOrder(implStruct, TLinearOrder<CRegistryData::TImplStruct> (TImplStruct::CompareImplStructUid));
  1.2376 +				if(impPos!=KErrNotFound)
  1.2377 +					{
  1.2378 +					TImplContainer& implContainer = (*impDataArray)[impPos];
  1.2379 +					// remove from unused list if exists
  1.2380 +					TInt count = implContainer.iUnusedImpls.Count();
  1.2381 +					while(count > 0)
  1.2382 +						{
  1.2383 +						--count;
  1.2384 +						if(implContainer.iUnusedImpls[count]->iParent->iParent == aDllData)
  1.2385 +							{
  1.2386 +							implContainer.iUnusedImpls.Remove(count);
  1.2387 +							}
  1.2388 +						}
  1.2389 +
  1.2390 +					// update current entry
  1.2391 +					if(implContainer.iCurrentImpl->iParent->iParent == aDllData)
  1.2392 +						{
  1.2393 +						// do not care about the return code.
  1.2394 +						RemoveImplByAddrFromImplIndex(implContainer.iCurrentImpl);
  1.2395 +						
  1.2396 +						TInt implContainerUnusedImplCount=implContainer.iUnusedImpls.Count();
  1.2397 +						// no unused impl's therefore no rollback and remove entry
  1.2398 +						if(implContainerUnusedImplCount == 0)
  1.2399 +							{
  1.2400 +							implContainer.Reset();
  1.2401 +							impDataArray->Remove(impPos);
  1.2402 +							}
  1.2403 +						else
  1.2404 +							{
  1.2405 +							// Rollback to implementation from unused array
  1.2406 +							// copy first from unused array
  1.2407 +							TInt selectedPos = 0;
  1.2408 +							implContainer.iCurrentImpl = implContainer.iUnusedImpls[selectedPos];
  1.2409 +							
  1.2410 +							// now check if any others in list should be preferred
  1.2411 +							for(count = 1;count < implContainerUnusedImplCount; count++)
  1.2412 +								{
  1.2413 +								// determine which implementation should be used.
  1.2414 +								// no security check required as this will have already been done when impl was
  1.2415 +								// first added to unused list.
  1.2416 +								TBool dummLegitimateImpl;
  1.2417 +								implContainer.iCurrentImpl = SelectPreferredImplL(implContainer.iCurrentImpl,
  1.2418 +																implContainer.iUnusedImpls[count],
  1.2419 +																dummLegitimateImpl,
  1.2420 +																EFalse);
  1.2421 +								if(implContainer.iCurrentImpl == implContainer.iUnusedImpls[count])
  1.2422 +									{
  1.2423 +									selectedPos = count;
  1.2424 +									}
  1.2425 +								}
  1.2426 +							implContainer.iUnusedImpls.Remove(selectedPos);
  1.2427 +							User::LeaveIfError(InsertImplIntoImplIndex(implContainer.iCurrentImpl));
  1.2428 +#ifdef ECOM_TRACE
  1.2429 +							{
  1.2430 +							CImplementationData* p = implContainer.iCurrentImpl;
  1.2431 +							__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()));
  1.2432 +							}
  1.2433 +#endif
  1.2434 +							}
  1.2435 +						}
  1.2436 +					}
  1.2437 +				//To make sure it is removed from the implIndex no matter what and that the return code is ignored.
  1.2438 +				//The previous removal is still required so that a subsequent InsertImplIntoImplIndex is possible
  1.2439 +				//for an implementation. e.g. an implementaion is on different drives and only one of htem was removed.
  1.2440 +				// The other one should now make it to the iImplIndex through InsertImplIntoImplIndex. If it wasn't 
  1.2441 +				// removed, before the insert operation, it will fail since both the implementations hav the same
  1.2442 +				// impl UID.
  1.2443 +				RemoveImplByAddrFromImplIndex((*interface->iImplementations)[i]);
  1.2444 +				}
  1.2445 +			if(impDataArray->Count() == 0)
  1.2446 +				{
  1.2447 +				iInterfaceImplIndex[indexPos].Reset();
  1.2448 +				iInterfaceImplIndex.Remove(indexPos);
  1.2449 +				}
  1.2450 +			}
  1.2451 +		counter++;
  1.2452 +		}
  1.2453 +	}
  1.2454 +
  1.2455 +/**
  1.2456 +This method inserts implementations into the index
  1.2457 +@param          aDriveData Drive data in which we are searching the implementations
  1.2458 +@pre            This object is fully constructed.
  1.2459 +@post           all implemementations found, have been inserted into the index.
  1.2460 +*/
  1.2461 +void CRegistryData::AddImplDataL(CDriveData* aDriveData)
  1.2462 +	{
  1.2463 + 	TBool checkIsNeeded = EFalse;
  1.2464 + 	TInt dllCount=aDriveData->iDllList->Count();
  1.2465 + 	for(TInt dllCounter=0; dllCounter < dllCount;dllCounter++)
  1.2466 + 		{
  1.2467 + 		CDllData* aDllData = (*aDriveData->iDllList)[dllCounter];
  1.2468 + 		TInt interfaceCount=aDllData->iIfList->Count();
  1.2469 + 		for(TInt ifListCounter=0; ifListCounter < interfaceCount; ifListCounter++)
  1.2470 + 			{
  1.2471 + 			// For each interface structure
  1.2472 + 			CInterfaceData* interface = (*aDllData->iIfList)[ifListCounter];
  1.2473 + 			TInt implementationCount=interface->iImplementations->Count();
  1.2474 + 			for(TInt impNum = 0; impNum < implementationCount; ++impNum)
  1.2475 + 				{
  1.2476 + 				CImplementationData* implData = (*interface->iImplementations)[impNum];
  1.2477 + 				TInt retValue = InsertIntoIndexL(implData, checkIsNeeded);
  1.2478 + 				//we know that during internalize, all implementations are legitimate,
  1.2479 + 				//as the check was already performed during discovery. No check is 
  1.2480 + 				//performed at this stage, therefore ignore return value, as it will always
  1.2481 + 				//KErrNone
  1.2482 + 				}
  1.2483 + 			}	
  1.2484 + 		}	
  1.2485 + 	}
  1.2486 +
  1.2487 +
  1.2488 +/** This method does a search by address and removes the specified entry from iImplIndex.
  1.2489 +
  1.2490 +@param  aPtr is the entry to remove
  1.2491 +@return True if aPtr is removed from iImplIndex. False if aPtr is not
  1.2492 +        in iImplIndex, i.e. nothing is removed.
  1.2493 +*/
  1.2494 +TBool CRegistryData::RemoveImplByAddrFromImplIndex(CImplementationData* aPtr) const
  1.2495 +    {
  1.2496 +    TInt aIdx = iImplIndex.Find(aPtr);
  1.2497 +    if (aIdx != KErrNotFound)
  1.2498 +        {
  1.2499 +        // This linear pointer search ensures a safe removal of the impl from iImplIndex so that it is free from a dead object.
  1.2500 +    
  1.2501 +        // The array does not own the pointer. Do not delete!
  1.2502 +        iImplIndex.Remove(aIdx);
  1.2503 +        return ETrue;
  1.2504 +        }
  1.2505 +    return EFalse;
  1.2506 +    }
  1.2507 +
  1.2508 +/** This method inserts the entry aNewImpl into iImplIndex.
  1.2509 +
  1.2510 +@param aNewImpl the item to add to iImplIndex.
  1.2511 +@return KErrNone aNewImpl is successfully added to the index.
  1.2512 +		KErrAlreadyExists iImplIndex has an entry with the same 
  1.2513 +		implementation UID and same parent Interface UID.
  1.2514 +		KErrNoMemory fail to insert due to out of memory.
  1.2515 +		Other system wide errors.
  1.2516 +@pre    aNewImpl is fully constructed.
  1.2517 +*/
  1.2518 +TInt CRegistryData::InsertImplIntoImplIndex(CImplementationData* aNewImpl) const
  1.2519 +	{
  1.2520 +	TLinearOrder<CImplementationData> ImplUidComparator(CImplementationData::CompareImplUid);
  1.2521 +
  1.2522 +	return iImplIndex.InsertInOrder(aNewImpl, ImplUidComparator);
  1.2523 +	}
  1.2524 +
  1.2525 +/** This method checks whether the language downgrade path has been changed.
  1.2526 +If it is, save language downgrade path information and set related flag true.
  1.2527 +
  1.2528 +@param aLanguageChanged the returned value to indicate language changed.
  1.2529 +*/
  1.2530 +void CRegistryData::LanguageChangedL(TBool& aLanguageChanged)
  1.2531 +	{
  1.2532 +	iLanguageChanged = RDowngradePath::HasChangedL(iFs);
  1.2533 +	aLanguageChanged = iLanguageChanged;
  1.2534 +	}
  1.2535 +
  1.2536 +/** setter
  1.2537 +If need to unset the callback, use a TCallBackWithArg constructed with no
  1.2538 +arguments.
  1.2539 +*/
  1.2540 +void CRegistryData::SetImplUpgradeCallBack(const TCallBackWithArg& aCallBack)
  1.2541 +	{
  1.2542 +	iImplUpgradeCallBack = aCallBack;
  1.2543 +	}
  1.2544 +
  1.2545 +#ifdef __ECOM_SERVER_PERFORMANCE__
  1.2546 +/**
  1.2547 +This method calculates the drive, plugins, interfaces, implementations counts for the drive
  1.2548 +type set
  1.2549 +@param			aType The drive type for which the counts should be calculated 
  1.2550 +@param			aCounts Holds the calculated counts
  1.2551 +@pre			This object is constructed
  1.2552 +*/
  1.2553 +void CRegistryData::GetRegistryCountsL(TInt aType, RegistryCounts::TRegistryCounts& aCounts) const
  1.2554 +	{
  1.2555 +	aCounts.iDrives = 0;
  1.2556 +	aCounts.iImplementations = 0;
  1.2557 +	aCounts.iInterfaces = 0;
  1.2558 +	aCounts.iDlls = 0;
  1.2559 +	
  1.2560 +	for(TInt driveIndex = 0; driveIndex< iRegistrations->Count(); driveIndex++)
  1.2561 +		{
  1.2562 +		CDriveData* drive = (*iRegistrations)[driveIndex];
  1.2563 +		TBool isReadOnly = iCachedDriveInfo->DriveIsReadOnlyInternalL(drive->iDrive);
  1.2564 +
  1.2565 +		if((aType == RegistryCounts::TRegistryCounts::EAll) ||
  1.2566 +			(aType == RegistryCounts::TRegistryCounts::ERoInternal && isReadOnly) ||
  1.2567 +			(aType == RegistryCounts::TRegistryCounts::ENonRoInternal && !isReadOnly))
  1.2568 +			{
  1.2569 +			aCounts.iDrives++;
  1.2570 +			aCounts.iDlls += drive->iDllList->Count();
  1.2571 +			for(TInt dllIndex = 0; dllIndex < drive->iDllList->Count(); dllIndex++)
  1.2572 +				{
  1.2573 +				CDllData* dllList = (*drive->iDllList)[dllIndex];
  1.2574 +				aCounts.iInterfaces += dllList->iIfList->Count();
  1.2575 +				for(TInt ifIndex = 0; ifIndex < dllList->iIfList->Count(); ifIndex++)
  1.2576 +					{
  1.2577 +					CInterfaceData* ifList = (*dllList->iIfList)[ifIndex];
  1.2578 +					aCounts.iImplementations += ifList->iImplementations->Count();
  1.2579 +					}
  1.2580 +				}
  1.2581 +			}
  1.2582 +		}
  1.2583 +	}
  1.2584 +
  1.2585 +#endif // __ECOM_SERVER_PERFORMANCE__