[gtk/gtk-3-24: 3/6] gdkkeys-win32: Fix crash when keyboard DLL failed to load




commit 8b1c334c4ae67363f2d5acd583b757c50d681097
Author: Philip Zander <philip zander gmail com>
Date:   Sun Jan 9 11:05:28 2022 +0100

    gdkkeys-win32: Fix crash when keyboard DLL failed to load
    
    DLL loading failures should not happen under normal circumstances, but
    we should at least try not to crash and and print better diagnostic
    messages if they do happen.
    
    See #4610

 gdk/win32/gdkkeys-win32-impl.c |  9 ++++---
 gdk/win32/gdkkeys-win32.c      | 58 ++++++++++++++++++++++++++++++++----------
 2 files changed, 50 insertions(+), 17 deletions(-)
---
diff --git a/gdk/win32/gdkkeys-win32-impl.c b/gdk/win32/gdkkeys-win32-impl.c
index a6124f943d..4539989c13 100644
--- a/gdk/win32/gdkkeys-win32-impl.c
+++ b/gdk/win32/gdkkeys-win32-impl.c
@@ -180,7 +180,8 @@ keystate_to_modbits (GdkWin32KeymapLayoutInfo *info,
   BYTE       result = 0;
   int        i;
 
-  g_return_val_if_fail (tables != NULL, 0);
+  if (tables == NULL)
+    return 0;
 
   vk_to_bit = tables->pCharModifiers.ptr->pVkToBit.ptr;
 
@@ -198,7 +199,8 @@ modbits_to_level (GdkWin32KeymapLayoutInfo *info,
   PKBDTABLES tables = (PKBDTABLES) info->tables;
   PMODIFIERS modifiers;
 
-  g_return_val_if_fail (tables != NULL, 0);
+  if (tables == NULL)
+    return 0;
 
   modifiers = tables->pCharModifiers.ptr;
   if (modbits > modifiers->wMaxModBits)
@@ -268,7 +270,8 @@ vk_to_char_fuzzy (GdkWin32KeymapLayoutInfo *info,
   if (is_dead)
     *is_dead = FALSE;
 
-  g_return_val_if_fail (tables != NULL, WCH_NONE);
+  if (tables == NULL)
+    return WCH_NONE;
 
   wch_tables = tables->pVkToWcharTable.ptr;
 
diff --git a/gdk/win32/gdkkeys-win32.c b/gdk/win32/gdkkeys-win32.c
index 85bcce224b..d835b44c67 100644
--- a/gdk/win32/gdkkeys-win32.c
+++ b/gdk/win32/gdkkeys-win32.c
@@ -179,6 +179,7 @@ get_keyboard_layout_file (const char *layout_name)
   DWORD  file_name_len = 0;
   int    dir_len       = 0;
   int    buf_len       = 0;
+  LSTATUS status;
 
   static const char prefix[] = "SYSTEM\\CurrentControlSet\\Control\\"
                                "Keyboard Layouts\\";
@@ -187,18 +188,32 @@ get_keyboard_layout_file (const char *layout_name)
   g_snprintf (kbdKeyPath, sizeof (prefix) + KL_NAMELENGTH, "%s%s", prefix,
               layout_name);
 
-  if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, (LPCSTR) kbdKeyPath, 0,
-                     KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS)
-    goto fail1;
+
+  status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, (LPCSTR) kbdKeyPath, 0,
+                          KEY_QUERY_VALUE, &hkey);
+  if (status != ERROR_SUCCESS)
+    {
+      g_warning("Could not open registry key '%s'. Error code: %d",
+                kbdKeyPath, (int)status);
+      goto fail1;
+    }
 
   /* Get sizes */
-  if (RegQueryValueExA (hkey, "Layout File", 0, &var_type, 0,
-                       &file_name_len) != ERROR_SUCCESS)
-    goto fail2;
+  status = RegQueryValueExA (hkey, "Layout File", 0, &var_type, 0,
+                             &file_name_len);
+  if (status != ERROR_SUCCESS)
+    {
+      g_warning("Could not query registry key '%s\\Layout File'. Error code: %d",
+                kbdKeyPath, (int)status);
+      goto fail2;
+    }
 
   dir_len = GetSystemDirectoryA (0, 0); /* includes \0 */
   if (dir_len == 0)
-    goto fail2;
+    {
+      g_warning("GetSystemDirectoryA failed. Error: %d", (int)GetLastError());
+      goto fail2;
+    }
 
   /* Allocate buffer */
   buf_len = dir_len + (int) strlen ("\\") + file_name_len;
@@ -212,10 +227,12 @@ get_keyboard_layout_file (const char *layout_name)
   result[dir_len - 1] = '\\';
 
   /* Append file name */
-  if (RegQueryValueExA (hkey, "Layout File", 0, &var_type,
-                       (LPBYTE) &result[dir_len], &file_name_len)
-      != ERROR_SUCCESS)
-    goto fail3;
+  status = RegQueryValueExA (hkey, "Layout File", 0, &var_type,
+                             (LPBYTE) &result[dir_len], &file_name_len);
+  if (status != ERROR_SUCCESS)
+    {
+      goto fail3;
+    }
 
   result[dir_len + file_name_len] = '\0';
 
@@ -413,6 +430,9 @@ gdk_keysym_to_key_entry_index (GdkWin32KeymapLayoutInfo *info,
   gunichar c;
   gintptr  index;
 
+  if (info->reverse_lookup_table == NULL)
+    return -1;
+
   /* Special cases */
   if (sym == GDK_KEY_Tab)
     return VK_TAB;
@@ -437,8 +457,6 @@ gdk_keysym_to_key_entry_index (GdkWin32KeymapLayoutInfo *info,
   /* Try converting to Unicode and back */
   c = gdk_keyval_to_unicode (sym);
 
-  g_return_val_if_fail (info->reverse_lookup_table != NULL, -1);
-
   index = -1;
   if (g_hash_table_lookup_extended (info->reverse_lookup_table,
                                     GINT_TO_POINTER (c),
@@ -555,7 +573,7 @@ update_keymap (GdkWin32Keymap *keymap)
 
           info->file = get_keyboard_layout_file (info->name);
 
-          if (load_layout_dll (keymap, info->file, info))
+          if (info->file != NULL && load_layout_dll (keymap, info->file, info))
             {
               info->key_entries = g_array_new (FALSE, FALSE,
                                                sizeof (GdkWin32KeymapKeyEntry));
@@ -564,6 +582,11 @@ update_keymap (GdkWin32Keymap *keymap)
                                                              g_direct_equal);
               init_vk_lookup_table (keymap, info);
             }
+          else
+            {
+              g_warning("Failed to load keyboard layout DLL for layout %s: %s",
+                        info->name, info->file);
+            }
         }
 
       if (info->handle == current_layout)
@@ -1015,6 +1038,13 @@ gdk_win32_keymap_translate_keyboard_state (GdkKeymap       *gdk_keymap,
   if (consumed_modifiers)
     *consumed_modifiers = mod_bits_to_gdk_mod_mask (consumed_mod_bits);
 
+  /* Just a diagnostic message to inform the user why their keypresses aren't working.
+   * Shouldn't happen under normal circumstances. */
+  if (tmp_keyval == GDK_KEY_VoidSymbol && layout_info->tables == NULL)
+    g_warning("Failed to translate keypress (keycode: %u) for group %d (%s) because "
+              "we could not load the layout.",
+              hardware_keycode, group, layout_info->name);
+
   return tmp_keyval != GDK_KEY_VoidSymbol;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]