|
|
@ -16,7 +16,11 @@ GNU General Public License for more details. |
|
|
|
#if XASH_LIB == LIB_WIN32 |
|
|
|
#if XASH_LIB == LIB_WIN32 |
|
|
|
#include "common.h" |
|
|
|
#include "common.h" |
|
|
|
#include "library.h" |
|
|
|
#include "library.h" |
|
|
|
|
|
|
|
#include <winnt.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CALCULATE_ADDRESS( base, offset ) ( ( DWORD )( base ) + ( DWORD )( offset ) ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if XASH_X86 |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
--------------------------------------------------------------- |
|
|
|
--------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
@ -25,106 +29,11 @@ GNU General Public License for more details. |
|
|
|
--------------------------------------------------------------- |
|
|
|
--------------------------------------------------------------- |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#define DOS_SIGNATURE 0x5A4D // MZ
|
|
|
|
|
|
|
|
#define NT_SIGNATURE 0x00004550 // PE00
|
|
|
|
|
|
|
|
#define NUMBER_OF_DIRECTORY_ENTRIES 16 |
|
|
|
#define NUMBER_OF_DIRECTORY_ENTRIES 16 |
|
|
|
#ifndef IMAGE_SIZEOF_BASE_RELOCATION |
|
|
|
#ifndef IMAGE_SIZEOF_BASE_RELOCATION |
|
|
|
#define IMAGE_SIZEOF_BASE_RELOCATION ( sizeof( IMAGE_BASE_RELOCATION )) |
|
|
|
#define IMAGE_SIZEOF_BASE_RELOCATION ( sizeof( IMAGE_BASE_RELOCATION )) |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
typedef struct |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// dos .exe header
|
|
|
|
|
|
|
|
word e_magic; // magic number
|
|
|
|
|
|
|
|
word e_cblp; // bytes on last page of file
|
|
|
|
|
|
|
|
word e_cp; // pages in file
|
|
|
|
|
|
|
|
word e_crlc; // relocations
|
|
|
|
|
|
|
|
word e_cparhdr; // size of header in paragraphs
|
|
|
|
|
|
|
|
word e_minalloc; // minimum extra paragraphs needed
|
|
|
|
|
|
|
|
word e_maxalloc; // maximum extra paragraphs needed
|
|
|
|
|
|
|
|
word e_ss; // initial (relative) SS value
|
|
|
|
|
|
|
|
word e_sp; // initial SP value
|
|
|
|
|
|
|
|
word e_csum; // checksum
|
|
|
|
|
|
|
|
word e_ip; // initial IP value
|
|
|
|
|
|
|
|
word e_cs; // initial (relative) CS value
|
|
|
|
|
|
|
|
word e_lfarlc; // file address of relocation table
|
|
|
|
|
|
|
|
word e_ovno; // overlay number
|
|
|
|
|
|
|
|
word e_res[4]; // reserved words
|
|
|
|
|
|
|
|
word e_oemid; // OEM identifier (for e_oeminfo)
|
|
|
|
|
|
|
|
word e_oeminfo; // OEM information; e_oemid specific
|
|
|
|
|
|
|
|
word e_res2[10]; // reserved words
|
|
|
|
|
|
|
|
long e_lfanew; // file address of new exe header
|
|
|
|
|
|
|
|
} DOS_HEADER; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// win .exe header
|
|
|
|
|
|
|
|
word Machine; |
|
|
|
|
|
|
|
word NumberOfSections; |
|
|
|
|
|
|
|
dword TimeDateStamp; |
|
|
|
|
|
|
|
dword PointerToSymbolTable; |
|
|
|
|
|
|
|
dword NumberOfSymbols; |
|
|
|
|
|
|
|
word SizeOfOptionalHeader; |
|
|
|
|
|
|
|
word Characteristics; |
|
|
|
|
|
|
|
} PE_HEADER; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
dword VirtualAddress; |
|
|
|
|
|
|
|
dword Size; |
|
|
|
|
|
|
|
} DATA_DIRECTORY; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
word Magic; |
|
|
|
|
|
|
|
byte MajorLinkerVersion; |
|
|
|
|
|
|
|
byte MinorLinkerVersion; |
|
|
|
|
|
|
|
dword SizeOfCode; |
|
|
|
|
|
|
|
dword SizeOfInitializedData; |
|
|
|
|
|
|
|
dword SizeOfUninitializedData; |
|
|
|
|
|
|
|
dword AddressOfEntryPoint; |
|
|
|
|
|
|
|
dword BaseOfCode; |
|
|
|
|
|
|
|
dword BaseOfData; |
|
|
|
|
|
|
|
dword ImageBase; |
|
|
|
|
|
|
|
dword SectionAlignment; |
|
|
|
|
|
|
|
dword FileAlignment; |
|
|
|
|
|
|
|
word MajorOperatingSystemVersion; |
|
|
|
|
|
|
|
word MinorOperatingSystemVersion; |
|
|
|
|
|
|
|
word MajorImageVersion; |
|
|
|
|
|
|
|
word MinorImageVersion; |
|
|
|
|
|
|
|
word MajorSubsystemVersion; |
|
|
|
|
|
|
|
word MinorSubsystemVersion; |
|
|
|
|
|
|
|
dword Win32VersionValue; |
|
|
|
|
|
|
|
dword SizeOfImage; |
|
|
|
|
|
|
|
dword SizeOfHeaders; |
|
|
|
|
|
|
|
dword CheckSum; |
|
|
|
|
|
|
|
word Subsystem; |
|
|
|
|
|
|
|
word DllCharacteristics; |
|
|
|
|
|
|
|
dword SizeOfStackReserve; |
|
|
|
|
|
|
|
dword SizeOfStackCommit; |
|
|
|
|
|
|
|
dword SizeOfHeapReserve; |
|
|
|
|
|
|
|
dword SizeOfHeapCommit; |
|
|
|
|
|
|
|
dword LoaderFlags; |
|
|
|
|
|
|
|
dword NumberOfRvaAndSizes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DATA_DIRECTORY DataDirectory[NUMBER_OF_DIRECTORY_ENTRIES]; |
|
|
|
|
|
|
|
} OPTIONAL_HEADER; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
dword Characteristics; |
|
|
|
|
|
|
|
dword TimeDateStamp; |
|
|
|
|
|
|
|
word MajorVersion; |
|
|
|
|
|
|
|
word MinorVersion; |
|
|
|
|
|
|
|
dword Name; |
|
|
|
|
|
|
|
dword Base; |
|
|
|
|
|
|
|
dword NumberOfFunctions; |
|
|
|
|
|
|
|
dword NumberOfNames; |
|
|
|
|
|
|
|
dword AddressOfFunctions; // RVA from base of image
|
|
|
|
|
|
|
|
dword AddressOfNames; // RVA from base of image
|
|
|
|
|
|
|
|
dword AddressOfNameOrdinals; // RVA from base of image
|
|
|
|
|
|
|
|
} EXPORT_DIRECTORY; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct |
|
|
|
typedef struct |
|
|
|
{ |
|
|
|
{ |
|
|
|
PIMAGE_NT_HEADERS headers; |
|
|
|
PIMAGE_NT_HEADERS headers; |
|
|
@ -134,26 +43,6 @@ typedef struct |
|
|
|
int initialized; |
|
|
|
int initialized; |
|
|
|
} MEMORYMODULE, *PMEMORYMODULE; |
|
|
|
} MEMORYMODULE, *PMEMORYMODULE; |
|
|
|
|
|
|
|
|
|
|
|
typedef struct |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
byte Name[8]; // dos name length
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
union |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
dword PhysicalAddress; |
|
|
|
|
|
|
|
dword VirtualSize; |
|
|
|
|
|
|
|
} Misc; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dword VirtualAddress; |
|
|
|
|
|
|
|
dword SizeOfRawData; |
|
|
|
|
|
|
|
dword PointerToRawData; |
|
|
|
|
|
|
|
dword PointerToRelocations; |
|
|
|
|
|
|
|
dword PointerToLinenumbers; |
|
|
|
|
|
|
|
word NumberOfRelocations; |
|
|
|
|
|
|
|
word NumberOfLinenumbers; |
|
|
|
|
|
|
|
dword Characteristics; |
|
|
|
|
|
|
|
} SECTION_HEADER; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Protection flags for memory pages (Executable, Readable, Writeable)
|
|
|
|
// Protection flags for memory pages (Executable, Readable, Writeable)
|
|
|
|
static int ProtectionFlags[2][2][2] = |
|
|
|
static int ProtectionFlags[2][2][2] = |
|
|
|
{ |
|
|
|
{ |
|
|
@ -170,7 +59,6 @@ static int ProtectionFlags[2][2][2] = |
|
|
|
typedef BOOL (WINAPI *DllEntryProc)( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved ); |
|
|
|
typedef BOOL (WINAPI *DllEntryProc)( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved ); |
|
|
|
|
|
|
|
|
|
|
|
#define GET_HEADER_DICTIONARY( module, idx ) &(module)->headers->OptionalHeader.DataDirectory[idx] |
|
|
|
#define GET_HEADER_DICTIONARY( module, idx ) &(module)->headers->OptionalHeader.DataDirectory[idx] |
|
|
|
#define CALCULATE_ADDRESS( base, offset ) ((DWORD)(base) + (DWORD)(offset)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void CopySections( const byte *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module ) |
|
|
|
static void CopySections( const byte *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -598,6 +486,7 @@ library_error: |
|
|
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
static DWORD GetOffsetByRVA( DWORD rva, PIMAGE_NT_HEADERS nt_header ) |
|
|
|
static DWORD GetOffsetByRVA( DWORD rva, PIMAGE_NT_HEADERS nt_header ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -653,41 +542,18 @@ static void FreeNameFuncGlobals( dll_user_t *hInst ) |
|
|
|
hInst->funcs = NULL; |
|
|
|
hInst->funcs = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
char *GetMSVCName( const char *in_name ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
static string out_name; |
|
|
|
|
|
|
|
char *pos; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( in_name[0] == '?' ) // is this a MSVC C++ mangled name?
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if(( pos = Q_strstr( in_name, "@@" )) != NULL ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int len = pos - in_name; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// strip off the leading '?'
|
|
|
|
|
|
|
|
Q_strncpy( out_name, in_name + 1, sizeof( out_name )); |
|
|
|
|
|
|
|
out_name[len-1] = 0; // terminate string at the "@@"
|
|
|
|
|
|
|
|
return out_name; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Q_strncpy( out_name, in_name, sizeof( out_name )); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return out_name; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qboolean LibraryLoadSymbols( dll_user_t *hInst ) |
|
|
|
qboolean LibraryLoadSymbols( dll_user_t *hInst ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
file_t *f; |
|
|
|
file_t *f; |
|
|
|
string errorstring; |
|
|
|
string errorstring; |
|
|
|
DOS_HEADER dos_header; |
|
|
|
IMAGE_DOS_HEADER dos_header; |
|
|
|
LONG nt_signature; |
|
|
|
LONG nt_signature; |
|
|
|
PE_HEADER pe_header; |
|
|
|
IMAGE_FILE_HEADER pe_header; |
|
|
|
SECTION_HEADER section_header; |
|
|
|
IMAGE_SECTION_HEADER section_header; |
|
|
|
qboolean rdata_found; |
|
|
|
qboolean rdata_found; |
|
|
|
OPTIONAL_HEADER optional_header; |
|
|
|
IMAGE_OPTIONAL_HEADER optional_header; |
|
|
|
long rdata_delta = 0; |
|
|
|
long rdata_delta = 0; |
|
|
|
EXPORT_DIRECTORY export_directory; |
|
|
|
IMAGE_EXPORT_DIRECTORY export_directory; |
|
|
|
long name_offset; |
|
|
|
long name_offset; |
|
|
|
long exports_offset; |
|
|
|
long exports_offset; |
|
|
|
long ordinal_offset; |
|
|
|
long ordinal_offset; |
|
|
@ -715,7 +581,7 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst ) |
|
|
|
goto table_error; |
|
|
|
goto table_error; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( dos_header.e_magic != DOS_SIGNATURE ) |
|
|
|
if( dos_header.e_magic != IMAGE_DOS_SIGNATURE ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Q_sprintf( errorstring, "%s does not have a valid dll signature", hInst->shortPath ); |
|
|
|
Q_sprintf( errorstring, "%s does not have a valid dll signature", hInst->shortPath ); |
|
|
|
goto table_error; |
|
|
|
goto table_error; |
|
|
@ -733,7 +599,7 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst ) |
|
|
|
goto table_error; |
|
|
|
goto table_error; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( nt_signature != NT_SIGNATURE ) |
|
|
|
if( nt_signature != IMAGE_NT_SIGNATURE ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Q_sprintf( errorstring, "%s does not have a valid NT signature", hInst->shortPath ); |
|
|
|
Q_sprintf( errorstring, "%s does not have a valid NT signature", hInst->shortPath ); |
|
|
|
goto table_error; |
|
|
|
goto table_error; |
|
|
@ -860,7 +726,7 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst ) |
|
|
|
if( FS_Seek( f, name_offset, SEEK_SET ) != -1 ) |
|
|
|
if( FS_Seek( f, name_offset, SEEK_SET ) != -1 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
FsGetString( f, function_name ); |
|
|
|
FsGetString( f, function_name ); |
|
|
|
hInst->names[i] = copystring( GetMSVCName( function_name )); |
|
|
|
hInst->names[i] = copystring( COM_GetMSVCName( function_name )); |
|
|
|
} |
|
|
|
} |
|
|
|
else break; |
|
|
|
else break; |
|
|
|
} |
|
|
|
} |
|
|
@ -880,8 +746,8 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst ) |
|
|
|
void *fn_offset; |
|
|
|
void *fn_offset; |
|
|
|
|
|
|
|
|
|
|
|
index = hInst->ordinals[i]; |
|
|
|
index = hInst->ordinals[i]; |
|
|
|
fn_offset = (void *)COM_GetProcAddress( hInst, "GiveFnptrsToDll" ); |
|
|
|
fn_offset = COM_GetProcAddress( hInst, "GiveFnptrsToDll" ); |
|
|
|
hInst->funcBase = (dword)(fn_offset) - hInst->funcs[index]; |
|
|
|
hInst->funcBase = (uintptr_t)(fn_offset) - hInst->funcs[index]; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -938,7 +804,7 @@ qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname |
|
|
|
importDir = &peHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; |
|
|
|
importDir = &peHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; |
|
|
|
if( importDir->Size <= 0 ) |
|
|
|
if( importDir->Size <= 0 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Q_snprintf( errorstring, sizeof( errorstring ), "%s has no dependencies. Is this library valid?\n", name ); |
|
|
|
Con_Printf( S_WARN "%s: %s has no dependencies. Is this library valid?\n", __FUNCTION__, name ); |
|
|
|
goto libraryerror; |
|
|
|
goto libraryerror; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -956,7 +822,10 @@ qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
libraryerror: |
|
|
|
libraryerror: |
|
|
|
if( errorstring[0] ) Con_Printf( errorstring ); |
|
|
|
if( errorstring[0] ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Con_Printf( S_ERROR "%s: %s\n", __FUNCTION__, errorstring ); |
|
|
|
|
|
|
|
} |
|
|
|
if( data ) Mem_Free( data ); // release memory
|
|
|
|
if( data ) Mem_Free( data ); // release memory
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
@ -975,17 +844,22 @@ void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean d |
|
|
|
hInst = FS_FindLibrary( dllname, directpath ); |
|
|
|
hInst = FS_FindLibrary( dllname, directpath ); |
|
|
|
if( !hInst ) return NULL; // nothing to load
|
|
|
|
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; |
|
|
|
Con_Printf( S_ERROR "LoadLibrary: couldn't load encrypted library %s\n", dllname ); |
|
|
|
} |
|
|
|
return NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if XASH_X86 |
|
|
|
|
|
|
|
if( hInst->custom_loader ) |
|
|
|
|
|
|
|
{ |
|
|
|
hInst->hInstance = MemoryLoadLibrary( hInst->fullPath ); |
|
|
|
hInst->hInstance = MemoryLoadLibrary( hInst->fullPath ); |
|
|
|
} |
|
|
|
} |
|
|
|
else hInst->hInstance = LoadLibrary( hInst->fullPath ); |
|
|
|
else |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
hInst->hInstance = LoadLibrary( hInst->fullPath ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( !hInst->hInstance ) |
|
|
|
if( !hInst->hInstance ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1017,8 +891,10 @@ void *COM_GetProcAddress( void *hInstance, const char *name ) |
|
|
|
if( !hInst || !hInst->hInstance ) |
|
|
|
if( !hInst || !hInst->hInstance ) |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if XASH_X86 |
|
|
|
if( hInst->custom_loader ) |
|
|
|
if( hInst->custom_loader ) |
|
|
|
return (void *)MemoryGetProcAddress( hInst->hInstance, name ); |
|
|
|
return (void *)MemoryGetProcAddress( hInst->hInstance, name ); |
|
|
|
|
|
|
|
#endif |
|
|
|
return (void *)GetProcAddress( hInst->hInstance, name ); |
|
|
|
return (void *)GetProcAddress( hInst->hInstance, name ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1037,9 +913,16 @@ void COM_FreeLibrary( void *hInstance ) |
|
|
|
} |
|
|
|
} |
|
|
|
else Con_Reportf( "Sys_FreeLibrary: Unloading %s\n", hInst->dllName ); |
|
|
|
else Con_Reportf( "Sys_FreeLibrary: Unloading %s\n", hInst->dllName ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if XASH_X86 |
|
|
|
if( hInst->custom_loader ) |
|
|
|
if( hInst->custom_loader ) |
|
|
|
|
|
|
|
{ |
|
|
|
MemoryFreeLibrary( hInst->hInstance ); |
|
|
|
MemoryFreeLibrary( hInst->hInstance ); |
|
|
|
else FreeLibrary( hInst->hInstance ); |
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
FreeLibrary( hInst->hInstance ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hInst->hInstance = NULL; |
|
|
|
hInst->hInstance = NULL; |
|
|
|
|
|
|
|
|
|
|
|