fix(windows): add check a fix for registry datatypes

Fixes: #14342
The Windows system level keyboard hotkeys controlled in
registry have sometimes been incorrectly written as
a DWORD datatype. There 106 events in sentry for just
July. When opening the Windows setting dialog and the registry
has DWORDS it will show unassinged in the dialog if apply
is pressed it will convert the keys to REG_SZ.
This fix follows a similar pattern it will check the data
type of the registry key if it is DWORD it will remove it
and add a new key of the same name as REG_SZ and set it to
the unassigned value.

Fixes: KEYMAN-WINDOWS-4NK
This commit is contained in:
rc-swag 2025-07-15 16:27:14 +10:00 • committed by Marc Durdin
parent d7e160cc36
commit 5bf1f635a6

View file

@ -1,4 +1,4 @@
(*
(*
Name: LangSwitchManager
Copyright: Copyright (C) SIL International.
Documentation:
@ -47,6 +47,7 @@ unit LangSwitchManager;
interface
uses
ErrorControlledRegistry,
System.Classes,
System.Contnrs,
System.SysUtils,
@ -230,6 +231,7 @@ type
FLanguageToggle: string;
FLayoutToggle: string;
procedure LoadCurrentHotkey;
function FixRegistryDataType(RegistryKey: TRegistryErrorControlled; const ValueName: string): Boolean;
procedure DisableWindowsHotkey;
procedure RestoreWindowsHotkey;
public
@ -251,7 +253,6 @@ uses
InterfaceHotkeys,
kmint,
LoadIndirectStringUnit,
ErrorControlledRegistry,
Registry,
RegistryKeys,
UfrmKeyman7Main,
@ -981,38 +982,73 @@ begin
FCurrentHotkey := FindHotkey(kmcom.Hotkeys);
end;
function TLangSwitchConfiguration.FixRegistryDataType(
RegistryKey: TRegistryErrorControlled;
const ValueName: string
): Boolean;
var
RegType: TRegDataType;
const CHotkeyNotAssigned = '3';
begin
Result := False;
if RegistryKey.ValueExists(ValueName) then
begin
RegType := RegistryKey.GetDataType(ValueName);
if not ((RegType = rdString) or (RegType = rdExpandString)) then
begin
RegistryKey.DeleteValue(ValueName);
RegistryKey.WriteString(ValueName, CHotkeyNotAssigned);
Result := True;
end;
end;
end;
procedure TLangSwitchConfiguration.DisableWindowsHotkey;
var
MatchValue: string;
FReset: Boolean;
KeyboardToggleReg: TRegistryErrorControlled;
FReset, FFixed: Boolean;
const CHotkeyNotAssigned = '3';
begin
if FCurrentHotkey = (HK_ALT or HK_SHIFT) then MatchValue := '1'
else if FCurrentHotkey = (HK_CTRL or HK_SHIFT) then MatchValue := '2'
else Exit;
FLanguageToggle := '3';
FLayoutToggle := '3';
FLanguageToggle := CHotkeyNotAssigned;
FLayoutToggle := CHotkeyNotAssigned;
//FFixed := False;
FReset := False;
with TRegistryErrorControlled.Create do // I2890
KeyboardToggleReg := TRegistryErrorControlled.Create; // I2890
try
if not OpenKey(SRegKey_KeyboardLayoutToggle, True) then // I2890
RaiseLastRegistryError;
if not KeyboardToggleReg.OpenKey(SRegKey_KeyboardLayoutToggle, True) then // I2890
KeyboardToggleReg.RaiseLastRegistryError;
// Fix potential corrupted registry keys
if FixRegistryDataType(KeyboardToggleReg, SRegValue_Toggle_Hotkey) then
FReset := True;
if FixRegistryDataType(KeyboardToggleReg, SRegValue_Toggle_LanguageHotkey) then
FReset := True;
if FixRegistryDataType(KeyboardToggleReg, SRegValue_Toggle_LayoutHotkey) then
FReset := True;
if ValueExists(SRegValue_Toggle_Hotkey) then FLanguageToggle := ReadString(SRegValue_Toggle_Hotkey);
if KeyboardToggleReg.ValueExists(SRegValue_Toggle_Hotkey) then
FLanguageToggle := KeyboardToggleReg.ReadString(SRegValue_Toggle_Hotkey);
if FLanguageToggle = MatchValue then
begin
WriteString(SRegValue_Toggle_Hotkey, '3');
WriteString(SRegValue_Toggle_LanguageHotkey, '3');
KeyboardToggleReg.WriteString(SRegValue_Toggle_Hotkey, CHotkeyNotAssigned);
KeyboardToggleReg.WriteString(SRegValue_Toggle_LanguageHotkey, CHotkeyNotAssigned);
FReset := True;
end;
if ValueExists(SRegValue_Toggle_LayoutHotkey) then FLayoutToggle := ReadString(SRegValue_Toggle_LayoutHotkey);
if KeyboardToggleReg.ValueExists(SRegValue_Toggle_LayoutHotkey) then
FLayoutToggle := KeyboardToggleReg.ReadString(SRegValue_Toggle_LayoutHotkey);
if FLayoutToggle = MatchValue then
begin
WriteString(SRegValue_Toggle_LayoutHotkey, '3');
KeyboardToggleReg.WriteString(SRegValue_Toggle_LayoutHotkey, CHotkeyNotAssigned);
FReset := True;
end;
finally
@ -1024,31 +1060,42 @@ end;
procedure TLangSwitchConfiguration.RestoreWindowsHotkey;
var
FReset: Boolean;
FReset, Changed: Boolean;
KeyboardToggleReg: TRegistryErrorControlled;
begin
FReset := False;
if FLanguageToggle = '' then Exit;
with TRegistryErrorControlled.Create do // I2890
KeyboardToggleReg := TRegistryErrorControlled.Create; // I2890
try
if not OpenKey(SRegKey_KeyboardLayoutToggle, True) then // I2890
RaiseLastRegistryError;
if not KeyboardToggleReg.OpenKey(SRegKey_KeyboardLayoutToggle, True) then // I2890
KeyboardToggleReg.RaiseLastRegistryError;
if not ValueExists(SRegValue_Toggle_Hotkey) or (ReadString(SRegValue_Toggle_Hotkey) <> FLanguageToggle) then
// Fix potential corrupted registry keys
if FixRegistryDataType(KeyboardToggleReg, SRegValue_Toggle_Hotkey) then
FReset := True;
if FixRegistryDataType(KeyboardToggleReg, SRegValue_Toggle_LanguageHotkey) then
FReset := True;
if FixRegistryDataType(KeyboardToggleReg, SRegValue_Toggle_LayoutHotkey) then
FReset := True;
if not KeyboardToggleReg.ValueExists(SRegValue_Toggle_Hotkey) or
(KeyboardToggleReg.ReadString(SRegValue_Toggle_Hotkey) <> FLanguageToggle) then
begin
WriteString(SRegValue_Toggle_Hotkey, FLanguageToggle);
WriteString(SRegValue_Toggle_LanguageHotkey, FLanguageToggle);
KeyboardToggleReg.WriteString(SRegValue_Toggle_Hotkey, FLanguageToggle);
KeyboardToggleReg.WriteString(SRegValue_Toggle_LanguageHotkey, FLanguageToggle);
FReset := True;
end;
if not ValueExists(SRegValue_Toggle_LayoutHotkey) or (ReadString(SRegValue_Toggle_LayoutHotkey) <> FLayoutToggle) then
if not KeyboardToggleReg.ValueExists(SRegValue_Toggle_LayoutHotkey) or
(KeyboardToggleReg.ReadString(SRegValue_Toggle_LayoutHotkey) <> FLayoutToggle) then
begin
WriteString(SRegValue_Toggle_LayoutHotkey, FLayoutToggle);
KeyboardToggleReg.WriteString(SRegValue_Toggle_LayoutHotkey, FLayoutToggle);
FReset := True;
end;
finally
Free;
KeyboardToggleReg.Free;
end;
if FReset then