lowlevellibsandfws/pluginfw/Framework/frame/LoadManager.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 14 Apr 2010 17:44:02 +0300
branchRCL_3
changeset 17 ef2ebc87518f
parent 0 e4d67989cc36
permissions -rw-r--r--
Revision: 201012 Kit: 201015

// 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 CLoadManager class
// 
//

/**
 @internalComponent
 @file
*/

#include "EComDebug.h"
#include "UnloadPolicy.h"
#include "LoadManager.h"
#include "EComUidCodes.h"
#include <ecom/ecomerrorcodes.h>
#include "e32math.h"
#include "EComInternalErrorCodes.h"
#include <ecom/ecomextendedinterfaceerrorcodes.h>
/**
Standardized safe construction which leaves nothing on the cleanup stack.
@return			A pointer to the new class
@post			CLoadManager is fully constructed, and initialized.
 */
CLoadManager* CLoadManager::NewL()
	{
	return new(ELeave) CLoadManager();
	}

CLoadManager::~CLoadManager()
	{
	iInstanceInfoList.ResetAndDestroy();
	iAllUnloadPolicies.ResetAndDestroy();
	ClearGarbage();
	}

/**
Notifies the interface implementation DLL that one of its objects has been destroyed if it exists,
otherwise returns false to indicate no exist aImplementationUid.
@param          aInstanceKey A key specifying a previously created implementation.
@pre 			CLoadManager is fully constructed,
@post			CLoadManager's interface implementation DLL references
				are decreased by one. The instance info representing the implementation
				is destroyed.
*/
TBool CLoadManager::DestroyedThis(TUid aInstanceKey)
	{
	// Clear the garbage list because we know we have finished with them
	ClearGarbage();

	__ECOM_TRACE1("ECOM: Implementation Instance destroyed %x", aInstanceKey.iUid);

	// Sanity check that the pointer is divisible by four. A binary number is divisible
	// by four if and only if the two rightmost bits are both zero.
	// This is a compromised check for checking that the pointer is an address.
    if ((aInstanceKey.iUid == 0) || ((aInstanceKey.iUid & 0x00000003) != 0))
        {
	    __ASSERT_DEBUG(EFalse, User::Panic(KEComClientDLLPanicCategory, EEComPanic_InvalidImplementationInstanceKey));
	    User::Leave(KErrNotFound);
        }

	// The instance info pointer is stored in the instance key.
	CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);

	// Check that the pointer exists before using it
	TInt position = iInstanceInfoList.FindInAddressOrder(instanceInfo);
	if(position == KErrNotFound)
		{
		return EFalse;
		}
	
	CUnloadPolicy* policy = instanceInfo->UnloadPolicy();
	if (policy != NULL)
		{
		// If needed, will move the policy to the garbage list, and remove policy from the unload policy list.
		Cleanup(policy);
		}
	iInstanceInfoList.Remove(position);
	// Remove the instance info item, finished with it.
	delete instanceInfo;
	return ETrue;
	}

/**
Check whether the policy Arrays are empty or not.
@return            Returns True if the policy Arrays are empty, otherwise return False.
@pre             CLoadManager is fully constructed,
@post            CLoadManager remains the same.
*/
TBool CLoadManager::PolicyArraysEmpty() const 
    {
    if( (iAllUnloadPolicies.Count() == 0)&&(iInstanceInfoList.Count() == 0) )
        {
        return ETrue;
        }
    else
        {
        return EFalse;
        }
    }

