Skip to content

[GEN][ZH] Prevent AMD/ATI driver crash on game launch by temporarily unloading and renaming dbghelp.dll #1066

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

xezon
Copy link

@xezon xezon commented Jun 14, 2025

This change prevents the AMD/ATI driver crash on game launch by temporarily loading and unloading the Windows system dbghelp.dll, before the driver would try to load and use the dbghelp.dll from the game install directory - if the user did not delete this file.

The crash workaround is quite a bit more complicated and intricate and adds a few new classes. On a positive note, it does get rid of the legacy dbghelp.lib link dependency.

dbghelp.dll is now loaded dynamically in WWLib code. This allows to unload it. And skip loading it if it is not even used. By default it will now also first try to load dbghelp.dll from Windows system32 directory which does not cause this crash. It appears that the AMD/ATI drivers are only incompatible with this old dbghelp.dll, likely because of insufficient error handling.

The DbgHelpLoader has a specific requirement, where it is not allowed to use new/delete, because of the timing it can be activated with MEMORYPOOL_DEBUG_STACKTRACE during game memory initialization. That is why the stl::malloc_allocator was added.

The ScopedFileRenamer was added to help safely rename and revert the dbghelp.dll on game launch.

The DbgHelpGuard was added to front load the dbghelp DLL in RAII fashion at the 2 necessary places.

  • Tested in VC6
  • Tested in VS2022
  • Tested with MEMORYPOOL_DEBUG_STACKTRACE
  • Tested without MEMORYPOOL_DEBUG_STACKTRACE
  • Improve implementation with Hooks
  • Improve implementation with front loading dll instead of file renaming

@xezon xezon added this to the Stability fixes milestone Jun 14, 2025
@xezon xezon requested a review from a team June 14, 2025 21:31
@xezon xezon added Blocker Severity: Minor < Major < Critical < Blocker Bug Something is not working right, typically is user facing Gen Relates to Generals ZH Relates to Zero Hour Tools Affects Tools only Crash This is a crash labels Jun 14, 2025
@helmutbuhler
Copy link

Will this still work when the game doesn't have the rights to move the dll?

I didn't look into the details of this PR, but overall this looks like overkill. Given that the retail game still works when the dll is deleted, wouldn't it make more sense to simply show an errormessage when the dll is detected and instruct the user to delete it? Maybe even just rename it automatically when the game has the rights or ask for permission from the user to do that.
I don't think we need the functionality in that dll anyway. There are better ways for callstacks during crashes. We might as well delete all the code that uses it instead of adding hacks to support something we don't need.

@xezon
Copy link
Author

xezon commented Jun 15, 2025

When the game cannot rename this file, then it will not work. The game would need to be launched with Admin privileges if the location requires that permission. In "Program Files" it typically does.

If we want this to work for unelevated executables, then we would need to hook ntdll's LoadLibrary and then prevent loading that way. We can add hooking for Windows with https://github.com/TsudaKageyu/minhook. Then we would not need to rename the file.

@xezon
Copy link
Author

xezon commented Jun 15, 2025

I will try rework the deactivation of dbghelp.dll so it does not require touching the physical file.

@xezon
Copy link
Author

xezon commented Jun 15, 2025

Given that the retail game still works when the dll is deleted, wouldn't it make more sense to simply show an errormessage when the dll is detected and instruct the user to delete it?

A prompt is not possible in fullscreen. It is also not necessary for NVIDIA GPU's which are used by the majority of users.

Maybe even just rename it automatically when the game has the rights or ask for permission from the user to do that.

That would mean dbghelp.dll would not work on systems that do not have dbghelp.dll in system32.

I don't think we need the functionality in that dll anyway. There are better ways for callstacks during crashes. We might as well delete all the code that uses it instead of adding hacks to support something we don't need.

Maybe. It is currently used for some debugs though.

@ViTeXFTW
Copy link

ViTeXFTW commented Jun 16, 2025

How was this tested? Do you have an AMD system?

@xezon
Copy link
Author

xezon commented Jun 16, 2025

Yes. AMD RX 590.

@helmutbuhler
Copy link

So, if we were to remove the dependency on dbghelp.dll, but the dll would still be there, would the AMD driver still crash?

@helmutbuhler
Copy link

If we want this to work for unelevated executables, then we would need to hook ntdll's LoadLibrary and then prevent loading that way. We can add hooking for Windows with https://github.com/TsudaKageyu/minhook. Then we would not need to rename the file.

Please don't add hooks...

@xezon
Copy link
Author

xezon commented Jun 16, 2025

So, if we were to remove the dependency on dbghelp.dll, but the dll would still be there, would the AMD driver still crash?

Yes. Because the driver will then load that file and try to use it.

Please don't add hooks...

Hooks are harmless if implemented correctly. GenTool works like that for 15 years :)

We either hook, or rename file on runtime. Hooking will have the advantage of requiring no permission to write files in the game install directory.

@helmutbuhler
Copy link

Hooks are harmless if implemented correctly. GenTool works like that for 15 years :)

They are still a hack. And MS explicitely recommends against using them.

So does the driver crash during DX initialization? How about we call SetDllDirectory(L"C:\\Windows\\System32") before that?

@xezon
Copy link
Author

xezon commented Jun 16, 2025

Good suggestion. I will try that.

@xezon
Copy link
Author

xezon commented Jun 18, 2025

I tested a bit yesterday with SetDllDirectory and it did not help the cause.

But there is another thing we can do that likely will work: We can front load the system dbghelp before calling into the driver. That way the driver will use the system's dbghelp instead of attempting to load it from the game directory.

@xezon xezon force-pushed the xezon/fix-dbghelp-boot-crash branch from d8b5c04 to c235db4 Compare June 18, 2025 16:36
@xezon
Copy link
Author

xezon commented Jun 18, 2025

Ok. The logic has been simplified by front loading the system dbghelp.dll before the driver attempts to load it from the game directory. This works and gets rid of the file renaming code. The process needs no elevated permissions to avoid crashing. This only works if there actually is a dbghelp.dll in Windows, which we assume to be true in modern versions of Windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Blocker Severity: Minor < Major < Critical < Blocker Bug Something is not working right, typically is user facing Crash This is a crash Gen Relates to Generals Tools Affects Tools only ZH Relates to Zero Hour
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Game crashes on launch with latest AMD Drivers + dbghelp.dll
3 participants