Skip to content

Commit be10139

Browse files
committed
Refactor Main.cpp (loader) with improved reliability and code quality
1 parent 45d6996 commit be10139

File tree

1 file changed

+179
-72
lines changed

1 file changed

+179
-72
lines changed

Client/loader/Main.cpp

Lines changed: 179 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,149 @@
1515
#include "Dialogs.h"
1616
#include "Utils.h"
1717
#include "SharedUtil.Win32Utf8FileHooks.hpp"
18+
1819
#if defined(MTA_DEBUG)
1920
#include "SharedUtil.Tests.hpp"
2021
#endif
22+
2123
#include <version.h>
24+
#include <memory>
25+
#include <algorithm>
26+
27+
namespace {
28+
// Constants
29+
constexpr size_t MAX_CMD_LINE_LENGTH = 4096;
30+
constexpr int ERROR_NULL_INSTANCE = -1;
31+
constexpr int ERROR_NULL_INSTALL_MANAGER = -2;
32+
constexpr int ERROR_LAUNCH_EXCEPTION = -3;
33+
constexpr int ERROR_INSTALL_CONTINUE = -4;
34+
35+
// Report log IDs
36+
constexpr int LOG_ID_END = 1044;
37+
constexpr int LOG_ID_CONTINUE_EXCEPTION = 1045;
38+
constexpr int LOG_ID_LAUNCH_EXCEPTION = 1046;
39+
40+
class Utf8FileHooksGuard {
41+
public:
42+
Utf8FileHooksGuard() { AddUtf8FileHooks(); }
43+
~Utf8FileHooksGuard() { RemoveUtf8FileHooks(); }
44+
45+
// Disable copy and move
46+
Utf8FileHooksGuard(const Utf8FileHooksGuard&) = delete;
47+
Utf8FileHooksGuard& operator=(const Utf8FileHooksGuard&) = delete;
48+
Utf8FileHooksGuard(Utf8FileHooksGuard&&) = delete;
49+
Utf8FileHooksGuard& operator=(Utf8FileHooksGuard&&) = delete;
50+
};
51+
52+
inline void SafeCopyCommandLine(LPSTR lpCmdLine, char* safeCmdLine, size_t bufferSize) {
53+
if (!lpCmdLine || !safeCmdLine || bufferSize == 0) {
54+
return;
55+
}
56+
57+
const size_t maxCopyLen = bufferSize - 1;
58+
const size_t cmdLineLen = strnlen(lpCmdLine, maxCopyLen);
59+
60+
memcpy(safeCmdLine, lpCmdLine, cmdLineLen);
61+
safeCmdLine[cmdLineLen] = '\0';
62+
}
63+
64+
65+
inline DWORD GetSafeProcessId() noexcept {
66+
try {
67+
return GetCurrentProcessId();
68+
}
69+
catch (...) {
70+
return 0;
71+
}
72+
}
73+
74+
bool PerformInitialization(const char* safeCmdLine) {
75+
auto* pInstallManager = GetInstallManager();
76+
if (!pInstallManager) {
77+
return false;
78+
}
79+
80+
// Configure install manager
81+
pInstallManager->SetMTASAPathSource(safeCmdLine);
82+
83+
// Initialize logging
84+
BeginEventLog();
85+
86+
// Start localization (non-critical, continue on failure)
87+
InitLocalization(false);
88+
89+
// Handle installer commands
90+
HandleSpecialLaunchOptions();
91+
92+
// Ensure single instance
93+
HandleDuplicateLaunching();
94+
95+
// Clear any pending operations
96+
ClearPendingBrowseToSolution();
97+
98+
// Validate GTA installation
99+
ValidateGTAPath();
100+
101+
return true;
102+
}
103+
104+
void PerformPreLaunchSetup(HINSTANCE hInstance) {
105+
// Ensure localization is fully initialized
106+
InitLocalization(true);
107+
108+
// Initialize monitoring systems
109+
PreLaunchWatchDogs();
110+
111+
// Handle custom configurations
112+
HandleCustomStartMessage();
113+
114+
#if !defined(MTA_DEBUG) && MTASA_VERSION_TYPE != VERSION_TYPE_CUSTOM
115+
ForbodenProgramsMessage();
116+
#endif
117+
118+
// Maintenance operations
119+
CycleEventLog();
120+
BsodDetectionPreLaunch();
121+
MaybeShowCopySettingsDialog();
122+
123+
// Check for conflicts
124+
HandleIfGTAIsAlreadyRunning();
125+
126+
// Maybe warn user if no anti-virus running
127+
CheckAntiVirusStatus();
128+
129+
// Show splash screen
130+
ShowSplash(hInstance);
131+
132+
// Verify integrity
133+
CheckDataFiles();
134+
CheckLibVersions();
135+
}
136+
137+
SString ContinueUpdateProcedure(CInstallManager* pInstallManager) {
138+
if (!pInstallManager) {
139+
return SString();
140+
}
141+
142+
try {
143+
return pInstallManager->Continue();
144+
}
145+
catch (...) {
146+
AddReportLog(LOG_ID_CONTINUE_EXCEPTION, "Exception in InstallManager::Continue()");
147+
return SString();
148+
}
149+
}
150+
151+
int LaunchGameSafely(const SString& strCmdLine) {
152+
try {
153+
return LaunchGame(strCmdLine);
154+
}
155+
catch (...) {
156+
AddReportLog(LOG_ID_LAUNCH_EXCEPTION, "Exception in LaunchGame()");
157+
return ERROR_LAUNCH_EXCEPTION;
158+
}
159+
}
160+
}
22161

