diff --git a/common/xash3d_types.h b/common/xash3d_types.h index bf9cd239..f246f16e 100644 --- a/common/xash3d_types.h +++ b/common/xash3d_types.h @@ -232,6 +232,7 @@ typedef struct dll_info_s { const char *name; // name of library const dllfunc_t *fcts; // list of dll exports + const size_t num_fcts; qboolean crash; // crash if dll not found void *link; // hinstance of loading library } dll_info_t; diff --git a/engine/client/avi/avi_win.c b/engine/client/avi/avi_win.c index 128fe62f..918c42a0 100644 --- a/engine/client/avi/avi_win.c +++ b/engine/client/avi/avi_win.c @@ -30,10 +30,9 @@ static dllfunc_t msvfw_funcs[] = { "DrawDibOpen", (void **) &pDrawDibOpen }, { "DrawDibDraw", (void **) &pDrawDibDraw }, { "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 static MMRESULT (_stdcall *pacmStreamOpen)( LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD ); @@ -51,10 +50,9 @@ static dllfunc_t msacm_funcs[] = { "acmStreamConvert", (void **) &pacmStreamConvert }, { "acmStreamSize", (void **) &pacmStreamSize }, { "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 static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize ); @@ -88,10 +86,9 @@ static dllfunc_t avifile_funcs[] = { "AVIStreamRelease", (void **) &pAVIStreamRelease }, { "AVIStreamStart", (void **) &pAVIStreamStart }, { "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 { diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index 1050053f..4449b68d 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -4062,8 +4062,7 @@ qboolean CL_LoadProgs( const char *name ) } // clear exports - for( i = 0; i < ARRAYSIZE( cdll_exports ); i++ ) - *(cdll_exports[i].func) = NULL; + ClearExports( cdll_exports, ARRAYSIZE( cdll_exports )); // trying to get single export if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL ) @@ -4081,19 +4080,8 @@ qboolean CL_LoadProgs( const char *name ) CL_GetSecuredClientAPI( GetClientAPI ); } - if( GetClientAPI != NULL ) - { - // 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; - } + if( GetClientAPI != NULL ) // check critical functions again + valid_single_export = ValidateExports( cdll_exports, ARRAYSIZE( cdll_exports )); 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 if( !valid_single_export ) - { - // clear new exports - for( i = 0; i < ARRAYSIZE( cdll_new_exports ); i++ ) - *(cdll_new_exports[i].func) = NULL; - } + ClearExports( cdll_new_exports, ARRAYSIZE( cdll_new_exports )); for( i = 0; i < ARRAYSIZE( cdll_new_exports ); i++ ) { diff --git a/engine/common/system.c b/engine/common/system.c index cc50b3e2..dbc210df 100644 --- a/engine/common/system.c +++ b/engine/common/system.c @@ -255,7 +255,7 @@ void Sys_SendKeyEvents( void ) //======================================================================= qboolean Sys_LoadLibrary( dll_info_t *dll ) { - const dllfunc_t *func; + size_t i; string errorstring; // check errors @@ -267,12 +267,8 @@ qboolean Sys_LoadLibrary( dll_info_t *dll ) Con_Reportf( "%s: Loading %s", __func__, dll->name ); - if( dll->fcts ) - { - // lookup export table - for( func = dll->fcts; func && func->name != NULL; func++ ) - *func->func = NULL; - } + if( dll->fcts ) // lookup export table + ClearExports( dll->fcts, dll->num_fcts ); if( !dll->link ) 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 - 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 ); goto error; @@ -300,19 +297,11 @@ error: Con_Reportf( " - failed\n" ); Sys_FreeLibrary( dll ); // trying to free if( dll->crash ) Sys_Error( "%s", errorstring ); - else Con_Reportf( S_ERROR "%s", errorstring ); + else Con_Reportf( S_ERROR "%s", errorstring ); 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 ) { // invalid desc or alredy freed @@ -330,6 +319,8 @@ qboolean Sys_FreeLibrary( dll_info_t *dll ) COM_FreeLibrary( dll->link ); dll->link = NULL; + ClearExports( dll->fcts, dll->num_fcts ); + return true; } diff --git a/engine/common/system.h b/engine/common/system.h index 086b27e1..630a347f 100644 --- a/engine/common/system.h +++ b/engine/common/system.h @@ -49,7 +49,6 @@ int Sys_CheckParm( const char *parm ); void Sys_Warn( const char *format, ... ) FORMAT_CHECK( 1 ); void Sys_Error( const char *error, ... ) FORMAT_CHECK( 1 ); qboolean Sys_LoadLibrary( dll_info_t *dll ); -void* Sys_GetProcAddress( dll_info_t *dll, const char* name ); qboolean Sys_FreeLibrary( dll_info_t *dll ); void Sys_ParseCommandLine( int argc, char **argv ); void Sys_SetupCrashHandler( void ); diff --git a/public/crtlib.h b/public/crtlib.h index c61920bf..5f795d23 100644 --- a/public/crtlib.h +++ b/public/crtlib.h @@ -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_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 ) { char out; diff --git a/public/dllhelpers.c b/public/dllhelpers.c new file mode 100644 index 00000000..9cd63aee --- /dev/null +++ b/public/dllhelpers.c @@ -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; +} diff --git a/ref/gl/gl_opengl.c b/ref/gl/gl_opengl.c index f109f2ba..e785221b 100644 --- a/ref/gl/gl_opengl.c +++ b/ref/gl/gl_opengl.c @@ -531,8 +531,7 @@ static qboolean GL_CheckExtension( const char *name, const dllfunc_t *funcs, siz #if !XASH_GL_STATIC // clear exports - for( i = 0; i < num_funcs; i++ ) - *(funcs[i].func) = NULL; + ClearExports( funcs, num_funcs ); for( i = 0; i < num_funcs; i++ ) {