From 7d038c57c2426bcd26ccb661972b9d4c39ad07da Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Sat, 14 Jun 2025 22:58:12 +0200
Subject: [PATCH 01/20] [GEN][ZH] Prevent AMD/ATI driver crash on game launch
by temporarily unloading and renaming dbghelp.dll
---
CMakeLists.txt | 1 -
.../Source/WWVegas/WWLib/CMakeLists.txt | 7 +
.../Source/WWVegas/WWLib/DbgHelpGuard.cpp | 63 ++++
.../Source/WWVegas/WWLib/DbgHelpGuard.h | 47 +++
.../Source/WWVegas/WWLib/DbgHelpLoader.cpp | 283 ++++++++++++++++++
.../Source/WWVegas/WWLib/DbgHelpLoader.h | 187 ++++++++++++
.../Source/WWVegas/WWLib/MallocAllocator.h | 129 ++++++++
.../WWVegas/WWLib/ScopedFileRenamer.cpp | 98 ++++++
.../Source/WWVegas/WWLib/ScopedFileRenamer.h | 47 +++
Core/Tools/ImagePacker/CMakeLists.txt | 1 -
Core/Tools/MapCacheBuilder/CMakeLists.txt | 1 -
Core/Tools/PATCHGET/CMakeLists.txt | 1 -
.../Source/Common/System/StackDump.cpp | 120 ++++----
.../Source/WWVegas/WW3D2/dx8wrapper.cpp | 32 +-
Generals/Code/Main/CMakeLists.txt | 1 -
Generals/Code/Tools/GUIEdit/CMakeLists.txt | 1 -
.../Code/Tools/ParticleEditor/CMakeLists.txt | 1 -
Generals/Code/Tools/W3DView/CMakeLists.txt | 1 -
.../Code/Tools/WorldBuilder/CMakeLists.txt | 1 -
.../Source/Common/System/StackDump.cpp | 120 ++++----
.../Source/WWVegas/WW3D2/dx8wrapper.cpp | 32 +-
GeneralsMD/Code/Main/CMakeLists.txt | 1 -
GeneralsMD/Code/Tools/GUIEdit/CMakeLists.txt | 1 -
.../Code/Tools/ParticleEditor/CMakeLists.txt | 1 -
GeneralsMD/Code/Tools/W3DView/CMakeLists.txt | 1 -
.../Code/Tools/WorldBuilder/CMakeLists.txt | 1 -
GeneralsMD/Code/Tools/wdump/CMakeLists.txt | 1 -
cmake/dbghelp.cmake | 7 -
28 files changed, 1005 insertions(+), 182 deletions(-)
create mode 100644 Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp
create mode 100644 Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
create mode 100644 Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
create mode 100644 Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
create mode 100644 Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h
create mode 100644 Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.cpp
create mode 100644 Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.h
delete mode 100644 cmake/dbghelp.cmake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d2b41feab51..4160c918c74 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,7 +43,6 @@ if((WIN32 OR "${CMAKE_SYSTEM}" MATCHES "Windows") AND ${CMAKE_SIZEOF_VOID_P} EQU
include(cmake/miles.cmake)
include(cmake/bink.cmake)
include(cmake/dx8.cmake)
- include(cmake/dbghelp.cmake)
endif()
# Define a dummy stlport target when not on VC6.
diff --git a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
index 99ae03ab2e8..2f8ff16000e 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
+++ b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
@@ -32,6 +32,10 @@ set(WWLIB_SRC
#crcstraw.h
cstraw.cpp
cstraw.h
+ DbgHelpGuard.cpp
+ DbgHelpGuard.h
+ DbgHelpLoader.cpp
+ DbgHelpLoader.h
Except.cpp
Except.h
FastAllocator.cpp
@@ -66,6 +70,7 @@ set(WWLIB_SRC
#lzostraw.cpp
#lzostraw.h
#lzo_conf.h
+ MallocAllocator.h
#md5.cpp
#md5.h
mempool.h
@@ -98,6 +103,8 @@ set(WWLIB_SRC
#regexpr.cpp
#regexpr.h
#search.h
+ ScopedFileRenamer.cpp
+ ScopedFileRenamer.h
sharebuf.h
Signaler.h
simplevec.h
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp
new file mode 100644
index 00000000000..9a0acc82148
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp
@@ -0,0 +1,63 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 TheSuperHackers
+**
+** 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 .
+*/
+
+#include "DbgHelpGuard.h"
+
+#include "DbgHelpLoader.h"
+
+
+DbgHelpGuard::DbgHelpGuard()
+{
+ deactivate();
+}
+
+DbgHelpGuard::~DbgHelpGuard()
+{
+ reactivate();
+}
+
+void DbgHelpGuard::deactivate()
+{
+ DbgHelpLoader::blockLoad();
+
+ if (DbgHelpLoader::isLoadedFromSystem())
+ {
+ // This is ok. Do nothing.
+ }
+ else if (DbgHelpLoader::isLoaded())
+ {
+ DbgHelpLoader::unload();
+ m_wasLoaded = true;
+ m_dbgHelpRenamer.rename("dbghelp.dll", "dbghelp.dll.bak");
+ }
+ else
+ {
+ m_dbgHelpRenamer.rename("dbghelp.dll", "dbghelp.dll.bak");
+ }
+}
+
+void DbgHelpGuard::reactivate()
+{
+ m_dbgHelpRenamer.revert();
+ DbgHelpLoader::unblockLoad();
+
+ if (m_wasLoaded)
+ {
+ DbgHelpLoader::load();
+ }
+}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
new file mode 100644
index 00000000000..243f4ed1cf4
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
@@ -0,0 +1,47 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 TheSuperHackers
+**
+** 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 .
+*/
+
+#pragma once
+
+#include "always.h"
+
+#include "ScopedFileRenamer.h"
+
+
+// This class temporarily unloads dbghelp.dll and prevents it from loading during its lifetime.
+// This helps avoid crashing on boot using recent AMD/ATI drivers, which attempt to load and use
+// dbghelp.dll from the game install directory but are unable to do so correctly because
+// the dbghelp.dll that ships with the game is very old and the AMD/ATI code does not handle
+// that correctly. This workaround is not required if the dbghelp.dll was loaded from the system
+// directory.
+
+class DbgHelpGuard
+{
+public:
+
+ DbgHelpGuard();
+ ~DbgHelpGuard();
+
+ void deactivate();
+ void reactivate();
+
+private:
+
+ ScopedFileRenamer m_dbgHelpRenamer;
+ bool m_wasLoaded;
+};
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
new file mode 100644
index 00000000000..b99ae06be7e
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -0,0 +1,283 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 TheSuperHackers
+**
+** 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 .
+*/
+
+#include "DbgHelpLoader.h"
+
+
+int DbgHelpLoader::BlockLoadCounter = 0;
+DbgHelpLoader* DbgHelpLoader::Inst = NULL;
+
+DbgHelpLoader::DbgHelpLoader()
+ : m_symInitialize(NULL)
+ , m_symCleanup(NULL)
+ , m_symLoadModule(NULL)
+ , m_symUnloadModule(NULL)
+ , m_symGetModuleBase(NULL)
+ , m_symGetSymFromAddr(NULL)
+ , m_symGetLineFromAddr(NULL)
+ , m_symSetOptions(NULL)
+ , m_symFunctionTableAccess(NULL)
+ , m_stackWalk(NULL)
+ , m_dllModule(HMODULE(0))
+ , m_failed(false)
+ , m_loadedFromSystem(false)
+{
+}
+
+DbgHelpLoader::~DbgHelpLoader()
+{
+}
+
+bool DbgHelpLoader::isLoaded()
+{
+ return Inst != NULL && Inst->m_dllModule != HMODULE(0);
+}
+
+bool DbgHelpLoader::isLoadedFromSystem()
+{
+ return Inst != NULL && Inst->m_loadedFromSystem;
+}
+
+void DbgHelpLoader::blockLoad()
+{
+ ++BlockLoadCounter;
+}
+
+bool DbgHelpLoader::unblockLoad()
+{
+ return --BlockLoadCounter == 0;
+}
+
+bool DbgHelpLoader::load()
+{
+ if (BlockLoadCounter > 0)
+ return false;
+
+ if (Inst == NULL)
+ {
+ // Cannot use new/delete here when this is loaded during game memory initialization.
+ void* p = ::malloc(sizeof(DbgHelpLoader));
+ Inst = new (p) DbgHelpLoader();
+ }
+
+ // Optimization: return early if it failed before.
+ if (Inst->m_failed)
+ return false;
+
+ // Try load dbghelp.dll from the system directory first.
+ char dllFilename[MAX_PATH];
+ ::GetSystemDirectoryA(dllFilename, ARRAY_SIZE(dllFilename));
+ strcat(dllFilename, "\\dbghelp.dll");
+
+ Inst->m_dllModule = ::LoadLibraryA(dllFilename);
+ if (Inst->m_dllModule == HMODULE(0))
+ {
+ // Not found. Try load dbghelp.dll from the work directory.
+ Inst->m_dllModule = ::LoadLibraryA("dbghelp.dll");
+ if (Inst->m_dllModule == HMODULE(0))
+ {
+ Inst->m_failed = true;
+ return false;
+ }
+ }
+ else
+ {
+ Inst->m_loadedFromSystem = true;
+ }
+
+ Inst->m_symInitialize = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymInitialize"));
+ Inst->m_symCleanup = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymCleanup"));
+ Inst->m_symLoadModule = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymLoadModule"));
+ Inst->m_symUnloadModule = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymUnloadModule"));
+ Inst->m_symGetModuleBase = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymGetModuleBase"));
+ Inst->m_symGetSymFromAddr = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymGetSymFromAddr"));
+ Inst->m_symGetLineFromAddr = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymGetLineFromAddr"));
+ Inst->m_symSetOptions = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymSetOptions"));
+ Inst->m_symFunctionTableAccess = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymFunctionTableAccess"));
+ Inst->m_stackWalk = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "StackWalk"));
+
+ if (Inst->m_symInitialize == NULL || Inst->m_symCleanup == NULL)
+ {
+ unload();
+ Inst->m_failed = true;
+ return false;
+ }
+
+ return true;
+}
+
+bool DbgHelpLoader::reload()
+{
+ unload();
+ return load();
+}
+
+void DbgHelpLoader::unload()
+{
+ if (Inst == NULL)
+ return;
+
+ while (!Inst->m_initializedProcesses.empty())
+ {
+ symCleanup(*Inst->m_initializedProcesses.begin());
+ }
+
+ if (Inst->m_dllModule != HMODULE(0))
+ {
+ ::FreeLibrary(Inst->m_dllModule);
+ Inst->m_dllModule = HMODULE(0);
+ }
+
+ Inst->~DbgHelpLoader();
+ ::free(Inst);
+ Inst = NULL;
+}
+
+BOOL DbgHelpLoader::symInitialize(
+ HANDLE hProcess,
+ LPSTR UserSearchPath,
+ BOOL fInvadeProcess)
+{
+ if (Inst == NULL)
+ return FALSE;
+
+ if (Inst->m_initializedProcesses.find(hProcess) != Inst->m_initializedProcesses.end())
+ return FALSE;
+
+ if (Inst->m_symInitialize)
+ {
+ if (Inst->m_symInitialize(hProcess, UserSearchPath, fInvadeProcess) != FALSE)
+ {
+ Inst->m_initializedProcesses.insert(hProcess);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL DbgHelpLoader::symCleanup(
+ HANDLE hProcess)
+{
+ if (Inst == NULL)
+ return FALSE;
+
+ // @todo stl::find_and_erase
+ Processes::iterator it = Inst->m_initializedProcesses.find(hProcess);
+ if (it != Inst->m_initializedProcesses.end())
+ Inst->m_initializedProcesses.erase(it);
+
+ if (Inst->m_symCleanup)
+ return Inst->m_symCleanup(hProcess);
+
+ return FALSE;
+}
+
+BOOL DbgHelpLoader::symLoadModule(
+ HANDLE hProcess,
+ HANDLE hFile,
+ LPSTR ImageName,
+ LPSTR ModuleName,
+ DWORD BaseOfDll,
+ DWORD SizeOfDll)
+{
+ if (Inst != NULL && Inst->m_symLoadModule)
+ return Inst->m_symLoadModule(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll);
+
+ return FALSE;
+}
+
+DWORD DbgHelpLoader::symGetModuleBase(
+ HANDLE hProcess,
+ DWORD dwAddr)
+{
+ if (Inst != NULL && Inst->m_symGetModuleBase)
+ return Inst->m_symGetModuleBase(hProcess, dwAddr);
+
+ return 0u;
+}
+
+BOOL DbgHelpLoader::symUnloadModule(
+ HANDLE hProcess,
+ DWORD BaseOfDll)
+{
+ if (Inst != NULL && Inst->m_symUnloadModule)
+ return Inst->m_symUnloadModule(hProcess, BaseOfDll);
+
+ return FALSE;
+}
+
+BOOL DbgHelpLoader::symGetSymFromAddr(
+ HANDLE hProcess,
+ DWORD Address,
+ LPDWORD Displacement,
+ PIMAGEHLP_SYMBOL Symbol)
+{
+ if (Inst != NULL && Inst->m_symGetSymFromAddr)
+ return Inst->m_symGetSymFromAddr(hProcess, Address, Displacement, Symbol);
+
+ return FALSE;
+}
+
+BOOL DbgHelpLoader::symGetLineFromAddr(
+ HANDLE hProcess,
+ DWORD dwAddr,
+ PDWORD pdwDisplacement,
+ PIMAGEHLP_LINE Line)
+{
+ if (Inst != NULL && Inst->m_symGetLineFromAddr)
+ return Inst->m_symGetLineFromAddr(hProcess, dwAddr, pdwDisplacement, Line);
+
+ return FALSE;
+}
+
+DWORD DbgHelpLoader::symSetOptions(
+ DWORD SymOptions)
+{
+ if (Inst != NULL && Inst->m_symSetOptions)
+ return Inst->m_symSetOptions(SymOptions);
+
+ return 0u;
+}
+
+LPVOID DbgHelpLoader::symFunctionTableAccess(
+ HANDLE hProcess,
+ DWORD AddrBase)
+{
+ if (Inst != NULL && Inst->m_symFunctionTableAccess)
+ return Inst->m_symFunctionTableAccess(hProcess, AddrBase);
+
+ return NULL;
+}
+
+BOOL DbgHelpLoader::stackWalk(
+ DWORD MachineType,
+ HANDLE hProcess,
+ HANDLE hThread,
+ LPSTACKFRAME StackFrame,
+ LPVOID ContextRecord,
+ PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
+ PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
+ PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
+ PTRANSLATE_ADDRESS_ROUTINE TranslateAddress)
+{
+ if (Inst != NULL && Inst->m_stackWalk)
+ return Inst->m_stackWalk(MachineType, hProcess, hThread, StackFrame, ContextRecord, ReadMemoryRoutine, FunctionTableAccessRoutine, GetModuleBaseRoutine, TranslateAddress);
+
+ return FALSE;
+}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
new file mode 100644
index 00000000000..8b6079e3c82
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
@@ -0,0 +1,187 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 TheSuperHackers
+**
+** 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 .
+*/
+
+#pragma once
+
+#include "always.h"
+
+#include
+#include // Must be included after Windows.h
+#include
+
+#include "MallocAllocator.h"
+
+// This static class can load and unload dbghelp.dll
+// Internally it must not use new and delete because it can be created during game memory initialization.
+
+class DbgHelpLoader
+{
+private:
+
+ static int BlockLoadCounter;
+ static DbgHelpLoader* Inst; // Is singleton class
+
+ DbgHelpLoader();
+ ~DbgHelpLoader();
+
+public:
+
+ // Returns whether dbghelp.dll is loaded
+ static bool isLoaded();
+
+ // Returns whether dbghelp.dll is loaded from the system directory
+ static bool isLoadedFromSystem();
+
+ // Blocks loading a dbghelp.dll
+ static void blockLoad();
+
+ // Unblocks loading a dbghelp.dll. Returns true if unblocked.
+ static bool unblockLoad();
+
+ static bool load();
+ static bool reload();
+ static void unload();
+
+ static BOOL WINAPI symInitialize(
+ HANDLE hProcess,
+ LPSTR UserSearchPath,
+ BOOL fInvadeProcess);
+
+ static BOOL WINAPI symCleanup(
+ HANDLE hProcess);
+
+ static BOOL WINAPI symLoadModule(
+ HANDLE hProcess,
+ HANDLE hFile,
+ LPSTR ImageName,
+ LPSTR ModuleName,
+ DWORD BaseOfDll,
+ DWORD SizeOfDll);
+
+ static DWORD WINAPI symGetModuleBase(
+ HANDLE hProcess,
+ DWORD dwAddr);
+
+ static BOOL WINAPI symUnloadModule(
+ HANDLE hProcess,
+ DWORD BaseOfDll);
+
+ static BOOL WINAPI symGetSymFromAddr(
+ HANDLE hProcess,
+ DWORD Address,
+ LPDWORD Displacement,
+ PIMAGEHLP_SYMBOL Symbol);
+
+ static BOOL WINAPI symGetLineFromAddr(
+ HANDLE hProcess,
+ DWORD dwAddr,
+ PDWORD pdwDisplacement,
+ PIMAGEHLP_LINE Line);
+
+ static DWORD WINAPI symSetOptions(
+ DWORD SymOptions);
+
+ static LPVOID WINAPI symFunctionTableAccess(
+ HANDLE hProcess,
+ DWORD AddrBase);
+
+ static BOOL WINAPI stackWalk(
+ DWORD MachineType,
+ HANDLE hProcess,
+ HANDLE hThread,
+ LPSTACKFRAME StackFrame,
+ LPVOID ContextRecord,
+ PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
+ PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
+ PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
+ PTRANSLATE_ADDRESS_ROUTINE TranslateAddress);
+
+private:
+
+ typedef BOOL (WINAPI *SymInitialize_t) (
+ HANDLE hProcess,
+ LPSTR UserSearchPath,
+ BOOL fInvadeProcess);
+
+ typedef BOOL (WINAPI *SymCleanup_t) (
+ HANDLE hProcess);
+
+ typedef BOOL (WINAPI *SymLoadModule_t) (
+ HANDLE hProcess,
+ HANDLE hFile,
+ LPSTR ImageName,
+ LPSTR ModuleName,
+ DWORD BaseOfDll,
+ DWORD SizeOfDll);
+
+ typedef DWORD (WINAPI *SymGetModuleBase_t) (
+ HANDLE hProcess,
+ DWORD dwAddr);
+
+ typedef BOOL (WINAPI *SymUnloadModule_t) (
+ HANDLE hProcess,
+ DWORD BaseOfDll);
+
+ typedef BOOL (WINAPI *SymGetSymFromAddr_t) (
+ HANDLE hProcess,
+ DWORD Address,
+ LPDWORD Displacement,
+ PIMAGEHLP_SYMBOL Symbol);
+
+ typedef BOOL (WINAPI* SymGetLineFromAddr_t) (
+ HANDLE hProcess,
+ DWORD dwAddr,
+ PDWORD pdwDisplacement,
+ PIMAGEHLP_LINE Line);
+
+ typedef DWORD (WINAPI *SymSetOptions_t) (
+ DWORD SymOptions);
+
+ typedef LPVOID (WINAPI *SymFunctionTableAccess_t) (
+ HANDLE hProcess,
+ DWORD AddrBase);
+
+ typedef BOOL (WINAPI *StackWalk_t) (
+ DWORD MachineType,
+ HANDLE hProcess,
+ HANDLE hThread,
+ LPSTACKFRAME StackFrame,
+ LPVOID ContextRecord,
+ PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
+ PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
+ PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
+ PTRANSLATE_ADDRESS_ROUTINE TranslateAddress);
+
+ SymInitialize_t m_symInitialize;
+ SymCleanup_t m_symCleanup;
+ SymLoadModule_t m_symLoadModule;
+ SymUnloadModule_t m_symUnloadModule;
+ SymGetModuleBase_t m_symGetModuleBase;
+ SymGetSymFromAddr_t m_symGetSymFromAddr;
+ SymGetLineFromAddr_t m_symGetLineFromAddr;
+ SymSetOptions_t m_symSetOptions;
+ SymFunctionTableAccess_t m_symFunctionTableAccess;
+ StackWalk_t m_stackWalk;
+
+ typedef std::set, stl::malloc_allocator > Processes;
+
+ Processes m_initializedProcesses;
+ HMODULE m_dllModule;
+ bool m_failed;
+ bool m_loadedFromSystem;
+};
diff --git a/Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h b/Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h
new file mode 100644
index 00000000000..e465b0ad5d1
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h
@@ -0,0 +1,129 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 TheSuperHackers
+**
+** 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 .
+*/
+
+#pragma once
+
+#include // malloc, free
+#include // std::size_t, std::ptrdiff_t
+#include // std::bad_alloc
+
+
+namespace stl
+{
+
+// STL allocator that uses malloc and free. Useful if allocations are meant to bypass new and delete.
+
+template
+class malloc_allocator
+{
+public:
+
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ template
+ struct rebind
+ {
+ typedef malloc_allocator other;
+ };
+
+ malloc_allocator() throw() {}
+
+#if !(defined(_MSC_VER) && _MSC_VER < 1300)
+ malloc_allocator(const malloc_allocator&) throw() {}
+#endif
+
+ template
+ malloc_allocator(const malloc_allocator&) throw() {}
+
+ ~malloc_allocator() throw() {}
+
+ pointer address(reference x) const { return &x; }
+ const_pointer address(const_reference x) const { return &x; }
+
+ pointer allocate(size_type n, const void* = 0)
+ {
+ if (n > max_size())
+ throw std::bad_alloc();
+
+ void* p = ::malloc(n * sizeof(T));
+ if (!p)
+ throw std::bad_alloc();
+ return static_cast(p);
+ }
+
+ void deallocate(pointer p, size_type)
+ {
+ ::free(p);
+ }
+
+ void construct(pointer p, const T& val)
+ {
+ new (static_cast(p)) T(val);
+ }
+
+ void destroy(pointer p)
+ {
+ p->~T();
+ }
+
+ size_type max_size() const throw()
+ {
+ return ~size_type(0) / sizeof(T);
+ }
+};
+
+// Allocators of same type are always equal
+template
+bool operator==(const malloc_allocator&, const malloc_allocator&) throw() {
+ return true;
+}
+
+template
+bool operator!=(const malloc_allocator&, const malloc_allocator&) throw() {
+ return false;
+}
+
+} // namespace stl
+
+
+#if defined(USING_STLPORT)
+
+// This tells STLport how to rebind malloc_allocator
+namespace std
+{
+ template
+ struct __stl_alloc_rebind_helper;
+
+ template
+ inline stl::malloc_allocator& __stl_alloc_rebind(stl::malloc_allocator& a, const Tp2*) {
+ return *reinterpret_cast*>(&a);
+ }
+
+ template
+ inline const stl::malloc_allocator& __stl_alloc_rebind(const stl::malloc_allocator& a, const Tp2*) {
+ return *reinterpret_cast*>(&a);
+ }
+}
+
+#endif
diff --git a/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.cpp b/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.cpp
new file mode 100644
index 00000000000..d13c089426f
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.cpp
@@ -0,0 +1,98 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 TheSuperHackers
+**
+** 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 .
+*/
+
+#include "ScopedFileRenamer.h"
+
+
+ScopedFileRenamer::ScopedFileRenamer()
+ : m_file(NULL)
+{
+}
+
+ScopedFileRenamer::ScopedFileRenamer(const char* oldName, const char* newName)
+ : m_file(NULL)
+{
+ this->rename(oldName, newName);
+}
+
+ScopedFileRenamer::~ScopedFileRenamer()
+{
+ revert();
+}
+
+bool ScopedFileRenamer::rename(const char* oldName, const char* newName)
+{
+ revert();
+
+ m_oldName = oldName;
+ m_newName = newName;
+
+ if (0 == ::rename(m_oldName.c_str(), m_newName.c_str()))
+ {
+ // Creates an empty *.tmp dummy file to remember that this program has renamed the file.
+ // If the program would crash before the file was renamed back to the previous name, then
+ // the rename condition will be able to recover the next time this code runs successfully.
+ std::string tmpFilename = createTmpName();
+ m_file = ::fopen(tmpFilename.c_str(), "wb");
+
+ return true;
+ }
+
+ return false;
+}
+
+bool ScopedFileRenamer::revert()
+{
+ if (m_oldName.empty())
+ return false;
+
+ bool success = false;
+ std::string tmpName;
+
+ if (m_file == NULL)
+ {
+ tmpName = createTmpName();
+ m_file = ::fopen(tmpName.c_str(), "rb");
+ }
+
+ if (m_file != NULL)
+ {
+ ::fclose(m_file);
+ m_file = NULL;
+
+ if (0 == ::rename(m_newName.c_str(), m_oldName.c_str()))
+ success = true;
+
+ if (tmpName.empty())
+ tmpName = createTmpName();
+
+ ::remove(tmpName.c_str());
+ }
+
+ m_oldName.clear();
+ m_newName.clear();
+
+ return success;
+}
+
+std::string ScopedFileRenamer::createTmpName() const
+{
+ std::string tmpFilename = m_oldName;
+ tmpFilename.append(".tmp");
+ return tmpFilename;
+}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.h b/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.h
new file mode 100644
index 00000000000..594192eceb2
--- /dev/null
+++ b/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.h
@@ -0,0 +1,47 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 TheSuperHackers
+**
+** 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 .
+*/
+
+#pragma once
+
+#include "always.h"
+
+#include
+#include
+
+
+class ScopedFileRenamer
+{
+public:
+
+ ScopedFileRenamer();
+ ScopedFileRenamer(const char* oldName, const char* newName);
+ ~ScopedFileRenamer();
+
+ bool rename(const char* oldName, const char* newName);
+ bool revert();
+
+private:
+
+ std::string createTmpName() const;
+
+private:
+
+ std::string m_oldName;
+ std::string m_newName;
+ FILE* m_file;
+};
diff --git a/Core/Tools/ImagePacker/CMakeLists.txt b/Core/Tools/ImagePacker/CMakeLists.txt
index c71eefca56d..db8aaf2d157 100644
--- a/Core/Tools/ImagePacker/CMakeLists.txt
+++ b/Core/Tools/ImagePacker/CMakeLists.txt
@@ -30,7 +30,6 @@ target_link_libraries(corei_imagepacker INTERFACE
core_debug
core_profile
core_wwcommon
- dbghelplib
imm32
vfw32
winmm
diff --git a/Core/Tools/MapCacheBuilder/CMakeLists.txt b/Core/Tools/MapCacheBuilder/CMakeLists.txt
index 5d390853a8f..bdb38951a54 100644
--- a/Core/Tools/MapCacheBuilder/CMakeLists.txt
+++ b/Core/Tools/MapCacheBuilder/CMakeLists.txt
@@ -17,7 +17,6 @@ target_link_libraries(corei_mapcachebuilder INTERFACE
comctl32
core_debug
core_profile
- dbghelplib
imm32
vfw32
winmm
diff --git a/Core/Tools/PATCHGET/CMakeLists.txt b/Core/Tools/PATCHGET/CMakeLists.txt
index 265a74c785b..d2822c3ddbb 100644
--- a/Core/Tools/PATCHGET/CMakeLists.txt
+++ b/Core/Tools/PATCHGET/CMakeLists.txt
@@ -25,7 +25,6 @@ target_link_libraries(corei_patchgrabber INTERFACE
comctl32
core_debug
core_profile
- dbghelplib
gamespy::gamespy
imm32
vfw32
diff --git a/Generals/Code/GameEngine/Source/Common/System/StackDump.cpp b/Generals/Code/GameEngine/Source/Common/System/StackDump.cpp
index 669264aa222..a0041ee8ccd 100644
--- a/Generals/Code/GameEngine/Source/Common/System/StackDump.cpp
+++ b/Generals/Code/GameEngine/Source/Common/System/StackDump.cpp
@@ -31,6 +31,7 @@
#include "Common/StackDump.h"
#include "Common/Debug.h"
+#include "DbgHelpLoader.h"
//*****************************************************************************
// Prototypes
@@ -45,14 +46,6 @@ void WriteStackLine(void*address, void (*callback)(const char*));
// Mis-named globals :-)
//*****************************************************************************
static CONTEXT gsContext;
-static Bool gsInit=FALSE;
-
-BOOL (__stdcall *gsSymGetLineFromAddr)(
- IN HANDLE hProcess,
- IN DWORD dwAddr,
- OUT PDWORD pdwDisplacement,
- OUT PIMAGEHLP_LINE Line
- );
//*****************************************************************************
@@ -72,7 +65,8 @@ void StackDump(void (*callback)(const char*))
callback = StackDumpDefaultHandler;
}
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
DWORD myeip,myesp,myebp;
@@ -101,7 +95,8 @@ void StackDumpFromContext(DWORD eip,DWORD esp,DWORD ebp, void (*callback)(const
callback = StackDumpDefaultHandler;
}
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
MakeStackTrace(eip,esp,ebp, 0, callback);
}
@@ -111,27 +106,20 @@ void StackDumpFromContext(DWORD eip,DWORD esp,DWORD ebp, void (*callback)(const
//*****************************************************************************
BOOL InitSymbolInfo()
{
- if (gsInit == TRUE)
+ if (DbgHelpLoader::isLoaded())
return TRUE;
- gsInit = TRUE;
+ if (!DbgHelpLoader::load())
+ return FALSE;
atexit(UninitSymbolInfo);
- // See if we have the line from address function
- // We use GetProcAddress to stop link failures at dll loadup
- HINSTANCE hInstDebugHlp = GetModuleHandle("dbghelp.dll");
-
- gsSymGetLineFromAddr = (BOOL (__stdcall *)( IN HANDLE,IN DWORD,OUT PDWORD,OUT PIMAGEHLP_LINE))
- GetProcAddress(hInstDebugHlp , "SymGetLineFromAddr");
-
char pathname[_MAX_PATH+1];
char drive[10];
char directory[_MAX_PATH+1];
HANDLE process;
-
- ::SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST);
+ DbgHelpLoader::symSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST);
process = GetCurrentProcess();
@@ -145,18 +133,18 @@ BOOL InitSymbolInfo()
// append the current directory to build a search path for SymInit
::lstrcat(pathname, ";.;");
- if(::SymInitialize(process, pathname, FALSE))
+ if(DbgHelpLoader::symInitialize(process, pathname, FALSE))
{
// regenerate the name of the app
::GetModuleFileName(NULL, pathname, _MAX_PATH);
- if(::SymLoadModule(process, NULL, pathname, NULL, 0, 0))
+ if(DbgHelpLoader::symLoadModule(process, NULL, pathname, NULL, 0, 0))
{
//Load any other relevant modules (ie dlls) here
return TRUE;
}
- ::SymCleanup(process);
}
+ DbgHelpLoader::unload();
return(FALSE);
}
@@ -165,14 +153,7 @@ BOOL InitSymbolInfo()
//*****************************************************************************
void UninitSymbolInfo(void)
{
- if (gsInit == FALSE)
- {
- return;
- }
-
- gsInit = FALSE;
-
- ::SymCleanup(GetCurrentProcess());
+ DbgHelpLoader::unload();
}
@@ -217,14 +198,14 @@ stack_frame.AddrFrame.Offset = myebp;
unsigned int skip = skipFrames;
while (b_ret&&skip)
{
- b_ret = StackWalk( IMAGE_FILE_MACHINE_I386,
+ b_ret = DbgHelpLoader::stackWalk( IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack_frame,
NULL, //&gsContext,
NULL,
- SymFunctionTableAccess,
- SymGetModuleBase,
+ DbgHelpLoader::symFunctionTableAccess,
+ DbgHelpLoader::symGetModuleBase,
NULL);
skip--;
}
@@ -233,14 +214,14 @@ stack_frame.AddrFrame.Offset = myebp;
while(b_ret&&skip)
{
- b_ret = StackWalk( IMAGE_FILE_MACHINE_I386,
+ b_ret = DbgHelpLoader::stackWalk( IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack_frame,
NULL, //&gsContext,
NULL,
- SymFunctionTableAccess,
- SymGetModuleBase,
+ DbgHelpLoader::symFunctionTableAccess,
+ DbgHelpLoader::symGetModuleBase,
NULL);
@@ -256,7 +237,9 @@ stack_frame.AddrFrame.Offset = myebp;
//*****************************************************************************
void GetFunctionDetails(void *pointer, char*name, char*filename, unsigned int* linenumber, unsigned int* address)
{
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
+
if (name)
{
strcpy(name, "");
@@ -285,8 +268,8 @@ void GetFunctionDetails(void *pointer, char*name, char*filename, unsigned int* l
psymbol->SizeOfStruct = sizeof(symbol_buffer);
psymbol->MaxNameLength = 512;
- if (SymGetSymFromAddr(process, (DWORD) pointer, &displacement, psymbol))
- {
+ if (DbgHelpLoader::symGetSymFromAddr(process, (DWORD) pointer, &displacement, psymbol))
+ {
if (name)
{
strcpy(name, psymbol->Name);
@@ -294,32 +277,27 @@ void GetFunctionDetails(void *pointer, char*name, char*filename, unsigned int* l
}
// Get line now
- if (gsSymGetLineFromAddr)
- {
- // Unsupported for win95/98 at least with my current dbghelp.dll
- IMAGEHLP_LINE line;
- memset(&line,0,sizeof(line));
- line.SizeOfStruct = sizeof(line);
+ IMAGEHLP_LINE line;
+ memset(&line,0,sizeof(line));
+ line.SizeOfStruct = sizeof(line);
-
- if (gsSymGetLineFromAddr(process, (DWORD) pointer, &displacement, &line))
+ if (DbgHelpLoader::symGetLineFromAddr(process, (DWORD) pointer, &displacement, &line))
+ {
+ if (filename)
+ {
+ strcpy(filename, line.FileName);
+ }
+ if (linenumber)
+ {
+ *linenumber = (unsigned int)line.LineNumber;
+ }
+ if (address)
{
- if (filename)
- {
- strcpy(filename, line.FileName);
- }
- if (linenumber)
- {
- *linenumber = (unsigned int)line.LineNumber;
- }
- if (address)
- {
- *address = (unsigned int)line.Address;
- }
+ *address = (unsigned int)line.Address;
}
}
- }
+ }
}
@@ -328,7 +306,8 @@ void GetFunctionDetails(void *pointer, char*name, char*filename, unsigned int* l
//*****************************************************************************
void FillStackAddresses(void**addresses, unsigned int count, unsigned int skip)
{
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
STACKFRAME stack_frame;
@@ -378,28 +357,28 @@ stack_frame.AddrFrame.Offset = myebp;
// Skip some?
while (stillgoing&&skip)
{
- stillgoing = StackWalk(IMAGE_FILE_MACHINE_I386,
+ stillgoing = DbgHelpLoader::stackWalk(IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack_frame,
NULL, //&gsContext,
NULL,
- SymFunctionTableAccess,
- SymGetModuleBase,
+ DbgHelpLoader::symFunctionTableAccess,
+ DbgHelpLoader::symGetModuleBase,
NULL) != 0;
skip--;
}
while(stillgoing&&count)
{
- stillgoing = StackWalk(IMAGE_FILE_MACHINE_I386,
+ stillgoing = DbgHelpLoader::stackWalk(IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack_frame,
NULL, //&gsContext,
NULL,
- SymFunctionTableAccess,
- SymGetModuleBase,
+ DbgHelpLoader::symFunctionTableAccess,
+ DbgHelpLoader::symGetModuleBase,
NULL) != 0;
if (stillgoing)
{
@@ -438,7 +417,8 @@ void StackDumpFromAddresses(void**addresses, unsigned int count, void (*callback
callback = StackDumpDefaultHandler;
}
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
while ((count--) && (*addresses!=NULL))
{
diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index a94c8d239c2..3f017b79964 100644
--- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -81,6 +81,7 @@
#include "dx8texman.h"
#include "bound.h"
#include "dx8webbrowser.h"
+#include "DbgHelpGuard.h"
const int DEFAULT_RESOLUTION_WIDTH = 640;
@@ -312,7 +313,12 @@ bool DX8Wrapper::Init(void * hwnd, bool lite)
** Create the D3D interface object
*/
WWDEBUG_SAY(("Create Direct3D8"));
- D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
+ {
+ // TheSuperHackers @bugfix xezon 13/06/2025 Temporarily unload dbghelp.dll and prevent it from loading.
+ DbgHelpGuard dbgHelpGuard;
+
+ D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
+ }
if (D3DInterface == NULL) {
return(false);
}
@@ -558,15 +564,21 @@ bool DX8Wrapper::Create_Device(void)
Vertex_Processing_Behavior|=D3DCREATE_FPU_PRESERVE;
#endif
- HRESULT hr=D3DInterface->CreateDevice
- (
- CurRenderDevice,
- WW3D_DEVTYPE,
- _Hwnd,
- Vertex_Processing_Behavior,
- &_PresentParameters,
- &D3DDevice
- );
+ HRESULT hr;
+ {
+ // TheSuperHackers @bugfix xezon 13/06/2025 Temporarily unload dbghelp.dll and prevent it from loading.
+ DbgHelpGuard dbgHelpGuard;
+
+ hr=D3DInterface->CreateDevice
+ (
+ CurRenderDevice,
+ WW3D_DEVTYPE,
+ _Hwnd,
+ Vertex_Processing_Behavior,
+ &_PresentParameters,
+ &D3DDevice
+ );
+ }
if (FAILED(hr))
{
diff --git a/Generals/Code/Main/CMakeLists.txt b/Generals/Code/Main/CMakeLists.txt
index 51ca97d5afb..f6b7a4640bd 100644
--- a/Generals/Code/Main/CMakeLists.txt
+++ b/Generals/Code/Main/CMakeLists.txt
@@ -12,7 +12,6 @@ target_link_libraries(g_generals PRIVATE
comctl32
d3d8
d3dx8
- dbghelplib
dinput8
dxguid
g_gameengine
diff --git a/Generals/Code/Tools/GUIEdit/CMakeLists.txt b/Generals/Code/Tools/GUIEdit/CMakeLists.txt
index c9bb07a3c06..a3c397408c8 100644
--- a/Generals/Code/Tools/GUIEdit/CMakeLists.txt
+++ b/Generals/Code/Tools/GUIEdit/CMakeLists.txt
@@ -48,7 +48,6 @@ target_include_directories(g_guiedit PRIVATE
target_link_libraries(g_guiedit PRIVATE
comctl32
d3d8lib
- dbghelplib
g_gameengine
g_gameenginedevice
g_wwvegas
diff --git a/Generals/Code/Tools/ParticleEditor/CMakeLists.txt b/Generals/Code/Tools/ParticleEditor/CMakeLists.txt
index bf7005ea58a..0ea7325438a 100644
--- a/Generals/Code/Tools/ParticleEditor/CMakeLists.txt
+++ b/Generals/Code/Tools/ParticleEditor/CMakeLists.txt
@@ -42,7 +42,6 @@ target_link_libraries(g_particleeditor PRIVATE
corei_libraries_source_wwvegas
corei_libraries_source_wwvegas_wwlib
d3d8lib
- dbghelplib
gi_gameengine_include
gi_always
gi_libraries_source_wwvegas
diff --git a/Generals/Code/Tools/W3DView/CMakeLists.txt b/Generals/Code/Tools/W3DView/CMakeLists.txt
index 80ab604011f..7a3f14db37e 100644
--- a/Generals/Code/Tools/W3DView/CMakeLists.txt
+++ b/Generals/Code/Tools/W3DView/CMakeLists.txt
@@ -8,7 +8,6 @@ target_link_libraries(g_w3dview PRIVATE
d3d8
d3d8lib
d3dx8
- dbghelplib
imm32
milesstub
Version
diff --git a/Generals/Code/Tools/WorldBuilder/CMakeLists.txt b/Generals/Code/Tools/WorldBuilder/CMakeLists.txt
index 3cb3b49c265..502d84d5e3c 100644
--- a/Generals/Code/Tools/WorldBuilder/CMakeLists.txt
+++ b/Generals/Code/Tools/WorldBuilder/CMakeLists.txt
@@ -206,7 +206,6 @@ target_compile_definitions(g_worldbuilder PRIVATE _AFXDLL)
target_link_libraries(g_worldbuilder PRIVATE
d3d8lib
- dbghelplib
core_browserdispatch
g_gameengine
g_gameenginedevice
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/StackDump.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/StackDump.cpp
index 012f649a16c..3474fc8b074 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/System/StackDump.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/System/StackDump.cpp
@@ -31,6 +31,7 @@
#include "Common/StackDump.h"
#include "Common/Debug.h"
+#include "DbgHelpLoader.h"
//*****************************************************************************
// Prototypes
@@ -45,14 +46,6 @@ void WriteStackLine(void*address, void (*callback)(const char*));
// Mis-named globals :-)
//*****************************************************************************
static CONTEXT gsContext;
-static Bool gsInit=FALSE;
-
-BOOL (__stdcall *gsSymGetLineFromAddr)(
- IN HANDLE hProcess,
- IN DWORD dwAddr,
- OUT PDWORD pdwDisplacement,
- OUT PIMAGEHLP_LINE Line
- );
//*****************************************************************************
@@ -72,7 +65,8 @@ void StackDump(void (*callback)(const char*))
callback = StackDumpDefaultHandler;
}
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
DWORD myeip,myesp,myebp;
@@ -101,7 +95,8 @@ void StackDumpFromContext(DWORD eip,DWORD esp,DWORD ebp, void (*callback)(const
callback = StackDumpDefaultHandler;
}
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
MakeStackTrace(eip,esp,ebp, 0, callback);
}
@@ -111,27 +106,20 @@ void StackDumpFromContext(DWORD eip,DWORD esp,DWORD ebp, void (*callback)(const
//*****************************************************************************
BOOL InitSymbolInfo()
{
- if (gsInit == TRUE)
+ if (DbgHelpLoader::isLoaded())
return TRUE;
- gsInit = TRUE;
+ if (!DbgHelpLoader::load())
+ return FALSE;
atexit(UninitSymbolInfo);
- // See if we have the line from address function
- // We use GetProcAddress to stop link failures at dll loadup
- HINSTANCE hInstDebugHlp = GetModuleHandle("dbghelp.dll");
-
- gsSymGetLineFromAddr = (BOOL (__stdcall *)( IN HANDLE,IN DWORD,OUT PDWORD,OUT PIMAGEHLP_LINE))
- GetProcAddress(hInstDebugHlp , "SymGetLineFromAddr");
-
char pathname[_MAX_PATH+1];
char drive[10];
char directory[_MAX_PATH+1];
HANDLE process;
-
- ::SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST);
+ DbgHelpLoader::symSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST);
process = GetCurrentProcess();
@@ -145,18 +133,18 @@ BOOL InitSymbolInfo()
// append the current directory to build a search path for SymInit
::lstrcat(pathname, ";.;");
- if(::SymInitialize(process, pathname, FALSE))
+ if(DbgHelpLoader::symInitialize(process, pathname, FALSE))
{
// regenerate the name of the app
::GetModuleFileName(NULL, pathname, _MAX_PATH);
- if(::SymLoadModule(process, NULL, pathname, NULL, 0, 0))
+ if(DbgHelpLoader::symLoadModule(process, NULL, pathname, NULL, 0, 0))
{
//Load any other relevant modules (ie dlls) here
return TRUE;
}
- ::SymCleanup(process);
}
+ DbgHelpLoader::unload();
return(FALSE);
}
@@ -165,14 +153,7 @@ BOOL InitSymbolInfo()
//*****************************************************************************
void UninitSymbolInfo(void)
{
- if (gsInit == FALSE)
- {
- return;
- }
-
- gsInit = FALSE;
-
- ::SymCleanup(GetCurrentProcess());
+ DbgHelpLoader::unload();
}
@@ -217,14 +198,14 @@ stack_frame.AddrFrame.Offset = myebp;
unsigned int skip = skipFrames;
while (b_ret&&skip)
{
- b_ret = StackWalk( IMAGE_FILE_MACHINE_I386,
+ b_ret = DbgHelpLoader::stackWalk( IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack_frame,
NULL, //&gsContext,
NULL,
- SymFunctionTableAccess,
- SymGetModuleBase,
+ DbgHelpLoader::symFunctionTableAccess,
+ DbgHelpLoader::symGetModuleBase,
NULL);
skip--;
}
@@ -233,14 +214,14 @@ stack_frame.AddrFrame.Offset = myebp;
while(b_ret&&skip)
{
- b_ret = StackWalk( IMAGE_FILE_MACHINE_I386,
+ b_ret = DbgHelpLoader::stackWalk( IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack_frame,
NULL, //&gsContext,
NULL,
- SymFunctionTableAccess,
- SymGetModuleBase,
+ DbgHelpLoader::symFunctionTableAccess,
+ DbgHelpLoader::symGetModuleBase,
NULL);
@@ -256,7 +237,9 @@ stack_frame.AddrFrame.Offset = myebp;
//*****************************************************************************
void GetFunctionDetails(void *pointer, char*name, char*filename, unsigned int* linenumber, unsigned int* address)
{
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
+
if (name)
{
strcpy(name, "");
@@ -285,8 +268,8 @@ void GetFunctionDetails(void *pointer, char*name, char*filename, unsigned int* l
psymbol->SizeOfStruct = sizeof(symbol_buffer);
psymbol->MaxNameLength = 512;
- if (SymGetSymFromAddr(process, (DWORD) pointer, &displacement, psymbol))
- {
+ if (DbgHelpLoader::symGetSymFromAddr(process, (DWORD) pointer, &displacement, psymbol))
+ {
if (name)
{
strcpy(name, psymbol->Name);
@@ -294,32 +277,27 @@ void GetFunctionDetails(void *pointer, char*name, char*filename, unsigned int* l
}
// Get line now
- if (gsSymGetLineFromAddr)
- {
- // Unsupported for win95/98 at least with my current dbghelp.dll
- IMAGEHLP_LINE line;
- memset(&line,0,sizeof(line));
- line.SizeOfStruct = sizeof(line);
+ IMAGEHLP_LINE line;
+ memset(&line,0,sizeof(line));
+ line.SizeOfStruct = sizeof(line);
-
- if (gsSymGetLineFromAddr(process, (DWORD) pointer, &displacement, &line))
+ if (DbgHelpLoader::symGetLineFromAddr(process, (DWORD) pointer, &displacement, &line))
+ {
+ if (filename)
+ {
+ strcpy(filename, line.FileName);
+ }
+ if (linenumber)
+ {
+ *linenumber = (unsigned int)line.LineNumber;
+ }
+ if (address)
{
- if (filename)
- {
- strcpy(filename, line.FileName);
- }
- if (linenumber)
- {
- *linenumber = (unsigned int)line.LineNumber;
- }
- if (address)
- {
- *address = (unsigned int)line.Address;
- }
+ *address = (unsigned int)line.Address;
}
}
- }
+ }
}
@@ -328,7 +306,8 @@ void GetFunctionDetails(void *pointer, char*name, char*filename, unsigned int* l
//*****************************************************************************
void FillStackAddresses(void**addresses, unsigned int count, unsigned int skip)
{
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
STACKFRAME stack_frame;
@@ -378,28 +357,28 @@ stack_frame.AddrFrame.Offset = myebp;
// Skip some?
while (stillgoing&&skip)
{
- stillgoing = StackWalk(IMAGE_FILE_MACHINE_I386,
+ stillgoing = DbgHelpLoader::stackWalk(IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack_frame,
NULL, //&gsContext,
NULL,
- SymFunctionTableAccess,
- SymGetModuleBase,
+ DbgHelpLoader::symFunctionTableAccess,
+ DbgHelpLoader::symGetModuleBase,
NULL) != 0;
skip--;
}
while(stillgoing&&count)
{
- stillgoing = StackWalk(IMAGE_FILE_MACHINE_I386,
+ stillgoing = DbgHelpLoader::stackWalk(IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack_frame,
NULL, //&gsContext,
NULL,
- SymFunctionTableAccess,
- SymGetModuleBase,
+ DbgHelpLoader::symFunctionTableAccess,
+ DbgHelpLoader::symGetModuleBase,
NULL) != 0;
if (stillgoing)
{
@@ -438,7 +417,8 @@ void StackDumpFromAddresses(void**addresses, unsigned int count, void (*callback
callback = StackDumpDefaultHandler;
}
- InitSymbolInfo();
+ if (!InitSymbolInfo())
+ return;
while ((count--) && (*addresses!=NULL))
{
diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 33adbebd630..48b0222ec08 100644
--- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -85,6 +85,7 @@
#include "dx8texman.h"
#include "bound.h"
#include "dx8webbrowser.h"
+#include "DbgHelpGuard.h"
#include "shdlib.h"
@@ -331,7 +332,12 @@ bool DX8Wrapper::Init(void * hwnd, bool lite)
** Create the D3D interface object
*/
WWDEBUG_SAY(("Create Direct3D8"));
- D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
+ {
+ // TheSuperHackers @bugfix xezon 13/06/2025 Temporarily unload dbghelp.dll and prevent it from loading.
+ DbgHelpGuard dbgHelpGuard;
+
+ D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
+ }
if (D3DInterface == NULL) {
return(false);
}
@@ -590,15 +596,21 @@ bool DX8Wrapper::Create_Device(void)
Vertex_Processing_Behavior|=D3DCREATE_FPU_PRESERVE;
#endif
- HRESULT hr=D3DInterface->CreateDevice
- (
- CurRenderDevice,
- WW3D_DEVTYPE,
- _Hwnd,
- Vertex_Processing_Behavior,
- &_PresentParameters,
- &D3DDevice
- );
+ HRESULT hr;
+ {
+ // TheSuperHackers @bugfix xezon 13/06/2025 Temporarily unload dbghelp.dll and prevent it from loading.
+ DbgHelpGuard dbgHelpGuard;
+
+ hr=D3DInterface->CreateDevice
+ (
+ CurRenderDevice,
+ WW3D_DEVTYPE,
+ _Hwnd,
+ Vertex_Processing_Behavior,
+ &_PresentParameters,
+ &D3DDevice
+ );
+ }
if (FAILED(hr))
{
diff --git a/GeneralsMD/Code/Main/CMakeLists.txt b/GeneralsMD/Code/Main/CMakeLists.txt
index fa73f03c136..cabc45befa4 100644
--- a/GeneralsMD/Code/Main/CMakeLists.txt
+++ b/GeneralsMD/Code/Main/CMakeLists.txt
@@ -14,7 +14,6 @@ target_link_libraries(z_generals PRIVATE
core_profile
d3d8
d3dx8
- dbghelplib
dinput8
dxguid
imm32
diff --git a/GeneralsMD/Code/Tools/GUIEdit/CMakeLists.txt b/GeneralsMD/Code/Tools/GUIEdit/CMakeLists.txt
index 64af9ee3b22..2b36b302134 100644
--- a/GeneralsMD/Code/Tools/GUIEdit/CMakeLists.txt
+++ b/GeneralsMD/Code/Tools/GUIEdit/CMakeLists.txt
@@ -50,7 +50,6 @@ target_link_libraries(z_guiedit PRIVATE
core_debug
core_profile
d3d8lib
- dbghelplib
imm32
stlport
vfw32
diff --git a/GeneralsMD/Code/Tools/ParticleEditor/CMakeLists.txt b/GeneralsMD/Code/Tools/ParticleEditor/CMakeLists.txt
index 0b410f34701..4d09c98ec22 100644
--- a/GeneralsMD/Code/Tools/ParticleEditor/CMakeLists.txt
+++ b/GeneralsMD/Code/Tools/ParticleEditor/CMakeLists.txt
@@ -42,7 +42,6 @@ target_link_libraries(z_particleeditor PRIVATE
corei_libraries_source_wwvegas
corei_libraries_source_wwvegas_wwlib
d3d8lib
- dbghelplib
imm32
core_config
stlport
diff --git a/GeneralsMD/Code/Tools/W3DView/CMakeLists.txt b/GeneralsMD/Code/Tools/W3DView/CMakeLists.txt
index 7225e63bd5f..9f321bc93db 100644
--- a/GeneralsMD/Code/Tools/W3DView/CMakeLists.txt
+++ b/GeneralsMD/Code/Tools/W3DView/CMakeLists.txt
@@ -8,7 +8,6 @@ target_link_libraries(z_w3dview PRIVATE
d3d8
d3d8lib
d3dx8
- dbghelplib
imm32
milesstub
Version
diff --git a/GeneralsMD/Code/Tools/WorldBuilder/CMakeLists.txt b/GeneralsMD/Code/Tools/WorldBuilder/CMakeLists.txt
index 1daa5339e90..1aaa85c92b9 100644
--- a/GeneralsMD/Code/Tools/WorldBuilder/CMakeLists.txt
+++ b/GeneralsMD/Code/Tools/WorldBuilder/CMakeLists.txt
@@ -213,7 +213,6 @@ target_link_libraries(z_worldbuilder PRIVATE
core_debug
core_profile
d3d8lib
- dbghelplib
imm32
vfw32
winmm
diff --git a/GeneralsMD/Code/Tools/wdump/CMakeLists.txt b/GeneralsMD/Code/Tools/wdump/CMakeLists.txt
index a363e40260b..65d190703e4 100644
--- a/GeneralsMD/Code/Tools/wdump/CMakeLists.txt
+++ b/GeneralsMD/Code/Tools/wdump/CMakeLists.txt
@@ -21,7 +21,6 @@ target_link_libraries(z_wdump PRIVATE
core_config
core_utility
core_wwstub # avoid linking GameEngine
- dbghelplib
imm32
vfw32
winmm
diff --git a/cmake/dbghelp.cmake b/cmake/dbghelp.cmake
deleted file mode 100644
index 7940400e3e9..00000000000
--- a/cmake/dbghelp.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-FetchContent_Declare(
- dbghelp
- GIT_REPOSITORY https://github.com/TheSuperHackers/dbghelp-import-lib.git
- GIT_TAG afeb423d4597167c8fa94215f4574f3ae310f920
-)
-
-FetchContent_MakeAvailable(dbghelp)
\ No newline at end of file
From c63da9192513c6c8197a72dbbbfb57bc473a9854 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Sat, 14 Jun 2025 23:42:59 +0200
Subject: [PATCH 02/20] Minor improvement in DbgHelpGuard
---
Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp | 5 +++--
Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp
index 9a0acc82148..16c705c8b55 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp
@@ -42,7 +42,7 @@ void DbgHelpGuard::deactivate()
else if (DbgHelpLoader::isLoaded())
{
DbgHelpLoader::unload();
- m_wasLoaded = true;
+ m_requiresLoad = true;
m_dbgHelpRenamer.rename("dbghelp.dll", "dbghelp.dll.bak");
}
else
@@ -56,8 +56,9 @@ void DbgHelpGuard::reactivate()
m_dbgHelpRenamer.revert();
DbgHelpLoader::unblockLoad();
- if (m_wasLoaded)
+ if (m_requiresLoad)
{
DbgHelpLoader::load();
+ m_requiresLoad = false;
}
}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
index 243f4ed1cf4..ddb534c520b 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
@@ -43,5 +43,5 @@ class DbgHelpGuard
private:
ScopedFileRenamer m_dbgHelpRenamer;
- bool m_wasLoaded;
+ bool m_requiresLoad;
};
From ea04cee910f57d8cfe0ca72142059ab8bf3a17bc Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Wed, 18 Jun 2025 18:35:48 +0200
Subject: [PATCH 03/20] Remove ScopeFileRenamer and use dbghelp front loading
strategy instead of file renaming
---
.../Source/WWVegas/WWLib/CMakeLists.txt | 2 -
.../Source/WWVegas/WWLib/DbgHelpGuard.cpp | 27 +++--
.../Source/WWVegas/WWLib/DbgHelpGuard.h | 13 +--
.../Source/WWVegas/WWLib/DbgHelpLoader.cpp | 14 ---
.../Source/WWVegas/WWLib/DbgHelpLoader.h | 7 --
.../WWVegas/WWLib/ScopedFileRenamer.cpp | 98 -------------------
.../Source/WWVegas/WWLib/ScopedFileRenamer.h | 47 ---------
7 files changed, 16 insertions(+), 192 deletions(-)
delete mode 100644 Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.cpp
delete mode 100644 Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.h
diff --git a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
index 2f8ff16000e..81579754a38 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
+++ b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
@@ -103,8 +103,6 @@ set(WWLIB_SRC
#regexpr.cpp
#regexpr.h
#search.h
- ScopedFileRenamer.cpp
- ScopedFileRenamer.h
sharebuf.h
Signaler.h
simplevec.h
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp
index 16c705c8b55..f53b89adcc1 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.cpp
@@ -22,43 +22,38 @@
DbgHelpGuard::DbgHelpGuard()
+ : m_hasLoaded(false)
{
- deactivate();
+ activate();
}
DbgHelpGuard::~DbgHelpGuard()
{
- reactivate();
+ deactivate();
}
-void DbgHelpGuard::deactivate()
+void DbgHelpGuard::activate()
{
- DbgHelpLoader::blockLoad();
-
if (DbgHelpLoader::isLoadedFromSystem())
{
// This is ok. Do nothing.
}
else if (DbgHelpLoader::isLoaded())
{
- DbgHelpLoader::unload();
- m_requiresLoad = true;
- m_dbgHelpRenamer.rename("dbghelp.dll", "dbghelp.dll.bak");
+ // This is maybe not ok. But do nothing until this becomes a user facing problem.
}
else
{
- m_dbgHelpRenamer.rename("dbghelp.dll", "dbghelp.dll.bak");
+ // Front load the DLL now to prevent other code from loading the potentially wrong DLL.
+ m_hasLoaded = DbgHelpLoader::load();
}
}
-void DbgHelpGuard::reactivate()
+void DbgHelpGuard::deactivate()
{
- m_dbgHelpRenamer.revert();
- DbgHelpLoader::unblockLoad();
-
- if (m_requiresLoad)
+ if (m_hasLoaded)
{
- DbgHelpLoader::load();
- m_requiresLoad = false;
+ DbgHelpLoader::unload();
+ m_hasLoaded = false;
}
}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
index ddb534c520b..c613cb3b4cd 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
@@ -20,15 +20,13 @@
#include "always.h"
-#include "ScopedFileRenamer.h"
-
-// This class temporarily unloads dbghelp.dll and prevents it from loading during its lifetime.
+// This class temporarily loads and unloads dbghelp.dll from the desired location to prevent
+// other code from potentially loading it from an undesired location.
// This helps avoid crashing on boot using recent AMD/ATI drivers, which attempt to load and use
// dbghelp.dll from the game install directory but are unable to do so correctly because
// the dbghelp.dll that ships with the game is very old and the AMD/ATI code does not handle
-// that correctly. This workaround is not required if the dbghelp.dll was loaded from the system
-// directory.
+// that correctly.
class DbgHelpGuard
{
@@ -37,11 +35,10 @@ class DbgHelpGuard
DbgHelpGuard();
~DbgHelpGuard();
+ void activate();
void deactivate();
- void reactivate();
private:
- ScopedFileRenamer m_dbgHelpRenamer;
- bool m_requiresLoad;
+ bool m_hasLoaded;
};
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
index b99ae06be7e..4449ff15a60 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -19,7 +19,6 @@
#include "DbgHelpLoader.h"
-int DbgHelpLoader::BlockLoadCounter = 0;
DbgHelpLoader* DbgHelpLoader::Inst = NULL;
DbgHelpLoader::DbgHelpLoader()
@@ -53,21 +52,8 @@ bool DbgHelpLoader::isLoadedFromSystem()
return Inst != NULL && Inst->m_loadedFromSystem;
}
-void DbgHelpLoader::blockLoad()
-{
- ++BlockLoadCounter;
-}
-
-bool DbgHelpLoader::unblockLoad()
-{
- return --BlockLoadCounter == 0;
-}
-
bool DbgHelpLoader::load()
{
- if (BlockLoadCounter > 0)
- return false;
-
if (Inst == NULL)
{
// Cannot use new/delete here when this is loaded during game memory initialization.
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
index 8b6079e3c82..3a7d9cafa90 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
@@ -33,7 +33,6 @@ class DbgHelpLoader
{
private:
- static int BlockLoadCounter;
static DbgHelpLoader* Inst; // Is singleton class
DbgHelpLoader();
@@ -47,12 +46,6 @@ class DbgHelpLoader
// Returns whether dbghelp.dll is loaded from the system directory
static bool isLoadedFromSystem();
- // Blocks loading a dbghelp.dll
- static void blockLoad();
-
- // Unblocks loading a dbghelp.dll. Returns true if unblocked.
- static bool unblockLoad();
-
static bool load();
static bool reload();
static void unload();
diff --git a/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.cpp b/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.cpp
deleted file mode 100644
index d13c089426f..00000000000
--- a/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-** Command & Conquer Generals Zero Hour(tm)
-** Copyright 2025 TheSuperHackers
-**
-** 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 .
-*/
-
-#include "ScopedFileRenamer.h"
-
-
-ScopedFileRenamer::ScopedFileRenamer()
- : m_file(NULL)
-{
-}
-
-ScopedFileRenamer::ScopedFileRenamer(const char* oldName, const char* newName)
- : m_file(NULL)
-{
- this->rename(oldName, newName);
-}
-
-ScopedFileRenamer::~ScopedFileRenamer()
-{
- revert();
-}
-
-bool ScopedFileRenamer::rename(const char* oldName, const char* newName)
-{
- revert();
-
- m_oldName = oldName;
- m_newName = newName;
-
- if (0 == ::rename(m_oldName.c_str(), m_newName.c_str()))
- {
- // Creates an empty *.tmp dummy file to remember that this program has renamed the file.
- // If the program would crash before the file was renamed back to the previous name, then
- // the rename condition will be able to recover the next time this code runs successfully.
- std::string tmpFilename = createTmpName();
- m_file = ::fopen(tmpFilename.c_str(), "wb");
-
- return true;
- }
-
- return false;
-}
-
-bool ScopedFileRenamer::revert()
-{
- if (m_oldName.empty())
- return false;
-
- bool success = false;
- std::string tmpName;
-
- if (m_file == NULL)
- {
- tmpName = createTmpName();
- m_file = ::fopen(tmpName.c_str(), "rb");
- }
-
- if (m_file != NULL)
- {
- ::fclose(m_file);
- m_file = NULL;
-
- if (0 == ::rename(m_newName.c_str(), m_oldName.c_str()))
- success = true;
-
- if (tmpName.empty())
- tmpName = createTmpName();
-
- ::remove(tmpName.c_str());
- }
-
- m_oldName.clear();
- m_newName.clear();
-
- return success;
-}
-
-std::string ScopedFileRenamer::createTmpName() const
-{
- std::string tmpFilename = m_oldName;
- tmpFilename.append(".tmp");
- return tmpFilename;
-}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.h b/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.h
deleted file mode 100644
index 594192eceb2..00000000000
--- a/Core/Libraries/Source/WWVegas/WWLib/ScopedFileRenamer.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-** Command & Conquer Generals Zero Hour(tm)
-** Copyright 2025 TheSuperHackers
-**
-** 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 .
-*/
-
-#pragma once
-
-#include "always.h"
-
-#include
-#include
-
-
-class ScopedFileRenamer
-{
-public:
-
- ScopedFileRenamer();
- ScopedFileRenamer(const char* oldName, const char* newName);
- ~ScopedFileRenamer();
-
- bool rename(const char* oldName, const char* newName);
- bool revert();
-
-private:
-
- std::string createTmpName() const;
-
-private:
-
- std::string m_oldName;
- std::string m_newName;
- FILE* m_file;
-};
From f92f4ff84aed2867c88f683215d3830b7af85a98 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Sat, 5 Jul 2025 20:23:56 +0200
Subject: [PATCH 04/20] Update comments
---
Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h | 2 +-
Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 6 ++++--
.../Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 6 ++++--
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
index c613cb3b4cd..1a3e8931a4a 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpGuard.h
@@ -24,7 +24,7 @@
// This class temporarily loads and unloads dbghelp.dll from the desired location to prevent
// other code from potentially loading it from an undesired location.
// This helps avoid crashing on boot using recent AMD/ATI drivers, which attempt to load and use
-// dbghelp.dll from the game install directory but are unable to do so correctly because
+// dbghelp.dll from the game install directory but are unable to do so without crashing because
// the dbghelp.dll that ships with the game is very old and the AMD/ATI code does not handle
// that correctly.
diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 3f017b79964..0b012124bfd 100644
--- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -314,7 +314,8 @@ bool DX8Wrapper::Init(void * hwnd, bool lite)
*/
WWDEBUG_SAY(("Create Direct3D8"));
{
- // TheSuperHackers @bugfix xezon 13/06/2025 Temporarily unload dbghelp.dll and prevent it from loading.
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll
+ // to prevent the graphics driver from potentially loading the old game dbghelp.dll.
DbgHelpGuard dbgHelpGuard;
D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
@@ -566,7 +567,8 @@ bool DX8Wrapper::Create_Device(void)
HRESULT hr;
{
- // TheSuperHackers @bugfix xezon 13/06/2025 Temporarily unload dbghelp.dll and prevent it from loading.
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll
+ // to prevent the graphics driver from potentially loading the old game dbghelp.dll.
DbgHelpGuard dbgHelpGuard;
hr=D3DInterface->CreateDevice
diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 48b0222ec08..16d085081bc 100644
--- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -333,7 +333,8 @@ bool DX8Wrapper::Init(void * hwnd, bool lite)
*/
WWDEBUG_SAY(("Create Direct3D8"));
{
- // TheSuperHackers @bugfix xezon 13/06/2025 Temporarily unload dbghelp.dll and prevent it from loading.
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll
+ // to prevent the graphics driver from potentially loading the old game dbghelp.dll.
DbgHelpGuard dbgHelpGuard;
D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
@@ -598,7 +599,8 @@ bool DX8Wrapper::Create_Device(void)
HRESULT hr;
{
- // TheSuperHackers @bugfix xezon 13/06/2025 Temporarily unload dbghelp.dll and prevent it from loading.
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll
+ // to prevent the graphics driver from potentially loading the old game dbghelp.dll.
DbgHelpGuard dbgHelpGuard;
hr=D3DInterface->CreateDevice
From 071dd7cd6422fe9bb0dd2d93ff5e42ab168e28ff Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Wed, 8 Oct 2025 19:33:56 +0200
Subject: [PATCH 05/20] Use leading tabs
---
.../Source/WWVegas/WWLib/DbgHelpLoader.cpp | 336 +++++++++---------
.../Source/WWVegas/WWLib/DbgHelpLoader.h | 274 +++++++-------
.../Source/WWVegas/WWLib/MallocAllocator.h | 120 +++----
3 files changed, 365 insertions(+), 365 deletions(-)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
index 4449ff15a60..31e8fa82e86 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -22,19 +22,19 @@
DbgHelpLoader* DbgHelpLoader::Inst = NULL;
DbgHelpLoader::DbgHelpLoader()
- : m_symInitialize(NULL)
- , m_symCleanup(NULL)
- , m_symLoadModule(NULL)
- , m_symUnloadModule(NULL)
- , m_symGetModuleBase(NULL)
- , m_symGetSymFromAddr(NULL)
- , m_symGetLineFromAddr(NULL)
- , m_symSetOptions(NULL)
- , m_symFunctionTableAccess(NULL)
- , m_stackWalk(NULL)
- , m_dllModule(HMODULE(0))
- , m_failed(false)
- , m_loadedFromSystem(false)
+ : m_symInitialize(NULL)
+ , m_symCleanup(NULL)
+ , m_symLoadModule(NULL)
+ , m_symUnloadModule(NULL)
+ , m_symGetModuleBase(NULL)
+ , m_symGetSymFromAddr(NULL)
+ , m_symGetLineFromAddr(NULL)
+ , m_symSetOptions(NULL)
+ , m_symFunctionTableAccess(NULL)
+ , m_stackWalk(NULL)
+ , m_dllModule(HMODULE(0))
+ , m_failed(false)
+ , m_loadedFromSystem(false)
{
}
@@ -44,226 +44,226 @@ DbgHelpLoader::~DbgHelpLoader()
bool DbgHelpLoader::isLoaded()
{
- return Inst != NULL && Inst->m_dllModule != HMODULE(0);
+ return Inst != NULL && Inst->m_dllModule != HMODULE(0);
}
bool DbgHelpLoader::isLoadedFromSystem()
{
- return Inst != NULL && Inst->m_loadedFromSystem;
+ return Inst != NULL && Inst->m_loadedFromSystem;
}
bool DbgHelpLoader::load()
{
- if (Inst == NULL)
- {
- // Cannot use new/delete here when this is loaded during game memory initialization.
- void* p = ::malloc(sizeof(DbgHelpLoader));
- Inst = new (p) DbgHelpLoader();
- }
-
- // Optimization: return early if it failed before.
- if (Inst->m_failed)
- return false;
-
- // Try load dbghelp.dll from the system directory first.
- char dllFilename[MAX_PATH];
- ::GetSystemDirectoryA(dllFilename, ARRAY_SIZE(dllFilename));
- strcat(dllFilename, "\\dbghelp.dll");
-
- Inst->m_dllModule = ::LoadLibraryA(dllFilename);
- if (Inst->m_dllModule == HMODULE(0))
- {
- // Not found. Try load dbghelp.dll from the work directory.
- Inst->m_dllModule = ::LoadLibraryA("dbghelp.dll");
- if (Inst->m_dllModule == HMODULE(0))
- {
- Inst->m_failed = true;
- return false;
- }
- }
- else
- {
- Inst->m_loadedFromSystem = true;
- }
-
- Inst->m_symInitialize = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymInitialize"));
- Inst->m_symCleanup = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymCleanup"));
- Inst->m_symLoadModule = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymLoadModule"));
- Inst->m_symUnloadModule = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymUnloadModule"));
- Inst->m_symGetModuleBase = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymGetModuleBase"));
- Inst->m_symGetSymFromAddr = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymGetSymFromAddr"));
- Inst->m_symGetLineFromAddr = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymGetLineFromAddr"));
- Inst->m_symSetOptions = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymSetOptions"));
- Inst->m_symFunctionTableAccess = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymFunctionTableAccess"));
- Inst->m_stackWalk = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "StackWalk"));
-
- if (Inst->m_symInitialize == NULL || Inst->m_symCleanup == NULL)
- {
- unload();
- Inst->m_failed = true;
- return false;
- }
-
- return true;
+ if (Inst == NULL)
+ {
+ // Cannot use new/delete here when this is loaded during game memory initialization.
+ void* p = ::malloc(sizeof(DbgHelpLoader));
+ Inst = new (p) DbgHelpLoader();
+ }
+
+ // Optimization: return early if it failed before.
+ if (Inst->m_failed)
+ return false;
+
+ // Try load dbghelp.dll from the system directory first.
+ char dllFilename[MAX_PATH];
+ ::GetSystemDirectoryA(dllFilename, ARRAY_SIZE(dllFilename));
+ strcat(dllFilename, "\\dbghelp.dll");
+
+ Inst->m_dllModule = ::LoadLibraryA(dllFilename);
+ if (Inst->m_dllModule == HMODULE(0))
+ {
+ // Not found. Try load dbghelp.dll from the work directory.
+ Inst->m_dllModule = ::LoadLibraryA("dbghelp.dll");
+ if (Inst->m_dllModule == HMODULE(0))
+ {
+ Inst->m_failed = true;
+ return false;
+ }
+ }
+ else
+ {
+ Inst->m_loadedFromSystem = true;
+ }
+
+ Inst->m_symInitialize = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymInitialize"));
+ Inst->m_symCleanup = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymCleanup"));
+ Inst->m_symLoadModule = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymLoadModule"));
+ Inst->m_symUnloadModule = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymUnloadModule"));
+ Inst->m_symGetModuleBase = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymGetModuleBase"));
+ Inst->m_symGetSymFromAddr = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymGetSymFromAddr"));
+ Inst->m_symGetLineFromAddr = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymGetLineFromAddr"));
+ Inst->m_symSetOptions = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymSetOptions"));
+ Inst->m_symFunctionTableAccess = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "SymFunctionTableAccess"));
+ Inst->m_stackWalk = reinterpret_cast(::GetProcAddress(Inst->m_dllModule, "StackWalk"));
+
+ if (Inst->m_symInitialize == NULL || Inst->m_symCleanup == NULL)
+ {
+ unload();
+ Inst->m_failed = true;
+ return false;
+ }
+
+ return true;
}
bool DbgHelpLoader::reload()
{
- unload();
- return load();
+ unload();
+ return load();
}
void DbgHelpLoader::unload()
{
- if (Inst == NULL)
- return;
-
- while (!Inst->m_initializedProcesses.empty())
- {
- symCleanup(*Inst->m_initializedProcesses.begin());
- }
-
- if (Inst->m_dllModule != HMODULE(0))
- {
- ::FreeLibrary(Inst->m_dllModule);
- Inst->m_dllModule = HMODULE(0);
- }
-
- Inst->~DbgHelpLoader();
- ::free(Inst);
- Inst = NULL;
+ if (Inst == NULL)
+ return;
+
+ while (!Inst->m_initializedProcesses.empty())
+ {
+ symCleanup(*Inst->m_initializedProcesses.begin());
+ }
+
+ if (Inst->m_dllModule != HMODULE(0))
+ {
+ ::FreeLibrary(Inst->m_dllModule);
+ Inst->m_dllModule = HMODULE(0);
+ }
+
+ Inst->~DbgHelpLoader();
+ ::free(Inst);
+ Inst = NULL;
}
BOOL DbgHelpLoader::symInitialize(
- HANDLE hProcess,
- LPSTR UserSearchPath,
- BOOL fInvadeProcess)
+ HANDLE hProcess,
+ LPSTR UserSearchPath,
+ BOOL fInvadeProcess)
{
- if (Inst == NULL)
- return FALSE;
-
- if (Inst->m_initializedProcesses.find(hProcess) != Inst->m_initializedProcesses.end())
- return FALSE;
-
- if (Inst->m_symInitialize)
- {
- if (Inst->m_symInitialize(hProcess, UserSearchPath, fInvadeProcess) != FALSE)
- {
- Inst->m_initializedProcesses.insert(hProcess);
- return TRUE;
- }
- }
-
- return FALSE;
+ if (Inst == NULL)
+ return FALSE;
+
+ if (Inst->m_initializedProcesses.find(hProcess) != Inst->m_initializedProcesses.end())
+ return FALSE;
+
+ if (Inst->m_symInitialize)
+ {
+ if (Inst->m_symInitialize(hProcess, UserSearchPath, fInvadeProcess) != FALSE)
+ {
+ Inst->m_initializedProcesses.insert(hProcess);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
}
BOOL DbgHelpLoader::symCleanup(
- HANDLE hProcess)
+ HANDLE hProcess)
{
- if (Inst == NULL)
- return FALSE;
+ if (Inst == NULL)
+ return FALSE;
- // @todo stl::find_and_erase
- Processes::iterator it = Inst->m_initializedProcesses.find(hProcess);
- if (it != Inst->m_initializedProcesses.end())
- Inst->m_initializedProcesses.erase(it);
+ // @todo stl::find_and_erase
+ Processes::iterator it = Inst->m_initializedProcesses.find(hProcess);
+ if (it != Inst->m_initializedProcesses.end())
+ Inst->m_initializedProcesses.erase(it);
- if (Inst->m_symCleanup)
- return Inst->m_symCleanup(hProcess);
+ if (Inst->m_symCleanup)
+ return Inst->m_symCleanup(hProcess);
- return FALSE;
+ return FALSE;
}
BOOL DbgHelpLoader::symLoadModule(
- HANDLE hProcess,
- HANDLE hFile,
- LPSTR ImageName,
- LPSTR ModuleName,
- DWORD BaseOfDll,
- DWORD SizeOfDll)
+ HANDLE hProcess,
+ HANDLE hFile,
+ LPSTR ImageName,
+ LPSTR ModuleName,
+ DWORD BaseOfDll,
+ DWORD SizeOfDll)
{
- if (Inst != NULL && Inst->m_symLoadModule)
- return Inst->m_symLoadModule(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll);
+ if (Inst != NULL && Inst->m_symLoadModule)
+ return Inst->m_symLoadModule(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll);
- return FALSE;
+ return FALSE;
}
DWORD DbgHelpLoader::symGetModuleBase(
- HANDLE hProcess,
- DWORD dwAddr)
+ HANDLE hProcess,
+ DWORD dwAddr)
{
- if (Inst != NULL && Inst->m_symGetModuleBase)
- return Inst->m_symGetModuleBase(hProcess, dwAddr);
+ if (Inst != NULL && Inst->m_symGetModuleBase)
+ return Inst->m_symGetModuleBase(hProcess, dwAddr);
- return 0u;
+ return 0u;
}
BOOL DbgHelpLoader::symUnloadModule(
- HANDLE hProcess,
- DWORD BaseOfDll)
+ HANDLE hProcess,
+ DWORD BaseOfDll)
{
- if (Inst != NULL && Inst->m_symUnloadModule)
- return Inst->m_symUnloadModule(hProcess, BaseOfDll);
+ if (Inst != NULL && Inst->m_symUnloadModule)
+ return Inst->m_symUnloadModule(hProcess, BaseOfDll);
- return FALSE;
+ return FALSE;
}
BOOL DbgHelpLoader::symGetSymFromAddr(
- HANDLE hProcess,
- DWORD Address,
- LPDWORD Displacement,
- PIMAGEHLP_SYMBOL Symbol)
+ HANDLE hProcess,
+ DWORD Address,
+ LPDWORD Displacement,
+ PIMAGEHLP_SYMBOL Symbol)
{
- if (Inst != NULL && Inst->m_symGetSymFromAddr)
- return Inst->m_symGetSymFromAddr(hProcess, Address, Displacement, Symbol);
+ if (Inst != NULL && Inst->m_symGetSymFromAddr)
+ return Inst->m_symGetSymFromAddr(hProcess, Address, Displacement, Symbol);
- return FALSE;
+ return FALSE;
}
BOOL DbgHelpLoader::symGetLineFromAddr(
- HANDLE hProcess,
- DWORD dwAddr,
- PDWORD pdwDisplacement,
- PIMAGEHLP_LINE Line)
+ HANDLE hProcess,
+ DWORD dwAddr,
+ PDWORD pdwDisplacement,
+ PIMAGEHLP_LINE Line)
{
- if (Inst != NULL && Inst->m_symGetLineFromAddr)
- return Inst->m_symGetLineFromAddr(hProcess, dwAddr, pdwDisplacement, Line);
+ if (Inst != NULL && Inst->m_symGetLineFromAddr)
+ return Inst->m_symGetLineFromAddr(hProcess, dwAddr, pdwDisplacement, Line);
- return FALSE;
+ return FALSE;
}
DWORD DbgHelpLoader::symSetOptions(
- DWORD SymOptions)
+ DWORD SymOptions)
{
- if (Inst != NULL && Inst->m_symSetOptions)
- return Inst->m_symSetOptions(SymOptions);
+ if (Inst != NULL && Inst->m_symSetOptions)
+ return Inst->m_symSetOptions(SymOptions);
- return 0u;
+ return 0u;
}
LPVOID DbgHelpLoader::symFunctionTableAccess(
- HANDLE hProcess,
- DWORD AddrBase)
+ HANDLE hProcess,
+ DWORD AddrBase)
{
- if (Inst != NULL && Inst->m_symFunctionTableAccess)
- return Inst->m_symFunctionTableAccess(hProcess, AddrBase);
+ if (Inst != NULL && Inst->m_symFunctionTableAccess)
+ return Inst->m_symFunctionTableAccess(hProcess, AddrBase);
- return NULL;
+ return NULL;
}
BOOL DbgHelpLoader::stackWalk(
- DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME StackFrame,
- LPVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE TranslateAddress)
+ DWORD MachineType,
+ HANDLE hProcess,
+ HANDLE hThread,
+ LPSTACKFRAME StackFrame,
+ LPVOID ContextRecord,
+ PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
+ PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
+ PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
+ PTRANSLATE_ADDRESS_ROUTINE TranslateAddress)
{
- if (Inst != NULL && Inst->m_stackWalk)
- return Inst->m_stackWalk(MachineType, hProcess, hThread, StackFrame, ContextRecord, ReadMemoryRoutine, FunctionTableAccessRoutine, GetModuleBaseRoutine, TranslateAddress);
+ if (Inst != NULL && Inst->m_stackWalk)
+ return Inst->m_stackWalk(MachineType, hProcess, hThread, StackFrame, ContextRecord, ReadMemoryRoutine, FunctionTableAccessRoutine, GetModuleBaseRoutine, TranslateAddress);
- return FALSE;
+ return FALSE;
}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
index 3a7d9cafa90..ab5780b96c9 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
@@ -33,148 +33,148 @@ class DbgHelpLoader
{
private:
- static DbgHelpLoader* Inst; // Is singleton class
+ static DbgHelpLoader* Inst; // Is singleton class
- DbgHelpLoader();
- ~DbgHelpLoader();
+ DbgHelpLoader();
+ ~DbgHelpLoader();
public:
- // Returns whether dbghelp.dll is loaded
- static bool isLoaded();
-
- // Returns whether dbghelp.dll is loaded from the system directory
- static bool isLoadedFromSystem();
-
- static bool load();
- static bool reload();
- static void unload();
-
- static BOOL WINAPI symInitialize(
- HANDLE hProcess,
- LPSTR UserSearchPath,
- BOOL fInvadeProcess);
-
- static BOOL WINAPI symCleanup(
- HANDLE hProcess);
-
- static BOOL WINAPI symLoadModule(
- HANDLE hProcess,
- HANDLE hFile,
- LPSTR ImageName,
- LPSTR ModuleName,
- DWORD BaseOfDll,
- DWORD SizeOfDll);
-
- static DWORD WINAPI symGetModuleBase(
- HANDLE hProcess,
- DWORD dwAddr);
-
- static BOOL WINAPI symUnloadModule(
- HANDLE hProcess,
- DWORD BaseOfDll);
-
- static BOOL WINAPI symGetSymFromAddr(
- HANDLE hProcess,
- DWORD Address,
- LPDWORD Displacement,
- PIMAGEHLP_SYMBOL Symbol);
-
- static BOOL WINAPI symGetLineFromAddr(
- HANDLE hProcess,
- DWORD dwAddr,
- PDWORD pdwDisplacement,
- PIMAGEHLP_LINE Line);
-
- static DWORD WINAPI symSetOptions(
- DWORD SymOptions);
-
- static LPVOID WINAPI symFunctionTableAccess(
- HANDLE hProcess,
- DWORD AddrBase);
-
- static BOOL WINAPI stackWalk(
- DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME StackFrame,
- LPVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE TranslateAddress);
+ // Returns whether dbghelp.dll is loaded
+ static bool isLoaded();
+
+ // Returns whether dbghelp.dll is loaded from the system directory
+ static bool isLoadedFromSystem();
+
+ static bool load();
+ static bool reload();
+ static void unload();
+
+ static BOOL WINAPI symInitialize(
+ HANDLE hProcess,
+ LPSTR UserSearchPath,
+ BOOL fInvadeProcess);
+
+ static BOOL WINAPI symCleanup(
+ HANDLE hProcess);
+
+ static BOOL WINAPI symLoadModule(
+ HANDLE hProcess,
+ HANDLE hFile,
+ LPSTR ImageName,
+ LPSTR ModuleName,
+ DWORD BaseOfDll,
+ DWORD SizeOfDll);
+
+ static DWORD WINAPI symGetModuleBase(
+ HANDLE hProcess,
+ DWORD dwAddr);
+
+ static BOOL WINAPI symUnloadModule(
+ HANDLE hProcess,
+ DWORD BaseOfDll);
+
+ static BOOL WINAPI symGetSymFromAddr(
+ HANDLE hProcess,
+ DWORD Address,
+ LPDWORD Displacement,
+ PIMAGEHLP_SYMBOL Symbol);
+
+ static BOOL WINAPI symGetLineFromAddr(
+ HANDLE hProcess,
+ DWORD dwAddr,
+ PDWORD pdwDisplacement,
+ PIMAGEHLP_LINE Line);
+
+ static DWORD WINAPI symSetOptions(
+ DWORD SymOptions);
+
+ static LPVOID WINAPI symFunctionTableAccess(
+ HANDLE hProcess,
+ DWORD AddrBase);
+
+ static BOOL WINAPI stackWalk(
+ DWORD MachineType,
+ HANDLE hProcess,
+ HANDLE hThread,
+ LPSTACKFRAME StackFrame,
+ LPVOID ContextRecord,
+ PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
+ PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
+ PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
+ PTRANSLATE_ADDRESS_ROUTINE TranslateAddress);
private:
- typedef BOOL (WINAPI *SymInitialize_t) (
- HANDLE hProcess,
- LPSTR UserSearchPath,
- BOOL fInvadeProcess);
-
- typedef BOOL (WINAPI *SymCleanup_t) (
- HANDLE hProcess);
-
- typedef BOOL (WINAPI *SymLoadModule_t) (
- HANDLE hProcess,
- HANDLE hFile,
- LPSTR ImageName,
- LPSTR ModuleName,
- DWORD BaseOfDll,
- DWORD SizeOfDll);
-
- typedef DWORD (WINAPI *SymGetModuleBase_t) (
- HANDLE hProcess,
- DWORD dwAddr);
-
- typedef BOOL (WINAPI *SymUnloadModule_t) (
- HANDLE hProcess,
- DWORD BaseOfDll);
-
- typedef BOOL (WINAPI *SymGetSymFromAddr_t) (
- HANDLE hProcess,
- DWORD Address,
- LPDWORD Displacement,
- PIMAGEHLP_SYMBOL Symbol);
-
- typedef BOOL (WINAPI* SymGetLineFromAddr_t) (
- HANDLE hProcess,
- DWORD dwAddr,
- PDWORD pdwDisplacement,
- PIMAGEHLP_LINE Line);
-
- typedef DWORD (WINAPI *SymSetOptions_t) (
- DWORD SymOptions);
-
- typedef LPVOID (WINAPI *SymFunctionTableAccess_t) (
- HANDLE hProcess,
- DWORD AddrBase);
-
- typedef BOOL (WINAPI *StackWalk_t) (
- DWORD MachineType,
- HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME StackFrame,
- LPVOID ContextRecord,
- PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
- PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
- PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
- PTRANSLATE_ADDRESS_ROUTINE TranslateAddress);
-
- SymInitialize_t m_symInitialize;
- SymCleanup_t m_symCleanup;
- SymLoadModule_t m_symLoadModule;
- SymUnloadModule_t m_symUnloadModule;
- SymGetModuleBase_t m_symGetModuleBase;
- SymGetSymFromAddr_t m_symGetSymFromAddr;
- SymGetLineFromAddr_t m_symGetLineFromAddr;
- SymSetOptions_t m_symSetOptions;
- SymFunctionTableAccess_t m_symFunctionTableAccess;
- StackWalk_t m_stackWalk;
-
- typedef std::set, stl::malloc_allocator > Processes;
-
- Processes m_initializedProcesses;
- HMODULE m_dllModule;
- bool m_failed;
- bool m_loadedFromSystem;
+ typedef BOOL (WINAPI *SymInitialize_t) (
+ HANDLE hProcess,
+ LPSTR UserSearchPath,
+ BOOL fInvadeProcess);
+
+ typedef BOOL (WINAPI *SymCleanup_t) (
+ HANDLE hProcess);
+
+ typedef BOOL (WINAPI *SymLoadModule_t) (
+ HANDLE hProcess,
+ HANDLE hFile,
+ LPSTR ImageName,
+ LPSTR ModuleName,
+ DWORD BaseOfDll,
+ DWORD SizeOfDll);
+
+ typedef DWORD (WINAPI *SymGetModuleBase_t) (
+ HANDLE hProcess,
+ DWORD dwAddr);
+
+ typedef BOOL (WINAPI *SymUnloadModule_t) (
+ HANDLE hProcess,
+ DWORD BaseOfDll);
+
+ typedef BOOL (WINAPI *SymGetSymFromAddr_t) (
+ HANDLE hProcess,
+ DWORD Address,
+ LPDWORD Displacement,
+ PIMAGEHLP_SYMBOL Symbol);
+
+ typedef BOOL (WINAPI* SymGetLineFromAddr_t) (
+ HANDLE hProcess,
+ DWORD dwAddr,
+ PDWORD pdwDisplacement,
+ PIMAGEHLP_LINE Line);
+
+ typedef DWORD (WINAPI *SymSetOptions_t) (
+ DWORD SymOptions);
+
+ typedef LPVOID (WINAPI *SymFunctionTableAccess_t) (
+ HANDLE hProcess,
+ DWORD AddrBase);
+
+ typedef BOOL (WINAPI *StackWalk_t) (
+ DWORD MachineType,
+ HANDLE hProcess,
+ HANDLE hThread,
+ LPSTACKFRAME StackFrame,
+ LPVOID ContextRecord,
+ PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
+ PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
+ PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
+ PTRANSLATE_ADDRESS_ROUTINE TranslateAddress);
+
+ SymInitialize_t m_symInitialize;
+ SymCleanup_t m_symCleanup;
+ SymLoadModule_t m_symLoadModule;
+ SymUnloadModule_t m_symUnloadModule;
+ SymGetModuleBase_t m_symGetModuleBase;
+ SymGetSymFromAddr_t m_symGetSymFromAddr;
+ SymGetLineFromAddr_t m_symGetLineFromAddr;
+ SymSetOptions_t m_symSetOptions;
+ SymFunctionTableAccess_t m_symFunctionTableAccess;
+ StackWalk_t m_stackWalk;
+
+ typedef std::set, stl::malloc_allocator > Processes;
+
+ Processes m_initializedProcesses;
+ HMODULE m_dllModule;
+ bool m_failed;
+ bool m_loadedFromSystem;
};
diff --git a/Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h b/Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h
index e465b0ad5d1..c56c955508c 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h
@@ -33,75 +33,75 @@ class malloc_allocator
{
public:
- typedef T value_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- template
- struct rebind
- {
- typedef malloc_allocator other;
- };
-
- malloc_allocator() throw() {}
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ template
+ struct rebind
+ {
+ typedef malloc_allocator other;
+ };
+
+ malloc_allocator() throw() {}
#if !(defined(_MSC_VER) && _MSC_VER < 1300)
- malloc_allocator(const malloc_allocator&) throw() {}
+ malloc_allocator(const malloc_allocator&) throw() {}
#endif
- template
- malloc_allocator(const malloc_allocator&) throw() {}
+ template
+ malloc_allocator(const malloc_allocator&) throw() {}
- ~malloc_allocator() throw() {}
+ ~malloc_allocator() throw() {}
- pointer address(reference x) const { return &x; }
- const_pointer address(const_reference x) const { return &x; }
+ pointer address(reference x) const { return &x; }
+ const_pointer address(const_reference x) const { return &x; }
- pointer allocate(size_type n, const void* = 0)
- {
- if (n > max_size())
- throw std::bad_alloc();
+ pointer allocate(size_type n, const void* = 0)
+ {
+ if (n > max_size())
+ throw std::bad_alloc();
- void* p = ::malloc(n * sizeof(T));
- if (!p)
- throw std::bad_alloc();
- return static_cast(p);
- }
+ void* p = ::malloc(n * sizeof(T));
+ if (!p)
+ throw std::bad_alloc();
+ return static_cast(p);
+ }
- void deallocate(pointer p, size_type)
- {
- ::free(p);
- }
+ void deallocate(pointer p, size_type)
+ {
+ ::free(p);
+ }
- void construct(pointer p, const T& val)
- {
- new (static_cast(p)) T(val);
- }
+ void construct(pointer p, const T& val)
+ {
+ new (static_cast(p)) T(val);
+ }
- void destroy(pointer p)
- {
- p->~T();
- }
+ void destroy(pointer p)
+ {
+ p->~T();
+ }
- size_type max_size() const throw()
- {
- return ~size_type(0) / sizeof(T);
- }
+ size_type max_size() const throw()
+ {
+ return ~size_type(0) / sizeof(T);
+ }
};
// Allocators of same type are always equal
template
bool operator==(const malloc_allocator&, const malloc_allocator&) throw() {
- return true;
+ return true;
}
template
bool operator!=(const malloc_allocator&, const malloc_allocator&) throw() {
- return false;
+ return false;
}
} // namespace stl
@@ -112,18 +112,18 @@ bool operator!=(const malloc_allocator&, const malloc_allocator&) throw(
// This tells STLport how to rebind malloc_allocator
namespace std
{
- template
- struct __stl_alloc_rebind_helper;
-
- template
- inline stl::malloc_allocator& __stl_alloc_rebind(stl::malloc_allocator& a, const Tp2*) {
- return *reinterpret_cast*>(&a);
- }
-
- template
- inline const stl::malloc_allocator& __stl_alloc_rebind(const stl::malloc_allocator& a, const Tp2*) {
- return *reinterpret_cast*>(&a);
- }
+ template
+ struct __stl_alloc_rebind_helper;
+
+ template
+ inline stl::malloc_allocator& __stl_alloc_rebind(stl::malloc_allocator& a, const Tp2*) {
+ return *reinterpret_cast*>(&a);
+ }
+
+ template
+ inline const stl::malloc_allocator& __stl_alloc_rebind(const stl::malloc_allocator& a, const Tp2*) {
+ return *reinterpret_cast*>(&a);
+ }
}
#endif
From 04007497dca06fb20cdf0e11731332c147a1b76d Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Wed, 8 Oct 2025 19:54:57 +0200
Subject: [PATCH 06/20] Use strlcat
---
Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
index 31e8fa82e86..0ec68c4f39e 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -68,7 +68,7 @@ bool DbgHelpLoader::load()
// Try load dbghelp.dll from the system directory first.
char dllFilename[MAX_PATH];
::GetSystemDirectoryA(dllFilename, ARRAY_SIZE(dllFilename));
- strcat(dllFilename, "\\dbghelp.dll");
+ strlcat(dllFilename, "\\dbghelp.dll", ARRAY_SIZE(dllFilename));
Inst->m_dllModule = ::LoadLibraryA(dllFilename);
if (Inst->m_dllModule == HMODULE(0))
From 9a40fb7ac67f7db992ee6185824f43e63e372d21 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Wed, 8 Oct 2025 19:55:26 +0200
Subject: [PATCH 07/20] Use stl::find_and_erase
---
Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
index 0ec68c4f39e..b1eed2d5fc7 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -163,10 +163,7 @@ BOOL DbgHelpLoader::symCleanup(
if (Inst == NULL)
return FALSE;
- // @todo stl::find_and_erase
- Processes::iterator it = Inst->m_initializedProcesses.find(hProcess);
- if (it != Inst->m_initializedProcesses.end())
- Inst->m_initializedProcesses.erase(it);
+ stl::find_and_erase(Inst->m_initializedProcesses, hProcess);
if (Inst->m_symCleanup)
return Inst->m_symCleanup(hProcess);
From c101568f46970f21315a8e830513121acc05582c Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Wed, 8 Oct 2025 20:02:00 +0200
Subject: [PATCH 08/20] Improve DbgHelpLoader
---
.../Source/WWVegas/WWLib/DbgHelpLoader.cpp | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
index b1eed2d5fc7..d1bcef2e3c4 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -143,12 +143,16 @@ BOOL DbgHelpLoader::symInitialize(
return FALSE;
if (Inst->m_initializedProcesses.find(hProcess) != Inst->m_initializedProcesses.end())
- return FALSE;
+ {
+ // Was already initialized.
+ return TRUE;
+ }
if (Inst->m_symInitialize)
{
if (Inst->m_symInitialize(hProcess, UserSearchPath, fInvadeProcess) != FALSE)
{
+ // Is now initialized.
Inst->m_initializedProcesses.insert(hProcess);
return TRUE;
}
@@ -163,10 +167,13 @@ BOOL DbgHelpLoader::symCleanup(
if (Inst == NULL)
return FALSE;
- stl::find_and_erase(Inst->m_initializedProcesses, hProcess);
-
- if (Inst->m_symCleanup)
- return Inst->m_symCleanup(hProcess);
+ if (stl::find_and_erase(Inst->m_initializedProcesses, hProcess))
+ {
+ if (Inst->m_symCleanup)
+ {
+ return Inst->m_symCleanup(hProcess);
+ }
+ }
return FALSE;
}
From e7a99e600ac4a29cac7b2e36f55f96452be30e23 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Wed, 8 Oct 2025 20:06:53 +0200
Subject: [PATCH 09/20] Fix trailing whitespace
---
Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 2 +-
GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 0b012124bfd..03c498e7920 100644
--- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -578,7 +578,7 @@ bool DX8Wrapper::Create_Device(void)
_Hwnd,
Vertex_Processing_Behavior,
&_PresentParameters,
- &D3DDevice
+ &D3DDevice
);
}
diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 16d085081bc..548fa59ec9c 100644
--- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -610,7 +610,7 @@ bool DX8Wrapper::Create_Device(void)
_Hwnd,
Vertex_Processing_Behavior,
&_PresentParameters,
- &D3DDevice
+ &D3DDevice
);
}
From 753790632f7ec3f058a29873a413f8ae5df89d9b Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Thu, 9 Oct 2025 21:09:10 +0200
Subject: [PATCH 10/20] Simplify lib load with LOAD_LIBRARY_SEARCH_SYSTEM32
---
Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
index d1bcef2e3c4..650304573af 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -66,14 +66,10 @@ bool DbgHelpLoader::load()
return false;
// Try load dbghelp.dll from the system directory first.
- char dllFilename[MAX_PATH];
- ::GetSystemDirectoryA(dllFilename, ARRAY_SIZE(dllFilename));
- strlcat(dllFilename, "\\dbghelp.dll", ARRAY_SIZE(dllFilename));
-
- Inst->m_dllModule = ::LoadLibraryA(dllFilename);
+ Inst->m_dllModule = ::LoadLibraryExA("dbghelp.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (Inst->m_dllModule == HMODULE(0))
{
- // Not found. Try load dbghelp.dll from the work directory.
+ // Not found. Try load dbghelp.dll from the work directory or wherever else it will be looking.
Inst->m_dllModule = ::LoadLibraryA("dbghelp.dll");
if (Inst->m_dllModule == HMODULE(0))
{
From d362366d7ed131a40c501ef43c236b8a36685621 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Fri, 10 Oct 2025 19:58:47 +0200
Subject: [PATCH 11/20] Replace MallocAllocator with SystemAllocator
---
Core/GameEngine/CMakeLists.txt | 1 +
Core/GameEngine/Include/Common/GameMemory.h | 15 +++
.../Source/Common/System/GameMemory.cpp | 95 +-------------
.../Source/Common/System/GameMemoryCommon.cpp | 121 ++++++++++++++++++
.../Source/WWVegas/WWLib/CMakeLists.txt | 2 +-
.../Source/WWVegas/WWLib/DbgHelpLoader.cpp | 4 +-
.../Source/WWVegas/WWLib/DbgHelpLoader.h | 4 +-
.../{MallocAllocator.h => SystemAllocator.h} | 32 ++---
Core/Libraries/Source/WWVegas/WWLib/always.h | 3 +
9 files changed, 166 insertions(+), 111 deletions(-)
create mode 100644 Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
rename Core/Libraries/Source/WWVegas/WWLib/{MallocAllocator.h => SystemAllocator.h} (69%)
diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt
index 0a58dfc4315..362c5be8f86 100644
--- a/Core/GameEngine/CMakeLists.txt
+++ b/Core/GameEngine/CMakeLists.txt
@@ -651,6 +651,7 @@ set(GAMEENGINE_SRC
# Source/Common/System/FunctionLexicon.cpp
# Source/Common/System/GameCommon.cpp
#Source/Common/System/GameMemory.cpp # is conditionally appended
+ Source/Common/System/GameMemoryCommon.cpp
#Source/Common/System/GameMemoryInit.cpp # is conditionally appended
# Source/Common/System/GameType.cpp
# Source/Common/System/Geometry.cpp
diff --git a/Core/GameEngine/Include/Common/GameMemory.h b/Core/GameEngine/Include/Common/GameMemory.h
index 65b1732e527..92f1ea2a911 100644
--- a/Core/GameEngine/Include/Common/GameMemory.h
+++ b/Core/GameEngine/Include/Common/GameMemory.h
@@ -177,8 +177,23 @@
};
+#define USE_FILLER_VALUE
+
#endif // MEMORYPOOL_DEBUG
+extern Int thePeakSystemAllocationInBytes;
+
+// TheSuperHackers @tweak The system allocator functions are now global.
+// Use this to bypass Game Memory Pools in exceptional circumstances.
+extern void* sysAllocateDoNotZero(size_t numBytes);
+extern void sysFree(void* p);
+extern void memset32(void* ptr, Int value, size_t bytesToFill);
+
+#ifdef USE_FILLER_VALUE
+extern UnsignedInt s_initFillerValue;
+extern void calcFillerValue(Int index);
+#endif
+
// TheSuperHackers @build xezon 30/03/2025 Define DISABLE_GAMEMEMORY to use a null implementations for Game Memory.
// Useful for address sanitizer checks and other investigations.
// Is included below the macros so that memory pool debug code can still be used.
diff --git a/Core/GameEngine/Source/Common/System/GameMemory.cpp b/Core/GameEngine/Source/Common/System/GameMemory.cpp
index 8fcf71b1388..123ce33b31d 100644
--- a/Core/GameEngine/Source/Common/System/GameMemory.cpp
+++ b/Core/GameEngine/Source/Common/System/GameMemory.cpp
@@ -114,21 +114,7 @@ DECLARE_PERF_TIMER(MemoryPoolInitFilling)
#define MEMORYPOOL_SINGLEBLOCK_GETS_STACKTRACE
#endif
- #define USE_FILLER_VALUE
-
const Int MAX_INIT_FILLER_COUNT = 8;
- #ifdef USE_FILLER_VALUE
- static UnsignedInt s_initFillerValue = 0xf00dcafe; // will be replaced, should never be this value at runtime
- static void calcFillerValue(Int index)
- {
- s_initFillerValue = (index & 3) << 1;
- s_initFillerValue |= 0x01;
- s_initFillerValue |= (~(s_initFillerValue << 4)) & 0xf0;
- s_initFillerValue |= (s_initFillerValue << 8);
- s_initFillerValue |= (s_initFillerValue << 16);
- //DEBUG_LOG(("Setting MemoryPool initFillerValue to %08x (index %d)",s_initFillerValue,index));
- }
- #endif
#endif
@@ -169,8 +155,6 @@ DECLARE_PERF_TIMER(MemoryPoolInitFilling)
#ifdef MEMORYPOOL_DEBUG
- static Int theTotalSystemAllocationInBytes = 0;
- static Int thePeakSystemAllocationInBytes = 0;
static Int theTotalLargeBlocks = 0;
static Int thePeakLargeBlocks = 0;
Int theTotalDMA = 0;
@@ -203,9 +187,7 @@ static Bool theMainInitFlag = false;
#define MEM_BOUND_ALIGNMENT 4
static Int roundUpMemBound(Int i);
-static void *sysAllocateDoNotZero(Int numBytes);
-static void sysFree(void* p);
-static void memset32(void* ptr, Int value, Int bytesToFill);
+
#ifdef MEMORYPOOL_STACKTRACE
static void doStackDumpOutput(const char* m);
static void doStackDump(void **stacktrace, int size);
@@ -223,73 +205,6 @@ static Int roundUpMemBound(Int i)
return (i + (MEM_BOUND_ALIGNMENT-1)) & ~(MEM_BOUND_ALIGNMENT-1);
}
-//-----------------------------------------------------------------------------
-/**
- this is the low-level allocator that we use to request memory from the OS.
- all (repeat, all) memory allocations in this module should ultimately
- go thru this routine (or sysAllocate).
-
- note: throws ERROR_OUT_OF_MEMORY on failure; never returns null
-*/
-static void* sysAllocateDoNotZero(Int numBytes)
-{
- void* p = ::GlobalAlloc(GMEM_FIXED, numBytes);
- if (!p)
- throw ERROR_OUT_OF_MEMORY;
-#ifdef MEMORYPOOL_DEBUG
- {
- USE_PERF_TIMER(MemoryPoolDebugging)
- #ifdef USE_FILLER_VALUE
- {
- USE_PERF_TIMER(MemoryPoolInitFilling)
- ::memset32(p, s_initFillerValue, ::GlobalSize(p));
- }
- #endif
- theTotalSystemAllocationInBytes += ::GlobalSize(p);
- if (thePeakSystemAllocationInBytes < theTotalSystemAllocationInBytes)
- thePeakSystemAllocationInBytes = theTotalSystemAllocationInBytes;
- }
-#endif
- return p;
-}
-
-//-----------------------------------------------------------------------------
-/**
- the counterpart to sysAllocate / sysAllocateDoNotZero; used to free blocks
- allocated by them. it is OK to pass null here (it will just be ignored).
-*/
-static void sysFree(void* p)
-{
- if (p)
- {
-#ifdef MEMORYPOOL_DEBUG
- {
- USE_PERF_TIMER(MemoryPoolDebugging)
- ::memset32(p, GARBAGE_FILL_VALUE, ::GlobalSize(p));
- theTotalSystemAllocationInBytes -= ::GlobalSize(p);
- }
-#endif
- ::GlobalFree(p);
- }
-}
-
-// ----------------------------------------------------------------------------
-/**
- fills memory with a 32-bit value (note: assumes the ptr is 4-byte-aligned)
-*/
-static void memset32(void* ptr, Int value, Int bytesToFill)
-{
- Int wordsToFill = bytesToFill>>2;
- bytesToFill -= (wordsToFill<<2);
-
- Int *p = (Int*)ptr;
- for (++wordsToFill; --wordsToFill; )
- *p++ = value;
-
- Byte *b = (Byte *)p;
- for (++bytesToFill; --bytesToFill; )
- *b++ = (Byte)value;
-}
#ifdef MEMORYPOOL_STACKTRACE
// ----------------------------------------------------------------------------
@@ -1633,7 +1548,7 @@ void* MemoryPool::allocateBlockDoNotZeroImplementation(DECLARE_LITERALSTRING_ARG
if (m_firstBlobWithFreeBlocks != NULL && !m_firstBlobWithFreeBlocks->hasAnyFreeBlocks())
{
// hmm... the current 'free' blob has nothing available. look and see if there
- // are any other existing blobs with freespace.
+ // are any other existing blobs with free space.
MemoryPoolBlob *blob = m_firstBlob;
for (; blob != NULL; blob = blob->getNextInList())
{
@@ -1641,12 +1556,12 @@ void* MemoryPool::allocateBlockDoNotZeroImplementation(DECLARE_LITERALSTRING_ARG
break;
}
- // note that if we walk thru the list without finding anything, this will
- // reset m_firstBlobWithFreeBlocks to null and fall thru.
+ // note that if we walk through the list without finding anything, this will
+ // reset m_firstBlobWithFreeBlocks to null and fall through.
m_firstBlobWithFreeBlocks = blob;
}
- // OK, if we are here then we have no blobs with freespace... darn.
+ // OK, if we are here then we have no blobs with free space... darn.
// allocate an overflow block.
if (m_firstBlobWithFreeBlocks == NULL)
{
diff --git a/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp b/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
new file mode 100644
index 00000000000..5f05219be6c
--- /dev/null
+++ b/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
@@ -0,0 +1,121 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 TheSuperHackers
+**
+** 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 .
+*/
+
+#include "PreRTS.h"
+
+#include "Common/GameMemory.h"
+#include "Common/PerfTimer.h"
+
+#ifdef MEMORYPOOL_DEBUG
+
+static Int theTotalSystemAllocationInBytes = 0;
+Int thePeakSystemAllocationInBytes = 0;
+
+constexpr const Int GARBAGE_FILL_VALUE = 0xdeadbeef;
+
+DECLARE_PERF_TIMER(SysMemoryDebugging)
+DECLARE_PERF_TIMER(SysMemoryInitFilling)
+
+#endif // MEMORYPOOL_DEBUG
+
+//-----------------------------------------------------------------------------
+/**
+ this is the low-level allocator that we use to request memory from the OS.
+ all (repeat, all) memory allocations in this module should ultimately
+ go through this routine (or sysAllocateDoNotZero).
+
+ note: throws ERROR_OUT_OF_MEMORY on failure; never returns null
+*/
+void* sysAllocateDoNotZero(size_t numBytes)
+{
+ void* p = ::GlobalAlloc(GMEM_FIXED, numBytes);
+ if (!p)
+ throw ERROR_OUT_OF_MEMORY;
+
+#ifdef MEMORYPOOL_DEBUG
+ {
+ USE_PERF_TIMER(SysMemoryDebugging)
+ #ifdef USE_FILLER_VALUE
+ {
+ USE_PERF_TIMER(SysMemoryInitFilling)
+ ::memset32(p, s_initFillerValue, ::GlobalSize(p));
+ }
+ #endif
+ theTotalSystemAllocationInBytes += ::GlobalSize(p);
+ if (thePeakSystemAllocationInBytes < theTotalSystemAllocationInBytes)
+ thePeakSystemAllocationInBytes = theTotalSystemAllocationInBytes;
+ }
+#endif
+
+ return p;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ the counterpart to sysAllocate / sysAllocateDoNotZero; used to free blocks
+ allocated by them. it is OK to pass null here (it will just be ignored).
+*/
+void sysFree(void* p)
+{
+ if (p)
+ {
+#ifdef MEMORYPOOL_DEBUG
+ {
+ USE_PERF_TIMER(MemoryPoolDebugging)
+ ::memset32(p, GARBAGE_FILL_VALUE, ::GlobalSize(p));
+ theTotalSystemAllocationInBytes -= ::GlobalSize(p);
+ }
+#endif
+
+ ::GlobalFree(p);
+ }
+}
+
+// ----------------------------------------------------------------------------
+/**
+ fills memory with a 32-bit value (note: assumes the ptr is 4-byte-aligned)
+*/
+void memset32(void* ptr, Int value, size_t bytesToFill)
+{
+ Int wordsToFill = bytesToFill>>2;
+ bytesToFill -= (wordsToFill<<2);
+
+ Int *p = (Int*)ptr;
+ for (++wordsToFill; --wordsToFill; )
+ *p++ = value;
+
+ Byte *b = (Byte *)p;
+ for (++bytesToFill; --bytesToFill; )
+ *b++ = (Byte)value;
+}
+
+#ifdef USE_FILLER_VALUE
+
+UnsignedInt s_initFillerValue = 0xf00dcafe; // will be replaced, should never be this value at runtime
+
+void calcFillerValue(Int index)
+{
+ s_initFillerValue = (index & 3) << 1;
+ s_initFillerValue |= 0x01;
+ s_initFillerValue |= (~(s_initFillerValue << 4)) & 0xf0;
+ s_initFillerValue |= (s_initFillerValue << 8);
+ s_initFillerValue |= (s_initFillerValue << 16);
+ //DEBUG_LOG(("Setting MemoryPool initFillerValue to %08x (index %d)",s_initFillerValue,index));
+}
+
+#endif // USE_FILLER_VALUE
diff --git a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
index 81579754a38..9a5ff2df350 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
+++ b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
@@ -70,7 +70,6 @@ set(WWLIB_SRC
#lzostraw.cpp
#lzostraw.h
#lzo_conf.h
- MallocAllocator.h
#md5.cpp
#md5.h
mempool.h
@@ -118,6 +117,7 @@ set(WWLIB_SRC
strtok_r.cpp
strtok_r.h
#swap.h
+ SystemAllocator.h
systimer.cpp
systimer.h
TARGA.CPP
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
index 650304573af..cbca3ea9c6c 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -57,7 +57,7 @@ bool DbgHelpLoader::load()
if (Inst == NULL)
{
// Cannot use new/delete here when this is loaded during game memory initialization.
- void* p = ::malloc(sizeof(DbgHelpLoader));
+ void* p = sysAllocateDoNotZero(sizeof(DbgHelpLoader));
Inst = new (p) DbgHelpLoader();
}
@@ -126,7 +126,7 @@ void DbgHelpLoader::unload()
}
Inst->~DbgHelpLoader();
- ::free(Inst);
+ sysFree(Inst);
Inst = NULL;
}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
index ab5780b96c9..7d83da31e5b 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.h
@@ -24,7 +24,7 @@
#include // Must be included after Windows.h
#include
-#include "MallocAllocator.h"
+#include "SystemAllocator.h"
// This static class can load and unload dbghelp.dll
// Internally it must not use new and delete because it can be created during game memory initialization.
@@ -171,7 +171,7 @@ class DbgHelpLoader
SymFunctionTableAccess_t m_symFunctionTableAccess;
StackWalk_t m_stackWalk;
- typedef std::set, stl::malloc_allocator > Processes;
+ typedef std::set, stl::system_allocator > Processes;
Processes m_initializedProcesses;
HMODULE m_dllModule;
diff --git a/Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h b/Core/Libraries/Source/WWVegas/WWLib/SystemAllocator.h
similarity index 69%
rename from Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h
rename to Core/Libraries/Source/WWVegas/WWLib/SystemAllocator.h
index c56c955508c..c0b399a17f4 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/SystemAllocator.h
@@ -26,10 +26,10 @@
namespace stl
{
-// STL allocator that uses malloc and free. Useful if allocations are meant to bypass new and delete.
+// STL allocator that uses the Operating System allocator functions. Useful if allocations are meant to bypass new and delete, malloc and free.
template
-class malloc_allocator
+class system_allocator
{
public:
@@ -44,19 +44,19 @@ class malloc_allocator
template
struct rebind
{
- typedef malloc_allocator other;
+ typedef system_allocator other;
};
- malloc_allocator() throw() {}
+ system_allocator() throw() {}
#if !(defined(_MSC_VER) && _MSC_VER < 1300)
- malloc_allocator(const malloc_allocator&) throw() {}
+ system_allocator(const system_allocator&) throw() {}
#endif
template
- malloc_allocator(const malloc_allocator&) throw() {}
+ system_allocator(const system_allocator&) throw() {}
- ~malloc_allocator() throw() {}
+ ~system_allocator() throw() {}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
@@ -66,7 +66,7 @@ class malloc_allocator
if (n > max_size())
throw std::bad_alloc();
- void* p = ::malloc(n * sizeof(T));
+ void* p = sysAllocateDoNotZero(n * sizeof(T));
if (!p)
throw std::bad_alloc();
return static_cast(p);
@@ -74,7 +74,7 @@ class malloc_allocator
void deallocate(pointer p, size_type)
{
- ::free(p);
+ sysFree(p);
}
void construct(pointer p, const T& val)
@@ -95,12 +95,12 @@ class malloc_allocator
// Allocators of same type are always equal
template
-bool operator==(const malloc_allocator&, const malloc_allocator&) throw() {
+bool operator==(const system_allocator&, const system_allocator&) throw() {
return true;
}
template
-bool operator!=(const malloc_allocator&, const malloc_allocator&) throw() {
+bool operator!=(const system_allocator&, const system_allocator&) throw() {
return false;
}
@@ -109,20 +109,20 @@ bool operator!=(const malloc_allocator&, const malloc_allocator&) throw(
#if defined(USING_STLPORT)
-// This tells STLport how to rebind malloc_allocator
+// This tells STLport how to rebind system_allocator
namespace std
{
template
struct __stl_alloc_rebind_helper;
template
- inline stl::malloc_allocator& __stl_alloc_rebind(stl::malloc_allocator& a, const Tp2*) {
- return *reinterpret_cast*>(&a);
+ inline stl::system_allocator& __stl_alloc_rebind(stl::system_allocator& a, const Tp2*) {
+ return *reinterpret_cast*>(&a);
}
template
- inline const stl::malloc_allocator& __stl_alloc_rebind(const stl::malloc_allocator& a, const Tp2*) {
- return *reinterpret_cast*>(&a);
+ inline const stl::system_allocator& __stl_alloc_rebind(const stl::system_allocator& a, const Tp2*) {
+ return *reinterpret_cast*>(&a);
}
}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/always.h b/Core/Libraries/Source/WWVegas/WWLib/always.h
index 3f7ab140549..4b46bd1a75d 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/always.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/always.h
@@ -79,6 +79,9 @@
#endif //_MSC_VER
#endif //RTS_DEBUG
+extern void* sysAllocateDoNotZero(size_t numBytes);
+extern void sysFree(void* p);
+
#if !defined(DISABLE_GAMEMEMORY) // (gth) killing the Generals Memory Manager!
#ifndef _OPERATOR_NEW_DEFINED_
From 3acad388b3184f16fb1fdf481d26a2f6e6c67b6d Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Fri, 10 Oct 2025 20:06:25 +0200
Subject: [PATCH 12/20] Fix compile error
---
Core/GameEngine/Include/Common/GameMemory.h | 1 +
Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/Core/GameEngine/Include/Common/GameMemory.h b/Core/GameEngine/Include/Common/GameMemory.h
index 92f1ea2a911..33922776abf 100644
--- a/Core/GameEngine/Include/Common/GameMemory.h
+++ b/Core/GameEngine/Include/Common/GameMemory.h
@@ -181,6 +181,7 @@
#endif // MEMORYPOOL_DEBUG
+extern Int theTotalSystemAllocationInBytes;
extern Int thePeakSystemAllocationInBytes;
// TheSuperHackers @tweak The system allocator functions are now global.
diff --git a/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp b/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
index 5f05219be6c..48ec20febc6 100644
--- a/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
+++ b/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
@@ -23,7 +23,7 @@
#ifdef MEMORYPOOL_DEBUG
-static Int theTotalSystemAllocationInBytes = 0;
+Int theTotalSystemAllocationInBytes = 0;
Int thePeakSystemAllocationInBytes = 0;
constexpr const Int GARBAGE_FILL_VALUE = 0xdeadbeef;
From f828b945d7b0a109baa78f9421267e607f7c9ff3 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Fri, 10 Oct 2025 20:08:46 +0200
Subject: [PATCH 13/20] Revert "Simplify lib load with
LOAD_LIBRARY_SEARCH_SYSTEM32"
This reverts commit 00c93ddbb1fe2f9a9e5111a0470101e71a0b7e0a.
---
Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
index cbca3ea9c6c..6c538ac6b48 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -66,10 +66,14 @@ bool DbgHelpLoader::load()
return false;
// Try load dbghelp.dll from the system directory first.
- Inst->m_dllModule = ::LoadLibraryExA("dbghelp.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ char dllFilename[MAX_PATH];
+ ::GetSystemDirectoryA(dllFilename, ARRAY_SIZE(dllFilename));
+ strlcat(dllFilename, "\\dbghelp.dll", ARRAY_SIZE(dllFilename));
+
+ Inst->m_dllModule = ::LoadLibraryA(dllFilename);
if (Inst->m_dllModule == HMODULE(0))
{
- // Not found. Try load dbghelp.dll from the work directory or wherever else it will be looking.
+ // Not found. Try load dbghelp.dll from the work directory.
Inst->m_dllModule = ::LoadLibraryA("dbghelp.dll");
if (Inst->m_dllModule == HMODULE(0))
{
From b267afb62ceb9fae931340435aba43f0d50a7eea Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Fri, 10 Oct 2025 20:14:27 +0200
Subject: [PATCH 14/20] Update comment
---
.../Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 548fa59ec9c..2d9f5c0e269 100644
--- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -333,8 +333,8 @@ bool DX8Wrapper::Init(void * hwnd, bool lite)
*/
WWDEBUG_SAY(("Create Direct3D8"));
{
- // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll
- // to prevent the graphics driver from potentially loading the old game dbghelp.dll.
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
+ // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
DbgHelpGuard dbgHelpGuard;
D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
@@ -599,8 +599,8 @@ bool DX8Wrapper::Create_Device(void)
HRESULT hr;
{
- // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll
- // to prevent the graphics driver from potentially loading the old game dbghelp.dll.
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
+ // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
DbgHelpGuard dbgHelpGuard;
hr=D3DInterface->CreateDevice
From b341518a0c141ab586a3f6e4e62dc75c4a543f22 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Fri, 10 Oct 2025 20:34:05 +0200
Subject: [PATCH 15/20] Fix W3DView compile error
---
Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp | 4 ++--
Core/Libraries/Source/WWVegas/WWLib/SystemAllocator.h | 5 ++---
Core/Libraries/Source/WWVegas/WWLib/always.h | 3 ---
3 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
index 6c538ac6b48..b5bcef62f48 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
+++ b/Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
@@ -57,7 +57,7 @@ bool DbgHelpLoader::load()
if (Inst == NULL)
{
// Cannot use new/delete here when this is loaded during game memory initialization.
- void* p = sysAllocateDoNotZero(sizeof(DbgHelpLoader));
+ void* p = GlobalAlloc(GMEM_FIXED, sizeof(DbgHelpLoader));
Inst = new (p) DbgHelpLoader();
}
@@ -130,7 +130,7 @@ void DbgHelpLoader::unload()
}
Inst->~DbgHelpLoader();
- sysFree(Inst);
+ GlobalFree(Inst);
Inst = NULL;
}
diff --git a/Core/Libraries/Source/WWVegas/WWLib/SystemAllocator.h b/Core/Libraries/Source/WWVegas/WWLib/SystemAllocator.h
index c0b399a17f4..00f65a79123 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/SystemAllocator.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/SystemAllocator.h
@@ -18,7 +18,6 @@
#pragma once
-#include // malloc, free
#include // std::size_t, std::ptrdiff_t
#include // std::bad_alloc
@@ -66,7 +65,7 @@ class system_allocator
if (n > max_size())
throw std::bad_alloc();
- void* p = sysAllocateDoNotZero(n * sizeof(T));
+ void* p = GlobalAlloc(GMEM_FIXED, n * sizeof(T));
if (!p)
throw std::bad_alloc();
return static_cast(p);
@@ -74,7 +73,7 @@ class system_allocator
void deallocate(pointer p, size_type)
{
- sysFree(p);
+ GlobalFree(p);
}
void construct(pointer p, const T& val)
diff --git a/Core/Libraries/Source/WWVegas/WWLib/always.h b/Core/Libraries/Source/WWVegas/WWLib/always.h
index 4b46bd1a75d..3f7ab140549 100644
--- a/Core/Libraries/Source/WWVegas/WWLib/always.h
+++ b/Core/Libraries/Source/WWVegas/WWLib/always.h
@@ -79,9 +79,6 @@
#endif //_MSC_VER
#endif //RTS_DEBUG
-extern void* sysAllocateDoNotZero(size_t numBytes);
-extern void sysFree(void* p);
-
#if !defined(DISABLE_GAMEMEMORY) // (gth) killing the Generals Memory Manager!
#ifndef _OPERATOR_NEW_DEFINED_
From 3648be636fede6362bd31b121935e2cded56e614 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Mon, 20 Oct 2025 18:18:06 +0200
Subject: [PATCH 16/20] Revert "Replace MallocAllocator with SystemAllocator"
This reverts commit de2f8b5a7b05f242712af7eab76a40a66f973c17.
# Conflicts:
# Core/GameEngine/Include/Common/GameMemory.h
# Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
# Core/Libraries/Source/WWVegas/WWLib/DbgHelpLoader.cpp
# Core/Libraries/Source/WWVegas/WWLib/MallocAllocator.h
---
Core/GameEngine/CMakeLists.txt | 1 -
Core/GameEngine/Include/Common/GameMemory.h | 16 ---
.../Source/Common/System/GameMemory.cpp | 95 +++++++++++++-
.../Source/Common/System/GameMemoryCommon.cpp | 121 ------------------
4 files changed, 90 insertions(+), 143 deletions(-)
delete mode 100644 Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt
index 362c5be8f86..0a58dfc4315 100644
--- a/Core/GameEngine/CMakeLists.txt
+++ b/Core/GameEngine/CMakeLists.txt
@@ -651,7 +651,6 @@ set(GAMEENGINE_SRC
# Source/Common/System/FunctionLexicon.cpp
# Source/Common/System/GameCommon.cpp
#Source/Common/System/GameMemory.cpp # is conditionally appended
- Source/Common/System/GameMemoryCommon.cpp
#Source/Common/System/GameMemoryInit.cpp # is conditionally appended
# Source/Common/System/GameType.cpp
# Source/Common/System/Geometry.cpp
diff --git a/Core/GameEngine/Include/Common/GameMemory.h b/Core/GameEngine/Include/Common/GameMemory.h
index 33922776abf..65b1732e527 100644
--- a/Core/GameEngine/Include/Common/GameMemory.h
+++ b/Core/GameEngine/Include/Common/GameMemory.h
@@ -177,24 +177,8 @@
};
-#define USE_FILLER_VALUE
-
#endif // MEMORYPOOL_DEBUG
-extern Int theTotalSystemAllocationInBytes;
-extern Int thePeakSystemAllocationInBytes;
-
-// TheSuperHackers @tweak The system allocator functions are now global.
-// Use this to bypass Game Memory Pools in exceptional circumstances.
-extern void* sysAllocateDoNotZero(size_t numBytes);
-extern void sysFree(void* p);
-extern void memset32(void* ptr, Int value, size_t bytesToFill);
-
-#ifdef USE_FILLER_VALUE
-extern UnsignedInt s_initFillerValue;
-extern void calcFillerValue(Int index);
-#endif
-
// TheSuperHackers @build xezon 30/03/2025 Define DISABLE_GAMEMEMORY to use a null implementations for Game Memory.
// Useful for address sanitizer checks and other investigations.
// Is included below the macros so that memory pool debug code can still be used.
diff --git a/Core/GameEngine/Source/Common/System/GameMemory.cpp b/Core/GameEngine/Source/Common/System/GameMemory.cpp
index 123ce33b31d..8fcf71b1388 100644
--- a/Core/GameEngine/Source/Common/System/GameMemory.cpp
+++ b/Core/GameEngine/Source/Common/System/GameMemory.cpp
@@ -114,7 +114,21 @@ DECLARE_PERF_TIMER(MemoryPoolInitFilling)
#define MEMORYPOOL_SINGLEBLOCK_GETS_STACKTRACE
#endif
+ #define USE_FILLER_VALUE
+
const Int MAX_INIT_FILLER_COUNT = 8;
+ #ifdef USE_FILLER_VALUE
+ static UnsignedInt s_initFillerValue = 0xf00dcafe; // will be replaced, should never be this value at runtime
+ static void calcFillerValue(Int index)
+ {
+ s_initFillerValue = (index & 3) << 1;
+ s_initFillerValue |= 0x01;
+ s_initFillerValue |= (~(s_initFillerValue << 4)) & 0xf0;
+ s_initFillerValue |= (s_initFillerValue << 8);
+ s_initFillerValue |= (s_initFillerValue << 16);
+ //DEBUG_LOG(("Setting MemoryPool initFillerValue to %08x (index %d)",s_initFillerValue,index));
+ }
+ #endif
#endif
@@ -155,6 +169,8 @@ DECLARE_PERF_TIMER(MemoryPoolInitFilling)
#ifdef MEMORYPOOL_DEBUG
+ static Int theTotalSystemAllocationInBytes = 0;
+ static Int thePeakSystemAllocationInBytes = 0;
static Int theTotalLargeBlocks = 0;
static Int thePeakLargeBlocks = 0;
Int theTotalDMA = 0;
@@ -187,7 +203,9 @@ static Bool theMainInitFlag = false;
#define MEM_BOUND_ALIGNMENT 4
static Int roundUpMemBound(Int i);
-
+static void *sysAllocateDoNotZero(Int numBytes);
+static void sysFree(void* p);
+static void memset32(void* ptr, Int value, Int bytesToFill);
#ifdef MEMORYPOOL_STACKTRACE
static void doStackDumpOutput(const char* m);
static void doStackDump(void **stacktrace, int size);
@@ -205,6 +223,73 @@ static Int roundUpMemBound(Int i)
return (i + (MEM_BOUND_ALIGNMENT-1)) & ~(MEM_BOUND_ALIGNMENT-1);
}
+//-----------------------------------------------------------------------------
+/**
+ this is the low-level allocator that we use to request memory from the OS.
+ all (repeat, all) memory allocations in this module should ultimately
+ go thru this routine (or sysAllocate).
+
+ note: throws ERROR_OUT_OF_MEMORY on failure; never returns null
+*/
+static void* sysAllocateDoNotZero(Int numBytes)
+{
+ void* p = ::GlobalAlloc(GMEM_FIXED, numBytes);
+ if (!p)
+ throw ERROR_OUT_OF_MEMORY;
+#ifdef MEMORYPOOL_DEBUG
+ {
+ USE_PERF_TIMER(MemoryPoolDebugging)
+ #ifdef USE_FILLER_VALUE
+ {
+ USE_PERF_TIMER(MemoryPoolInitFilling)
+ ::memset32(p, s_initFillerValue, ::GlobalSize(p));
+ }
+ #endif
+ theTotalSystemAllocationInBytes += ::GlobalSize(p);
+ if (thePeakSystemAllocationInBytes < theTotalSystemAllocationInBytes)
+ thePeakSystemAllocationInBytes = theTotalSystemAllocationInBytes;
+ }
+#endif
+ return p;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ the counterpart to sysAllocate / sysAllocateDoNotZero; used to free blocks
+ allocated by them. it is OK to pass null here (it will just be ignored).
+*/
+static void sysFree(void* p)
+{
+ if (p)
+ {
+#ifdef MEMORYPOOL_DEBUG
+ {
+ USE_PERF_TIMER(MemoryPoolDebugging)
+ ::memset32(p, GARBAGE_FILL_VALUE, ::GlobalSize(p));
+ theTotalSystemAllocationInBytes -= ::GlobalSize(p);
+ }
+#endif
+ ::GlobalFree(p);
+ }
+}
+
+// ----------------------------------------------------------------------------
+/**
+ fills memory with a 32-bit value (note: assumes the ptr is 4-byte-aligned)
+*/
+static void memset32(void* ptr, Int value, Int bytesToFill)
+{
+ Int wordsToFill = bytesToFill>>2;
+ bytesToFill -= (wordsToFill<<2);
+
+ Int *p = (Int*)ptr;
+ for (++wordsToFill; --wordsToFill; )
+ *p++ = value;
+
+ Byte *b = (Byte *)p;
+ for (++bytesToFill; --bytesToFill; )
+ *b++ = (Byte)value;
+}
#ifdef MEMORYPOOL_STACKTRACE
// ----------------------------------------------------------------------------
@@ -1548,7 +1633,7 @@ void* MemoryPool::allocateBlockDoNotZeroImplementation(DECLARE_LITERALSTRING_ARG
if (m_firstBlobWithFreeBlocks != NULL && !m_firstBlobWithFreeBlocks->hasAnyFreeBlocks())
{
// hmm... the current 'free' blob has nothing available. look and see if there
- // are any other existing blobs with free space.
+ // are any other existing blobs with freespace.
MemoryPoolBlob *blob = m_firstBlob;
for (; blob != NULL; blob = blob->getNextInList())
{
@@ -1556,12 +1641,12 @@ void* MemoryPool::allocateBlockDoNotZeroImplementation(DECLARE_LITERALSTRING_ARG
break;
}
- // note that if we walk through the list without finding anything, this will
- // reset m_firstBlobWithFreeBlocks to null and fall through.
+ // note that if we walk thru the list without finding anything, this will
+ // reset m_firstBlobWithFreeBlocks to null and fall thru.
m_firstBlobWithFreeBlocks = blob;
}
- // OK, if we are here then we have no blobs with free space... darn.
+ // OK, if we are here then we have no blobs with freespace... darn.
// allocate an overflow block.
if (m_firstBlobWithFreeBlocks == NULL)
{
diff --git a/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp b/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
deleted file mode 100644
index 48ec20febc6..00000000000
--- a/Core/GameEngine/Source/Common/System/GameMemoryCommon.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-** Command & Conquer Generals Zero Hour(tm)
-** Copyright 2025 TheSuperHackers
-**
-** 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 .
-*/
-
-#include "PreRTS.h"
-
-#include "Common/GameMemory.h"
-#include "Common/PerfTimer.h"
-
-#ifdef MEMORYPOOL_DEBUG
-
-Int theTotalSystemAllocationInBytes = 0;
-Int thePeakSystemAllocationInBytes = 0;
-
-constexpr const Int GARBAGE_FILL_VALUE = 0xdeadbeef;
-
-DECLARE_PERF_TIMER(SysMemoryDebugging)
-DECLARE_PERF_TIMER(SysMemoryInitFilling)
-
-#endif // MEMORYPOOL_DEBUG
-
-//-----------------------------------------------------------------------------
-/**
- this is the low-level allocator that we use to request memory from the OS.
- all (repeat, all) memory allocations in this module should ultimately
- go through this routine (or sysAllocateDoNotZero).
-
- note: throws ERROR_OUT_OF_MEMORY on failure; never returns null
-*/
-void* sysAllocateDoNotZero(size_t numBytes)
-{
- void* p = ::GlobalAlloc(GMEM_FIXED, numBytes);
- if (!p)
- throw ERROR_OUT_OF_MEMORY;
-
-#ifdef MEMORYPOOL_DEBUG
- {
- USE_PERF_TIMER(SysMemoryDebugging)
- #ifdef USE_FILLER_VALUE
- {
- USE_PERF_TIMER(SysMemoryInitFilling)
- ::memset32(p, s_initFillerValue, ::GlobalSize(p));
- }
- #endif
- theTotalSystemAllocationInBytes += ::GlobalSize(p);
- if (thePeakSystemAllocationInBytes < theTotalSystemAllocationInBytes)
- thePeakSystemAllocationInBytes = theTotalSystemAllocationInBytes;
- }
-#endif
-
- return p;
-}
-
-//-----------------------------------------------------------------------------
-/**
- the counterpart to sysAllocate / sysAllocateDoNotZero; used to free blocks
- allocated by them. it is OK to pass null here (it will just be ignored).
-*/
-void sysFree(void* p)
-{
- if (p)
- {
-#ifdef MEMORYPOOL_DEBUG
- {
- USE_PERF_TIMER(MemoryPoolDebugging)
- ::memset32(p, GARBAGE_FILL_VALUE, ::GlobalSize(p));
- theTotalSystemAllocationInBytes -= ::GlobalSize(p);
- }
-#endif
-
- ::GlobalFree(p);
- }
-}
-
-// ----------------------------------------------------------------------------
-/**
- fills memory with a 32-bit value (note: assumes the ptr is 4-byte-aligned)
-*/
-void memset32(void* ptr, Int value, size_t bytesToFill)
-{
- Int wordsToFill = bytesToFill>>2;
- bytesToFill -= (wordsToFill<<2);
-
- Int *p = (Int*)ptr;
- for (++wordsToFill; --wordsToFill; )
- *p++ = value;
-
- Byte *b = (Byte *)p;
- for (++bytesToFill; --bytesToFill; )
- *b++ = (Byte)value;
-}
-
-#ifdef USE_FILLER_VALUE
-
-UnsignedInt s_initFillerValue = 0xf00dcafe; // will be replaced, should never be this value at runtime
-
-void calcFillerValue(Int index)
-{
- s_initFillerValue = (index & 3) << 1;
- s_initFillerValue |= 0x01;
- s_initFillerValue |= (~(s_initFillerValue << 4)) & 0xf0;
- s_initFillerValue |= (s_initFillerValue << 8);
- s_initFillerValue |= (s_initFillerValue << 16);
- //DEBUG_LOG(("Setting MemoryPool initFillerValue to %08x (index %d)",s_initFillerValue,index));
-}
-
-#endif // USE_FILLER_VALUE
From 15eb10124487ae806746c4aaffb6631ce3530a05 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Sat, 1 Nov 2025 12:38:50 +0100
Subject: [PATCH 17/20] Update comment in Generals
---
.../Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 03c498e7920..32f44bd9bd7 100644
--- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -314,8 +314,8 @@ bool DX8Wrapper::Init(void * hwnd, bool lite)
*/
WWDEBUG_SAY(("Create Direct3D8"));
{
- // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll
- // to prevent the graphics driver from potentially loading the old game dbghelp.dll.
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
+ // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
DbgHelpGuard dbgHelpGuard;
D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
@@ -567,8 +567,8 @@ bool DX8Wrapper::Create_Device(void)
HRESULT hr;
{
- // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll
- // to prevent the graphics driver from potentially loading the old game dbghelp.dll.
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
+ // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
DbgHelpGuard dbgHelpGuard;
hr=D3DInterface->CreateDevice
From 1ffa737da30b394c2b25dda3c04547212f5c19c7 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Sat, 1 Nov 2025 12:43:11 +0100
Subject: [PATCH 18/20] Add one more dbghelp guard in Zero Hour
---
.../Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 2d9f5c0e269..ba2942972bd 100644
--- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -627,6 +627,11 @@ bool DX8Wrapper::Create_Device(void)
_PresentParameters.AutoDepthStencilFormat==D3DFMT_D24X8))
{
_PresentParameters.AutoDepthStencilFormat=D3DFMT_D16;
+
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
+ // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
+ DbgHelpGuard dbgHelpGuard;
+
hr = D3DInterface->CreateDevice
(
CurRenderDevice,
From 4d7fb465addd54a5ac11027c88f99255caea1e12 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Sat, 1 Nov 2025 12:46:17 +0100
Subject: [PATCH 19/20] Simplify new code
---
.../Source/WWVegas/WW3D2/dx8wrapper.cpp | 27 +++++++---------
.../Source/WWVegas/WW3D2/dx8wrapper.cpp | 32 +++++++------------
2 files changed, 24 insertions(+), 35 deletions(-)
diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 32f44bd9bd7..760ac9a6976 100644
--- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -565,22 +565,19 @@ bool DX8Wrapper::Create_Device(void)
Vertex_Processing_Behavior|=D3DCREATE_FPU_PRESERVE;
#endif
- HRESULT hr;
- {
- // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
- // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
- DbgHelpGuard dbgHelpGuard;
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
+ // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
+ DbgHelpGuard dbgHelpGuard;
- hr=D3DInterface->CreateDevice
- (
- CurRenderDevice,
- WW3D_DEVTYPE,
- _Hwnd,
- Vertex_Processing_Behavior,
- &_PresentParameters,
- &D3DDevice
- );
- }
+ HRESULT hr=D3DInterface->CreateDevice
+ (
+ CurRenderDevice,
+ WW3D_DEVTYPE,
+ _Hwnd,
+ Vertex_Processing_Behavior,
+ &_PresentParameters,
+ &D3DDevice
+ );
if (FAILED(hr))
{
diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index ba2942972bd..e5077aaafa8 100644
--- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -597,22 +597,19 @@ bool DX8Wrapper::Create_Device(void)
Vertex_Processing_Behavior|=D3DCREATE_FPU_PRESERVE;
#endif
- HRESULT hr;
- {
- // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
- // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
- DbgHelpGuard dbgHelpGuard;
+ // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
+ // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
+ DbgHelpGuard dbgHelpGuard;
- hr=D3DInterface->CreateDevice
- (
- CurRenderDevice,
- WW3D_DEVTYPE,
- _Hwnd,
- Vertex_Processing_Behavior,
- &_PresentParameters,
- &D3DDevice
- );
- }
+ HRESULT hr=D3DInterface->CreateDevice
+ (
+ CurRenderDevice,
+ WW3D_DEVTYPE,
+ _Hwnd,
+ Vertex_Processing_Behavior,
+ &_PresentParameters,
+ &D3DDevice
+ );
if (FAILED(hr))
{
@@ -627,11 +624,6 @@ bool DX8Wrapper::Create_Device(void)
_PresentParameters.AutoDepthStencilFormat==D3DFMT_D24X8))
{
_PresentParameters.AutoDepthStencilFormat=D3DFMT_D16;
-
- // TheSuperHackers @bugfix xezon 13/06/2025 Front load the system dbghelp.dll to prevent
- // the graphics driver from potentially loading the old game dbghelp.dll and then crashing the game process.
- DbgHelpGuard dbgHelpGuard;
-
hr = D3DInterface->CreateDevice
(
CurRenderDevice,
From d12b41fe87e84f599e062516116135cce9dc7637 Mon Sep 17 00:00:00 2001
From: xezon <4720891+xezon@users.noreply.github.com>
Date: Sat, 1 Nov 2025 12:51:57 +0100
Subject: [PATCH 20/20] Unload dbghelp.dll sooner after call to CreateDevice
---
Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 2 ++
GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 2 ++
2 files changed, 4 insertions(+)
diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index 760ac9a6976..e413eec2b1a 100644
--- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -584,6 +584,8 @@ bool DX8Wrapper::Create_Device(void)
return false;
}
+ dbgHelpGuard.deactivate();
+
/*
** Initialize all subsystems
*/
diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
index e5077aaafa8..d631b5f39b7 100644
--- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
+++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
@@ -645,6 +645,8 @@ bool DX8Wrapper::Create_Device(void)
}
}
+ dbgHelpGuard.deactivate();
+
/*
** Initialize all subsystems
*/