#ifndef _LOADPLUGIN_H_
#define _LOADPLUGIN_H_
#include<map>
//#include<helpers_s.h>
#ifdef _UNICODE
#define _tstring wstring
#else
#define _tstring string
#endif
typedef HRESULT (STDAPICALLTYPE *PDLLGETCLASSOBJECT)(const CLSID& clsid, const IID& iid, void** ppv);
class cLoadPlugin
{
public:
cLoadPlugin()
{
m_plugins.clear();
InitializeCriticalSection( &m_cs );
}
~cLoadPlugin();
bool LoadPlugin( const TCHAR* szDllPath , IID IInterface , void** pInterface );
private:
HMODULE GetModule( const TCHAR* szDllPath );
_tstring& toLower( _tstring& sin );
HMODULE isInList( _tstring& path );
map<_tstring , HMODULE> m_plugins;
CRITICAL_SECTION m_cs;
void ecs()
{
EnterCriticalSection( &m_cs );
}
void lcs()
{
LeaveCriticalSection( &m_cs );
}
};
cLoadPlugin::~cLoadPlugin()
{
map<_tstring , HMODULE>::iterator it;
DeleteCriticalSection( &m_cs );
for ( it=m_plugins.begin() ; it != m_plugins.end(); it++ )
{
FreeLibrary( (HMODULE)it->second );
}
}
_tstring& cLoadPlugin::toLower( _tstring& sin )
{
TCHAR cStart = L'A', cEnd=L'Z';
for( unsigned int i=0; i < sin.length(); i++ )
{
if( sin[i] >= cStart && sin[i] <= cEnd )
{
sin[i] = sin[i]+32;
}
}
return( sin );
}
HMODULE cLoadPlugin::isInList( _tstring& path )
{
map<_tstring , HMODULE>::iterator it;
it = m_plugins.find( path );
if( it == m_plugins.end() )
return( NULL );
return( it->second );
}
bool cLoadPlugin::LoadPlugin( const TCHAR* szDllPath , IID IInterface , void** pInterface )
{
ecs();
HRESULT hr;
HMODULE hMod = NULL;
PDLLGETCLASSOBJECT proc = NULL;
IClassFactory* pFactory = NULL;
//Get the module from list or load it
hMod = GetModule( szDllPath );
if( !hMod )
{
lcs();
return( false );
}
//Get Proc address
proc = (PDLLGETCLASSOBJECT) GetProcAddress( hMod , "DllGetClassObject" );
if( !proc )
{
lcs();
return( false );
}
hr = proc( IInterface , IID_IClassFactory , (void**)&pFactory );
if( hr || !pFactory )
{
lcs();
return( false );
}
hr = pFactory->CreateInstance( NULL, IInterface , pInterface );
if( hr || !pInterface )
{
lcs();
return( false );
}
pFactory->Release();
lcs();
return( true );
}
HMODULE cLoadPlugin::GetModule( const TCHAR* szDllPath )
{
_tstring spath;
_tstring mname;
const TCHAR *pName = NULL, c = L'\\';
HMODULE hMod = NULL;
PDLLGETCLASSOBJECT proc = NULL;
if( !szDllPath )
return( NULL );
//convet path to lowercase and check if file exist
//If not a file
spath = szDllPath;
toLower( spath );
//if( !IsFile( toLower( spath ).c_str() ) )
// return( false );
//Is alread on list
pName = _tcsrchr( spath.c_str() , c );
if( !pName )
pName = spath.c_str();
else
pName++;
mname = pName;
//Check if module already loaded
hMod = isInList( mname );
//if not on list load module and store it to list
if( !hMod )
{
if( ( hMod = LoadLibrary( spath.c_str() ) ) == NULL )
return( NULL );
proc = (PDLLGETCLASSOBJECT) GetProcAddress( hMod , "DllGetClassObject" );
if( !proc )
{
FreeLibrary( hMod );
return( NULL );
}
//insert plugin
m_plugins[mname] = hMod;
}
return( hMod );
}
#endif //_LOADPLUGIN_H_