123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "platformWin32/platformWin32.h"
- #include "platformWin32/winConsole.h"
- #include "platformWin32/winDirectInput.h"
- #include "windowManager/win32/win32Window.h"
- #include "console/console.h"
- #include "console/engineAPI.h"
- #include "math/mRandom.h"
- #include "core/stream/fileStream.h"
- #include "T3D/resource.h"
- #include "gfx/gfxInit.h"
- #include "gfx/gfxDevice.h"
- #include "core/strings/unicode.h"
- #include "gui/core/guiCanvas.h"
- extern void createFontInit();
- extern void createFontShutdown();
- extern void installRedBookDevices();
- extern void handleRedBookCallback(U32, U32);
- static MRandomLCG sgPlatRandom;
- static bool sgQueueEvents;
- // is keyboard input a standard (non-changing) VK keycode
- #define dIsStandardVK(c) (((0x08 <= (c)) && ((c) <= 0x12)) || \
- ((c) == 0x1b) || \
- ((0x20 <= (c)) && ((c) <= 0x2e)) || \
- ((0x30 <= (c)) && ((c) <= 0x39)) || \
- ((0x41 <= (c)) && ((c) <= 0x5a)) || \
- ((0x70 <= (c)) && ((c) <= 0x7B)))
- extern InputObjectInstances DIK_to_Key( U8 dikCode );
- // static helper variables
- static HANDLE gMutexHandle = NULL;
- static bool sgDoubleByteEnabled = false;
- // track window states
- Win32PlatState winState;
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- //
- // Microsoft Layer for Unicode
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mslu/winprog/compiling_your_application_with_the_microsoft_layer_for_unicode.asp
- //
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------
- #ifdef UNICODE
- HMODULE LoadUnicowsProc(void)
- {
- return(LoadLibraryA("unicows.dll"));
- }
- #ifdef _cplusplus
- extern "C" {
- #endif
- extern FARPROC _PfnLoadUnicows = (FARPROC) &LoadUnicowsProc;
- #ifdef _cplusplus
- }
- #endif
- #endif
- //--------------------------------------
- Win32PlatState::Win32PlatState()
- {
- log_fp = NULL;
- hinstOpenGL = NULL;
- hinstGLU = NULL;
- hinstOpenAL = NULL;
- appDC = NULL;
- appInstance = NULL;
- currentTime = 0;
- processId = 0;
- }
- //--------------------------------------
- bool Platform::excludeOtherInstances(const char *mutexName)
- {
- #ifdef UNICODE
- UTF16 b[512];
- convertUTF8toUTF16((UTF8 *)mutexName, b);
- gMutexHandle = CreateMutex(NULL, true, b);
- #else
- gMutexHandle = CreateMutex(NULL, true, mutexName);
- #endif
- if(!gMutexHandle)
- return false;
- if(GetLastError() == ERROR_ALREADY_EXISTS)
- {
- CloseHandle(gMutexHandle);
- gMutexHandle = NULL;
- return false;
- }
- return true;
- }
- void Platform::restartInstance()
- {
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- ZeroMemory( &si, sizeof(si) );
- si.cb = sizeof(si);
- ZeroMemory( &pi, sizeof(pi) );
- TCHAR cen_buf[2048];
- GetModuleFileName( NULL, cen_buf, 2047);
- // Start the child process.
- if( CreateProcess( cen_buf,
- NULL, // Command line
- NULL, // Process handle not inheritable
- NULL, // Thread handle not inheritable
- FALSE, // Set handle inheritance to FALSE
- 0, // No creation flags
- NULL, // Use parent's environment block
- NULL, // Use parent's starting directory
- &si, // Pointer to STARTUPINFO structure
- &pi ) // Pointer to PROCESS_INFORMATION structure
- != false )
- {
- WaitForInputIdle( pi.hProcess, 5000 );
- CloseHandle( pi.hProcess );
- CloseHandle( pi.hThread );
- }
- }
- ///just check if the app's global mutex exists, and if so,
- ///return true - otherwise, false. Should be called before ExcludeOther
- /// at very start of app execution.
- bool Platform::checkOtherInstances(const char *mutexName)
- {
- #ifdef TORQUE_MULTITHREAD
- HANDLE pMutex = NULL;
-
- #ifdef UNICODE
- UTF16 b[512];
- convertUTF8toUTF16((UTF8 *)mutexName, b);
- pMutex = CreateMutex(NULL, true, b);
- #else
- pMutex = CreateMutex(NULL, true, mutexName);
- #endif
- if(!pMutex)
- return false;
- if(GetLastError() == ERROR_ALREADY_EXISTS)
- {
- //another mutex of the same name exists
- //close ours
- CloseHandle(pMutex);
- pMutex = NULL;
- return true;
- }
- CloseHandle(pMutex);
- pMutex = NULL;
- #endif
- //we don;t care, always false
- return false;
- }
- #ifndef TORQUE_SDL
- //--------------------------------------
- void Platform::AlertOK(const char *windowTitle, const char *message)
- {
- ShowCursor(true);
- #ifdef UNICODE
- UTF16 m[1024], t[512];
- convertUTF8toUTF16((UTF8 *)windowTitle, t);
- convertUTF8toUTF16((UTF8 *)message, m);
- MessageBox(NULL, m, t, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TASKMODAL | MB_OK);
- #else
- MessageBox(NULL, message, windowTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TASKMODAL | MB_OK);
- #endif
- }
- //--------------------------------------
- bool Platform::AlertOKCancel(const char *windowTitle, const char *message)
- {
- ShowCursor(true);
- #ifdef UNICODE
- UTF16 m[1024], t[512];
- convertUTF8toUTF16((UTF8 *)windowTitle, t);
- convertUTF8toUTF16((UTF8 *)message, m);
- return MessageBox(NULL, m, t, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TASKMODAL | MB_OKCANCEL) == IDOK;
- #else
- return MessageBox(NULL, message, windowTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TASKMODAL | MB_OKCANCEL) == IDOK;
- #endif
- }
- //--------------------------------------
- bool Platform::AlertRetry(const char *windowTitle, const char *message)
- {
- ShowCursor(true);
- #ifdef UNICODE
- UTF16 m[1024], t[512];
- convertUTF8toUTF16((UTF8 *)windowTitle, t);
- convertUTF8toUTF16((UTF8 *)message, m);
- return (MessageBox(NULL, m, t, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TASKMODAL | MB_RETRYCANCEL) == IDRETRY);
- #else
- return (MessageBox(NULL, message, windowTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TASKMODAL | MB_RETRYCANCEL) == IDRETRY);
- #endif
- }
- Platform::ALERT_ASSERT_RESULT Platform::AlertAssert(const char *windowTitle, const char *message)
- {
- #ifndef TORQUE_TOOLS
- ShowCursor(true);
- #endif // TORQUE_TOOLS
- #ifdef UNICODE
- UTF16 messageUTF[1024], title[512];
- convertUTF8toUTF16((UTF8 *)windowTitle, title);
- convertUTF8toUTF16((UTF8 *)message, messageUTF);
- #else
- const char* messageUTF = message;
- const char* title = windowTitle;
- #endif
- // TODO: Change this to a custom dialog that has Exit, Ignore, Ignore All, and Debug buttons
- ALERT_ASSERT_RESULT alertResult = ALERT_ASSERT_DEBUG;
- int result = MessageBox(winState.appWindow, messageUTF, title, MB_ABORTRETRYIGNORE | MB_ICONSTOP | MB_DEFBUTTON2 | MB_TASKMODAL | MB_SETFOREGROUND);
- switch( result )
- {
- case IDABORT:
- alertResult = ALERT_ASSERT_EXIT;
- break;
- case IDIGNORE:
- alertResult = ALERT_ASSERT_IGNORE;
- break;
- default:
- case IDRETRY:
- alertResult = ALERT_ASSERT_DEBUG;
- break;
- }
- return alertResult;
- }
- #endif
- //--------------------------------------
- HIMC gIMEContext;
- static void InitInput()
- {
- #ifndef TORQUE_LIB
- #ifdef UNICODE
- //gIMEContext = ImmGetContext(getWin32WindowHandle());
- //ImmReleaseContext( getWin32WindowHandle(), gIMEContext );
- #endif
- #endif
- }
- //--------------------------------------
- void Platform::init()
- {
- Con::printf("Initializing platform...");
- // Set the platform variable for the scripts
- Con::setVariable( "$platform", "windows" );
- WinConsole::create();
- if ( !WinConsole::isEnabled() )
- Input::init();
- InitInput(); // in case DirectInput falls through
- installRedBookDevices();
- sgDoubleByteEnabled = GetSystemMetrics( SM_DBCSENABLED );
- sgQueueEvents = true;
- Con::printf("Done");
- }
- //--------------------------------------
- void Platform::shutdown()
- {
- sgQueueEvents = false;
- if(gMutexHandle)
- CloseHandle(gMutexHandle);
- Input::destroy();
-
- GFXDevice::destroy();
- WinConsole::destroy();
- }
- extern bool LinkConsoleFunctions;
- #ifndef TORQUE_SHARED
- extern S32 TorqueMain(S32 argc, const char **argv);
- //--------------------------------------
- static S32 run(S32 argc, const char **argv)
- {
- // Console hack to ensure consolefunctions get linked in
- LinkConsoleFunctions=true;
- createFontInit();
- S32 ret = TorqueMain(argc, argv);
- createFontShutdown();
- return ret;
- }
- //--------------------------------------
- S32 main(S32 argc, const char **argv)
- {
- winState.appInstance = GetModuleHandle(NULL);
- return run(argc, argv);
- }
- //--------------------------------------
- #include "app/mainLoop.h"
- S32 WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, S32)
- {
- Vector<char *> argv( __FILE__, __LINE__ );
- enum { moduleNameSize = 256 };
- char moduleName[moduleNameSize];
- #ifdef TORQUE_UNICODE
- {
- TCHAR buf[ moduleNameSize ];
- GetModuleFileNameW( NULL, buf, moduleNameSize );
- convertUTF16toUTF8( buf, moduleName );
- }
- #else
- GetModuleFileNameA(NULL, moduleName, moduleNameSize);
- #endif
- argv.push_back(moduleName);
- for (const char* word,*ptr = lpszCmdLine; *ptr; )
- {
- // Eat white space
- for (; dIsspace(*ptr) && *ptr; ptr++)
- ;
-
- // Pick out the next word
- for (word = ptr; !dIsspace(*ptr) && *ptr; ptr++)
- ;
-
- // Add the word to the argument list.
- if (*word)
- {
- S32 len = ptr - word;
- char *arg = (char *) dMalloc(len + 1);
- dStrncpy(arg, word, len);
- arg[len] = 0;
- argv.push_back(arg);
- }
- }
- winState.appInstance = hInstance;
- S32 retVal = run(argv.size(), (const char **) argv.address());
- for(U32 j = 1; j < argv.size(); j++)
- dFree(argv[j]);
- return retVal;
- }
- #else //TORQUE_SHARED
- extern "C"
- {
- bool torque_engineinit(S32 argc, const char **argv);
- S32 torque_enginetick();
- S32 torque_getreturnstatus();
- bool torque_engineshutdown();
- };
- S32 TorqueMain(int argc, const char **argv)
- {
- if (!torque_engineinit(argc, argv))
- return 1;
- while(torque_enginetick())
- {
- }
- torque_engineshutdown();
- return torque_getreturnstatus();
- }
- extern "C" {
- S32 torque_winmain( HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, S32)
- {
- Vector<char *> argv( __FILE__, __LINE__ );
- enum { moduleNameSize = 256 };
- char moduleName[moduleNameSize];
- #ifdef TORQUE_UNICODE
- {
- TCHAR buf[ moduleNameSize ];
- GetModuleFileNameW( NULL, buf, moduleNameSize );
- convertUTF16toUTF8( buf, moduleName );
- }
- #else
- GetModuleFileNameA(NULL, moduleName, moduleNameSize);
- #endif
- argv.push_back(moduleName);
- for (const char* word,*ptr = lpszCmdLine; *ptr; )
- {
- // Eat white space
- for (; dIsspace(*ptr) && *ptr; ptr++)
- ;
- // Test for quotes
- bool withinQuotes = dIsquote(*ptr);
- if (!withinQuotes)
- {
- // Pick out the next word
- for (word = ptr; !dIsspace(*ptr) && *ptr; ptr++)
- ;
- }
- else
- {
- // Advance past the first quote. We don't want to include it.
- ptr++;
- // Pick out the next quote
- for (word = ptr; !dIsquote(*ptr) && *ptr; ptr++)
- ;
- }
- // Add the word to the argument list.
- if (*word)
- {
- S32 len = ptr - word;
- char *arg = (char *) dMalloc(len + 1);
- dStrncpy(arg, word, len);
- arg[len] = 0;
- argv.push_back(arg);
- }
- // If we had a quote, skip past it for the next arg
- if (withinQuotes && *ptr)
- {
- ptr++;
- }
- }
- winState.appInstance = hInstance;
- S32 retVal = TorqueMain(argv.size(), (const char **) argv.address());
- for(U32 j = 1; j < argv.size(); j++)
- dFree(argv[j]);
- return retVal;
- }
- } // extern "C"
- #endif
- //--------------------------------------
- F32 Platform::getRandom()
- {
- return sgPlatRandom.randF();
- }
- #ifndef TORQUE_SDL
- ////--------------------------------------
- /// Spawn the default Operating System web browser with a URL
- /// @param webAddress URL to pass to browser
- /// @return true if browser successfully spawned
- bool Platform::openWebBrowser( const char* webAddress )
- {
- static bool sHaveKey = false;
- static wchar_t sWebKey[512];
- char utf8WebKey[512];
- {
- HKEY regKey;
- DWORD size = sizeof( sWebKey );
- if ( RegOpenKeyEx( HKEY_CLASSES_ROOT, dT("\\http\\shell\\open\\command"), 0, KEY_QUERY_VALUE, ®Key ) != ERROR_SUCCESS )
- {
- Con::errorf( ConsoleLogEntry::General, "Platform::openWebBrowser - Failed to open the HKCR\\http registry key!!!");
- return( false );
- }
- if ( RegQueryValueEx( regKey, dT(""), NULL, NULL, (U8 *)sWebKey, &size ) != ERROR_SUCCESS )
- {
- Con::errorf( ConsoleLogEntry::General, "Platform::openWebBrowser - Failed to query the open command registry key!!!" );
- return( false );
- }
- RegCloseKey( regKey );
- sHaveKey = true;
- convertUTF16toUTF8(sWebKey,utf8WebKey);
- #ifdef UNICODE
- char *p = dStrstr((const char *)utf8WebKey, "%1");
- #else
- char *p = strstr( (const char *) sWebKey , "%1");
- #endif
- if (p) *p = 0;
- }
- STARTUPINFO si;
- dMemset( &si, 0, sizeof( si ) );
- si.cb = sizeof( si );
- char buf[1024];
- #ifdef UNICODE
- dSprintf( buf, sizeof( buf ), "%s %s", utf8WebKey, webAddress );
- UTF16 b[1024];
- convertUTF8toUTF16((UTF8 *)buf, b);
- #else
- dSprintf( buf, sizeof( buf ), "%s %s", sWebKey, webAddress );
- #endif
- //Con::errorf( ConsoleLogEntry::General, "** Web browser command = %s **", buf );
- PROCESS_INFORMATION pi;
- dMemset( &pi, 0, sizeof( pi ) );
- CreateProcess( NULL,
- #ifdef UNICODE
- b,
- #else
- buf,
- #endif
- NULL,
- NULL,
- false,
- CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
- NULL,
- NULL,
- &si,
- &pi );
- return( true );
- }
- #endif
- //--------------------------------------
- // Login password routines:
- //--------------------------------------
- #ifdef UNICODE
- static const UTF16* TorqueRegKey = dT("SOFTWARE\\GarageGames\\Torque");
- #else
- static const char* TorqueRegKey = "SOFTWARE\\GarageGames\\Torque";
- #endif
- const char* Platform::getLoginPassword()
- {
- HKEY regKey;
- char* returnString = NULL;
- if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TorqueRegKey, 0, KEY_QUERY_VALUE, ®Key ) == ERROR_SUCCESS )
- {
- U8 buf[32];
- DWORD size = sizeof( buf );
- if ( RegQueryValueEx( regKey, dT("LoginPassword"), NULL, NULL, buf, &size ) == ERROR_SUCCESS )
- {
- returnString = Con::getReturnBuffer( size + 1 );
- dStrcpy( returnString, (const char*) buf, size + 1 );
- }
- RegCloseKey( regKey );
- }
- if ( returnString )
- return( returnString );
- else
- return( "" );
- }
- //--------------------------------------
- bool Platform::setLoginPassword( const char* password )
- {
- HKEY regKey;
- if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TorqueRegKey, 0, KEY_WRITE, ®Key ) == ERROR_SUCCESS )
- {
- if ( RegSetValueEx( regKey, dT("LoginPassword"), 0, REG_SZ, (const U8*) password, dStrlen( password ) + 1 ) != ERROR_SUCCESS )
- Con::errorf( ConsoleLogEntry::General, "setLoginPassword - Failed to set the subkey value!" );
- RegCloseKey( regKey );
- return( true );
- }
- else
- Con::errorf( ConsoleLogEntry::General, "setLoginPassword - Failed to open the Torque registry key!" );
- return( false );
- }
- //--------------------------------------
- // Silly Korean registry key checker:
- //
- // NOTE: "Silly" refers to the nature of this hack, and is not intended
- // as commentary on Koreans as a nationality. Thank you for your
- // attention.
- //--------------------------------------
- DefineEngineFunction( isKoreanBuild, bool, ( ), , "isKoreanBuild()")
- {
- HKEY regKey;
- bool result = false;
- if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TorqueRegKey, 0, KEY_QUERY_VALUE, ®Key ) == ERROR_SUCCESS )
- {
- DWORD val;
- DWORD size = sizeof( val );
- if ( RegQueryValueEx( regKey, dT("Korean"), NULL, NULL, (U8*) &val, &size ) == ERROR_SUCCESS )
- result = ( val > 0 );
- RegCloseKey( regKey );
- }
- return( result );
- }
|