/**
Returns an implementation object to satisfy the specified interface.
@param			aUniqueImplementationUid The implementation to find.
@param			aEntry Information on the dll containing the implementation
@param			aCreationParameters A pointer to the creation parameter
				structure passed to the creation method when called.
@param			aCreationParamsFlag A boolean flag to indicate the existence or non-existence
				of aCreationParameters. Will be ETrue even for if the value of
				aCreationParameters is NULL.
@param          aInstanceKey A key specifying a previously created implementation.
@return			TAny* a pointer to the fully constructed instantiation. The pointer is
				guaranteed to be valid only until DestroyedThis is called.
@pre 			CLoadManager is fully constructed,
@post			Fully constructed implementation is returned to the
				caller, and aUniqueUid contains the implementation Dll's
				unique UID.
*/
TAny* CLoadManager::ImplementationObjectL(const TUid& aUniqueImplementationUid,
										 const TEntry& aEntry,
										 TAny* aCreationParameters,
										 TBool aCreationParamsFlag,
										 TUid& aInstanceKey)
	{
	//if the implementation Uid here is Null or the entry returned by the ecomserver
	//contains nothing, we should leave with KErrNotFound
	if(aUniqueImplementationUid == KNullUid || (aEntry.iName).Length()==0)
		{
		User::Leave(KErrNotFound);
		}

	TAny* object = NULL;               // Instantiation object
	CUnloadPolicy* policy = NULL;      // Policy of implementation
	TLibraryFunction libFunctionProxy; // Library function proxy pointer

	GetUnloadPolicy(aUniqueImplementationUid,aEntry,policy);
	if (policy == NULL)
		{
		// No policy found, so create a new CUnloadPolicy and load DLL.
		policy = CUnloadPolicy::NewLC(aEntry);
		libFunctionProxy = policy->LoadDllAndReturnProxyL();
		if (libFunctionProxy==NULL)
			{
			User::Leave(KErrNotFound);
			}
		iAllUnloadPolicies.AppendL(policy);
		CleanupStack::Pop(policy);	// owned by iAllUnloadPolicies
		}
	else
		{
		// Found a policy. Load Dll if not already loaded.
		libFunctionProxy = policy->LoadDllAndReturnProxyL();
		if (libFunctionProxy==NULL)
			{
			User::Leave(KErrNotFound);
			}
		}
	// Initial count of instances. This is used for cleanup purposes, to see if an instance
	// was added to the instance info list during the object creation. If a failure occurs
	// than the instance info that was added to the list will be removed.
	TInt initialCount = iInstanceInfoList.Count();
	TInt err = KErrNone;

	if (aEntry[1] == KUidInterfaceImplementationCollection)
		{
		// PLUGIN1 dll. Create the implementation object.
		TRAP(err,object = ImplementationObject1L(aUniqueImplementationUid,aCreationParameters,
			aCreationParamsFlag,aInstanceKey,policy,libFunctionProxy));
		}
	else if (aEntry[1] == KUidInterfaceImplementationCollection3)
		{
		// PLUGIN3 dll. Create the implementation object.
		TRAP(err,object = ImplementationObject3L(aUniqueImplementationUid,aCreationParameters,
			aCreationParamsFlag, aInstanceKey,policy, libFunctionProxy));
		}
	else
		{
		err = KErrNotSupported;
		}
	
	if (err != KErrNone)
		{
		if (iInstanceInfoList.Count() > initialCount)
			{
			// If an instance was added to the instance list, remove it here.
			// The instance info pointer is stored in the instance key. We know its
			// valid because it was set by ecom in call to ImplementationObject1L or
			// ImplementationObject3L
			CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);
			TInt pos = iInstanceInfoList.FindInAddressOrder(instanceInfo);
			if(pos != KErrNotFound)
				{
				iInstanceInfoList.Remove(pos);
				}
			}

		ClearGarbage();
		// If needed, will move the policy to the garbage list, and remove policy from the unload policy list.
		Cleanup(policy);
		User::Leave(err);
		}
		
	__ECOM_TRACE2("ECOM: Implementation created (%03d) %x", ++iDebugInstantiationCounter, aUniqueImplementationUid.iUid);
			
	return object;
	}

/**
Returns an implementation object to satisfy the specified interface.
@param			aUniqueImplementationUid The implementation to find.
@param			aCreationParameters A pointer to the creation parameter
				structure passed to the creation method when called.
@param			aCreationParamsFlag A boolean flag to indicate the existence or non-existence
				of aCreationParameters. Will be ETrue even for if the value of
				aCreationParameters is NULL.
@param          aInstanceKey A key specifying a previously created implementation.
@param          aPolicy policy of implementation
@param          aLibFunctionProxy Library function proxy pointer.
@return			TAny* a pointer to the fully constructed instantiation. The pointer is
				guaranteed to be valid only until DestroyedThis is called.
*/
TAny* CLoadManager::ImplementationObject1L(const TUid& aUniqueImplementationUid,
										 TAny* aCreationParameters,
										 TBool aCreationParamsFlag,
										 TUid& aInstanceKey,
										 CUnloadPolicy* aPolicy,
										 TLibraryFunction& aLibFunctionProxy)
	{
	TAny* object = NULL; // Instantiation object
	TInstantiationL proxy = reinterpret_cast<TInstantiationL>(aLibFunctionProxy);

	TImplementationProxy* implementationProxyRow = NULL;
	TAny* newLPointer = GetNewLPointerAndProxyTableRowL<TImplementationProxy,TInstantiationL>(aUniqueImplementationUid,implementationProxyRow,proxy);
	// Now create an instance info object to store the information about this instance derived from
	// the parameters just fetched. This must be created here since no leaves can occur after the object
	// instantiation below.
	CInstanceInfoSimple* instanceInfoSimple = CInstanceInfoSimple::NewL(aPolicy,implementationProxyRow);
	CleanupStack::PushL(instanceInfoSimple);

	// The pointer to instanceInfo will be used to identify this instance, and will
	// be returned to the caller for future identification of this instance.
	aInstanceKey.iUid = reinterpret_cast<TInt32>(instanceInfoSimple);

	// Add item to instance info list. This list will contain all of the instance objects.
	iInstanceInfoList.InsertInAddressOrderL(instanceInfoSimple);

	// Get the implementation object using the instantiation pointer fetched earlier. Note
	// that the object creation must be the last leaving operation to be performed. No leaves can occur
	// after this operation, as the instantiation object cannnot be deleted on the cleanup stack if
	// a leave occurs (cannot delete a TAny* pointer, the type is not known within ECOM).
	object = ImplementationObjectL(aCreationParameters, 
	 aCreationParamsFlag,newLPointer);

	CleanupStack::Pop(instanceInfoSimple);

	return object;
	}

/**
Returns an implementation object to satisfy the specified interface.
@param			aUniqueImplementationUid The implementation to find.
@param			aCreationParameters A pointer to the creation parameter
				structure passed to the creation method when called.
@param			aCreationParamsFlag A boolean flag to indicate the existence or non-existence
				of aCreationParameters. Will be ETrue even for if the value of
				aCreationParameters is NULL.
@param          aInstanceKey A key specifying a previously created implementation.
@param          aPolicy policy of implementation
@param          aLibFunctionProxy Library function proxy pointer.
@return			TAny* a pointer to the fully constructed instantiation. The pointer is
				guaranteed to be valid only until DestroyedThis is called.
*/
TAny* CLoadManager::ImplementationObject3L(const TUid& aUniqueImplementationUid,
										 TAny* aCreationParameters,
										 TBool aCreationParamsFlag,
										 TUid& aInstanceKey,
										 CUnloadPolicy* aPolicy,
										 TLibraryFunction& aLibFunctionProxy)
	{
	TAny* object = NULL;  // Instantiation object
	TInstantiation3L proxy = reinterpret_cast<TInstantiation3L>(aLibFunctionProxy);

	TImplementationProxy3* implementationProxyRow = NULL;
	TAny* newLPointer = GetNewLPointerAndProxyTableRowL<TImplementationProxy3,TInstantiation3L>(aUniqueImplementationUid,implementationProxyRow,proxy);

	// Now create an instance info object to store the information about this instance derived from
	// the parameters just fetched. This must be created here since no leaves can occur after the object
	// instantiation below.
	CInstanceInfoExtended* instanceInfoExtended = CInstanceInfoExtended::NewL(aPolicy,implementationProxyRow);
	CleanupStack::PushL(instanceInfoExtended);

	// The pointer to instanceInfo will be used to identify this instance, and will
	// be returned to the caller for future identification of this instance.
	aInstanceKey.iUid = reinterpret_cast<TInt32>(instanceInfoExtended);

	// Add item to instance info list. This list will contain all of the instance objects.
	iInstanceInfoList.InsertInAddressOrderL(instanceInfoExtended);

	// Get the implementation object using the instantiation pointer fetched earlier. Note
	// that the object creation must be the last leaving operation to be performed. No leaves can occur
	// after this operation, as the instantiation object cannnot be deleted on the cleanup stack if
	// a leave occurs (cannot delete a TAny* pointer, the type is not known within ECOM).
	object = ImplementationObjectL(aCreationParameters, 
	 aCreationParamsFlag,newLPointer);

	// The extended instance info requires an object set. This is done here
	// as the object is not known until now, but the instance info object was required to
	// be created earlier to avoid a leave after the object creation.
	instanceInfoExtended->SetObject(object);
	CleanupStack::Pop(instanceInfoExtended);

	return object;
	}

