📄 plghand2.cpp
字号:
/*
LoadDLL()
This is called during a Refresh() (which is deprecated)
or if we determine that the DLL is dirty and needs to be updated
*/
Plugin2Handler::Errors Plugin2Handler::LoadDLL( char* pszDllName,
PluginMountPoint* pMountPoint )
{
Errors result = NO_ERRORS;
UINT32 i = 0;
struct stat stat_stuct;
IHXBuffer* pPathBuffer = pMountPoint->Path();
// Make sure there is no path in the pszDllName
HX_ASSERT( !strrchr(pszDllName, Plugin2Handler::zm_cDirectorySeperator) );
Plugin2Handler::PluginDLL* pPluginDll = NULL;
if( !( pPluginDll = new Plugin2Handler::PluginDLL( pszDllName, pMountPoint, this ) ) )
{
return MEMORY_ERROR;
}
pPluginDll->AddRef();
CHXString sFileWithPath = pPathBuffer->GetBuffer();
UINT32 len = sFileWithPath.GetLength();
if(len &&
sFileWithPath.GetAt(len - 1) != Plugin2Handler::zm_cDirectorySeperator)
sFileWithPath += Plugin2Handler::zm_cDirectorySeperator;
sFileWithPath += pszDllName;
if (NO_ERRORS==Stat(sFileWithPath, &stat_stuct))
{
pPluginDll->SetFileSize((INT32)stat_stuct.st_size);
}
result = pPluginDll->Load(m_pContext);
if (NO_ERRORS != result )
{
goto cleanup;
}
// Set the hash
if (pPathBuffer)
{
IHXBuffer* pNewChecksum = ChecksumFile( pszDllName, pPathBuffer );
if (pNewChecksum)
{
HX_RELEASE(pPathBuffer);
pPluginDll->SetHash((char*)pNewChecksum->GetBuffer());
HX_RELEASE(pNewChecksum);
}
}
// Remove this DLL from the list of supported DLL (based on GUIDs)
RemoveDLLFromGUIDSupportLists(pszDllName);
// ReconnectDLL() replaces one PluginDLL object with another PluginDLL; however,
// both of these PluginDLL objects refer to the same DLL. This ensures that
// only one PluginDLL object per DLL is in the m_PluginDLLList.
ReconnectDLL(pszDllName, pPluginDll);
for(i=0;i<pPluginDll->GetNumPlugins();i++)
{
Plugin* pPlugin = NULL;
// create a new plugin object
if (!(pPlugin = new Plugin(m_pContext)))
{
return MEMORY_ERROR;
}
// Setup plugin information
pPlugin->AddRef();
pPlugin->SetDLL(pPluginDll);
pPlugin->SetIndex((UINT16)i);
pPlugin->SetInfoNeedsRefresh(TRUE);
IUnknown* pUnk = NULL;
if( NO_ERRORS != pPlugin->GetPlugin( pUnk ) )
{
// This plugin doesn't work. Delete it.
HX_RELEASE( pPlugin );
}
else
{
IHXPluginNamespace* pPluginNamespace = NULL;
if (SUCCEEDED(pUnk->QueryInterface(IID_IHXPluginNamespace, (void**) &pPluginNamespace)))
{
/*
* Memory for the IHXBuffer is allocated in the plugin
*/
IHXBuffer* pBuffer = NULL;
if (SUCCEEDED(pPluginNamespace->GetPluginNamespace(pBuffer)))
{
pPluginDll->SetNamespace(pBuffer);
HX_RELEASE(pBuffer);
}
HX_RELEASE(pPluginNamespace);
}
IHXComponentPlugin* pIIterator = NULL;
if( SUCCEEDED( pUnk->QueryInterface( IID_IHXComponentPlugin, (void**) &pIIterator ) ) )
{
// We don't need this.
HX_RELEASE( pPlugin );
LoadPluginsFromComponentDLL( pPluginDll, pIIterator );
HX_RELEASE( pIIterator );
}
else
{
IHXPlugin* pIHXPlugin;
if( SUCCEEDED( pUnk->QueryInterface(IID_IHXPlugin, (void**)&pIHXPlugin ) ) )
{
pPlugin->GetValuesFromDLL(pIHXPlugin);
m_PluginList.AddTail(pPlugin);
// Print out some log info about the plugin we just loaded
{
const char *pDesc, *pCopy, *pURL;
ULONG32 ulVersionNumber = 0;
BOOL junk;
pIHXPlugin->GetPluginInfo(junk, pDesc, pCopy, pURL, ulVersionNumber);
ReportError( HXLOG_INFO, pszDllName, pDesc );
}
// At this point since we have the HXPlugin we should query it to see if
// it supports any of the GUIDs which have been enumerated so far.
UINT32 nNumGUIDs = GetNumSupportedGUIDs();
for(; nNumGUIDs; nNumGUIDs--)
{
CHXString pszGUID;
GUID theGUID;
GetGUIDForIndex(nNumGUIDs-1, pszGUID);
CHXuuid::HXUuidFromString(pszGUID, (uuid_tt*)&theGUID);
IUnknown* pQueryUnk;
if (HXR_OK == pIHXPlugin->QueryInterface(theGUID, (void**)&pQueryUnk))
{
AddSupportForGUID(pszGUID, pPluginDll, i);
HX_RELEASE(pQueryUnk);
}
}
// if this is a required plugin, validate it // XXXAH this could be a problem
// if (IsPluginRequired(pDesc, pPlugin))
// {
// bValidated = ValidateRequiredPlugin(pIHXPlugin, pPlugin);
// }
pIHXPlugin->Release();
}
}
}
HX_RELEASE( pUnk );
}
cleanup:
HX_RELEASE(pPathBuffer);
if (result != NO_ERRORS)
{
HX_RELEASE( pPluginDll );
}
return result;
}
void Plugin2Handler::LoadPluginsFromComponentDLL( Plugin2Handler::PluginDLL* pPluginDll,
IHXComponentPlugin* pIIterator )
{
IHXPlugin* pIHXPlugin = NULL;
if( SUCCEEDED( pIIterator->QueryInterface(IID_IHXPlugin, (void**)&pIHXPlugin ) ) )
{
// XXXHP - this is now done in the PluginDLL::Load() method
// pIHXPlugin->InitPlugin( m_pContext );
for( UINT32 index = 0; index < pIIterator->GetNumComponents(); index++ )
{
IHXValues* pIValues = NULL;
if( SUCCEEDED( pIIterator->GetComponentInfoAtIndex( index, pIValues ) ) )
{
IHXBuffer* pBuffer = NULL;
if (SUCCEEDED(pIValues->GetPropertyCString(PLUGIN_COMPONENT_NAME, pBuffer)))
{
IHXBuffer* pNamespace = pPluginDll->GetNamespace();
if (pNamespace)
{
CHXString TempNamespace = pNamespace->GetBuffer();
TempNamespace += NAMESPACE_SEPARATOR;
TempNamespace += pBuffer->GetBuffer();
IHXBuffer* pTempBuffer = new CHXBuffer();
pTempBuffer->AddRef();
pTempBuffer->Set((BYTE*)(const char*)TempNamespace, TempNamespace.GetLength()+1);
pIValues->SetPropertyCString(PLUGIN_COMPONENT_NAME, pTempBuffer);
HX_RELEASE(pTempBuffer);
HX_RELEASE(pNamespace);
}
HX_RELEASE(pBuffer);
}
// create a new plugin object
Plugin* pPlugin = new Plugin( m_pContext );
HX_ASSERT( pPlugin );
// Setup plugin object
pPlugin->AddRef();
pPlugin->SetDLL( pPluginDll );
// XXXP - this isn't necessary, the Plugin is initialized with an index of 0 if no index is found.
// pPlugin->SetIndex( (UINT16) 0 );
pPlugin->SetInfoNeedsRefresh( TRUE );
// XXXND FIX I don't like this specialized interface.
// This gets the basic info from pIHXPlugin, and the rest from pValues
pPlugin->InitializeComponentPlugin( pIHXPlugin, pIValues );
// Put in plugin list
m_PluginList.AddTail(pPlugin);
// Stick CLSID in map
AddPluginToIndices( pPlugin );
HX_RELEASE( pIValues );
}
}
HX_RELEASE (pIHXPlugin);
}
}
STDMETHODIMP Plugin2Handler::ReloadPlugins()
{
// now we have to tell all other players that they should also
// reload their plugins.
IHXShutDownEverything* pShutDown = NULL ;
if (HXR_OK == m_pContext->QueryInterface(IID_IHXShutDownEverything, (void**) &pShutDown))
{
pShutDown->AskAllOtherPlayersToReload();
HX_RELEASE(pShutDown);
}
// This will re-initialize all the MountPoints
return ReloadPluginsNoPropagate();
}
///////////////////////////////////////////////////////////////////////////////
// These functions will find all plugins which are different
// then those loaded into the registry.
// It will then load them into memory, get their data, and unload them.
// It will return HXR_FAIL if some DLL has different values within the
// registry, and is presently in memory (how could this happen??)
// If anyone was keeping an index to a loaded DLL and assuming that it
// would remain constant ... that won't work!!
HX_RESULT Plugin2Handler::ReloadPluginsNoPropagate()
{
HX_LOG_BLOCK( "Plugin2Handler::ReloadPluginsNoPropagate" );
HX_RESULT result = HXR_OK;
// Reload them all.
for(CHXMapStringToOb::Iterator mp = m_MountPoints.Begin(); mp!=m_MountPoints.End(); ++mp)
{
PluginMountPoint* pMountPoint = (PluginMountPoint*) *mp;
if( FAILED( ReloadPluginsNoPropagate( pMountPoint ) ) )
{
result = HXR_FAIL;
}
}
return result;
}
HX_RESULT Plugin2Handler::ReloadPluginsNoPropagate( PluginMountPoint* pMountPoint )
{
HX_LOG_BLOCK( "Plugin2Handler::ReloadPluginsNoPropagate(PluginMP*)" );
#ifndef _STATICALLY_LINKED
CFindFile* pFileFinder = NULL;
#else
CStaticFindFile* pFileFinder = NULL;
#endif
IHXBuffer* pPathBuffer = NULL;
char* pszPluginDir = NULL;
ULONG32 nPluginDirLen = 0;
char* pszDllName = 0;
IHXBuffer* pNewChecksum = 0;
BOOL bRegIsDirty = FALSE;
BOOL bContinue;
// if we have no context do not proceed.
if (!m_pContext)
{
return INVALID_CONTEXT;
}
// If this is the 1st time, load everything into the registry.
#ifndef _STATICALLY_LINKED
pPathBuffer = pMountPoint->Path();
if (!pPathBuffer)
{
return HXR_FAIL;
}
pPathBuffer->Get((UCHAR*&)pszPluginDir, nPluginDirLen);
if (!nPluginDirLen)
{
return HXR_FAIL;
}
#else
pszPluginDir="";
#endif
pFileFinder =
#ifndef _STATICALLY_LINKED
CFindFile::CreateFindFile
#else
CStaticFindFile::CreateFindFile
#endif
(pszPluginDir, 0, Plugin2Handler::zm_pszFileExtension);
if (NULL == pFileFinder)
{
pPathBuffer->Release();
HX_DELETE(pFileFinder);
return HXR_FAIL;
}
pszDllName = pFileFinder->FindFirst();
BOOL bDLLIsDirty = FALSE;
while (pszDllName)
{
// See if this file exists in our list of pluginDLLs
BOOL bFound = FALSE;
CHXSimpleList::Iterator i;
Plugin2Handler::PluginDLL* pDLL = NULL;
bFound = m_FileNameMap.Lookup(pszDllName, (void*&)pDLL);
// If it was not found it may a misc DLL -- ie not an
// RMA DLL. Thus, we should ignore it.
bContinue = FALSE;
if (!bFound)
{
for(i=m_MiscDLLList.Begin();i!=m_MiscDLLList.End(); ++i)
{
Plugin2Handler::OtherDLL* pOther = (Plugin2Handler::OtherDLL*) *i;
if (!stricmp(pOther->m_filename, pszDllName))
{
// ok we have a match does the checksum match?
if (pNewChecksum = ChecksumFile(pszDllName, pPathBuffer))
{
if (!strcmp((char*)pNewChecksum->GetBuffer(), pOther->m_fileChecksum))
bContinue = TRUE;
HX_RELEASE(pNewChecksum);
}
}
}
}
if (bContinue)
{
pszDllName = pFileFinder->FindNext();
continue;
}
if (bFound)
{
if (pNewChecksum = ChecksumFile(pszDllName, pPathBuffer))
{
if (!strcasecmp(pDLL->GetHash(), (const char*)pNewChecksum->GetBuffer()))
{
pszDllName = pFileFinder->FindNext();
pNewChecksum->Release();
continue; // old checksum == new checksum. no changes.
}
pNewChecksum->Release();
pNewChecksum = NULL;
}
// Delete all Plugins which are associated with this PluginDLL.
LISTPOSITION pPos = NULL;
if ( m_PluginList.GetCount() )
{
LISTPOSITION pPos = m_PluginList.GetHeadPosition();
while (pPos)
{
// save off current position for delete
LISTPOSITION posAt = pPos;
Plugin2Handler::Plugin* pPlugin = (Plugin2Handler::Plugin*)m_PluginList.GetNext(pPos);
HX_ASSERT(pPlugin);
if ( pPlugin && pPlugin->GetDLL() == pDLL )
{
RemovePluginFromIndices( pPlugin );
m_PluginList.RemoveAt( posAt );
HX_RELEASE( pPlugin );
}
}
}
// Remove the pluginDLL from the PluginDLL list.
pPos = m_PluginDLLList.Find(pDLL);
if (pPos)
{
m_PluginDLLList.RemoveAt(pPos);
m_FileNameMap.RemoveKey(pszDllName);
// Since this PluginDLL was unloaded, no need to keep
// it in the list of PluginDLLs which export CanUnload2().
LISTPOSITION posCanUnload = m_CanUnload2DllList.Find( pDLL );
if ( posCanUnload )
{
m_CanUnload2DllList.RemoveAt( posCanUnload );
}
}
bDLLIsDirty = TRUE;
}
else
{
bDLLIsDirty = TRUE;
}
if (bDLLIsDirty)
{
// if we got here we have a new dll.
Plugin2Handler::Errors loadResult;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -