engine: add a function to determine if library has direct dependency on chosen DLL(Win32 only)

This commit is contained in:
Alibek Omarov 2019-06-29 23:25:50 +03:00
parent 413882a8d5
commit b5d9bf5dc8
3 changed files with 76 additions and 3 deletions

View File

@ -42,6 +42,7 @@ void *COM_FunctionFromName_SR( void *hInstance, const char *pName ); // Save/Res
void *COM_FunctionFromName( void *hInstance, const char *pName );
void COM_FreeLibrary( void *hInstance );
const char *COM_GetLibraryError( void );
qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname, qboolean directpath );
// TODO: Move to internal?
void COM_ResetLibraryError( void );

View File

@ -58,6 +58,12 @@ int dladdr( const void *addr, Dl_info *info )
}
#endif // XASH_NO_LIBDL
qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname, qboolean directpath )
{
// TODO: implement
return true;
}
void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean directpath )
{
dll_user_t *hInst = NULL;

View File

@ -591,7 +591,7 @@ void *MemoryLoadLibrary( const char *name )
{
// try to allocate memory at arbitrary position
code = (byte *)VirtualAlloc( NULL, old_header->OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_READWRITE );
}
}
if( code == NULL )
{
@ -951,6 +951,72 @@ table_error:
return false;
}
qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname, qboolean directpath )
{
MEMORYMODULE *result = NULL;
PIMAGE_DOS_HEADER dos_header;
PIMAGE_NT_HEADERS old_header;
PIMAGE_DATA_DIRECTORY directory;
PIMAGE_IMPORT_DESCRIPTOR importDesc;
string errorstring;
void *data = NULL;
dll_user_t *hInst;
hInst = FS_FindLibrary( name, directpath );
if( !hInst )
{
return false; // nothing to load
}
data = FS_LoadFile( name, NULL, false );
if( !data )
{
Q_snprintf( errorstring, sizeof( errorstring ), "couldn't load %s", name );
return false;
}
dos_header = ( PIMAGE_DOS_HEADER )data;
if( dos_header->e_magic != IMAGE_DOS_SIGNATURE )
{
Q_snprintf( errorstring, sizeof( errorstring ), "%s it's not a valid executable file", name );
goto libraryerror;
}
old_header = ( PIMAGE_NT_HEADERS )&( ( const byte * )( data ) )[dos_header->e_lfanew];
if( old_header->Signature != IMAGE_NT_SIGNATURE )
{
Q_snprintf( errorstring, sizeof( errorstring ), "%s missing PE header", name );
goto libraryerror;
}
directory = &old_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
if( directory->Size <= 0 )
{
Q_snprintf( errorstring, sizeof( errorstring ), "%s has no dependencies. Is this dll valid?\n" );
goto libraryerror;
}
importDesc = (PIMAGE_IMPORT_DESCRIPTOR)CALCULATE_ADDRESS( data, directory->VirtualAddress );
for( ; importDesc->Name; importDesc++ )
{
const char *importName = ( const char* )CALCULATE_ADDRESS( data, importDesc->Name );
Con_Reportf( "library %s has direct dependency %s\n", name, importName );
if( !Q_stricmp( importName, depname ) )
{
Mem_Free( data );
return true;
}
}
libraryerror:
Con_Printf( errorstring );
Mem_Free( data ); // release memory
return false;
}
/*
================
COM_LoadLibrary
@ -964,10 +1030,10 @@ void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean d
hInst = FS_FindLibrary( dllname, directpath );
if( !hInst ) return NULL; // nothing to load
if( hInst->custom_loader )
{
if( hInst->encrypted )
if( hInst->encrypted )
{
Con_Printf( S_ERROR "LoadLibrary: couldn't load encrypted library %s\n", dllname );
return NULL;