//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // //===========================================================================// #if defined( _WIN32 ) && !defined( _X360 ) #include #endif #if !defined( DONT_PROTECT_FILEIO_FUNCTIONS ) #define DONT_PROTECT_FILEIO_FUNCTIONS // for protected_things.h #endif #if defined( PROTECTED_THINGS_ENABLE ) #undef PROTECTED_THINGS_ENABLE // from protected_things.h #endif #include #include "interface.h" #include "basetypes.h" #include "tier0/dbg.h" #include #include #include "tier1/strtools.h" #include "tier0/icommandline.h" #include "tier0/dbg.h" #include "tier0/threadtools.h" #ifdef _WIN32 #include // getcwd #elif defined _LINUX || defined __APPLE__ #define _getcwd getcwd #endif #if defined( _X360 ) #include "xbox/xbox_win32stubs.h" #endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" #if !defined COMPILER_MSVC && !defined HMODULE #define HMODULE void * #endif // ------------------------------------------------------------------------------------ // // InterfaceReg. // ------------------------------------------------------------------------------------ // InterfaceReg *s_pInterfaceRegs = NULL; InterfaceReg::InterfaceReg( InstantiateInterfaceFn fn, const char *pName ) : m_pName(pName) { m_CreateFn = fn; m_pNext = s_pInterfaceRegs; s_pInterfaceRegs = this; } // ------------------------------------------------------------------------------------ // // CreateInterface. // This is the primary exported function by a dll, referenced by name via dynamic binding // that exposes an opqaue function pointer to the interface. // ------------------------------------------------------------------------------------ // void* CreateInterface( const char *pName, int *pReturnCode ) { InterfaceReg *pCur; for (pCur=s_pInterfaceRegs; pCur; pCur=pCur->m_pNext) { if (strcmp(pCur->m_pName, pName) == 0) { if (pReturnCode) { *pReturnCode = IFACE_OK; } return pCur->m_CreateFn(); } } if (pReturnCode) { *pReturnCode = IFACE_FAILED; } return NULL; } #if defined _LINUX || defined __APPLE__ // Linux doesn't have this function so this emulates its functionality void *GetModuleHandle(const char *name) { void *handle; if( name == NULL ) { // hmm, how can this be handled under linux.... // is it even needed? return NULL; } if( (handle=dlopen(name, RTLD_NOW))==NULL) { printf("DLOPEN Error:%s\n",dlerror()); // couldn't open this file return NULL; } // read "man dlopen" for details // in short dlopen() inc a ref count // so dec the ref count by performing the close dlclose(handle); return handle; } #endif #if defined( _WIN32 ) && !defined( _X360 ) #define WIN32_LEAN_AND_MEAN #include "windows.h" #endif bool Sys_IsDebuggerPresent() { return Plat_IsInDebugSession(); } struct ThreadedLoadLibaryContext_t { const char *m_pLibraryName; HMODULE m_hLibrary; }; //----------------------------------------------------------------------------- // Purpose: get the interface for the specified module and version // Input : // Output : //----------------------------------------------------------------------------- bool Sys_LoadInterface( const char *pModuleName, const char *pInterfaceVersionName, HMODULE *pOutModule, void **pOutInterface ) { HMODULE pMod = Plat_LoadModule( pModuleName ); if ( !pMod ) return false; CreateInterfaceFn fn = Plat_GetModuleInterfaceFactory( pMod ); if ( !fn ) { Plat_UnloadModule( pMod ); return false; } *pOutInterface = fn( pInterfaceVersionName, NULL ); if ( !( *pOutInterface ) ) { Plat_UnloadModule( pMod ); return false; } if ( pOutModule ) *pOutModule = pMod; return true; } //----------------------------------------------------------------------------- // Purpose: Place this as a singleton at module scope (e.g.) and use it to get the factory from the specified module name. // // When the singleton goes out of scope (.dll unload if at module scope), // then it'll call Sys_UnloadModule on the module so that the refcount is decremented // and the .dll actually can unload from memory. //----------------------------------------------------------------------------- CDllDemandLoader::CDllDemandLoader( char const *pchModuleName ) : m_pchModuleName( pchModuleName ), m_hModule( 0 ), m_bLoadAttempted( false ) { } CDllDemandLoader::~CDllDemandLoader() { Unload(); } CreateInterfaceFn CDllDemandLoader::GetFactory() { if ( !m_hModule && !m_bLoadAttempted ) { m_bLoadAttempted = true; m_hModule = Plat_LoadModule( m_pchModuleName ); } if ( !m_hModule ) { return NULL; } return Plat_GetModuleInterfaceFactory( m_hModule ); } void CDllDemandLoader::Unload() { if ( m_hModule ) { Plat_UnloadModule( m_hModule ); m_hModule = 0; } }