lowlevellibsandfws/pluginfw/Framework/frame/Registrar.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lowlevellibsandfws/pluginfw/Framework/frame/Registrar.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,412 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implementation of the registrar class
+// 
+//
+
+/**
+ @internalComponent
+ @file 
+*/
+
+#include <barsc2.h> // CResourceFile
+#include <barsread2.h> // RResourceReader
+#include <bautils.h>
+#include <e32uid.h>
+#include <startup.hrh> // for EStartupStateNonCritical
+
+#include "ecompanics.h"
+#include "EComDebug.h"
+#include <ecom/ecom.h>
+#include <ecom/ecomerrorcodes.h>
+#include <ecom/ecomresolverparams.h>
+#include "TestUtilities.h"	// For __FILE__LINE__
+#include "Registrar.h"
+#include "Discoverer.h"
+#include "BackupNotifier.h"
+#include "RegistryData.h"
+#include "EComUidCodes.h"
+#include "RegistrarObserver.h"
+#include "DriveInfo.h"
+#include "ParseImplementationData.h"
+#include "EComInternalErrorCodes.h"
+	
+const TInt KMinBuffAllocSize = 1;
+
+
+#define UNUSED_VAR(a) a = a
+
+
+CRegistrar* CRegistrar::NewL(CRegistryData& aRegistry, MRegistrarObserver& aRegistrarObserver, RFs& aFs)
+	{
+	CRegistrar* self = new(ELeave) CRegistrar(aRegistry,aRegistrarObserver,aFs);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+// Default d'tor
+
+CRegistrar::~CRegistrar()
+	{
+	delete iBackupNotifier;
+	delete iDiscoverer;
+	delete iCachedDriveInfo;
+	}
+
+// Default c'tor
+
+CRegistrar::CRegistrar(CRegistryData& aRegistry, MRegistrarObserver& aRegistrarObserver, RFs& aFs)
+: CBase(), iRegistry(aRegistry), iRegistrarObserver(aRegistrarObserver), iFs(aFs), iState(EReg_Undefined)
+	{
+	}
+
+
+void CRegistrar::ConstructL()
+	{
+	iCachedDriveInfo = CEComCachedDriveInfo::NewL(iFs);
+
+	// Instantiate the discoverer
+	iDiscoverer = CDiscoverer::NewL(*this, iFs);
+	InitialiseEvent();
+	}
+
+
+TInt CRegistrar::Disable(TUid aImplementationUid)
+	{
+	return iRegistry.SetEnabledState(aImplementationUid, EFalse);
+	}
+
+
+TInt CRegistrar::Enable(TUid aImplementationUid)
+	{
+	return iRegistry.SetEnabledState(aImplementationUid, ETrue);
+	}
+
+
+TInt CRegistrar::Resume()
+	{
+	return iDiscoverer->Resume();
+	}
+
+
+TInt CRegistrar::Suspend()
+	{
+	return iDiscoverer->Suspend();
+	}
+
+
+void CRegistrar::DriveRemovedL(TDriveUnit aDrive)
+	{
+	iRegistry.TemporaryUninstallL(aDrive);
+	}
+
+
+void CRegistrar::DriveReinstatedL(TDriveUnit aDrive)
+	{
+	iRegistry.UndoTemporaryUninstallL(aDrive);
+	}
+	
+TBool CRegistrar::IsAnyDllRegisteredWithDriveL(const TDriveUnit aDrive)const
+	{
+	return iRegistry.IsAnyDllRegisteredWithDriveL(aDrive);
+	}
+
+void CRegistrar::RegisterDiscoveryL(const TDriveName& aDrive,CPluginBase*& aDirEntry, TBool aAnyDllDiscovered)
+	{
+	TBool found = EFalse;
+	TBool update = EFalse;
+	TInt  registryDriveIndex = KErrNotFound;
+
+	// Find the appropriate drive entry
+	TChar driveLetter = User::UpperCase(aDrive[0]) - 'A';
+	TDriveUnit driveUnit = EDriveA + driveLetter;
+	CRegistryData::CDriveData* drive =NULL;
+	
+	// Get the drive data in the registry.
+	registryDriveIndex = iRegistry.FindDriveL(driveUnit, drive);
+	if(registryDriveIndex == KErrNotFound)
+		{
+		User::Leave(KEComErrDriveNotFound);
+		}
+		
+
+	// Get the registry to return enough data so that the Add and Update routines
+	// can be optimised to avoid rescanning the registry data.
+	// This means that registryDriveIndex MUST remain valid until after
+	// the ParseRegistrationDataL call below.
+	
+	// IsRegisteredWithDate will be called if the this drive is NOT
+	// under its initial discovery. If any Dll is discovered in the drive, then
+	// this drive is NOT in its initial discovery.
+	
+	// In read-only drive with SPI enable, aAnyDllDiscovered will be always false. 
+	// If language downgrade path has been changed, IsRegisteredWithDate will be
+	// called to check whether current localised file need to be updated. 
+	if((aAnyDllDiscovered) || (iRegistry.HasLanguageChanged()))
+		{
+		found = iRegistry.IsRegisteredWithDate(aDirEntry->iDllThirdUid, aDirEntry->iDllModifiedTime, update, drive);
+		}
+	
+	if(!found || update || iRegistry.HasLanguageChanged())
+		{
+		if(found && !update && iRegistry.HasLanguageChanged())
+			{
+			// If we got here because the language has changed
+			// ensure the existing registry data is updated rather than a new entry added
+			update = ETrue;
+			}
+		ParseRegistrationDataL(aDirEntry,driveUnit, update, registryDriveIndex, drive);
+		}
+	}
+
+
+void CRegistrar::DiscoveriesBegin()
+	{
+	// We are about to receive registrations so inform the registry that its index
+	// is about to be invalid
+	iRegistry.DiscoveriesBeginning();
+	}
+
+
+void CRegistrar::DiscoveriesComplete(TBool aSuccessful, TPluginProcessingTypeIdentifier aProcessingType)
+	{
+	
+	TBool doesRegChanged = EFalse;
+
+	// Successfully completed, if registry data has been changed, update 
+	TRAPD(error,iRegistry.DiscoveriesCompleteL(aSuccessful, aProcessingType,doesRegChanged));
+    UNUSED_VAR(error);
+	// Notify if the registry data has been changed.
+	if(doesRegChanged)
+		{
+	// Notify that we have updated the registry
+		iRegistrarObserver.Notification(KErrNone);
+		}
+	}
+
+void CRegistrar::SetDiscoveryFlagL(const TDriveUnit& aDriveUnit)
+	{
+	//set the drive flag to indicate it has changes.
+	iRegistry.SetDiscoveryFlagL(aDriveUnit);
+	}
+	
+TBool CRegistrar::NotifiedWithErrorCode(TInt aError)
+	{
+	// Test the safe error codes
+	return (aError == KErrNotReady ||		// Drive removed?
+			aError == KErrPathNotFound);	// Directory deleted?
+	}
+
+void CRegistrar::ParseRegistrationDataL(CPluginBase*& aEntry,
+										const TDriveUnit& aDrive, 
+										TBool aUpdate, 
+										TInt aRegistryDriveIndex,
+										CRegistryData::CDriveData* aDriveData)
+	{
+	// Ok we intend installing this item so 
+	// create the Interface Implementation Collection entry first
+	CRegistryData::CDllData* dll = CRegistryData::CDllData::NewLC(*(aEntry->iDllName),aEntry->iDllModifiedTime,aEntry->iDllSecondUid,aEntry->iDllThirdUid,aDriveData);
+
+#ifdef ECOM_TRACE
+	static int counter = 0; counter++;
+	TFileName fullFileName(aDrive.Name());
+	fullFileName.Append(_L("\\sys\\bin\\"));
+	fullFileName.Append(*(aEntry->iDllName));
+	__ECOM_TRACE2("ECOM: Plugin discovered (%04d) %S", counter, &fullFileName);
+#endif
+
+	// update resource ext info
+	HBufC* resourceExt = aEntry->RscFileExt();
+	if(resourceExt)
+		dll->SetResourceExtL(*resourceExt);
+	
+	// Don't automatically leave during the parse of the implementation
+	// collection's registration data.
+	// If we did then there would be a cascade of leaves which stop the 
+	// entire registration process for all discoveries remaining on the list.
+	// Check to see if there is a problem specifically with the registration data
+	// OR if its a general problem. In the latter case leave.
+	TInt error=KErrNone;
+			
+	TRAP(error, ParseL(aEntry,*dll));
+	if (error==KErrNoMemory)
+		User::LeaveNoMemory();
+	if(error == KErrNone)
+		{
+		if(aUpdate)
+			{	
+			iRegistry.UpdateDllDataL(aDrive, aRegistryDriveIndex, dll);
+			}
+		else
+			{	
+			iRegistry.AddDllDataL(aDrive, aRegistryDriveIndex, dll);
+			}
+		// Remove dll from CleanupStack as ownership has been passed in one of
+		// the two functions above
+		CleanupStack::Pop(dll);
+		}
+	else
+		{
+		// This interface implementation collection 
+		// cannot be registered correctly.
+		CleanupStack::PopAndDestroy(dll);
+		}
+	}
+
+void CRegistrar::GetResourceFormatVersionL(RResourceReader& aReader, TInt& aResourceFormatVersion)
+	{
+	aResourceFormatVersion = 1;
+	TUid dllUid(KNullUid);
+	TUid uid = {aReader.ReadInt32L()};
+	if(uid==KUidEComResourceFormatV2)
+		{
+		aResourceFormatVersion = 2;
+		dllUid.iUid = aReader.ReadInt32L();
+		}
+	else if(uid==KUidEComResourceFormatV3)
+		{
+		aResourceFormatVersion = 3;
+		dllUid.iUid = aReader.ReadInt32L();
+		}		
+	else
+		dllUid = uid;
+	}
+
+	
+void CRegistrar::ParseL(CPluginBase*& aEntry,CRegistryData::CDllData& aDll)
+	{
+// Read the resource file starting at offset:0 section size:0
+	CResourceFile* regFile =aEntry->RscFile();
+//	Note : There may be an issue here with resource reading when the 
+//  file is not in the ROM. The solution would be to call
+//	regFile.ConfirmSignatureL(regFile.SignatureL());
+//	However for 6.2 interface implementation collections will ALL
+//	be within the ROM. and future development will move to an
+//	XML parsed solution @ build time.
+//	IF this situation changes, place the fix here.
+ 	RResourceReader theReader;
+ 	theReader.OpenLC(regFile, KMinBuffAllocSize);
+	TInt resourceFormatVersion = 0;
+	GetResourceFormatVersionL(theReader,resourceFormatVersion);
+	
+	TDriveUnit drive(aDll.iParent->iDrive);
+	TBool romBased = iCachedDriveInfo->DriveIsReadOnlyInternalL(drive);
+	const TInt numInterfaces = theReader.ReadInt16L();
+	if (resourceFormatVersion == 3 && numInterfaces > KMaxInterfacesInResV3)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	for(TInt iface = 0; iface < numInterfaces; ++iface)
+		{
+		// Read the interface uid
+		const TUid interfaceUid = {theReader.ReadInt32L()};
+		CRegistryData::CInterfaceData* interfaceList = CRegistryData::CInterfaceData::NewLC(interfaceUid,&aDll);
+		aDll.AddL(interfaceList);
+		CleanupStack::Pop(interfaceList);		// Now owned by aDll
+		const TInt numImplementations = theReader.ReadInt16L();
+		if (resourceFormatVersion == 3 && numImplementations > KMaxImplementationsForEachInterfacesInResV3)
+			{
+			User::Leave(KErrNotSupported);
+			}
+		for(TInt index = 0; index < numImplementations; ++index)
+			{
+			TUid implementationUid;
+			TInt versionNo;
+			TInt infoFormat;
+			TBool romOnly;
+			RExtendedInterfacesArray* extendedInterfaces = NULL;
+			HBufC* name = NULL;
+			HBufC8* defaultData = NULL;
+			HBufC8* opaqueData = NULL;
+			CParseImplementationData* parseImplementationData = CParseImplementationData::NewLC(resourceFormatVersion);
+			parseImplementationData->ParseL(theReader,
+											infoFormat,
+											implementationUid,
+											versionNo,
+									   	  	name,
+									      	defaultData,
+									      	opaqueData,
+									      	extendedInterfaces,
+									      	romOnly);
+			CleanupStack::PopAndDestroy(parseImplementationData);									      	
+			
+			CleanupStack::PushL(TCleanupItem(CloseAndDeleteArray, extendedInterfaces));
+			CleanupStack::PushL(name);
+			CleanupStack::PushL(defaultData);
+			CleanupStack::PushL(opaqueData);
+			if (romOnly && !(romBased))
+				{
+				// pop and destroy opaquedata, defaultdata,name and extendedInterfaces
+				CleanupStack::PopAndDestroy(4,extendedInterfaces); 
+				}
+			else
+				{
+				CRegistryData::CImplementationData* implData = CRegistryData::CImplementationData::NewL(interfaceList,
+																										implementationUid, 
+																				 						versionNo, 
+																				 						name, 
+																						 				defaultData,
+																										opaqueData,
+																					 					drive,
+																					 					romOnly,
+																				 						romBased,
+																				 						extendedInterfaces);
+				CleanupStack::Pop(4,extendedInterfaces); // opaqueData,defaultData,name,extendedInterfaces owned by implData
+				CleanupStack::PushL(implData);
+				interfaceList->AddL(implData);	// Now owned by interfaceList	
+				CleanupStack::Pop(implData);
+				}
+			}
+		}
+	CleanupStack::PopAndDestroy(&theReader);		
+	}
+
+	
+CRegistrar::TRegistrarState CRegistrar::State()const
+	{
+	return iState;
+	}
+
+void CRegistrar::ProcessSSAEventL(TStartupStateIdentifier aKnownState)
+	{
+	iDiscoverer->ProcessSSAEventL(aKnownState); 
+	if(aKnownState == EStartupStateNonCritical && iState == EReg_StartupInProgess)
+		{
+		__ECOM_TRACE("ECOM: CRegistrar::ProcessSSAEventL(): EStartupStateNonCritical is reached.");
+
+		iState = EReg_StartupComplete;
+		iBackupNotifier = CBackupNotifier::NewL(*this);
+		}
+	}
+void CRegistrar::InitialiseEvent()
+	{
+	iState = EReg_StartupInProgess;
+	}
+
+void CRegistrar::LanguageChangedL(TBool& aLanguageChanged)
+	{
+	iRegistry.LanguageChangedL(aLanguageChanged);
+	}
+
+void CRegistrar::InstallSwiEventCallBack(const TCallBackWithArg& aCallBack)
+	{
+	iDiscoverer->SetSwiChangeCallBack(aCallBack);
+	}
+
+void CRegistrar::InstallBurEventCallBack(const TCallBackWithArg& aCallBack)
+	{
+	iDiscoverer->SetBurChangeCallBack(aCallBack);
+	}