diff options
author | Mikko Tiusanen <ams@daug.net> | 2014-05-04 01:18:52 +0300 |
---|---|---|
committer | Mikko Tiusanen <ams@daug.net> | 2014-05-04 01:18:52 +0300 |
commit | 01beb9919b95479d8be040bec74abc5cc67a5e43 (patch) | |
tree | 65f0b79e793848491832756a4c3a32b23668fab3 /src/sys/sys_win32.c | |
parent | 191d731da136b7ee959a17e63111c9146219a768 (diff) |
Initial import.
Diffstat (limited to 'src/sys/sys_win32.c')
-rw-r--r-- | src/sys/sys_win32.c | 811 |
1 files changed, 811 insertions, 0 deletions
diff --git a/src/sys/sys_win32.c b/src/sys/sys_win32.c new file mode 100644 index 0000000..8ca1bf6 --- /dev/null +++ b/src/sys/sys_win32.c @@ -0,0 +1,811 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2009 Darklegion Development + + +This file is part of Tremulous. + +Tremulous is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Tremulous is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "../qcommon/q_shared.h" +#include "../qcommon/qcommon.h" +#include "sys_local.h" + +#include <windows.h> +#include <lmerr.h> +#include <lmcons.h> +#include <lmwksta.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <direct.h> +#include <io.h> +#include <conio.h> +#include <wincrypt.h> +#include <shlobj.h> +#include <psapi.h> + +// Used to determine where to store user-specific files +static char homePath[ MAX_OSPATH ] = { 0 }; + +#ifndef DEDICATED +static UINT timerResolution = 0; +#endif + +#ifdef __WIN64__ +void Sys_SnapVector( float *v ) +{ + v[0] = rint(v[0]); + v[1] = rint(v[1]); + v[2] = rint(v[2]); +} +#endif + +/* +================ +Sys_DefaultHomePath +================ +*/ +char *Sys_DefaultHomePath( void ) +{ + TCHAR szPath[MAX_PATH]; + FARPROC qSHGetFolderPath; + HMODULE shfolder = LoadLibrary("shfolder.dll"); + + if( !*homePath ) + { + if(shfolder == NULL) + { + Com_Printf("Unable to load SHFolder.dll\n"); + return NULL; + } + + qSHGetFolderPath = GetProcAddress(shfolder, "SHGetFolderPathA"); + if(qSHGetFolderPath == NULL) + { + Com_Printf("Unable to find SHGetFolderPath in SHFolder.dll\n"); + FreeLibrary(shfolder); + return NULL; + } + + if( !SUCCEEDED( qSHGetFolderPath( NULL, CSIDL_APPDATA, + NULL, 0, szPath ) ) ) + { + Com_Printf("Unable to detect CSIDL_APPDATA\n"); + FreeLibrary(shfolder); + return NULL; + } + Q_strncpyz( homePath, szPath, sizeof( homePath ) ); + Q_strcat( homePath, sizeof( homePath ), "\\Tremulous" ); + FreeLibrary(shfolder); + } + + return homePath; +} + +/* +================ +Sys_TempPath +================ +*/ +const char *Sys_TempPath( void ) +{ + static TCHAR path[ MAX_PATH ]; + DWORD length; + + length = GetTempPath( sizeof( path ), path ); + + if( length > sizeof( path ) || length == 0 ) + return Sys_DefaultHomePath( ); + else + return path; +} + +/* +================ +Sys_Milliseconds +================ +*/ +int sys_timeBase; +int Sys_Milliseconds (void) +{ + int sys_curtime; + static qboolean initialized = qfalse; + + if (!initialized) { + sys_timeBase = timeGetTime(); + initialized = qtrue; + } + sys_curtime = timeGetTime() - sys_timeBase; + + return sys_curtime; +} + +#ifndef __GNUC__ //see snapvectora.s +/* +================ +Sys_SnapVector +================ +*/ +void Sys_SnapVector( float *v ) +{ + int i; + float f; + + f = *v; + __asm fld f; + __asm fistp i; + *v = i; + v++; + f = *v; + __asm fld f; + __asm fistp i; + *v = i; + v++; + f = *v; + __asm fld f; + __asm fistp i; + *v = i; +} +#endif + +/* +================ +Sys_RandomBytes +================ +*/ +qboolean Sys_RandomBytes( byte *string, int len ) +{ + HCRYPTPROV prov; + + if( !CryptAcquireContext( &prov, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) ) { + + return qfalse; + } + + if( !CryptGenRandom( prov, len, (BYTE *)string ) ) { + CryptReleaseContext( prov, 0 ); + return qfalse; + } + CryptReleaseContext( prov, 0 ); + return qtrue; +} + +/* +================ +Sys_GetCurrentUser +================ +*/ +char *Sys_GetCurrentUser( void ) +{ + static char s_userName[1024]; + unsigned long size = sizeof( s_userName ); + + if( !GetUserName( s_userName, &size ) ) + strcpy( s_userName, "player" ); + + if( !s_userName[0] ) + { + strcpy( s_userName, "player" ); + } + + return s_userName; +} + +/* +================ +Sys_GetClipboardData +================ +*/ +char *Sys_GetClipboardData( void ) +{ + char *data = NULL; + char *cliptext; + + if ( OpenClipboard( NULL ) != 0 ) { + HANDLE hClipboardData; + + if ( ( hClipboardData = GetClipboardData( CF_TEXT ) ) != 0 ) { + if ( ( cliptext = GlobalLock( hClipboardData ) ) != 0 ) { + data = Z_Malloc( GlobalSize( hClipboardData ) + 1 ); + Q_strncpyz( data, cliptext, GlobalSize( hClipboardData ) ); + GlobalUnlock( hClipboardData ); + + strtok( data, "\n\r\b" ); + } + } + CloseClipboard(); + } + return data; +} + +#define MEM_THRESHOLD 96*1024*1024 + +/* +================== +Sys_LowPhysicalMemory +================== +*/ +qboolean Sys_LowPhysicalMemory( void ) +{ + MEMORYSTATUS stat; + GlobalMemoryStatus (&stat); + return (stat.dwTotalPhys <= MEM_THRESHOLD) ? qtrue : qfalse; +} + +/* +============== +Sys_Basename +============== +*/ +const char *Sys_Basename( char *path ) +{ + static char base[ MAX_OSPATH ] = { 0 }; + int length; + + length = strlen( path ) - 1; + + // Skip trailing slashes + while( length > 0 && path[ length ] == '\\' ) + length--; + + while( length > 0 && path[ length - 1 ] != '\\' ) + length--; + + Q_strncpyz( base, &path[ length ], sizeof( base ) ); + + length = strlen( base ) - 1; + + // Strip trailing slashes + while( length > 0 && base[ length ] == '\\' ) + base[ length-- ] = '\0'; + + return base; +} + +/* +============== +Sys_Dirname +============== +*/ +const char *Sys_Dirname( char *path ) +{ + static char dir[ MAX_OSPATH ] = { 0 }; + int length; + + Q_strncpyz( dir, path, sizeof( dir ) ); + length = strlen( dir ) - 1; + + while( length > 0 && dir[ length ] != '\\' ) + length--; + + dir[ length ] = '\0'; + + return dir; +} + +/* +============== +Sys_Mkdir +============== +*/ +qboolean Sys_Mkdir( const char *path ) +{ + if( !CreateDirectory( path, NULL ) ) + { + if( GetLastError( ) != ERROR_ALREADY_EXISTS ) + return qfalse; + } + + return qtrue; +} + +/* +================== +Sys_Mkfifo +Noop on windows because named pipes do not function the same way +================== +*/ +FILE *Sys_Mkfifo( const char *ospath ) +{ + return NULL; +} + +/* +============== +Sys_Cwd +============== +*/ +char *Sys_Cwd( void ) { + static char cwd[MAX_OSPATH]; + + _getcwd( cwd, sizeof( cwd ) - 1 ); + cwd[MAX_OSPATH-1] = 0; + + return cwd; +} + +/* +============================================================== + +DIRECTORY SCANNING + +============================================================== +*/ + +#define MAX_FOUND_FILES 0x1000 + +/* +============== +Sys_ListFilteredFiles +============== +*/ +void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles ) +{ + char search[MAX_OSPATH], newsubdirs[MAX_OSPATH]; + char filename[MAX_OSPATH]; + intptr_t findhandle; + struct _finddata_t findinfo; + + if ( *numfiles >= MAX_FOUND_FILES - 1 ) { + return; + } + + if (strlen(subdirs)) { + Com_sprintf( search, sizeof(search), "%s\\%s\\*", basedir, subdirs ); + } + else { + Com_sprintf( search, sizeof(search), "%s\\*", basedir ); + } + + findhandle = _findfirst (search, &findinfo); + if (findhandle == -1) { + return; + } + + do { + if (findinfo.attrib & _A_SUBDIR) { + if (Q_stricmp(findinfo.name, ".") && Q_stricmp(findinfo.name, "..")) { + if (strlen(subdirs)) { + Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s\\%s", subdirs, findinfo.name); + } + else { + Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", findinfo.name); + } + Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles ); + } + } + if ( *numfiles >= MAX_FOUND_FILES - 1 ) { + break; + } + Com_sprintf( filename, sizeof(filename), "%s\\%s", subdirs, findinfo.name ); + if (!Com_FilterPath( filter, filename, qfalse )) + continue; + list[ *numfiles ] = CopyString( filename ); + (*numfiles)++; + } while ( _findnext (findhandle, &findinfo) != -1 ); + + _findclose (findhandle); +} + +/* +============== +strgtr +============== +*/ +static qboolean strgtr(const char *s0, const char *s1) +{ + int l0, l1, i; + + l0 = strlen(s0); + l1 = strlen(s1); + + if (l1<l0) { + l0 = l1; + } + + for(i=0;i<l0;i++) { + if (s1[i] > s0[i]) { + return qtrue; + } + if (s1[i] < s0[i]) { + return qfalse; + } + } + return qfalse; +} + +/* +============== +Sys_ListFiles +============== +*/ +char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs ) +{ + char search[MAX_OSPATH]; + int nfiles; + char **listCopy; + char *list[MAX_FOUND_FILES]; + struct _finddata_t findinfo; + intptr_t findhandle; + int flag; + int i; + + if (filter) { + + nfiles = 0; + Sys_ListFilteredFiles( directory, "", filter, list, &nfiles ); + + list[ nfiles ] = 0; + *numfiles = nfiles; + + if (!nfiles) + return NULL; + + listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) ); + for ( i = 0 ; i < nfiles ; i++ ) { + listCopy[i] = list[i]; + } + listCopy[i] = NULL; + + return listCopy; + } + + if ( !extension) { + extension = ""; + } + + // passing a slash as extension will find directories + if ( extension[0] == '/' && extension[1] == 0 ) { + extension = ""; + flag = 0; + } else { + flag = _A_SUBDIR; + } + + Com_sprintf( search, sizeof(search), "%s\\*%s", directory, extension ); + + // search + nfiles = 0; + + findhandle = _findfirst (search, &findinfo); + if (findhandle == -1) { + *numfiles = 0; + return NULL; + } + + do { + if ( (!wantsubs && flag ^ ( findinfo.attrib & _A_SUBDIR )) || (wantsubs && findinfo.attrib & _A_SUBDIR) ) { + if ( nfiles == MAX_FOUND_FILES - 1 ) { + break; + } + list[ nfiles ] = CopyString( findinfo.name ); + nfiles++; + } + } while ( _findnext (findhandle, &findinfo) != -1 ); + + list[ nfiles ] = 0; + + _findclose (findhandle); + + // return a copy of the list + *numfiles = nfiles; + + if ( !nfiles ) { + return NULL; + } + + listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) ); + for ( i = 0 ; i < nfiles ; i++ ) { + listCopy[i] = list[i]; + } + listCopy[i] = NULL; + + do { + flag = 0; + for(i=1; i<nfiles; i++) { + if (strgtr(listCopy[i-1], listCopy[i])) { + char *temp = listCopy[i]; + listCopy[i] = listCopy[i-1]; + listCopy[i-1] = temp; + flag = 1; + } + } + } while(flag); + + return listCopy; +} + +/* +============== +Sys_FreeFileList +============== +*/ +void Sys_FreeFileList( char **list ) +{ + int i; + + if ( !list ) { + return; + } + + for ( i = 0 ; list[i] ; i++ ) { + Z_Free( list[i] ); + } + + Z_Free( list ); +} + + +/* +============== +Sys_Sleep + +Block execution for msec or until input is received. +============== +*/ +void Sys_Sleep( int msec ) +{ + if( msec == 0 ) + return; + +#ifdef DEDICATED + if( msec < 0 ) + WaitForSingleObject( GetStdHandle( STD_INPUT_HANDLE ), INFINITE ); + else + WaitForSingleObject( GetStdHandle( STD_INPUT_HANDLE ), msec ); +#else + // Client Sys_Sleep doesn't support waiting on stdin + if( msec < 0 ) + return; + + Sleep( msec ); +#endif +} + +/* +============== +Sys_ErrorDialog + +Display an error message +============== +*/ +void Sys_ErrorDialog( const char *error ) +{ + if( Sys_Dialog( DT_YES_NO, va( "%s. Copy console log to clipboard?", error ), + "Error" ) == DR_YES ) + { + HGLOBAL memoryHandle; + char *clipMemory; + + memoryHandle = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, CON_LogSize( ) + 1 ); + clipMemory = (char *)GlobalLock( memoryHandle ); + + if( clipMemory ) + { + char *p = clipMemory; + char buffer[ 1024 ]; + unsigned int size; + + while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 ) + { + Com_Memcpy( p, buffer, size ); + p += size; + } + + *p = '\0'; + + if( OpenClipboard( NULL ) && EmptyClipboard( ) ) + SetClipboardData( CF_TEXT, memoryHandle ); + + GlobalUnlock( clipMemory ); + CloseClipboard( ); + } + } +} + +/* +============== +Sys_Dialog + +Display a win32 dialog box +============== +*/ +dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title ) +{ + UINT uType; + + switch( type ) + { + default: + case DT_INFO: uType = MB_ICONINFORMATION|MB_OK; break; + case DT_WARNING: uType = MB_ICONWARNING|MB_OK; break; + case DT_ERROR: uType = MB_ICONERROR|MB_OK; break; + case DT_YES_NO: uType = MB_ICONQUESTION|MB_YESNO; break; + case DT_OK_CANCEL: uType = MB_ICONWARNING|MB_OKCANCEL; break; + } + + switch( MessageBox( NULL, message, title, uType ) ) + { + default: + case IDOK: return DR_OK; + case IDCANCEL: return DR_CANCEL; + case IDYES: return DR_YES; + case IDNO: return DR_NO; + } +} + +#ifndef DEDICATED +static qboolean SDL_VIDEODRIVER_externallySet = qfalse; +#endif + +/* +============== +Sys_GLimpSafeInit + +Windows specific "safe" GL implementation initialisation +============== +*/ +void Sys_GLimpSafeInit( void ) +{ +#ifndef DEDICATED + if( !SDL_VIDEODRIVER_externallySet ) + { + // Here, we want to let SDL decide what do to unless + // explicitly requested otherwise + _putenv( "SDL_VIDEODRIVER=" ); + } +#endif +} + +/* +============== +Sys_GLimpInit + +Windows specific GL implementation initialisation +============== +*/ +void Sys_GLimpInit( void ) +{ +#ifndef DEDICATED + if( !SDL_VIDEODRIVER_externallySet ) + { + // It's a little bit weird having in_mouse control the + // video driver, but from ioq3's point of view they're + // virtually the same except for the mouse input anyway + if( Cvar_VariableIntegerValue( "in_mouse" ) == -1 ) + { + // Use the windib SDL backend, which is closest to + // the behaviour of idq3 with in_mouse set to -1 + _putenv( "SDL_VIDEODRIVER=windib" ); + } + else + { + // Use the DirectX SDL backend + _putenv( "SDL_VIDEODRIVER=directx" ); + } + } +#endif +} + +/* +============== +Sys_PlatformInit + +Windows specific initialisation +============== +*/ +void Sys_PlatformInit( void ) +{ +#ifndef DEDICATED + TIMECAPS ptc; + + const char *SDL_VIDEODRIVER = getenv( "SDL_VIDEODRIVER" ); + + if( SDL_VIDEODRIVER ) + { + Com_Printf( "SDL_VIDEODRIVER is externally set to \"%s\", " + "in_mouse -1 will have no effect\n", SDL_VIDEODRIVER ); + SDL_VIDEODRIVER_externallySet = qtrue; + } + else + SDL_VIDEODRIVER_externallySet = qfalse; + + if(timeGetDevCaps(&ptc, sizeof(ptc)) == MMSYSERR_NOERROR) + { + timerResolution = ptc.wPeriodMin; + + if(timerResolution > 1) + { + Com_Printf("Warning: Minimum supported timer resolution is %ums " + "on this system, recommended resolution 1ms\n", timerResolution); + } + + timeBeginPeriod(timerResolution); + } + else + timerResolution = 0; +#endif +} + +/* +============== +Sys_PlatformExit + +Windows specific initialisation +============== +*/ +void Sys_PlatformExit( void ) +{ +#ifndef DEDICATED + if(timerResolution) + timeEndPeriod(timerResolution); +#endif +} + +/* +============== +Sys_SetEnv + +set/unset environment variables (empty value removes it) +============== +*/ +void Sys_SetEnv(const char *name, const char *value) +{ + if(value) + _putenv(va("%s=%s", name, value)); + else + _putenv(va("%s=", name)); +} + +/* +============== +Sys_PID +============== +*/ +int Sys_PID( void ) +{ + return GetCurrentProcessId( ); +} + +/* +============== +Sys_PIDIsRunning +============== +*/ +qboolean Sys_PIDIsRunning( int pid ) +{ + DWORD processes[ 1024 ]; + DWORD numBytes, numProcesses; + int i; + + if( !EnumProcesses( processes, sizeof( processes ), &numBytes ) ) + return qfalse; // Assume it's not running + + numProcesses = numBytes / sizeof( DWORD ); + + // Search for the pid + for( i = 0; i < numProcesses; i++ ) + { + if( processes[ i ] == pid ) + return qtrue; + } + + return qfalse; +} |