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