| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program 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 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Installer *
- * *
- * $Archive:: /Commando/Code/Installer/WinMain.cpp $*
- * *
- * $Author:: Ian_l $*
- * *
- * $Modtime:: 1/22/02 2:17p $*
- * *
- * $Revision:: 12 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- // Include files.
- #include "Argv.h"
- #include "Bufffile.h"
- #include "Chunkio.h"
- #include "ErrorHandler.h"
- #include "FFactory.h"
- #include "Installer.h"
- #include "MixFile.h"
- #include "Msgloop.h"
- #include "RAMFileFactory.h"
- #include "Resource.h"
- #include "SafeTimer.h"
- #include "SaveLoad.h"
- #include "Timer.h"
- #include "Translator.h"
- #include "Win.h"
- #include "WW3D.h"
- #include "WWFile.h"
- #include <malloc.h>
- #include <dbt.h>
- // Defines.
- #define AUTORUN_MUTEX_OBJECT TEXT("01AF9993-3492-11d3-8F6F-0060089C05B1")
- #define APPLICATION_MUTEX_OBJECT TEXT("C6D925A3-7A9B-4ca3-866D-8B4D506C3665")
- // Static variables.
- // Foward declarations.
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
- ATOM MyRegisterClass (HINSTANCE hInstance);
- bool Is_Autorun_Running();
- bool Is_Application_Running();
- bool Is_Win_95_Or_Above();
- bool Is_Win_2K_Or_Above();
- bool Running_As_Administrator();
- void Prog_End();
- /***********************************************************************************************
- * WinMain -- Entry point to program. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
- {
- int result;
- // Initialize command line parser.
- ArgvClass::Init (lpCmdLine);
- TranslateDBClass::Initialize();
- try {
- // Set global copy of program instance.
- ProgramInstance = hInstance;
- // Ensure Autorun or another instance of this application is not running.
- if ((!Is_Autorun_Running()) && (!Is_Application_Running())) {
- // WARNING: Can only raise fatal system errors (not fatal application errors) until
- // the translation table has been loaded.
- const char *installmixname = "InstallMix.dat";
- const char *installstringsfilename = "InstallStrings.tdb";
- RAMFileFactoryClass ramfilefactory;
- MixFileFactoryClass mixfilefactory (installmixname, &ramfilefactory);
- FileClass *file;
- // Perform application initialization.
- // An invalid mixfile factory indicates a read error.
- if (!mixfilefactory.Is_Valid()) FATAL_SYSTEM_ERROR;
- _TheFileFactory = &mixfilefactory;
- // Load the translation table.
- file = _TheFileFactory->Get_File (installstringsfilename);
- if (file == NULL) {
-
- // Output an appropriate Windows error message.
- SetLastError (2);
- FATAL_SYSTEM_ERROR;
- }
- file->Open (FileClass::READ);
- if (file->Is_Available()) {
- ChunkLoadClass cload (file);
-
- SaveLoadSystemClass::Load (cload);
-
- } else {
- // Output an appropriate Windows error message.
- SetLastError (2);
- FATAL_SYSTEM_ERROR;
- }
- file->Close();
- _TheFileFactory->Return_File (file);
- // Check for valid OS.
- if (!(Is_Win_95_Or_Above() || Is_Win_2K_Or_Above())) FATAL_APP_ERROR (IDS_BAD_OS);
- // Check for Administrator rights under Win 2k or above.
- if (Is_Win_2K_Or_Above()) {
- if (!Running_As_Administrator()) FATAL_APP_ERROR (IDS_NOT_ADMINISTRATOR);
- }
- // Register function to be called at exit.
- atexit (Prog_End);
- MyRegisterClass (hInstance);
- MainWindow = CreateWindow (RxStringClass (IDS_APPLICATION_MAIN_WINDOW),
- StringClass (TxWideStringClass (IDS_APPLICATION_NAME)),
- WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX|WS_CLIPCHILDREN,
- 0, 0, 0, 0,
- NULL, NULL,
- hInstance, NULL);
- if (MainWindow == NULL) FATAL_SYSTEM_ERROR;
- ShowCursor (false);
- _Installer.Install (&mixfilefactory);
- ShowCursor (true);
- }
- result = 1;
- } catch (const WideStringClass &errormessage) {
- // Catch handler for fatal errors.
- DestroyWindow (MainWindow);
- Windows_Message_Handler();
- Message_Box (TxWideStringClass (IDS_APPLICATION_ERROR), errormessage);
- result = 0;
- }
- TranslateDBClass::Shutdown();
- ArgvClass::Free();
- return (result);
- }
- /***********************************************************************************************
- * MyRegisterClass -- *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- ATOM MyRegisterClass (HINSTANCE hInstance)
- {
- static RxStringClass _classname (IDS_APPLICATION_MAIN_WINDOW);
- WNDCLASSEX wcex;
- wcex.cbSize = sizeof (WNDCLASSEX);
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = (WNDPROC)WndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = hInstance;
- wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_INSTALLER);
- wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
- wcex.lpszMenuName = (LPCSTR)IDS_INSTALLER;
- wcex.lpszClassName = _classname;
- wcex.hIconSm = LoadIcon (hInstance, (LPCTSTR)IDI_INSTALLER);
- return RegisterClassEx (&wcex);
- }
- /***********************************************************************************************
- * WndProc -- Windows message handler. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- // Pass this message through to the input handler. If the message
- // was processed and requires no further action, then return with
- // this information.
- if (_Installer.Get_Input() != NULL) {
- LRESULT result = 0;
- if (_Installer.Get_Input()->ProcessMessage (hWnd, message, wParam, lParam, result)) {
- return (result);
- }
- }
- switch (message)
- {
- case WM_ACTIVATEAPP:
- if (wParam && !GameInFocus) {
- GameInFocus = true;
- } else {
- if (!wParam && GameInFocus) {
- GameInFocus = false;
- }
- }
- return (0);
- case WM_ERASEBKGND:
- return (1);
- case WM_PAINT:
- ValidateRect (hWnd, NULL);
- break;
- case WM_CREATE:
- break;
- case WM_DESTROY:
- PostQuitMessage (0);
- break;
- case WM_SYSCOMMAND:
-
- switch (wParam) {
- case SC_CLOSE:
-
- // Windows sent us a close message - probably in response to Alt-F4. Ignore it.
- return (0);
- case SC_SCREENSAVE:
-
- // Windows is about to start the screen saver. If we just return without passing
- // this message to DefWindowProc then the screen saver will not be allowed to start.
- return (0);
- case SC_KEYMENU:
- // Ignore all "menu-activation" commands.
- return (0);
- }
- break;
- case WM_KEYUP:
-
- // Test for SHIFT + ESC.
- if ((wParam & 0xff) == VK_ESCAPE && ((GetKeyState (VK_SHIFT) & 0x8000) != 0x0)) {
- _Installer.Cancel_Introduction();
- }
- #if !NDEBUG
- // Test for Print Screen (screenshot).
- if ((wParam & 0xff) == VK_SNAPSHOT) {
- WW3D::Make_Screen_Shot();
- }
- #endif
- case WM_MOUSEWHEEL:
- {
- if (_Installer.Get_Input() != NULL) {
- _Installer.Get_Input()->Add_Mouse_Wheel (HIWORD (wParam));
- return (0);
- }
- break;
- }
- case WM_DEVICECHANGE:
- {
- PDEV_BROADCAST_HDR pdbch;
- pdbch = (PDEV_BROADCAST_HDR) lParam;
- if (pdbch != NULL) {
- if (pdbch->dbch_devicetype == DBT_DEVTYP_VOLUME) {
- // Assume that this is the CD-ROM drive.
- if (wParam == DBT_DEVICEQUERYREMOVE) {
- ShowWindow (hWnd, SW_MINIMIZE);
- } else {
- if (wParam == DBT_DEVICEARRIVAL) {
- if (IsIconic (hWnd)) {
- ShowWindow (hWnd, SW_RESTORE);
- }
- SetForegroundWindow (hWnd);
- }
- }
- return (TRUE);
- }
- }
- break;
- }
-
- default:
- break;
- }
- return (DefWindowProc (hWnd, message, wParam, lParam));
- }
- /***********************************************************************************************
- * InstallerClass::Is_Autorun_Running -- Determine whether Autorun (a sister application) is *
- * running. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- bool Is_Autorun_Running()
- {
- HANDLE autorunmutex = OpenMutex (MUTEX_ALL_ACCESS & SYNCHRONIZE, FALSE, AUTORUN_MUTEX_OBJECT);
- if (autorunmutex != NULL) {
- HWND window = FindWindow (RxStringClass (IDS_AUTORUN_MAIN_WINDOW), NULL);
- if (window) {
- CDTimerClass <SafeTimerClass> delaytimer (10 * 1000);
- // Hang around for a while to see if Autorun is about to quit...
- while ((delaytimer.Value() > 0) && (window != NULL)) {
- window = FindWindow (RxStringClass (IDS_AUTORUN_MAIN_WINDOW), NULL);
- }
- }
- CloseHandle (autorunmutex);
-
- // If the Autorun window still exists bring it to the foreground.
- if (window) {
- if (IsIconic (window)) {
- ShowWindow (window, SW_RESTORE);
- }
- SetForegroundWindow (window);
- }
- }
- return (autorunmutex != NULL);
- }
- /***********************************************************************************************
- * InstallerClass::Is_Application_Running -- Determine whether this application is running. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- bool Is_Application_Running()
- {
- HANDLE appmutex = CreateMutex (NULL, FALSE, APPLICATION_MUTEX_OBJECT);
- if (appmutex == NULL) FATAL_SYSTEM_ERROR;
- // See if the application was already running.
- HWND prev = FindWindow (RxStringClass (IDS_APPLICATION_MAIN_WINDOW), NULL);
- if (prev) {
- if (IsIconic (prev)) {
- ShowWindow (prev, SW_RESTORE);
- }
- SetForegroundWindow (prev);
- return (true);
- } else {
- return (false);
- }
- }
- /***********************************************************************************************
- * InstallerClass::Is_Win_95_Or_Above -- *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- bool Is_Win_95_Or_Above()
- {
- OSVERSIONINFO versioninfo;
- BOOL result;
- bool validos = false;
- versioninfo.dwOSVersionInfoSize = sizeof (versioninfo);
- result = GetVersionEx (&versioninfo);
- if (result) {
- if (versioninfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
- validos = true;
- }
- }
- return (validos);
- }
- /***********************************************************************************************
- * InstallerClass::Is_Win_2K_Or_Above -- *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- bool Is_Win_2K_Or_Above()
- {
- OSVERSIONINFO versioninfo;
- BOOL result;
- bool validos = false;
- versioninfo.dwOSVersionInfoSize = sizeof (versioninfo);
- result = GetVersionEx (&versioninfo);
- if (result) {
- if (versioninfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- validos = (versioninfo.dwMajorVersion >= 5) && (versioninfo.dwMinorVersion >= 0);
- }
- }
- return (validos);
- }
- /***********************************************************************************************
- * InstallerClass::Running_As_Administrator -- *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- bool Running_As_Administrator()
- {
- bool fAdmin;
- HANDLE hThread;
- TOKEN_GROUPS *ptg = NULL;
- DWORD cbTokenGroups;
- DWORD dwGroup;
- PSID psidAdmin;
- SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
- // Open a handle to the access token for this thread.
- if (!OpenThreadToken (GetCurrentThread(), TOKEN_QUERY, FALSE, &hThread)) {
- if (GetLastError() == ERROR_NO_TOKEN) {
- // If the thread does not have an access token, examine the access token associated with the process.
- if (! OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hThread)) {
- return (false);
- }
- } else {
- return (false);
- }
- }
- // Query the size of the group information associated with the token. Note that we expect a FALSE result from GetTokenInformation
- // because we've given it a NULL buffer. On exit cbTokenGroups will tell the size of the group information.
- if (GetTokenInformation (hThread, TokenGroups, NULL, 0, &cbTokenGroups)) {
- return (false);
- }
- // Verify that GetTokenInformation failed for lack of a large enough buffer.
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- return (false);
- }
- // Allocate a buffer for the group information. Since _alloca allocates on the stack, we don't have
- // to explicitly deallocate it. That happens automatically when we exit this function.
- if (!(ptg = (TOKEN_GROUPS*) _alloca (cbTokenGroups))) {
- return (false);
- }
- // Ask for the group information again. This may fail if an administrator has added this account
- // to an additional group between our first call to GetTokenInformation and this one.
- if (!GetTokenInformation (hThread, TokenGroups, ptg, cbTokenGroups, &cbTokenGroups)) {
- return (false);
- }
-
- // Create a System Identifier for the Admin group.
- if (!AllocateAndInitializeSid (&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin)) {
- return (false);
- }
- // Iterate through the list of groups for this access token looking for a match against the SID we created above.
- fAdmin = false;
- for (dwGroup = 0; dwGroup < ptg->GroupCount; dwGroup++) {
- if (EqualSid (ptg->Groups[dwGroup].Sid, psidAdmin)) {
- fAdmin = true;
- break;
- }
- }
- // Explicity deallocate the SID we created.
- FreeSid (psidAdmin);
- return (fAdmin);
- }
- /***********************************************************************************************
- * Prog_End -- *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- void Prog_End()
- {
- try {
-
- _Installer.On_Prog_End();
- } catch (const WideStringClass &errormessage) {
- // Catch handler for fatal errors.
- DestroyWindow (MainWindow);
- Windows_Message_Handler();
- Message_Box (TxWideStringClass (IDS_APPLICATION_ERROR), errormessage);
- }
- }
|