Skip to content

Commit 9d06998

Browse files
committed
fix(replay): prevent crash when replay deleted during version mismatch prompt
1 parent d81e743 commit 9d06998

File tree

4 files changed

+66
-4
lines changed

4 files changed

+66
-4
lines changed

Generals/Code/GameEngine/Source/Common/Recorder.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,8 @@ Bool RecorderClass::playbackFile(AsciiString filename)
11921192
}
11931193
}
11941194

1195-
m_mode = RECORDERMODETYPE_PLAYBACK;
1195+
// TheSuperHackers @bugfix bobtista Don't set playback mode until after file opens successfully
1196+
// to prevent crash if playback is updated while m_file is NULL
11961197

11971198
ReplayHeader header;
11981199
header.forPlayback = TRUE;
@@ -1203,6 +1204,8 @@ Bool RecorderClass::playbackFile(AsciiString filename)
12031204
return FALSE;
12041205
}
12051206

1207+
m_mode = RECORDERMODETYPE_PLAYBACK;
1208+
12061209
#ifdef DEBUG_CRASHING
12071210
Bool versionStringDiff = header.versionString != TheVersion->getUnicodeVersion();
12081211
Bool versionTimeStringDiff = header.versionTimeString != TheVersion->getUnicodeBuildTime();

Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,13 @@ static GameWindow *buttonAnalyzeReplay = NULL;
8282

8383
void deleteReplay( void );
8484
void copyReplay( void );
85+
void showReplayNotFoundError( void );
8586
static Bool callCopy = FALSE;
8687
static Bool callDelete = FALSE;
88+
static Bool callShowReplayNotFound = FALSE;
8789
void deleteReplayFlag( void ) { callDelete = TRUE;}
8890
void copyReplayFlag( void ) { callCopy = TRUE;}
91+
void showReplayNotFoundFlag( void ) { callShowReplayNotFound = TRUE;}
8992

9093
UnicodeString GetReplayFilenameFromListbox(GameWindow *listbox, Int index)
9194
{
@@ -462,6 +465,8 @@ void ReplayMenuUpdate( WindowLayout *layout, void *userData )
462465
copyReplay();
463466
if(callDelete)
464467
deleteReplay();
468+
if(callShowReplayNotFound)
469+
showReplayNotFoundError();
465470
// We'll only be successful if we've requested to
466471
if(isShuttingDown && TheShell->isAnimFinished()&& TheTransitionHandler->isFinished())
467472
TheShell->shutdownComplete( layout );
@@ -534,7 +539,22 @@ void reallyLoadReplay(void)
534539
AsciiString asciiFilename;
535540
asciiFilename.translate(filename);
536541

537-
TheRecorder->playbackFile(asciiFilename);
542+
// TheSuperHackers @bugfix bobtista Validate file exists before playback to prevent crash when deleted during version mismatch prompt
543+
AsciiString filepath = TheRecorder->getReplayDir();
544+
filepath.concat(asciiFilename.str());
545+
546+
File *testFile = TheFileSystem->openFile(filepath.str(), File::READ | File::BINARY);
547+
if (testFile == NULL)
548+
{
549+
showReplayNotFoundFlag();
550+
return;
551+
}
552+
testFile->close();
553+
554+
if(!TheRecorder->playbackFile(asciiFilename))
555+
{
556+
return;
557+
}
538558

539559
if(parentReplayMenu != NULL)
540560
{
@@ -797,3 +817,11 @@ void copyReplay( void )
797817

798818
}
799819

820+
void showReplayNotFoundError( void )
821+
{
822+
callShowReplayNotFound = FALSE;
823+
UnicodeString title = TheGameText->FETCH_OR_SUBSTITUTE("GUI:ReplayFileNotFoundTitle", L"REPLAY NOT FOUND");
824+
UnicodeString body = TheGameText->FETCH_OR_SUBSTITUTE("GUI:ReplayFileNotFound", L"This replay cannot be loaded because the file no longer exists on this device.");
825+
MessageBoxOk(title, body, NULL);
826+
}
827+

GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,8 @@ Bool RecorderClass::playbackFile(AsciiString filename)
11951195
}
11961196
}
11971197

