mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-09-19 20:16:10 +08:00

Not done, but this should fix current MM:S build from tier1 headers not matching lib on Windows.
274 lines
7.6 KiB
C++
274 lines
7.6 KiB
C++
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//===========================================================================//
|
|
#if defined( _WIN32 ) && !defined( _X360 )
|
|
#include <windows.h>
|
|
#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 <stdio.h>
|
|
#include "interface.h"
|
|
#include "basetypes.h"
|
|
#include "tier0/dbg.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "tier1/strtools.h"
|
|
#include "tier0/icommandline.h"
|
|
#include "tier0/dbg.h"
|
|
#include "tier0/threadtools.h"
|
|
#ifdef _WIN32
|
|
#include <direct.h> // 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
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns a pointer to a function, given a module
|
|
// Input : pModuleName - module name
|
|
// *pName - proc name
|
|
//-----------------------------------------------------------------------------
|
|
static void *Sys_GetProcAddress( const char *pModuleName, const char *pName )
|
|
{
|
|
HMODULE hModule = GetModuleHandle( pModuleName );
|
|
return GetProcAddress( hModule, pName );
|
|
}
|
|
|
|
static void *Sys_GetProcAddress( HMODULE hModule, const char *pName )
|
|
{
|
|
return GetProcAddress( hModule, pName );
|
|
}
|
|
|
|
bool Sys_IsDebuggerPresent()
|
|
{
|
|
return Plat_IsInDebugSession();
|
|
}
|
|
|
|
struct ThreadedLoadLibaryContext_t
|
|
{
|
|
const char *m_pLibraryName;
|
|
HMODULE m_hLibrary;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns a pointer to a function, given a module
|
|
// Input : module - windows HMODULE from Sys_LoadModule()
|
|
// *pName - proc name
|
|
// Output : factory for this module
|
|
//-----------------------------------------------------------------------------
|
|
CreateInterfaceFn Sys_GetFactory( CSysModule *pModule )
|
|
{
|
|
if ( !pModule )
|
|
return NULL;
|
|
|
|
HMODULE hDLL = reinterpret_cast<HMODULE>(pModule);
|
|
#ifdef _WIN32
|
|
return reinterpret_cast<CreateInterfaceFn>(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME ));
|
|
#elif defined(_LINUX) || defined(__APPLE__)
|
|
// Linux gives this error:
|
|
//../public/interface.cpp: In function `IBaseInterface *(*Sys_GetFactory
|
|
//(CSysModule *)) (const char *, int *)':
|
|
//../public/interface.cpp:154: ISO C++ forbids casting between
|
|
//pointer-to-function and pointer-to-object
|
|
//
|
|
// so lets get around it :)
|
|
return (CreateInterfaceFn)(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME ));
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns the instance of this module
|
|
// Output : interface_instance_t
|
|
//-----------------------------------------------------------------------------
|
|
CreateInterfaceFn Sys_GetFactoryThis( void )
|
|
{
|
|
return CreateInterface;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns the instance of the named module
|
|
// Input : *pModuleName - name of the module
|
|
// Output : interface_instance_t - instance of that module
|
|
//-----------------------------------------------------------------------------
|
|
CreateInterfaceFn Sys_GetFactory( const char *pModuleName )
|
|
{
|
|
#ifdef _WIN32
|
|
return static_cast<CreateInterfaceFn>( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) );
|
|
#elif defined(_LINUX) || defined(__APPLE__)
|
|
// see Sys_GetFactory( CSysModule *pModule ) for an explanation
|
|
return (CreateInterfaceFn)( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) );
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: get the interface for the specified module and version
|
|
// Input :
|
|
// Output :
|
|
//-----------------------------------------------------------------------------
|
|
bool Sys_LoadInterface(
|
|
const char *pModuleName,
|
|
const char *pInterfaceVersionName,
|
|
CSysModule **pOutModule,
|
|
void **pOutInterface )
|
|
{
|
|
CSysModule *pMod = Sys_LoadModule( pModuleName );
|
|
if ( !pMod )
|
|
return false;
|
|
|
|
CreateInterfaceFn fn = Sys_GetFactory( pMod );
|
|
if ( !fn )
|
|
{
|
|
Sys_UnloadModule( pMod );
|
|
return false;
|
|
}
|
|
|
|
*pOutInterface = fn( pInterfaceVersionName, NULL );
|
|
if ( !( *pOutInterface ) )
|
|
{
|
|
Sys_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 = Sys_LoadModule( m_pchModuleName );
|
|
}
|
|
|
|
if ( !m_hModule )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return Sys_GetFactory( m_hModule );
|
|
}
|
|
|
|
void CDllDemandLoader::Unload()
|
|
{
|
|
if ( m_hModule )
|
|
{
|
|
Sys_UnloadModule( m_hModule );
|
|
m_hModule = 0;
|
|
}
|
|
}
|