1 /* 2 * PROJECT: ReactOS IMM32 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Implementing IME manipulation of IMM32 5 * COPYRIGHT: Copyright 1998 Patrik Stridvall 6 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart 7 * Copyright 2017 James Tabor <james.tabor@reactos.org> 8 * Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org> 9 * Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua> 10 * Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 11 */ 12 13 #include "precomp.h" 14 15 WINE_DEFAULT_DEBUG_CHANNEL(imm); 16 17 RTL_CRITICAL_SECTION g_csImeDpi; 18 PIMEDPI g_pImeDpiList = NULL; 19 20 PIMEDPI APIENTRY Imm32FindImeDpi(HKL hKL) 21 { 22 PIMEDPI pImeDpi; 23 24 RtlEnterCriticalSection(&g_csImeDpi); 25 for (pImeDpi = g_pImeDpiList; pImeDpi != NULL; pImeDpi = pImeDpi->pNext) 26 { 27 if (pImeDpi->hKL == hKL) 28 break; 29 } 30 RtlLeaveCriticalSection(&g_csImeDpi); 31 32 return pImeDpi; 33 } 34 35 VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy) 36 { 37 if (pImeDpi->hInst == NULL) 38 return; 39 if (bDestroy) 40 pImeDpi->ImeDestroy(0); 41 FreeLibrary(pImeDpi->hInst); 42 pImeDpi->hInst = NULL; 43 } 44 45 BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi) 46 { 47 WCHAR szUIClass[64]; 48 WNDCLASSW wcW; 49 DWORD dwSysInfoFlags = 0; 50 LPIMEINFO pImeInfo = &pImeDpi->ImeInfo; 51 52 if (NtUserGetThreadState(16)) 53 dwSysInfoFlags |= IME_SYSINFO_WINLOGON; 54 55 if (IS_IME_HKL(pImeDpi->hKL)) 56 { 57 if (!pImeDpi->ImeInquire(pImeInfo, szUIClass, dwSysInfoFlags)) 58 return FALSE; 59 } 60 else if (Imm32IsCiceroMode() && pImeDpi->CtfImeInquireExW) 61 { 62 if (!pImeDpi->CtfImeInquireExW(pImeInfo, szUIClass, dwSysInfoFlags, pImeDpi->hKL)) 63 return FALSE; 64 } 65 else 66 { 67 return FALSE; 68 } 69 70 szUIClass[_countof(szUIClass) - 1] = 0; 71 72 if (pImeInfo->dwPrivateDataSize == 0) 73 pImeInfo->dwPrivateDataSize = sizeof(DWORD); 74 75 #define VALID_IME_PROP (IME_PROP_AT_CARET | \ 76 IME_PROP_SPECIAL_UI | \ 77 IME_PROP_CANDLIST_START_FROM_1 | \ 78 IME_PROP_UNICODE | \ 79 IME_PROP_COMPLETE_ON_UNSELECT | \ 80 IME_PROP_END_UNLOAD | \ 81 IME_PROP_KBD_CHAR_FIRST | \ 82 IME_PROP_IGNORE_UPKEYS | \ 83 IME_PROP_NEED_ALTKEY | \ 84 IME_PROP_NO_KEYS_ON_CLOSE | \ 85 IME_PROP_ACCEPT_WIDE_VKEY) 86 #define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \ 87 IME_CMODE_NATIVE | \ 88 IME_CMODE_KATAKANA | \ 89 IME_CMODE_LANGUAGE | \ 90 IME_CMODE_FULLSHAPE | \ 91 IME_CMODE_ROMAN | \ 92 IME_CMODE_CHARCODE | \ 93 IME_CMODE_HANJACONVERT | \ 94 IME_CMODE_SOFTKBD | \ 95 IME_CMODE_NOCONVERSION | \ 96 IME_CMODE_EUDC | \ 97 IME_CMODE_SYMBOL | \ 98 IME_CMODE_FIXED) 99 #define VALID_SMODE_CAPS (IME_SMODE_NONE | \ 100 IME_SMODE_PLAURALCLAUSE | \ 101 IME_SMODE_SINGLECONVERT | \ 102 IME_SMODE_AUTOMATIC | \ 103 IME_SMODE_PHRASEPREDICT | \ 104 IME_SMODE_CONVERSATION) 105 #define VALID_UI_CAPS (UI_CAP_2700 | \ 106 UI_CAP_ROT90 | \ 107 UI_CAP_ROTANY | \ 108 UI_CAP_SOFTKBD) 109 #define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \ 110 SCS_CAP_MAKEREAD | \ 111 SCS_CAP_SETRECONVERTSTRING) 112 #define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE) 113 114 if (pImeInfo->fdwProperty & ~VALID_IME_PROP) 115 return FALSE; 116 if (pImeInfo->fdwConversionCaps & ~VALID_CMODE_CAPS) 117 return FALSE; 118 if (pImeInfo->fdwSentenceCaps & ~VALID_SMODE_CAPS) 119 return FALSE; 120 if (pImeInfo->fdwUICaps & ~VALID_UI_CAPS) 121 return FALSE; 122 if (pImeInfo->fdwSCSCaps & ~VALID_SCS_CAPS) 123 return FALSE; 124 if (pImeInfo->fdwSelectCaps & ~VALID_SELECT_CAPS) 125 return FALSE; 126 127 #undef VALID_IME_PROP 128 #undef VALID_CMODE_CAPS 129 #undef VALID_SMODE_CAPS 130 #undef VALID_UI_CAPS 131 #undef VALID_SCS_CAPS 132 #undef VALID_SELECT_CAPS 133 134 if (pImeInfo->fdwProperty & IME_PROP_UNICODE) 135 { 136 StringCchCopyW(pImeDpi->szUIClass, _countof(pImeDpi->szUIClass), szUIClass); 137 } 138 else 139 { 140 if (pImeDpi->uCodePage != GetACP() && pImeDpi->uCodePage) 141 return FALSE; 142 143 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPSTR)szUIClass, -1, 144 pImeDpi->szUIClass, _countof(pImeDpi->szUIClass)); 145 } 146 147 return GetClassInfoW(pImeDpi->hInst, pImeDpi->szUIClass, &wcW); 148 } 149 150 BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi) 151 { 152 WCHAR szPath[MAX_PATH]; 153 HINSTANCE hIME; 154 FARPROC fn; 155 BOOL ret = FALSE; 156 157 if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile)) 158 return FALSE; 159 160 hIME = GetModuleHandleW(szPath); 161 if (hIME == NULL) 162 { 163 hIME = LoadLibraryW(szPath); 164 if (hIME == NULL) 165 { 166 ERR("Imm32LoadImeInfo: LoadLibraryW(%S) failed\n", szPath); 167 return FALSE; 168 } 169 } 170 pImeDpi->hInst = hIME; 171 172 #define DEFINE_IME_ENTRY(type, name, params, optional) \ 173 do { \ 174 fn = GetProcAddress(hIME, #name); \ 175 if (fn) pImeDpi->name = (FN_##name)fn; \ 176 else if (!(optional)) { \ 177 ERR("'%s' not found in the IME module '%s'.\n", #name, debugstr_w(szPath)); \ 178 goto Failed; \ 179 } \ 180 } while (0); 181 #include "imetable.h" 182 #undef DEFINE_IME_ENTRY 183 184 if (Imm32InquireIme(pImeDpi)) 185 { 186 ret = TRUE; 187 } 188 else 189 { 190 ERR("Imm32InquireIme failed\n"); 191 Failed: 192 ret = FALSE; 193 FreeLibrary(pImeDpi->hInst); 194 pImeDpi->hInst = NULL; 195 } 196 197 if (pImeInfoEx->fLoadFlag == 0) 198 { 199 if (ret) 200 { 201 C_ASSERT(sizeof(pImeInfoEx->wszUIClass) == sizeof(pImeDpi->szUIClass)); 202 pImeInfoEx->ImeInfo = pImeDpi->ImeInfo; 203 RtlCopyMemory(pImeInfoEx->wszUIClass, pImeDpi->szUIClass, 204 sizeof(pImeInfoEx->wszUIClass)); 205 pImeInfoEx->fLoadFlag = 2; 206 } 207 else 208 { 209 pImeInfoEx->fLoadFlag = 1; 210 } 211 212 NtUserSetImeInfoEx(pImeInfoEx); 213 } 214 215 return ret; 216 } 217 218 PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock) 219 { 220 IMEINFOEX ImeInfoEx; 221 CHARSETINFO ci; 222 PIMEDPI pImeDpiNew, pImeDpiFound; 223 UINT uCodePage; 224 LCID lcid; 225 226 if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL) || 227 ImeInfoEx.fLoadFlag == 1) 228 { 229 return NULL; 230 } 231 232 pImeDpiNew = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(IMEDPI)); 233 if (pImeDpiNew == NULL) 234 return NULL; 235 236 pImeDpiNew->hKL = hKL; 237 238 lcid = LOWORD(hKL); 239 if (TranslateCharsetInfo((LPDWORD)(DWORD_PTR)lcid, &ci, TCI_SRCLOCALE)) 240 uCodePage = ci.ciACP; 241 else 242 uCodePage = CP_ACP; 243 pImeDpiNew->uCodePage = uCodePage; 244 245 if (!Imm32LoadImeInfo(&ImeInfoEx, pImeDpiNew)) 246 { 247 Imm32HeapFree(pImeDpiNew); 248 return FALSE; 249 } 250 251 RtlEnterCriticalSection(&g_csImeDpi); 252 253 pImeDpiFound = Imm32FindImeDpi(hKL); 254 if (pImeDpiFound) 255 { 256 if (!bLock) 257 pImeDpiFound->dwFlags &= ~IMEDPI_FLAG_LOCKED; 258 259 RtlLeaveCriticalSection(&g_csImeDpi); 260 261 Imm32FreeImeDpi(pImeDpiNew, FALSE); 262 Imm32HeapFree(pImeDpiNew); 263 return pImeDpiFound; 264 } 265 else 266 { 267 if (bLock) 268 { 269 pImeDpiNew->dwFlags |= IMEDPI_FLAG_LOCKED; 270 pImeDpiNew->cLockObj = 1; 271 } 272 273 pImeDpiNew->pNext = g_pImeDpiList; 274 g_pImeDpiList = pImeDpiNew; 275 276 RtlLeaveCriticalSection(&g_csImeDpi); 277 return pImeDpiNew; 278 } 279 } 280 281 PIMEDPI APIENTRY ImmLockOrLoadImeDpi(HKL hKL) 282 { 283 PIMEDPI pImeDpi; 284 285 if (!IS_IME_HKL(hKL) && (!Imm32IsCiceroMode() || Imm32Is16BitMode())) 286 return NULL; 287 288 pImeDpi = ImmLockImeDpi(hKL); 289 if (pImeDpi == NULL) 290 pImeDpi = Ime32LoadImeDpi(hKL, TRUE); 291 return pImeDpi; 292 } 293 294 static LRESULT APIENTRY 295 ImeDpi_Escape(PIMEDPI pImeDpi, HIMC hIMC, UINT uSubFunc, LPVOID lpData, HKL hKL) 296 { 297 if (IS_IME_HKL(hKL)) 298 return pImeDpi->ImeEscape(hIMC, uSubFunc, lpData); 299 300 if (Imm32IsCiceroMode() && pImeDpi->CtfImeEscapeEx) 301 return pImeDpi->CtfImeEscapeEx(hIMC, uSubFunc, lpData, hKL); 302 303 return 0; 304 } 305 306 BOOL APIENTRY Imm32ReleaseIME(HKL hKL) 307 { 308 BOOL ret = TRUE; 309 PIMEDPI pImeDpi0, pImeDpi1; 310 311 RtlEnterCriticalSection(&g_csImeDpi); 312 313 for (pImeDpi0 = g_pImeDpiList; pImeDpi0; pImeDpi0 = pImeDpi0->pNext) 314 { 315 if (pImeDpi0->hKL == hKL) 316 break; 317 } 318 319 if (!pImeDpi0) 320 goto Quit; 321 322 if (pImeDpi0->cLockObj) 323 { 324 pImeDpi0->dwFlags |= IMEDPI_FLAG_UNKNOWN; 325 ret = FALSE; 326 goto Quit; 327 } 328 329 if (g_pImeDpiList == pImeDpi0) 330 { 331 g_pImeDpiList = pImeDpi0->pNext; 332 } 333 else if (g_pImeDpiList) 334 { 335 for (pImeDpi1 = g_pImeDpiList; pImeDpi1; pImeDpi1 = pImeDpi1->pNext) 336 { 337 if (pImeDpi1->pNext == pImeDpi0) 338 { 339 pImeDpi1->pNext = pImeDpi0->pNext; 340 break; 341 } 342 } 343 } 344 345 Imm32FreeImeDpi(pImeDpi0, TRUE); 346 Imm32HeapFree(pImeDpi0); 347 348 Quit: 349 RtlLeaveCriticalSection(&g_csImeDpi); 350 return ret; 351 } 352 353 DWORD APIENTRY 354 Imm32GetImeMenuItemWCrossProcess(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu, 355 LPVOID lpImeMenu, DWORD dwSize) 356 { 357 FIXME("We have to do something\n"); 358 return 0; 359 } 360 361 DWORD APIENTRY 362 Imm32GetImeMenuItemsAW(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu, 363 LPVOID lpImeMenu, DWORD dwSize, BOOL bTargetIsAnsi) 364 { 365 DWORD ret = 0, cbTotal, dwProcessId, dwThreadId, iItem; 366 LPINPUTCONTEXT pIC; 367 PIMEDPI pImeDpi = NULL; 368 IMEMENUITEMINFOA ParentA; 369 IMEMENUITEMINFOW ParentW; 370 LPIMEMENUITEMINFOA pItemA; 371 LPIMEMENUITEMINFOW pItemW; 372 LPVOID pNewItems = NULL, pNewParent = NULL; 373 BOOL bImcIsAnsi; 374 HKL hKL; 375 376 if (!hIMC) 377 return 0; 378 379 dwProcessId = NtUserQueryInputContext(hIMC, 0); 380 if (dwProcessId == 0) 381 return 0; 382 383 if (dwProcessId != GetCurrentProcessId()) 384 { 385 if (bTargetIsAnsi) 386 return 0; 387 return Imm32GetImeMenuItemWCrossProcess(hIMC, dwFlags, dwType, lpImeParentMenu, 388 lpImeMenu, dwSize); 389 } 390 391 pIC = ImmLockIMC(hIMC); 392 if (pIC == NULL) 393 return 0; 394 395 dwThreadId = NtUserQueryInputContext(hIMC, 1); 396 if (dwThreadId == 0) 397 { 398 ImmUnlockIMC(hIMC); 399 return 0; 400 } 401 402 hKL = GetKeyboardLayout(dwThreadId); 403 pImeDpi = ImmLockImeDpi(hKL); 404 if (!pImeDpi) 405 { 406 ImmUnlockIMC(hIMC); 407 return 0; 408 } 409 410 if (pImeDpi->ImeGetImeMenuItems == NULL) 411 goto Quit; 412 413 bImcIsAnsi = Imm32IsImcAnsi(hIMC); 414 415 if (bImcIsAnsi != bTargetIsAnsi) 416 { 417 if (bTargetIsAnsi) 418 { 419 if (lpImeParentMenu) 420 pNewParent = &ParentW; 421 422 if (lpImeMenu) 423 { 424 cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOA)) * sizeof(IMEMENUITEMINFOW)); 425 pNewItems = Imm32HeapAlloc(0, cbTotal); 426 if (!pNewItems) 427 goto Quit; 428 } 429 } 430 else 431 { 432 if (lpImeParentMenu) 433 pNewParent = &ParentA; 434 435 if (lpImeMenu) 436 { 437 cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOW)) * sizeof(IMEMENUITEMINFOA)); 438 pNewItems = Imm32HeapAlloc(0, cbTotal); 439 if (!pNewItems) 440 goto Quit; 441 } 442 } 443 } 444 else 445 { 446 pNewItems = lpImeMenu; 447 pNewParent = lpImeParentMenu; 448 } 449 450 ret = pImeDpi->ImeGetImeMenuItems(hIMC, dwFlags, dwType, pNewParent, pNewItems, dwSize); 451 if (!ret || !lpImeMenu) 452 goto Quit; 453 454 if (bImcIsAnsi != bTargetIsAnsi) 455 { 456 if (bTargetIsAnsi) 457 { 458 if (pNewParent) 459 Imm32ImeMenuWideToAnsi(pNewParent, lpImeParentMenu, CP_ACP); 460 461 pItemW = pNewItems; 462 pItemA = lpImeMenu; 463 for (iItem = 0; iItem < ret; ++iItem, ++pItemW, ++pItemA) 464 { 465 if (!Imm32ImeMenuWideToAnsi(pItemW, pItemA, CP_ACP)) 466 { 467 ret = 0; 468 break; 469 } 470 } 471 } 472 else 473 { 474 if (pNewParent) 475 Imm32ImeMenuAnsiToWide(pNewParent, lpImeParentMenu, pImeDpi->uCodePage, TRUE); 476 477 pItemA = pNewItems; 478 pItemW = lpImeMenu; 479 for (iItem = 0; iItem < dwSize; ++iItem, ++pItemA, ++pItemW) 480 { 481 if (!Imm32ImeMenuAnsiToWide(pItemA, pItemW, pImeDpi->uCodePage, TRUE)) 482 { 483 ret = 0; 484 break; 485 } 486 } 487 } 488 } 489 490 Quit: 491 if (pNewItems != lpImeMenu) 492 Imm32HeapFree(pNewItems); 493 ImmUnlockImeDpi(pImeDpi); 494 ImmUnlockIMC(hIMC); 495 return ret; 496 } 497 498 /*********************************************************************** 499 * ImmInstallIMEA (IMM32.@) 500 */ 501 HKL WINAPI ImmInstallIMEA(LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText) 502 { 503 HKL hKL = NULL; 504 LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL; 505 506 TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)); 507 508 pszFileNameW = Imm32WideFromAnsi(lpszIMEFileName); 509 if (!pszFileNameW) 510 goto Quit; 511 512 pszLayoutTextW = Imm32WideFromAnsi(lpszLayoutText); 513 if (!pszLayoutTextW) 514 goto Quit; 515 516 hKL = ImmInstallIMEW(pszFileNameW, pszLayoutTextW); 517 518 Quit: 519 Imm32HeapFree(pszFileNameW); 520 Imm32HeapFree(pszLayoutTextW); 521 return hKL; 522 } 523 524 /*********************************************************************** 525 * ImmInstallIMEW (IMM32.@) 526 */ 527 HKL WINAPI ImmInstallIMEW(LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText) 528 { 529 WCHAR szImeFileName[MAX_PATH], szImeDestPath[MAX_PATH], szImeKey[20]; 530 IMEINFOEX InfoEx; 531 LPWSTR pchFilePart; 532 UINT iLayout, cLayouts; 533 HKL hNewKL; 534 WORD wLangID; 535 PREG_IME pLayouts = NULL; 536 537 TRACE("(%s, %s)\n", debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)); 538 539 GetFullPathNameW(lpszIMEFileName, _countof(szImeFileName), szImeFileName, &pchFilePart); 540 CharUpperW(szImeFileName); 541 if (!pchFilePart) 542 return NULL; 543 544 /* Load the IME version info */ 545 InfoEx.hkl = hNewKL = NULL; 546 StringCchCopyW(InfoEx.wszImeFile, _countof(InfoEx.wszImeFile), pchFilePart); 547 if (Imm32LoadImeVerInfo(&InfoEx) && InfoEx.hkl) 548 wLangID = LOWORD(InfoEx.hkl); 549 else 550 return NULL; 551 552 /* Get the IME layouts from registry */ 553 cLayouts = Imm32GetRegImes(NULL, 0); 554 if (cLayouts) 555 { 556 pLayouts = Imm32HeapAlloc(0, cLayouts * sizeof(REG_IME)); 557 if (!pLayouts || !Imm32GetRegImes(pLayouts, cLayouts)) 558 { 559 Imm32HeapFree(pLayouts); 560 return NULL; 561 } 562 563 for (iLayout = 0; iLayout < cLayouts; ++iLayout) 564 { 565 if (lstrcmpiW(pLayouts[iLayout].szFileName, pchFilePart) == 0) 566 { 567 if (wLangID != LOWORD(pLayouts[iLayout].hKL)) 568 goto Quit; /* The language is different */ 569 570 hNewKL = pLayouts[iLayout].hKL; /* Found */ 571 break; 572 } 573 } 574 } 575 576 /* If the IME for the specified filename is valid, then unload it now */ 577 /* FIXME: ImmGetImeInfoEx is broken */ 578 if (ImmGetImeInfoEx(&InfoEx, 3, pchFilePart) && 579 !UnloadKeyboardLayout(InfoEx.hkl)) 580 { 581 hNewKL = NULL; 582 goto Quit; 583 } 584 585 Imm32GetSystemLibraryPath(szImeDestPath, _countof(szImeDestPath), pchFilePart); 586 CharUpperW(szImeDestPath); 587 588 /* If the source and the destination pathnames were different, then copy the IME file */ 589 if (lstrcmpiW(szImeFileName, szImeDestPath) != 0 && 590 !Imm32CopyFile(szImeFileName, szImeDestPath)) 591 { 592 hNewKL = NULL; 593 goto Quit; 594 } 595 596 if (hNewKL == NULL) 597 hNewKL = Imm32GetNextHKL(cLayouts, pLayouts, wLangID); 598 599 if (hNewKL) 600 { 601 /* Write the IME layout to registry */ 602 if (Imm32WriteRegIme(hNewKL, pchFilePart, lpszLayoutText)) 603 { 604 /* Load the keyboard layout */ 605 Imm32UIntToStr((DWORD)(DWORD_PTR)hNewKL, 16, szImeKey, _countof(szImeKey)); 606 hNewKL = LoadKeyboardLayoutW(szImeKey, KLF_REPLACELANG); 607 } 608 else 609 { 610 hNewKL = NULL; 611 } 612 } 613 614 Quit: 615 Imm32HeapFree(pLayouts); 616 return hNewKL; 617 } 618 619 /*********************************************************************** 620 * ImmIsIME (IMM32.@) 621 */ 622 BOOL WINAPI ImmIsIME(HKL hKL) 623 { 624 IMEINFOEX info; 625 TRACE("(%p)\n", hKL); 626 /* FIXME: ImmGetImeInfoEx is broken */ 627 return !!ImmGetImeInfoEx(&info, 1, &hKL); 628 } 629 630 /*********************************************************************** 631 * ImmGetDefaultIMEWnd (IMM32.@) 632 */ 633 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd) 634 { 635 if (!Imm32IsImmMode()) 636 return NULL; 637 638 // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken. 639 if (hWnd == NULL) 640 return (HWND)NtUserGetThreadState(3); 641 642 return (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_IME); 643 } 644 645 /*********************************************************************** 646 * ImmNotifyIME (IMM32.@) 647 */ 648 BOOL WINAPI ImmNotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) 649 { 650 HKL hKL; 651 PIMEDPI pImeDpi; 652 BOOL ret; 653 654 TRACE("(%p, %lu, %lu, %lu)\n", hIMC, dwAction, dwIndex, dwValue); 655 656 if (hIMC && Imm32IsCrossThreadAccess(hIMC)) 657 return FALSE; 658 659 hKL = GetKeyboardLayout(0); 660 pImeDpi = ImmLockImeDpi(hKL); 661 if (pImeDpi == NULL) 662 return FALSE; 663 664 ret = pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue); 665 ImmUnlockImeDpi(pImeDpi); 666 return ret; 667 } 668 669 /*********************************************************************** 670 * ImmDisableLegacyIME(IMM32.@) 671 */ 672 BOOL WINAPI ImmDisableLegacyIME(void) 673 { 674 FIXME("stub\n"); 675 return TRUE; 676 } 677 678 /*********************************************************************** 679 * ImmGetImeInfoEx (IMM32.@) 680 */ 681 BOOL WINAPI 682 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID pvSearchKey) 683 { 684 BOOL bDisabled = FALSE; 685 HKL hKL; 686 687 /* FIXME: broken */ 688 switch (SearchType) 689 { 690 case ImeInfoExKeyboardLayout: 691 break; 692 693 case ImeInfoExImeWindow: 694 bDisabled = CtfImmIsTextFrameServiceDisabled(); 695 SearchType = ImeInfoExKeyboardLayout; 696 break; 697 698 case ImeInfoExImeFileName: 699 StringCchCopyW(pImeInfoEx->wszImeFile, _countof(pImeInfoEx->wszImeFile), 700 pvSearchKey); 701 goto Quit; 702 } 703 704 hKL = *(HKL*)pvSearchKey; 705 pImeInfoEx->hkl = hKL; 706 707 if (!IS_IME_HKL(hKL)) 708 { 709 if (Imm32IsCiceroMode()) 710 { 711 if (Imm32Is16BitMode()) 712 return FALSE; 713 if (!bDisabled) 714 goto Quit; 715 } 716 return FALSE; 717 } 718 719 Quit: 720 return NtUserGetImeInfoEx(pImeInfoEx, SearchType); 721 } 722 723 /*********************************************************************** 724 * ImmLockImeDpi (IMM32.@) 725 */ 726 PIMEDPI WINAPI ImmLockImeDpi(HKL hKL) 727 { 728 PIMEDPI pImeDpi = NULL; 729 730 TRACE("(%p)\n", hKL); 731 732 RtlEnterCriticalSection(&g_csImeDpi); 733 734 /* Find by hKL */ 735 for (pImeDpi = g_pImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext) 736 { 737 if (pImeDpi->hKL == hKL) /* found */ 738 { 739 /* lock if possible */ 740 if (pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN) 741 pImeDpi = NULL; 742 else 743 ++(pImeDpi->cLockObj); 744 break; 745 } 746 } 747 748 RtlLeaveCriticalSection(&g_csImeDpi); 749 return pImeDpi; 750 } 751 752 /*********************************************************************** 753 * ImmUnlockImeDpi (IMM32.@) 754 */ 755 VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi) 756 { 757 PIMEDPI *ppEntry; 758 759 TRACE("(%p)\n", pImeDpi); 760 761 if (pImeDpi == NULL) 762 return; 763 764 RtlEnterCriticalSection(&g_csImeDpi); 765 766 /* unlock */ 767 --(pImeDpi->cLockObj); 768 if (pImeDpi->cLockObj != 0) 769 { 770 RtlLeaveCriticalSection(&g_csImeDpi); 771 return; 772 } 773 774 if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN) == 0) 775 { 776 if ((pImeDpi->dwFlags & IMEDPI_FLAG_LOCKED) == 0 || 777 (pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD) == 0) 778 { 779 RtlLeaveCriticalSection(&g_csImeDpi); 780 return; 781 } 782 } 783 784 /* Remove from list */ 785 for (ppEntry = &g_pImeDpiList; *ppEntry; ppEntry = &((*ppEntry)->pNext)) 786 { 787 if (*ppEntry == pImeDpi) /* found */ 788 { 789 *ppEntry = pImeDpi->pNext; 790 break; 791 } 792 } 793 794 Imm32FreeImeDpi(pImeDpi, TRUE); 795 Imm32HeapFree(pImeDpi); 796 797 RtlLeaveCriticalSection(&g_csImeDpi); 798 } 799 800 /*********************************************************************** 801 * ImmLoadIME (IMM32.@) 802 */ 803 BOOL WINAPI ImmLoadIME(HKL hKL) 804 { 805 PIMEDPI pImeDpi; 806 807 if (!IS_IME_HKL(hKL) && (!Imm32IsCiceroMode() || Imm32Is16BitMode())) 808 return FALSE; 809 810 pImeDpi = Imm32FindImeDpi(hKL); 811 if (pImeDpi == NULL) 812 pImeDpi = Ime32LoadImeDpi(hKL, FALSE); 813 return (pImeDpi != NULL); 814 } 815 816 /*********************************************************************** 817 * ImmDisableIME (IMM32.@) 818 */ 819 BOOL WINAPI ImmDisableIME(DWORD dwThreadId) 820 { 821 return NtUserDisableThreadIme(dwThreadId); 822 } 823 824 /*********************************************************************** 825 * ImmGetDescriptionA (IMM32.@) 826 */ 827 UINT WINAPI ImmGetDescriptionA(HKL hKL, LPSTR lpszDescription, UINT uBufLen) 828 { 829 IMEINFOEX info; 830 size_t cch; 831 832 TRACE("(%p,%p,%d)\n", hKL, lpszDescription, uBufLen); 833 834 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL)) 835 return 0; 836 837 StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch); 838 cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeDescription, (INT)cch, 839 lpszDescription, uBufLen, NULL, NULL); 840 if (uBufLen) 841 lpszDescription[cch] = 0; 842 return (UINT)cch; 843 } 844 845 /*********************************************************************** 846 * ImmGetDescriptionW (IMM32.@) 847 */ 848 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen) 849 { 850 IMEINFOEX info; 851 size_t cch; 852 853 TRACE("(%p, %p, %d)\n", hKL, lpszDescription, uBufLen); 854 855 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL)) 856 return 0; 857 858 if (uBufLen != 0) 859 StringCchCopyW(lpszDescription, uBufLen, info.wszImeDescription); 860 861 StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch); 862 return (UINT)cch; 863 } 864 865 /*********************************************************************** 866 * ImmGetIMEFileNameA (IMM32.@) 867 */ 868 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen) 869 { 870 BOOL bDefUsed; 871 IMEINFOEX info; 872 size_t cch; 873 874 TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen); 875 876 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL)) 877 { 878 if (uBufLen > 0) 879 lpszFileName[0] = 0; 880 return 0; 881 } 882 883 StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch); 884 885 cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeFile, (INT)cch, 886 lpszFileName, uBufLen, NULL, &bDefUsed); 887 if (uBufLen == 0) 888 return (UINT)cch; 889 890 if (cch > uBufLen - 1) 891 cch = uBufLen - 1; 892 893 lpszFileName[cch] = 0; 894 return (UINT)cch; 895 } 896 897 /*********************************************************************** 898 * ImmGetIMEFileNameW (IMM32.@) 899 */ 900 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen) 901 { 902 IMEINFOEX info; 903 size_t cch; 904 905 TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen); 906 907 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL)) 908 { 909 if (uBufLen > 0) 910 lpszFileName[0] = 0; 911 return 0; 912 } 913 914 StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch); 915 if (uBufLen == 0) 916 return (UINT)cch; 917 918 StringCchCopyNW(lpszFileName, uBufLen, info.wszImeFile, cch); 919 920 if (cch > uBufLen - 1) 921 cch = uBufLen - 1; 922 923 lpszFileName[cch] = 0; 924 return (UINT)cch; 925 } 926 927 /*********************************************************************** 928 * ImmGetProperty (IMM32.@) 929 */ 930 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) 931 { 932 IMEINFOEX ImeInfoEx; 933 LPIMEINFO pImeInfo; 934 DWORD dwValue; 935 PIMEDPI pImeDpi = NULL; 936 937 TRACE("(%p, %lu)\n", hKL, fdwIndex); 938 939 if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL)) 940 return FALSE; 941 942 if (fdwIndex == IGP_GETIMEVERSION) 943 return ImeInfoEx.dwImeWinVersion; 944 945 if (ImeInfoEx.fLoadFlag != 2) 946 { 947 pImeDpi = ImmLockOrLoadImeDpi(hKL); 948 if (pImeDpi == NULL) 949 return FALSE; 950 951 pImeInfo = &pImeDpi->ImeInfo; 952 } 953 else 954 { 955 pImeInfo = &ImeInfoEx.ImeInfo; 956 } 957 958 switch (fdwIndex) 959 { 960 case IGP_PROPERTY: dwValue = pImeInfo->fdwProperty; break; 961 case IGP_CONVERSION: dwValue = pImeInfo->fdwConversionCaps; break; 962 case IGP_SENTENCE: dwValue = pImeInfo->fdwSentenceCaps; break; 963 case IGP_UI: dwValue = pImeInfo->fdwUICaps; break; 964 case IGP_SETCOMPSTR: dwValue = pImeInfo->fdwSCSCaps; break; 965 case IGP_SELECT: dwValue = pImeInfo->fdwSelectCaps; break; 966 default: dwValue = 0; break; 967 } 968 969 if (pImeDpi) 970 ImmUnlockImeDpi(pImeDpi); 971 return dwValue; 972 } 973 974 /*********************************************************************** 975 * ImmEscapeA (IMM32.@) 976 */ 977 LRESULT WINAPI ImmEscapeA(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData) 978 { 979 LRESULT ret; 980 PIMEDPI pImeDpi; 981 INT cch; 982 CHAR szA[MAX_IMM_FILENAME]; 983 WCHAR szW[MAX_IMM_FILENAME]; 984 985 TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData); 986 987 pImeDpi = ImmLockOrLoadImeDpi(hKL); 988 if (!pImeDpi) 989 return 0; 990 991 if (!ImeDpi_IsUnicode(pImeDpi) || !lpData) 992 { 993 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 994 ImmUnlockImeDpi(pImeDpi); 995 return ret; 996 } 997 998 switch (uSubFunc) 999 { 1000 case IME_ESC_SEQUENCE_TO_INTERNAL: 1001 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1002 1003 cch = 0; 1004 if (HIWORD(ret)) 1005 szW[cch++] = HIWORD(ret); 1006 if (LOWORD(ret)) 1007 szW[cch++] = LOWORD(ret); 1008 1009 cch = WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, cch, szA, _countof(szA), 1010 NULL, NULL); 1011 switch (cch) 1012 { 1013 case 1: 1014 ret = MAKEWORD(szA[0], 0); 1015 break; 1016 case 2: 1017 ret = MAKEWORD(szA[1], szA[0]); 1018 break; 1019 case 3: 1020 ret = MAKELONG(MAKEWORD(szA[2], szA[1]), MAKEWORD(szA[0], 0)); 1021 break; 1022 case 4: 1023 ret = MAKELONG(MAKEWORD(szA[3], szA[2]), MAKEWORD(szA[1], szA[0])); 1024 break; 1025 default: 1026 ret = 0; 1027 break; 1028 } 1029 break; 1030 1031 case IME_ESC_GET_EUDC_DICTIONARY: 1032 case IME_ESC_IME_NAME: 1033 case IME_ESC_GETHELPFILENAME: 1034 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL); 1035 if (ret) 1036 { 1037 szW[_countof(szW) - 1] = 0; 1038 WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, -1, 1039 lpData, MAX_IMM_FILENAME, NULL, NULL); 1040 ((LPSTR)lpData)[MAX_IMM_FILENAME - 1] = 0; 1041 } 1042 break; 1043 1044 case IME_ESC_SET_EUDC_DICTIONARY: 1045 case IME_ESC_HANJA_MODE: 1046 MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, 1047 lpData, -1, szW, _countof(szW)); 1048 szW[_countof(szW) - 1] = 0; 1049 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL); 1050 break; 1051 1052 default: 1053 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1054 break; 1055 } 1056 1057 ImmUnlockImeDpi(pImeDpi); 1058 return ret; 1059 } 1060 1061 /*********************************************************************** 1062 * ImmEscapeW (IMM32.@) 1063 */ 1064 LRESULT WINAPI ImmEscapeW(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData) 1065 { 1066 LRESULT ret; 1067 PIMEDPI pImeDpi; 1068 INT cch; 1069 CHAR szA[MAX_IMM_FILENAME]; 1070 WCHAR szW[MAX_IMM_FILENAME]; 1071 WORD word; 1072 1073 TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData); 1074 1075 pImeDpi = ImmLockOrLoadImeDpi(hKL); 1076 if (!pImeDpi) 1077 return 0; 1078 1079 if (ImeDpi_IsUnicode(pImeDpi) || !lpData) 1080 { 1081 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1082 ImmUnlockImeDpi(pImeDpi); 1083 return ret; 1084 } 1085 1086 switch (uSubFunc) 1087 { 1088 case IME_ESC_SEQUENCE_TO_INTERNAL: 1089 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1090 1091 word = LOWORD(ret); 1092 cch = 0; 1093 if (HIBYTE(word)) 1094 szA[cch++] = HIBYTE(word); 1095 if (LOBYTE(word)) 1096 szA[cch++] = LOBYTE(word); 1097 1098 cch = MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, 1099 szA, cch, szW, _countof(szW)); 1100 switch (cch) 1101 { 1102 case 1: ret = szW[0]; break; 1103 case 2: ret = MAKELONG(szW[1], szW[0]); break; 1104 default: ret = 0; break; 1105 } 1106 break; 1107 1108 case IME_ESC_GET_EUDC_DICTIONARY: 1109 case IME_ESC_IME_NAME: 1110 case IME_ESC_GETHELPFILENAME: 1111 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL); 1112 if (ret) 1113 { 1114 szA[_countof(szA) - 1] = 0; 1115 MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, 1116 szA, -1, lpData, MAX_IMM_FILENAME); 1117 ((LPWSTR)lpData)[MAX_IMM_FILENAME - 1] = 0; 1118 } 1119 break; 1120 1121 case IME_ESC_SET_EUDC_DICTIONARY: 1122 case IME_ESC_HANJA_MODE: 1123 WideCharToMultiByte(pImeDpi->uCodePage, 0, 1124 lpData, -1, szA, _countof(szA), NULL, NULL); 1125 szA[_countof(szA) - 1] = 0; 1126 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL); 1127 break; 1128 1129 default: 1130 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1131 break; 1132 } 1133 1134 ImmUnlockImeDpi(pImeDpi); 1135 return ret; 1136 } 1137 1138 /*********************************************************************** 1139 * ImmGetOpenStatus (IMM32.@) 1140 */ 1141 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC) 1142 { 1143 BOOL ret; 1144 LPINPUTCONTEXT pIC; 1145 1146 TRACE("(%p)\n", hIMC); 1147 1148 if (!hIMC) 1149 return FALSE; 1150 1151 pIC = ImmLockIMC(hIMC); 1152 if (!pIC) 1153 return FALSE; 1154 1155 ret = pIC->fOpen; 1156 1157 ImmUnlockIMC(hIMC); 1158 return ret; 1159 } 1160 1161 /*********************************************************************** 1162 * ImmSetOpenStatus (IMM32.@) 1163 */ 1164 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) 1165 { 1166 DWORD dwConversion; 1167 LPINPUTCONTEXT pIC; 1168 HWND hWnd; 1169 BOOL bHasChange = FALSE; 1170 1171 TRACE("(%p, %d)\n", hIMC, fOpen); 1172 1173 if (Imm32IsCrossThreadAccess(hIMC)) 1174 return FALSE; 1175 1176 pIC = ImmLockIMC(hIMC); 1177 if (pIC == NULL) 1178 return FALSE; 1179 1180 if (pIC->fOpen != fOpen) 1181 { 1182 pIC->fOpen = fOpen; 1183 hWnd = pIC->hWnd; 1184 dwConversion = pIC->fdwConversion; 1185 bHasChange = TRUE; 1186 } 1187 1188 ImmUnlockIMC(hIMC); 1189 1190 if (bHasChange) 1191 { 1192 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, 1193 IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0); 1194 NtUserNotifyIMEStatus(hWnd, fOpen, dwConversion); 1195 } 1196 1197 return TRUE; 1198 } 1199 1200 /*********************************************************************** 1201 * ImmGetStatusWindowPos (IMM32.@) 1202 */ 1203 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 1204 { 1205 LPINPUTCONTEXT pIC; 1206 BOOL ret; 1207 1208 TRACE("(%p, %p)\n", hIMC, lpptPos); 1209 1210 pIC = ImmLockIMC(hIMC); 1211 if (pIC == NULL) 1212 return FALSE; 1213 1214 ret = !!(pIC->fdwInit & INIT_STATUSWNDPOS); 1215 if (ret) 1216 *lpptPos = pIC->ptStatusWndPos; 1217 1218 ImmUnlockIMC(hIMC); 1219 return ret; 1220 } 1221 1222 /*********************************************************************** 1223 * ImmSetStatusWindowPos (IMM32.@) 1224 */ 1225 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 1226 { 1227 LPINPUTCONTEXT pIC; 1228 HWND hWnd; 1229 1230 TRACE("(%p, {%ld, %ld})\n", hIMC, lpptPos->x, lpptPos->y); 1231 1232 if (Imm32IsCrossThreadAccess(hIMC)) 1233 return FALSE; 1234 1235 pIC = ImmLockIMC(hIMC); 1236 if (!pIC) 1237 return FALSE; 1238 1239 hWnd = pIC->hWnd; 1240 pIC->ptStatusWndPos = *lpptPos; 1241 pIC->fdwInit |= INIT_STATUSWNDPOS; 1242 1243 ImmUnlockIMC(hIMC); 1244 1245 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, 1246 IMC_SETSTATUSWINDOWPOS, IMN_SETSTATUSWINDOWPOS, 0); 1247 return TRUE; 1248 } 1249 1250 /*********************************************************************** 1251 * ImmGetCompositionWindow (IMM32.@) 1252 */ 1253 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 1254 { 1255 LPINPUTCONTEXT pIC; 1256 BOOL ret = FALSE; 1257 1258 TRACE("(%p, %p)\n", hIMC, lpCompForm); 1259 1260 pIC = ImmLockIMC(hIMC); 1261 if (!pIC) 1262 return FALSE; 1263 1264 if (pIC->fdwInit & INIT_COMPFORM) 1265 { 1266 *lpCompForm = pIC->cfCompForm; 1267 ret = TRUE; 1268 } 1269 1270 ImmUnlockIMC(hIMC); 1271 return ret; 1272 } 1273 1274 /*********************************************************************** 1275 * ImmSetCompositionWindow (IMM32.@) 1276 */ 1277 BOOL WINAPI ImmSetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 1278 { 1279 LPINPUTCONTEXT pIC; 1280 HWND hWnd; 1281 1282 if (Imm32IsCrossThreadAccess(hIMC)) 1283 return FALSE; 1284 1285 pIC = ImmLockIMC(hIMC); 1286 if (pIC == NULL) 1287 return FALSE; 1288 1289 pIC->cfCompForm = *lpCompForm; 1290 pIC->fdwInit |= INIT_COMPFORM; 1291 1292 hWnd = pIC->hWnd; 1293 1294 ImmUnlockIMC(hIMC); 1295 1296 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, 1297 IMC_SETCOMPOSITIONWINDOW, IMN_SETCOMPOSITIONWINDOW, 0); 1298 return TRUE; 1299 } 1300 1301 /*********************************************************************** 1302 * ImmGetCompositionFontA (IMM32.@) 1303 */ 1304 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 1305 { 1306 PCLIENTIMC pClientImc; 1307 BOOL ret = FALSE, bWide; 1308 LPINPUTCONTEXT pIC; 1309 1310 TRACE("(%p, %p)\n", hIMC, lplf); 1311 1312 pClientImc = ImmLockClientImc(hIMC); 1313 if (pClientImc == NULL) 1314 return FALSE; 1315 1316 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1317 ImmUnlockClientImc(pClientImc); 1318 1319 pIC = ImmLockIMC(hIMC); 1320 if (pIC == NULL) 1321 return FALSE; 1322 1323 if (pIC->fdwInit & INIT_LOGFONT) 1324 { 1325 if (bWide) 1326 LogFontWideToAnsi(&pIC->lfFont.W, lplf); 1327 else 1328 *lplf = pIC->lfFont.A; 1329 1330 ret = TRUE; 1331 } 1332 1333 ImmUnlockIMC(hIMC); 1334 return ret; 1335 } 1336 1337 /*********************************************************************** 1338 * ImmGetCompositionFontW (IMM32.@) 1339 */ 1340 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 1341 { 1342 PCLIENTIMC pClientImc; 1343 BOOL bWide; 1344 LPINPUTCONTEXT pIC; 1345 BOOL ret = FALSE; 1346 1347 TRACE("(%p, %p)\n", hIMC, lplf); 1348 1349 pClientImc = ImmLockClientImc(hIMC); 1350 if (pClientImc == NULL) 1351 return FALSE; 1352 1353 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1354 ImmUnlockClientImc(pClientImc); 1355 1356 pIC = ImmLockIMC(hIMC); 1357 if (pIC == NULL) 1358 return FALSE; 1359 1360 if (pIC->fdwInit & INIT_LOGFONT) 1361 { 1362 if (bWide) 1363 *lplf = pIC->lfFont.W; 1364 else 1365 LogFontAnsiToWide(&pIC->lfFont.A, lplf); 1366 1367 ret = TRUE; 1368 } 1369 1370 ImmUnlockIMC(hIMC); 1371 return ret; 1372 } 1373 1374 /*********************************************************************** 1375 * ImmSetCompositionFontA (IMM32.@) 1376 */ 1377 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 1378 { 1379 LOGFONTW lfW; 1380 PCLIENTIMC pClientImc; 1381 BOOL bWide; 1382 LPINPUTCONTEXTDX pIC; 1383 LCID lcid; 1384 HWND hWnd; 1385 PTEB pTeb; 1386 1387 TRACE("(%p, %p)\n", hIMC, lplf); 1388 1389 if (Imm32IsCrossThreadAccess(hIMC)) 1390 return FALSE; 1391 1392 pClientImc = ImmLockClientImc(hIMC); 1393 if (pClientImc == NULL) 1394 return FALSE; 1395 1396 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1397 ImmUnlockClientImc(pClientImc); 1398 1399 if (bWide) 1400 { 1401 LogFontAnsiToWide(lplf, &lfW); 1402 return ImmSetCompositionFontW(hIMC, &lfW); 1403 } 1404 1405 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 1406 if (pIC == NULL) 1407 return FALSE; 1408 1409 pTeb = NtCurrentTeb(); 1410 if (pTeb->Win32ClientInfo[2] < 0x400) 1411 { 1412 lcid = GetSystemDefaultLCID(); 1413 if (PRIMARYLANGID(lcid) == LANG_JAPANESE && !(pIC->dwUIFlags & 2) && 1414 pIC->cfCompForm.dwStyle != CFS_DEFAULT) 1415 { 1416 PostMessageA(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0); 1417 } 1418 } 1419 1420 pIC->lfFont.A = *lplf; 1421 pIC->fdwInit |= INIT_LOGFONT; 1422 hWnd = pIC->hWnd; 1423 1424 ImmUnlockIMC(hIMC); 1425 1426 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT, 1427 IMN_SETCOMPOSITIONFONT, 0); 1428 return TRUE; 1429 } 1430 1431 /*********************************************************************** 1432 * ImmSetCompositionFontW (IMM32.@) 1433 */ 1434 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 1435 { 1436 LOGFONTA lfA; 1437 PCLIENTIMC pClientImc; 1438 BOOL bWide; 1439 HWND hWnd; 1440 LPINPUTCONTEXTDX pIC; 1441 PTEB pTeb; 1442 LCID lcid; 1443 1444 TRACE("(%p, %p)\n", hIMC, lplf); 1445 1446 if (Imm32IsCrossThreadAccess(hIMC)) 1447 return FALSE; 1448 1449 pClientImc = ImmLockClientImc(hIMC); 1450 if (pClientImc == NULL) 1451 return FALSE; 1452 1453 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1454 ImmUnlockClientImc(pClientImc); 1455 1456 if (!bWide) 1457 { 1458 LogFontWideToAnsi(lplf, &lfA); 1459 return ImmSetCompositionFontA(hIMC, &lfA); 1460 } 1461 1462 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 1463 if (pIC == NULL) 1464 return FALSE; 1465 1466 pTeb = NtCurrentTeb(); 1467 if (pTeb->Win32ClientInfo[2] < 0x400) 1468 { 1469 lcid = GetSystemDefaultLCID(); 1470 if (PRIMARYLANGID(lcid) == LANG_JAPANESE && 1471 !(pIC->dwUIFlags & 2) && 1472 pIC->cfCompForm.dwStyle != CFS_DEFAULT) 1473 { 1474 PostMessageW(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0); 1475 } 1476 } 1477 1478 pIC->lfFont.W = *lplf; 1479 pIC->fdwInit |= INIT_LOGFONT; 1480 hWnd = pIC->hWnd; 1481 1482 ImmUnlockIMC(hIMC); 1483 1484 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT, 1485 IMN_SETCOMPOSITIONFONT, 0); 1486 return TRUE; 1487 } 1488 1489 /*********************************************************************** 1490 * ImmGetConversionListA (IMM32.@) 1491 */ 1492 DWORD WINAPI 1493 ImmGetConversionListA(HKL hKL, HIMC hIMC, LPCSTR pSrc, LPCANDIDATELIST lpDst, 1494 DWORD dwBufLen, UINT uFlag) 1495 { 1496 DWORD ret = 0; 1497 UINT cb; 1498 LPWSTR pszSrcW = NULL; 1499 LPCANDIDATELIST pCL = NULL; 1500 PIMEDPI pImeDpi; 1501 1502 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_a(pSrc), 1503 lpDst, dwBufLen, uFlag); 1504 1505 pImeDpi = ImmLockOrLoadImeDpi(hKL); 1506 if (pImeDpi == NULL) 1507 return 0; 1508 1509 if (!ImeDpi_IsUnicode(pImeDpi)) 1510 { 1511 ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag); 1512 ImmUnlockImeDpi(pImeDpi); 1513 return ret; 1514 } 1515 1516 if (pSrc) 1517 { 1518 pszSrcW = Imm32WideFromAnsi(pSrc); 1519 if (pszSrcW == NULL) 1520 goto Quit; 1521 } 1522 1523 cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, NULL, 0, uFlag); 1524 if (cb == 0) 1525 goto Quit; 1526 1527 pCL = Imm32HeapAlloc(0, cb); 1528 if (pCL == NULL) 1529 goto Quit; 1530 1531 cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, pCL, cb, uFlag); 1532 if (cb == 0) 1533 goto Quit; 1534 1535 ret = CandidateListWideToAnsi(pCL, lpDst, dwBufLen, CP_ACP); 1536 1537 Quit: 1538 Imm32HeapFree(pszSrcW); 1539 Imm32HeapFree(pCL); 1540 ImmUnlockImeDpi(pImeDpi); 1541 return ret; 1542 } 1543 1544 /*********************************************************************** 1545 * ImmGetConversionListW (IMM32.@) 1546 */ 1547 DWORD WINAPI 1548 ImmGetConversionListW(HKL hKL, HIMC hIMC, LPCWSTR pSrc, LPCANDIDATELIST lpDst, 1549 DWORD dwBufLen, UINT uFlag) 1550 { 1551 DWORD ret = 0; 1552 INT cb; 1553 PIMEDPI pImeDpi; 1554 LPCANDIDATELIST pCL = NULL; 1555 LPSTR pszSrcA = NULL; 1556 1557 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_w(pSrc), 1558 lpDst, dwBufLen, uFlag); 1559 1560 pImeDpi = ImmLockOrLoadImeDpi(hKL); 1561 if (!pImeDpi) 1562 return 0; 1563 1564 if (ImeDpi_IsUnicode(pImeDpi)) 1565 { 1566 ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag); 1567 ImmUnlockImeDpi(pImeDpi); 1568 return ret; 1569 } 1570 1571 if (pSrc) 1572 { 1573 pszSrcA = Imm32AnsiFromWide(pSrc); 1574 if (pszSrcA == NULL) 1575 goto Quit; 1576 } 1577 1578 cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, NULL, 0, uFlag); 1579 if (cb == 0) 1580 goto Quit; 1581 1582 pCL = Imm32HeapAlloc(0, cb); 1583 if (!pCL) 1584 goto Quit; 1585 1586 cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, pCL, cb, uFlag); 1587 if (!cb) 1588 goto Quit; 1589 1590 ret = CandidateListAnsiToWide(pCL, lpDst, dwBufLen, CP_ACP); 1591 1592 Quit: 1593 Imm32HeapFree(pszSrcA); 1594 Imm32HeapFree(pCL); 1595 ImmUnlockImeDpi(pImeDpi); 1596 return ret; 1597 } 1598 1599 /*********************************************************************** 1600 * ImmGetConversionStatus (IMM32.@) 1601 */ 1602 BOOL WINAPI ImmGetConversionStatus(HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence) 1603 { 1604 LPINPUTCONTEXT pIC; 1605 1606 TRACE("(%p %p %p)\n", hIMC, lpfdwConversion, lpfdwSentence); 1607 1608 pIC = ImmLockIMC(hIMC); 1609 if (!pIC) 1610 return FALSE; 1611 1612 if (lpfdwConversion) 1613 *lpfdwConversion = pIC->fdwConversion; 1614 if (lpfdwSentence) 1615 *lpfdwSentence = pIC->fdwSentence; 1616 1617 ImmUnlockIMC(hIMC); 1618 return TRUE; 1619 } 1620 1621 /*********************************************************************** 1622 * ImmSetConversionStatus (IMM32.@) 1623 */ 1624 BOOL WINAPI ImmSetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) 1625 { 1626 HKL hKL; 1627 LPINPUTCONTEXT pIC; 1628 DWORD dwOldConversion, dwOldSentence; 1629 BOOL fOpen = FALSE, fConversionChange = FALSE, fSentenceChange = FALSE, fUseCicero = FALSE; 1630 HWND hWnd; 1631 1632 TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC, fdwConversion, fdwSentence); 1633 1634 hKL = GetKeyboardLayout(0); 1635 if (!IS_IME_HKL(hKL) && Imm32IsCiceroMode() && !Imm32Is16BitMode()) 1636 fUseCicero = TRUE; 1637 1638 if (Imm32IsCrossThreadAccess(hIMC)) 1639 return FALSE; 1640 1641 pIC = ImmLockIMC(hIMC); 1642 if (pIC == NULL) 1643 return FALSE; 1644 1645 if (pIC->fdwConversion != fdwConversion) 1646 { 1647 dwOldConversion = pIC->fdwConversion; 1648 pIC->fdwConversion = fdwConversion; 1649 fConversionChange = TRUE; 1650 } 1651 1652 if (pIC->fdwSentence != fdwSentence) 1653 { 1654 dwOldSentence = pIC->fdwSentence; 1655 pIC->fdwSentence = fdwSentence; 1656 fSentenceChange = TRUE; 1657 } 1658 1659 hWnd = pIC->hWnd; 1660 fOpen = pIC->fOpen; 1661 ImmUnlockIMC(hIMC); 1662 1663 if (fConversionChange || fUseCicero) 1664 { 1665 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldConversion, 1666 IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0); 1667 if (fConversionChange) 1668 NtUserNotifyIMEStatus(hWnd, fOpen, fdwConversion); 1669 } 1670 1671 if (fSentenceChange || fUseCicero) 1672 { 1673 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldSentence, 1674 IMC_SETSENTENCEMODE, IMN_SETSENTENCEMODE, 0); 1675 } 1676 1677 return TRUE; 1678 } 1679 1680 /*********************************************************************** 1681 * ImmConfigureIMEA (IMM32.@) 1682 */ 1683 BOOL WINAPI ImmConfigureIMEA(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 1684 { 1685 BOOL ret = FALSE; 1686 PIMEDPI pImeDpi; 1687 REGISTERWORDW RegWordW; 1688 LPREGISTERWORDA pRegWordA; 1689 1690 TRACE("(%p, %p, 0x%lX, %p)", hKL, hWnd, dwMode, lpData); 1691 1692 if (!ValidateHwndNoErr(hWnd) || Imm32IsCrossProcessAccess(hWnd)) 1693 return FALSE; 1694 1695 pImeDpi = ImmLockOrLoadImeDpi(hKL); 1696 if (!pImeDpi) 1697 return FALSE; 1698 1699 RtlZeroMemory(&RegWordW, sizeof(RegWordW)); 1700 1701 if (!ImeDpi_IsUnicode(pImeDpi) || !lpData || dwMode != IME_CONFIG_REGISTERWORD) 1702 goto DoIt; 1703 1704 pRegWordA = lpData; 1705 1706 if (pRegWordA->lpReading) 1707 { 1708 RegWordW.lpReading = Imm32WideFromAnsi(pRegWordA->lpReading); 1709 if (!RegWordW.lpReading) 1710 goto Quit; 1711 } 1712 1713 if (pRegWordA->lpWord) 1714 { 1715 RegWordW.lpWord = Imm32WideFromAnsi(pRegWordA->lpWord); 1716 if (!RegWordW.lpWord) 1717 goto Quit; 1718 } 1719 1720 lpData = &RegWordW; 1721 1722 DoIt: 1723 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1B, 0); 1724 ret = pImeDpi->ImeConfigure(hKL, hWnd, dwMode, lpData); 1725 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1A, 0); 1726 1727 Quit: 1728 Imm32HeapFree(RegWordW.lpReading); 1729 Imm32HeapFree(RegWordW.lpWord); 1730 ImmUnlockImeDpi(pImeDpi); 1731 return ret; 1732 } 1733 1734 /*********************************************************************** 1735 * ImmConfigureIMEW (IMM32.@) 1736 */ 1737 BOOL WINAPI ImmConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 1738 { 1739 BOOL ret = FALSE; 1740 PIMEDPI pImeDpi; 1741 REGISTERWORDA RegWordA; 1742 LPREGISTERWORDW pRegWordW; 1743 1744 TRACE("(%p, %p, 0x%lX, %p)", hKL, hWnd, dwMode, lpData); 1745 1746 if (!ValidateHwndNoErr(hWnd) || Imm32IsCrossProcessAccess(hWnd)) 1747 return FALSE; 1748 1749 pImeDpi = ImmLockOrLoadImeDpi(hKL); 1750 if (!pImeDpi) 1751 return FALSE; 1752 1753 RtlZeroMemory(&RegWordA, sizeof(RegWordA)); 1754 1755 if (ImeDpi_IsUnicode(pImeDpi) || !lpData || dwMode != IME_CONFIG_REGISTERWORD) 1756 goto DoIt; 1757 1758 pRegWordW = lpData; 1759 1760 if (pRegWordW->lpReading) 1761 { 1762 RegWordA.lpReading = Imm32AnsiFromWide(pRegWordW->lpReading); 1763 if (!RegWordA.lpReading) 1764 goto Quit; 1765 } 1766 1767 if (pRegWordW->lpWord) 1768 { 1769 RegWordA.lpWord = Imm32AnsiFromWide(pRegWordW->lpWord); 1770 if (!RegWordA.lpWord) 1771 goto Quit; 1772 } 1773 1774 lpData = &RegWordA; 1775 1776 DoIt: 1777 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1B, 0); 1778 ret = pImeDpi->ImeConfigure(hKL, hWnd, dwMode, lpData); 1779 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1A, 0); 1780 1781 Quit: 1782 Imm32HeapFree(RegWordA.lpReading); 1783 Imm32HeapFree(RegWordA.lpWord); 1784 ImmUnlockImeDpi(pImeDpi); 1785 return ret; 1786 } 1787 1788 /*********************************************************************** 1789 * ImmGetImeMenuItemsA (IMM32.@) 1790 */ 1791 DWORD WINAPI 1792 ImmGetImeMenuItemsA(HIMC hIMC, DWORD dwFlags, DWORD dwType, 1793 LPIMEMENUITEMINFOA lpImeParentMenu, 1794 LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize) 1795 { 1796 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", 1797 hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize); 1798 return Imm32GetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, 1799 dwSize, TRUE); 1800 } 1801 1802 /*********************************************************************** 1803 * ImmGetImeMenuItemsW (IMM32.@) 1804 */ 1805 DWORD WINAPI 1806 ImmGetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType, 1807 LPIMEMENUITEMINFOW lpImeParentMenu, 1808 LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize) 1809 { 1810 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", 1811 hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize); 1812 return Imm32GetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, 1813 dwSize, FALSE); 1814 } 1815