/*!
\section terms_of_use Terms of Use
libspl - the simple plugin layer library.
Copyright (C) 2004 Andreas Loeffler and Ren� Stuhr (www.unitedbytes.de).
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\section author Author
Andreas Loeffler (www.unitedbytes.de)
*/
//---------------------------------------------------------------------------------------------------------------------------
/// @file spl_pluginserver_win32.cpp
/// @version 1.0
/// @author Andreas Loeffler
//---------------------------------------------------------------------------------------------------------------------------
#ifndef __SPL_PLATFORM_H__
#include "spl_platform.h"
#endif
#if SPL_PLATFORM == SPL_PLATFORM_WIN32
#define _WIN32_WINNT 0x0400
#ifndef _WINDOWS_
#include <windows.h>
#endif
#ifndef __SPL_PLUGINSERVER_WIN32_H__
#include "spl_pluginserver_win32.h"
#endif
#ifndef __SPL_THREADLOCK_H__
#include "spl_threadlock.h"
#endif
//
// Disable warning messages
//
#pragma warning( disable : 4311 4312 4267 )
slcPluginServer::slcPluginServer( void )
{
}
slcPluginServer::~slcPluginServer( void )
{
if( this->GetLoadedPlugins() > 0 )
this->UnloadAllPlugins();
}
slcPluginInfo slcPluginServer::GetPluginInfo( const long a_lIndex )
{
//
// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
// IMPLICIT USAGE.
//
slcThreadLock threadLock( this, true );
if( ( a_lIndex < 0 ) ||
( a_lIndex > ( long )this->m_mapPluginInfos.size() ) )
{
slcPluginInfo invalidInfo;
return invalidInfo;
}
this->itIds = this->m_mapPluginIds.find( a_lIndex );
if( this->itIds != this->m_mapPluginIds.end() )
{
SPL_INFO_FUNC pInfoFunc = ( SPL_INFO_FUNC )::GetProcAddress( ( HMODULE )( SPL_BITTYPE )this->itIds->second, SPL_GETINFO_NAME );
if( NULL != pInfoFunc )
{
slcPluginInfo plugInfo = *pInfoFunc();
this->m_mapPluginInfos.insert( pair<long, slcPluginInfo>( this->m_mapPluginInfos.size() , plugInfo ) );
}
else
{
//
// INFO FUNCTION NOT LOADED, INSERT DUMMY ENTRY TO AVOID ASYNCRON MAPS
//
slcPluginInfo nullInfo;
this->m_mapPluginInfos.insert( pair<long, slcPluginInfo>( this->m_mapPluginInfos.size(), nullInfo ) );
}
}
return this->m_mapPluginInfos[ a_lIndex ];
}
void slcPluginServer::GetAllPluginInfos( void )
{
long l = 0;
//
// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
// IMPLICIT USAGE.
//
slcThreadLock threadLock( this, true );
for( this->itIds = this->m_mapPluginIds.begin();
this->itIds != this->m_mapPluginIds.end(); this->itIds++ )
{
SPL_INFO_FUNC pInfoFunc = ( SPL_INFO_FUNC )::GetProcAddress( ( HMODULE )( SPL_BITTYPE )this->itIds->second,
SPL_GETINFO_NAME );
if( NULL != pInfoFunc )
{
slcPluginInfo plugInfo = *pInfoFunc();
this->m_mapPluginInfos.insert( pair<long, slcPluginInfo>( l++, plugInfo ) );
}
else
{
//
// INFO FUNCTION NOT LOADED, INSERT DUMMY ENTRY TO AVOID ASYNCRON MAPS
//
slcPluginInfo nullInfo;
this->m_mapPluginInfos.insert( pair<long, slcPluginInfo>( l++, nullInfo ) );
}
}
}
long slcPluginServer::LoadAllPlugins( const string& a_strPath,
const string& a_strWildcard,
const slcPluginArgs* a_pPluginArgs )
{
//
// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
// IMPLICIT USAGE.
//
slcThreadLock threadLock( this, true );
WIN32_FIND_DATA FindData;
string strWildcard;
if( a_strWildcard.empty() )
strWildcard = "*.dll";
else
strWildcard = a_strWildcard;
const slcPluginArgs* pPluginArgs = a_pPluginArgs;
if( NULL == pPluginArgs )
pPluginArgs = &this->m_nullArgs;
::SetCurrentDirectory( a_strPath.c_str() );
HANDLE hDirectory = ::FindFirstFileEx( strWildcard.c_str(), FindExInfoStandard,
&FindData, FindExSearchNameMatch, NULL, 0 );
if( hDirectory != INVALID_HANDLE_VALUE )
{
do {
if( ( strcmp( FindData.cFileName, "." ) != 0 ) &&
( strcmp( FindData.cFileName, ".." ) != 0 ) )
{
HMODULE hModule = ::LoadLibrary( FindData.cFileName );
if ( NULL != hModule )
{
SPL_INIT_FUNC pInitFunc =( SPL_INIT_FUNC )::GetProcAddress( ( HINSTANCE )hModule,
SPL_INIT_NAME );
if( NULL != pInitFunc )
{
pInitFunc( pPluginArgs );
this->m_mapPluginIds.insert( pair< long, SPL_BITTYPE >( ( long )this->m_mapPluginIds.size(), ( SPL_BITTYPE )hModule ) );
}
}
}
}
while( ::FindNextFile( hDirectory, &FindData ) );
::FindClose( hDirectory );
}
return ( long )this->m_mapPluginIds.size();
}
long slcPluginServer::LoadPlugin( const string& a_strFileName, const slcPluginArgs* a_pPluginArgs )
{
//
// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
// IMPLICIT USAGE.
//
slcThreadLock threadLock( this, true );
if( a_strFileName.empty() )
return -2;
const slcPluginArgs* pPluginArgs = a_pPluginArgs;
if( NULL == pPluginArgs )
pPluginArgs = &this->m_nullArgs;
HMODULE hModule = ::LoadLibrary( a_strFileName.c_str() );
if ( NULL != hModule )
{
SPL_INIT_FUNC pInitFunc =( SPL_INIT_FUNC )::GetProcAddress( ( HINSTANCE )hModule,
SPL_INIT_NAME );
this->m_mapPluginIds.insert( pair< long, SPL_BITTYPE >( ( long )this->m_mapPluginIds.size(), ( SPL_BITTYPE )hModule ) );
if( NULL != pInitFunc )
{
return pInitFunc( pPluginArgs ) ? 1 : 0;
}
return -1;
}
return -2;
}
bool slcPluginServer::UnloadPlugin( const long a_lIndex, const slcPluginArgs* a_pPluginArgs )
{
//
// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
// IMPLICIT USAGE.
//
slcThreadLock threadLock( this, true );
if( ( a_lIndex < 0 ) ||
( a_lIndex > ( long )this->m_mapPluginInfos.size() ) )
{
return false;
}
const slcPluginArgs* pPluginArgs = a_pPluginArgs;
if( NULL == pPluginArgs )
pPluginArgs = &this->m_nullArgs;
this->itIds = this->m_mapPluginIds.find( a_lIndex );
if( this->itIds != this->m_mapPluginIds.end() )
{
SPL_SHUTDOWN_FUNC pShutdownFunc =( SPL_SHUTDOWN_FUNC )::GetProcAddress( ( HINSTANCE )this->itIds->second,
SPL_SHUTDOWN_NAME );
if( NULL != pShutdownFunc )
{
pShutdownFunc( pPluginArgs );
}
//
// UNLOAD LIBRARY
//
::FreeLibrary( ( HMODULE )this->itIds->second );
//
// REMOVE LIBRARY FROM ID-MAP AND INFO-MAP
//
this->m_mapPluginInfos.erase( this->itIds->first );
this->m_mapPluginIds.erase( this->itIds->first );
//
// REFRESH ALL MAP IDS (CREATE NEW KEYS FOR ALL VALUES)
//
int i = 0;
long lSize = this->m_mapPluginIds.size();
map< long, SPL_BITTYPE > tempIds;
map< long, SPL_BITTYPE >::iterator itTempIds;
tempIds = this->m_mapPluginIds;
this->m_mapPluginIds.clear();
itTempIds = tempIds.begin();
for( i = 0 ; i < lSize; i++, itTempIds++ )
this->m_mapPluginIds.insert( pair<long, SPL_BITTYPE> (i, itTempIds->second ) );
lSize = this->m_mapPluginInfos.size();
map< long, slcPluginInfo > tempInfos;
map< long, slcPluginInfo >::iterator itTempInfos;
tempInfos = this->m_mapPluginInfos;
this->m_mapPluginInfos.clear();
itTempInfos = tempInfos.begin();
for( i = 0 ; i < lSize; i++, itTempInfos++ )
this->m_mapPluginInfos.insert( pair<long, slcPluginInfo> (i, itTempInfos->second ) );
return true;
}
return false;
}
void slcPluginServer::UnloadAllPlugins( const slcPluginArgs* a_pPluginArgs )
{
//
// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
// IMPLICIT USAGE.
//
slcThreadLock threadLock( this, true );
long lCount = ( long )this->m_mapPluginIds.size();
for( long l = 0; l < lCount; l++ )
{
this->UnloadPlugin( 0, a_pPluginArgs );
}
this->Clear();
}
bool slcPluginServer::RunPlugin( long a_lIndex, const slcPluginArgs* a_pPluginArgs )
{
//
// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
// IMPLICIT USAGE.
//
slcThreadLock threadLock( this, true );
const slcPluginArgs* pPluginArgs = a_pPluginArgs;
if( NULL == pPluginArgs )
pPluginArgs = &this->m_nullArgs;
if( ( a_lIndex < 0 ) ||
( a_lIndex > ( long )this->m_mapPluginInfos.size() ) )
{
return false;
}
this->itIds = this->m_mapPluginIds.find( a_lIndex );
if( this->itIds != this->m_mapPluginIds.end() )
{
SPL_RUN_FUNC pRunFunc =( SPL_RUN_FUNC )::GetProcAddress( ( HINSTANCE )this->itIds->second,
SPL_RUN_NAME );
if( NULL != pRunFunc )
{
return pRunFunc( pPluginArgs );
}
}
return false;
}
long slcPluginServer::RunAllPlugins( const slcPluginArgs* a_pPluginArgs )
{
//
// LOCKS OBJECT FOR EXCLUSIVE USE, UNLOCKS AUTOMATICALLY AT THE END OF FUNCTION.
// IMPLICIT USAGE.
//
slcThreadLock threadLock( this, true );
long lPluginsRunned = 0;
const slcPluginArgs* pPluginArgs = a_pPluginArgs;
if( NULL == pPluginArgs )
pPluginArgs = &this->m_nullArgs;
if( this->m_mapPluginIds.empty() )
return 0;
for( long l = 0; l < ( long )this->m_mapPluginIds.size(); l++ )
{
if( this->RunPlugin( l, pPluginArgs ) )
lPluginsRunned++;
}
return lPluginsRunned;
}
long slcPluginServer::Refresh( const string& a_strPath,
const string& a_strWildcard,
const slcPluginArgs* a_pPluginShutdownArgs,
const slcPluginArgs* a_pPluginInitArgs )
{
this->UnloadAllPlugins( a_pPluginShutdownArgs );
//
// Lock this object for exclusive use.
// Explicitly usage.
//
slcThreadLock threadLock( this );
threadLock.Lock();
this->Clear();
threadLock.Unlock();
return( this->LoadAllPlugins( a_strPath, a_strWildcard, a_pPluginInitArgs ) );
}
//
// Enable warning messages
//
#pragma warning( default : 4311 4312 4267 )
#endif // SPL_PLATFORM_WIN32