/**
Gets the main implementation object using the instantiation pointer provided
@param			aCreationParameters A pointer to the creation parameter
				structure passed to the creation method when called.
@param			aCreationParamsFlag A boolean flag to indicate the existence or non-existence
				of aCreationParameters. Will be ETrue even for if the value of
				aCreationParameters is NULL.
@param			aNewLpointer Instantation pointer.
				aCreationParameters is NULL.
@return			TAny* a pointer to the fully constructed instantiation.
*/
TAny* CLoadManager::ImplementationObjectL(TAny* aCreationParameters,
										 TBool aCreationParamsFlag,
										 const TAny* aNewLpointer)
	{
	TAny* object=NULL;

	// So cast to the correct type : This gives an ANSI C++ warning
	// When using a REINTERPRET_CAST so simply cast instead
	// Two different object creation one with creation parameters
	if (aCreationParamsFlag)
		{
		typedef TAny* (*TNewL)(TAny*);
		TNewL creationL = (TNewL)(aNewLpointer);
		object=creationL(aCreationParameters);
		}
	else
		{
		typedef TAny* (*TNewL)();
		TNewL creationL = (TNewL)(aNewLpointer);
		object=creationL();
		}

	return object;
	}

/**
Get the unload policy.
@param			aUniqueImplementationUid The implementation to find.
@param			aEntry Information on the dll containing the implementation
@param			aPolicy Return parameter containing the policy
@return			None
*/
void CLoadManager::GetUnloadPolicy(TUid aUniqueImplementationUid,
							  const TEntry& aEntry,
							  CUnloadPolicy*& aPolicy)
	{
	const TInt numImps = iInstanceInfoList.Count();
	TBool foundImp = EFalse;
	TInt matchingDllIndex=0;
	TBool matchingDllFound=EFalse;
	CUnloadPolicy* policy = NULL;

	for (TInt index = 0; (index<numImps) && !foundImp; ++index)
		{
		//Check if there is existing mapping between the supplied implUid and a policy
		if(iInstanceInfoList[index]->ImplementationUid() == aUniqueImplementationUid)
			{
			policy = iInstanceInfoList[index]->UnloadPolicy();

			foundImp = ETrue;
			}
		else
			{
			//if cannot find a mapping entry but current index has the same DLL as the one requested from
			//the client, store the index to this unloadPolicy for use later on if we have finished
			//searching the entire mapping list
			if (!matchingDllFound && (iInstanceInfoList[index]->UnloadPolicy()->DllEntryInformation().GetName()).CompareF(aEntry.iName)==0)
				{
				matchingDllIndex=index;
				matchingDllFound=ETrue;
				}
			}
		}

	//If we cannot find any mapping in the policy index array(iUnloadPolicyMapping)
	if(!foundImp)
		{
		//if not found but there is a matching DLL,we can simply create a new policy index mapping without
		//having to load the library again.
		if (matchingDllFound)
			{
			policy = iInstanceInfoList[matchingDllIndex]->UnloadPolicy();
			}
		}

	aPolicy = policy;
	}

/**
Clears the policy inside the iGarbagePolicies attribute.
@pre			CLoadManager is fully constructed
@post			CLoadManager iGarbagePolicies is zero'd
*/
void CLoadManager::ClearGarbage()
	{
	if (iGarbagePolicy != NULL)
		{
		delete iGarbagePolicy;
		iGarbagePolicy=0;
		}
	}

CLoadManager::CLoadManager() :
	CBase()
	{
	// Do nothing here
	}

