This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/launcher/utils.c

405 lines
9.6 KiB
C

//=======================================================================
// Copyright XashXT Group 2007 ©
// utils.c - shared launcher utils
//=======================================================================
#include <time.h>
#include "launcher.h"
#include "basemath.h"
char sys_rootdir[ MAX_SYSPATH ];
bool debug_mode = false;
bool console_read_only = true;
int dev_mode = 0;
/*
====================
Log_Timestamp
====================
*/
const char* Log_Timestamp( void )
{
static char timestamp [128];
time_t crt_time;
const struct tm *crt_tm;
char timestring [64];
// Build the time stamp (ex: "Apr03 2007 [23:31:55]");
time (&crt_time);
crt_tm = localtime (&crt_time);
strftime (timestring, sizeof (timestring), "%b%d %Y [%H:%M:%S]", crt_tm);
strcpy( timestamp, timestring );
return timestamp;
}
float CalcEngineVersion( void )
{
return LAUNCHER_VERSION + COMMON_VERSION + RENDER_VERSION + ENGINE_VERSION;
}
float CalcEditorVersion( void )
{
return LAUNCHER_VERSION + COMMON_VERSION + RENDER_VERSION + EDITOR_VERSION;
}
/*
==================
ParseCommandLine
==================
*/
void ParseCommandLine (LPSTR lpCmdLine)
{
com_argc = 1;
com_argv[0] = "exe";
while (*lpCmdLine && (com_argc < MAX_NUM_ARGVS))
{
while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
lpCmdLine++;
if (*lpCmdLine)
{
com_argv[com_argc] = lpCmdLine;
com_argc++;
while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
lpCmdLine++;
if (*lpCmdLine)
{
*lpCmdLine = 0;
lpCmdLine++;
}
}
}
}
/*
================
CheckParm
Returns the position (1 to argc-1) in the program's argument list
where the given parameter apears, or 0 if not present
================
*/
int CheckParm (const char *parm)
{
int i;
for (i = 1; i < com_argc; i++ )
{
// NEXTSTEP sometimes clears appkit vars.
if (!com_argv[i]) continue;
if (!strcmp (parm, com_argv[i])) return i;
}
return 0;
}
bool _GetParmFromCmdLine( char *parm, char *out, size_t size )
{
int argc = CheckParm( parm );
if(!argc) return false;
if(!out) return false;
strncpy( out, com_argv[argc+1], size );
return true;
}
/*
================
Sys_Sleep
freeze application for some time
================
*/
void Sys_Sleep( int msec)
{
msec = bound(1, msec, 1000 );
Sleep( msec );
}
/*
================
Sys_Exit
NOTE: we must prepare engine to shutdown
before call this
================
*/
void Sys_Exit (void)
{
// prepare host to close
Host_Free();
Sys_FreeLibrary( linked_dll );
Sys_FreeConsole();
exit(sys_error);
}
//=======================================================================
// DLL'S MANAGER SYSTEM
//=======================================================================
bool Sys_LoadLibrary ( dll_info_t *dll )
{
const dllfunc_t *func;
bool native_lib = false;
char errorstring[MAX_QPATH];
// check errors
if(!dll) return false; // invalid desc
if(!dll->name) return false; // nothing to load
if(dll->link) return true; // already loaded
MsgDev(D_ERROR, "Sys_LoadLibrary: Loading %s", dll->name );
if(dll->fcts)
{
// lookup export table
for (func = dll->fcts; func && func->name != NULL; func++)
*func->func = NULL;
}
else if( dll->entry) native_lib = true;
if(!dll->link) dll->link = LoadLibrary ( va("bin/%s", dll->name));
if(!dll->link) dll->link = LoadLibrary ( dll->name ); // environment pathes
// No DLL found
if (!dll->link)
{
sprintf(errorstring, "Sys_LoadLibrary: couldn't load %s\n", dll->name );
goto error;
}
if(native_lib)
{
if((dll->main = Sys_GetProcAddress(dll, dll->entry )) == 0)
{
sprintf(errorstring, "Sys_LoadLibrary: %s has no valid entry point\n", dll->name );
goto error;
}
}
else
{
// Get the function adresses
for(func = dll->fcts; func && func->name != NULL; func++)
{
if (!(*func->func = Sys_GetProcAddress(dll, func->name)))
{
sprintf(errorstring, "Sys_LoadLibrary: %s missing or invalid function (%s)\n", dll->name, func->name );
goto error;
}
}
}
if( native_lib )
{
generic_api_t *check = NULL;
// NOTE: native dlls must support null import!
// e.g. see platform.c for details
check = (void *)dll->main( NULL );
if(!check)
{
sprintf(errorstring, "Sys_LoadLibrary: \"%s\" have no export\n", dll->name );
goto error;
}
if(check->apiversion != dll->apiversion)
{
sprintf(errorstring, "Sys_LoadLibrary: mismatch version (%i should be %i)\n", check->apiversion, dll->apiversion);
goto error;
}
else MsgDev(D_ERROR, " [%d]", check->apiversion );
if(check->api_size != dll->api_size)
{
sprintf(errorstring, "Sys_LoadLibrary: mismatch interface size (%i should be %i)\n", check->api_size, dll->api_size);
goto error;
}
}
MsgDev(D_ERROR, " - ok\n");
return true;
error:
MsgDev(D_ERROR, " - failed\n");
Sys_FreeLibrary ( dll ); // trying to free
if(dll->crash) Sys_Error( errorstring );
else MsgDev( D_INFO, errorstring );
return false;
}
void* Sys_GetProcAddress ( dll_info_t *dll, const char* name )
{
if(!dll || !dll->link) // invalid desc
return NULL;
return (void *)GetProcAddress (dll->link, name);
}
bool Sys_FreeLibrary ( dll_info_t *dll )
{
if(!dll || !dll->link) // invalid desc or alredy freed
return false;
MsgDev(D_ERROR, "Sys_FreeLibrary: Unloading %s\n", dll->name );
FreeLibrary (dll->link);
dll->link = NULL;
return true;
}
void Sys_WaitForQuit( void )
{
MSG msg;
ZeroMemory(&msg, sizeof(msg));
// wait for the user to quit
while(!hooked_out && msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else Sys_Sleep( 20 );
}
}
//=======================================================================
// REGISTRY COMMON TOOLS
//=======================================================================
bool REG_GetValue( HKEY hKey, const char *SubKey, const char *Value, char *pBuffer)
{
dword dwBufLen = 4096;
long lRet;
if(lRet = RegOpenKeyEx( hKey, SubKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS )
return false;
else
{
lRet = RegQueryValueEx( hKey, Value, NULL, NULL, (byte *)pBuffer, &dwBufLen);
if(lRet != ERROR_SUCCESS) return false;
RegCloseKey( hKey );
}
return true;
}
bool REG_SetValue( HKEY hKey, const char *SubKey, const char *Value, char *pBuffer )
{
dword dwBufLen = 4096;
long lRet;
if(lRet = RegOpenKeyEx(hKey, SubKey, 0, KEY_WRITE, &hKey) != ERROR_SUCCESS)
return false;
else
{
lRet = RegSetValueEx(hKey, Value, 0, REG_SZ, (byte *)pBuffer, dwBufLen );
if(lRet != ERROR_SUCCESS) return false;
RegCloseKey(hKey);
}
return true;
}
bool SysFileExists (const char *path)
{
int desc;
desc = open (path, O_RDONLY | O_BINARY);
if (desc < 0) return false;
close (desc);
return true;
}
void GetBaseDir( char *pszBuffer, char *out )
{
char basedir[ MAX_SYSPATH ];
char szBuffer[ MAX_SYSPATH ];
int j;
char *pBuffer = NULL;
strcpy( szBuffer, pszBuffer );
pBuffer = strrchr( szBuffer,'\\' );
if ( pBuffer ) *(pBuffer+1) = '\0';
strcpy( basedir, szBuffer );
j = strlen( basedir );
if (j > 0)
{
if ( ( basedir[ j-1 ] == '\\' ) || ( basedir[ j-1 ] == '/' ) )
{
basedir[ j-1 ] = 0;
}
}
strcpy(out, basedir);
}
void ReadEnvironmentVariables( char *pPath )
{
// get basepath from registry
REG_GetValue(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Session Manager\\Environment", "Xash3D", pPath );
}
void SaveEnvironmentVariables( char *pPath )
{
// save new path
REG_SetValue(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Session Manager\\Environment", "Xash3D", pPath );
SendMessageTimeout( HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_NORMAL, 10, NULL);//system update message
}
static void BuildPath( char *pPath, char *pOut )
{
// set working directory
SetCurrentDirectory ( pPath );
sprintf( pOut, "%s\\bin\\launcher.dll", pPath );
}
void UpdateEnvironmentVariables( void )
{
char szTemp[ 4096 ];
char szPath[ MAX_SYSPATH ]; //test path
//NOTE: we want set "real" work directory
//defined in environment variables, but in some reasons
//we need make some additional checks before set current dir
//get variable from registry and current directory
ReadEnvironmentVariables( szTemp );
GetCurrentDirectory(MAX_SYSPATH, sys_rootdir );
// if both values is math - no run additional tests
if(stricmp(sys_rootdir, szTemp ))
{
// Step1: path from registry have higher priority than current working directory
// because user can execute launcher from random place or from a bat-file
// so, set current working directory as path from registry and test it
BuildPath( szTemp, szPath );
if(!SysFileExists( szPath )) // Step2: engine root dir has been moved to other place?
{
BuildPath( sys_rootdir, szPath );
if(!SysFileExists( szPath )) // Step3: directly execute from bin directory?
{
// Step4: create last test for bin directory
GetBaseDir( sys_rootdir, szTemp );
BuildPath( szTemp, szPath );
if(!SysFileExists( szPath )) //make exception
{
// big bada-boom: engine was moved and launcher running from other place
// step5: so, path form registry is invalid, current path is no valid
Sys_Error("Invalid root directory!\n");
}
else SaveEnvironmentVariables( szTemp );
}
else SaveEnvironmentVariables( sys_rootdir );
}
}
}