From b51b74ab76dba0b851349dfb7be3f15a7b1600dd Mon Sep 17 00:00:00 2001 From: Tin Tin Hamans <5984296+tintinhamans@users.noreply.github.com> Date: Sun, 11 Oct 2026 20:50:36 +0200 Subject: [PATCH 1/3] fix(addoncompat): Close fullviewport.dat file handle after reading it (#3476) (cherry picked from commit d914b0f15808cf40c07a072c650aeb81436fb10e) --- Core/GameEngine/Source/Common/AddonCompat.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/GameEngine/Source/Common/AddonCompat.cpp b/Core/GameEngine/Source/Common/AddonCompat.cpp index 6d88feb47d6..a877ec1edda 100644 --- a/Core/GameEngine/Source/Common/AddonCompat.cpp +++ b/Core/GameEngine/Source/Common/AddonCompat.cpp @@ -29,6 +29,7 @@ Bool HasFullviewportDat() if (File* file = TheFileSystem->openFile("GenTool/fullviewport.dat", File::READ | File::BINARY)) { file->read(&value, 1); + file->close(); } return value != '0'; } From ea96e6efa182c53c9e9482267a142e73832eb8b9 Mon Sep 17 00:00:00 2001 From: Tin Tin Hamans <5984296+tintinhamans@users.noreply.github.com> Date: Tue, 13 Oct 2026 21:08:04 +0200 Subject: [PATCH 2/3] fix: Close leaked system handles in GameWindowManager, ImageCollection, MainMenuUtils (#3497) (cherry picked from commit e98d64467252a912720487b1a1bb792e8617dd13) --- Core/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp | 2 ++ .../Source/GameClient/GUI/GameWindowManagerScript.cpp | 4 +++- .../Source/GameClient/GUI/GameWindowManagerScript.cpp | 4 +++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Core/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp index 551071fd104..0db1233b077 100644 --- a/Core/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp +++ b/Core/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp @@ -776,6 +776,7 @@ int asyncGethostbyname(char * szName) /* Thread finished */ stat = 0; s_asyncDNSLookupInProgress = FALSE; + CloseHandle(s_asyncDNSThreadHandle); s_asyncDNSThreadHandle = nullptr; return( (s_asyncDNSThreadSucceeded)?LOOKUP_SUCCEEDED:LOOKUP_FAILED ); } @@ -833,6 +834,7 @@ void StopAsyncDNSCheck() MAYBE_UNUSED Int res = TerminateThread(s_asyncDNSThreadHandle, 0); (void)res; DEBUG_ASSERTCRASH(res, ("Could not terminate the Async DNS Lookup thread!")); // Thread still not killed! + CloseHandle(s_asyncDNSThreadHandle); } s_asyncDNSThreadHandle = nullptr; s_asyncDNSLookupInProgress = FALSE; diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp index e234b654278..9fc3840da7d 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp @@ -2747,7 +2747,9 @@ GameWindow *GameWindowManager::winCreateFromScript( AsciiString filenameString, { DEBUG_LOG(( "WinCreateFromScript: Error parsing layout block" )); - return FALSE; + inFile->close(); + inFile = nullptr; + return nullptr; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp index d588e90cc31..ce7723ac6d8 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp @@ -2772,7 +2772,9 @@ GameWindow *GameWindowManager::winCreateFromScript( AsciiString filenameString, { DEBUG_LOG(( "WinCreateFromScript: Error parsing layout block" )); - return FALSE; + inFile->close(); + inFile = nullptr; + return nullptr; } From d01cb8a9cf96f4f73266f49f865a51597c59ef60 Mon Sep 17 00:00:00 2001 From: Tin Tin Hamans <5984296+tintinhamans@users.noreply.github.com> Date: Thu, 15 Oct 2026 19:00:41 +0200 Subject: [PATCH 3/3] fix(maputil): Close the file and free the buffer when a map preview copy fails (#3485) (cherry picked from commit 8e6d7bf180493f48ff388831f3e61b96d252dbac) --- Core/GameEngine/Source/GameClient/MapUtil.cpp | 58 ++++++------------- 1 file changed, 17 insertions(+), 41 deletions(-) diff --git a/Core/GameEngine/Source/GameClient/MapUtil.cpp b/Core/GameEngine/Source/GameClient/MapUtil.cpp index ef776c2e1f7..5ea1a305944 100644 --- a/Core/GameEngine/Source/GameClient/MapUtil.cpp +++ b/Core/GameEngine/Source/GameClient/MapUtil.cpp @@ -1142,53 +1142,38 @@ const MapMetaData *MapCache::findMap(AsciiString mapName) // ------------------------------------------------------------------------------------------------ /** Embed the pristine map into the xfer stream */ // ------------------------------------------------------------------------------------------------ -static void copyFromBigToDir( const AsciiString& infile, const AsciiString& outfile ) +static Bool copyFromBigToDir( const AsciiString& infile, const AsciiString& outfile ) { - // open the map file - File *file = TheFileSystem->openFile( infile.str(), File::READ | File::BINARY ); if( file == nullptr ) { DEBUG_CRASH(( "copyFromBigToDir - Error opening source file '%s'", infile.str() )); - throw SC_INVALID_DATA; + return FALSE; } - // how big is the map file - Int fileSize = file->seek( 0, File::END ); - - - // rewind to beginning of file + const Int fileSize = file->seek( 0, File::END ); file->seek( 0, File::START ); - // allocate buffer big enough to hold the entire map file char *buffer = NEW char[ fileSize ]; - if( buffer == nullptr ) - { - DEBUG_CRASH(( "copyFromBigToDir - Unable to allocate buffer for file '%s'", infile.str() )); - throw SC_INVALID_DATA; - } - - // copy the file to the buffer - if( file->read( buffer, fileSize ) < fileSize ) - { - DEBUG_CRASH(( "copyFromBigToDir - Error reading from file '%s'", infile.str() )); - throw SC_INVALID_DATA; - } - // close the BIG file + const Bool readOk = file->read( buffer, fileSize ) == fileSize; file->close(); + DEBUG_ASSERTCRASH( readOk, ( "copyFromBigToDir - Error reading from file '%s'", infile.str() ) ); - File *filenew = TheFileSystem->openFile( outfile.str(), File::WRITE | File::CREATE | File::BINARY ); - - if( !filenew || filenew->write(buffer, fileSize) < fileSize) + Bool writeOk = FALSE; + if( readOk ) { - DEBUG_CRASH(( "copyFromBigToDir - Error writing to file '%s'", outfile.str() )); - throw SC_INVALID_DATA; + File *filenew = TheFileSystem->openFile( outfile.str(), File::WRITE | File::CREATE | File::BINARY ); + if( filenew != nullptr ) + { + writeOk = filenew->write( buffer, fileSize ) == fileSize; + filenew->close(); + } + DEBUG_ASSERTCRASH( writeOk, ( "copyFromBigToDir - Error writing to file '%s'", outfile.str() ) ); } - filenew->close(); - - // delete the buffer delete [] buffer; + + return writeOk; } Image *getMapPreviewImage( AsciiString mapName ) @@ -1233,16 +1218,7 @@ Image *getMapPreviewImage( AsciiString mapName ) mapPreviewDir.concat(name); - Bool success = false; - try - { - copyFromBigToDir(tgaName, mapPreviewDir); - success = true; - } - catch (...) - { - success = false; // no rethrow - } + const Bool success = copyFromBigToDir(tgaName, mapPreviewDir); if (success) {