public: add dll helpers to simplify basic interaction with exported functions lists

This commit is contained in:
Alibek Omarov 2024-12-23 04:43:15 +03:00
parent f1d7101ad8
commit 70897af362
8 changed files with 60 additions and 47 deletions

View file

@ -232,6 +232,7 @@ typedef struct dll_info_s
{ {
const char *name; // name of library const char *name; // name of library
const dllfunc_t *fcts; // list of dll exports const dllfunc_t *fcts; // list of dll exports
const size_t num_fcts;
qboolean crash; // crash if dll not found qboolean crash; // crash if dll not found
void *link; // hinstance of loading library void *link; // hinstance of loading library
} dll_info_t; } dll_info_t;

View file

@ -30,10 +30,9 @@ static dllfunc_t msvfw_funcs[] =
{ "DrawDibOpen", (void **) &pDrawDibOpen }, { "DrawDibOpen", (void **) &pDrawDibOpen },
{ "DrawDibDraw", (void **) &pDrawDibDraw }, { "DrawDibDraw", (void **) &pDrawDibDraw },
{ "DrawDibClose", (void **) &pDrawDibClose }, { "DrawDibClose", (void **) &pDrawDibClose },
{ NULL, NULL }
}; };
dll_info_t msvfw_dll = { "msvfw32.dll", msvfw_funcs, false }; dll_info_t msvfw_dll = { "msvfw32.dll", msvfw_funcs, ARRAYSIZE( msvfw_funcs ), false };
// msacm32.dll exports // msacm32.dll exports
static MMRESULT (_stdcall *pacmStreamOpen)( LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD ); static MMRESULT (_stdcall *pacmStreamOpen)( LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD );
@ -51,10 +50,9 @@ static dllfunc_t msacm_funcs[] =
{ "acmStreamConvert", (void **) &pacmStreamConvert }, { "acmStreamConvert", (void **) &pacmStreamConvert },
{ "acmStreamSize", (void **) &pacmStreamSize }, { "acmStreamSize", (void **) &pacmStreamSize },
{ "acmStreamClose", (void **) &pacmStreamClose }, { "acmStreamClose", (void **) &pacmStreamClose },
{ NULL, NULL }
}; };
dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, false }; dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, ARRAYSIZE( msacm_funcs ), false };
// avifil32.dll exports // avifil32.dll exports
static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize ); static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize );
@ -88,10 +86,9 @@ static dllfunc_t avifile_funcs[] =
{ "AVIStreamRelease", (void **) &pAVIStreamRelease }, { "AVIStreamRelease", (void **) &pAVIStreamRelease },
{ "AVIStreamStart", (void **) &pAVIStreamStart }, { "AVIStreamStart", (void **) &pAVIStreamStart },
{ "AVIStreamTimeToSample", (void **) &pAVIStreamTimeToSample }, { "AVIStreamTimeToSample", (void **) &pAVIStreamTimeToSample },
{ NULL, NULL }
}; };
dll_info_t avifile_dll = { "avifil32.dll", avifile_funcs, false }; dll_info_t avifile_dll = { "avifil32.dll", avifile_funcs, ARRAYSIZE( avifile_funcs ), false };
typedef struct movie_state_s typedef struct movie_state_s
{ {

View file

@ -4062,8 +4062,7 @@ qboolean CL_LoadProgs( const char *name )
} }
// clear exports // clear exports
for( i = 0; i < ARRAYSIZE( cdll_exports ); i++ ) ClearExports( cdll_exports, ARRAYSIZE( cdll_exports ));
*(cdll_exports[i].func) = NULL;
// trying to get single export // trying to get single export
if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL ) if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL )
@ -4081,19 +4080,8 @@ qboolean CL_LoadProgs( const char *name )
CL_GetSecuredClientAPI( GetClientAPI ); CL_GetSecuredClientAPI( GetClientAPI );
} }
if( GetClientAPI != NULL ) if( GetClientAPI != NULL ) // check critical functions again
{ valid_single_export = ValidateExports( cdll_exports, ARRAYSIZE( cdll_exports ));
// check critical functions again
for( i = 0; i < ARRAYSIZE( cdll_exports ); i++ )
{
if( *(cdll_exports[i].func) == NULL )
break; // BAH critical function was missed
}
// everything was loaded
if( i == ARRAYSIZE( cdll_exports ))
valid_single_export = true;
}
for( i = 0; i < ARRAYSIZE( cdll_exports ); i++ ) for( i = 0; i < ARRAYSIZE( cdll_exports ); i++ )
{ {
@ -4119,11 +4107,7 @@ qboolean CL_LoadProgs( const char *name )
// it may be loaded through 'GetClientAPI' so we don't need to clear them // it may be loaded through 'GetClientAPI' so we don't need to clear them
if( !valid_single_export ) if( !valid_single_export )
{ ClearExports( cdll_new_exports, ARRAYSIZE( cdll_new_exports ));
// clear new exports
for( i = 0; i < ARRAYSIZE( cdll_new_exports ); i++ )
*(cdll_new_exports[i].func) = NULL;
}
for( i = 0; i < ARRAYSIZE( cdll_new_exports ); i++ ) for( i = 0; i < ARRAYSIZE( cdll_new_exports ); i++ )
{ {

View file

@ -255,7 +255,7 @@ void Sys_SendKeyEvents( void )
//======================================================================= //=======================================================================
qboolean Sys_LoadLibrary( dll_info_t *dll ) qboolean Sys_LoadLibrary( dll_info_t *dll )
{ {
const dllfunc_t *func; size_t i;
string errorstring; string errorstring;
// check errors // check errors
@ -267,12 +267,8 @@ qboolean Sys_LoadLibrary( dll_info_t *dll )
Con_Reportf( "%s: Loading %s", __func__, dll->name ); Con_Reportf( "%s: Loading %s", __func__, dll->name );
if( dll->fcts ) if( dll->fcts ) // lookup export table
{ ClearExports( dll->fcts, dll->num_fcts );
// lookup export table
for( func = dll->fcts; func && func->name != NULL; func++ )
*func->func = NULL;
}
if( !dll->link ) if( !dll->link )
dll->link = COM_LoadLibrary( dll->name, false, true ); // environment pathes dll->link = COM_LoadLibrary( dll->name, false, true ); // environment pathes
@ -285,9 +281,10 @@ qboolean Sys_LoadLibrary( dll_info_t *dll )
} }
// Get the function adresses // Get the function adresses
for( func = dll->fcts; func && func->name != NULL; func++ ) for( i = 0; i < dll->num_fcts; i++ )
{ {
if( !( *func->func = Sys_GetProcAddress( dll, func->name ))) const dllfunc_t *func = &dll->fcts[i];
if( !( *func->func = COM_GetProcAddress( dll->link, func->name )))
{ {
Q_snprintf( errorstring, sizeof( errorstring ), "Sys_LoadLibrary: %s missing or invalid function (%s)\n", dll->name, func->name ); Q_snprintf( errorstring, sizeof( errorstring ), "Sys_LoadLibrary: %s missing or invalid function (%s)\n", dll->name, func->name );
goto error; goto error;
@ -300,19 +297,11 @@ error:
Con_Reportf( " - failed\n" ); Con_Reportf( " - failed\n" );
Sys_FreeLibrary( dll ); // trying to free Sys_FreeLibrary( dll ); // trying to free
if( dll->crash ) Sys_Error( "%s", errorstring ); if( dll->crash ) Sys_Error( "%s", errorstring );
else Con_Reportf( S_ERROR "%s", errorstring ); else Con_Reportf( S_ERROR "%s", errorstring );
return false; return false;
} }
void* Sys_GetProcAddress( dll_info_t *dll, const char* name )
{
if( !dll || !dll->link ) // invalid desc
return NULL;
return (void *)COM_GetProcAddress( dll->link, name );
}
qboolean Sys_FreeLibrary( dll_info_t *dll ) qboolean Sys_FreeLibrary( dll_info_t *dll )
{ {
// invalid desc or alredy freed // invalid desc or alredy freed
@ -330,6 +319,8 @@ qboolean Sys_FreeLibrary( dll_info_t *dll )
COM_FreeLibrary( dll->link ); COM_FreeLibrary( dll->link );
dll->link = NULL; dll->link = NULL;
ClearExports( dll->fcts, dll->num_fcts );
return true; return true;
} }

View file

@ -49,7 +49,6 @@ int Sys_CheckParm( const char *parm );
void Sys_Warn( const char *format, ... ) FORMAT_CHECK( 1 ); void Sys_Warn( const char *format, ... ) FORMAT_CHECK( 1 );
void Sys_Error( const char *error, ... ) FORMAT_CHECK( 1 ); void Sys_Error( const char *error, ... ) FORMAT_CHECK( 1 );
qboolean Sys_LoadLibrary( dll_info_t *dll ); qboolean Sys_LoadLibrary( dll_info_t *dll );
void* Sys_GetProcAddress( dll_info_t *dll, const char* name );
qboolean Sys_FreeLibrary( dll_info_t *dll ); qboolean Sys_FreeLibrary( dll_info_t *dll );
void Sys_ParseCommandLine( int argc, char **argv ); void Sys_ParseCommandLine( int argc, char **argv );
void Sys_SetupCrashHandler( void ); void Sys_SetupCrashHandler( void );

View file

@ -106,6 +106,12 @@ char *COM_ParseFileSafe( char *data, char *token, const int size, unsigned int f
int matchpattern( const char *in, const char *pattern, qboolean caseinsensitive ); int matchpattern( const char *in, const char *pattern, qboolean caseinsensitive );
int matchpattern_with_separator( const char *in, const char *pattern, qboolean caseinsensitive, const char *separators, qboolean wildcard_least_one ); int matchpattern_with_separator( const char *in, const char *pattern, qboolean caseinsensitive, const char *separators, qboolean wildcard_least_one );
//
// dllhelpers.c
//
void ClearExports( const dllfunc_t *funcs, size_t num_funcs );
qboolean ValidateExports( const dllfunc_t *funcs, size_t num_funcs );
static inline char Q_toupper( const char in ) static inline char Q_toupper( const char in )
{ {
char out; char out;

36
public/dllhelpers.c Normal file
View file

@ -0,0 +1,36 @@
/*
dllhelpers.c - dll exports helpers
Copyright (C) 2024 Alibek Omarov
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
*/
#include "crtlib.h"
void ClearExports( const dllfunc_t *funcs, size_t num_funcs )
{
size_t i;
for( i = 0; i < num_funcs; i++ )
*(funcs[i].func) = NULL;
}
qboolean ValidateExports( const dllfunc_t *funcs, size_t num_funcs )
{
size_t i;
for( i = 0; i < num_funcs; i++ )
{
if( *(funcs[i].func) == NULL )
return false;
}
return true;
}

View file

@ -531,8 +531,7 @@ static qboolean GL_CheckExtension( const char *name, const dllfunc_t *funcs, siz
#if !XASH_GL_STATIC #if !XASH_GL_STATIC
// clear exports // clear exports
for( i = 0; i < num_funcs; i++ ) ClearExports( funcs, num_funcs );
*(funcs[i].func) = NULL;
for( i = 0; i < num_funcs; i++ ) for( i = 0; i < num_funcs; i++ )
{ {