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 https://gitlab.gnome.org/GNOME/gtk/-/issues/4610
This commit is contained in:
Philip Zander 2022-01-12 21:31:21 +01:00 committed by Luca Bacci
parent 82f8f878bc
commit 438fad803e
No known key found for this signature in database
GPG Key ID: 8E3C8D989C98883D
2 changed files with 50 additions and 17 deletions

View File

@ -180,7 +180,8 @@ keystate_to_modbits (GdkWin32KeymapLayoutInfo *info,
BYTE result = 0; BYTE result = 0;
int i; int i;
g_return_val_if_fail (tables != NULL, 0); if (tables == NULL)
return 0;
vk_to_bit = tables->pCharModifiers.ptr->pVkToBit.ptr; vk_to_bit = tables->pCharModifiers.ptr->pVkToBit.ptr;
@ -198,7 +199,8 @@ modbits_to_level (GdkWin32KeymapLayoutInfo *info,
PKBDTABLES tables = (PKBDTABLES) info->tables; PKBDTABLES tables = (PKBDTABLES) info->tables;
PMODIFIERS modifiers; PMODIFIERS modifiers;
g_return_val_if_fail (tables != NULL, 0); if (tables == NULL)
return 0;
modifiers = tables->pCharModifiers.ptr; modifiers = tables->pCharModifiers.ptr;
if (modbits > modifiers->wMaxModBits) if (modbits > modifiers->wMaxModBits)
@ -268,7 +270,8 @@ vk_to_char_fuzzy (GdkWin32KeymapLayoutInfo *info,
if (is_dead) if (is_dead)
*is_dead = FALSE; *is_dead = FALSE;
g_return_val_if_fail (tables != NULL, WCH_NONE); if (tables == NULL)
return WCH_NONE;
wch_tables = tables->pVkToWcharTable.ptr; wch_tables = tables->pVkToWcharTable.ptr;

View File

@ -181,6 +181,7 @@ get_keyboard_layout_file (const char *layout_name)
DWORD file_name_len = 0; DWORD file_name_len = 0;
int dir_len = 0; int dir_len = 0;
int buf_len = 0; int buf_len = 0;
LSTATUS status;
static const char prefix[] = "SYSTEM\\CurrentControlSet\\Control\\" static const char prefix[] = "SYSTEM\\CurrentControlSet\\Control\\"
"Keyboard Layouts\\"; "Keyboard Layouts\\";
@ -189,18 +190,32 @@ get_keyboard_layout_file (const char *layout_name)
g_snprintf (kbdKeyPath, sizeof (prefix) + KL_NAMELENGTH, "%s%s", prefix, g_snprintf (kbdKeyPath, sizeof (prefix) + KL_NAMELENGTH, "%s%s", prefix,
layout_name); layout_name);
if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, (LPCSTR) kbdKeyPath, 0,
KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, (LPCSTR) kbdKeyPath, 0,
goto fail1; 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 */ /* Get sizes */
if (RegQueryValueExA (hkey, "Layout File", 0, &var_type, 0, status = RegQueryValueExA (hkey, "Layout File", 0, &var_type, 0,
&file_name_len) != ERROR_SUCCESS) &file_name_len);
goto fail2; 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 */ dir_len = GetSystemDirectoryA (0, 0); /* includes \0 */
if (dir_len == 0) if (dir_len == 0)
goto fail2; {
g_warning("GetSystemDirectoryA failed. Error: %d", (int)GetLastError());
goto fail2;
}
/* Allocate buffer */ /* Allocate buffer */
buf_len = dir_len + (int) strlen ("\\") + file_name_len; buf_len = dir_len + (int) strlen ("\\") + file_name_len;
@ -214,10 +229,12 @@ get_keyboard_layout_file (const char *layout_name)
result[dir_len - 1] = '\\'; result[dir_len - 1] = '\\';
/* Append file name */ /* Append file name */
if (RegQueryValueExA (hkey, "Layout File", 0, &var_type, status = RegQueryValueExA (hkey, "Layout File", 0, &var_type,
(LPBYTE) &result[dir_len], &file_name_len) (LPBYTE) &result[dir_len], &file_name_len);
!= ERROR_SUCCESS) if (status != ERROR_SUCCESS)
goto fail3; {
goto fail3;
}
result[dir_len + file_name_len] = '\0'; result[dir_len + file_name_len] = '\0';
@ -415,6 +432,9 @@ gdk_keysym_to_key_entry_index (GdkWin32KeymapLayoutInfo *info,
gunichar c; gunichar c;
gintptr index; gintptr index;
if (info->reverse_lookup_table == NULL)
return -1;
/* Special cases */ /* Special cases */
if (sym == GDK_KEY_Tab) if (sym == GDK_KEY_Tab)
return VK_TAB; return VK_TAB;
@ -439,8 +459,6 @@ gdk_keysym_to_key_entry_index (GdkWin32KeymapLayoutInfo *info,
/* Try converting to Unicode and back */ /* Try converting to Unicode and back */
c = gdk_keyval_to_unicode (sym); c = gdk_keyval_to_unicode (sym);
g_return_val_if_fail (info->reverse_lookup_table != NULL, -1);
index = -1; index = -1;
if (g_hash_table_lookup_extended (info->reverse_lookup_table, if (g_hash_table_lookup_extended (info->reverse_lookup_table,
GINT_TO_POINTER (c), GINT_TO_POINTER (c),
@ -537,7 +555,7 @@ update_keymap (GdkWin32Keymap *keymap)
info->file = get_keyboard_layout_file (info->name); 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, info->key_entries = g_array_new (FALSE, FALSE,
sizeof (GdkWin32KeymapKeyEntry)); sizeof (GdkWin32KeymapKeyEntry));
@ -546,6 +564,11 @@ update_keymap (GdkWin32Keymap *keymap)
g_direct_equal); g_direct_equal);
init_vk_lookup_table (keymap, info); 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) if (info->handle == current_layout)
@ -978,6 +1001,13 @@ gdk_win32_keymap_translate_keyboard_state (GdkKeymap *gdk_keymap,
if (consumed_modifiers) if (consumed_modifiers)
*consumed_modifiers = mod_bits_to_gdk_mod_mask (consumed_mod_bits); *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; return tmp_keyval != GDK_KEY_VoidSymbol;
} }