1198-
m_mode = RECORDERMODETYPE_PLAYBACK;
1198+
// TheSuperHackers @bugfix bobtista Don't set playback mode until after file opens successfully
1199+
// to prevent crash if playback is updated while m_file is NULL
11991200

12001201
ReplayHeader header;
12011202
header.forPlayback = TRUE;
@@ -1206,6 +1207,8 @@ Bool RecorderClass::playbackFile(AsciiString filename)
12061207
return FALSE;
12071208
}
12081209

1210+
m_mode = RECORDERMODETYPE_PLAYBACK;
1211+
12091212
#ifdef DEBUG_CRASHING
12101213
Bool versionStringDiff = header.versionString != TheVersion->getUnicodeVersion();
12111214
Bool versionTimeStringDiff = header.versionTimeString != TheVersion->getUnicodeBuildTime();

GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,13 @@ static GameWindow *buttonAnalyzeReplay = NULL;
8282

8383
void deleteReplay( void );
8484
void copyReplay( void );
85+
void showReplayNotFoundError( void );
8586
static Bool callCopy = FALSE;
8687
static Bool callDelete = FALSE;
88+
static Bool callShowReplayNotFound = FALSE;
8789
void deleteReplayFlag( void ) { callDelete = TRUE;}
8890
void copyReplayFlag( void ) { callCopy = TRUE;}
91+
void showReplayNotFoundFlag( void ) { callShowReplayNotFound = TRUE;}
8992

9093
UnicodeString GetReplayFilenameFromListbox(GameWindow *listbox, Int index)
9194
{
@@ -462,6 +465,8 @@ void ReplayMenuUpdate( WindowLayout *layout, void *userData )
462465
copyReplay();
463466
if(callDelete)
464467
deleteReplay();
468+
if(callShowReplayNotFound)
469+
showReplayNotFoundError();
465470
// We'll only be successful if we've requested to
466471
if(isShuttingDown && TheShell->isAnimFinished()&& TheTransitionHandler->isFinished())
467472
TheShell->shutdownComplete( layout );
@@ -534,7 +539,22 @@ void reallyLoadReplay(void)
534539
AsciiString asciiFilename;
535540
asciiFilename.translate(filename);
536541

537-
TheRecorder->playbackFile(asciiFilename);
542+
// TheSuperHackers @bugfix bobtista Validate file exists before playback to prevent crash when deleted during version mismatch prompt
543+
AsciiString filepath = TheRecorder->getReplayDir();
544+
filepath.concat(asciiFilename.str());
545+
546+
File *testFile = TheFileSystem->openFile(filepath.str(), File::READ | File::BINARY);
547+
if (testFile == NULL)
548+
{
549+
showReplayNotFoundFlag();
550+
return;
551+
}
552+
testFile->close();
553+
554+
if(!TheRecorder->playbackFile(asciiFilename))
555+
{
556+
return;
557+
}
538558

539559
if(parentReplayMenu != NULL)
540560
{
@@ -797,3 +817,11 @@ void copyReplay( void )
797817

798818
}
799819

820+
void showReplayNotFoundError( void )
821+
{
822+
callShowReplayNotFound = FALSE;
823+
UnicodeString title = TheGameText->FETCH_OR_SUBSTITUTE("GUI:ReplayFileNotFoundTitle", L"REPLAY NOT FOUND");
824+
UnicodeString body = TheGameText->FETCH_OR_SUBSTITUTE("GUI:ReplayFileNotFound", L"This replay cannot be loaded because the file no longer exists on this device.");
825+
MessageBoxOk(title, body, NULL);
826+
}
827+

0 commit comments

Comments
 (0)