22 Jan 2009

This commit is contained in:
g-cont 2009-01-22 00:00:00 +03:00 committed by Alibek Omarov
parent 3975e2034b
commit 539f54b707
24 changed files with 696 additions and 28282 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 );
}
/*

View File

@ -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;

View File

@ -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

View File

@ -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" );

View File

@ -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 );

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View 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;

View File

@ -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;
}

View File

@ -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[];

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
Список доступных рендереров: Что в них интересного

View File

@ -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)))
{