/**
Returns the implementation ID for a given instance Key.
@leave			KErrNotFound
@param			aInstanceKey A key specifying a previously created implementation instance.
@return			TUid The uid of the corresponding implementation.
@pre 			CLoadManager is fully constructed,
@post			CLoadManager remains the same.
*/
TUid CLoadManager::GetImplementationUidL(TUid aInstanceKey)
	{
	// Sanity check that the pointer is divisible by four. A binary number is divisible
	// by four if and only if the two rightmost bits are both zero.
	// This is a compromised check for checking that the pointer is an address.
    if ((aInstanceKey.iUid == 0) || ((aInstanceKey.iUid & 0x00000003) != 0))
        {
	    __ASSERT_DEBUG(EFalse, User::Panic(KEComClientDLLPanicCategory, EEComPanic_InvalidImplementationInstanceKey));
	    User::Leave(KErrNotFound);
        }

	// The instance info pointer is stored in the instance key.
	CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);

	// Check that the pointer exists before using it - leaves with KErrNotFound
	iInstanceInfoList.FindInAddressOrderL(instanceInfo);
	return instanceInfo->ImplementationUid();
	}

/**
Fetches the requested extended interface from a specified implementation instance.
@leave			KErrNotFound
@param 			aInstanceKey A key specifying a previously created implementation.
@param 			aExtendedInterfaceUid Identifies an interface to fetch from the plug-in instance.
@return			TAny* A pointer to the extended interface, will be NULL if it does not exist.
*/
TAny* CLoadManager::GetExtendedInterfaceL(const TUid& aInstanceKey, const TUid& aExtendedInterfaceUid)
	{
	// Sanity check that the pointer is divisible by four. A binary number is divisible
	// by four if and only if the two rightmost bits are both zero.
	// This is a compromised check for checking that the pointer is an address.
    if ((aInstanceKey.iUid == 0) || ((aInstanceKey.iUid & 0x00000003) != 0))
        {
	    __ASSERT_DEBUG(EFalse, User::Panic(KEComClientDLLPanicCategory, EEComPanic_InvalidImplementationInstanceKey));
	    User::Leave(KErrNotFound);
        }

	// The instance info pointer is stored in the instance key.
	CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);

	// Check that the pointer exists before using it - leaves with KErrNotFound
	iInstanceInfoList.FindInAddressOrderL(instanceInfo);
	
	// Create the extension object. The instance info object will be populated with
	// the extension info during creation.
	TAny* object = instanceInfo->CreateExtObjectL(aExtendedInterfaceUid);
	return object;
	}

/**
Manually releases the requested interface. Does nothing if it does not exist.
This interface is optional, normally the interfaces are cleaned up automatically.
@leave			KErrNotFound
@param			aInstanceKey A key specifying a previously created implementation.
@param			aExtendedInterfaceUid Identifies the interface to release
@return None.
*/
void CLoadManager::ManuallyReleaseExtendedInterfaceL(const TUid& aInstanceKey, const TUid& aExtendedInterfaceUid)
	{
	// Sanity check that the pointer is divisible by four. A binary number is divisible
	// by four if and only if the two rightmost bits are both zero.
	// This is a compromised check for checking that the pointer is an address.
    if ((aInstanceKey.iUid == 0) || ((aInstanceKey.iUid & 0x00000003) != 0))
        {
	    __ASSERT_DEBUG(EFalse, User::Panic(KEComClientDLLPanicCategory, EEComPanic_InvalidImplementationInstanceKey));
	    User::Leave(KErrNotFound);
        }
        
	// The instance info pointer is stored in the instance key.
	CInstanceInfo* instanceInfo = reinterpret_cast<CInstanceInfo*>(aInstanceKey.iUid);

	// Check that the pointer exists before using it - leaves with KErrNotFound
	iInstanceInfoList.FindInAddressOrderL(instanceInfo);
	
	instanceInfo->DestroyExtObject(aExtendedInterfaceUid);
	}

/**
Utility method to move the policy to the garbage list, remove
policy from the unload policy list.
@param aPolicy Unload policy to clean up
@return None.
*/
void CLoadManager::Cleanup(CUnloadPolicy* aPolicy)
	{
	if (aPolicy->DecreaseReference() == EDeleteMe)
		{
		// Move the policy to the garbage list
		iGarbagePolicy=aPolicy;

		TInt index = iAllUnloadPolicies.Find(aPolicy);
		if (index != KErrNotFound)
			{
			iAllUnloadPolicies.Remove(index);
			}
		}
	}

