diff --git a/sdk/include/reactos/imm32_undoc.h b/sdk/include/reactos/imm32_undoc.h index 71be9852f47..fb5d7134c34 100644 --- a/sdk/include/reactos/imm32_undoc.h +++ b/sdk/include/reactos/imm32_undoc.h @@ -233,6 +233,10 @@ LRESULT WINAPI ImmPutImeMenuItemsIntoMappedFile(_In_ HIMC hIMC); BOOL WINAPI ImmIMPGetIMEA(_In_opt_ HWND hWnd, _Out_ LPIMEPROA pImePro); BOOL WINAPI ImmIMPGetIMEW(_In_opt_ HWND hWnd, _Out_ LPIMEPROW pImePro); +BOOL WINAPI ImmIMPQueryIMEA(_Inout_ LPIMEPROA pImePro); +BOOL WINAPI ImmIMPQueryIMEW(_Inout_ LPIMEPROW pImePro); +BOOL WINAPI ImmIMPSetIMEA(_In_opt_ HWND hWnd, _Inout_ LPIMEPROA pImePro); +BOOL WINAPI ImmIMPSetIMEW(_In_opt_ HWND hWnd, _Inout_ LPIMEPROW pImePro); HRESULT WINAPI CtfAImmActivate(_Out_opt_ HINSTANCE *phinstCtfIme); HRESULT WINAPI CtfAImmDeactivate(_In_ BOOL bDestroy); @@ -260,8 +264,12 @@ CtfImmDispatchDefImeMessage( #ifdef UNICODE #define ImmIMPGetIME ImmIMPGetIMEW + #define ImmIMPQueryIME ImmIMPQueryIMEW + #define ImmIMPSetIME ImmIMPSetIMEW #else #define ImmIMPGetIME ImmIMPGetIMEA + #define ImmIMPQueryIME ImmIMPQueryIMEA + #define ImmIMPSetIME ImmIMPSetIMEA #endif #ifdef __cplusplus diff --git a/win32ss/user/imm32/imepro.c b/win32ss/user/imm32/imepro.c index e5f3609de2b..b865d29f658 100644 --- a/win32ss/user/imm32/imepro.c +++ b/win32ss/user/imm32/imepro.c @@ -15,8 +15,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm); */ static VOID -Imm32ConvertImeProWideToAnsi(_In_ const IMEPROW *pProW, _Out_ PIMEPROA pProA) +Imm32ConvertImeProWideToAnsi( + _In_ const IMEPROW *pProW, + _Out_ PIMEPROA pProA) { + ASSERT(pProW); + ASSERT(pProA); + pProA->hWnd = pProW->hWnd; pProA->InstDate = pProW->InstDate; pProA->wVersion = pProW->wVersion; @@ -33,8 +38,12 @@ Imm32ConvertImeProWideToAnsi(_In_ const IMEPROW *pProW, _Out_ PIMEPROA pProA) } static BOOL -Imm32IMPGetIME(_In_ HKL hKL, _Out_ PIMEPROW pProW) +Imm32IMPGetIME( + _In_ HKL hKL, + _Out_ PIMEPROW pProW) { + ASSERT(pProW); + IMEINFOEX ImeInfoEx; if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL)) return FALSE; @@ -56,12 +65,16 @@ Imm32IMPGetIME(_In_ HKL hKL, _Out_ PIMEPROW pProW) * ImmIMPGetIMEA(IMM32.@) */ BOOL WINAPI -ImmIMPGetIMEA(_In_opt_ HWND hWnd, _Out_ LPIMEPROA pImePro) +ImmIMPGetIMEA( + _In_opt_ HWND hWnd, + _Out_ LPIMEPROA pImePro) { UNREFERENCED_PARAMETER(hWnd); TRACE("(%p, %p)\n", hWnd, pImePro); + ASSERT(pImePro); + if (!Imm32IsSystemJapaneseOrKorean()) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); @@ -81,12 +94,16 @@ ImmIMPGetIMEA(_In_opt_ HWND hWnd, _Out_ LPIMEPROA pImePro) * ImmIMPGetIMEW(IMM32.@) */ BOOL WINAPI -ImmIMPGetIMEW(_In_opt_ HWND hWnd, _Out_ LPIMEPROW pImePro) +ImmIMPGetIMEW( + _In_opt_ HWND hWnd, + _Out_ LPIMEPROW pImePro) { UNREFERENCED_PARAMETER(hWnd); TRACE("(%p, %p)\n", hWnd, pImePro); + ASSERT(pImePro); + if (!Imm32IsSystemJapaneseOrKorean()) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); @@ -100,39 +117,222 @@ ImmIMPGetIMEW(_In_opt_ HWND hWnd, _Out_ LPIMEPROW pImePro) /*********************************************************************** * ImmIMPQueryIMEA(IMM32.@) */ -BOOL WINAPI ImmIMPQueryIMEA(LPIMEPROA pImePro) +BOOL WINAPI +ImmIMPQueryIMEA(_Inout_ LPIMEPROA pImePro) { - FIXME("(%p)\n", pImePro); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + TRACE("(%p)\n", pImePro); + + ASSERT(pImePro); + + if (!Imm32IsSystemJapaneseOrKorean()) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + IMEPROW ProW; + if (pImePro->szName[0]) + { + /* pImePro->szName is BYTE[], so we need type cast */ + if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (PSTR)pImePro->szName, -1, + ProW.szName, _countof(ProW.szName))) + { + ERR("szName: %s\n", debugstr_a((PSTR)pImePro->szName)); + return FALSE; + } + ProW.szName[_countof(ProW.szName) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ + } + else + { + ProW.szName[0] = UNICODE_NULL; + } + + if (!ImmIMPQueryIMEW(&ProW)) + return FALSE; + + Imm32ConvertImeProWideToAnsi(&ProW, pImePro); + return TRUE; } /*********************************************************************** * ImmIMPQueryIMEW(IMM32.@) */ -BOOL WINAPI ImmIMPQueryIMEW(LPIMEPROW pImePro) +BOOL WINAPI +ImmIMPQueryIMEW(_Inout_ LPIMEPROW pImePro) { - FIXME("(%p)\n", pImePro); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + TRACE("(%p)\n", pImePro); + + ASSERT(pImePro); + + if (!Imm32IsSystemJapaneseOrKorean()) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + INT nLayouts = GetKeyboardLayoutList(0, NULL); + if (nLayouts <= 0) + { + ERR("nLayouts: %d\n", nLayouts); + return FALSE; + } + + HKL *phKLs = ImmLocalAlloc(0, nLayouts * sizeof(HKL)); + if (!phKLs) + { + ERR("Out of memory\n"); + return FALSE; + } + + if (GetKeyboardLayoutList(nLayouts, phKLs) != nLayouts) + { + ERR("KL count mismatch\n"); + ImmLocalFree(phKLs); + return FALSE; + } + + BOOL result = FALSE; + if (pImePro->szName[0]) + { + IMEINFOEX ImeInfoEx; + if (ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExImeFileName, pImePro->szName)) + { + for (INT iKL = 0; iKL < nLayouts; ++iKL) + { + if (phKLs[iKL] == ImeInfoEx.hkl) + { + result = Imm32IMPGetIME(phKLs[iKL], pImePro); + break; + } + } + } + } + else + { + for (INT iKL = 0; iKL < nLayouts; ++iKL) + { + result = Imm32IMPGetIME(phKLs[iKL], pImePro); + if (result) + break; + } + } + + ImmLocalFree(phKLs); + return result; } /*********************************************************************** * ImmIMPSetIMEA(IMM32.@) */ -BOOL WINAPI ImmIMPSetIMEA(HWND hWnd, LPIMEPROA pImePro) +BOOL WINAPI +ImmIMPSetIMEA( + _In_opt_ HWND hWnd, + _Inout_ LPIMEPROA pImePro) { - FIXME("(%p, %p)\n", hWnd, pImePro); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + TRACE("(%p, %p)\n", hWnd, pImePro); + + ASSERT(pImePro); + + IMEPROW ProW; + if (!Imm32IsSystemJapaneseOrKorean()) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + if (pImePro->szName[0]) + { + /* pImePro->szName is BYTE[], so we need type cast */ + if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (PSTR)pImePro->szName, -1, + ProW.szName, _countof(ProW.szName))) + { + ERR("szName: %s\n", debugstr_a((PSTR)pImePro->szName)); + return FALSE; + } + ProW.szName[_countof(ProW.szName) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ + } + else + { + ProW.szName[0] = UNICODE_NULL; + } + + return ImmIMPSetIMEW(hWnd, &ProW); } /*********************************************************************** * ImmIMPSetIMEW(IMM32.@) */ -BOOL WINAPI ImmIMPSetIMEW(HWND hWnd, LPIMEPROW pImePro) +BOOL WINAPI +ImmIMPSetIMEW( + _In_opt_ HWND hWnd, + _Inout_ LPIMEPROW pImePro) { - FIXME("(%p, %p)\n", hWnd, pImePro); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + UNREFERENCED_PARAMETER(hWnd); + + TRACE("(%p, %p)\n", hWnd, pImePro); + + ASSERT(pImePro); + + if (!Imm32IsSystemJapaneseOrKorean()) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + HKL hTargetKL = NULL; + if (pImePro->szName[0]) + { + IMEINFOEX ImeInfoEx; + if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExImeFileName, pImePro->szName)) + return FALSE; + + hTargetKL = ImeInfoEx.hkl; + } + else + { + INT nLayouts = GetKeyboardLayoutList(0, NULL); + if (nLayouts <= 0) + { + ERR("nLayouts: %d\n", nLayouts); + return FALSE; + } + + HKL *phKLs = ImmLocalAlloc(0, nLayouts * sizeof(HKL)); + if (!phKLs) + { + ERR("Out of memory\n"); + return FALSE; + } + + if (GetKeyboardLayoutList(nLayouts, phKLs) == nLayouts) + { + for (INT iKL = 0; iKL < nLayouts; ++iKL) + { + if (!ImmIsIME(phKLs[iKL])) + { + hTargetKL = phKLs[iKL]; + break; + } + } + } + else + { + ERR("KL count mismatch\n"); + } + + ImmLocalFree(phKLs); + } + + if (hTargetKL && GetKeyboardLayout(0) != hTargetKL) + { + HWND hwndFocus = GetFocus(); + if (hwndFocus) + { + PostMessageW(hwndFocus, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_SYSCHARSET, + (LPARAM)hTargetKL); + return TRUE; + } + } + return FALSE; }