Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125/* * ReactOS kernel * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * PROJECT: ReactOS user32.dll * FILE: win32ss/user/user32/windows/input.c * PURPOSE: Input * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * UPDATE HISTORY: * 09-05-2001 CSH Created */
#include <user32.h>
#include <strsafe.h>
WINE_DEFAULT_DEBUG_CHANNEL(user32);
typedef struct tagIMEHOTKEYENTRY{ DWORD dwHotKeyId; UINT uVirtualKey; UINT uModifiers; HKL hKL;} IMEHOTKEYENTRY, *PIMEHOTKEYENTRY;
// JapaneseIMEHOTKEYENTRY DefaultHotKeyTableJ[] ={ { IME_JHOTKEY_CLOSE_OPEN, VK_KANJI, MOD_IGNORE_ALL_MODIFIER, NULL },};
// Chinese TraditionalIMEHOTKEYENTRY DefaultHotKeyTableT[] ={ { IME_THOTKEY_IME_NONIME_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_CONTROL, NULL }, { IME_THOTKEY_SHAPE_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_SHIFT, NULL },};
// Chinese SimplifiedIMEHOTKEYENTRY DefaultHotKeyTableC[] ={ { IME_CHOTKEY_IME_NONIME_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_CONTROL, NULL }, { IME_CHOTKEY_SHAPE_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_SHIFT, NULL },};
// The far-east flags#define FE_JAPANESE (1 << 0)#define FE_CHINESE_TRADITIONAL (1 << 1)#define FE_CHINESE_SIMPLIFIED (1 << 2)#define FE_KOREAN (1 << 3)
// Sets the far-east flagsVOID FASTCALL IntSetFeKeyboardFlags(LANGID LangID, PBYTE pbFlags){ switch (LangID) { case MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT): *pbFlags |= FE_JAPANESE; break;
case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL): case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG): *pbFlags |= FE_CHINESE_TRADITIONAL; break;
case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED): case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE): *pbFlags |= FE_CHINESE_SIMPLIFIED; break;
case MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN): *pbFlags |= FE_KOREAN; break;
default: break; }}
DWORD FASTCALL CliReadRegistryValue(HANDLE hKey, LPCWSTR pszName){ DWORD dwValue, cbValue; LONG error;
cbValue = sizeof(dwValue); error = RegQueryValueExW(hKey, pszName, NULL, NULL, (LPBYTE)&dwValue, &cbValue); if (error != ERROR_SUCCESS || cbValue < sizeof(DWORD)) return 0;
return dwValue;}
BOOL APIENTRYCliImmSetHotKeyWorker(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DWORD dwAction){ if (dwAction == SETIMEHOTKEY_ADD) { if (IME_HOTKEY_DSWITCH_FIRST <= dwHotKeyId && dwHotKeyId <= IME_HOTKEY_DSWITCH_LAST) { if (!hKL) goto Failure; } else { if (hKL) goto Failure;
if (IME_KHOTKEY_SHAPE_TOGGLE <= dwHotKeyId && dwHotKeyId < IME_THOTKEY_IME_NONIME_TOGGLE) { // The Korean cannot set the IME hotkeys goto Failure; } }
#define MOD_ALL_MODS (MOD_ALT | MOD_CONTROL | MOD_SHIFT | MOD_WIN) if ((uModifiers & MOD_ALL_MODS) && !(uModifiers & (MOD_LEFT | MOD_RIGHT))) goto Failure;#undef MOD_ALL_MODS }
return NtUserSetImeHotKey(dwHotKeyId, uModifiers, uVirtualKey, hKL, dwAction);
Failure: SetLastError(ERROR_INVALID_PARAMETER); return FALSE;}
VOID IntLoadPreloadKeyboardLayouts(VOID){ UINT nNumber, uFlags; DWORD cbValue, dwType; WCHAR szNumber[32], szValue[KL_NAMELENGTH]; HKEY hPreloadKey; BOOL bOK = FALSE; HKL hKL, hDefaultKL = NULL;
if (RegOpenKeyW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", &hPreloadKey) != ERROR_SUCCESS) { return; }
for (nNumber = 1; nNumber <= 1000; ++nNumber) { _ultow(nNumber, szNumber, 10);
cbValue = sizeof(szValue); if (RegQueryValueExW(hPreloadKey, szNumber, NULL, &dwType, (LPBYTE)szValue, &cbValue) != ERROR_SUCCESS) { break; }
if (dwType != REG_SZ) continue;
if (nNumber == 1) /* The first entry is for default keyboard layout */ uFlags = KLF_SUBSTITUTE_OK | KLF_ACTIVATE | KLF_RESET; else uFlags = KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL | KLF_REPLACELANG;
hKL = LoadKeyboardLayoutW(szValue, uFlags); if (hKL) { bOK = TRUE; if (nNumber == 1) /* The first entry */ hDefaultKL = hKL; } }
RegCloseKey(hPreloadKey);
if (hDefaultKL) SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG, 0, &hDefaultKL, 0);
if (!bOK) { /* Fallback to English (US) */ LoadKeyboardLayoutW(L"00000409", KLF_SUBSTITUTE_OK | KLF_ACTIVATE | KLF_RESET); }}
BOOL APIENTRYCliSaveImeHotKey(DWORD dwID, UINT uModifiers, UINT uVirtualKey, HKL hKL, BOOL bDelete){ WCHAR szName[MAX_PATH]; LONG error; HKEY hKey; BOOL ret = FALSE, bRevertOnFailure = FALSE;
StringCchPrintfW(szName, _countof(szName), L"Control Panel\\Input Method\\Hot Keys\\%08lX", dwID);
if (bDelete) { error = RegDeleteKeyW(HKEY_CURRENT_USER, szName); return (error == ERROR_SUCCESS); }
error = RegCreateKeyExW(HKEY_CURRENT_USER, szName, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); if (error == ERROR_SUCCESS) { bRevertOnFailure = TRUE;
// Set "Virtual Key" error = RegSetValueExW(hKey, L"Virtual Key", 0, REG_BINARY, (LPBYTE)&uVirtualKey, sizeof(uVirtualKey)); if (error == ERROR_SUCCESS) { // Set "Key Modifiers" error = RegSetValueExW(hKey, L"Key Modifiers", 0, REG_BINARY, (LPBYTE)&uModifiers, sizeof(uModifiers)); if (error == ERROR_SUCCESS) { // Set "Target IME" error = RegSetValueExW(hKey, L"Target IME", 0, REG_BINARY, (LPBYTE)&hKL, sizeof(hKL)); if (error == ERROR_SUCCESS) { // Success! ret = TRUE; bRevertOnFailure = FALSE; } } } RegCloseKey(hKey); }
if (bRevertOnFailure) CliSaveImeHotKey(dwID, uVirtualKey, uModifiers, hKL, TRUE);
return ret;}
/** * @implemented * @note Same as imm32!ImmSetHotKey. */BOOL WINAPICliImmSetHotKey( _In_ DWORD dwID, _In_ UINT uModifiers, _In_ UINT uVirtualKey, _In_opt_ _When_((dwAction == SETIMEHOTKEY_ADD) && !(IME_HOTKEY_DSWITCH_FIRST <= dwHotKeyId && dwHotKeyId <= IME_HOTKEY_DSWITCH_LAST), _Null_) HKL hKL){ BOOL ret;
if (uVirtualKey == 0) // Delete? { ret = CliSaveImeHotKey(dwID, uModifiers, uVirtualKey, hKL, TRUE); if (ret) CliImmSetHotKeyWorker(dwID, uModifiers, uVirtualKey, hKL, SETIMEHOTKEY_DELETE); return ret; }
// Add ret = CliImmSetHotKeyWorker(dwID, uModifiers, uVirtualKey, hKL, SETIMEHOTKEY_ADD); if (ret) { ret = CliSaveImeHotKey(dwID, uModifiers, uVirtualKey, hKL, FALSE); if (!ret) // Failure? CliImmSetHotKeyWorker(dwID, uModifiers, uVirtualKey, hKL, SETIMEHOTKEY_DELETE); }
return ret;}
BOOL FASTCALL CliSetSingleHotKey(LPCWSTR pszSubKey, HANDLE hKey){ LONG error; HKEY hSubKey; DWORD dwHotKeyId = 0; UINT uModifiers = 0, uVirtualKey = 0; HKL hKL = NULL; UNICODE_STRING ustrName;
error = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_READ, &hSubKey); if (error != ERROR_SUCCESS) return FALSE;
RtlInitUnicodeString(&ustrName, pszSubKey); RtlUnicodeStringToInteger(&ustrName, 16, &dwHotKeyId);
uModifiers = CliReadRegistryValue(hSubKey, L"Key Modifiers"); hKL = (HKL)(ULONG_PTR)CliReadRegistryValue(hSubKey, L"Target IME"); uVirtualKey = CliReadRegistryValue(hSubKey, L"Virtual Key");
RegCloseKey(hSubKey);
return CliImmSetHotKeyWorker(dwHotKeyId, uModifiers, uVirtualKey, hKL, SETIMEHOTKEY_ADD);}
BOOL FASTCALL CliGetImeHotKeysFromRegistry(VOID){ HKEY hKey; LONG error; BOOL ret = FALSE; DWORD dwIndex, cchKeyName; WCHAR szKeyName[16];
error = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\Input Method\\Hot Keys", 0, KEY_READ, &hKey); if (error != ERROR_SUCCESS) return ret;
for (dwIndex = 0; dwIndex < 1000; ++dwIndex) { cchKeyName = _countof(szKeyName); error = RegEnumKeyExW(hKey, dwIndex, szKeyName, &cchKeyName, NULL, NULL, NULL, NULL); if (error != ERROR_SUCCESS) break;
szKeyName[_countof(szKeyName) - 1] = 0; /* Avoid stack overrun */
if (CliSetSingleHotKey(szKeyName, hKey)) ret = TRUE; }
RegCloseKey(hKey); return ret;}
VOID APIENTRY CliGetPreloadKeyboardLayouts(PBYTE pbFlags){ WCHAR szValueName[33], szValue[16]; UNICODE_STRING ustrValue; DWORD dwKL, cbValue, dwType; UINT iNumber; HKEY hKey; LONG error;
error = RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", 0, KEY_READ, &hKey); if (error != ERROR_SUCCESS) return;
for (iNumber = 1; iNumber < 1000; ++iNumber) { _ultow(iNumber, szValueName, 10);
cbValue = sizeof(szValue); error = RegQueryValueExW(hKey, szValueName, NULL, &dwType, (LPBYTE)szValue, &cbValue); if (error != ERROR_SUCCESS) break;
if (dwType != REG_SZ) continue;
szValue[_countof(szValue) - 1] = 0; /* Avoid stack overrun */
RtlInitUnicodeString(&ustrValue, szValue); RtlUnicodeStringToInteger(&ustrValue, 16, &dwKL);
IntSetFeKeyboardFlags(LOWORD(dwKL), pbFlags); }
RegCloseKey(hKey);}
VOID APIENTRY CliSetDefaultImeHotKeys(PIMEHOTKEYENTRY pEntries, UINT nCount, BOOL bCheck){ UINT uVirtualKey, uModifiers; HKL hKL;
while (nCount-- > 0) { if (!bCheck || !NtUserGetImeHotKey(pEntries->dwHotKeyId, &uModifiers, &uVirtualKey, &hKL)) { CliImmSetHotKeyWorker(pEntries->dwHotKeyId, pEntries->uModifiers, pEntries->uVirtualKey, pEntries->hKL, SETIMEHOTKEY_ADD); } ++pEntries; }}
VOID APIENTRY CliImmInitializeHotKeys(DWORD dwAction, HKL hKL){ UINT nCount; LPHKL pList; UINT iIndex; LANGID LangID; BYTE bFlags = 0; BOOL bCheck;
NtUserSetImeHotKey(0, 0, 0, NULL, SETIMEHOTKEY_INITIALIZE);
bCheck = CliGetImeHotKeysFromRegistry();
if (dwAction == SETIMEHOTKEY_INITIALIZE) { LangID = LANGIDFROMLCID(GetUserDefaultLCID()); IntSetFeKeyboardFlags(LangID, &bFlags);
CliGetPreloadKeyboardLayouts(&bFlags); } else { nCount = NtUserGetKeyboardLayoutList(0, NULL); if (!nCount) return;
pList = RtlAllocateHeap(RtlGetProcessHeap(), 0, nCount * sizeof(HKL)); if (!pList) return;
NtUserGetKeyboardLayoutList(nCount, pList);
for (iIndex = 0; iIndex < nCount; ++iIndex) { LangID = LOWORD(pList[iIndex]); IntSetFeKeyboardFlags(LangID, &bFlags); }
RtlFreeHeap(RtlGetProcessHeap(), 0, pList); }
if (bFlags & FE_JAPANESE) CliSetDefaultImeHotKeys(DefaultHotKeyTableJ, _countof(DefaultHotKeyTableJ), bCheck);
if (bFlags & FE_CHINESE_TRADITIONAL) CliSetDefaultImeHotKeys(DefaultHotKeyTableT, _countof(DefaultHotKeyTableT), bCheck);
if (bFlags & FE_CHINESE_SIMPLIFIED) CliSetDefaultImeHotKeys(DefaultHotKeyTableC, _countof(DefaultHotKeyTableC), bCheck);}
/* * @implemented */BOOLWINAPIDragDetect( HWND hWnd, POINT pt){ return NtUserDragDetect(hWnd, pt);#if 0 MSG msg; RECT rect; POINT tmp; ULONG dx = GetSystemMetrics(SM_CXDRAG); ULONG dy = GetSystemMetrics(SM_CYDRAG);
rect.left = pt.x - dx; rect.right = pt.x + dx; rect.top = pt.y - dy; rect.bottom = pt.y + dy;
SetCapture(hWnd);
for (;;) { while ( PeekMessageW(&msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || PeekMessageW(&msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) ) { if (msg.message == WM_LBUTTONUP) { ReleaseCapture(); return FALSE; } if (msg.message == WM_MOUSEMOVE) { tmp.x = LOWORD(msg.lParam); tmp.y = HIWORD(msg.lParam); if (!PtInRect(&rect, tmp)) { ReleaseCapture(); return TRUE; } } if (msg.message == WM_KEYDOWN) { if (msg.wParam == VK_ESCAPE) { ReleaseCapture(); return TRUE; } } } WaitMessage(); } return 0;#endif}
/* * @implemented */BOOL WINAPIEnableWindow(HWND hWnd, BOOL bEnable){ return NtUserxEnableWindow(hWnd, bEnable);}
/* * @implemented */SHORTWINAPIDECLSPEC_HOTPATCHGetAsyncKeyState(int vKey){ if (vKey < 0 || vKey > 256) return 0; return (SHORT)NtUserGetAsyncKeyState((DWORD)vKey);}
/* * @implemented */HKL WINAPIGetKeyboardLayout(DWORD idThread){ return NtUserxGetKeyboardLayout(idThread);}
/* * @implemented */UINT WINAPIGetKBCodePage(VOID){ return GetOEMCP();}
/* * @implemented */int WINAPIGetKeyNameTextA(LONG lParam, LPSTR lpString, int nSize){ LPWSTR pwszBuf; UINT cchBuf = 0; int iRet = 0; BOOL defChar = FALSE;
pwszBuf = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR)); if (!pwszBuf) return 0;
cchBuf = NtUserGetKeyNameText(lParam, pwszBuf, nSize);
iRet = WideCharToMultiByte(CP_ACP, 0, pwszBuf, cchBuf, lpString, nSize, ".", &defChar); // FIXME: do we need defChar? lpString[iRet] = 0; HeapFree(GetProcessHeap(), 0, pwszBuf);
return iRet;}
/* * @implemented */int WINAPIGetKeyNameTextW(LONG lParam, LPWSTR lpString, int nSize){ return NtUserGetKeyNameText(lParam, lpString, nSize);}
/* * @implemented */SHORTWINAPIDECLSPEC_HOTPATCHGetKeyState(int nVirtKey){ return (SHORT)NtUserGetKeyState((DWORD)nVirtKey);}
/* * @implemented */BOOL WINAPIGetKeyboardLayoutNameA(LPSTR pwszKLID){ WCHAR buf[KL_NAMELENGTH];
if (!GetKeyboardLayoutNameW(buf)) return FALSE;
if (!WideCharToMultiByte(CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH, NULL, NULL)) return FALSE;
return TRUE;}
/* * @implemented */BOOL WINAPIGetKeyboardLayoutNameW(LPWSTR pwszKLID){ UNICODE_STRING Name;
RtlInitEmptyUnicodeString(&Name, pwszKLID, KL_NAMELENGTH * sizeof(WCHAR));
return NtUserGetKeyboardLayoutName(&Name);}
/* * @implemented */int WINAPIGetKeyboardType(int nTypeFlag){ return NtUserxGetKeyboardType(nTypeFlag);}
/* * @implemented */BOOL WINAPIGetLastInputInfo(PLASTINPUTINFO plii){ TRACE("%p\n", plii);
if (plii->cbSize != sizeof (*plii)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
plii->dwTime = gpsi->dwLastRITEventTickCount; return TRUE;}
/* * @implemented */HKL WINAPILoadKeyboardLayoutA(LPCSTR pszKLID, UINT Flags){ WCHAR wszKLID[16];
if (!MultiByteToWideChar(CP_ACP, 0, pszKLID, -1, wszKLID, sizeof(wszKLID)/sizeof(wszKLID[0]))) { return FALSE; }
return LoadKeyboardLayoutW(wszKLID, Flags);}
static inline BOOL IsValidKLID(_In_ LPCWSTR pwszKLID){ return (pwszKLID != NULL) && (wcsspn(pwszKLID, L"0123456789ABCDEFabcdef") == (KL_NAMELENGTH - 1));}
VOID GetSystemLibraryPath(LPWSTR pszPath, INT cchPath, LPCWSTR pszFileName){ WCHAR szSysDir[MAX_PATH]; GetSystemDirectoryW(szSysDir, _countof(szSysDir)); StringCchPrintfW(pszPath, cchPath, L"%s\\%s", szSysDir, pszFileName);}
#define ENGLISH_US MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
/* * @unimplemented * * NOTE: We adopt a different design from Microsoft's one due to security reason. * See NtUserLoadKeyboardLayoutEx. */HKL APIENTRYIntLoadKeyboardLayout( _In_ HKL hklUnload, _In_z_ LPCWSTR pwszKLID, _In_ LANGID wLangID, _In_ UINT Flags, _In_ BOOL unknown5){ DWORD dwKLID, dwHKL, dwType, dwSize; UNICODE_STRING ustrKLID; WCHAR wszRegKey[256] = L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\"; WCHAR wszLayoutId[10], wszNewKLID[KL_NAMELENGTH], szImeFileName[80]; HKL hNewKL; HKEY hKey; BOOL bIsIME; WORD wLow, wHigh;
if (!IsValidKLID(pwszKLID)) { ERR("pwszKLID: %s\n", debugstr_w(pwszKLID)); return UlongToHandle(MAKELONG(ENGLISH_US, ENGLISH_US)); }
dwKLID = wcstoul(pwszKLID, NULL, 16); bIsIME = IS_IME_HKL(UlongToHandle(dwKLID));
wLow = LOWORD(dwKLID); wHigh = HIWORD(dwKLID);
if (Flags & KLF_SUBSTITUTE_OK) { /* Check substitutes key */ if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Substitutes", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { dwSize = sizeof(wszNewKLID); if (RegQueryValueExW(hKey, pwszKLID, NULL, &dwType, (LPBYTE)wszNewKLID, &dwSize) == ERROR_SUCCESS && dwType == REG_SZ) { /* Use new KLID value */ pwszKLID = wszNewKLID; dwKLID = wcstoul(pwszKLID, NULL, 16); wHigh = LOWORD(dwKLID); }
/* Close the key now */ RegCloseKey(hKey); } }
/* Append KLID at the end of registry key */ StringCbCatW(wszRegKey, sizeof(wszRegKey), pwszKLID);
/* Open layout registry key for read */ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { dwSize = sizeof(wszLayoutId); if (RegQueryValueExW(hKey, L"Layout Id", NULL, &dwType, (LPBYTE)wszLayoutId, &dwSize) == ERROR_SUCCESS && dwType == REG_SZ) { /* If Layout Id is specified, use this value | f000 as HIWORD */ wHigh = (0xF000 | wcstoul(wszLayoutId, NULL, 16)); }
if (bIsIME) { /* Check "IME File" value */ dwSize = sizeof(szImeFileName); if (RegQueryValueExW(hKey, L"IME File", NULL, &dwType, (LPBYTE)szImeFileName, &dwSize) != ERROR_SUCCESS) { bIsIME = FALSE; wHigh = 0; ERR("0x%X\n", dwKLID); } else { WCHAR szPath[MAX_PATH]; szImeFileName[_countof(szImeFileName) - 1] = UNICODE_NULL; GetSystemLibraryPath(szPath, _countof(szPath), szImeFileName);
/* We don't allow the invalid "IME File" values due to security reason */ if (dwType != REG_SZ || szImeFileName[0] == 0 || wcscspn(szImeFileName, L":\\/") != wcslen(szImeFileName) || GetFileAttributesW(szPath) == INVALID_FILE_ATTRIBUTES) /* Does not exist? */ { bIsIME = FALSE; wHigh = 0; ERR("'%s'\n", debugstr_w(szPath)); } } }
/* Close the key now */ RegCloseKey(hKey); } else { ERR("Could not find keyboard layout %S.\n", pwszKLID); return NULL; }
if (wHigh == 0) wHigh = wLow;
dwHKL = MAKELONG(wLow, wHigh);
RtlInitUnicodeString(&ustrKLID, pwszKLID); hNewKL = NtUserLoadKeyboardLayoutEx(NULL, 0, NULL, hklUnload, &ustrKLID, dwHKL, Flags); CliImmInitializeHotKeys(SETIMEHOTKEY_ADD, hNewKL); return hNewKL;}
/* * @implemented */HKL WINAPILoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags){ TRACE("(%s, 0x%X)\n", debugstr_w(pwszKLID), Flags); return IntLoadKeyboardLayout(NULL, pwszKLID, 0, Flags, FALSE);}
/* * @unimplemented */HKL WINAPILoadKeyboardLayoutEx(HKL hklUnload, LPCWSTR pwszKLID, UINT Flags){ FIXME("(%p, %s, 0x%X)", hklUnload, debugstr_w(pwszKLID), Flags); if (!hklUnload) return NULL; return IntLoadKeyboardLayout(hklUnload, pwszKLID, 0, Flags, FALSE);}
/* * @implemented */BOOL WINAPI UnloadKeyboardLayout(HKL hKL){ if (!NtUserUnloadKeyboardLayout(hKL)) return FALSE;
CliImmInitializeHotKeys(SETIMEHOTKEY_DELETE, hKL); return TRUE;}
/* * @implemented */UINT WINAPIMapVirtualKeyA(UINT uCode, UINT uMapType){ return MapVirtualKeyExA(uCode, uMapType, GetKeyboardLayout(0));}
/* * @implemented */UINT WINAPIMapVirtualKeyExA(UINT uCode, UINT uMapType, HKL dwhkl){ return MapVirtualKeyExW(uCode, uMapType, dwhkl);}
/* * @implemented */UINT WINAPIMapVirtualKeyExW(UINT uCode, UINT uMapType, HKL dwhkl){ return NtUserMapVirtualKeyEx(uCode, uMapType, 0, dwhkl);}
/* * @implemented */UINT WINAPIMapVirtualKeyW(UINT uCode, UINT uMapType){ return MapVirtualKeyExW(uCode, uMapType, GetKeyboardLayout(0));}
/* * @implemented */DWORD WINAPIOemKeyScan(WORD wOemChar){ WCHAR p; SHORT Vk; UINT Scan;
MultiByteToWideChar(CP_OEMCP, 0, (PCSTR)&wOemChar, 1, &p, 1); Vk = VkKeyScanW(p); Scan = MapVirtualKeyW((Vk & 0x00ff), 0); if (!Scan) return -1; /* Page 450-1, MS W2k SuperBible by SAMS. Return, low word has the scan code and high word has the shift state. */ return ((Vk & 0xff00) << 8) | Scan;}
/* * @implemented */BOOL WINAPISetDoubleClickTime(UINT uInterval){ return (BOOL)NtUserSystemParametersInfo(SPI_SETDOUBLECLICKTIME, uInterval, NULL, 0);}
/* * @implemented */BOOLWINAPISwapMouseButton( BOOL fSwap){ return NtUserxSwapMouseButton(fSwap);}
/* * @implemented */int WINAPIToAscii(UINT uVirtKey, UINT uScanCode, CONST BYTE *lpKeyState, LPWORD lpChar, UINT uFlags){ return ToAsciiEx(uVirtKey, uScanCode, lpKeyState, lpChar, uFlags, 0);}
/* * @implemented */int WINAPIToAsciiEx(UINT uVirtKey, UINT uScanCode, CONST BYTE *lpKeyState, LPWORD lpChar, UINT uFlags, HKL dwhkl){ WCHAR UniChars[2]; int Ret, CharCount;
Ret = ToUnicodeEx(uVirtKey, uScanCode, lpKeyState, UniChars, 2, uFlags, dwhkl); CharCount = (Ret < 0 ? 1 : Ret); WideCharToMultiByte(CP_ACP, 0, UniChars, CharCount, (LPSTR)lpChar, 2, NULL, NULL);
return Ret;}
/* * @implemented */int WINAPIToUnicode(UINT wVirtKey, UINT wScanCode, CONST BYTE *lpKeyState, LPWSTR pwszBuff, int cchBuff, UINT wFlags){ return ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff, wFlags, 0);}
/* * @implemented */int WINAPIToUnicodeEx(UINT wVirtKey, UINT wScanCode, CONST BYTE *lpKeyState, LPWSTR pwszBuff, int cchBuff, UINT wFlags, HKL dwhkl){ return NtUserToUnicodeEx(wVirtKey, wScanCode, (PBYTE)lpKeyState, pwszBuff, cchBuff, wFlags, dwhkl);}
/* * @implemented */SHORT WINAPIVkKeyScanA(CHAR ch){ WCHAR wChar;
if (IsDBCSLeadByte(ch)) return -1;
MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1); return VkKeyScanW(wChar);}
/* * @implemented */SHORT WINAPIVkKeyScanExA(CHAR ch, HKL dwhkl){ WCHAR wChar;
if (IsDBCSLeadByte(ch)) return -1;
MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1); return VkKeyScanExW(wChar, dwhkl);}
/* * @implemented */SHORT WINAPIVkKeyScanExW(WCHAR ch, HKL dwhkl){ return (SHORT)NtUserVkKeyScanEx(ch, dwhkl, TRUE);}
/* * @implemented */SHORT WINAPIVkKeyScanW(WCHAR ch){ return (SHORT)NtUserVkKeyScanEx(ch, 0, FALSE);}
/* * @implemented */VOIDWINAPIkeybd_event( BYTE bVk, BYTE bScan, DWORD dwFlags, ULONG_PTR dwExtraInfo){ INPUT Input;
Input.type = INPUT_KEYBOARD; Input.ki.wVk = bVk; Input.ki.wScan = bScan; Input.ki.dwFlags = dwFlags; Input.ki.time = 0; Input.ki.dwExtraInfo = dwExtraInfo;
NtUserSendInput(1, &Input, sizeof(INPUT));}
/* * @implemented */VOIDWINAPImouse_event( DWORD dwFlags, DWORD dx, DWORD dy, DWORD dwData, ULONG_PTR dwExtraInfo){ INPUT Input;
Input.type = INPUT_MOUSE; Input.mi.dx = dx; Input.mi.dy = dy; Input.mi.mouseData = dwData; Input.mi.dwFlags = dwFlags; Input.mi.time = 0; Input.mi.dwExtraInfo = dwExtraInfo;
NtUserSendInput(1, &Input, sizeof(INPUT));}
/* EOF */