--- /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);
+ }