--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lowlevellibsandfws/pluginfw/Framework/frame/LoadManager.cpp Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,754 @@
+// 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);
+ }