spiegel-keyman/windows/src/engine/keyman32/glossary.cpp
Marc Durdin 738e1946a6 [Windows] Debug logging and proof of concept tests for keyboarding support within metro-style apps
[Windows] More tidyup and robustness for metro app support - debug cleanup and serialization of input (not quite finished)

[windows] Refactor serialized input code when used with key event thread model

[windows] Add consistent precompiled headers for other projects

[windows] Merge console window test into metro support

[Windows] Tidy up work and identify additional TODOs for metro-style app support

[Windows] Ensure error case falls through to default hook processing for console windows

[Windows] Refactor shared memory into memory mapped file so we can cross 32-64 bit boundary

[Windows] Tweaks to C++ security calls and parameters

[Windows] Start refactor of SerialKeyEvent* classes

[Windows] Rename to SerialKeyEventServer (refactoring)

[Windows] Complete refactoring of SerialKeyEventClient class

[Windows] Further encapsulation and cleanup with 'interfaces' to reduce header pollution

[Windows] Complete serialization fix with move of modifier state management from client thread to server thread to guarantee consistency

[Windows] Replace atom-based keyboard switching with memory mapped file indexed to avoid security constraints

[Windows] Fixup Left Alt+Shift interaction with serializer

[Windows] Use Windows 8.1 SDK for test
2018-10-18 20:00:49 +11:00

202 lines
6.1 KiB
C++

