Fixed crash if a broken EZFRD64.DLL is installed

It turns out GameInput crashes the same way as DirectInput
This commit is contained in:
Sam Lantinga
2026-09-15 16:42:32 -07:00
parent a24429c192
commit 18d32d5a50
4 changed files with 39 additions and 25 deletions

View File

@@ -40,6 +40,10 @@ static int g_nGameInputRefCount;
bool SDL_InitGameInput(IGameInput **ppGameInput)
{
if (g_nGameInputRefCount == 0) {
if (WIN_HasBrokenEZFRD64DLL()) {
return SDL_SetError("GameInput disabled to prevent application crashing");
}
// This is recommended, as Microsoft's GameInputCreate() is robust
// and better handles various GameInput installations
HRESULT hr = GameInputCreate(&g_pGameInput);

View File

@@ -773,4 +773,35 @@ char *WIN_GetModulePath(HMODULE handle)
return retval;
}
bool WIN_HasBrokenEZFRD64DLL(void)
{
static bool checked = false;
static bool has_broken_EZFRD64_DLL = false;
#ifdef _WIN64
if (!checked) {
if (SDL_GetHintBoolean("SDL_CHECK_BROKEN_EZFRD64", true)) {
// The 64-bit version of EZFRD64.DLL crashes after being loaded,
// which happens implicitly when querying the device capabilities,
// so make sure we don't do that if there's a possibility of crashing
static const char *directories[] = {
"C:/Windows/USB_Vibration",
"C:/Windows/USB Vibration"
};
for (int i = 0; i < SDL_arraysize(directories) && !has_broken_EZFRD64_DLL; ++i) {
int count = 0;
char **files = SDL_GlobDirectory(directories[i], "*/EZFRD64.DLL", SDL_GLOB_CASEINSENSITIVE, &count);
if (count > 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "Broken EZFRD64.DLL detected, disabling GameInput and DirectInput force feedback");
has_broken_EZFRD64_DLL = true;
}
SDL_free(files);
}
}
checked = true;
}
#endif
return has_broken_EZFRD64_DLL;
}
#endif // defined(SDL_PLATFORM_WINDOWS)

View File

@@ -231,6 +231,9 @@ extern const char *WIN_CheckDefaultArgcArgv(int *pargc, char ***pargv, void **pa
// Does all the win32 tapdancing to make GetModuleFileName work. Returns a SDL_malloc'd UTF-8 string, or NULL on failure.
extern char *WIN_GetModulePath(HMODULE handle);
// Return true if this system has a broken EZFRD64.DLL installed
extern bool WIN_HasBrokenEZFRD64DLL(void);
// Ends C function definitions when using C++
#ifdef __cplusplus
}

View File

@@ -46,7 +46,6 @@ extern HWND SDL_HelperWindow;
// local variables
static bool coinitialized = false;
static LPDIRECTINPUT8 dinput = NULL;
static bool has_broken_EZFRD64DLL = false;
// Taken from Wine - Thanks!
static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
@@ -440,29 +439,6 @@ bool SDL_DINPUT_JoystickInit(void)
dinput = NULL;
return SetDIerror("IDirectInput::Initialize", result);
}
#ifdef _WIN64
if (SDL_GetHintBoolean("SDL_JOYSTICK_CHECK_EZFRD64", true)) {
// The 64-bit version of EZFRD64.DLL crashes after being loaded,
// which happens implicitly when querying the device capabilities,
// so make sure we don't do that if there's a possibility of crashing
static const char *directories[] = {
"C:/Windows/USB_Vibration",
"C:/Windows/USB Vibration"
};
for (int i = 0; i < SDL_arraysize(directories) && !has_broken_EZFRD64DLL; ++i) {
int count = 0;
char **files = SDL_GlobDirectory(directories[i], "*/EZFRD64.DLL", SDL_GLOB_CASEINSENSITIVE, &count);
if (count > 0) {
has_broken_EZFRD64DLL = true;
}
SDL_free(files);
}
if (has_broken_EZFRD64DLL) {
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "Broken EZFRD64.DLL detected, disabling DirectInput force feedback");
}
}
#endif
return true;
}
@@ -808,7 +784,7 @@ bool SDL_DINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joysti
return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
}
if (!has_broken_EZFRD64DLL) {
if (!WIN_HasBrokenEZFRD64DLL()) {
// Get device capabilities to see if we are force feedback capable
result =
IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,