/*
** 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 .
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Installer *
* *
* $Archive:: /Commando/Code/Installer/Installer.cpp $*
* *
* $Author:: Ian_l $*
* *
* $Modtime:: 1/17/02 7:43p $*
* *
* $Revision:: 18 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
// Include files.
#include "Installer.h"
#include "Argv.h"
#include "AssetMgr.h"
#include "AssetStatus.h"
#include "AudibleSound.h"
#include "BINKMovie.h"
#include "CardSelectionDialog.h"
#include "CodeControl.h"
#include "CopyDialog.h"
#include "DialogMgr.h"
#include "DirectoryDialog.h"
#include "DX8Wrapper.h"
#include "ErrorHandler.h"
#include "FinalDialog.h"
#include "FolderDialog.h"
#include "Ini.h"
#include "LicenseDialog.h"
#include "MixFile.h"
#include "Msgloop.h"
#include "Registry.h"
#include "ReviewDialog.h"
#include "SafeTimer.h"
#include "SerialDialog.h"
#include "Timer.h"
#include "TransitionDialog.h"
#include "Translator.h"
#include "Utilities.h"
#include "WelcomeDialog.h"
#include "WhatToInstallDialog.h"
#include "Ww3D.h"
#include "Wwmath.h"
#include "WOL1Dialog.h"
#include "WOL2Dialog.h"
#include
#include
#include
#include
// Section names and entry names for IDS_GAME_INI_FILENAME.
#define INI_CD_LABEL_SECTION "CDLabel"
#define INI_SUBDIRECTORY_SECTION "SubDirectories"
#define INI_FILES_SECTION "Files"
#define INI_VOLUME_LABEL_ENTRY "VolumeLabel"
#define INI_SUBDIRECTORY_ENTRY_PREFIX "Dir"
#define INI_TOTAL_DISK_SPACE_NEEDED_ENTRY "TotalDiskSpaceNeeded"
#define INI_NUM_FILES_ENTRY "NumFiles"
// Section names and entry names for IDS_WOLAPI_INI_FILENAME.
#define INI_WOLAPI_SECTION "Wolapi"
#define INI_WOLREGISTER_SECTION "Register"
#define INI_WOLBROWSER_SECTION "Browser"
#define INI_VERSION_MAJOR_ENTRY "Major"
#define INI_VERSION_MINOR_ENTRY "Minor"
// Section names and entry names for IDS_SETUP_INI_FILENAME.
#define INI_SETUP_SECTION "Setup"
#define INI_LANGUAGE_ENTRY "Language"
#define INI_SKU_ENTRY "SKU"
#define INI_CAN_USE_IGR_SETTNGS_ENTRY "CanUseIGRSettings"
// Miscellaneous.
#define ENCRYPTION_STRING_LENGTH 128
#define INSTALLER_NOMINAL_BYTE_COUNT 0x40000
// Registry access.
#define APPLICATION_SUB_KEY_NAME "Software\\Westwood\\Renegade"
#define APPLICATION_SUB_KEY_NAME_RENDER "Software\\Westwood\\Renegade\\Render"
#define APPLICATION_SUB_KEY_NAME_OPTIONS "Software\\Westwood\\Renegade\\Options"
// Macros.
#define END_DIALOG(dialog) \
if (dialog != NULL) { \
dialog->End_Dialog(); \
}
#define REGISTER_DIALOG(dialogclass, dialog, args) \
if (dialog == NULL) { \
dialog = NEW_REF (dialogclass, args); \
dialog->Start_Dialog(); \
} else { \
DialogMgrClass::Register_Dialog (dialog); \
}
#define UNREGISTER_DIALOG(dialog) \
DialogMgrClass::UnRegister_Dialog (dialog);
#define DO_CANCEL \
CancelApplication = true; \
PostQuitMessage (0);
// Foward declarations.
void WWDebug_Message_Callback (DebugType type, const char *message);
void WWAssert_Callback (const char *message);
// Prototypes.
bool CALLBACK Default_On_Command (DialogBaseClass *dialog, int ctrl_id, int mesage_id, DWORD param);
// Singleton.
InstallerClass _Installer;
// Type definitions.
typedef HRESULT (*DLLREGISTERSERVER)(void);
typedef HRESULT (*DLLUNREGISTERSERVER)(void);
/***********************************************************************************************
* InstallerClass::InstallerClass -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
InstallerClass::InstallerClass()
: SetupIni (NULL),
GameIni (NULL),
WOLIni (NULL),
AssetManager (NULL),
FreshGameInstall (true),
FreshWOLInstall (true),
TargetWOLOlder (true),
WwmathInitialized (false),
DialogMgrInitialized (false),
AudioSystem (NULL),
TransitionMusic (NULL),
InstallMusic (NULL),
UIInput (NULL),
CancelIntroduction (false),
CancelApplication (false),
WelcomeDialog (NULL),
NDADialog (NULL),
LicenseDialog (NULL),
SerialDialog (NULL),
WhatToInstallDialog (NULL),
GameDirectoryDialog (NULL),
GameFolderDialog (NULL),
WOLDirectoryDialog (NULL),
WOLFolderDialog (NULL),
ReviewDialog (NULL),
CopyDialog (NULL),
WOL1Dialog (NULL),
WOL2Dialog (NULL),
FinalDialog (NULL),
GameFileCount (0),
GameSize (0),
WOLFileCount (0),
WOLSize (0),
CardSelectionDialog (NULL),
ProgEndAction (ACTION_NONE)
{
SetupIni = new INIClass;
GameIni = new INIClass;
WOLIni = new INIClass;
}
/***********************************************************************************************
* InstallerClass::~InstallerClass -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
InstallerClass::~InstallerClass()
{
delete WOLIni;
delete GameIni;
delete SetupIni;
}
/***********************************************************************************************
* InstallerClass::Install -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Install (MixFileFactoryClass *mixfilefactory)
{
try {
const Vector3 black (0.0f, 0.0f, 0.0f);
MixFileFactory = mixfilefactory;
// Install debug callbacks.
WWDebug_Install_Message_Handler (WWDebug_Message_Callback);
WWDebug_Install_Assert_Handler (WWAssert_Callback);
// Check that the source data for the install is present.
if (Check_Source()) {
const char *intromoviename = "InstallMovie.bik";
const int playouttime = 2000;
bool cancelapplication = false;
int time;
Check_Existing_Install();
Initialize();
// If the user has more than one video card, run the video card selection dialog.
CardSelectionDialog = NEW_REF (CardSelectionDialogClass, (false));
while (CardSelectionDialog->Get_Card_Count() > 1) {
int cardselection;
CardSelectionDialog->Start_Dialog();
while (CardSelectionDialog->Is_Running()) {
DialogMgrClass::On_Frame_Update();
WW3D::Begin_Render (true, true, black);
if (GameInFocus) {
DialogMgrClass::Render();
} else {
Sleep (50);
}
WW3D::End_Render();
Windows_Message_Handler();
}
cardselection = CardSelectionDialog->Get_Card_Selection();
cancelapplication = CardSelectionDialog->Cancel_Application();
if (cancelapplication) break;
// NOTE: Must release all dialogs before attempting initialization.
REF_PTR_RELEASE (CardSelectionDialog);
WW3D_Shutdown();
if (WW3D_Initialize (cardselection)) break;
// Re-initialize with the default video card and driver and inform the user
// that their selected card would not initialize.
WW3D_Shutdown();
WW3D_Initialize();
CardSelectionDialog = NEW_REF (CardSelectionDialogClass, (true));
}
REF_PTR_RELEASE (CardSelectionDialog);
// Does the user wish to exit?
if (!cancelapplication) {
if (!Beta_Test()) {
// Play BINK intro movie.
BINKMovie::Init();
BINKMovie::Play (intromoviename);
while (!BINKMovie::Is_Complete()) {
if (CancelIntroduction) {
BINKMovie::Stop();
break;
}
BINKMovie::Update();
WW3D::Begin_Render (false, false, black);
if (GameInFocus) {
BINKMovie::Render();
} else {
Sleep (50);
}
WW3D::End_Render();
Windows_Message_Handler();
}
BINKMovie::Shutdown();
// For artistic reasons, end the movie on a black frame.
WW3D::Begin_Render (true, true, black);
WW3D::End_Render();
// If the user cancelled during the intro movie, then don't bother with the transition.
if (!CancelIntroduction) {
TransitionDialogClass *transition;
// Create the transition animation.
transition = NEW_REF (TransitionDialogClass, ());
transition->Start_Dialog();
// Start the transition music.
if (TransitionMusic != NULL) TransitionMusic->Play();
TTimerClass timer;
// Play.
while (true) {
DialogMgrClass::On_Frame_Update();
// Has the dialog 'played out'?
// NOTE: Wait for both video and audio to finish.
if (!transition->Is_Running()) {
if (TransitionMusic != NULL) {
if (!TransitionMusic->Is_Playing()) break;
} else {
break;
}
}
WW3D::Begin_Render (true, true, black);
if (GameInFocus) {
DialogMgrClass::Render();
if (TransitionMusic != NULL) {
if (TransitionMusic->Get_State() == AudibleSoundClass::STATE_PAUSED) TransitionMusic->Resume();
}
if (!timer.Is_Active()) timer.Start();
} else {
if (TransitionMusic != NULL) {
if (TransitionMusic->Get_State() == AudibleSoundClass::STATE_PLAYING) TransitionMusic->Pause();
}
if (timer.Is_Active()) timer.Stop();
Sleep (50);
}
WW3D::End_Render();
WW3D::Sync (timer.Value());
WWAudioClass::Get_Instance()->On_Frame_Update();
Windows_Message_Handler();
// Has the user cancelled the transition?
if (CancelIntroduction) {
transition->End_Dialog();
if (TransitionMusic != NULL) TransitionMusic->Stop();
break;
}
}
REF_PTR_RELEASE (transition);
}
}
// Set the command handler for all subsequent dialogs.
DialogBaseClass::Set_Default_Command_Handler (Default_On_Command);
// Put up the first dialog.
Default_On_Command (NULL, 0, 0, 0);
// Start the install music.
if (InstallMusic != NULL) InstallMusic->Play();
TTimerClass timer;
// Run dialog loop.
while (!CancelApplication) {
DialogMgrClass::On_Frame_Update();
WW3D::Begin_Render (true, true, black);
if (GameInFocus) {
DialogMgrClass::Render();
if (InstallMusic != NULL) {
if (InstallMusic->Get_State() == AudibleSoundClass::STATE_PAUSED) InstallMusic->Resume();
}
if (!timer.Is_Active()) timer.Start();
} else {
if (InstallMusic != NULL) {
if (InstallMusic->Get_State() == AudibleSoundClass::STATE_PLAYING) InstallMusic->Pause();
}
if (timer.Is_Active()) timer.Stop();
Sleep (50);
}
WW3D::End_Render();
WW3D::Sync (timer.Value());
WWAudioClass::Get_Instance()->On_Frame_Update();
Windows_Message_Handler();
}
// Before shutting down, allow a short time for sound effects to 'play out'.
time = timer.Value();
while (timer.Value() < time + playouttime) {
WW3D::Sync (timer.Value());
WWAudioClass::Get_Instance()->On_Frame_Update();
Windows_Message_Handler();
}
// Clear the frame buffer.
WW3D::Begin_Render (true, true, black);
WW3D::End_Render();
}
Shutdown();
}
}
catch (const WideStringClass &errormessage) {
Shutdown();
throw (errormessage);
}
}
/***********************************************************************************************
* InstallerClass::Check_Source -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Check_Source()
{
ArgvClass commandlineparser (false, true);
// Use the simple file factory to read INI files from the current working directory.
_TheFileFactory = _TheSimpleFileFactory;
#if PERMIT_INSTALL_FROM_NETWORK
if (!commandlineparser.Find ("-N")) {
#else
if (true) {
#endif
char sourcedriveletter;
// Prompt for a CD with correct volume label.
if (Prompt_Install_CD (RxWideStringClass (IDS_INSTALL_CD_VOLUME_NAME), sourcedriveletter)) {
char sourcedrive [] = "?:";
sourcedrive [0] = tolower (sourcedriveletter);
SourceGamePath = sourcedrive;
SourceWOLPath = sourcedrive;
} else {
// No CD found.
return (false);
}
} else {
#if PERMIT_INSTALL_FROM_NETWORK
Get_Current_Directory (SourceGamePath);
Remove_Trailing_Name (SourceGamePath);
SourceWOLPath = SourceGamePath;
#endif
}
// Initialize the game and WOL source paths.
SourceGamePath += L"\\";
SourceGamePath += RxWideStringClass (IDS_GAME_DIRECTORY_NAME);
SourceWOLPath += L"\\";
SourceWOLPath += RxWideStringClass (IDS_WOL_DIRECTORY_NAME);
// Look in the current directory for Setup.ini file.
if (!SetupIni->Is_Loaded()) {
if (!SetupIni->Load (RxStringClass (IDS_SETUP_INI_FILENAME))) FATAL_APP_ERROR (IDS_INI_FILE_NOT_FOUND_OR_LOADED);
}
// Look in the current directory for .ini file.
if (!GameIni->Is_Loaded()) {
if (!GameIni->Load (RxStringClass (IDS_GAME_INI_FILENAME))) FATAL_APP_ERROR (IDS_INI_FILE_NOT_FOUND_OR_LOADED);
}
// Look in the WOL source directory for WOLAPI.ini file.
if (!WOLIni->Is_Loaded()) {
WideStringClass wolinipathname;
StringClass multibytewolinipathname;
wolinipathname = SourceWOLPath;
wolinipathname += L"\\";
wolinipathname += RxWideStringClass (IDS_WOL_INI_FILENAME);
multibytewolinipathname = wolinipathname;
if (!WOLIni->Load (multibytewolinipathname)) FATAL_APP_ERROR (IDS_INI_FILE_NOT_FOUND_OR_LOADED);
}
// Count no. and total file size of contents of game directory.
Count_Source_Files (SourceGamePath, GameFileCount, GameSize);
// Add game file count and size contained in CAB files.
// WARNING: Only values < 2Gb will be reported correctly due to 32-bit limit on INIClass::Get_Int().
// However, result is returned in 64-bits so that all callers are ready to handle >= 2Gb when the need arises.
GameFileCount += GameIni->Get_Int (INI_FILES_SECTION, INI_NUM_FILES_ENTRY);
GameSize += GameIni->Get_Int (INI_FILES_SECTION, INI_TOTAL_DISK_SPACE_NEEDED_ENTRY);
// Count no. and total file size of contents of WOL directory.
// NOTE: WOL directory does not contain CAB files.
Count_Source_Files (SourceWOLPath, WOLFileCount, WOLSize);
// Return success.
return (true);
}
/***********************************************************************************************
* InstallerClass::Count_Source_Files -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Count_Source_Files (const WideStringClass &sourcepath, unsigned &filecount, __int64 &filesize)
{
const WCHAR *wildcardname = L"*.*";
WideStringClass sourcepathname (sourcepath);
StringClass multibytesourcewolpath;
WIN32_FIND_DATA finddata;
HANDLE handle;
bool done = false;
sourcepathname += L"\\";
sourcepathname += wildcardname;
multibytesourcewolpath = sourcepathname;
handle = FindFirstFile (multibytesourcewolpath, &finddata);
if (handle != INVALID_HANDLE_VALUE) {
while (!done) {
WideStringClass filename (finddata.cFileName);
if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// Filter out system diretories.
if (filename [0] != L'.') {
WideStringClass subsourcepath;
// Recurse on subdirectory..
subsourcepath = sourcepath;
subsourcepath += L"\\";
subsourcepath += filename;
Count_Source_Files (subsourcepath, filecount, filesize);
}
} else {
const WCHAR *cabextension = L".cab";
WCHAR extension [_MAX_EXT];
// Filter out CAB files.
_wsplitpath (filename, NULL, NULL, NULL, extension);
if (_wcsicmp (cabextension, extension) != 0) {
filecount++;
filesize += (finddata.nFileSizeHigh * ((__int64) MAXDWORD) + 1) + finddata.nFileSizeLow;
}
}
if (done = FindNextFile (handle, &finddata) == 0) {
if (GetLastError() != ERROR_NO_MORE_FILES) FATAL_SYSTEM_ERROR;
}
}
if (!FindClose (handle)) FATAL_SYSTEM_ERROR;
}
}
/***********************************************************************************************
* InstallerClass::Check_Existing_Install -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Check_Existing_Install()
{
WideStringClass pathname;
StringClass multibytepathname;
WIN32_FIND_DATA finddata;
HANDLE handle;
bool fresh;
bool older;
// Check for existence of target game .exe.
fresh = true;
if (_RegistryManager.Get_Target_Game_Pathname (pathname)) {
multibytepathname = pathname;
handle = FindFirstFile (multibytepathname, &finddata);
if (handle != INVALID_HANDLE_VALUE) {
FindClose (handle);
fresh = false;
}
}
FreshGameInstall = fresh;
// Iterate over all WOL components. Install is a fresh install if one or more components are
// missing from the user's system. The target is deemed older that the source if one or more
// target version nos. is older than source.
const char *sectionname [RegistryManagerClass::COMPONENT_COUNT] = {INI_WOLAPI_SECTION, INI_WOLREGISTER_SECTION, INI_WOLBROWSER_SECTION};
fresh = false;
older = false;
for (int c = RegistryManagerClass::COMPONENT_FIRST; c < RegistryManagerClass::COMPONENT_COUNT; c++) {
WideStringClass pathname;
StringClass multibytepathname;
WIN32_FIND_DATA finddata;
HANDLE handle;
DWORD major, minor, sourceversion, targetversion;
// Check for existence of target .exe.
if (!_RegistryManager.Get_Target_WOL_Pathname ((RegistryManagerClass::WOLComponentEnum) c, pathname)) {
fresh = true;
older = true;
break;
}
multibytepathname = pathname;
handle = FindFirstFile (multibytepathname, &finddata);
if (handle == INVALID_HANDLE_VALUE) {
fresh = true;
older = true;
break;
}
FindClose (handle);
// Compare source and target versions.
if (!_RegistryManager.Get_Target_WOL_Version ((RegistryManagerClass::WOLComponentEnum) c, targetversion)) {
older = true;
break;
}
major = WOLIni->Get_Int (sectionname [c], INI_VERSION_MAJOR_ENTRY, 0x1);
minor = WOLIni->Get_Int (sectionname [c], INI_VERSION_MINOR_ENTRY, 0x0);
sourceversion = (major << 16) + minor;
if (sourceversion > targetversion) {
older = true;
break;
}
}
FreshWOLInstall = fresh;
TargetWOLOlder = older;
}
/***********************************************************************************************
* InstallerClass::Initialize -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Initialize()
{
const char *transitionmusicfilename = "TransitionMusic.mp3";
const char *installmusicfilename = "InstallMusic.mp3";
// All subsequent file factory access uses the mix file.
_TheFileFactory = MixFileFactory;
// Initialize WW systems.
WWMath::Init();
WwmathInitialized = true;
if (!WW3D_Initialize()) FATAL_APP_ERROR (IDS_CANNOT_INITIALIZE_ANY_D3D_DEVICE);
// Initialize the music.
AudioSystem = new WWAudioClass();
WWAudioClass::Get_Instance()->Initialize();
WWAudioClass::Get_Instance()->Set_File_Factory (_TheFileFactory);
TransitionMusic = WWAudioClass::Get_Instance()->Create_Sound_Effect (transitionmusicfilename);
if (TransitionMusic != NULL) {
TransitionMusic->Set_Type (AudibleSoundClass::TYPE_MUSIC);
}
InstallMusic = WWAudioClass::Get_Instance()->Create_Sound_Effect (installmusicfilename);
if (InstallMusic != NULL) {
InstallMusic->Set_Type (AudibleSoundClass::TYPE_MUSIC);
InstallMusic->Set_Loop_Count (0);
}
}
/***********************************************************************************************
* InstallerClass::Shutdown -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Shutdown()
{
// Close any open dialogs.
END_DIALOG (WelcomeDialog)
REF_PTR_RELEASE (WelcomeDialog)
END_DIALOG (NDADialog)
REF_PTR_RELEASE (NDADialog)
END_DIALOG (LicenseDialog)
REF_PTR_RELEASE (LicenseDialog)
END_DIALOG (SerialDialog)
REF_PTR_RELEASE (SerialDialog)
END_DIALOG (WhatToInstallDialog)
REF_PTR_RELEASE (WhatToInstallDialog)
END_DIALOG (GameDirectoryDialog)
REF_PTR_RELEASE (GameDirectoryDialog)
END_DIALOG (GameFolderDialog)
REF_PTR_RELEASE (GameFolderDialog)
END_DIALOG (WOLDirectoryDialog)
REF_PTR_RELEASE (WOLDirectoryDialog)
END_DIALOG (WOLFolderDialog)
REF_PTR_RELEASE (WOLFolderDialog)
END_DIALOG (ReviewDialog)
REF_PTR_RELEASE (ReviewDialog)
END_DIALOG (CopyDialog)
REF_PTR_RELEASE (CopyDialog)
END_DIALOG (WOL1Dialog)
REF_PTR_RELEASE (WOL1Dialog)
END_DIALOG (WOL2Dialog)
REF_PTR_RELEASE (WOL2Dialog)
END_DIALOG (FinalDialog)
REF_PTR_RELEASE (FinalDialog)
END_DIALOG (CardSelectionDialog)
REF_PTR_RELEASE (CardSelectionDialog)
// Shutdown the music.
if (TransitionMusic != NULL) {
TransitionMusic->Stop();
TransitionMusic->Release_Ref();
}
if (InstallMusic != NULL) {
InstallMusic->Stop();
InstallMusic->Release_Ref();
}
if (AudioSystem != NULL) {
WWAudioClass::Get_Instance()->Shutdown();
delete AudioSystem;
}
// Shutdown WW systems.
WW3D_Shutdown();
if (WwmathInitialized) WWMath::Shutdown();
}
/***********************************************************************************************
* InstallerClass::WW3D_Initialize -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::WW3D_Initialize (int cardselection)
{
const char *stylemgrini = "StyleMgr.ini";
bool windowedmode;
// Initialize WW3D.
AssetManager = new WW3DAssetManager;
AssetManager->Set_WW3D_Load_On_Demand (true);
WW3D::Init (MainWindow);
WW3D::Enable_Sorting (true);
WW3D::Set_Thumbnail_Enabled (false);
AssetStatusClass::Peek_Instance()->Enable_Reporting (false);
// All subsequent file factory access uses the mix file.
_TheFileFactory = MixFileFactory;
ArgvClass commandlineparser (false, true);
windowedmode = (commandlineparser.Find ("-W") != NULL);
// For each available video card...
for (int d = 0; d < WW3D::Get_Render_Device_Count(); d++) {
// Does this card index match the supplied card index or should we try all cards until success?
if ((cardselection == -1) || (cardselection == d)) {
// Set the card index and whether windowed mode in the registry.
WW3D::Registry_Save_Render_Device (APPLICATION_SUB_KEY_NAME_RENDER, d, -1, -1, -1, 0, -1);
// Configure video for the user.
Auto_Configure();
// Set UV bias according to registry.
RegistryClass optionsregistry (APPLICATION_SUB_KEY_NAME_OPTIONS);
if (optionsregistry.Is_Valid()) {
WW3D::Set_Screen_UV_Bias (optionsregistry.Get_Int ("ScreenUVBias", 1) != 0);
}
// Override the windowed mode.
RegistryClass renderregistry (APPLICATION_SUB_KEY_NAME_RENDER);
if (optionsregistry.Is_Valid()) {
renderregistry.Set_Int ("RenderDeviceWindowed", windowedmode ? 1 : 0);
}
// Attempt to initialize the device.
if (WW3D::Registry_Load_Render_Device (APPLICATION_SUB_KEY_NAME_RENDER, true) == WW3D_ERROR_OK) {
// Clear frame buffers.
for (int frame = 0; frame < 3; frame++) {
WW3D::Begin_Render (true, true, Vector3 (0.0f,0.0f,0.0f));
WW3D::End_Render();
}
// Success! Initialize dialog system.
DialogMgrClass::Initialize (stylemgrini);
DialogMgrInitialized = true;
UIInput = NEW_REF (InstallerUIInputClass, ());
UIInput->InitIME (MainWindow);
DialogMgrClass::Install_Input (UIInput);
return (true);
}
}
}
// Failure.
return (false);
}
/***********************************************************************************************
* InstallerClass::WW3D_Shutdown -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::WW3D_Shutdown()
{
// Clear frame buffers.
for (int frame = 0; frame < 3; frame++) {
WW3D::Begin_Render (true, true, Vector3 (0.0f,0.0f,0.0f));
WW3D::End_Render();
}
// Shutdown WW3D (if previously initialized).
REF_PTR_RELEASE (UIInput);
if (DialogMgrInitialized) DialogMgrClass::Shutdown();
if (WW3D::Is_Initted()) WW3D::Shutdown();
if (AssetManager != NULL) {
AssetManager->Free_Assets();
delete AssetManager;
}
}
/***********************************************************************************************
* InstallerClass::Auto_Configure -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Auto_Configure()
{
PROCESS_INFORMATION processinfo;
STARTUPINFO startupinfo;
memset (&startupinfo, 0, sizeof (STARTUPINFO));
startupinfo.cb = sizeof (STARTUPINFO);
// Start the child process.
if (CreateProcess (NULL, // Address of module name
"WWConfig.exe -autoconfig", // Address of command line
NULL, // Address of process security attributes
NULL, // Address of thread security attributes
FALSE, // Does new process inherit handles?
0, // Creation flags
NULL, // Address of new environment block
NULL, // Address of current directory name
&startupinfo, // Address of STARTUPINFO
&processinfo)) { // Address of PROCESS_INFORMATION
// Wait until child process exits.
WaitForSingleObject (processinfo.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle (processinfo.hProcess);
CloseHandle (processinfo.hThread);
}
}
/***********************************************************************************************
* InstallerClass::Install_* -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Install_Game()
{
WWASSERT (WhatToInstallDialog != NULL);
return (WhatToInstallDialog->Install_Game());
}
bool InstallerClass::Install_WOL()
{
WWASSERT (WhatToInstallDialog != NULL);
return (WhatToInstallDialog->Install_WOL());
}
bool InstallerClass::Install_Game_Shortcut()
{
WWASSERT (WhatToInstallDialog != NULL);
return (WhatToInstallDialog->Install_Game() && WhatToInstallDialog->Install_Game_Shortcut());
}
/***********************************************************************************************
* InstallerClass::Get_Target_* -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
const WCHAR *InstallerClass::Get_Target_Game_Path (WideStringClass &path)
{
WWASSERT (GameDirectoryDialog != NULL);
return (GameDirectoryDialog->Get_Path (path));
}
const WCHAR *InstallerClass::Get_Target_WOL_Path (WideStringClass &path)
{
WWASSERT (WOLDirectoryDialog != NULL);
return (WOLDirectoryDialog->Get_Path (path));
}
const WCHAR *InstallerClass::Get_Target_Game_Folder (WideStringClass &folder)
{
WWASSERT (GameFolderDialog != NULL);
return (GameFolderDialog->Get_Folder (folder));
}
const WCHAR *InstallerClass::Get_Target_WOL_Folder (WideStringClass &folder)
{
WWASSERT (WOLFolderDialog != NULL);
return (WOLFolderDialog->Get_Folder (folder));
}
/***********************************************************************************************
* InstallerClass::Get_Target_Sub_Path -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Get_Target_Sub_Path (unsigned index, WideStringClass &subpath)
{
StringClass multibytesubdirectoryname, entryname;
WideStringClass subdirectoryname, targetpath;
char numberstring [MAX_NUMBER_STRING_LENGTH];
entryname = INI_SUBDIRECTORY_ENTRY_PREFIX;
entryname += ltoa (index, numberstring, 10);
GameIni->Get_String (multibytesubdirectoryname, INI_SUBDIRECTORY_SECTION, entryname);
subdirectoryname = multibytesubdirectoryname;
if (subdirectoryname.Get_Length() > 0) {
subpath = Get_Target_Game_Path (targetpath);
subpath += L"\\";
subpath += subdirectoryname;
return (true);
} else {
return (false);
}
}
/***********************************************************************************************
* InstallerClass::Get_Game_Size -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
__int64 InstallerClass::Get_Game_Size (bool ondisk)
{
__int64 bytecount = 0;
if (Install_Game()) {
bytecount = GameSize;
if (ondisk) {
// Account for cluster padding.
bytecount += Cluster_Padding (GameFileCount);
// Account for any .key (Encryption) and .wsu (Uninstall log) files that will be created by the Installer.
bytecount += INSTALLER_NOMINAL_BYTE_COUNT;
}
}
return (bytecount);
}
/***********************************************************************************************
* InstallerClass::Get_WOL_Size -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
__int64 InstallerClass::Get_WOL_Size (bool ondisk)
{
__int64 bytecount = 0;
if (Install_WOL()) {
bytecount = WOLSize;
if (ondisk) {
// Account for cluster padding.
bytecount += Cluster_Padding (WOLFileCount);
// Account for any .key (Encryption) and .wsu (Uninstall log) files that will be created by the Installer.
bytecount += INSTALLER_NOMINAL_BYTE_COUNT;
}
}
return (bytecount);
}
/***********************************************************************************************
* InstallerClass::Get_Total_Size -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
__int64 InstallerClass::Get_Total_Size (bool ondisk)
{
return (Get_Game_Size (ondisk) + Get_WOL_Size (ondisk));
}
/***********************************************************************************************
* InstallerClass::Get_WOL_Space_Available -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Get_WOL_Space_Available (const WideStringClass &path, __int64 &diskspace)
{
WideStringClass targetgamepath, targetwolpath;
// If the game is to be installed on the same drive, subtract game space needed from disk space available.
if (Get_Disk_Space_Available (path, diskspace)) {
if (Install_Game() && (Get_Target_Game_Path (targetgamepath) [0] == Get_Target_WOL_Path (targetwolpath) [0])) {
diskspace -= Get_Game_Size (true);
WWASSERT (diskspace >= 0);
}
return (true);
}
return (false);
}
/***********************************************************************************************
* InstallerClass:Get_Serial_Number: -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
const char *InstallerClass::Get_Serial_Number (StringClass &serialnumber)
{
bool valid;
WWASSERT (SerialDialog != NULL);
valid = SerialDialog->Get_Serial_Number (serialnumber);
WWASSERT (valid);
return (serialnumber);
}
/***********************************************************************************************
* InstallerClass::Dialog_Callback -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Dialog_Callback (DialogBaseClass *dialog, int ctrl_id, int message_id, DWORD param)
{
InstallMenuDialogClass *installmenudialog = (InstallMenuDialogClass*) dialog;
// If no dialog is currently active display the welcome dialog.
if (installmenudialog == NULL) {
REGISTER_DIALOG (WelcomeDialogClass, WelcomeDialog, ())
} else {
// Is the current dialog the Welcome dialog?
if (installmenudialog->As_WelcomeDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
if (!Beta_Test()) {
REGISTER_DIALOG (LicenseDialogClass, LicenseDialog, ())
} else {
REGISTER_DIALOG (NDADialogClass, NDADialog, ())
}
return;
}
}
// Is the current dialog the NDA agreement?
if (installmenudialog->As_NDADialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (LicenseDialogClass, LicenseDialog, ())
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (WelcomeDialogClass, WelcomeDialog, ())
return;
}
}
// Is the current dialog the License dialog?
if (installmenudialog->As_LicenseDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (SerialDialogClass, SerialDialog, ())
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
if (!Beta_Test()) {
REGISTER_DIALOG (WelcomeDialogClass, WelcomeDialog, ())
} else {
REGISTER_DIALOG (NDADialogClass, NDADialog, ())
}
return;
}
}
// Is the current dialog the Serial dialog?
if (installmenudialog->As_SerialDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (WhatToInstallDialogClass, WhatToInstallDialog, ())
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (LicenseDialogClass, LicenseDialog, ())
return;
}
}
// Is the current dialog the What To Install dialog?
if (installmenudialog->As_WhatToInstallDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
// Does the user want to install the game? If not skip to WOL dialogs.
if (Install_Game()) {
REGISTER_DIALOG (GameDirectoryDialogClass, GameDirectoryDialog, ())
} else {
REGISTER_DIALOG (WOLDirectoryDialogClass, WOLDirectoryDialog, ())
}
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (SerialDialogClass, SerialDialog, ())
return;
}
}
// Is the current dialog the Game Directory dialog?
if (installmenudialog->As_GameDirectoryDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (GameFolderDialogClass, GameFolderDialog, ())
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (WhatToInstallDialogClass, WhatToInstallDialog, ())
return;
}
}
// Is the current dialog the Game Folder dialog?
if (installmenudialog->As_GameFolderDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
// Does the user want to install WOL? If not skip to Review dialog.
if (Install_WOL()) {
REGISTER_DIALOG (WOLDirectoryDialogClass, WOLDirectoryDialog, ())
} else {
REGISTER_DIALOG (ReviewDialogClass, ReviewDialog, ())
}
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (GameDirectoryDialogClass, GameDirectoryDialog, ())
return;
}
}
// Is the current dialog the Online Directory dialog?
if (installmenudialog->As_WOLDirectoryDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (WOLFolderDialogClass, WOLFolderDialog, ())
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
// Does the user want to install the game? If not skip to the What To Install dialog.
if (Install_Game()) {
REGISTER_DIALOG (GameFolderDialogClass, GameFolderDialog, ())
} else {
REGISTER_DIALOG (WhatToInstallDialogClass, WhatToInstallDialog, ())
}
return;
}
}
// Is the current dialog the Online Folder dialog?
if (installmenudialog->As_WOLFolderDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (ReviewDialogClass, ReviewDialog, ())
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (WOLDirectoryDialogClass, WOLDirectoryDialog, ())
return;
}
}
// Is the current dialog the Review dialog?
if (installmenudialog->As_ReviewDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (CopyDialogClass, CopyDialog, ())
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
// Does the user want to install WOL? If not skip to game folder.
if (Install_WOL()) {
REGISTER_DIALOG (WOLFolderDialogClass, WOLFolderDialog, ())
} else {
REGISTER_DIALOG (GameFolderDialogClass, GameFolderDialog, ())
}
return;
}
}
// Is the current dialog the Copy dialog.
if (installmenudialog->As_CopyDialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
if (((CopyDialogClass*) installmenudialog->As_CopyDialogClass())->Was_Successful()) {
// Copying was successful - advance straight to final dialog.
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (FinalDialogClass, FinalDialog, (false))
} else {
// Copying was not successful - cancel as normal.
DO_CANCEL
UNREGISTER_DIALOG (dialog)
}
return;
case IDOK:
UNREGISTER_DIALOG (dialog)
// Does the user have existing Westwood Online accounts?
if (Has_WOL_Account()) {
REGISTER_DIALOG (WOL1DialogClass, WOL1Dialog, ())
} else {
REGISTER_DIALOG (FinalDialogClass, FinalDialog, (false))
}
return;
}
}
// Is the current dialog the WOL1 dialog?
if (installmenudialog->As_WOL1DialogClass()) {
switch (ctrl_id) {
case IDC_BUTTON_YES:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (WOL2DialogClass, WOL2Dialog, ())
return;
case IDC_BUTTON_NO:
case IDCANCEL:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (FinalDialogClass, FinalDialog, (true))
return;
}
}
// Is the current dialog the WOL2 dialog?
if (installmenudialog->As_WOL2DialogClass()) {
switch (ctrl_id) {
case IDCANCEL:
case IDOK:
UNREGISTER_DIALOG (dialog)
REGISTER_DIALOG (FinalDialogClass, FinalDialog, (true))
return;
}
}
// Is the current dialog the Final dialog?
if (installmenudialog->As_FinalDialogClass()) {
switch (ctrl_id) {
case IDOK:
DO_CANCEL
UNREGISTER_DIALOG (dialog)
// Extract any information from dialogs that will be needed on program end.
if (Install_Game()) {
Get_Target_Game_Path (TargetGamePath);
if (FinalDialog->Run_Game()) {
ProgEndAction = ACTION_RUN_GAME;
} else {
if (FinalDialog->Display_Readme()) {
ProgEndAction = ACTION_DISPLAY_README;
}
}
}
return;
case IDC_BUTTON_BACK:
UNREGISTER_DIALOG (dialog)
// If WOL2Dialog exists return to it - otherwise return to WOL1Dialog.
if (WOL2Dialog != NULL) {
REGISTER_DIALOG (WOL2DialogClass, WOL2Dialog, ())
} else {
WWASSERT (WOL1Dialog != NULL);
REGISTER_DIALOG (WOL1DialogClass, WOL1Dialog, ())
}
return;
}
}
}
}
/***********************************************************************************************
* Default_On_Command -- Callback for all menu dialogs. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool CALLBACK Default_On_Command (DialogBaseClass *dialog, int ctrl_id, int message_id, DWORD param)
{
_Installer.Dialog_Callback (dialog, ctrl_id, message_id, param);
return (true);
}
/***********************************************************************************************
* WWDebug_Message_Callback -- WWDebug message callback to define the behavior of WWDEBUG_SAY()*
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void WWDebug_Message_Callback (DebugType type, const char *message)
{
OutputDebugString (message);
}
/***********************************************************************************************
* WWAssert_Callback -- WWAssert callback to define the behavior of WWASSERT(). *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void WWAssert_Callback (const char *message)
{
OutputDebugString (message);
_asm int 0x03
}
/***********************************************************************************************
* InstallerClass::Can_Use_IGR_Settings -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Can_Use_IGR_Settings()
{
return (SetupIni->Get_Hex (INI_SETUP_SECTION, INI_CAN_USE_IGR_SETTNGS_ENTRY, 0x0) > 0x0);
}
/***********************************************************************************************
* InstallerClass::Use_IGR_Settings -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Use_IGR_Settings()
{
WWASSERT (WhatToInstallDialog != NULL);
return (WhatToInstallDialog->Use_IGR_Settings());
}
/***********************************************************************************************
* InstallerClass::Beta_Test -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Beta_Test()
{
const char *ndafilename = "NDA.txt";
HANDLE handle;
WIN32_FIND_DATA finddata;
// Use existence of Beta NDA to indicate whether this is the Beta test version.
handle = FindFirstFile (ndafilename, &finddata);
if (handle != INVALID_HANDLE_VALUE) {
FindClose (handle);
return (true);
}
return (false);
}
/***********************************************************************************************
* InstallerClass::Update_Registry -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Update_Registry()
{
if (Install_Game()) {
WideStringClass installpathname, folderpath, shortcutpathname;
StringClass serialnumber, encryptedserialnumber;
DWORD languageid, sku, version;
WideStringClass pathname, gamefolder, gamepath;
DWORD major, minor;
Get_Target_Game_Path (installpathname);
installpathname += L"\\";
installpathname += RxWideStringClass (IDS_GAME_EXECUTABLE_FILENAME);
_RegistryManager.Get_Folder_Path (folderpath);
folderpath += L"\\";
folderpath += Get_Target_Game_Folder (gamefolder);
folderpath += L"\\";
folderpath += TxWideStringClass (IDS_GAME_PRODUCT_NAME, IDS_RESOURCE_GAME_PRODUCT_NAME);
_RegistryManager.Get_Desktop_Path (shortcutpathname);
shortcutpathname += L"\\";
shortcutpathname += TxWideStringClass (IDS_GAME_PRODUCT_NAME, IDS_RESOURCE_GAME_PRODUCT_NAME);
shortcutpathname += L".lnk";
languageid = SetupIni->Get_Hex (INI_SETUP_SECTION, INI_LANGUAGE_ENTRY, 0x0);
// Create encryption file in target directory.
Get_Target_Game_Path (pathname);
pathname += L"\\";
pathname += RxWideStringClass (IDS_SERIAL_ENCRYPTION_FILENAME);
Create_Encryption_File (pathname);
// Encrypt the serial no.
Encrypt (Get_Serial_Number (serialnumber), pathname, encryptedserialnumber);
sku = SetupIni->Get_Int (INI_SETUP_SECTION, INI_SKU_ENTRY, 0x0);
major = SetupIni->Get_Int (INI_SETUP_SECTION, INI_VERSION_MAJOR_ENTRY, 0x1);
minor = SetupIni->Get_Int (INI_SETUP_SECTION, INI_VERSION_MINOR_ENTRY, 0x0);
version = (major << 16) + minor;
_RegistryManager.Register_Game (TxWideStringClass (IDS_GAME_PRODUCT_NAME, IDS_RESOURCE_GAME_PRODUCT_NAME),
installpathname,
folderpath,
shortcutpathname,
languageid,
encryptedserialnumber,
sku,
version);
}
if (Install_WOL()) {
WideStringClass folderpath, wolapipathname, wolregisterpathname, wolbrowserpathname;
DWORD sku, version;
WideStringClass WOLfolder;
DWORD major, minor;
_RegistryManager.Get_Folder_Path (folderpath);
folderpath += L"\\";
folderpath += Get_Target_WOL_Folder (WOLfolder);
folderpath += L"\\";
folderpath += TxWideStringClass (IDS_WOL_PRODUCT_NAME, IDS_RESOURCE_WOL_PRODUCT_NAME);
Get_Target_WOL_Path (wolapipathname);
wolapipathname += L"\\";
wolapipathname += RxWideStringClass (IDS_WOLAPI_DLL_FILENAME);
sku = atol (RxStringClass (IDS_WOLAPI_SKU));
major = WOLIni->Get_Int (INI_WOLAPI_SECTION, INI_VERSION_MAJOR_ENTRY, 0x1);
minor = WOLIni->Get_Int (INI_WOLAPI_SECTION, INI_VERSION_MINOR_ENTRY, 0x0);
version = (major << 16) + minor;
_RegistryManager.Register_WOLAPI (folderpath,
wolapipathname,
TxWideStringClass (IDS_WOL_PRODUCT_NAME, IDS_RESOURCE_WOL_PRODUCT_NAME),
sku,
version,
Use_IGR_Settings());
Get_Target_WOL_Path (wolregisterpathname);
wolregisterpathname += L"\\";
wolregisterpathname += RxWideStringClass (IDS_INTERNET_REGISTRATION_FILENAME);
sku = atol (RxStringClass (IDS_WOLREGISTER_SKU));
major = WOLIni->Get_Int (INI_WOLREGISTER_SECTION, INI_VERSION_MAJOR_ENTRY, 0x1);
minor = WOLIni->Get_Int (INI_WOLREGISTER_SECTION, INI_VERSION_MINOR_ENTRY, 0x0);
version = (major << 16) + minor;
_RegistryManager.Register_WOLRegister (folderpath,
wolregisterpathname,
TxWideStringClass (IDS_WOLREGISTER_NAME, IDS_RESOURCE_WOLREGISTER_NAME),
sku,
version);
Get_Target_WOL_Path (wolbrowserpathname);
wolbrowserpathname += "\\";
wolbrowserpathname += RxWideStringClass (IDS_WOLBROWSER_DLL_FILENAME);
major = WOLIni->Get_Int (INI_WOLBROWSER_SECTION, INI_VERSION_MAJOR_ENTRY, 0x1);
minor = WOLIni->Get_Int (INI_WOLBROWSER_SECTION, INI_VERSION_MINOR_ENTRY, 0x0);
version = (major << 16) + minor;
_RegistryManager.Register_WOLBrowser (wolbrowserpathname,
TxWideStringClass (IDS_WOLBROWSER_NAME, IDS_RESOURCE_WOLBROWSER_NAME),
version);
// Now register the DLL's.
Register_COM_Server (wolapipathname);
Register_COM_Server (wolbrowserpathname);
}
// Update WOLAPI.
_RegistryManager.Update_WOLAPI();
}
/***********************************************************************************************
* InstallerClass::Create_Links -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Create_Links()
{
if (CoInitialize (NULL) != S_OK) FATAL_APP_ERROR (IDS_COM_ERROR);
if (Install_Game()) {
WideStringClass folderpath, gamefolder, gamepathname, readmepathname;
WideStringClass readmeiconpathname, uninstallpathname, internetpathname, wwconfigpathname;
WideStringClass grabpatches ("GrabPatches");
// Create subdirectory in folder path for menu item links.
_RegistryManager.Get_Folder_Path (folderpath);
folderpath += L"\\";
folderpath += Get_Target_Game_Folder (gamefolder);
folderpath += L"\\";
folderpath += TxWideStringClass (IDS_GAME_PRODUCT_NAME, IDS_RESOURCE_GAME_PRODUCT_NAME);
Create_Directory (folderpath);
// Create Renegade menu item.
Get_Target_Game_Path (gamepathname);
gamepathname += L"\\";
gamepathname += RxWideStringClass (IDS_GAME_EXECUTABLE_FILENAME);
Create_File_Link (folderpath, TxWideStringClass (IDS_GAME_PRODUCT_NAME, IDS_RESOURCE_GAME_PRODUCT_NAME), gamepathname, gamepathname);
// Create Auto Update menu item.
Create_File_Link (folderpath, TxWideStringClass (IDS_AUTO_UPDATE_TITLE, IDS_RESOURCE_AUTO_UPDATE_TITLE), gamepathname, gamepathname, &grabpatches);
// Create Readme menu item.
Get_Target_Game_Path (readmepathname);
readmepathname += L"\\";
readmepathname += RxWideStringClass (IDS_WORD_README_FILENAME);
Get_Target_Game_Path (readmeiconpathname);
readmeiconpathname += L"\\";
readmeiconpathname += RxWideStringClass (IDS_README_ICON_FILENAME);
Create_File_Link (folderpath, TxWideStringClass (IDS_README_TITLE, IDS_RESOURCE_README_TITLE), readmepathname, readmeiconpathname);
// Create Uninstall menu item.
Get_Target_Game_Path (uninstallpathname);
uninstallpathname += L"\\";
uninstallpathname += RxWideStringClass (IDS_GAME_UNINSTALL_FILENAME);
Create_File_Link (folderpath, TxWideStringClass (IDS_GAME_UNINSTALL_TITLE, IDS_RESOURCE_GAME_UNINSTALL_TITLE), uninstallpathname, uninstallpathname);
// Create Internet Registration menu item.
Get_Target_Game_Path (internetpathname);
internetpathname += L"\\";
internetpathname += RxWideStringClass (IDS_INTERNET_REGISTRATION_FILENAME);
Create_File_Link (folderpath, TxWideStringClass (IDS_INTERNET_REGISTRATION_TITLE, IDS_RESOURCE_INTERNET_REGISTRATION_TITLE), internetpathname, internetpathname);
// Create GameSpy Arcade menu item.
// LOCALIZATION NOTE: The French have decided not to include this link.
if (SetupIni->Get_Hex (INI_SETUP_SECTION, INI_LANGUAGE_ENTRY, 0x0) != 0x3) {
Create_URL_Link (folderpath, TxWideStringClass (IDS_PLAY_ONLINE_WITH_GAMESPY, IDS_RESOURCE_PLAY_ONLINE_WITH_GAMESPY), L"http://www.gamespyarcade.com/features/launch.asp?svcname=ccrenegade&distID=391");
}
// Create link to WWConfig.
Get_Target_Game_Path (wwconfigpathname);
wwconfigpathname += L"\\";
wwconfigpathname += RxWideStringClass (IDS_WWCONFIG_FILENAME);
Create_File_Link (folderpath, TxWideStringClass (IDS_WWCONFIG_TITLE, IDS_RESOURCE_WWCONFIG_TITLE), wwconfigpathname, wwconfigpathname);
// Create desktop icon (if requested).
if (Install_Game_Shortcut()) {
WideStringClass shortcutpath;
_RegistryManager.Get_Desktop_Path (shortcutpath);
Create_File_Link (shortcutpath, TxWideStringClass (IDS_GAME_PRODUCT_NAME, IDS_RESOURCE_GAME_PRODUCT_NAME), gamepathname, gamepathname);
}
}
if (Install_WOL()) {
WideStringClass folderpath, wolfolder, registerpathname, registericonpathname, uninstallpathname;
// Create subdirectory in folder path for menu item links.
_RegistryManager.Get_Folder_Path (folderpath);
folderpath += L"\\";
folderpath += Get_Target_WOL_Folder (wolfolder);
folderpath += L"\\";
folderpath += TxWideStringClass (IDS_WOL_PRODUCT_NAME, IDS_RESOURCE_WOL_PRODUCT_NAME);
Create_Directory (folderpath);
// Create Internet Registration menu item.
Get_Target_WOL_Path (registerpathname);
registerpathname += L"\\";
registerpathname += RxWideStringClass (IDS_INTERNET_REGISTRATION_FILENAME);
Create_File_Link (folderpath, TxWideStringClass (IDS_INTERNET_REGISTRATION_TITLE, IDS_RESOURCE_INTERNET_REGISTRATION_TITLE), registerpathname, registerpathname);
// Create Uninstall Registration menu item.
Get_Target_WOL_Path (uninstallpathname);
uninstallpathname += L"\\";
uninstallpathname += RxWideStringClass (IDS_WOL_UNINSTALL_FILENAME);
Create_File_Link (folderpath, TxWideStringClass (IDS_WOL_UNINSTALL_TITLE, IDS_RESOURCE_WOL_UNINSTALL_TITLE), uninstallpathname, uninstallpathname);
}
CoUninitialize();
}
/***********************************************************************************************
* InstallerClass::Create_File_Link -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Create_File_Link (const WideStringClass &linkpath, const WideStringClass &title, const WideStringClass &targetpathname, const WideStringClass &iconpathname, const WideStringClass *arguments)
{
WideStringClass linkpathname, trimmedtitle, targetpath;
StringClass multibytelinkpathname, multibytetargetpath, multibytetitle, multibytetargetpathname, multibyteiconpathname;
IShellLink *psl;
IPersistFile *ppf;
bool success;
// The title is used in a pathname so it should be freed of any leading or trailing whitespace.
trimmedtitle = title;
trimmedtitle.Trim();
linkpathname = linkpath;
linkpathname += L"\\";
linkpathname += trimmedtitle;
linkpathname += L".lnk";
targetpath = targetpathname;
Remove_Trailing_Name (targetpath);
multibytelinkpathname = linkpathname;
multibytetargetpath = targetpath;
multibytetitle = trimmedtitle;
multibytetargetpathname = targetpathname;
multibyteiconpathname = iconpathname;
// Remove previous icon (if it exists).
DeleteFile (multibytelinkpathname);
success = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**) &psl) == S_OK;
if (success) {
try {
if (psl->SetPath (multibytetargetpathname) != NOERROR) throw (IDS_COM_ERROR);
if (psl->SetDescription (multibytetitle) != NOERROR) throw (IDS_COM_ERROR);
if (psl->SetIconLocation (multibyteiconpathname, 0) != NOERROR) throw (IDS_COM_ERROR);
if (arguments != NULL) {
StringClass multibytearguments (*arguments);
if (psl->SetArguments (multibytearguments) != NOERROR) throw (IDS_COM_ERROR);
}
if (psl->SetWorkingDirectory (multibytetargetpath) != NOERROR) throw (IDS_COM_ERROR);
if (psl->SetShowCmd (SW_NORMAL) != NOERROR) throw (IDS_COM_ERROR);
if (psl->SetHotkey (0) != NOERROR) throw (IDS_COM_ERROR);
if (psl->QueryInterface (IID_IPersistFile, (void**) &ppf) == S_OK) {
success = ppf->Save (linkpathname, TRUE) == S_OK;
ppf->Release();
}
} catch (...) {
success = false;
}
psl->Release();
}
return (success);
}
/***********************************************************************************************
* InstallerClass::Create_URL_Link -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Create_URL_Link (const WideStringClass &linkpath, const WideStringClass &title, const WideStringClass &url)
{
WideStringClass trimmedtitle, linkpathname;
StringClass multibytelinkpathname, multibyteurl;
IUniformResourceLocator *purl;
IPersistFile *ppf;
bool success;
// The title is used in a pathname so it should be freed of any leading or trailing whitespace.
trimmedtitle = title;
trimmedtitle.Trim();
linkpathname = linkpath;
linkpathname += L"\\";
linkpathname += trimmedtitle;
linkpathname += L".url";
multibytelinkpathname = linkpathname;
multibyteurl = url;
// Remove previous icon (if it exists).
DeleteFile (multibytelinkpathname);
// Create an IUniformResourceLocator object
success = CoCreateInstance (CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, IID_IUniformResourceLocator, (void**) &purl) == S_OK;
if (success) {
success = purl->SetURL (multibyteurl, 0) == S_OK;
if (success) {
success = purl->QueryInterface (IID_IPersistFile, (void**) &ppf) == S_OK;
if (success) {
success = ppf->Save (linkpathname, TRUE) == S_OK;
ppf->Release();
}
}
purl->Release();
}
return (success);
}
/***********************************************************************************************
* InstallerClass::Has_WOL_Account -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Has_WOL_Account()
{
WideStringClass name, password;
return (_RegistryManager.Get_WOL_Account (0, name, password));
}
/***********************************************************************************************
* InstallerClass::Get_WOL_Account -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Get_WOL_Account (unsigned index, WideStringClass &name, WideStringClass &password)
{
return (_RegistryManager.Get_WOL_Account (index, name, password));
}
/***********************************************************************************************
* InstallerClass::Log -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Log (const WideStringClass &pathname, __int64 size)
{
WideStringClass path;
if (Install_Game()) {
// Does the start of the pathname match either the game or WOL target path?
if (wcsstr (pathname, Get_Target_Game_Path (path)) != NULL) {
if (size == -1) {
WideStringClass subdirectoryname (((WideStringClass) pathname).Peek_Buffer() + path.Get_Length() + 1);
GameSubdirectories.Add (subdirectoryname);
} else {
FileLogClass filelog;
filelog.RelativePathname = ((WideStringClass) pathname).Peek_Buffer() + path.Get_Length() + 1;
filelog.Size = size;
GameFiles.Add (filelog);
}
return;
}
}
if (Install_WOL()) {
if (wcsstr (pathname, Get_Target_WOL_Path (path)) != NULL) {
FileLogClass filelog;
// NOTE: Logging WOL subdirectories is not supported.
WWASSERT (size != -1);
filelog.RelativePathname = ((WideStringClass) pathname).Peek_Buffer() + path.Get_Length() + 1;
filelog.Size = size;
WOLFiles.Add (filelog);
}
}
}
/***********************************************************************************************
* InstallerClass::Create_Uninstall_Logs -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Create_Uninstall_Logs()
{
if (Install_Game()) {
Create_Game_Uninstall_Log();
}
if (Install_WOL()) {
Create_WOL_Uninstall_Log();
}
}
/***********************************************************************************************
* InstallerClass::Create_Game_Uninstall_Log -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Create_Game_Uninstall_Log()
{
WideStringClass log;
WideStringClass installpathname, folderpath, gamefolder, shortcutpath;
WideStringClass s;
WideStringClass logfilepathname;
WideStringClass gamefilepathname;
HANDLE handle;
int i;
DWORD byteswritten;
StringClass multibytelogfilepathname, multibytelog;
__int64 totalfilesize;
_RegistryManager.Get_Folder_Path (folderpath);
_RegistryManager.Get_Desktop_Path (shortcutpath);
// Log temporary files that will/may be created by the game.
Get_Target_Game_Path (gamefilepathname);
gamefilepathname += L"\\";
gamefilepathname += L"commands.txt";
Log (gamefilepathname, 0);
Get_Target_Game_Path (gamefilepathname);
gamefilepathname += L"\\";
gamefilepathname += L"_logfile.txt";
Log (gamefilepathname, 0);
Get_Target_Game_Path (gamefilepathname);
gamefilepathname += L"\\";
gamefilepathname += L"_asserts.txt";
Log (gamefilepathname, 0);
Get_Target_Game_Path (gamefilepathname);
gamefilepathname += L"\\";
gamefilepathname += L"_except.txt";
Log (gamefilepathname, 0);
Get_Target_Game_Path (gamefilepathname);
gamefilepathname += L"\\";
gamefilepathname += L"sysinfo.txt";
Log (gamefilepathname, 0);
Get_Target_Game_Path (gamefilepathname);
gamefilepathname += L"\\";
gamefilepathname += L"history.txt";
Log (gamefilepathname, 0);
Get_Target_Game_Path (gamefilepathname);
gamefilepathname += L"\\";
gamefilepathname += L"asset_report.txt";
Log (gamefilepathname, 0);
// Create log pathname and log this file so it gets written to the uninstall log.
// NOTE: File size is not important - substitute zero.
Get_Target_Game_Path (logfilepathname);
logfilepathname += L"\\";
logfilepathname += RxWideStringClass (IDS_GAME_UNINSTALL_LOG_FILENAME);
Log (logfilepathname, 0);
// Build the log.
log += L"[Product]\n";
log += L"Name=";
log += TxWideStringClass (IDS_GAME_PRODUCT_NAME, IDS_RESOURCE_GAME_PRODUCT_NAME);
log += L"\n";
log += L"FullName=";
log += TxWideStringClass (IDS_VERBOSE_GAME_PRODUCT_NAME, IDS_RESOURCE_VERBOSE_GAME_PRODUCT_NAME);
log += L"\n";
log += L"Key=";
log += RxWideStringClass (IDS_GAME_PRODUCT_KEY);
log += L"\n";
log += L"Exe=";
log += Get_Target_Game_Path (installpathname);
log += L"\\";
log += RxWideStringClass (IDS_GAME_EXECUTABLE_FILENAME);
log += L"\n\n";
log += L"[Icons]\n";
log += L"LNK=";
log += folderpath;
log += L"\\";
log += Get_Target_Game_Folder (gamefolder);
log += L"\\";
log += TxWideStringClass (IDS_GAME_PRODUCT_NAME, IDS_RESOURCE_GAME_PRODUCT_NAME);
log += L"\n";
log += L"Desktop=";
log += shortcutpath;
log += L"\\";
log += TxWideStringClass (IDS_GAME_PRODUCT_NAME, IDS_RESOURCE_GAME_PRODUCT_NAME);
log += L".lnk";
log += L"\n\n";
// Append subdirectory information.
log += L"[SubDirectories]\n";
for (i = 0; i < GameSubdirectories.Count(); i++) {
s.Format (L"Dir%d=%s\n", i, GameSubdirectories [i]);
log += s;
}
s.Format (L"NumFiles=%u\n\n", GameSubdirectories.Count());
log += s;
// Append relative pathname information.
log += L"[Files]\n";
for (i = 0; i < GameFiles.Count(); i++) {
s.Format (L"F:%d=%s\n", i, GameFiles [i].RelativePathname);
log += s;
}
s.Format (L"NumFiles=%u\n\n", GameFiles.Count());
log += s;
// Append relative file size information.
log += L"[FileSizes]\n";
totalfilesize = 0;
for (i = 0; i < GameFiles.Count(); i++) {
s.Format (L"S:%d=%I64d\n", i, GameFiles [i].Size);
log += s;
totalfilesize += GameFiles [i].Size;
}
s.Format (L"Total=%I64d\n", totalfilesize);
log += s;
// Write the log file.
// NOTE: Convert strings from wide to multibyte.
multibytelogfilepathname = logfilepathname;
handle = CreateFile (multibytelogfilepathname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE) FATAL_SYSTEM_ERROR;
multibytelog = log;
if (!WriteFile (handle, multibytelog.Peek_Buffer(), multibytelog.Get_Length() * sizeof (TCHAR), &byteswritten, NULL)) FATAL_SYSTEM_ERROR;
if (!CloseHandle (handle)) FATAL_SYSTEM_ERROR;
}
/***********************************************************************************************
* InstallerClass::Create_WOL_Uninstall_Log -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Create_WOL_Uninstall_Log()
{
WideStringClass log;
WideStringClass s;
WideStringClass logfilepathname;
HANDLE handle;
int i;
DWORD byteswritten;
StringClass multibytelogfilepathname, multibytelog;
// Create log pathname and log this file so it gets written to the uninstall log.
// NOTE: File size is not important - substitute zero.
Get_Target_WOL_Path (logfilepathname);
logfilepathname += L"\\";
logfilepathname += RxWideStringClass (IDS_WOL_UNINSTALL_LOG_FILENAME);
Log (logfilepathname, 0);
// Append relative pathname information.
for (i = 0; i < WOLFiles.Count(); i++) {
s.Format (L"%s\n", WOLFiles [i].RelativePathname);
log += s;
}
// Write the log file.
multibytelogfilepathname = logfilepathname;
handle = CreateFile (multibytelogfilepathname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE) FATAL_SYSTEM_ERROR;
multibytelog = log;
if (!WriteFile (handle, multibytelog.Peek_Buffer(), multibytelog.Get_Length() * sizeof (TCHAR), &byteswritten, NULL)) FATAL_SYSTEM_ERROR;
if (!CloseHandle (handle)) FATAL_SYSTEM_ERROR;
}
/***********************************************************************************************
* InstallerClass::Create_Encryption_File -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Create_Encryption_File (const WideStringClass &pathname)
{
StringClass multibytepathname (pathname);
char stringbuffer [ENCRYPTION_STRING_LENGTH];
HANDLE handle;
DWORD byteswritten;
handle = CreateFile (multibytepathname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if (handle == INVALID_HANDLE_VALUE) FATAL_SYSTEM_ERROR;
// Seed the random no. generator.
srand (timeGetTime());
for (unsigned i = 0; i < ENCRYPTION_STRING_LENGTH; i++) {
char digit;
digit = rand() % 10;
stringbuffer [i] = digit + '0';
}
if (!WriteFile (handle, stringbuffer, sizeof (stringbuffer), &byteswritten, NULL)) FATAL_SYSTEM_ERROR;
if (!CloseHandle (handle)) FATAL_SYSTEM_ERROR;
// Log the file so it gets written to the uninstall log.
// NOTE: File size is not important - substitute zero.
Log (pathname, 0);
}
/***********************************************************************************************
* InstallerClass::Encrypt -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Encrypt (const char *number, const WideStringClass &pathname, StringClass &encryptednumber)
{
StringClass multibytepathname (pathname);
char *s;
int numberlength;
HANDLE handle;
DWORD bytesread;
char stringbuffer [ENCRYPTION_STRING_LENGTH];
int p;
numberlength = strlen (number);
s = new char [numberlength + 1];
memcpy (s, number, numberlength + 1);
handle = CreateFile (multibytepathname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (handle == INVALID_HANDLE_VALUE) FATAL_SYSTEM_ERROR;
if (!ReadFile (handle, stringbuffer, sizeof (stringbuffer), &bytesread, NULL)) FATAL_SYSTEM_ERROR;
p = 0;
for (unsigned i = 0; i < ENCRYPTION_STRING_LENGTH; i++) {
int t;
char c;
t = s [p] - '0';
t %= 10;
t += stringbuffer [i];
t %= 10;
c = t + '0';
s [p] = c;
p++;
if (p == numberlength) p = 0;
}
encryptednumber = s;
// Clean-up.
delete [] s;
}
/***********************************************************************************************
* InstallerClass::Register_COM_Server -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
bool InstallerClass::Register_COM_Server (const WideStringClass &comdll)
{
StringClass multibytecomdll (comdll);
HMODULE module = LoadLibrary (multibytecomdll);
if (module) {
HRESULT hr = E_FAIL;
DLLREGISTERSERVER dllRegister = (DLLREGISTERSERVER) GetProcAddress (module, "DllRegisterServer");
if (dllRegister) {
hr = dllRegister();
}
FreeLibrary (module);
module = NULL;
return (SUCCEEDED (hr));
}
return (false);
}
/***********************************************************************************************
* InstallerClass::Finish -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::On_Prog_End()
{
switch (ProgEndAction) {
case ACTION_NONE:
break;
case ACTION_RUN_GAME:
Run_Game();
break;
case ACTION_DISPLAY_README:
Display_Readme();
break;
}
}
/***********************************************************************************************
* InstallerClass::Run_Game -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Run_Game()
{
WideStringClass modulepathname;
StringClass multibytemodulepathname, multibytetargetgamepath;
PROCESS_INFORMATION processinfo;
STARTUPINFO startupinfo;
modulepathname = TargetGamePath;
modulepathname += L"\\";
modulepathname += RxWideStringClass (IDS_GAME_EXECUTABLE_FILENAME);
multibytemodulepathname = modulepathname;
multibytetargetgamepath = TargetGamePath;
memset (&startupinfo, 0, sizeof (STARTUPINFO));
startupinfo.cb = sizeof (STARTUPINFO);
if (!CreateProcess (multibytemodulepathname.Peek_Buffer(), // Address of module name
NULL, // Address of command line
NULL, // Address of process security attributes
NULL, // Address of thread security attributes
FALSE, // Does new process inherit handles?
CREATE_NEW_PROCESS_GROUP | NORMAL_PRIORITY_CLASS, // Creation flags
NULL, // Address of new environment block
multibytetargetgamepath.Peek_Buffer(), // Address of current directory name
&startupinfo, // Address of STARTUPINFO
&processinfo)) { // Address of PROCESS_INFORMATION
FATAL_SYSTEM_ERROR;
}
}
/***********************************************************************************************
* InstallerClass::Display_Readme -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 08/22/01 IML : Created. *
*=============================================================================================*/
void InstallerClass::Display_Readme()
{
const unsigned applicationcount = 3;
const WCHAR *winwordprogramname = L"WINWORD.EXE";
const WCHAR *wordprocessornames [applicationcount] = {L"Wordpad.exe", L"Notepad.exe", L"Write.exe"};
WideStringClass pathname;
WCHAR docapppathname [_MAX_PATH];
WCHAR *t;
unsigned i;
PROCESS_INFORMATION processinfo;
STARTUPINFO startupinfo;
WideStringClass commandline;
StringClass multibytecommandline;
BOOL success = false;
// See if Winword is the owner of .doc files.
_RegistryManager.Get_Document_Application_Pathname (pathname);
wcscpy (docapppathname, pathname);
_wcsupr (docapppathname);
t = wcsstr (docapppathname, winwordprogramname);
if (t != NULL) {
t += wcslen (winwordprogramname);
*t = L'\0';
// Launch Winword with the Readme.doc file.
commandline = docapppathname;
commandline += L" \"";
commandline += TargetGamePath;
commandline += L"\\";
commandline += RxWideStringClass (IDS_WORD_README_FILENAME);
commandline += L"\"";
memset (&startupinfo, 0, sizeof (STARTUPINFO));
startupinfo.cb = sizeof (STARTUPINFO);
multibytecommandline = commandline;
success = CreateProcess (NULL, // Address of module name
multibytecommandline.Peek_Buffer(), // Address of command line
NULL, // Address of process security attributes
NULL, // Address of thread security attributes
FALSE, // Does new process inherit handles?
CREATE_NEW_PROCESS_GROUP | NORMAL_PRIORITY_CLASS, // Creation flags
NULL, // Address of new environment block
NULL, // Address of current directory name
&startupinfo, // Address of STARTUPINFO
&processinfo); // Address of PROCESS_INFORMATION
}
// No success? Try to launch any of the common text processor applications with the Readme.txt file.
i = 0;
while ((!success) && (i < applicationcount)) {
commandline = wordprocessornames [i];
commandline += L" \"";
commandline += TargetGamePath;
commandline += L"\\";
commandline += RxWideStringClass (IDS_TEXT_README_FILENAME);
commandline += L"\"";
memset (&startupinfo, 0, sizeof (STARTUPINFO));
startupinfo.cb = sizeof (STARTUPINFO);
multibytecommandline = commandline;
success = CreateProcess (NULL, // Address of module name
multibytecommandline.Peek_Buffer(), // Address of command line
NULL, // Address of process security attributes
NULL, // Address of thread security attributes
FALSE, // Does new process inherit handles?
CREATE_NEW_PROCESS_GROUP | NORMAL_PRIORITY_CLASS, // Creation flags
NULL, // Address of new environment block
NULL, // Address of current directory name
&startupinfo, // Address of STARTUPINFO
&processinfo); // Address of PROCESS_INFORMATION
i++;
}
// If still no success, throw error.
if (!success) FATAL_SYSTEM_ERROR;
}
#undef END_DIALOG
#undef REGISTER_DIALOG
#undef UNREGISTER_DIALOG
#undef DO_CANCEL