22 Jan 2009
This commit is contained in:
parent
3975e2034b
commit
539f54b707
27853
baserc/progs.h
27853
baserc/progs.h
File diff suppressed because it is too large
Load Diff
|
@ -6,7 +6,6 @@
|
|||
#include <windows.h>
|
||||
#include "launch_api.h"
|
||||
#include "baserc_api.h"
|
||||
#include "progs.h"
|
||||
|
||||
// resources
|
||||
#include "images.h"
|
||||
|
@ -31,7 +30,6 @@ loadres_t load_resources[] =
|
|||
{"default.dds", deffont_dds, sizeof(deffont_dds)},
|
||||
{"conback.dds", conback_dds, sizeof(conback_dds)},
|
||||
{"net.png", net_png, sizeof(net_png)},
|
||||
{"progs.pk3", progs_pk3, sizeof(progs_pk3)},
|
||||
{"uimenu.dat", uimenu_dat, sizeof(uimenu_dat)}, // FIXME: get rid of this
|
||||
{NULL, NULL, 0 }
|
||||
};
|
||||
|
@ -56,6 +54,12 @@ byte *RC_FindFile( const char *filename, fs_offset_t *size )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// main DLL entry point
|
||||
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
baserc_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
|
||||
{
|
||||
static baserc_exp_t Com;
|
||||
|
|
|
@ -61,8 +61,8 @@ TargetDir=\Xash3D\src_main\temp\client\!release
|
|||
InputPath=\Xash3D\src_main\temp\client\!release\client.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"D:\Xash3D\tmpQuArK\bin\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\client.dll "D:\Xash3D\tmpQuArK\bin\client.dll"
|
||||
"D:\Xash3D\bin\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\client.dll "D:\Xash3D\bin\client.dll"
|
||||
|
||||
# End Custom Build
|
||||
|
||||
|
@ -101,8 +101,8 @@ TargetDir=\Xash3D\src_main\temp\client\!debug
|
|||
InputPath=\Xash3D\src_main\temp\client\!debug\client.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"D:\Xash3D\tmpQuArK\bin\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\client.dll "D:\Xash3D\tmpQuArK\bin\client.dll"
|
||||
"D:\Xash3D\bin\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\client.dll "D:\Xash3D\bin\client.dll"
|
||||
|
||||
# End Custom Build
|
||||
|
||||
|
|
|
@ -72,6 +72,9 @@ inline void CL_PlaySound( int iSound, float flVolume, Vector &pos, float pitch =
|
|||
#define FILE_EXISTS (*g_engfuncs.pfnFileExists)
|
||||
#define FREE_FILE FREE
|
||||
#define GET_GAME_DIR (*g_engfuncs.pfnGetGameDir)
|
||||
#define LOAD_LIBRARY (*g_engfuncs.pfnLoadLibrary)
|
||||
#define GET_PROC_ADDRESS (*g_engfuncs.pfnGetProcAddress)
|
||||
#define FREE_LIBRARY (*g_engfuncs.pfnFreeLibrary)
|
||||
#define HOST_ERROR (*g_engfuncs.pfnHostError)
|
||||
|
||||
#endif//ENGINECALLBACKS_H
|
|
@ -40,7 +40,7 @@ typedef struct client_sprite_s
|
|||
wrect_t rc;
|
||||
} client_sprite_t;
|
||||
|
||||
typedef HMODULE dllhandle_t;
|
||||
typedef void* dllhandle_t;
|
||||
typedef struct dllfunction_s
|
||||
{
|
||||
const char *name;
|
||||
|
|
|
@ -620,7 +620,6 @@ Sys LoadGameDLL
|
|||
BOOL Sys_LoadLibrary( const char* dllname, dllhandle_t* handle, const dllfunction_t *fcts )
|
||||
{
|
||||
const dllfunction_t *gamefunc;
|
||||
char dllpath[256], gamedir[256];
|
||||
dllhandle_t dllhandle = 0;
|
||||
|
||||
if( handle == NULL ) return false;
|
||||
|
@ -629,21 +628,21 @@ BOOL Sys_LoadLibrary( const char* dllname, dllhandle_t* handle, const dllfunctio
|
|||
for( gamefunc = fcts; gamefunc && gamefunc->name != NULL; gamefunc++ )
|
||||
*gamefunc->funcvariable = NULL;
|
||||
|
||||
GET_GAME_DIR( gamedir );
|
||||
sprintf( dllpath, "%s/bin/%s", gamedir, dllname );
|
||||
dllhandle = LoadLibrary( dllpath );
|
||||
dllhandle = (dllhandle_t)LOAD_LIBRARY( dllname );
|
||||
|
||||
// No DLL found
|
||||
if( !dllhandle ) return false;
|
||||
|
||||
// Get the function adresses
|
||||
for( gamefunc = fcts; gamefunc && gamefunc->name != NULL; gamefunc++ )
|
||||
{
|
||||
if(!( *gamefunc->funcvariable = (void *) Sys_GetProcAddress( dllhandle, gamefunc->name )))
|
||||
{
|
||||
Sys_UnloadLibrary( &dllhandle );
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ALERT( at_loading, "%s loaded succesfully!\n", dllname );
|
||||
*handle = dllhandle;
|
||||
return true;
|
||||
|
@ -654,13 +653,13 @@ void Sys_UnloadLibrary( dllhandle_t *handle )
|
|||
if( handle == NULL || *handle == NULL )
|
||||
return;
|
||||
|
||||
FreeLibrary( *handle );
|
||||
FREE_LIBRARY( *handle );
|
||||
*handle = NULL;
|
||||
}
|
||||
|
||||
void* Sys_GetProcAddress( dllhandle_t handle, const char* name )
|
||||
{
|
||||
return (void *)GetProcAddress( handle, name );
|
||||
return (void *)GET_PROC_ADDRESS( handle, name );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -130,6 +130,9 @@ typedef struct cl_enginefuncs_s
|
|||
byte* (*pfnLoadFile)( const char *filename, int *pLength );
|
||||
int (*pfnFileExists)( const char *filename );
|
||||
void (*pfnGetGameDir)( char *szGetGameDir );
|
||||
void* (*pfnLoadLibrary)( const char *name );
|
||||
void* (*pfnGetProcAddress)( void *hInstance, const char *name );
|
||||
void (*pfnFreeLibrary)( void *hInstance );
|
||||
void (*pfnHostError)( const char *szFmt, ... ); // invoke host error
|
||||
|
||||
struct triapi_s *pTriAPI;
|
||||
|
|
|
@ -72,5 +72,5 @@ if exist xtools\xtools.plg del /f /q xtools\xtools.plg
|
|||
echo Build succeeded!
|
||||
echo Please wait. Xash is now loading
|
||||
cd D:\Xash3D\
|
||||
quake.exe -game tmpQuArK -log -debug -dev 3 +map qctest
|
||||
quake.exe -game tmpQuArK -log -debug -dev 3 +map dm_knot
|
||||
:done
|
|
@ -1007,6 +1007,43 @@ const char *CL_GetString( string_t iString )
|
|||
return StringTable_GetString( clgame.hStringTable, iString );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_LoadLibrary
|
||||
|
||||
=============
|
||||
*/
|
||||
static void *CL_LoadLibrary( const char *name )
|
||||
{
|
||||
string libpath;
|
||||
|
||||
Com_BuildPath( name, libpath );
|
||||
return Com_LoadLibrary( libpath );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_GetProcAddress
|
||||
|
||||
=============
|
||||
*/
|
||||
static void *CL_GetProcAddress( void *hInstance, const char *name )
|
||||
{
|
||||
if( !hInstance ) return NULL;
|
||||
return Com_GetProcAddress( hInstance, name );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_FreeLibrary
|
||||
|
||||
=============
|
||||
*/
|
||||
static void CL_FreeLibrary( void *hInstance )
|
||||
{
|
||||
Com_FreeLibrary( hInstance );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
pfnFindExplosionPlane
|
||||
|
@ -1147,6 +1184,9 @@ static cl_enginefuncs_t gEngfuncs =
|
|||
pfnLoadFile,
|
||||
pfnFileExists,
|
||||
pfnGetGameDir,
|
||||
CL_LoadLibrary,
|
||||
CL_GetProcAddress,
|
||||
CL_FreeLibrary,
|
||||
Host_Error,
|
||||
&gTriApi,
|
||||
&gEfxApi
|
||||
|
@ -1178,18 +1218,18 @@ void CL_UnloadProgs( void )
|
|||
bool CL_LoadProgs( const char *name )
|
||||
{
|
||||
static CLIENTAPI GetClientAPI;
|
||||
string libname;
|
||||
string libpath;
|
||||
edict_t *e;
|
||||
int i;
|
||||
|
||||
if( cls.game ) CL_UnloadProgs();
|
||||
|
||||
// fill it in
|
||||
com.snprintf( libname, MAX_STRING, "bin/%s.dll", name );
|
||||
Com_BuildPath( name, libpath );
|
||||
cls.mempool = Mem_AllocPool( "Client Edicts Zone" );
|
||||
cls.private = Mem_AllocPool( "Client Private Zone" );
|
||||
|
||||
cls.game = Com_LoadLibrary( libname );
|
||||
cls.game = Com_LoadLibrary( libpath );
|
||||
if( !cls.game ) return false;
|
||||
|
||||
GetClientAPI = (CLIENTAPI)Com_GetProcAddress( cls.game, "CreateAPI" );
|
||||
|
|
|
@ -160,7 +160,6 @@ float pfnRandomFloat( float flLow, float flHigh );
|
|||
void pfnAlertMessage( ALERT_TYPE level, char *szFmt, ... );
|
||||
void pfnGetGameDir( char *szGetGameDir );
|
||||
|
||||
char *ED_NewString( const char *string, byte *mempool );
|
||||
#define prog vm->prog // global callback to vprogs.dll
|
||||
#define PRVM_EDICT_NUM( num ) _PRVM_EDICT_NUM( num, __FILE__, __LINE__ )
|
||||
|
||||
|
@ -335,7 +334,8 @@ enum e_trace
|
|||
|
||||
extern byte *zonepool;
|
||||
|
||||
#define Z_Malloc(size) Mem_Alloc( zonepool, size )
|
||||
#define Z_Malloc(size) Mem_Alloc( zonepool, size )
|
||||
#define Z_Realloc( ptr, size ) Mem_Realloc( zonepool, ptr, size )
|
||||
void CL_GetEntitySoundSpatialization( int ent, vec3_t origin, vec3_t velocity );
|
||||
bool SV_GetComment( char *comment, int savenum );
|
||||
int CL_PMpointcontents( vec3_t point );
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2008 ©
|
||||
// com_edict.c - generic edict manager
|
||||
//=======================================================================
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
=============
|
||||
ED_NewString
|
||||
|
||||
FIXME: hashtable ?
|
||||
=============
|
||||
*/
|
||||
char *ED_NewString( const char *string, byte *mempool )
|
||||
{
|
||||
char *data, *data_p;
|
||||
int i, l;
|
||||
|
||||
l = com.strlen( string ) + 1;
|
||||
data = Mem_Alloc( mempool, l );
|
||||
data_p = data;
|
||||
|
||||
for( i = 0; i < l; i++ )
|
||||
{
|
||||
if( string[i] == '\\' && i < l - 1 )
|
||||
{
|
||||
i++;
|
||||
if( string[i] == 'n' )
|
||||
*data_p++ = '\n';
|
||||
else *data_p++ = '\\';
|
||||
}
|
||||
else *data_p++ = string[i];
|
||||
}
|
||||
return data;
|
||||
}
|
|
@ -6,11 +6,14 @@
|
|||
#include "common.h"
|
||||
#include "com_library.h"
|
||||
|
||||
// FIXME: broken code
|
||||
//#define EXPORT_FROM_MEMORY
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PIMAGE_NT_HEADERS headers;
|
||||
byte *codeBase;
|
||||
HMODULE *modules;
|
||||
void **modules;
|
||||
int numModules;
|
||||
int initialized;
|
||||
} MEMORYMODULE, *PMEMORYMODULE;
|
||||
|
@ -51,6 +54,30 @@ static void CopySections( const byte *data, PIMAGE_NT_HEADERS old_headers, PMEMO
|
|||
}
|
||||
}
|
||||
|
||||
static void FreeSections( PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module )
|
||||
{
|
||||
int i, size;
|
||||
byte *codeBase = module->codeBase;
|
||||
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
|
||||
|
||||
for( i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++ )
|
||||
{
|
||||
if( section->SizeOfRawData == 0 )
|
||||
{
|
||||
size = old_headers->OptionalHeader.SectionAlignment;
|
||||
if( size > 0 )
|
||||
{
|
||||
VirtualFree( codeBase + section->VirtualAddress, size, MEM_DECOMMIT );
|
||||
section->Misc.PhysicalAddress = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
VirtualFree( codeBase + section->VirtualAddress, section->SizeOfRawData, MEM_DECOMMIT );
|
||||
section->Misc.PhysicalAddress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Protection flags for memory pages (Executable, Readable, Writeable)
|
||||
static int ProtectionFlags[2][2][2] =
|
||||
{
|
||||
|
@ -66,8 +93,8 @@ static int ProtectionFlags[2][2][2] =
|
|||
|
||||
static void FinalizeSections( MEMORYMODULE *module )
|
||||
{
|
||||
int i;
|
||||
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION( module->headers );
|
||||
int i;
|
||||
|
||||
// loop through all sections and change access flags
|
||||
for( i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++ )
|
||||
|
@ -100,13 +127,10 @@ static void FinalizeSections( MEMORYMODULE *module )
|
|||
}
|
||||
|
||||
if( size > 0 )
|
||||
{
|
||||
{
|
||||
// change memory access flags
|
||||
if( !VirtualProtect((LPVOID)section->Misc.PhysicalAddress, section->SizeOfRawData, protect, &oldProtect ))
|
||||
#ifdef _DEBUG
|
||||
Sys_Break( "Error protecting memory page\n" )
|
||||
#endif
|
||||
;
|
||||
if( !VirtualProtect((LPVOID)section->Misc.PhysicalAddress, size, protect, &oldProtect ))
|
||||
Host_Error( "Com_FinalizeSections: error protecting memory page\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,19 +194,26 @@ static int BuildImportTable( MEMORYMODULE *module )
|
|||
for( ; !IsBadReadPtr( importDesc, sizeof( IMAGE_IMPORT_DESCRIPTOR )) && importDesc->Name; importDesc++ )
|
||||
{
|
||||
DWORD *thunkRef, *funcRef;
|
||||
HMODULE handle = LoadLibrary((LPCSTR)CALCULATE_ADDRESS(codeBase, importDesc->Name));
|
||||
void *handle;
|
||||
|
||||
// FIXME: allow to loading libraries from memory
|
||||
if( handle == INVALID_HANDLE_VALUE )
|
||||
#ifdef EXPORT_FROM_MEMORY
|
||||
char libpath[MAX_SYSPATH];
|
||||
|
||||
FS_AllowDirectPaths( true );
|
||||
Com_BuildPath((LPCSTR)CALCULATE_ADDRESS(codeBase, importDesc->Name), libpath );
|
||||
handle = Com_LoadLibrary( libpath );
|
||||
FS_AllowDirectPaths( false );
|
||||
#else
|
||||
handle = LoadLibrary((LPCSTR)CALCULATE_ADDRESS(codeBase, importDesc->Name));
|
||||
#endif
|
||||
if( handle == NULL )
|
||||
{
|
||||
#if DEBUG_OUTPUT
|
||||
Sys_Break( "Can't load library\n" );
|
||||
#endif
|
||||
MsgDev( D_ERROR, "couldn't load library\n" );
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
module->modules = (HMODULE *)realloc( module->modules, (module->numModules + 1) * (sizeof( HMODULE )));
|
||||
module->modules = (void *)Z_Realloc( module->modules, (module->numModules + 1) * (sizeof( void* )));
|
||||
if( module->modules == NULL )
|
||||
{
|
||||
result = 0;
|
||||
|
@ -204,11 +235,21 @@ static int BuildImportTable( MEMORYMODULE *module )
|
|||
for( ; *thunkRef; thunkRef++, funcRef++ )
|
||||
{
|
||||
if( IMAGE_SNAP_BY_ORDINAL( *thunkRef ))
|
||||
{
|
||||
#ifdef EXPORT_FROM_MEMORY
|
||||
*funcRef = (DWORD)Com_GetProcAddress( handle, (LPCSTR)IMAGE_ORDINAL( *thunkRef ));
|
||||
#else
|
||||
*funcRef = (DWORD)GetProcAddress( handle, (LPCSTR)IMAGE_ORDINAL( *thunkRef ));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)CALCULATE_ADDRESS( codeBase, *thunkRef );
|
||||
#ifdef EXPORT_FROM_MEMORY
|
||||
*funcRef = (DWORD)Com_GetProcAddress( handle, (LPCSTR)&thunkData->Name );
|
||||
#else
|
||||
*funcRef = (DWORD)GetProcAddress( handle, (LPCSTR)&thunkData->Name );
|
||||
#endif
|
||||
}
|
||||
if( *funcRef == 0 )
|
||||
{
|
||||
|
@ -239,20 +280,16 @@ void *Com_LoadLibrary( const char *name )
|
|||
dos_header = (PIMAGE_DOS_HEADER)data;
|
||||
if( dos_header->e_magic != IMAGE_DOS_SIGNATURE )
|
||||
{
|
||||
MsgDev( D_NOTE, "%s it's not a valid executable file\n", name );
|
||||
Mem_Free( data );
|
||||
#if _DEBUG
|
||||
Sys_Break( "Not a valid executable file.\n" );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
old_header = (PIMAGE_NT_HEADERS)&((const byte *)(data))[dos_header->e_lfanew];
|
||||
if( old_header->Signature != IMAGE_NT_SIGNATURE )
|
||||
{
|
||||
MsgDev( D_NOTE, "library %s: no PE header found\n", name );
|
||||
Mem_Free( data );
|
||||
#if _DEBUG
|
||||
Sys_Break( "No PE header found.\n" );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -266,10 +303,8 @@ void *Com_LoadLibrary( const char *name )
|
|||
}
|
||||
if( code == NULL )
|
||||
{
|
||||
MsgDev( D_NOTE, "library %s: can't reserve memory\n", name );
|
||||
Mem_Free( data );
|
||||
#if _DEBUG
|
||||
Sys_Break( "Can't reserve memory\n" );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -313,9 +348,7 @@ void *Com_LoadLibrary( const char *name )
|
|||
DllEntry = (DllEntryProc)CALCULATE_ADDRESS( code, result->headers->OptionalHeader.AddressOfEntryPoint );
|
||||
if( DllEntry == 0 )
|
||||
{
|
||||
#if _DEBUG
|
||||
Sys_Break( "Library has no entry point.\n" );
|
||||
#endif
|
||||
MsgDev( D_NOTE, "library %s: has no entry point\n", name );
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -323,9 +356,7 @@ void *Com_LoadLibrary( const char *name )
|
|||
successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0 );
|
||||
if( !successfull )
|
||||
{
|
||||
#if _DEBUG
|
||||
Sys_Break( "Can't attach library.\n" );
|
||||
#endif
|
||||
MsgDev( D_ERROR, "can't attach library %s\n", name );
|
||||
goto error;
|
||||
}
|
||||
result->initialized = 1;
|
||||
|
@ -340,7 +371,7 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void *Com_GetProcAddress( void *module, const char *name )
|
||||
FARPROC Com_GetProcAddress( void *module, const char *name )
|
||||
{
|
||||
int idx = -1;
|
||||
DWORD i, *nameRef;
|
||||
|
@ -396,7 +427,7 @@ void Com_FreeLibrary( void *hInstance )
|
|||
|
||||
if( module != NULL )
|
||||
{
|
||||
if (module->initialized != 0)
|
||||
if( module->initialized != 0 )
|
||||
{
|
||||
// notify library about detaching from process
|
||||
DllEntryProc DllEntry = (DllEntryProc)CALCULATE_ADDRESS( module->codeBase, module->headers->OptionalHeader.AddressOfEntryPoint );
|
||||
|
@ -408,16 +439,47 @@ void Com_FreeLibrary( void *hInstance )
|
|||
{
|
||||
// free previously opened libraries
|
||||
for( i = 0; i < module->numModules; i++ )
|
||||
if( module->modules[i] != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
if( module->modules[i] != NULL )
|
||||
{
|
||||
#ifdef EXPORT_FROM_MEMORY
|
||||
Com_FreeLibrary( module->modules[i] );
|
||||
#else
|
||||
FreeLibrary( module->modules[i] );
|
||||
free( module->modules ); // realloc end
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Mem_Free( module->modules ); // Z_Realloc end
|
||||
}
|
||||
|
||||
FreeSections( module->headers, module );
|
||||
|
||||
if( module->codeBase != NULL )
|
||||
{
|
||||
// release memory of library
|
||||
VirtualFree(module->codeBase, 0, MEM_RELEASE);
|
||||
VirtualFree( module->codeBase, 0, MEM_RELEASE );
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, module );
|
||||
}
|
||||
}
|
||||
|
||||
void Com_BuildPathExt( const char *dllname, char *fullpath, size_t size )
|
||||
{
|
||||
string name;
|
||||
|
||||
if( !dllname || !fullpath || size <= 0 ) return;
|
||||
|
||||
// only libraries with extension .dll are valid
|
||||
com.strncpy( name, dllname, sizeof( string ));
|
||||
FS_FileBase( name, name );
|
||||
|
||||
// game path (Xash3D/game/bin/)
|
||||
com.snprintf( fullpath, size, "bin/%s.dll", name );
|
||||
if( FS_FileExists( fullpath )) return; // found
|
||||
|
||||
// absoulte path (Xash3D/bin/)
|
||||
com.snprintf( fullpath, size, "%s.dll", name );
|
||||
if( FS_FileExists( fullpath )) return; // found
|
||||
|
||||
fullpath[0] = 0;
|
||||
}
|
|
@ -123,7 +123,9 @@ typedef struct
|
|||
} EXPORT_DIRECTORY;
|
||||
|
||||
void *Com_LoadLibrary( const char *name );
|
||||
void *Com_GetProcAddress( void *hInstance, const char *name );
|
||||
FARPROC Com_GetProcAddress( void *hInstance, const char *name );
|
||||
void Com_FreeLibrary( void *hInstance );
|
||||
void Com_BuildPathExt( const char *dllname, char *fullpath, size_t size );
|
||||
#define Com_BuildPath( a, b ) Com_BuildPathExt( a, b, sizeof( b ))
|
||||
|
||||
#endif//COM_LIBRARY
|
|
@ -1,289 +1,457 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// net_msg.h - message io functions
|
||||
// Copyright XashXT Group 2008 ©
|
||||
// com_library.c - custom dlls loader
|
||||
//=======================================================================
|
||||
#ifndef NET_MSG_H
|
||||
#define NET_MSG_H
|
||||
|
||||
enum net_types_e
|
||||
#include "common.h"
|
||||
#include "com_library.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NET_BAD = 0,
|
||||
NET_CHAR,
|
||||
NET_BYTE,
|
||||
NET_SHORT,
|
||||
NET_WORD,
|
||||
NET_LONG,
|
||||
NET_FLOAT,
|
||||
NET_ANGLE,
|
||||
NET_SCALE,
|
||||
NET_COORD,
|
||||
NET_COLOR,
|
||||
NET_INT64,
|
||||
NET_DOUBLE,
|
||||
NET_TYPES,
|
||||
PIMAGE_NT_HEADERS headers;
|
||||
byte *codeBase;
|
||||
HMODULE *modules;
|
||||
int numModules;
|
||||
int initialized;
|
||||
} MEMORYMODULE, *PMEMORYMODULE;
|
||||
|
||||
typedef BOOL (WINAPI *DllEntryProc)( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved );
|
||||
|
||||
#define GET_HEADER_DICTIONARY( module, idx ) &(module)->headers->OptionalHeader.DataDirectory[idx]
|
||||
#define CALCULATE_ADDRESS( base, offset ) (((DWORD)(base)) + (offset))
|
||||
|
||||
static void CopySections( const byte *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module )
|
||||
{
|
||||
int i, size;
|
||||
byte *dest;
|
||||
byte *codeBase = module->codeBase;
|
||||
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
|
||||
|
||||
for( i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++ )
|
||||
{
|
||||
if( section->SizeOfRawData == 0 )
|
||||
{
|
||||
// section doesn't contain data in the dll itself, but may define
|
||||
// uninitialized data
|
||||
size = old_headers->OptionalHeader.SectionAlignment;
|
||||
if( size > 0 )
|
||||
{
|
||||
dest = (byte *)VirtualAlloc((byte *)CALCULATE_ADDRESS(codeBase, section->VirtualAddress), size, MEM_COMMIT, PAGE_READWRITE );
|
||||
section->Misc.PhysicalAddress = (DWORD)dest;
|
||||
Mem_Set( dest, 0, size );
|
||||
}
|
||||
// section is empty
|
||||
continue;
|
||||
}
|
||||
|
||||
// commit memory block and copy data from dll
|
||||
dest = (byte *)VirtualAlloc((byte *)CALCULATE_ADDRESS(codeBase, section->VirtualAddress), section->SizeOfRawData, MEM_COMMIT, PAGE_READWRITE );
|
||||
Mem_Copy( dest, (byte *)CALCULATE_ADDRESS(data, section->PointerToRawData), section->SizeOfRawData );
|
||||
section->Misc.PhysicalAddress = (DWORD)dest;
|
||||
}
|
||||
}
|
||||
|
||||
static void FreeSections( PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module )
|
||||
{
|
||||
int i, size;
|
||||
byte *codeBase = module->codeBase;
|
||||
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
|
||||
|
||||
for( i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++ )
|
||||
{
|
||||
if( section->SizeOfRawData == 0 )
|
||||
{
|
||||
size = old_headers->OptionalHeader.SectionAlignment;
|
||||
if( size > 0 )
|
||||
{
|
||||
VirtualFree( codeBase + section->VirtualAddress, size, MEM_DECOMMIT );
|
||||
section->Misc.PhysicalAddress = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
VirtualFree( codeBase + section->VirtualAddress, section->SizeOfRawData, MEM_DECOMMIT );
|
||||
section->Misc.PhysicalAddress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Protection flags for memory pages (Executable, Readable, Writeable)
|
||||
static int ProtectionFlags[2][2][2] =
|
||||
{
|
||||
{
|
||||
{ PAGE_NOACCESS, PAGE_WRITECOPY }, // not executable
|
||||
{ PAGE_READONLY, PAGE_READWRITE },
|
||||
},
|
||||
{
|
||||
{ PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY }, // executable
|
||||
{ PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE },
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct net_desc_s
|
||||
static void FinalizeSections( MEMORYMODULE *module )
|
||||
{
|
||||
int type; // pixelformat
|
||||
char name[8]; // used for debug
|
||||
int min_range;
|
||||
int max_range;
|
||||
} net_desc_t;
|
||||
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION( module->headers );
|
||||
int i;
|
||||
|
||||
// loop through all sections and change access flags
|
||||
for( i = 0; i < module->headers->FileHeader.NumberOfSections; i++, section++ )
|
||||
{
|
||||
DWORD protect, oldProtect, size;
|
||||
int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
|
||||
int readable = (section->Characteristics & IMAGE_SCN_MEM_READ) != 0;
|
||||
int writeable = (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
|
||||
|
||||
// communication state description
|
||||
typedef struct net_field_s
|
||||
if( section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE )
|
||||
{
|
||||
// section is not needed any more and can safely be freed
|
||||
VirtualFree((LPVOID)section->Misc.PhysicalAddress, section->SizeOfRawData, MEM_DECOMMIT);
|
||||
continue;
|
||||
}
|
||||
|
||||
// determine protection flags based on characteristics
|
||||
protect = ProtectionFlags[executable][readable][writeable];
|
||||
if( section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED )
|
||||
protect |= PAGE_NOCACHE;
|
||||
|
||||
// determine size of region
|
||||
size = section->SizeOfRawData;
|
||||
if( size == 0 )
|
||||
{
|
||||
if( section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA )
|
||||
size = module->headers->OptionalHeader.SizeOfInitializedData;
|
||||
else if( section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA )
|
||||
size = module->headers->OptionalHeader.SizeOfUninitializedData;
|
||||
}
|
||||
|
||||
if( size > 0 )
|
||||
{
|
||||
// change memory access flags
|
||||
if( !VirtualProtect((LPVOID)section->Misc.PhysicalAddress, size, protect, &oldProtect ))
|
||||
Host_Error( "Com_FinalizeSections: error protecting memory page\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PerformBaseRelocation( MEMORYMODULE *module, DWORD delta )
|
||||
{
|
||||
char *name;
|
||||
int offset;
|
||||
int bits;
|
||||
bool force; // will be send for newentity
|
||||
} net_field_t;
|
||||
DWORD i;
|
||||
byte *codeBase = module->codeBase;
|
||||
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY( module, IMAGE_DIRECTORY_ENTRY_BASERELOC );
|
||||
|
||||
// server to client
|
||||
enum svc_ops_e
|
||||
if( directory->Size > 0 )
|
||||
{
|
||||
PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION)CALCULATE_ADDRESS( codeBase, directory->VirtualAddress );
|
||||
for( ; relocation->VirtualAddress > 0; )
|
||||
{
|
||||
byte *dest = (byte *)CALCULATE_ADDRESS( codeBase, relocation->VirtualAddress );
|
||||
word *relInfo = (word *)((byte *)relocation + IMAGE_SIZEOF_BASE_RELOCATION );
|
||||
|
||||
for( i = 0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++ )
|
||||
{
|
||||
DWORD *patchAddrHL;
|
||||
int type, offset;
|
||||
|
||||
// the upper 4 bits define the type of relocation
|
||||
type = *relInfo >> 12;
|
||||
// the lower 12 bits define the offset
|
||||
offset = *relInfo & 0xfff;
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case IMAGE_REL_BASED_ABSOLUTE:
|
||||
// skip relocation
|
||||
break;
|
||||
case IMAGE_REL_BASED_HIGHLOW:
|
||||
// change complete 32 bit address
|
||||
patchAddrHL = (DWORD *)CALCULATE_ADDRESS( dest, offset );
|
||||
*patchAddrHL += delta;
|
||||
break;
|
||||
default:
|
||||
MsgDev( D_ERROR, "PerformBaseRelocation: unknown relocation: %d\n", type );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// advance to next relocation block
|
||||
relocation = (PIMAGE_BASE_RELOCATION)CALCULATE_ADDRESS( relocation, relocation->SizeOfBlock );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int BuildImportTable( MEMORYMODULE *module )
|
||||
{
|
||||
// user messages
|
||||
svc_bad = 0, // don't send!
|
||||
int result=1;
|
||||
byte *codeBase = module->codeBase;
|
||||
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY( module, IMAGE_DIRECTORY_ENTRY_IMPORT );
|
||||
|
||||
// engine messages
|
||||
svc_nop = 201, // end of user messages
|
||||
svc_disconnect, // kick client from server
|
||||
svc_reconnect, // reconnecting server request
|
||||
svc_stufftext, // [string] stuffed into client's console buffer, should be \n terminated
|
||||
svc_serverdata, // [long] protocol ...
|
||||
svc_configstring, // [short] [string]
|
||||
svc_spawnbaseline, // valid only at spawn
|
||||
svc_download, // [short] size [size bytes]
|
||||
svc_playerinfo, // [...]
|
||||
svc_packetentities, // [...]
|
||||
svc_deltapacketentities, // [...]
|
||||
svc_frame, // server frame
|
||||
svc_sound, // <see code>
|
||||
svc_setangle, // [short short short] set the view angle to this absolute value
|
||||
svc_print, // [byte] id [string] null terminated string
|
||||
};
|
||||
if( directory->Size > 0 )
|
||||
{
|
||||
PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)CALCULATE_ADDRESS( codeBase, directory->VirtualAddress );
|
||||
|
||||
// client to server
|
||||
enum clc_ops_e
|
||||
for( ; !IsBadReadPtr( importDesc, sizeof( IMAGE_IMPORT_DESCRIPTOR )) && importDesc->Name; importDesc++ )
|
||||
{
|
||||
DWORD *thunkRef, *funcRef;
|
||||
HMODULE handle = LoadLibrary((LPCSTR)CALCULATE_ADDRESS(codeBase, importDesc->Name));
|
||||
|
||||
// FIXME: allow to loading libraries from memory
|
||||
if( handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
MsgDev( D_ERROR, "couldn't load library\n" );
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
module->modules = (HMODULE *)Z_Realloc( module->modules, (module->numModules + 1) * (sizeof( HMODULE )));
|
||||
if( module->modules == NULL )
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
module->modules[module->numModules++] = handle;
|
||||
if( importDesc->OriginalFirstThunk )
|
||||
{
|
||||
thunkRef = (DWORD *)CALCULATE_ADDRESS( codeBase, importDesc->OriginalFirstThunk );
|
||||
funcRef = (DWORD *)CALCULATE_ADDRESS( codeBase, importDesc->FirstThunk );
|
||||
}
|
||||
else
|
||||
{
|
||||
// no hint table
|
||||
thunkRef = (DWORD *)CALCULATE_ADDRESS( codeBase, importDesc->FirstThunk );
|
||||
funcRef = (DWORD *)CALCULATE_ADDRESS( codeBase, importDesc->FirstThunk );
|
||||
}
|
||||
for( ; *thunkRef; thunkRef++, funcRef++ )
|
||||
{
|
||||
if IMAGE_SNAP_BY_ORDINAL( *thunkRef )
|
||||
*funcRef = (DWORD)GetProcAddress( handle, (LPCSTR)IMAGE_ORDINAL( *thunkRef ));
|
||||
else
|
||||
{
|
||||
PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)CALCULATE_ADDRESS( codeBase, *thunkRef );
|
||||
*funcRef = (DWORD)GetProcAddress( handle, (LPCSTR)&thunkData->Name );
|
||||
}
|
||||
if( *funcRef == 0 )
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !result ) break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void *Com_LoadLibraryExt( const char *name, bool system )
|
||||
{
|
||||
clc_bad = 0,
|
||||
MEMORYMODULE *result;
|
||||
PIMAGE_DOS_HEADER dos_header;
|
||||
PIMAGE_NT_HEADERS old_header;
|
||||
byte *code, *headers;
|
||||
DWORD locationDelta;
|
||||
DllEntryProc DllEntry;
|
||||
BOOL successfull;
|
||||
void *data;
|
||||
|
||||
// engine messages
|
||||
clc_nop = 201,
|
||||
clc_move, // [[usercmd_t]
|
||||
clc_userinfo, // [[userinfo string]
|
||||
clc_stringcmd, // [string] message
|
||||
};
|
||||
if( system ) FS_AllowDirectPaths( true );
|
||||
data = FS_LoadFile( name, NULL );
|
||||
if( system ) FS_AllowDirectPaths( false );
|
||||
if( !data ) return NULL;
|
||||
|
||||
typedef enum
|
||||
dos_header = (PIMAGE_DOS_HEADER)data;
|
||||
if( dos_header->e_magic != IMAGE_DOS_SIGNATURE )
|
||||
{
|
||||
MsgDev( D_NOTE, "%s it's not a valid executable file\n", name );
|
||||
Mem_Free( data );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
old_header = (PIMAGE_NT_HEADERS)&((const byte *)(data))[dos_header->e_lfanew];
|
||||
if( old_header->Signature != IMAGE_NT_SIGNATURE )
|
||||
{
|
||||
MsgDev( D_NOTE, "library %s: no PE header found\n", name );
|
||||
Mem_Free( data );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// reserve memory for image of library
|
||||
code = (byte *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase), old_header->OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_READWRITE );
|
||||
|
||||
if( code == NULL )
|
||||
{
|
||||
// try to allocate memory at arbitrary position
|
||||
code = (byte *)VirtualAlloc( NULL, old_header->OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_READWRITE );
|
||||
}
|
||||
if( code == NULL )
|
||||
{
|
||||
MsgDev( D_NOTE, "library %s: can't reserve memory\n", name );
|
||||
Mem_Free( data );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = (MEMORYMODULE *)HeapAlloc( GetProcessHeap(), 0, sizeof( MEMORYMODULE ));
|
||||
result->codeBase = code;
|
||||
result->numModules = 0;
|
||||
result->modules = NULL;
|
||||
result->initialized = 0;
|
||||
|
||||
// XXX: is it correct to commit the complete memory region at once?
|
||||
// calling DllEntry raises an exception if we don't...
|
||||
VirtualAlloc( code, old_header->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_READWRITE );
|
||||
|
||||
// commit memory for headers
|
||||
headers = (byte *)VirtualAlloc( code, old_header->OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE );
|
||||
|
||||
// copy PE header to code
|
||||
Mem_Copy( headers, dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders );
|
||||
result->headers = (PIMAGE_NT_HEADERS)&((const byte *)(headers))[dos_header->e_lfanew];
|
||||
|
||||
// update position
|
||||
result->headers->OptionalHeader.ImageBase = (DWORD)code;
|
||||
|
||||
// copy sections from DLL file block to new memory location
|
||||
CopySections( data, old_header, result );
|
||||
|
||||
// adjust base address of imported data
|
||||
locationDelta = (DWORD)(code - old_header->OptionalHeader.ImageBase);
|
||||
if( locationDelta != 0 ) PerformBaseRelocation( result, locationDelta );
|
||||
|
||||
// load required dlls and adjust function table of imports
|
||||
if( !BuildImportTable( result )) goto error;
|
||||
|
||||
// mark memory pages depending on section headers and release
|
||||
// sections that are marked as "discardable"
|
||||
FinalizeSections( result );
|
||||
|
||||
// get entry point of loaded library
|
||||
if( result->headers->OptionalHeader.AddressOfEntryPoint != 0 )
|
||||
{
|
||||
DllEntry = (DllEntryProc)CALCULATE_ADDRESS( code, result->headers->OptionalHeader.AddressOfEntryPoint );
|
||||
if( DllEntry == 0 )
|
||||
{
|
||||
MsgDev( D_NOTE, "library %s: has no entry point\n", name );
|
||||
goto error;
|
||||
}
|
||||
|
||||
// notify library about attaching to process
|
||||
successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0 );
|
||||
if( !successfull )
|
||||
{
|
||||
MsgDev( D_ERROR, "can't attach library %s\n", name );
|
||||
goto error;
|
||||
}
|
||||
result->initialized = 1;
|
||||
}
|
||||
Mem_Free( data ); // release memory
|
||||
|
||||
return (void *)result;
|
||||
error:
|
||||
// cleanup
|
||||
Mem_Free( data );
|
||||
Com_FreeLibrary( result );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FARPROC Com_GetProcAddress( void *module, const char *name )
|
||||
{
|
||||
MSG_ONE = 0, // never send by QC-code (just not declared)
|
||||
MSG_ALL,
|
||||
MSG_PHS,
|
||||
MSG_PVS,
|
||||
MSG_ONE_R, // reliable messages
|
||||
MSG_ALL_R,
|
||||
MSG_PHS_R,
|
||||
MSG_PVS_R,
|
||||
} msgtype_t;
|
||||
int idx = -1;
|
||||
DWORD i, *nameRef;
|
||||
WORD *ordinal;
|
||||
PIMAGE_EXPORT_DIRECTORY exports;
|
||||
byte *codeBase = ((PMEMORYMODULE)module)->codeBase;
|
||||
PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((MEMORYMODULE *)module, IMAGE_DIRECTORY_ENTRY_EXPORT );
|
||||
|
||||
static const net_desc_t NWDesc[] =
|
||||
if( directory->Size == 0 )
|
||||
{
|
||||
// no export table found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
exports = (PIMAGE_EXPORT_DIRECTORY)CALCULATE_ADDRESS( codeBase, directory->VirtualAddress );
|
||||
if( exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0 )
|
||||
{
|
||||
// DLL doesn't export anything
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// search function name in list of exported names
|
||||
nameRef = (DWORD *)CALCULATE_ADDRESS( codeBase, exports->AddressOfNames );
|
||||
ordinal = (WORD *)CALCULATE_ADDRESS( codeBase, exports->AddressOfNameOrdinals );
|
||||
for( i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++ )
|
||||
{
|
||||
// GetProcAddress case insensative ?????
|
||||
if( !com.stricmp( name, (const char *)CALCULATE_ADDRESS( codeBase, *nameRef )))
|
||||
{
|
||||
idx = *ordinal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( idx == -1 )
|
||||
{
|
||||
// exported symbol not found
|
||||
return NULL;
|
||||
}
|
||||
if((DWORD)idx > exports->NumberOfFunctions )
|
||||
{
|
||||
// name <-> ordinal number don't match
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// addressOfFunctions contains the RVAs to the "real" functions
|
||||
return (FARPROC)CALCULATE_ADDRESS( codeBase, *(DWORD *)CALCULATE_ADDRESS( codeBase, exports->AddressOfFunctions + (idx * 4)));
|
||||
}
|
||||
|
||||
void Com_FreeLibrary( void *hInstance )
|
||||
{
|
||||
{ NET_BAD, "none", 0, 0 }, // full range
|
||||
{ NET_CHAR, "Char", -128, 127 },
|
||||
{ NET_BYTE, "Byte", 0, 255 },
|
||||
{ NET_SHORT, "Short", -32767, 32767 },
|
||||
{ NET_WORD, "Word", 0, 65535 },
|
||||
{ NET_LONG, "Long", 0, 0 }, // can't overflow
|
||||
{ NET_FLOAT, "Float", 0, 0 }, // can't overflow
|
||||
{ NET_ANGLE, "Angle", -360, 360 },
|
||||
{ NET_SCALE, "Scale", -128, 127 },
|
||||
{ NET_COORD, "Coord", -262140, 262140 },
|
||||
{ NET_COLOR, "Color", 0, 255 },
|
||||
{ NET_INT64, "int64", 0, 0 }, // can't overflow
|
||||
{ NET_DOUBLE, "Double", 0, 0 }, // can't overflow
|
||||
};
|
||||
MEMORYMODULE *module = (MEMORYMODULE *)hInstance;
|
||||
int i;
|
||||
|
||||
/*
|
||||
==========================================================
|
||||
if( module != NULL )
|
||||
{
|
||||
if( module->initialized != 0 )
|
||||
{
|
||||
// notify library about detaching from process
|
||||
DllEntryProc DllEntry = (DllEntryProc)CALCULATE_ADDRESS( module->codeBase, module->headers->OptionalHeader.AddressOfEntryPoint );
|
||||
(*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0 );
|
||||
module->initialized = 0;
|
||||
}
|
||||
|
||||
ELEMENTS COMMUNICATED ACROSS THE NET
|
||||
if( module->modules != NULL )
|
||||
{
|
||||
// free previously opened libraries
|
||||
for( i = 0; i < module->numModules; i++ )
|
||||
if( module->modules[i] != INVALID_HANDLE_VALUE )
|
||||
FreeLibrary( module->modules[i] );
|
||||
Mem_Free( module->modules ); // Z_Realloc end
|
||||
}
|
||||
|
||||
==========================================================
|
||||
*/
|
||||
FreeSections( module->headers, module );
|
||||
|
||||
#include "entity_state.h"
|
||||
if( module->codeBase != NULL )
|
||||
{
|
||||
// release memory of library
|
||||
VirtualFree( module->codeBase, 0, MEM_RELEASE );
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, module );
|
||||
}
|
||||
}
|
||||
|
||||
#define ES_FIELD( x ) #x,(int)&((entity_state_t*)0)->x
|
||||
#define CM_FIELD( x ) #x,(int)&((usercmd_t*)0)->x
|
||||
|
||||
// config strings are a general means of communication from
|
||||
// the server to all connected clients.
|
||||
// each config string can be at most CS_SIZE characters.
|
||||
#define CS_SIZE 64 // size of one config string
|
||||
#define CS_NAME 0 // map name
|
||||
#define CS_MAPCHECKSUM 1 // level checksum (for catching cheater maps)
|
||||
#define CS_SKYNAME 2 // skybox shader name
|
||||
#define CS_MAXCLIENTS 3 // server maxclients value (0-255)
|
||||
#define CS_BACKGROUND_TRACK 4 // basename of background track
|
||||
#define CS_GRAVITY 5 // sv_gravity
|
||||
#define CS_MAXVELOCITY 6 // sv_maxvelocity
|
||||
|
||||
// reserved config strings
|
||||
|
||||
#define CS_MODELS 16 // configstrings starts here
|
||||
#define CS_SOUNDS (CS_MODELS+MAX_MODELS) // sound names
|
||||
#define CS_DECALS (CS_SOUNDS+MAX_SOUNDS) // server decal indexes
|
||||
#define CS_CLASSNAMES (CS_DECALS+MAX_DECALS) // edicts classnames
|
||||
#define CS_LIGHTSTYLES (CS_CLASSNAMES+MAX_CLASSNAMES) // lightstyle patterns
|
||||
#define CS_USER_MESSAGES (CS_LIGHTSTYLES+MAX_LIGHTSTYLES) // names of user messages
|
||||
#define MAX_CONFIGSTRINGS (CS_USER_MESSAGES+MAX_USER_MESSAGES) // total count
|
||||
|
||||
// sound flags
|
||||
#define SND_VOL (1<<0) // a scaled byte
|
||||
#define SND_ATTN (1<<1) // a byte
|
||||
#define SND_POS (1<<2) // three coordinates
|
||||
#define SND_ENT (1<<3) // a short 0 - 2: channel, 3 - 12: entity
|
||||
#define SND_PITCH (1<<4) // a byte
|
||||
#define SND_STOP (1<<5) // stop sound or loopsound
|
||||
#define SND_CHANGE_VOL (1<<6) // change sound vol
|
||||
#define SND_CHANGE_PITCH (1<<7) // change sound pitch
|
||||
#define SND_SPAWNING (1<<8) // we're spawing, used in some cases for ambients
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
MESSAGE IO FUNCTIONS
|
||||
Handles byte ordering and avoids alignment errors
|
||||
==============================================================================
|
||||
*/
|
||||
void MSG_Init( sizebuf_t *buf, byte *data, size_t length );
|
||||
void MSG_Clear( sizebuf_t *buf );
|
||||
void MSG_Print( sizebuf_t *msg, const char *data );
|
||||
void MSG_Bitstream( sizebuf_t *buf, bool state );
|
||||
void _MSG_WriteBits( sizebuf_t *msg, int64 value, const char *name, int bits, const char *filename, const int fileline );
|
||||
int64 _MSG_ReadBits( sizebuf_t *msg, int bits, const char *filename, const int fileline );
|
||||
void _MSG_Begin( int dest, const char *filename, int fileline );
|
||||
void _MSG_WriteString( sizebuf_t *sb, const char *s, const char *filename, int fileline );
|
||||
void _MSG_WriteFloat( sizebuf_t *sb, float f, const char *filename, int fileline );
|
||||
void _MSG_WriteDouble( sizebuf_t *sb, double f, const char *filename, int fileline );
|
||||
void _MSG_WritePos( sizebuf_t *sb, vec3_t pos, const char *filename, int fileline );
|
||||
void _MSG_WriteData( sizebuf_t *sb, const void *data, size_t length, const char *filename, int fileline );
|
||||
void _MSG_WriteDeltaUsercmd( sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd, const char *filename, const int fileline );
|
||||
void _MSG_WriteDeltaEntity( struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, bool force, bool newentity, const char *filename, int fileline );
|
||||
void _MSG_Send( msgtype_t to, vec3_t origin, edict_t *ent, const char *filename, int fileline );
|
||||
|
||||
#define MSG_Begin( x ) _MSG_Begin( x, __FILE__, __LINE__)
|
||||
#define MSG_WriteChar(x,y) _MSG_WriteBits (x, y, NULL, NET_CHAR, __FILE__, __LINE__)
|
||||
#define MSG_WriteByte(x,y) _MSG_WriteBits (x, y, NULL, NET_BYTE, __FILE__, __LINE__)
|
||||
#define MSG_WriteShort(x,y) _MSG_WriteBits(x, y, NULL, NET_SHORT,__FILE__, __LINE__)
|
||||
#define MSG_WriteWord(x,y) _MSG_WriteBits (x, y, NULL, NET_WORD, __FILE__, __LINE__)
|
||||
#define MSG_WriteLong(x,y) _MSG_WriteBits (x, y, NULL, NET_LONG, __FILE__, __LINE__)
|
||||
#define MSG_WriteFloat(x,y) _MSG_WriteFloat(x, y, __FILE__, __LINE__)
|
||||
#define MSG_WriteDouble(x,y) _MSG_WriteDouble(x, y, __FILE__, __LINE__)
|
||||
#define MSG_WriteString(x,y) _MSG_WriteString (x, y, __FILE__, __LINE__)
|
||||
#define MSG_WriteCoord16(x, y) _MSG_WriteBits(x, y, NULL, NET_COORD, __FILE__, __LINE__)
|
||||
#define MSG_WriteCoord32(x, y) _MSG_WriteBits(x, y, NULL, NET_FLOAT, __FILE__, __LINE__)
|
||||
#define MSG_WriteAngle16(x, y) _MSG_WriteBits(x, y, NULL, NET_ANGLE, __FILE__, __LINE__)
|
||||
#define MSG_WriteAngle32(x, y) _MSG_WriteBits(x, y, NULL, NET_FLOAT, __FILE__, __LINE__)
|
||||
#define MSG_WritePos(x, y) _MSG_WritePos( x, y, __FILE__, __LINE__ )
|
||||
#define MSG_WriteData(x,y,z) _MSG_WriteData (x, y, z, __FILE__, __LINE__)
|
||||
#define MSG_WriteDeltaUsercmd(x, y, z) _MSG_WriteDeltaUsercmd (x, y, z, __FILE__, __LINE__)
|
||||
#define MSG_WriteDeltaEntity(from, to, msg, force, new ) _MSG_WriteDeltaEntity (from, to, msg, force, new, __FILE__, __LINE__)
|
||||
#define MSG_WriteBits( buf, value, name, bits ) _MSG_WriteBits( buf, value, name, bits, __FILE__, __LINE__ )
|
||||
#define MSG_ReadBits( buf, bits ) _MSG_ReadBits( buf, bits, __FILE__, __LINE__ )
|
||||
#define MSG_Send(x, y, z) _MSG_Send(x, y, z, __FILE__, __LINE__)
|
||||
|
||||
void MSG_BeginReading (sizebuf_t *sb);
|
||||
#define MSG_ReadChar( x ) _MSG_ReadBits( x, NET_CHAR, __FILE__, __LINE__ )
|
||||
#define MSG_ReadByte( x ) _MSG_ReadBits( x, NET_BYTE, __FILE__, __LINE__ )
|
||||
#define MSG_ReadShort( x) _MSG_ReadBits( x, NET_SHORT, __FILE__, __LINE__ )
|
||||
#define MSG_ReadWord( x ) _MSG_ReadBits( x, NET_WORD, __FILE__, __LINE__ )
|
||||
#define MSG_ReadLong( x ) _MSG_ReadBits( x, NET_LONG, __FILE__, __LINE__ )
|
||||
#define MSG_ReadAngle16( x ) _MSG_ReadBits( x, NET_ANGLE, __FILE__, __LINE__ )
|
||||
#define MSG_ReadAngle32( x ) _MSG_ReadBits( x, NET_FLOAT, __FILE__, __LINE__ )
|
||||
float MSG_ReadFloat( sizebuf_t *msg );
|
||||
char *MSG_ReadString( sizebuf_t *sb );
|
||||
double MSG_ReadDouble( sizebuf_t *msg );
|
||||
char *MSG_ReadStringLine( sizebuf_t *sb );
|
||||
void MSG_ReadPos( sizebuf_t *sb, vec3_t pos );
|
||||
void MSG_ReadData( sizebuf_t *sb, void *buffer, size_t size );
|
||||
void MSG_ReadDeltaUsercmd( sizebuf_t *sb, usercmd_t *from, usercmd_t *cmd );
|
||||
void MSG_ReadDeltaEntity( sizebuf_t *sb, entity_state_t *from, entity_state_t *to, int number );
|
||||
entity_state_t MSG_ParseDeltaPlayer( entity_state_t *from, entity_state_t *to );
|
||||
void MSG_WriteDeltaPlayerstate( entity_state_t *from, entity_state_t *to, sizebuf_t *msg );
|
||||
void MSG_ReadDeltaPlayerstate( sizebuf_t *msg, entity_state_t *from, entity_state_t *to );
|
||||
|
||||
|
||||
// huffman compression
|
||||
void Huff_Init( void );
|
||||
void Huff_CompressPacket( sizebuf_t *msg, int offset );
|
||||
void Huff_DecompressPacket( sizebuf_t *msg, int offset );
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
NET
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
bool NET_GetLoopPacket( netsrc_t sock, netadr_t *from, sizebuf_t *msg );
|
||||
void NET_SendPacket( netsrc_t sock, int length, void *data, netadr_t to );
|
||||
bool NET_StringToAdr( const char *s, netadr_t *a );
|
||||
bool NET_CompareBaseAdr( netadr_t a, netadr_t b );
|
||||
bool NET_CompareAdr( netadr_t a, netadr_t b );
|
||||
bool NET_IsLocalAddress( netadr_t adr );
|
||||
|
||||
typedef struct netchan_s
|
||||
void Com_BuildPathExt( const char *dllname, char *fullpath, size_t size, bool clearpath )
|
||||
{
|
||||
bool fatal_error;
|
||||
netsrc_t sock;
|
||||
string name;
|
||||
|
||||
int dropped; // between last packet and previous
|
||||
bool compress; // enable huffman compression
|
||||
if( !dllname || !fullpath || size <= 0 ) return;
|
||||
|
||||
int last_received; // for timeouts
|
||||
int last_sent; // for retransmits
|
||||
// only libraries with extension .dll are valid
|
||||
com.strncpy( name, dllname, sizeof( string ));
|
||||
FS_FileBase( name, name );
|
||||
|
||||
netadr_t remote_address;
|
||||
int qport; // qport value to write when transmitting
|
||||
// game path (Xash3D/game/bin/)
|
||||
com.snprintf( fullpath, size, "bin/%s.dll", name );
|
||||
if( FS_FileExists( fullpath )) return; // found
|
||||
|
||||
// sequencing variables
|
||||
int incoming_sequence;
|
||||
int incoming_acknowledged;
|
||||
int incoming_reliable_acknowledged; // single bit
|
||||
// absoulte path (Xash3D/bin/)
|
||||
com.snprintf( fullpath, size, "%s.dll", name );
|
||||
if( FS_FileExists( fullpath )) return; // found
|
||||
|
||||
int incoming_reliable_sequence; // single bit, maintained local
|
||||
|
||||
int outgoing_sequence;
|
||||
int reliable_sequence; // single bit
|
||||
int last_reliable_sequence; // sequence number of last send
|
||||
|
||||
// reliable staging and holding areas
|
||||
sizebuf_t message; // writing buffer to send to server
|
||||
byte message_buf[MAX_MSGLEN-16]; // leave space for header
|
||||
|
||||
// message is copied to this buffer when it is first transfered
|
||||
int reliable_length;
|
||||
byte reliable_buf[MAX_MSGLEN-16]; // unacked reliable message
|
||||
|
||||
} netchan_t;
|
||||
|
||||
#define PROTOCOL_VERSION 36
|
||||
#define PORT_MASTER 27900
|
||||
#define PORT_CLIENT 27901
|
||||
#define PORT_SERVER 27910
|
||||
#define UPDATE_BACKUP 32 // copies of entity_state_t to keep buffered, must be power of two
|
||||
#define UPDATE_MASK (UPDATE_BACKUP - 1)
|
||||
|
||||
void Netchan_Init( void );
|
||||
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport );
|
||||
bool Netchan_NeedReliable( netchan_t *chan );
|
||||
void Netchan_Transmit( netchan_t *chan, int length, byte *data );
|
||||
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data );
|
||||
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, char *format, ... );
|
||||
bool Netchan_Process( netchan_t *chan, sizebuf_t *msg );
|
||||
bool Netchan_CanReliable( netchan_t *chan );
|
||||
|
||||
#endif//NET_MSG_H
|
||||
if( clearpath ) fullpath[0] = 0;
|
||||
}
|
|
@ -162,10 +162,6 @@ SOURCE=.\client\cl_view.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\com_edict.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\com_library.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -3033,7 +3033,7 @@ void SV_LoadProgs( const char *name )
|
|||
{
|
||||
static SERVERAPI GetEntityAPI;
|
||||
static globalvars_t gpGlobals;
|
||||
string libname;
|
||||
string libpath;
|
||||
edict_t *e;
|
||||
int i;
|
||||
|
||||
|
@ -3041,11 +3041,12 @@ void SV_LoadProgs( const char *name )
|
|||
|
||||
// fill it in
|
||||
svgame.globals = &gpGlobals;
|
||||
com.snprintf( libname, MAX_STRING, "bin/%s.dll", name );
|
||||
Com_BuildPath( name, libpath );
|
||||
svgame.mempool = Mem_AllocPool( "Server Edicts Zone" );
|
||||
svgame.private = Mem_AllocPool( "Server Private Zone" );
|
||||
|
||||
svgame.hInstance = Com_LoadLibrary( libname );
|
||||
svgame.hInstance = Com_LoadLibrary( libpath );
|
||||
|
||||
if( !svgame.hInstance )
|
||||
{
|
||||
Host_Error( "SV_LoadProgs: can't initialize server.dll\n" );
|
||||
|
@ -3059,7 +3060,7 @@ void SV_LoadProgs( const char *name )
|
|||
return;
|
||||
}
|
||||
|
||||
if( !Sys_LoadSymbols( va( "bin/%s.dll", name )))
|
||||
if( !Sys_LoadSymbols( libpath ))
|
||||
{
|
||||
Host_Error( "SV_LoadProgs: can't loading export symbols\n" );
|
||||
return;
|
||||
|
|
|
@ -95,7 +95,6 @@ typedef struct pack_s
|
|||
{
|
||||
char filename [MAX_SYSPATH];
|
||||
int handle;
|
||||
int ignorecase;// PK3 ignores case
|
||||
int numfiles;
|
||||
packfile_t *files;
|
||||
} pack_t;
|
||||
|
@ -111,6 +110,7 @@ typedef struct searchpath_s
|
|||
|
||||
byte *fs_mempool;
|
||||
searchpath_t *fs_searchpaths = NULL;
|
||||
searchpath_t fs_directpath; // static direct path
|
||||
|
||||
static void FS_InitMemory( void );
|
||||
const char *FS_FileExtension (const char *in);
|
||||
|
@ -333,7 +333,6 @@ pack_t *FS_LoadPackPK3 (const char *packfile)
|
|||
|
||||
// Create a package structure in memory
|
||||
pack = (pack_t *)Mem_Alloc(fs_mempool, sizeof (pack_t));
|
||||
pack->ignorecase = true; //PK3 ignores case
|
||||
com_strncpy (pack->filename, packfile, sizeof (pack->filename));
|
||||
pack->handle = packhandle;
|
||||
pack->numfiles = eocd.nbentries;
|
||||
|
@ -532,12 +531,9 @@ Add a file to the list of files contained into a package
|
|||
*/
|
||||
static packfile_t* FS_AddFileToPack(const char* name, pack_t* pack, fs_offset_t offset, fs_offset_t packsize, fs_offset_t realsize, int flags)
|
||||
{
|
||||
int (*strcmp_funct) (const char* str1, const char* str2);
|
||||
int left, right, middle;
|
||||
packfile_t *pfile;
|
||||
|
||||
strcmp_funct = pack->ignorecase ? com_stricmp : com_strcmp;
|
||||
|
||||
// Look for the slot we should put that file into (binary search)
|
||||
left = 0;
|
||||
right = pack->numfiles - 1;
|
||||
|
@ -546,7 +542,7 @@ static packfile_t* FS_AddFileToPack(const char* name, pack_t* pack, fs_offset_t
|
|||
int diff;
|
||||
|
||||
middle = (left + right) / 2;
|
||||
diff = strcmp_funct(pack->files[middle].name, name);
|
||||
diff = com.stricmp( pack->files[middle].name, name );
|
||||
|
||||
// If we found the file, there's a problem
|
||||
if (!diff) Msg ("Package %s contains the file %s several times\n", pack->filename, name);
|
||||
|
@ -749,7 +745,6 @@ pack_t *FS_LoadPackPAK(const char *packfile)
|
|||
}
|
||||
|
||||
pack = (pack_t *)Mem_Alloc(fs_mempool, sizeof (pack_t));
|
||||
pack->ignorecase = false; // PAK is case sensitive
|
||||
com_strncpy (pack->filename, packfile, sizeof (pack->filename));
|
||||
pack->handle = packhandle;
|
||||
pack->numfiles = 0;
|
||||
|
@ -825,7 +820,6 @@ pack_t *FS_LoadPackPK2(const char *packfile)
|
|||
}
|
||||
|
||||
pack = (pack_t *)Mem_Alloc(fs_mempool, sizeof (pack_t));
|
||||
pack->ignorecase = false; // PK2 is case sensitive
|
||||
com_strncpy (pack->filename, packfile, sizeof (pack->filename));
|
||||
pack->handle = packhandle;
|
||||
pack->numfiles = 0;
|
||||
|
@ -1231,42 +1225,43 @@ Return true if the path should be rejected due to one of the following:
|
|||
or are just not a good idea for a mod to be using.
|
||||
====================
|
||||
*/
|
||||
int FS_CheckNastyPath (const char *path, bool isgamedir)
|
||||
int FS_CheckNastyPath( const char *path, bool isgamedir )
|
||||
{
|
||||
// all: never allow an empty path, as for gamedir it would access the parent directory and a non-gamedir path it is just useless
|
||||
if (!path[0]) return 2;
|
||||
if( !path[0] ) return 2;
|
||||
|
||||
// Windows: don't allow \ in filenames (windows-only), period.
|
||||
// (on Windows \ is a directory separator, but / is also supported)
|
||||
if (strstr(path, "\\")) return 1; // non-portable
|
||||
if( com.strstr( path, "\\" ) && !fs_ext_path ) return 1; // non-portable
|
||||
|
||||
// Mac: don't allow Mac-only filenames - : is a directory separator
|
||||
// instead of /, but we rely on / working already, so there's no reason to
|
||||
// support a Mac-only path
|
||||
// Amiga and Windows: : tries to go to root of drive
|
||||
if (strstr(path, ":")) return 1; // non-portable attempt to go to root of drive
|
||||
if( com.strstr( path, ":" ) && !fs_ext_path ) return 1; // non-portable attempt to go to root of drive
|
||||
|
||||
// Amiga: // is parent directory
|
||||
if (strstr(path, "//")) return 1; // non-portable attempt to go to parent directory
|
||||
if( com.strstr( path, "//" ) && !fs_ext_path ) return 1; // non-portable attempt to go to parent directory
|
||||
|
||||
// all: don't allow going to parent directory (../ or /../)
|
||||
if (strstr(path, "..") && !fs_ext_path) return 2; // attempt to go outside the game directory
|
||||
if( com.strstr( path, ".." ) && !fs_ext_path ) return 2; // attempt to go outside the game directory
|
||||
|
||||
// Windows and UNIXes: don't allow absolute paths
|
||||
if (path[0] == '/' && !fs_ext_path ) return 2; // attempt to go outside the game directory
|
||||
if( path[0] == '/' && !fs_ext_path ) return 2; // attempt to go outside the game directory
|
||||
|
||||
// all: don't allow . characters before the last slash (it should only be used in filenames, not path elements), this catches all imaginable cases of ./, ../, .../, etc
|
||||
if (com_strchr(path, '.') && !fs_ext_path)
|
||||
// all: don't allow . characters before the last slash (it should only be used in filenames, not path elements),
|
||||
// this catches all imaginable cases of ./, ../, .../, etc
|
||||
if( com.strchr( path, '.' ) && !fs_ext_path )
|
||||
{
|
||||
if (isgamedir) return 2; // gamedir is entirely path elements, so simply forbid . entirely
|
||||
if (com_strchr(path, '.') < com_strrchr(path, '/')) return 2; // possible attempt to go outside the game directory
|
||||
if( isgamedir ) return 2; // gamedir is entirely path elements, so simply forbid . entirely
|
||||
if( com.strchr( path, '.' ) < com.strrchr( path, '/' )) return 2; // possible attempt to go outside the game directory
|
||||
}
|
||||
|
||||
// all: forbid trailing slash on gamedir
|
||||
if (isgamedir && !fs_ext_path && path[com_strlen(path)-1] == '/') return 2;
|
||||
if( isgamedir && !fs_ext_path && path[com.strlen( path )-1] == '/' ) return 2;
|
||||
|
||||
// all: forbid leading dot on any filename for any reason
|
||||
if (strstr(path, "/.") && !fs_ext_path) return 2; // attempt to go outside the game directory
|
||||
if( com.strstr( path, "/." ) && !fs_ext_path ) return 2; // attempt to go outside the game directory
|
||||
|
||||
// after all these checks we're pretty sure it's a / separated filename
|
||||
// and won't do much if any harm
|
||||
|
@ -1518,6 +1513,11 @@ bool FS_GetParmFromCmdLine( char *parm, char *out, size_t size )
|
|||
return true;
|
||||
}
|
||||
|
||||
void FS_AllowDirectPaths( bool enable )
|
||||
{
|
||||
fs_ext_path = enable;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
FS_WriteVariables
|
||||
|
@ -1580,12 +1580,12 @@ Internal function used to create a file_t and open the relevant non-packed file
|
|||
*/
|
||||
static file_t* FS_SysOpen( const char* filepath, const char* mode )
|
||||
{
|
||||
file_t* file;
|
||||
int mod, opt;
|
||||
unsigned int ind;
|
||||
file_t *file;
|
||||
int mod, opt;
|
||||
uint ind;
|
||||
|
||||
// Parse the mode string
|
||||
switch (mode[0])
|
||||
switch( mode[0] )
|
||||
{
|
||||
case 'r':
|
||||
mod = O_RDONLY;
|
||||
|
@ -1600,7 +1600,7 @@ static file_t* FS_SysOpen( const char* filepath, const char* mode )
|
|||
opt = O_CREAT | O_APPEND;
|
||||
break;
|
||||
default:
|
||||
Msg("FS_SysOpen(%s, %s): invalid mode\n", filepath, mode);
|
||||
MsgDev( D_ERROR, "FS_SysOpen(%s, %s): invalid mode\n", filepath, mode );
|
||||
return NULL;
|
||||
}
|
||||
for( ind = 1; mode[ind] != '\0'; ind++ )
|
||||
|
@ -1721,10 +1721,10 @@ bool FS_SysFileExists (const char *path)
|
|||
{
|
||||
int desc;
|
||||
|
||||
desc = open (path, O_RDONLY | O_BINARY);
|
||||
desc = open( path, O_RDONLY|O_BINARY );
|
||||
|
||||
if (desc < 0) return false;
|
||||
close (desc);
|
||||
if( desc < 0 ) return false;
|
||||
close( desc );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1740,8 +1740,9 @@ and the file index in the package if relevant
|
|||
*/
|
||||
static searchpath_t *FS_FindFile( const char *name, int* index, bool quiet )
|
||||
{
|
||||
searchpath_t *search;
|
||||
pack_t *pak;
|
||||
searchpath_t *search;
|
||||
char *pEnvPath;
|
||||
pack_t *pak;
|
||||
|
||||
// search through the path, one element at a time
|
||||
for( search = fs_searchpaths; search; search = search->next )
|
||||
|
@ -1749,11 +1750,9 @@ static searchpath_t *FS_FindFile( const char *name, int* index, bool quiet )
|
|||
// is the element a pak file?
|
||||
if( search->pack )
|
||||
{
|
||||
int (*strcmp_funct) (const char* str1, const char* str2);
|
||||
int left, right, middle;
|
||||
|
||||
pak = search->pack;
|
||||
strcmp_funct = pak->ignorecase ? com_stricmp : com_strcmp;
|
||||
|
||||
// look for the file (binary search)
|
||||
left = 0;
|
||||
|
@ -1763,7 +1762,7 @@ static searchpath_t *FS_FindFile( const char *name, int* index, bool quiet )
|
|||
int diff;
|
||||
|
||||
middle = (left + right) / 2;
|
||||
diff = strcmp_funct(pak->files[middle].name, name);
|
||||
diff = com.stricmp( pak->files[middle].name, name );
|
||||
|
||||
// Found it
|
||||
if( !diff )
|
||||
|
@ -1798,17 +1797,43 @@ static searchpath_t *FS_FindFile( const char *name, int* index, bool quiet )
|
|||
}
|
||||
else
|
||||
{
|
||||
char netpath[MAX_SYSPATH];
|
||||
com_sprintf(netpath, "%s%s", search->filename, name);
|
||||
if (FS_SysFileExists(netpath))
|
||||
char netpath[MAX_SYSPATH];
|
||||
com.sprintf( netpath, "%s%s", search->filename, name );
|
||||
if( FS_SysFileExists( netpath ))
|
||||
{
|
||||
if (!quiet) MsgDev(D_INFO, "FS_FindFile: %s\n", netpath);
|
||||
if (index != NULL) *index = -1;
|
||||
if( !quiet ) MsgDev( D_INFO, "FS_FindFile: %s\n", netpath );
|
||||
if( index != NULL ) *index = -1;
|
||||
return search;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( fs_ext_path && (pEnvPath = getenv( "Path" )))
|
||||
{
|
||||
char netpath[MAX_SYSPATH];
|
||||
|
||||
// clear searchpath
|
||||
search = &fs_directpath;
|
||||
Mem_Set( search, 0, sizeof( searchpath_t ));
|
||||
|
||||
// search for environment path
|
||||
while( pEnvPath )
|
||||
{
|
||||
char *end = com.strchr( pEnvPath, ';' );
|
||||
if( !end ) break;
|
||||
com.strncpy( search->filename, pEnvPath, (end - pEnvPath) + 1 );
|
||||
com.strcat( search->filename, "\\" );
|
||||
com.snprintf( netpath, MAX_SYSPATH, "%s%s", search->filename, name );
|
||||
if( FS_SysFileExists( netpath ))
|
||||
{
|
||||
if( !quiet ) MsgDev( D_INFO, "FS_FindFile: %s\n", netpath );
|
||||
if( index != NULL ) *index = -1;
|
||||
return search;
|
||||
}
|
||||
pEnvPath += (end - pEnvPath) + 1; // move pointer
|
||||
}
|
||||
}
|
||||
|
||||
if( !quiet ) MsgDev( D_WARN, "FS_FindFile: can't find %s\n", name );
|
||||
if( index != NULL ) *index = -1;
|
||||
|
||||
|
@ -1828,7 +1853,7 @@ file_t *FS_OpenReadFile( const char *filename, const char *mode, bool quiet )
|
|||
searchpath_t *search;
|
||||
int pack_ind;
|
||||
|
||||
search = FS_FindFile(filename, &pack_ind, quiet );
|
||||
search = FS_FindFile( filename, &pack_ind, quiet );
|
||||
|
||||
// not found?
|
||||
if( search == NULL )
|
||||
|
@ -1863,21 +1888,21 @@ Open a file. The syntax is the same as fopen
|
|||
*/
|
||||
file_t* _FS_Open( const char* filepath, const char* mode, bool quiet )
|
||||
{
|
||||
if (FS_CheckNastyPath(filepath, false))
|
||||
if( FS_CheckNastyPath( filepath, false ))
|
||||
{
|
||||
MsgDev( D_NOTE, "FS_Open: (\"%s\", \"%s\"): nasty filename rejected\n", filepath, mode );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If the file is opened in "write", "append", or "read/write" mode
|
||||
if (mode[0] == 'w' || mode[0] == 'a' || com_strchr (mode, '+'))
|
||||
// if the file is opened in "write", "append", or "read/write" mode
|
||||
if( mode[0] == 'w' || mode[0] == 'a' || com.strchr( mode, '+' ))
|
||||
{
|
||||
char real_path [MAX_SYSPATH];
|
||||
char real_path[MAX_SYSPATH];
|
||||
|
||||
// Open the file on disk directly
|
||||
com_sprintf (real_path, "%s/%s", fs_gamedir, filepath);
|
||||
FS_CreatePath (real_path);// Create directories up to the file
|
||||
return FS_SysOpen (real_path, mode );
|
||||
// open the file on disk directly
|
||||
com.sprintf( real_path, "%s/%s", fs_gamedir, filepath );
|
||||
FS_CreatePath( real_path );// Create directories up to the file
|
||||
return FS_SysOpen( real_path, mode );
|
||||
}
|
||||
|
||||
// else, we look at the various search paths and open the file in read-only mode
|
||||
|
@ -2365,7 +2390,7 @@ Filename are relative to the xash directory.
|
|||
Always appends a 0 byte.
|
||||
============
|
||||
*/
|
||||
byte *FS_LoadFile (const char *path, fs_offset_t *filesizeptr )
|
||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr )
|
||||
{
|
||||
file_t *file;
|
||||
byte *buf = NULL;
|
||||
|
@ -2468,9 +2493,9 @@ FS_FileExists
|
|||
Look for a file in the packages and in the filesystem
|
||||
==================
|
||||
*/
|
||||
bool FS_FileExists (const char *filename)
|
||||
bool FS_FileExists( const char *filename )
|
||||
{
|
||||
if(FS_FindFile( filename, NULL, true))
|
||||
if( FS_FindFile( filename, NULL, true ))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -313,15 +313,16 @@ void FS_Path( void );
|
|||
void FS_Shutdown( void );
|
||||
void FS_InitEditor( void );
|
||||
void FS_InitRootDir( char *path );
|
||||
void FS_ClearSearchPath (void);
|
||||
void FS_AddGameHierarchy (const char *dir);
|
||||
int FS_CheckParm (const char *parm);
|
||||
void FS_ClearSearchPath( void );
|
||||
void FS_AllowDirectPaths( bool enable );
|
||||
void FS_AddGameHierarchy( const char *dir );
|
||||
int FS_CheckParm( const char *parm );
|
||||
void FS_LoadGameInfo( const char *filename );
|
||||
void FS_FileBase( const char *in, char *out);
|
||||
const char *FS_FileExtension (const char *in);
|
||||
void FS_DefaultExtension (char *path, const char *extension );
|
||||
void FS_FileBase( const char *in, char *out );
|
||||
const char *FS_FileExtension( const char *in );
|
||||
void FS_DefaultExtension( char *path, const char *extension );
|
||||
bool FS_GetParmFromCmdLine( char *parm, char *out, size_t size );
|
||||
void FS_ExtractFilePath(const char* const path, char* dest);
|
||||
void FS_ExtractFilePath( const char* const path, char* dest );
|
||||
void FS_UpdateEnvironmentVariables( void );
|
||||
const char *FS_FileWithoutPath( const char *in );
|
||||
extern char sys_rootdir[];
|
||||
|
|
|
@ -90,6 +90,7 @@ void Sys_GetStdAPI( void )
|
|||
com.Com_InitRootDir = FS_InitRootDir; // init custom rootdir
|
||||
com.Com_LoadGameInfo = FS_LoadGameInfo; // gate game info from script file
|
||||
com.Com_AddGameHierarchy = FS_AddGameHierarchy; // add base directory in search list
|
||||
com.Com_AllowDirectPaths = FS_AllowDirectPaths; // allow direct paths e.g. C:\windows
|
||||
com.Com_CheckParm = FS_CheckParm; // get parm from cmdline
|
||||
com.Com_GetParm = FS_GetParmFromCmdLine; // get filename without path & ext
|
||||
com.Com_FileBase = FS_FileBase; // get filename without path & ext
|
||||
|
|
|
@ -449,6 +449,7 @@ typedef struct stdilib_api_s
|
|||
void (*Com_InitRootDir)( char *path ); // init custom rootdir
|
||||
void (*Com_LoadGameInfo)( const char *filename ); // gate game info from script file
|
||||
void (*Com_AddGameHierarchy)(const char *dir); // add base directory in search list
|
||||
void (*Com_AllowDirectPaths)( bool enable ); // allow direct paths e.g. C:\windows
|
||||
int (*Com_CheckParm)( const char *parm ); // check parm in cmdline
|
||||
bool (*Com_GetParm)( char *parm, char *out, size_t size ); // get parm from cmdline
|
||||
void (*Com_FileBase)(const char *in, char *out); // get filename without path & ext
|
||||
|
@ -712,6 +713,7 @@ filesystem manager
|
|||
#define FS_AddGameHierarchy com.Com_AddGameHierarchy
|
||||
#define FS_LoadGameInfo com.Com_LoadGameInfo
|
||||
#define FS_InitRootDir com.Com_InitRootDir
|
||||
#define FS_AllowDirectPaths com.Com_AllowDirectPaths
|
||||
#define FS_LoadFile com.Com_LoadFile
|
||||
#define FS_Search com.Com_Search
|
||||
#define FS_WriteFile com.Com_WriteFile
|
||||
|
|
|
@ -234,7 +234,7 @@ void R_StudioLoadModel( rmodel_t *mod, const void *buffer )
|
|||
if( !thdr ) return; // there were problems
|
||||
mod->thdr = (dstudiohdr_t *)Mem_Alloc( mod->mempool, LittleLong( thdr->length ));
|
||||
Mem_Copy( mod->thdr, texbuf, LittleLong( thdr->length ));
|
||||
Mem_Free( texbuf );
|
||||
if( texbuf ) Mem_Free( texbuf );
|
||||
}
|
||||
else mod->thdr = mod->phdr; // just make link
|
||||
|
||||
|
|
|
@ -61,8 +61,8 @@ TargetDir=\Xash3D\src_main\temp\server\!release
|
|||
InputPath=\Xash3D\src_main\temp\server\!release\server.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"D:\Xash3D\tmpQuArK\bin\server.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\server.dll "D:\Xash3D\tmpQuArK\bin\server.dll"
|
||||
"D:\Xash3D\bin\server.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\server.dll "D:\Xash3D\bin\server.dll"
|
||||
|
||||
# End Custom Build
|
||||
|
||||
|
@ -101,8 +101,8 @@ TargetDir=\Xash3D\src_main\temp\server\!debug
|
|||
InputPath=\Xash3D\src_main\temp\server\!debug\server.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"D:\Xash3D\tmpQuArK\bin\server.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\server.dll "D:\Xash3D\tmpQuArK\bin\server.dll"
|
||||
"D:\Xash3D\bin\server.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\server.dll "D:\Xash3D\bin\server.dll"
|
||||
|
||||
# End Custom Build
|
||||
|
||||
|
|
2
todo.log
2
todo.log
|
@ -60,6 +60,8 @@ Beta 13.12.08
|
|||
29.dm_knot wrong entities OK
|
||||
30.func_pendulum OK
|
||||
31.weapon_egon & weapon_gauss
|
||||
32.Com_LoadLibrary: searchpaths: game/bin, bin OK
|
||||
33. prepare resources for pak
|
||||
|
||||
|
||||
Список доступных рендереров: Что в них интересного
|
||||
|
|
|
@ -253,13 +253,7 @@ void PRVM_Init( int argc, char **argv )
|
|||
size_t size;
|
||||
byte *image;
|
||||
|
||||
if( !FS_FileExists( "bin/client.dll" ) || !FS_FileExists( "bin/server.dll" ))
|
||||
{
|
||||
image = FS_LoadInternal( "progs.pk3", &size );
|
||||
if( size ) FS_WriteFile( "progs.pk3", image, size );
|
||||
Cmd_ExecuteString( "fs_rescan\n" );
|
||||
}
|
||||
|
||||
// FIXME: get rid of this
|
||||
// dump internal copies of progs into hdd if missing
|
||||
if(!FS_FileExists(va("%s/uimenu.dat", GI->vprogs_dir)))
|
||||
{
|
||||
|
|
Reference in New Issue