--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/layouts/cdl/CdlEngine/src/CdlLibrary.cpp Thu Dec 17 09:14:12 2009 +0200
@@ -0,0 +1,334 @@
+/*
+* Copyright (c) 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:
+*
+*/
+#include "CdlLibrary.h"
+#include "CCdlEngine.h"
+#include <e32svr.h>
+#include <f32file.h>
+#include <e32uid.h>
+#ifdef RD_SECURE_BIN_RES
+#include <ecom/ecom.h>
+#endif
+
+const TInt KCdlLibManGranularity = 4;
+const TUid KCdlLibraryUid = { 0x101F8BD1 };
+
+template<class T>
+inline T* CheckPtrL(T* aPtr)
+ {
+ if (aPtr == NULL)
+ User::Leave(KErrNotFound);
+ return aPtr;
+ }
+
+
+//
+// RCdlLibrary
+//
+
+enum TRCdlLibraryFlags
+ {
+ ERCdlLibrary_RomOnly
+ };
+
+RCdlLibrary::RCdlLibrary() : iName(0), iRefCount(0)
+,iEcomDtorUid(KNullUid), iEcomImpl(0)
+ {
+ }
+
+void RCdlLibrary::Close()
+ {
+ REComSession::DestroyedImplementation(iEcomDtorUid);
+ iEcomDtorUid.iUid = 0;
+ iEcomImpl = 0;
+ delete iName;
+ iName = NULL;
+ }
+
+TInt RCdlLibrary::CdlLoad(const TDesC& aLibName, TBool /*aRomOnly*/)
+ {
+ // get the ECom implementation id from the DLL name
+ TParsePtrC parse(aLibName);
+ TPtrC name(parse.Name());
+ TLex lexer(name);
+ TUint32 uid;
+ TInt r = lexer.Val(uid, EHex);
+ if (r!=KErrNone)
+ return r;
+
+ TRAP(r, iEcomImpl = REComSession::CreateImplementationL(TUid::Uid(uid), iEcomDtorUid, NULL));
+
+ delete iName;
+ iName = 0;
+
+ if (r==KErrNone)
+ {
+ iName = aLibName.Alloc();
+ if (!iName)
+ {
+ Close();
+ return KErrNoMemory;
+ }
+
+ iShortName.Set(ExtractName(*iName));
+ }
+
+ return r;
+ }
+
+TBool RCdlLibrary::CheckIfNotRomOnly(TBool aRomOnly, const TDesC& aName)
+ {
+ return aRomOnly &&
+ aName.Length() >= 2 && aName[1] == ':' &&
+ aName[0] != 'z' && aName[0] != 'Z';
+ }
+
+const SCdlCustomisation* RCdlLibrary::CustomisationL(TUid aUid, TInt aImplId) const
+ {
+ const TCdlArray<SCdlCustomisation>& contents = ContentsL();
+
+ // first try the micro customisation optimisation, where aImplId is an index into
+ // the contents table.
+ if (0 <= aImplId && aImplId < contents.iCount)
+ {
+ const SCdlCustomisation& c = contents[aImplId];
+ if (c.iInterface->iUid == aUid && c.iId == aImplId)
+ return &c;
+ }
+
+ // if that failed, scan the contents table.
+ for (TInt ii=0; ii<contents.iCount; ii++)
+ {
+ const SCdlCustomisation& c = contents[ii];
+ if (c.iInterface->iUid == aUid && c.iId == aImplId)
+ return &c;
+ }
+
+ User::Leave(KErrNotFound);
+ return NULL;
+ }
+
+const TCdlArray<SCdlCustomisation>& RCdlLibrary::ContentsL() const
+ {
+ TAny* f = iEcomImpl;
+ SCdlMain* m = CheckPtrL((SCdlMain*)(f));
+
+ if (m->iMajorVer != KCdlCompilerMajorVersion || m->iMinorVer != KCdlCompilerMinorVersion)
+ User::Leave(KErrCorrupt);
+ return *CheckPtrL((const TCdlArray<SCdlCustomisation>*)(m->iData));
+ }
+
+TPtrC RCdlLibrary::Name() const
+ {
+ return iShortName;
+ }
+
+const TDesC* RCdlLibrary::FullName() const
+ {
+ return iName;
+ }
+
+TPtrC RCdlLibrary::ExtractName(const TDesC& aLibName)
+ {
+ // find the postion of the colon in aLibName
+ TInt colonPos = aLibName.Locate(':');
+ // set name to be after the colon in aLibName, this works when colonPos is KErrNotFound (-1) too
+ TPtrC name(aLibName.Mid(colonPos + 1));
+ // find the postion of the last slash
+ TInt lastSlashPos = name.LocateReverse('\\');
+ // move name so that it only contains name after the last slash. Works with -1 again.
+ name.Set(name.Mid(lastSlashPos + 1));
+ // find the position of the "." in the name
+ TInt dotPos = name.Locate('.');
+ // if there is a dot, set the name to be the portion before the dot.
+ if (dotPos != KErrNotFound)
+ name.Set(name.Left(dotPos));
+ // name will now be the file name only, without extension.
+ return name;
+ }
+
+TBool RCdlLibrary::SameShortName(const TDesC& aShortLibName)
+ {
+ // Call Compare first, because it's much faster if the
+ // strings match
+ if (iShortName.Compare(aShortLibName) == 0)
+ {
+ return ETrue;
+ }
+ return iShortName.CompareF(aShortLibName) == 0;
+ }
+
+TBool RCdlLibrary::IsLibLoadedAsRomOnly() const
+ {
+ return iFlags[ERCdlLibrary_RomOnly];
+ }
+
+void RCdlLibrary::SetLibLoadedAsRomOnly()
+ {
+ iFlags.Set(ERCdlLibrary_RomOnly);
+ }
+
+//
+// RCdlLibRef
+//
+
+RCdlLibRef::RCdlLibRef() : iLibMan(0), iLib(0)
+ {
+ }
+
+void RCdlLibRef::Close()
+ {
+ if (iLib && iLibMan)
+ iLibMan->Close(iLib);
+ iLibMan = 0;
+ iLib = 0;
+ }
+
+RCdlLibrary* RCdlLibRef::Lib() const
+ {
+ return iLib;
+ }
+
+void RCdlLibRef::SetRef(CCdlLibManager* aLibMan, RCdlLibrary* aLib)
+ {
+ __ASSERT_ALWAYS(!iLib && !iLibMan, Panic(ECdlEngPanic_LibraryAlreadySet));
+ iLibMan = aLibMan;
+ iLib = aLib;
+ }
+
+TPtrC RCdlLibRef::Name() const
+ {
+ return iLib->Name();
+ }
+
+
+
+//
+// CCdlLibManager
+//
+
+CCdlLibManager::CCdlLibManager() : iLibs(KCdlLibManGranularity)
+ {
+ }
+
+CCdlLibManager::~CCdlLibManager()
+ {
+ delete iLazyUnloader;
+ TInt count = iLibs.Count();
+ for (TInt ii=0; ii<count; ii++)
+ iLibs[ii]->Close();
+ iLibs.ResetAndDestroy();
+ if (iEcom)
+ {
+ iEcom->Close();
+ REComSession::FinalClose();
+ }
+ }
+
+void CCdlLibManager::ConstructL()
+ {
+ iEcom = &REComSession::OpenL();
+ }
+
+RCdlLibRef CCdlLibManager::LoadL(const TDesC& aLibName, RCdlLibrary* aLib, TBool aRomOnly)
+ {
+ __ASSERT_DEBUG(aLib || !FindLib(aLibName), Panic(ECdlEngPanic_LibraryCanBeFound));
+
+ // load new library if a lib is not supplied
+ if (!aLib)
+ {
+ aLib = new(ELeave) RCdlLibrary;
+ CleanupStack::PushL(aLib);
+ User::LeaveIfError(aLib->CdlLoad(aLibName, aRomOnly));
+ CleanupClosePushL(*aLib);
+ iLibs.AppendL(aLib);
+ CleanupStack::Pop(2); // lib->Close() and lib's heap cell
+ }
+
+ if (aRomOnly)
+ {
+ // the lib must be ROM only if aRomOnly is set and we got here.
+ aLib->SetLibLoadedAsRomOnly();
+ }
+
+ RCdlLibRef ref;
+ ref.SetRef(this, aLib);
+ aLib->RefCount()++;
+ return ref;
+ }
+
+void CCdlLibManager::Close(RCdlLibrary* aLib)
+ {
+ aLib->RefCount()--;
+ if (aLib->RefCount()==0 && !iLazyUnloader)
+ {
+ // note, not (ELeave) because Close can't leave and
+ // unloading can always be left till another time if
+ // it doesn't work now.
+ iLazyUnloader = new CAsyncCallBack(TCallBack(LazyUnload, this), CActive::EPriorityLow);
+ if (iLazyUnloader)
+ iLazyUnloader->CallBack();
+ }
+ }
+
+TInt CCdlLibManager::LazyUnload(TAny* aThis)
+ {
+ static_cast<CCdlLibManager*>(aThis)->DoLazyUnload();
+ return 0;
+ }
+
+void CCdlLibManager::DoLazyUnload()
+ {
+ TInt count = iLibs.Count();
+ for (TInt ii=count-1; ii>=0; ii--)
+ {
+ RCdlLibrary* lib = iLibs[ii];
+ if (lib->RefCount() <= 0)
+ {
+ iLibs.Delete(ii--);
+ lib->Close();
+ delete lib;
+ }
+ }
+
+ delete iLazyUnloader;
+ iLazyUnloader = 0;
+ }
+
+RCdlLibrary* CCdlLibManager::FindLib(const TDesC& aLibName) const
+ {
+ RCdlLibrary* lib = NULL;
+ TPtrC libName(RCdlLibrary::ExtractName(aLibName));
+
+ // search for already loaded library
+ TInt count = iLibs.Count();
+ for (TInt ii=0; ii<count; ii++)
+ {
+ if (iLibs[ii]->SameShortName(libName))
+ {
+ lib = iLibs[ii];
+ break;
+ }
+ }
+
+ return lib;
+ }
+
+TBool CCdlLibManager::IsLibLoadedAsRomOnly(const TDesC& aLibName) const
+ {
+ RCdlLibrary* lib = FindLib(aLibName);
+ return lib && lib->IsLibLoadedAsRomOnly();
+ }