lowlevellibsandfws/pluginfw/Framework/frame/LoadManager.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implementation of the CLoadManager class
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @internalComponent
       
    20  @file
       
    21 */
       
    22 
       
    23 #include "EComDebug.h"
       
    24 #include "UnloadPolicy.h"
       
    25 #include "LoadManager.h"
       
    26 #include "EComUidCodes.h"
       
    27 #include <ecom/ecomerrorcodes.h>
       
    28 #include "e32math.h"
       
    29 #include "EComInternalErrorCodes.h"
       
    30 #include <ecom/ecomextendedinterfaceerrorcodes.h>
       
    31 /**
       
    32 Standardized safe construction which leaves nothing on the cleanup stack.
       
    33 @return			A pointer to the new class
       
    34 @post			CLoadManager is fully constructed, and initialized.
       
    35  */
       
    36 CLoadManager* CLoadManager::NewL()
       
    37 	{
       
    38 	return new(ELeave) CLoadManager();
       
    39 	}
       
    40 
       
    41 CLoadManager::~CLoadManager()
       
    42 	{
       
    43 	iInstanceInfoList.ResetAndDestroy();
       
    44 	iAllUnloadPolicies.ResetAndDestroy();
       
    45 	ClearGarbage();
       
    46 	}
       
    47 
       
    48 /**
       
    49 Notifies the interface implementation DLL that one of its objects has been destroyed if it exists,
       
    50 otherwise returns false to indicate no exist aImplementationUid.
       
    51 @param          aInstanceKey A key specifying a previously created implementation.
       
    52 @pre 			CLoadManager is fully constructed,
       
    53 @post			CLoadManager's interface implementation DLL references
       
    54 				are decreased by one. The instance info representing the implementation
       
    55 				is destroyed.
       
    56 */
       
    57 TBool CLoadManager::DestroyedThis(TUid aInstanceKey)
       
    58 	{
       
    59 	// Clear the garbage list because we know we have finished with them
       
    60 	ClearGarbage();
       
    61 
       
    62 	__ECOM_TRACE1("ECOM: Implementation Instance destroyed %x", aInstanceKey.iUid);
       
    63 
       
    64 	// Sanity check that the pointer is divisible by four. A binary number is divisible
       
    65 	// by four if and only if the two rightmost bits are both zero.
       
    66 	// This is a compromised check for checking that the pointer is an address.
       
    67     if ((aInstanceKey.iUid == 0) || ((aInstanceKey.iUid & 0x00000003) != 0))
       
    68         {
       
    69 	    __ASSERT_DEBUG(EFalse, User::Panic(KEComClientDLLPanicCategory, EEComPanic_InvalidImplementationInstanceKey));
       
    70 	    User::Leave(KErrNotFound);
       
    71         }
       
    72 
       
    73 	// The instance info pointer is stored in the instance key.
       
    74 	CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);
       
    75 
       
    76 	// Check that the pointer exists before using it
       
    77 	TInt position = iInstanceInfoList.FindInAddressOrder(instanceInfo);
       
    78 	if(position == KErrNotFound)
       
    79 		{
       
    80 		return EFalse;
       
    81 		}
       
    82 	
       
    83 	CUnloadPolicy* policy = instanceInfo->UnloadPolicy();
       
    84 	if (policy != NULL)
       
    85 		{
       
    86 		// If needed, will move the policy to the garbage list, and remove policy from the unload policy list.
       
    87 		Cleanup(policy);
       
    88 		}
       
    89 	iInstanceInfoList.Remove(position);
       
    90 	// Remove the instance info item, finished with it.
       
    91 	delete instanceInfo;
       
    92 	return ETrue;
       
    93 	}
       
    94 
       
    95 /**
       
    96 Check whether the policy Arrays are empty or not.
       
    97 @return            Returns True if the policy Arrays are empty, otherwise return False.
       
    98 @pre             CLoadManager is fully constructed,
       
    99 @post            CLoadManager remains the same.
       
   100 */
       
   101 TBool CLoadManager::PolicyArraysEmpty() const 
       
   102     {
       
   103     if( (iAllUnloadPolicies.Count() == 0)&&(iInstanceInfoList.Count() == 0) )
       
   104         {
       
   105         return ETrue;
       
   106         }
       
   107     else
       
   108         {
       
   109         return EFalse;
       
   110         }
       
   111     }
       
   112 
       
   113 /**
       
   114 Returns an implementation object to satisfy the specified interface.
       
   115 @param			aUniqueImplementationUid The implementation to find.
       
   116 @param			aEntry Information on the dll containing the implementation
       
   117 @param			aCreationParameters A pointer to the creation parameter
       
   118 				structure passed to the creation method when called.
       
   119 @param			aCreationParamsFlag A boolean flag to indicate the existence or non-existence
       
   120 				of aCreationParameters. Will be ETrue even for if the value of
       
   121 				aCreationParameters is NULL.
       
   122 @param          aInstanceKey A key specifying a previously created implementation.
       
   123 @return			TAny* a pointer to the fully constructed instantiation. The pointer is
       
   124 				guaranteed to be valid only until DestroyedThis is called.
       
   125 @pre 			CLoadManager is fully constructed,
       
   126 @post			Fully constructed implementation is returned to the
       
   127 				caller, and aUniqueUid contains the implementation Dll's
       
   128 				unique UID.
       
   129 */
       
   130 TAny* CLoadManager::ImplementationObjectL(const TUid& aUniqueImplementationUid,
       
   131 										 const TEntry& aEntry,
       
   132 										 TAny* aCreationParameters,
       
   133 										 TBool aCreationParamsFlag,
       
   134 										 TUid& aInstanceKey)
       
   135 	{
       
   136 	//if the implementation Uid here is Null or the entry returned by the ecomserver
       
   137 	//contains nothing, we should leave with KErrNotFound
       
   138 	if(aUniqueImplementationUid == KNullUid || (aEntry.iName).Length()==0)
       
   139 		{
       
   140 		User::Leave(KErrNotFound);
       
   141 		}
       
   142 
       
   143 	TAny* object = NULL;               // Instantiation object
       
   144 	CUnloadPolicy* policy = NULL;      // Policy of implementation
       
   145 	TLibraryFunction libFunctionProxy; // Library function proxy pointer
       
   146 
       
   147 	GetUnloadPolicy(aUniqueImplementationUid,aEntry,policy);
       
   148 	if (policy == NULL)
       
   149 		{
       
   150 		// No policy found, so create a new CUnloadPolicy and load DLL.
       
   151 		policy = CUnloadPolicy::NewLC(aEntry);
       
   152 		libFunctionProxy = policy->LoadDllAndReturnProxyL();
       
   153 		if (libFunctionProxy==NULL)
       
   154 			{
       
   155 			User::Leave(KErrNotFound);
       
   156 			}
       
   157 		iAllUnloadPolicies.AppendL(policy);
       
   158 		CleanupStack::Pop(policy);	// owned by iAllUnloadPolicies
       
   159 		}
       
   160 	else
       
   161 		{
       
   162 		// Found a policy. Load Dll if not already loaded.
       
   163 		libFunctionProxy = policy->LoadDllAndReturnProxyL();
       
   164 		if (libFunctionProxy==NULL)
       
   165 			{
       
   166 			User::Leave(KErrNotFound);
       
   167 			}
       
   168 		}
       
   169 	// Initial count of instances. This is used for cleanup purposes, to see if an instance
       
   170 	// was added to the instance info list during the object creation. If a failure occurs
       
   171 	// than the instance info that was added to the list will be removed.
       
   172 	TInt initialCount = iInstanceInfoList.Count();
       
   173 	TInt err = KErrNone;
       
   174 
       
   175 	if (aEntry[1] == KUidInterfaceImplementationCollection)
       
   176 		{
       
   177 		// PLUGIN1 dll. Create the implementation object.
       
   178 		TRAP(err,object = ImplementationObject1L(aUniqueImplementationUid,aCreationParameters,
       
   179 			aCreationParamsFlag,aInstanceKey,policy,libFunctionProxy));
       
   180 		}
       
   181 	else if (aEntry[1] == KUidInterfaceImplementationCollection3)
       
   182 		{
       
   183 		// PLUGIN3 dll. Create the implementation object.
       
   184 		TRAP(err,object = ImplementationObject3L(aUniqueImplementationUid,aCreationParameters,
       
   185 			aCreationParamsFlag, aInstanceKey,policy, libFunctionProxy));
       
   186 		}
       
   187 	else
       
   188 		{
       
   189 		err = KErrNotSupported;
       
   190 		}
       
   191 	
       
   192 	if (err != KErrNone)
       
   193 		{
       
   194 		if (iInstanceInfoList.Count() > initialCount)
       
   195 			{
       
   196 			// If an instance was added to the instance list, remove it here.
       
   197 			// The instance info pointer is stored in the instance key. We know its
       
   198 			// valid because it was set by ecom in call to ImplementationObject1L or
       
   199 			// ImplementationObject3L
       
   200 			CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);
       
   201 			TInt pos = iInstanceInfoList.FindInAddressOrder(instanceInfo);
       
   202 			if(pos != KErrNotFound)
       
   203 				{
       
   204 				iInstanceInfoList.Remove(pos);
       
   205 				}
       
   206 			}
       
   207 
       
   208 		ClearGarbage();
       
   209 		// If needed, will move the policy to the garbage list, and remove policy from the unload policy list.
       
   210 		Cleanup(policy);
       
   211 		User::Leave(err);
       
   212 		}
       
   213 		
       
   214 	__ECOM_TRACE2("ECOM: Implementation created (%03d) %x", ++iDebugInstantiationCounter, aUniqueImplementationUid.iUid);
       
   215 			
       
   216 	return object;
       
   217 	}
       
   218 
       
   219 /**
       
   220 Returns an implementation object to satisfy the specified interface.
       
   221 @param			aUniqueImplementationUid The implementation to find.
       
   222 @param			aCreationParameters A pointer to the creation parameter
       
   223 				structure passed to the creation method when called.
       
   224 @param			aCreationParamsFlag A boolean flag to indicate the existence or non-existence
       
   225 				of aCreationParameters. Will be ETrue even for if the value of
       
   226 				aCreationParameters is NULL.
       
   227 @param          aInstanceKey A key specifying a previously created implementation.
       
   228 @param          aPolicy policy of implementation
       
   229 @param          aLibFunctionProxy Library function proxy pointer.
       
   230 @return			TAny* a pointer to the fully constructed instantiation. The pointer is
       
   231 				guaranteed to be valid only until DestroyedThis is called.
       
   232 */
       
   233 TAny* CLoadManager::ImplementationObject1L(const TUid& aUniqueImplementationUid,
       
   234 										 TAny* aCreationParameters,
       
   235 										 TBool aCreationParamsFlag,
       
   236 										 TUid& aInstanceKey,
       
   237 										 CUnloadPolicy* aPolicy,
       
   238 										 TLibraryFunction& aLibFunctionProxy)
       
   239 	{
       
   240 	TAny* object = NULL; // Instantiation object
       
   241 	TInstantiationL proxy = reinterpret_cast<TInstantiationL>(aLibFunctionProxy);
       
   242 
       
   243 	TImplementationProxy* implementationProxyRow = NULL;
       
   244 	TAny* newLPointer = GetNewLPointerAndProxyTableRowL<TImplementationProxy,TInstantiationL>(aUniqueImplementationUid,implementationProxyRow,proxy);
       
   245 	// Now create an instance info object to store the information about this instance derived from
       
   246 	// the parameters just fetched. This must be created here since no leaves can occur after the object
       
   247 	// instantiation below.
       
   248 	CInstanceInfoSimple* instanceInfoSimple = CInstanceInfoSimple::NewL(aPolicy,implementationProxyRow);
       
   249 	CleanupStack::PushL(instanceInfoSimple);
       
   250 
       
   251 	// The pointer to instanceInfo will be used to identify this instance, and will
       
   252 	// be returned to the caller for future identification of this instance.
       
   253 	aInstanceKey.iUid = reinterpret_cast<TInt32>(instanceInfoSimple);
       
   254 
       
   255 	// Add item to instance info list. This list will contain all of the instance objects.
       
   256 	iInstanceInfoList.InsertInAddressOrderL(instanceInfoSimple);
       
   257 
       
   258 	// Get the implementation object using the instantiation pointer fetched earlier. Note
       
   259 	// that the object creation must be the last leaving operation to be performed. No leaves can occur
       
   260 	// after this operation, as the instantiation object cannnot be deleted on the cleanup stack if
       
   261 	// a leave occurs (cannot delete a TAny* pointer, the type is not known within ECOM).
       
   262 	object = ImplementationObjectL(aCreationParameters, 
       
   263 	 aCreationParamsFlag,newLPointer);
       
   264 
       
   265 	CleanupStack::Pop(instanceInfoSimple);
       
   266 
       
   267 	return object;
       
   268 	}
       
   269 
       
   270 /**
       
   271 Returns an implementation object to satisfy the specified interface.
       
   272 @param			aUniqueImplementationUid The implementation to find.
       
   273 @param			aCreationParameters A pointer to the creation parameter
       
   274 				structure passed to the creation method when called.
       
   275 @param			aCreationParamsFlag A boolean flag to indicate the existence or non-existence
       
   276 				of aCreationParameters. Will be ETrue even for if the value of
       
   277 				aCreationParameters is NULL.
       
   278 @param          aInstanceKey A key specifying a previously created implementation.
       
   279 @param          aPolicy policy of implementation
       
   280 @param          aLibFunctionProxy Library function proxy pointer.
       
   281 @return			TAny* a pointer to the fully constructed instantiation. The pointer is
       
   282 				guaranteed to be valid only until DestroyedThis is called.
       
   283 */
       
   284 TAny* CLoadManager::ImplementationObject3L(const TUid& aUniqueImplementationUid,
       
   285 										 TAny* aCreationParameters,
       
   286 										 TBool aCreationParamsFlag,
       
   287 										 TUid& aInstanceKey,
       
   288 										 CUnloadPolicy* aPolicy,
       
   289 										 TLibraryFunction& aLibFunctionProxy)
       
   290 	{
       
   291 	TAny* object = NULL;  // Instantiation object
       
   292 	TInstantiation3L proxy = reinterpret_cast<TInstantiation3L>(aLibFunctionProxy);
       
   293 
       
   294 	TImplementationProxy3* implementationProxyRow = NULL;
       
   295 	TAny* newLPointer = GetNewLPointerAndProxyTableRowL<TImplementationProxy3,TInstantiation3L>(aUniqueImplementationUid,implementationProxyRow,proxy);
       
   296 
       
   297 	// Now create an instance info object to store the information about this instance derived from
       
   298 	// the parameters just fetched. This must be created here since no leaves can occur after the object
       
   299 	// instantiation below.
       
   300 	CInstanceInfoExtended* instanceInfoExtended = CInstanceInfoExtended::NewL(aPolicy,implementationProxyRow);
       
   301 	CleanupStack::PushL(instanceInfoExtended);
       
   302 
       
   303 	// The pointer to instanceInfo will be used to identify this instance, and will
       
   304 	// be returned to the caller for future identification of this instance.
       
   305 	aInstanceKey.iUid = reinterpret_cast<TInt32>(instanceInfoExtended);
       
   306 
       
   307 	// Add item to instance info list. This list will contain all of the instance objects.
       
   308 	iInstanceInfoList.InsertInAddressOrderL(instanceInfoExtended);
       
   309 
       
   310 	// Get the implementation object using the instantiation pointer fetched earlier. Note
       
   311 	// that the object creation must be the last leaving operation to be performed. No leaves can occur
       
   312 	// after this operation, as the instantiation object cannnot be deleted on the cleanup stack if
       
   313 	// a leave occurs (cannot delete a TAny* pointer, the type is not known within ECOM).
       
   314 	object = ImplementationObjectL(aCreationParameters, 
       
   315 	 aCreationParamsFlag,newLPointer);
       
   316 
       
   317 	// The extended instance info requires an object set. This is done here
       
   318 	// as the object is not known until now, but the instance info object was required to
       
   319 	// be created earlier to avoid a leave after the object creation.
       
   320 	instanceInfoExtended->SetObject(object);
       
   321 	CleanupStack::Pop(instanceInfoExtended);
       
   322 
       
   323 	return object;
       
   324 	}
       
   325 
       
   326 /**
       
   327 Gets the main implementation object using the instantiation pointer provided
       
   328 @param			aCreationParameters A pointer to the creation parameter
       
   329 				structure passed to the creation method when called.
       
   330 @param			aCreationParamsFlag A boolean flag to indicate the existence or non-existence
       
   331 				of aCreationParameters. Will be ETrue even for if the value of
       
   332 				aCreationParameters is NULL.
       
   333 @param			aNewLpointer Instantation pointer.
       
   334 				aCreationParameters is NULL.
       
   335 @return			TAny* a pointer to the fully constructed instantiation.
       
   336 */
       
   337 TAny* CLoadManager::ImplementationObjectL(TAny* aCreationParameters,
       
   338 										 TBool aCreationParamsFlag,
       
   339 										 const TAny* aNewLpointer)
       
   340 	{
       
   341 	TAny* object=NULL;
       
   342 
       
   343 	// So cast to the correct type : This gives an ANSI C++ warning
       
   344 	// When using a REINTERPRET_CAST so simply cast instead
       
   345 	// Two different object creation one with creation parameters
       
   346 	if (aCreationParamsFlag)
       
   347 		{
       
   348 		typedef TAny* (*TNewL)(TAny*);
       
   349 		TNewL creationL = (TNewL)(aNewLpointer);
       
   350 		object=creationL(aCreationParameters);
       
   351 		}
       
   352 	else
       
   353 		{
       
   354 		typedef TAny* (*TNewL)();
       
   355 		TNewL creationL = (TNewL)(aNewLpointer);
       
   356 		object=creationL();
       
   357 		}
       
   358 
       
   359 	return object;
       
   360 	}
       
   361 
       
   362 /**
       
   363 Get the unload policy.
       
   364 @param			aUniqueImplementationUid The implementation to find.
       
   365 @param			aEntry Information on the dll containing the implementation
       
   366 @param			aPolicy Return parameter containing the policy
       
   367 @return			None
       
   368 */
       
   369 void CLoadManager::GetUnloadPolicy(TUid aUniqueImplementationUid,
       
   370 							  const TEntry& aEntry,
       
   371 							  CUnloadPolicy*& aPolicy)
       
   372 	{
       
   373 	const TInt numImps = iInstanceInfoList.Count();
       
   374 	TBool foundImp = EFalse;
       
   375 	TInt matchingDllIndex=0;
       
   376 	TBool matchingDllFound=EFalse;
       
   377 	CUnloadPolicy* policy = NULL;
       
   378 
       
   379 	for (TInt index = 0; (index<numImps) && !foundImp; ++index)
       
   380 		{
       
   381 		//Check if there is existing mapping between the supplied implUid and a policy
       
   382 		if(iInstanceInfoList[index]->ImplementationUid() == aUniqueImplementationUid)
       
   383 			{
       
   384 			policy = iInstanceInfoList[index]->UnloadPolicy();
       
   385 
       
   386 			foundImp = ETrue;
       
   387 			}
       
   388 		else
       
   389 			{
       
   390 			//if cannot find a mapping entry but current index has the same DLL as the one requested from
       
   391 			//the client, store the index to this unloadPolicy for use later on if we have finished
       
   392 			//searching the entire mapping list
       
   393 			if (!matchingDllFound && (iInstanceInfoList[index]->UnloadPolicy()->DllEntryInformation().GetName()).CompareF(aEntry.iName)==0)
       
   394 				{
       
   395 				matchingDllIndex=index;
       
   396 				matchingDllFound=ETrue;
       
   397 				}
       
   398 			}
       
   399 		}
       
   400 
       
   401 	//If we cannot find any mapping in the policy index array(iUnloadPolicyMapping)
       
   402 	if(!foundImp)
       
   403 		{
       
   404 		//if not found but there is a matching DLL,we can simply create a new policy index mapping without
       
   405 		//having to load the library again.
       
   406 		if (matchingDllFound)
       
   407 			{
       
   408 			policy = iInstanceInfoList[matchingDllIndex]->UnloadPolicy();
       
   409 			}
       
   410 		}
       
   411 
       
   412 	aPolicy = policy;
       
   413 	}
       
   414 
       
   415 /**
       
   416 Clears the policy inside the iGarbagePolicies attribute.
       
   417 @pre			CLoadManager is fully constructed
       
   418 @post			CLoadManager iGarbagePolicies is zero'd
       
   419 */
       
   420 void CLoadManager::ClearGarbage()
       
   421 	{
       
   422 	if (iGarbagePolicy != NULL)
       
   423 		{
       
   424 		delete iGarbagePolicy;
       
   425 		iGarbagePolicy=0;
       
   426 		}
       
   427 	}
       
   428 
       
   429 CLoadManager::CLoadManager() :
       
   430 	CBase()
       
   431 	{
       
   432 	// Do nothing here
       
   433 	}
       
   434 
       
   435 /**
       
   436 Returns the implementation ID for a given instance Key.
       
   437 @leave			KErrNotFound
       
   438 @param			aInstanceKey A key specifying a previously created implementation instance.
       
   439 @return			TUid The uid of the corresponding implementation.
       
   440 @pre 			CLoadManager is fully constructed,
       
   441 @post			CLoadManager remains the same.
       
   442 */
       
   443 TUid CLoadManager::GetImplementationUidL(TUid aInstanceKey)
       
   444 	{
       
   445 	// Sanity check that the pointer is divisible by four. A binary number is divisible
       
   446 	// by four if and only if the two rightmost bits are both zero.
       
   447 	// This is a compromised check for checking that the pointer is an address.
       
   448     if ((aInstanceKey.iUid == 0) || ((aInstanceKey.iUid & 0x00000003) != 0))
       
   449         {
       
   450 	    __ASSERT_DEBUG(EFalse, User::Panic(KEComClientDLLPanicCategory, EEComPanic_InvalidImplementationInstanceKey));
       
   451 	    User::Leave(KErrNotFound);
       
   452         }
       
   453 
       
   454 	// The instance info pointer is stored in the instance key.
       
   455 	CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);
       
   456 
       
   457 	// Check that the pointer exists before using it - leaves with KErrNotFound
       
   458 	iInstanceInfoList.FindInAddressOrderL(instanceInfo);
       
   459 	return instanceInfo->ImplementationUid();
       
   460 	}
       
   461 
       
   462 /**
       
   463 Fetches the requested extended interface from a specified implementation instance.
       
   464 @leave			KErrNotFound
       
   465 @param 			aInstanceKey A key specifying a previously created implementation.
       
   466 @param 			aExtendedInterfaceUid Identifies an interface to fetch from the plug-in instance.
       
   467 @return			TAny* A pointer to the extended interface, will be NULL if it does not exist.
       
   468 */
       
   469 TAny* CLoadManager::GetExtendedInterfaceL(const TUid& aInstanceKey, const TUid& aExtendedInterfaceUid)
       
   470 	{
       
   471 	// Sanity check that the pointer is divisible by four. A binary number is divisible
       
   472 	// by four if and only if the two rightmost bits are both zero.
       
   473 	// This is a compromised check for checking that the pointer is an address.
       
   474     if ((aInstanceKey.iUid == 0) || ((aInstanceKey.iUid & 0x00000003) != 0))
       
   475         {
       
   476 	    __ASSERT_DEBUG(EFalse, User::Panic(KEComClientDLLPanicCategory, EEComPanic_InvalidImplementationInstanceKey));
       
   477 	    User::Leave(KErrNotFound);
       
   478         }
       
   479 
       
   480 	// The instance info pointer is stored in the instance key.
       
   481 	CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);
       
   482 
       
   483 	// Check that the pointer exists before using it - leaves with KErrNotFound
       
   484 	iInstanceInfoList.FindInAddressOrderL(instanceInfo);
       
   485 	
       
   486 	// Create the extension object. The instance info object will be populated with
       
   487 	// the extension info during creation.
       
   488 	TAny* object = instanceInfo->CreateExtObjectL(aExtendedInterfaceUid);
       
   489 	return object;
       
   490 	}
       
   491 
       
   492 /**
       
   493 Manually releases the requested interface. Does nothing if it does not exist.
       
   494 This interface is optional, normally the interfaces are cleaned up automatically.
       
   495 @leave			KErrNotFound
       
   496 @param			aInstanceKey A key specifying a previously created implementation.
       
   497 @param			aExtendedInterfaceUid Identifies the interface to release
       
   498 @return None.
       
   499 */
       
   500 void CLoadManager::ManuallyReleaseExtendedInterfaceL(const TUid& aInstanceKey, const TUid& aExtendedInterfaceUid)
       
   501 	{
       
   502 	// Sanity check that the pointer is divisible by four. A binary number is divisible
       
   503 	// by four if and only if the two rightmost bits are both zero.
       
   504 	// This is a compromised check for checking that the pointer is an address.
       
   505     if ((aInstanceKey.iUid == 0) || ((aInstanceKey.iUid & 0x00000003) != 0))
       
   506         {
       
   507 	    __ASSERT_DEBUG(EFalse, User::Panic(KEComClientDLLPanicCategory, EEComPanic_InvalidImplementationInstanceKey));
       
   508 	    User::Leave(KErrNotFound);
       
   509         }
       
   510         
       
   511 	// The instance info pointer is stored in the instance key.
       
   512 	CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);
       
   513 
       
   514 	// Check that the pointer exists before using it - leaves with KErrNotFound
       
   515 	iInstanceInfoList.FindInAddressOrderL(instanceInfo);
       
   516 	
       
   517 	instanceInfo->DestroyExtObject(aExtendedInterfaceUid);
       
   518 	}
       
   519 
       
   520 /**
       
   521 Utility method to move the policy to the garbage list, remove
       
   522 policy from the unload policy list.
       
   523 @param aPolicy Unload policy to clean up
       
   524 @return None.
       
   525 */
       
   526 void CLoadManager::Cleanup(CUnloadPolicy* aPolicy)
       
   527 	{
       
   528 	if (aPolicy->DecreaseReference() == EDeleteMe)
       
   529 		{
       
   530 		// Move the policy to the garbage list
       
   531 		iGarbagePolicy=aPolicy;
       
   532 
       
   533 		TInt index = iAllUnloadPolicies.Find(aPolicy);
       
   534 		if (index != KErrNotFound)
       
   535 			{
       
   536 			iAllUnloadPolicies.Remove(index);
       
   537 			}
       
   538 		}
       
   539 	}
       
   540 
       
   541 //
       
   542 // CInstanceInfo
       
   543 /**
       
   544 Default constructor of CInstanceInfo
       
   545 @param			aUnloadPolicy The CUnloadPolicy of the dll
       
   546 */
       
   547 CInstanceInfo::CInstanceInfo(CUnloadPolicy* aUnloadPolicy):
       
   548 	iUnloadPolicy(aUnloadPolicy)
       
   549 	{
       
   550 	// Do nothing here
       
   551 	}
       
   552 
       
   553 /** 
       
   554 Destructor of CInstanceInfo
       
   555 */
       
   556 CInstanceInfo::~CInstanceInfo()
       
   557 	{
       
   558 	// Do nothing here
       
   559 	}
       
   560 
       
   561 
       
   562 //
       
   563 // CInstanceInfoExtended
       
   564 /**
       
   565 Default constructor of CInstanceInfoExtended
       
   566 @param			aUnloadPolicy The CUnloadPolicy of the dll
       
   567 @param			aImplementationProxyRow The interface implementation proxy row entry
       
   568 */
       
   569 CInstanceInfoExtended::CInstanceInfoExtended(CUnloadPolicy* aUnloadPolicy,const TImplementationProxy3* aImplementationProxyRow):
       
   570 	CInstanceInfo(aUnloadPolicy),iImplementationProxyRow(aImplementationProxyRow)
       
   571 	{
       
   572 	// Do nothing here
       
   573 	}
       
   574 
       
   575 /**
       
   576 create an instance of CInstanceInfoExtended
       
   577 @param			aUnloadPolicy The CUnloadPolicy of the dll
       
   578 @param			aImplementationProxyRow The interface implementation proxy row entry
       
   579 @return			A pointer to the newly created object.
       
   580 */
       
   581 CInstanceInfoExtended* CInstanceInfoExtended::NewL(CUnloadPolicy* aUnloadPolicy,const TImplementationProxy3* aImplementationProxyRow)
       
   582 	{
       
   583 	return new(ELeave) CInstanceInfoExtended(aUnloadPolicy,aImplementationProxyRow);
       
   584 	}
       
   585 
       
   586 /**
       
   587 Sets the implementation object.
       
   588 @param			aImplementationObject The object instance of this instances' implementation
       
   589 @return			None
       
   590 */
       
   591 void CInstanceInfoExtended::SetObject(TAny* aImplementationObject)
       
   592 	{
       
   593 	iImplementationObject = aImplementationObject;
       
   594 	}
       
   595 
       
   596 /**
       
   597 Creates the extension interface object. This will use the get extended interface
       
   598 function pointer from the proxy table to fetch the extended interface from the
       
   599 plug-in implementation.
       
   600 @param			aExtendedInterfaceUID The extended interface UID
       
   601 @return			TAny* A pointer to an instance of an extended interface created
       
   602 */
       
   603 TAny* CInstanceInfoExtended::CreateExtObjectL(const TUid& aExtendedInterfaceUID)
       
   604 	{
       
   605 	// Fetch the function pointer to create the extended interface
       
   606 	TProxyExtendedInterfaceGetPtrL createFunctionPtrL = iImplementationProxyRow->iFuncPtrInterfaceGetL;
       
   607 	if (createFunctionPtrL == NULL)
       
   608 		{
       
   609 		// No extension interface object can be created. Return NULL indicating that
       
   610 		// no extended interface object is available.
       
   611 		return NULL;
       
   612 		}
       
   613 
       
   614 	// Valid function pointer exists in proxy table.
       
   615 	TAny* object = NULL;         // Extended interface object (this points to the interface
       
   616 							     // within the object)
       
   617 	TAny* releaseObject = NULL;  // Eextended interface object (this points to the extended
       
   618 								 // object itself). Used to delete the extended interface
       
   619 								 // object later.
       
   620 	TUint32 flags = 0;           // Flags to allow the plug-in and ECOM to communicate
       
   621 	// Create the extension object.
       
   622 	object = createFunctionPtrL(iImplementationObject,aExtendedInterfaceUID,flags,releaseObject);
       
   623 
       
   624 	if (flags & KReleaseRequiredMask)
       
   625 		{
       
   626 		// If release of the extended interface is required then save the release object pointer.
       
   627 		// The interface object (returned by the function pointer call) and the release object
       
   628 		// are not necessarily the same pointer. This is because the  interface pointer is not
       
   629 		// guaranteed to be the same as the pointer to the extended interface object. That
       
   630 		// is why the release object is required to be fetched from the plug-in.
       
   631 
       
   632         // First perform some checks to ensure that the plugin is consistent 
       
   633         TProxyExtendedInterfaceReleasePtr release = iImplementationProxyRow->iFuncPtrInterfaceRelease;
       
   634                 
       
   635         if (release == NULL)
       
   636             {
       
   637             // ...the release object pointer must not be non null
       
   638             __ECOM_TRACE("ECOM: PANIC in CInstanceInfoExtended::CreateExtObjectL, release required but release function missing");
       
   639 	        __ASSERT_DEBUG(EFalse, User::Panic (KEComClientDLLPanicCategory, EEComPanic_CInstanceInfoExtended_CreateExtObjectL_NoReleaseFunc));
       
   640             User::Leave(KEComErrNoExtendedInterfaceReleaseFunction);
       
   641             }
       
   642             
       
   643         if (releaseObject == NULL)
       
   644             {
       
   645             // ... the releaseObject must be non null
       
   646             __ECOM_TRACE("ECOM: PANIC in CInstanceInfoExtended::CreateExtObjectL, release required but release object missing");
       
   647 	        __ASSERT_DEBUG(EFalse, User::Panic (KEComClientDLLPanicCategory, EEComPanic_CInstanceInfoExtended_CreateExtObjectL_NoReleaseObj));
       
   648            User::Leave(KEComErrNoExtendedInterfaceReleaseObject);
       
   649  		    }
       
   650             
       
   651 		//Create the extended object info type and add it to the extended object info array.
       
   652 		TExtendedObjectInfo extendedObjectInfo;
       
   653 		extendedObjectInfo.iExtendedInterfaceObject = releaseObject;
       
   654 		extendedObjectInfo.iExtendedInterfaceUID = aExtendedInterfaceUID;
       
   655 
       
   656 		TInt err = iExtendedObjectInfo.Append(extendedObjectInfo);
       
   657 
       
   658 		if (err != KErrNone)
       
   659 			{
       
   660 			if (release != NULL)
       
   661 				{
       
   662 				// Release the extended interface. Release must not leave.
       
   663 				release(extendedObjectInfo.iExtendedInterfaceObject,extendedObjectInfo.iExtendedInterfaceUID);
       
   664 				}
       
   665 			User::Leave(err);
       
   666 			}
       
   667 		}
       
   668 
       
   669 	return object;
       
   670 	}
       
   671 
       
   672 
       
   673 /**
       
   674 Destroys the extension interface object.
       
   675 @param			aExtendedInterfaceUID The extended interface UID
       
   676 @return			None
       
   677 */
       
   678 void CInstanceInfoExtended::DestroyExtObject(const TUid& aExtendedInterfaceUID)
       
   679 	{
       
   680 	// Get release interface
       
   681 	TProxyExtendedInterfaceReleasePtr release = iImplementationProxyRow->iFuncPtrInterfaceRelease;
       
   682 
       
   683 	if (release != NULL)
       
   684 		{
       
   685 		// Release extended interface. Find the extended object info.
       
   686 		for(TInt i = 0; i < iExtendedObjectInfo.Count(); i++)
       
   687 			{
       
   688 			if (iExtendedObjectInfo[i].iExtendedInterfaceUID == aExtendedInterfaceUID)
       
   689 				{
       
   690 				TAny* releaseObject = iExtendedObjectInfo[i].iExtendedInterfaceObject;
       
   691                 if (releaseObject == NULL)
       
   692                     {
       
   693                     // ... the releaseObject must be non null
       
   694                     __ECOM_TRACE("ECOM: PANIC in CInstanceInfoExtended::DestroyExtObject, release required but release object missing");
       
   695 	                __ASSERT_DEBUG(EFalse, User::Panic (KEComClientDLLPanicCategory, EEComPanic_CInstanceInfoExtended_DestroyExtObject_NoReleaseObj));	              
       
   696 		            }
       
   697 
       
   698 				// Release the extended interface. Release should not be leaving.
       
   699 				release(releaseObject, iExtendedObjectInfo[i].iExtendedInterfaceUID);
       
   700 				// Remove the extended object info element from the array.
       
   701 				iExtendedObjectInfo.Remove(i);
       
   702 				break;
       
   703 				}
       
   704 			}
       
   705 		}
       
   706 	}
       
   707 
       
   708 /**
       
   709 Destructor of CInstanceInfoExtended
       
   710 */
       
   711 CInstanceInfoExtended::~CInstanceInfoExtended()
       
   712 	{
       
   713 	// Get release interface
       
   714 	if (iImplementationProxyRow != NULL)
       
   715 		{
       
   716 		TProxyExtendedInterfaceReleasePtr release = iImplementationProxyRow->iFuncPtrInterfaceRelease;
       
   717 
       
   718 		if (release != NULL)
       
   719 			{
       
   720 			// Release all extended interfaces (if any still to be released)
       
   721 			for(TInt i = 0; i < iExtendedObjectInfo.Count(); i++)
       
   722 				{
       
   723 				// Release is supposed to be non-leavable.
       
   724 				release(iExtendedObjectInfo[i].iExtendedInterfaceObject,iExtendedObjectInfo[i].iExtendedInterfaceUID);
       
   725 				}
       
   726 			}
       
   727 		}
       
   728 
       
   729 	iExtendedObjectInfo.Close();
       
   730 	}
       
   731 
       
   732 //
       
   733 // CInstanceInfoSimple
       
   734 /**
       
   735 Default constructor of CInstanceInfoSimple
       
   736 @param			aUnloadPolicy The CUnloadPolicy of the dll
       
   737 @param			aImplementationProxyRow The interface implementation proxy row entry
       
   738 */
       
   739 CInstanceInfoSimple::CInstanceInfoSimple(CUnloadPolicy* aUnloadPolicy,const TImplementationProxy* aImplementationProxyRow):
       
   740 	CInstanceInfo(aUnloadPolicy),iImplementationProxyRow(aImplementationProxyRow)
       
   741 	{
       
   742 	// Do nothing here
       
   743 	}
       
   744 
       
   745 /**
       
   746 Create an instance of CInstanceInfoSimple
       
   747 @param			aUnloadPolicy The CUnloadPolicy of the dll
       
   748 @param			aImplementationProxyRow The interface implementation proxy row entry
       
   749 @return			A pointer to the newly created object.
       
   750 */
       
   751 CInstanceInfoSimple* CInstanceInfoSimple::NewL(CUnloadPolicy* aUnloadPolicy,const TImplementationProxy* aImplementationProxyRow)
       
   752 	{
       
   753 	return new(ELeave) CInstanceInfoSimple(aUnloadPolicy,aImplementationProxyRow);
       
   754 	}