23162
///////////////////////////////////////////////////////////////
24163
//
@@ -28,100 +167,68 @@
28167
// 1. During install with /kdinstall command (as admin)
29168
// 2. During uninstall with /kduninstall command (as admin)
30169
// 3. By 'MTA San Andreas.exe' when temporary elevated privileges are required (as admin)
31-
// 4. By 'MTA San Andreas.exe' during auto-update (in a temporary directory somewhere) (Which may then call it again as admin)
170+
// 4. By 'MTA San Andreas.exe' during auto-update (in a temporary directory somewhere)
171+
// (Which may then call it again as admin)
32172
//
33173
///////////////////////////////////////////////////////////////
34-
MTAEXPORT int DoWinMain(HINSTANCE hLauncherInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
174+
MTAEXPORT int DoWinMain(HINSTANCE hLauncherInstance, HINSTANCE hPrevInstance,
175+
LPSTR lpCmdLine, int nCmdShow)
35176
{
36-
AddUtf8FileHooks();
177+
// Validate critical parameters
178+
if (!hLauncherInstance) {
179+
return ERROR_NULL_INSTANCE;
180+
}
37181

38-
#if defined(MTA_DEBUG)
182+
// RAII guard for UTF8 file hooks
183+
Utf8FileHooksGuard utf8Guard;
184+
185+
// Run debug tests if in debug mode
186+
#if defined(MTA_DEBUG)
39187
SharedUtil_Tests();
40-
#endif
188+
#endif
189+
190+
// Prepare safe command line buffer
191+
char safeCmdLine[MAX_CMD_LINE_LENGTH] = {0};
192+
SafeCopyCommandLine(lpCmdLine, safeCmdLine, sizeof(safeCmdLine));
41193

42194
//
43-
// Init
195+
// Initialization Phase
44196
//
197+
if (!PerformInitialization(safeCmdLine)) {
198+
return ERROR_NULL_INSTALL_MANAGER;
199+
}
45200

46-
// Let install manager figure out what MTASA path to use
47-
GetInstallManager()->SetMTASAPathSource(lpCmdLine);
48-
49-
// Start logging.....now
50-
BeginEventLog();
51-
52-
// Start localization if possible
53-
InitLocalization(false);
54-
55-
// Handle commands from the installer
56-
HandleSpecialLaunchOptions();
57-
58-
// Check MTA is launched only once
59-
HandleDuplicateLaunching();
60-
61-
// Show logo
62-
ShowSplash(g_hInstance);
63-
64-
// Other init stuff
65-
ClearPendingBrowseToSolution();
66-
67-
// Find GTA path to use
68-
ValidateGTAPath();
201+
// Show initial splash screen
202+
ShowSplash(hLauncherInstance);
69203

70204
//
71-
// Update
205+
// Update Phase
72206
//
73-
74-
// Continue any update procedure
75-
SString strCmdLine = GetInstallManager()->Continue();
207+
auto* pInstallManager = GetInstallManager();
208+
const SString strCmdLine = ContinueUpdateProcedure(pInstallManager);
76209

77210
//
78-
// Launch
211+
// Pre-Launch Phase
79212
//
213+
PerformPreLaunchSetup(hLauncherInstance);
80214

81-
// Ensure localization is started
82-
InitLocalization(true);
83-
84-
// Setup/test various counters and flags for monitoring problems
85-
PreLaunchWatchDogs();
86-
87-
// Stuff
88-
HandleCustomStartMessage();
89-
#if !defined(MTA_DEBUG) && MTASA_VERSION_TYPE != VERSION_TYPE_CUSTOM
90-
ForbodenProgramsMessage();
91-
#endif
92-
CycleEventLog();
93-
BsodDetectionPreLaunch();
94-
MaybeShowCopySettingsDialog();
95-
96-
// Make sure GTA is not running
97-
HandleIfGTAIsAlreadyRunning();
98-
99-
// Maybe warn user if no anti-virus running
100-
CheckAntiVirusStatus();
101-
102-
// Ensure logo is showing
103-
ShowSplash(g_hInstance);
104-
105-
// Check MTA files look good
106-
CheckDataFiles();
107-
CheckLibVersions();
108-
109-
// Go for launch
110-
int iReturnCode = LaunchGame(strCmdLine);
111-
215+
//
216+
// Launch Phase
217+
//
218+
const int iReturnCode = LaunchGameSafely(strCmdLine);
219+
220+
// Post-launch monitoring
112221
PostRunWatchDogs(iReturnCode);
113222

114223
//
115-
// Quit
224+
// Cleanup Phase
116225
//
117-
118226
HandleOnQuitCommand();
119-
120-
// Maybe show help if trouble was encountered
121227
ProcessPendingBrowseToSolution();
122228

123-
AddReportLog(1044, SString("* End (0x%X)* pid:%d", iReturnCode, GetCurrentProcessId()));
229+
// Log termination details
230+
const DWORD currentPid = GetSafeProcessId();
231+
AddReportLog(LOG_ID_END, SString("* End (0x%X)* pid:%d", iReturnCode, currentPid));
124232

125-
RemoveUtf8FileHooks();
126233
return iReturnCode;
127-
}
234+
}

0 commit comments

Comments
 (0)