//
// CInstanceInfo
/**
Default constructor of CInstanceInfo
@param			aUnloadPolicy The CUnloadPolicy of the dll
*/
CInstanceInfo::CInstanceInfo(CUnloadPolicy* aUnloadPolicy):
	iUnloadPolicy(aUnloadPolicy)
	{
	// Do nothing here
	}

/** 
Destructor of CInstanceInfo
*/
CInstanceInfo::~CInstanceInfo()
	{
	// Do nothing here
	}


//
// CInstanceInfoExtended
/**
Default constructor of CInstanceInfoExtended
@param			aUnloadPolicy The CUnloadPolicy of the dll
@param			aImplementationProxyRow The interface implementation proxy row entry
*/
CInstanceInfoExtended::CInstanceInfoExtended(CUnloadPolicy* aUnloadPolicy,const TImplementationProxy3* aImplementationProxyRow):
	CInstanceInfo(aUnloadPolicy),iImplementationProxyRow(aImplementationProxyRow)
	{
	// Do nothing here
	}

/**
create an instance of CInstanceInfoExtended
@param			aUnloadPolicy The CUnloadPolicy of the dll
@param			aImplementationProxyRow The interface implementation proxy row entry
@return			A pointer to the newly created object.
*/
CInstanceInfoExtended* CInstanceInfoExtended::NewL(CUnloadPolicy* aUnloadPolicy,const TImplementationProxy3* aImplementationProxyRow)
	{
	return new(ELeave) CInstanceInfoExtended(aUnloadPolicy,aImplementationProxyRow);
	}

/**
Sets the implementation object.
@param			aImplementationObject The object instance of this instances' implementation
@return			None
*/
void CInstanceInfoExtended::SetObject(TAny* aImplementationObject)
	{
	iImplementationObject = aImplementationObject;
	}

/**
Creates the extension interface object. This will use the get extended interface
function pointer from the proxy table to fetch the extended interface from the
plug-in implementation.
@param			aExtendedInterfaceUID The extended interface UID
@return			TAny* A pointer to an instance of an extended interface created
*/
TAny* CInstanceInfoExtended::CreateExtObjectL(const TUid& aExtendedInterfaceUID)
	{
	// Fetch the function pointer to create the extended interface
	TProxyExtendedInterfaceGetPtrL createFunctionPtrL = iImplementationProxyRow->iFuncPtrInterfaceGetL;
	if (createFunctionPtrL == NULL)
		{
		// No extension interface object can be created. Return NULL indicating that
		// no extended interface object is available.
		return NULL;
		}

	// Valid function pointer exists in proxy table.
	TAny* object = NULL;         // Extended interface object (this points to the interface
							     // within the object)
	TAny* releaseObject = NULL;  // Eextended interface object (this points to the extended
								 // object itself). Used to delete the extended interface
								 // object later.
	TUint32 flags = 0;           // Flags to allow the plug-in and ECOM to communicate
	// Create the extension object.
	object = createFunctionPtrL(iImplementationObject,aExtendedInterfaceUID,flags,releaseObject);

	if (flags & KReleaseRequiredMask)
		{
		// If release of the extended interface is required then save the release object pointer.
		// The interface object (returned by the function pointer call) and the release object
		// are not necessarily the same pointer. This is because the  interface pointer is not
		// guaranteed to be the same as the pointer to the extended interface object. That
		// is why the release object is required to be fetched from the plug-in.

        // First perform some checks to ensure that the plugin is consistent 
        TProxyExtendedInterfaceReleasePtr release = iImplementationProxyRow->iFuncPtrInterfaceRelease;
                
        if (release == NULL)
            {
            // ...the release object pointer must not be non null
            __ECOM_TRACE("ECOM: PANIC in CInstanceInfoExtended::CreateExtObjectL, release required but release function missing");
	        __ASSERT_DEBUG(EFalse, User::Panic (KEComClientDLLPanicCategory, EEComPanic_CInstanceInfoExtended_CreateExtObjectL_NoReleaseFunc));
            User::Leave(KEComErrNoExtendedInterfaceReleaseFunction);
            }
            
        if (releaseObject == NULL)
            {
            // ... the releaseObject must be non null
            __ECOM_TRACE("ECOM: PANIC in CInstanceInfoExtended::CreateExtObjectL, release required but release object missing");
	        __ASSERT_DEBUG(EFalse, User::Panic (KEComClientDLLPanicCategory, EEComPanic_CInstanceInfoExtended_CreateExtObjectL_NoReleaseObj));
           User::Leave(KEComErrNoExtendedInterfaceReleaseObject);
 		    }
            
		//Create the extended object info type and add it to the extended object info array.
		TExtendedObjectInfo extendedObjectInfo;
		extendedObjectInfo.iExtendedInterfaceObject = releaseObject;
		extendedObjectInfo.iExtendedInterfaceUID = aExtendedInterfaceUID;

		TInt err = iExtendedObjectInfo.Append(extendedObjectInfo);

		if (err != KErrNone)
			{
			if (release != NULL)
				{
				// Release the extended interface. Release must not leave.
				release(extendedObjectInfo.iExtendedInterfaceObject,extendedObjectInfo.iExtendedInterfaceUID);
				}
			User::Leave(err);
			}
		}

	return object;
	}


