diff --git a/engine/common/library.h b/engine/common/library.h index 9c2ec15c..a029a06b 100644 --- a/engine/common/library.h +++ b/engine/common/library.h @@ -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 ); diff --git a/engine/platform/posix/lib_posix.c b/engine/platform/posix/lib_posix.c index 2b26d7fd..437cb3b0 100644 --- a/engine/platform/posix/lib_posix.c +++ b/engine/platform/posix/lib_posix.c @@ -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; diff --git a/engine/platform/win32/lib_win.c b/engine/platform/win32/lib_win.c index c8705ce6..1a553ce2 100644 --- a/engine/platform/win32/lib_win.c +++ b/engine/platform/win32/lib_win.c @@ -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;