Przeglądaj źródła

Fixed crash if a broken EZFRD64.DLL is installed

It turns out GameInput crashes the same way as DirectInput
Sam Lantinga 3 dni temu
rodzic
commit
18d32d5a50

+ 4 - 0
src/core/windows/SDL_gameinput.cpp

@@ -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);

+ 31 - 0
src/core/windows/SDL_windows.c

@@ -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)

+ 3 - 0
src/core/windows/SDL_windows.h

@@ -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
 }

+ 1 - 25
src/joystick/windows/SDL_dinputjoystick.c

@@ -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,