/* * 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 #include WINE_DEFAULT_DEBUG_CHANNEL(user32); typedef struct tagIMEHOTKEYENTRY { DWORD dwHotKeyId; UINT uVirtualKey; UINT uModifiers; HKL hKL; } IMEHOTKEYENTRY, *PIMEHOTKEYENTRY; // Japanese IMEHOTKEYENTRY DefaultHotKeyTableJ[] = { { IME_JHOTKEY_CLOSE_OPEN, VK_KANJI, MOD_IGNORE_ALL_MODIFIER, NULL }, }; // Chinese Traditional IMEHOTKEYENTRY 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 Simplified IMEHOTKEYENTRY 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 flags // Win: SetFeKeyboardFlags VOID 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 APIENTRY CliImmSetHotKeyWorker(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; } /* Win: LoadPreloadKeyboardLayouts */ 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 APIENTRY CliSaveImeHotKey(DWORD dwID, UINT uModifiers, UINT uVirtualKey, HKL hKL, BOOL bDelete) { WCHAR szName[MAX_PATH]; LONG error; HKEY hControlPanel = NULL, hInputMethod = NULL, hHotKeys = NULL, hKey = NULL; BOOL ret = FALSE, bRevertOnFailure = FALSE; if (bDelete) { StringCchPrintfW(szName, _countof(szName), L"Control Panel\\Input Method\\Hot Keys\\%08lX", dwID); error = RegDeleteKeyW(HKEY_CURRENT_USER, szName); return (error == ERROR_SUCCESS); } // Open "Control Panel" error = RegCreateKeyExW(HKEY_CURRENT_USER, L"Control Panel", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hControlPanel, NULL); if (error == ERROR_SUCCESS) { // Open "Input Method" error = RegCreateKeyExW(hControlPanel, L"Input Method", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hInputMethod, NULL); if (error == ERROR_SUCCESS) { // Open "Hot Keys" error = RegCreateKeyExW(hInputMethod, L"Hot Keys", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hHotKeys, NULL); if (error == ERROR_SUCCESS) { // Open "Key" StringCchPrintfW(szName, _countof(szName), L"%08lX", dwID); error = RegCreateKeyExW(hHotKeys, szName, 0, NULL, 0, KEY_ALL_ACCESS, 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); } RegCloseKey(hHotKeys); } RegCloseKey(hInputMethod); } RegCloseKey(hControlPanel); } if (bRevertOnFailure) CliSaveImeHotKey(dwID, uVirtualKey, uModifiers, hKL, TRUE); return ret; } /* * @implemented * Same as imm32!ImmSetHotKey. */ BOOL WINAPI CliImmSetHotKey(DWORD dwID, UINT uModifiers, UINT uVirtualKey, 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 */ BOOL WINAPI DragDetect( 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 WINAPI EnableWindow(HWND hWnd, BOOL bEnable) { return NtUserxEnableWindow(hWnd, bEnable); } /* * @implemented */ SHORT WINAPI DECLSPEC_HOTPATCH GetAsyncKeyState(int vKey) { if (vKey < 0 || vKey > 256) return 0; return (SHORT)NtUserGetAsyncKeyState((DWORD)vKey); } /* * @implemented */ HKL WINAPI GetKeyboardLayout(DWORD idThread) { return NtUserxGetKeyboardLayout(idThread); } /* * @implemented */ UINT WINAPI GetKBCodePage(VOID) { return GetOEMCP(); } /* * @implemented */ int WINAPI GetKeyNameTextA(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 WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpString, int nSize) { return NtUserGetKeyNameText(lParam, lpString, nSize); } /* * @implemented */ SHORT WINAPI DECLSPEC_HOTPATCH GetKeyState(int nVirtKey) { return (SHORT)NtUserGetKeyState((DWORD)nVirtKey); } /* * @implemented */ BOOL WINAPI GetKeyboardLayoutNameA(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 WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID) { UNICODE_STRING Name; RtlInitEmptyUnicodeString(&Name, pwszKLID, KL_NAMELENGTH * sizeof(WCHAR)); return NtUserGetKeyboardLayoutName(&Name); } /* * @implemented */ int WINAPI GetKeyboardType(int nTypeFlag) { return NtUserxGetKeyboardType(nTypeFlag); } /* * @implemented */ BOOL WINAPI GetLastInputInfo(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 WINAPI LoadKeyboardLayoutA(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 APIENTRY IntLoadKeyboardLayout( _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 WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags) { TRACE("(%s, 0x%X)\n", debugstr_w(pwszKLID), Flags); return IntLoadKeyboardLayout(NULL, pwszKLID, 0, Flags, FALSE); } /* * @unimplemented */ HKL WINAPI LoadKeyboardLayoutEx(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 WINAPI MapVirtualKeyA(UINT uCode, UINT uMapType) { return MapVirtualKeyExA(uCode, uMapType, GetKeyboardLayout(0)); } /* * @implemented */ UINT WINAPI MapVirtualKeyExA(UINT uCode, UINT uMapType, HKL dwhkl) { return MapVirtualKeyExW(uCode, uMapType, dwhkl); } /* * @implemented */ UINT WINAPI MapVirtualKeyExW(UINT uCode, UINT uMapType, HKL dwhkl) { return NtUserMapVirtualKeyEx(uCode, uMapType, 0, dwhkl); } /* * @implemented */ UINT WINAPI MapVirtualKeyW(UINT uCode, UINT uMapType) { return MapVirtualKeyExW(uCode, uMapType, GetKeyboardLayout(0)); } /* * @implemented */ DWORD WINAPI OemKeyScan(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 WINAPI SetDoubleClickTime(UINT uInterval) { return (BOOL)NtUserSystemParametersInfo(SPI_SETDOUBLECLICKTIME, uInterval, NULL, 0); } /* * @implemented */ BOOL WINAPI SwapMouseButton( BOOL fSwap) { return NtUserxSwapMouseButton(fSwap); } /* * @implemented */ int WINAPI ToAscii(UINT uVirtKey, UINT uScanCode, CONST BYTE *lpKeyState, LPWORD lpChar, UINT uFlags) { return ToAsciiEx(uVirtKey, uScanCode, lpKeyState, lpChar, uFlags, 0); } /* * @implemented */ int WINAPI ToAsciiEx(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 WINAPI ToUnicode(UINT wVirtKey, UINT wScanCode, CONST BYTE *lpKeyState, LPWSTR pwszBuff, int cchBuff, UINT wFlags) { return ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff, wFlags, 0); } /* * @implemented */ int WINAPI ToUnicodeEx(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 WINAPI VkKeyScanA(CHAR ch) { WCHAR wChar; if (IsDBCSLeadByte(ch)) return -1; MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1); return VkKeyScanW(wChar); } /* * @implemented */ SHORT WINAPI VkKeyScanExA(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 WINAPI VkKeyScanExW(WCHAR ch, HKL dwhkl) { return (SHORT)NtUserVkKeyScanEx(ch, dwhkl, TRUE); } /* * @implemented */ SHORT WINAPI VkKeyScanW(WCHAR ch) { return (SHORT)NtUserVkKeyScanEx(ch, 0, FALSE); } /* * @implemented */ VOID WINAPI keybd_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 */ VOID WINAPI mouse_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 */