layouts/cdl/CdlEngine/src/CdlLibrary.cpp
changeset 0 05e9090e2422
equal deleted inserted replaced
-1:000000000000 0:05e9090e2422
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 #include "CdlLibrary.h"
       
    18 #include "CCdlEngine.h"
       
    19 #include <e32svr.h>
       
    20 #include <f32file.h>
       
    21 #include <e32uid.h>
       
    22 #ifdef RD_SECURE_BIN_RES
       
    23 #include <ecom/ecom.h>
       
    24 #endif
       
    25 
       
    26 const TInt KCdlLibManGranularity = 4;
       
    27 const TUid KCdlLibraryUid = { 0x101F8BD1 };
       
    28 
       
    29 template<class T> 
       
    30 inline T* CheckPtrL(T* aPtr)
       
    31 	{
       
    32 	if (aPtr == NULL)
       
    33 		User::Leave(KErrNotFound);
       
    34 	return aPtr;
       
    35 	}
       
    36 
       
    37 
       
    38 //
       
    39 // RCdlLibrary
       
    40 //
       
    41 
       
    42 enum TRCdlLibraryFlags
       
    43 	{
       
    44 	ERCdlLibrary_RomOnly
       
    45 	};
       
    46 
       
    47 RCdlLibrary::RCdlLibrary() : iName(0), iRefCount(0)
       
    48 ,iEcomDtorUid(KNullUid), iEcomImpl(0)
       
    49 	{
       
    50 	}
       
    51 
       
    52 void RCdlLibrary::Close()
       
    53 	{
       
    54 	REComSession::DestroyedImplementation(iEcomDtorUid);
       
    55 	iEcomDtorUid.iUid = 0;
       
    56 	iEcomImpl = 0;
       
    57 	delete iName;
       
    58 	iName = NULL;
       
    59 	}
       
    60 
       
    61 TInt RCdlLibrary::CdlLoad(const TDesC& aLibName, TBool /*aRomOnly*/)
       
    62 	{
       
    63 	// get the ECom implementation id from the DLL name
       
    64 	TParsePtrC parse(aLibName);
       
    65 	TPtrC name(parse.Name());
       
    66 	TLex lexer(name);
       
    67 	TUint32 uid;
       
    68 	TInt r = lexer.Val(uid, EHex);
       
    69 	if (r!=KErrNone)
       
    70 		return r;
       
    71 
       
    72 	TRAP(r, iEcomImpl = REComSession::CreateImplementationL(TUid::Uid(uid), iEcomDtorUid, NULL));
       
    73 
       
    74 	delete iName;
       
    75 	iName = 0;
       
    76 
       
    77 	if (r==KErrNone)
       
    78 		{
       
    79 		iName = aLibName.Alloc();
       
    80 		if (!iName)
       
    81 			{
       
    82 			Close();
       
    83 			return KErrNoMemory;
       
    84 			}
       
    85 
       
    86 		iShortName.Set(ExtractName(*iName));
       
    87 		}
       
    88 
       
    89 	return r;
       
    90 	}
       
    91 
       
    92 TBool RCdlLibrary::CheckIfNotRomOnly(TBool aRomOnly, const TDesC& aName)
       
    93 	{
       
    94 	return	aRomOnly &&
       
    95 			aName.Length() >= 2 && aName[1] == ':' && 
       
    96 			aName[0] != 'z' && aName[0] != 'Z';
       
    97 	}
       
    98 
       
    99 const SCdlCustomisation* RCdlLibrary::CustomisationL(TUid aUid, TInt aImplId) const
       
   100 	{
       
   101 	const TCdlArray<SCdlCustomisation>& contents = ContentsL();
       
   102 
       
   103 	// first try the micro customisation optimisation, where aImplId is an index into
       
   104 	// the contents table.
       
   105 	if (0 <= aImplId && aImplId < contents.iCount)
       
   106 		{
       
   107 		const SCdlCustomisation& c = contents[aImplId];
       
   108 		if (c.iInterface->iUid == aUid && c.iId == aImplId)
       
   109 			return &c;
       
   110 		}
       
   111 
       
   112 	// if that failed, scan the contents table.
       
   113 	for (TInt ii=0; ii<contents.iCount; ii++)
       
   114 		{
       
   115 		const SCdlCustomisation& c = contents[ii];
       
   116 		if (c.iInterface->iUid == aUid && c.iId == aImplId)
       
   117 			return &c;
       
   118 		}
       
   119 
       
   120 	User::Leave(KErrNotFound);
       
   121 	return NULL;
       
   122 	}
       
   123 
       
   124 const TCdlArray<SCdlCustomisation>& RCdlLibrary::ContentsL() const
       
   125 	{
       
   126 	TAny* f = iEcomImpl;
       
   127 	SCdlMain* m = CheckPtrL((SCdlMain*)(f));
       
   128 
       
   129 	if (m->iMajorVer != KCdlCompilerMajorVersion || m->iMinorVer != KCdlCompilerMinorVersion)
       
   130 		User::Leave(KErrCorrupt);
       
   131 	return *CheckPtrL((const TCdlArray<SCdlCustomisation>*)(m->iData));
       
   132 	}
       
   133 
       
   134 TPtrC RCdlLibrary::Name() const
       
   135 	{
       
   136 	return iShortName;
       
   137 	}
       
   138 
       
   139 const TDesC* RCdlLibrary::FullName() const
       
   140 	{
       
   141 	return iName;
       
   142 	}
       
   143 
       
   144 TPtrC RCdlLibrary::ExtractName(const TDesC& aLibName)
       
   145 	{
       
   146 	// find the postion of the colon in aLibName
       
   147 	TInt colonPos = aLibName.Locate(':');
       
   148 	// set name to be after the colon in aLibName, this works when colonPos is KErrNotFound (-1) too
       
   149 	TPtrC name(aLibName.Mid(colonPos + 1));
       
   150 	// find the postion of the last slash
       
   151 	TInt lastSlashPos = name.LocateReverse('\\');
       
   152 	// move name so that it only contains name after the last slash. Works with -1 again.
       
   153 	name.Set(name.Mid(lastSlashPos + 1));
       
   154 	// find the position of the "." in the name
       
   155 	TInt dotPos = name.Locate('.');
       
   156 	// if there is a dot, set the name to be the portion before the dot.
       
   157 	if (dotPos != KErrNotFound)
       
   158 		name.Set(name.Left(dotPos));
       
   159 	// name will now be the file name only, without extension.
       
   160 	return name;
       
   161 	}
       
   162 
       
   163 TBool RCdlLibrary::SameShortName(const TDesC& aShortLibName)
       
   164     {
       
   165     // Call Compare first, because it's much faster if the
       
   166 	// strings match
       
   167 	if (iShortName.Compare(aShortLibName) == 0)
       
   168 		{
       
   169 		return ETrue;
       
   170 		}
       
   171 	return iShortName.CompareF(aShortLibName) == 0;
       
   172 	}
       
   173 
       
   174 TBool RCdlLibrary::IsLibLoadedAsRomOnly() const
       
   175 	{
       
   176 	return iFlags[ERCdlLibrary_RomOnly];
       
   177 	}
       
   178 
       
   179 void RCdlLibrary::SetLibLoadedAsRomOnly()
       
   180 	{
       
   181 	iFlags.Set(ERCdlLibrary_RomOnly);
       
   182 	}
       
   183 
       
   184 //
       
   185 // RCdlLibRef
       
   186 //
       
   187 
       
   188 RCdlLibRef::RCdlLibRef() : iLibMan(0), iLib(0)
       
   189 	{
       
   190 	}
       
   191 
       
   192 void RCdlLibRef::Close()
       
   193 	{
       
   194 	if (iLib && iLibMan)
       
   195 		iLibMan->Close(iLib);
       
   196 	iLibMan = 0;
       
   197 	iLib = 0;
       
   198 	}
       
   199 
       
   200 RCdlLibrary* RCdlLibRef::Lib() const
       
   201 	{
       
   202 	return iLib;
       
   203 	}
       
   204 
       
   205 void RCdlLibRef::SetRef(CCdlLibManager* aLibMan, RCdlLibrary* aLib)
       
   206 	{
       
   207 	__ASSERT_ALWAYS(!iLib && !iLibMan, Panic(ECdlEngPanic_LibraryAlreadySet));
       
   208 	iLibMan = aLibMan;
       
   209 	iLib = aLib;
       
   210 	}
       
   211 
       
   212 TPtrC RCdlLibRef::Name() const
       
   213 	{
       
   214 	return iLib->Name();
       
   215 	}
       
   216 
       
   217 
       
   218 
       
   219 //
       
   220 // CCdlLibManager
       
   221 //
       
   222 
       
   223 CCdlLibManager::CCdlLibManager() : iLibs(KCdlLibManGranularity)
       
   224 	{
       
   225 	}
       
   226 
       
   227 CCdlLibManager::~CCdlLibManager()
       
   228 	{
       
   229 	delete iLazyUnloader;
       
   230 	TInt count = iLibs.Count();
       
   231 	for (TInt ii=0; ii<count; ii++)
       
   232 		iLibs[ii]->Close();
       
   233 	iLibs.ResetAndDestroy();
       
   234 	if (iEcom)
       
   235 		{
       
   236 		iEcom->Close();
       
   237 		REComSession::FinalClose();
       
   238 		}
       
   239 	}
       
   240 
       
   241 void CCdlLibManager::ConstructL()
       
   242 	{
       
   243 	iEcom = &REComSession::OpenL();
       
   244 	}
       
   245 
       
   246 RCdlLibRef CCdlLibManager::LoadL(const TDesC& aLibName, RCdlLibrary* aLib, TBool aRomOnly)
       
   247 	{
       
   248 	__ASSERT_DEBUG(aLib || !FindLib(aLibName), Panic(ECdlEngPanic_LibraryCanBeFound));
       
   249 
       
   250 	// load new library if a lib is not supplied
       
   251 	if (!aLib)
       
   252 		{
       
   253 		aLib = new(ELeave) RCdlLibrary;
       
   254 		CleanupStack::PushL(aLib);
       
   255 		User::LeaveIfError(aLib->CdlLoad(aLibName, aRomOnly));
       
   256 		CleanupClosePushL(*aLib);
       
   257 		iLibs.AppendL(aLib);
       
   258 		CleanupStack::Pop(2);		// lib->Close() and lib's heap cell
       
   259 		}
       
   260 
       
   261 	if (aRomOnly)
       
   262 		{
       
   263 		// the lib must be ROM only if aRomOnly is set and we got here.
       
   264 		aLib->SetLibLoadedAsRomOnly();
       
   265 		}
       
   266 
       
   267 	RCdlLibRef ref;
       
   268 	ref.SetRef(this, aLib);
       
   269 	aLib->RefCount()++;
       
   270 	return ref;
       
   271 	}
       
   272 
       
   273 void CCdlLibManager::Close(RCdlLibrary* aLib)
       
   274 	{
       
   275 	aLib->RefCount()--;
       
   276 	if (aLib->RefCount()==0 && !iLazyUnloader)
       
   277 		{
       
   278 		// note, not (ELeave) because Close can't leave and
       
   279 		// unloading can always be left till another time if
       
   280 		// it doesn't work now.
       
   281 		iLazyUnloader = new CAsyncCallBack(TCallBack(LazyUnload, this), CActive::EPriorityLow);
       
   282 		if (iLazyUnloader)
       
   283 			iLazyUnloader->CallBack();
       
   284 		}
       
   285 	}
       
   286 
       
   287 TInt CCdlLibManager::LazyUnload(TAny* aThis)
       
   288 	{
       
   289 	static_cast<CCdlLibManager*>(aThis)->DoLazyUnload();
       
   290 	return 0;
       
   291 	}
       
   292 	
       
   293 void CCdlLibManager::DoLazyUnload()
       
   294 	{
       
   295 	TInt count = iLibs.Count();
       
   296 	for (TInt ii=count-1; ii>=0; ii--)
       
   297 		{
       
   298 		RCdlLibrary* lib = iLibs[ii];
       
   299 		if (lib->RefCount() <= 0)
       
   300 			{
       
   301 			iLibs.Delete(ii--);
       
   302 			lib->Close();
       
   303 			delete lib;
       
   304 			}
       
   305 		}
       
   306 
       
   307 	delete iLazyUnloader;
       
   308 	iLazyUnloader = 0;
       
   309 	}
       
   310 	
       
   311 RCdlLibrary* CCdlLibManager::FindLib(const TDesC& aLibName) const
       
   312 	{
       
   313 	RCdlLibrary* lib = NULL;
       
   314 	TPtrC libName(RCdlLibrary::ExtractName(aLibName));
       
   315 
       
   316 	// search for already loaded library
       
   317 	TInt count = iLibs.Count();
       
   318 	for (TInt ii=0; ii<count; ii++)
       
   319 		{
       
   320 		if (iLibs[ii]->SameShortName(libName))
       
   321 			{
       
   322 			lib = iLibs[ii];
       
   323 			break;
       
   324 			}
       
   325 		}
       
   326 
       
   327 	return lib;
       
   328 	}
       
   329 
       
   330 TBool CCdlLibManager::IsLibLoadedAsRomOnly(const TDesC& aLibName) const
       
   331 	{
       
   332 	RCdlLibrary* lib = FindLib(aLibName);
       
   333 	return lib && lib->IsLibLoadedAsRomOnly();
       
   334 	}