/**
Destroys the extension interface object.
@param			aExtendedInterfaceUID The extended interface UID
@return			None
*/
void CInstanceInfoExtended::DestroyExtObject(const TUid& aExtendedInterfaceUID)
	{
	// Get release interface
	TProxyExtendedInterfaceReleasePtr release = iImplementationProxyRow->iFuncPtrInterfaceRelease;

	if (release != NULL)
		{
		// Release extended interface. Find the extended object info.
		for(TInt i = 0; i < iExtendedObjectInfo.Count(); i++)
			{
			if (iExtendedObjectInfo[i].iExtendedInterfaceUID == aExtendedInterfaceUID)
				{
				TAny* releaseObject = iExtendedObjectInfo[i].iExtendedInterfaceObject;
                if (releaseObject == NULL)
                    {
                    // ... the releaseObject must be non null
                    __ECOM_TRACE("ECOM: PANIC in CInstanceInfoExtended::DestroyExtObject, release required but release object missing");
	                __ASSERT_DEBUG(EFalse, User::Panic (KEComClientDLLPanicCategory, EEComPanic_CInstanceInfoExtended_DestroyExtObject_NoReleaseObj));	              
		            }

				// Release the extended interface. Release should not be leaving.
				release(releaseObject, iExtendedObjectInfo[i].iExtendedInterfaceUID);
				// Remove the extended object info element from the array.
				iExtendedObjectInfo.Remove(i);
				break;
				}
			}
		}
	}

/**
Destructor of CInstanceInfoExtended
*/
CInstanceInfoExtended::~CInstanceInfoExtended()
	{
	// Get release interface
	if (iImplementationProxyRow != NULL)
		{
		TProxyExtendedInterfaceReleasePtr release = iImplementationProxyRow->iFuncPtrInterfaceRelease;

		if (release != NULL)
			{
			// Release all extended interfaces (if any still to be released)
			for(TInt i = 0; i < iExtendedObjectInfo.Count(); i++)
				{
				// Release is supposed to be non-leavable.
				release(iExtendedObjectInfo[i].iExtendedInterfaceObject,iExtendedObjectInfo[i].iExtendedInterfaceUID);
				}
			}
		}

	iExtendedObjectInfo.Close();
	}

//
// CInstanceInfoSimple
/**
Default constructor of CInstanceInfoSimple
@param			aUnloadPolicy The CUnloadPolicy of the dll
@param			aImplementationProxyRow The interface implementation proxy row entry
*/
CInstanceInfoSimple::CInstanceInfoSimple(CUnloadPolicy* aUnloadPolicy,const TImplementationProxy* aImplementationProxyRow):
	CInstanceInfo(aUnloadPolicy),iImplementationProxyRow(aImplementationProxyRow)
	{
	// Do nothing here
	}

/**
Create an instance of CInstanceInfoSimple
@param			aUnloadPolicy The CUnloadPolicy of the dll
@param			aImplementationProxyRow The interface implementation proxy row entry
@return			A pointer to the newly created object.
*/
CInstanceInfoSimple* CInstanceInfoSimple::NewL(CUnloadPolicy* aUnloadPolicy,const TImplementationProxy* aImplementationProxyRow)
	{
	return new(ELeave) CInstanceInfoSimple(aUnloadPolicy,aImplementationProxyRow);
	}