/*
Name: glossary
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 20 Jul 2008
Modified Date: 28 May 2014
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 20 Jul 2008 - mcdurdin - I1498 - Fix keyboard switching for Shadow keyboards on Vista+
20 Jul 2008 - mcdurdin - I1546 - Fix language switch with ids >= x80000000
20 Jul 2008 - mcdurdin - I1545 - Fix registry leak
11 Mar 2009 - mcdurdin - I1894 - Fix threading bugs introduced in I1888
11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
12 Mar 2010 - mcdurdin - I934 - x64 - Complete
12 Mar 2010 - mcdurdin - I2229 - Remove hints and warnings
04 May 2010 - mcdurdin - I2351 - Robustness - verify _td return value
23 Dec 2011 - mcdurdin - I3191 - Corruption of keyboard selection cache between x86 and x64
04 Nov 2012 - mcdurdin - I3526 - V9.0 - Merge of I3191 - Corruption of keyboard selection cache between x86 and x64
28 May 2014 - mcdurdin - I4220 - V9.0 - Remove references to LoadKeyboardLayout, Preload, Substitutes, etc. and use only TSF
*/
#include "pch.h"
// I4220
#ifndef SM_IMMENABLED
#define SM_IMMENABLED 82
#endif
#pragma warning(disable: 4996)
BOOL HKLIsIME(HKL hkl) // I1498 - fix keyboard switching for shadow keyboards on Vista+
{
BOOL r;
if( (GetVersion() & 0xFF) >= 6 ) return FALSE;
if( (GetVersion() & 0x8000000) == 0x8000000 || (GetVersion() & 0xFF) == 4 )
r = GetSystemMetrics(SM_DBCSENABLED);
else
r = GetSystemMetrics(SM_IMMENABLED);
return r && ImmIsIME(hkl);
}
#pragma warning(default: 4996)
HKL ForceKeymanIDToHKL(DWORD KeymanID) // I3191 // I3526
{
#ifdef _WIN64
return (HKL) (LONG_PTR) (INT64) (LONG) KeymanID; // Sign extension for x64
#else
return (HKL) (DWORD_PTR) KeymanID;
#endif
}
DWORD ForceHKLToKeymanID(HKL hkl) // I3191 // I3526
{
return (DWORD) (DWORD_PTR) hkl; // Just truncate for x64
}
DWORD HKLToKeyboardID(HKL hkl)
{
HKEY hkey, hsubkey;
char str[16], str2[16];
DWORD i = 0;
DWORD n;
FILETIME ft;
DWORD len;
//SendDebugMessageFormat(0, sdmGlobal, 0, "HKLToKeyboardID: hkl=%x", hkl);
// Test for IME, and if IME return LanguageID
if(HKLIsIME(hkl)) // I1498 - was ImmIsIME
{
//SendDebugMessageFormat(0, sdmGlobal, 0, "HKLToKeyboardID: return HKLIsIME is true=%x", hkl);
return ForceHKLToKeymanID(hkl); // MCD 19/03/02 // I3191 // I3526
}
//if((HIWORD(hkl) & 0xF000) == 0xE000) return (DWORD) hkl;
// Test for standard layouts: 0409041D for instance
// specialised layout is: F0020409 fr instance [find layout id:0002]
DWORD LayoutID = HKLToLayoutID(hkl);
if(LayoutID == 0)
{
//SendDebugMessageFormat(0, sdmGlobal, 0, "HKLToKeyboardID: no LayoutID, so return HIWORD(hkl)=%x", HIWORD(hkl));
return HIWORD(hkl);
}
//SendDebugMessageFormat(0, sdmGlobal, 0, "HKLToKeyboardID: LayoutID=%x", LayoutID);
// Find the KeyboardID associated with the LayoutID
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSZ_SystemKeyboardLayouts, NULL, KEY_READ, &hkey) != ERROR_SUCCESS)
{
//SendDebugMessageFormat(0, sdmGlobal, 0, "HKLToKeyboardID: fails, return LOWORD(hkl)=%x", LOWORD(hkl));
return (DWORD) LOWORD(hkl);
}
for(len=16, n = i = 0; RegEnumKeyEx(hkey, i, str, &len, 0, NULL, NULL, &ft) == ERROR_SUCCESS;
len = 16, i++, n=0)
{
RegOpenKeyEx(hkey, str, NULL, KEY_READ, &hsubkey);
len = 16;
if(RegQueryValueEx(hsubkey, REGSZ_LayoutID, NULL, NULL, (LPBYTE) str2, &len) == ERROR_SUCCESS)
{
n = strtoul(str2, NULL, 16); // I1546
if(n == LayoutID)
{
RegCloseKey(hsubkey); // I1545
RegCloseKey(hkey);
n = strtoul(str, NULL, 16); // I1546
SendDebugMessageFormat(0, sdmGlobal, 0, "HKLToKeyboardID: return keyboard from LayoutID = %x [%s]", n, str);
return n;
}
}
RegCloseKey(hsubkey);
}
RegCloseKey(hkey);
//SendDebugMessageFormat(0, sdmGlobal, 0, "HKLToKeyboardID: fails[2], return LOWORD(hkl)=%x", LOWORD(hkl));
return (DWORD) LOWORD(hkl); // should never happen
}
WORD HKLToLanguageID(HKL hkl)
{
return LOWORD(hkl);
}
WORD HKLToLayoutNumber(HKL hkl)
{
WORD LayoutID = HKLToLayoutID(hkl);
HKEY hkey, hsubkey;
DWORD len, n, i;
FILETIME ft;
char str[16], str2[16];
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSZ_SystemKeyboardLayouts, NULL, KEY_READ, &hkey) != ERROR_SUCCESS)
return 0;
for(len=16, n = i = 0; RegEnumKeyEx(hkey, i, str, &len, 0, NULL, NULL, &ft) == ERROR_SUCCESS; len = 16, i++, n=0)
{
RegOpenKeyEx(hkey, str, NULL, KEY_READ, &hsubkey);
len = 16;
if(RegQueryValueEx(hsubkey, REGSZ_LayoutID, NULL, NULL, (LPBYTE) str2, &len) == ERROR_SUCCESS)
{
if(strtoul(str2, NULL, 16) == LayoutID) break; // strtoul - I1546
}
RegCloseKey(hsubkey);
}
RegCloseKey(hkey);
n = strtoul(str, NULL, 16); // strtoul - I1546
return HIWORD(n);
}
WORD HKLToLayoutID(HKL hkl)
{
if((HIWORD(hkl) & 0xF000) != 0xF000) return 0;
return HIWORD(hkl) & 0x0FFF;
}
DWORD EthnologueCodeToKeymanID(DWORD EthCode)
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return KEYMANID_NONKEYMAN;
for(int i = 0; i < _td->nKeyboards; i++)
{
if(!_td->lpKeyboards[i].Keyboard && !LoadlpKeyboard(i))
{
SendDebugMessageFormat(0,sdmGlobal,0,
"EthnologueCodeToKeymanID: Unable to load keyboard %s", _td->lpKeyboards[i].Name);
return KEYMANID_NONKEYMAN;
}
PWSTR ps = GetSystemStore(_td->lpKeyboards[i].Keyboard, TSS_ETHNOLOGUECODE);
if(ps)
{
SendDebugMessageFormat(0,sdmGlobal,0,"EthnologueCodeToKeymanID: %s %ws %x", _td->lpKeyboards[i].Name, ps, EthnologueStringCodeToDWord(ps));
if(EthnologueStringCodeToDWord(ps) == EthCode) return _td->lpKeyboards[i].KeymanID;
}
}
return KEYMANID_NONKEYMAN;
}
DWORD EthnologueStringCodeToDWord(PWSTR EthCode)
{
if(wcslen(EthCode) < 3 || wcslen(EthCode) > 4) return (DWORD)-1;
return (LOBYTE(EthCode[0])) |
(LOBYTE(EthCode[1]) << 8) |
(LOBYTE(EthCode[2]) << 16) |
(LOBYTE(EthCode[3]) << 24);
}