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 (GetWin32ClientInfo()->dwTIFlags & TIF_16BIT) 58 dwSysInfoFlags |= IME_SYSINFO_WOW16; 59 60 if (IS_IME_HKL(pImeDpi->hKL)) 61 { 62 if (!pImeDpi->ImeInquire(pImeInfo, szUIClass, dwSysInfoFlags)) 63 { 64 ERR("\n"); 65 return FALSE; 66 } 67 } 68 else if (IS_CICERO_MODE() && !IS_16BIT_MODE()) 69 { 70 if (!pImeDpi->CtfImeInquireExW(pImeInfo, szUIClass, dwSysInfoFlags, pImeDpi->hKL)) 71 { 72 ERR("\n"); 73 return FALSE; 74 } 75 } 76 else 77 { 78 ERR("\n"); 79 return FALSE; 80 } 81 82 szUIClass[_countof(szUIClass) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 83 84 if (pImeInfo->dwPrivateDataSize < sizeof(DWORD)) 85 pImeInfo->dwPrivateDataSize = sizeof(DWORD); 86 87 #define VALID_IME_PROP (IME_PROP_AT_CARET | \ 88 IME_PROP_SPECIAL_UI | \ 89 IME_PROP_CANDLIST_START_FROM_1 | \ 90 IME_PROP_UNICODE | \ 91 IME_PROP_COMPLETE_ON_UNSELECT | \ 92 IME_PROP_END_UNLOAD | \ 93 IME_PROP_KBD_CHAR_FIRST | \ 94 IME_PROP_IGNORE_UPKEYS | \ 95 IME_PROP_NEED_ALTKEY | \ 96 IME_PROP_NO_KEYS_ON_CLOSE | \ 97 IME_PROP_ACCEPT_WIDE_VKEY) 98 #define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \ 99 IME_CMODE_NATIVE | \ 100 IME_CMODE_KATAKANA | \ 101 IME_CMODE_LANGUAGE | \ 102 IME_CMODE_FULLSHAPE | \ 103 IME_CMODE_ROMAN | \ 104 IME_CMODE_CHARCODE | \ 105 IME_CMODE_HANJACONVERT | \ 106 IME_CMODE_SOFTKBD | \ 107 IME_CMODE_NOCONVERSION | \ 108 IME_CMODE_EUDC | \ 109 IME_CMODE_SYMBOL | \ 110 IME_CMODE_FIXED) 111 #define VALID_SMODE_CAPS (IME_SMODE_NONE | \ 112 IME_SMODE_PLAURALCLAUSE | \ 113 IME_SMODE_SINGLECONVERT | \ 114 IME_SMODE_AUTOMATIC | \ 115 IME_SMODE_PHRASEPREDICT | \ 116 IME_SMODE_CONVERSATION) 117 #define VALID_UI_CAPS (UI_CAP_2700 | \ 118 UI_CAP_ROT90 | \ 119 UI_CAP_ROTANY | \ 120 UI_CAP_SOFTKBD) 121 #define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \ 122 SCS_CAP_MAKEREAD | \ 123 SCS_CAP_SETRECONVERTSTRING) 124 #define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE) 125 126 if (pImeInfo->fdwProperty & ~VALID_IME_PROP) 127 { 128 ERR("Bad flags\n"); 129 return FALSE; 130 } 131 if (pImeInfo->fdwConversionCaps & ~VALID_CMODE_CAPS) 132 { 133 ERR("Bad flags\n"); 134 return FALSE; 135 } 136 if (pImeInfo->fdwSentenceCaps & ~VALID_SMODE_CAPS) 137 { 138 ERR("Bad flags\n"); 139 return FALSE; 140 } 141 if (pImeInfo->fdwUICaps & ~VALID_UI_CAPS) 142 { 143 ERR("Bad flags\n"); 144 return FALSE; 145 } 146 if (pImeInfo->fdwSCSCaps & ~VALID_SCS_CAPS) 147 { 148 ERR("Bad flags\n"); 149 return FALSE; 150 } 151 if (pImeInfo->fdwSelectCaps & ~VALID_SELECT_CAPS) 152 { 153 ERR("Bad flags\n"); 154 return FALSE; 155 } 156 157 #undef VALID_IME_PROP 158 #undef VALID_CMODE_CAPS 159 #undef VALID_SMODE_CAPS 160 #undef VALID_UI_CAPS 161 #undef VALID_SCS_CAPS 162 #undef VALID_SELECT_CAPS 163 164 if (pImeInfo->fdwProperty & IME_PROP_UNICODE) 165 { 166 StringCchCopyW(pImeDpi->szUIClass, _countof(pImeDpi->szUIClass), szUIClass); 167 } 168 else 169 { 170 if (pImeDpi->uCodePage != GetACP() && pImeDpi->uCodePage != CP_ACP) 171 return FALSE; 172 173 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPSTR)szUIClass, -1, 174 pImeDpi->szUIClass, _countof(pImeDpi->szUIClass)); 175 176 pImeDpi->szUIClass[_countof(pImeDpi->szUIClass) - 1] = UNICODE_NULL; 177 } 178 179 if (!GetClassInfoW(pImeDpi->hInst, pImeDpi->szUIClass, &wcW)) 180 { 181 ERR("\n"); 182 return FALSE; 183 } 184 185 return TRUE; 186 } 187 188 /* Define stub IME functions */ 189 #define DEFINE_IME_ENTRY(type, name, params, optional) \ 190 type APIENTRY Stub##name params { \ 191 FIXME("%s: Why stub called?\n", #name); \ 192 return (type)0; \ 193 } 194 #include "imetable.h" 195 #undef DEFINE_IME_ENTRY 196 197 // Win: LoadIME 198 BOOL APIENTRY Imm32LoadIME(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi) 199 { 200 WCHAR szPath[MAX_PATH]; 201 HINSTANCE hIME; 202 FARPROC fn; 203 BOOL ret = FALSE; 204 205 if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile)) 206 return FALSE; 207 208 pImeDpi->hInst = hIME = LoadLibraryW(szPath); 209 if (hIME == NULL) 210 { 211 ERR("LoadLibraryW(%s) failed\n", debugstr_w(szPath)); 212 return FALSE; 213 } 214 215 /* Populate the table by stub IME functions */ 216 #define DEFINE_IME_ENTRY(type, name, params, optional) pImeDpi->name = Stub##name; 217 #include "imetable.h" 218 #undef DEFINE_IME_ENTRY 219 220 /* Populate the table by real IME functions */ 221 #define DEFINE_IME_ENTRY(type, name, params, optional) \ 222 do { \ 223 fn = GetProcAddress(hIME, #name); \ 224 if (fn) pImeDpi->name = (FN_##name)fn; \ 225 else if (!(optional)) { \ 226 ERR("'%s' not found in IME module '%s'.\n", #name, debugstr_w(szPath)); \ 227 goto Failed; \ 228 } \ 229 } while (0); 230 #include "imetable.h" 231 #undef DEFINE_IME_ENTRY 232 233 if (Imm32InquireIme(pImeDpi)) 234 { 235 ret = TRUE; 236 } 237 else 238 { 239 Failed: 240 ret = FALSE; 241 FreeLibrary(pImeDpi->hInst); 242 pImeDpi->hInst = NULL; 243 } 244 245 if (pImeInfoEx->fLoadFlag == 0) 246 { 247 if (ret) 248 { 249 C_ASSERT(sizeof(pImeInfoEx->wszUIClass) == sizeof(pImeDpi->szUIClass)); 250 pImeInfoEx->ImeInfo = pImeDpi->ImeInfo; 251 RtlCopyMemory(pImeInfoEx->wszUIClass, pImeDpi->szUIClass, 252 sizeof(pImeInfoEx->wszUIClass)); 253 pImeInfoEx->fLoadFlag = 2; 254 } 255 else 256 { 257 pImeInfoEx->fLoadFlag = 1; 258 } 259 260 NtUserSetImeInfoEx(pImeInfoEx); 261 } 262 263 return ret; 264 } 265 266 // Win: LoadImeDpi 267 PIMEDPI APIENTRY Imm32LoadImeDpi(HKL hKL, BOOL bLock) 268 { 269 IMEINFOEX ImeInfoEx; 270 CHARSETINFO ci; 271 PIMEDPI pImeDpiNew, pImeDpiFound; 272 UINT uCodePage; 273 LCID lcid; 274 275 if (!IS_IME_HKL(hKL)) 276 { 277 TRACE("\n"); 278 return NULL; 279 } 280 281 if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL)) 282 { 283 ERR("\n"); 284 return NULL; 285 } 286 287 if (ImeInfoEx.fLoadFlag == 1) 288 { 289 ERR("\n"); 290 return NULL; 291 } 292 293 pImeDpiNew = ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(IMEDPI)); 294 if (IS_NULL_UNEXPECTEDLY(pImeDpiNew)) 295 return NULL; 296 297 pImeDpiNew->hKL = hKL; 298 299 lcid = LOWORD(hKL); 300 if (TranslateCharsetInfo((LPDWORD)(DWORD_PTR)lcid, &ci, TCI_SRCLOCALE)) 301 uCodePage = ci.ciACP; 302 else 303 uCodePage = CP_ACP; 304 pImeDpiNew->uCodePage = uCodePage; 305 306 if (!Imm32LoadIME(&ImeInfoEx, pImeDpiNew)) 307 { 308 ERR("\n"); 309 ImmLocalFree(pImeDpiNew); 310 return FALSE; 311 } 312 313 RtlEnterCriticalSection(&gcsImeDpi); 314 315 pImeDpiFound = Imm32FindImeDpi(hKL); 316 if (pImeDpiFound) 317 { 318 if (!bLock) 319 pImeDpiFound->dwFlags &= ~IMEDPI_FLAG_LOCKED; 320 321 RtlLeaveCriticalSection(&gcsImeDpi); 322 Imm32FreeIME(pImeDpiNew, FALSE); 323 ImmLocalFree(pImeDpiNew); 324 return pImeDpiFound; 325 } 326 else 327 { 328 if (bLock) 329 { 330 pImeDpiNew->dwFlags |= IMEDPI_FLAG_LOCKED; 331 pImeDpiNew->cLockObj = 1; 332 } 333 334 pImeDpiNew->pNext = gpImeDpiList; 335 gpImeDpiList = pImeDpiNew; 336 337 RtlLeaveCriticalSection(&gcsImeDpi); 338 return pImeDpiNew; 339 } 340 } 341 342 // Win: FindOrLoadImeDpi 343 PIMEDPI APIENTRY Imm32FindOrLoadImeDpi(HKL hKL) 344 { 345 PIMEDPI pImeDpi; 346 347 if (!IS_IME_HKL(hKL) && (!IS_CICERO_MODE() || IS_16BIT_MODE())) 348 { 349 TRACE("\n"); 350 return NULL; 351 } 352 353 pImeDpi = ImmLockImeDpi(hKL); 354 if (pImeDpi == NULL) 355 pImeDpi = Imm32LoadImeDpi(hKL, TRUE); 356 return pImeDpi; 357 } 358 359 static LRESULT APIENTRY 360 ImeDpi_Escape(PIMEDPI pImeDpi, HIMC hIMC, UINT uSubFunc, LPVOID lpData, HKL hKL) 361 { 362 if (IS_IME_HKL(hKL)) 363 return pImeDpi->ImeEscape(hIMC, uSubFunc, lpData); 364 if (IS_CICERO_MODE() && !IS_16BIT_MODE()) 365 return pImeDpi->CtfImeEscapeEx(hIMC, uSubFunc, lpData, hKL); 366 367 return 0; 368 } 369 370 // Win: ImmUnloadIME 371 BOOL APIENTRY Imm32ReleaseIME(HKL hKL) 372 { 373 BOOL ret = TRUE; 374 PIMEDPI pImeDpi0, pImeDpi1; 375 376 RtlEnterCriticalSection(&gcsImeDpi); 377 378 for (pImeDpi0 = gpImeDpiList; pImeDpi0; pImeDpi0 = pImeDpi0->pNext) 379 { 380 if (pImeDpi0->hKL == hKL) 381 break; 382 } 383 384 if (!pImeDpi0) 385 goto Quit; 386 387 if (pImeDpi0->cLockObj) 388 { 389 pImeDpi0->dwFlags |= IMEDPI_FLAG_UNLOADED; 390 ret = FALSE; 391 goto Quit; 392 } 393 394 if (gpImeDpiList == pImeDpi0) 395 { 396 gpImeDpiList = pImeDpi0->pNext; 397 } 398 else if (gpImeDpiList) 399 { 400 for (pImeDpi1 = gpImeDpiList; pImeDpi1; pImeDpi1 = pImeDpi1->pNext) 401 { 402 if (pImeDpi1->pNext == pImeDpi0) 403 { 404 pImeDpi1->pNext = pImeDpi0->pNext; 405 break; 406 } 407 } 408 } 409 410 Imm32FreeIME(pImeDpi0, TRUE); 411 ImmLocalFree(pImeDpi0); 412 413 Quit: 414 RtlLeaveCriticalSection(&gcsImeDpi); 415 return ret; 416 } 417 418 // We will transport the IME menu items by using a flat memory block via 419 // a file mapping object beyond the boundary of a process. 420 421 #define MAX_IMEMENU_BITMAP_BYTES 0xF00 422 423 typedef struct tagIMEMENUITEM 424 { 425 IMEMENUITEMINFOW Info; 426 BYTE abChecked[MAX_IMEMENU_BITMAP_BYTES]; 427 BYTE abUnchecked[MAX_IMEMENU_BITMAP_BYTES]; 428 BYTE abItem[MAX_IMEMENU_BITMAP_BYTES]; 429 } IMEMENUITEM, *PIMEMENUITEM; 430 431 typedef struct tagIMEMENU 432 { 433 DWORD dwVersion; 434 DWORD dwFlags; 435 DWORD dwType; 436 DWORD dwItemCount; 437 IMEMENUITEMINFOW Parent; 438 IMEMENUITEM Items[ANYSIZE_ARRAY]; 439 } IMEMENU, *PIMEMENU; 440 441 /*********************************************************************** 442 * ImmPutImeMenuItemsIntoMappedFile (IMM32.@) 443 * 444 * Called from user32.dll to transport the IME menu items by using a 445 * file mapping object. This function is provided for WM_IME_SYSTEM:IMS_GETIMEMENU 446 * handling. 447 */ 448 LRESULT WINAPI ImmPutImeMenuItemsIntoMappedFile(HIMC hIMC) 449 { 450 LRESULT ret = FALSE; 451 HANDLE hMapping; 452 PIMEMENU pView; 453 LPIMEMENUITEMINFOW pParent = NULL, pItems = NULL; 454 DWORD i, cItems, cbItems = 0; 455 456 hMapping = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, L"ImmMenuInfo"); 457 pView = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); 458 if (IS_NULL_UNEXPECTEDLY(pView)) 459 goto Quit; 460 461 if (pView->dwVersion != 1) 462 { 463 ERR("\n"); 464 goto Quit; 465 } 466 467 if (pView->Parent.cbSize > 0) 468 pParent = &pView->Parent; 469 470 if (pView->dwItemCount > 0) 471 { 472 cbItems = pView->dwItemCount * sizeof(IMEMENUITEMINFOW); 473 pItems = ImmLocalAlloc(HEAP_ZERO_MEMORY, cbItems); 474 if (IS_NULL_UNEXPECTEDLY(pItems)) 475 goto Quit; 476 } 477 478 cItems = ImmGetImeMenuItemsW(hIMC, pView->dwFlags, pView->dwType, pParent, pItems, cbItems); 479 pView->dwItemCount = cItems; 480 if (IS_ZERO_UNEXPECTEDLY(cItems)) 481 goto Quit; 482 483 if (pItems) 484 { 485 for (i = 0; i < cItems; ++i) 486 { 487 pView->Items[i].Info = pItems[i]; 488 489 // store bitmaps to bytes 490 if (pItems[i].hbmpChecked) 491 { 492 Imm32StoreBitmapToBytes(pItems[i].hbmpChecked, pView->Items[i].abChecked, 493 MAX_IMEMENU_BITMAP_BYTES); 494 DeleteObject(pItems[i].hbmpChecked); 495 } 496 if (pItems[i].hbmpUnchecked) 497 { 498 Imm32StoreBitmapToBytes(pItems[i].hbmpUnchecked, pView->Items[i].abUnchecked, 499 MAX_IMEMENU_BITMAP_BYTES); 500 DeleteObject(pItems[i].hbmpUnchecked); 501 } 502 if (pItems[i].hbmpItem) 503 { 504 Imm32StoreBitmapToBytes(pItems[i].hbmpItem, pView->Items[i].abItem, 505 MAX_IMEMENU_BITMAP_BYTES); 506 DeleteObject(pItems[i].hbmpItem); 507 } 508 } 509 } 510 511 ret = TRUE; 512 513 Quit: 514 if (pItems) 515 ImmLocalFree(pItems); 516 if (pView) 517 UnmapViewOfFile(pView); 518 if (hMapping) 519 CloseHandle(hMapping); 520 return ret; 521 } 522 523 // Win: ImmGetImeMenuItemsInterProcess 524 DWORD APIENTRY 525 Imm32GetImeMenuItemWInterProcess(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu, 526 LPVOID lpImeMenu, DWORD dwSize) 527 { 528 HANDLE hMapping; 529 PIMEMENU pView; 530 DWORD i, cbView, dwItemCount, ret = 0; 531 HWND hImeWnd; 532 PIMEMENUITEM pGotItem; 533 LPIMEMENUITEMINFOW pSetInfo; 534 535 hImeWnd = (HWND)NtUserQueryInputContext(hIMC, QIC_DEFAULTWINDOWIME); 536 if (!hImeWnd || !IsWindow(hImeWnd)) 537 { 538 ERR("\n"); 539 return 0; 540 } 541 542 dwItemCount = (lpImeMenu ? (dwSize / sizeof(IMEMENUITEMINFOW)) : 0); 543 cbView = sizeof(IMEMENU) + ((size_t)dwItemCount - 1) * sizeof(IMEMENUITEM); 544 545 RtlEnterCriticalSection(&gcsImeDpi); 546 547 // create a file mapping 548 hMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 549 0, cbView, L"ImmMenuInfo"); 550 pView = MapViewOfFile(hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); 551 if (IS_NULL_UNEXPECTEDLY(pView)) 552 goto Quit; 553 554 ZeroMemory(pView, cbView); 555 pView->dwVersion = 1; 556 pView->dwFlags = dwFlags; 557 pView->dwType = dwType; 558 pView->dwItemCount = dwItemCount; 559 if (lpImeParentMenu) 560 { 561 pView->Parent = *(LPIMEMENUITEMINFOW)lpImeParentMenu; 562 pView->Parent.cbSize = sizeof(IMEMENUITEMINFOW); 563 } 564 565 if (!SendMessageW(hImeWnd, WM_IME_SYSTEM, IMS_GETIMEMENU, (LPARAM)hIMC)) 566 { 567 ERR("\n"); 568 goto Quit; 569 } 570 571 ret = pView->dwItemCount; 572 573 if (!lpImeMenu) 574 goto Quit; 575 576 for (i = 0; i < ret; ++i) 577 { 578 pGotItem = &(pView->Items[i]); 579 pSetInfo = &((LPIMEMENUITEMINFOW)lpImeMenu)[i]; 580 581 *pSetInfo = pGotItem->Info; 582 583 // load bitmaps from bytes 584 if (pSetInfo->hbmpChecked) 585 { 586 pSetInfo->hbmpChecked = Imm32LoadBitmapFromBytes(pGotItem->abChecked); 587 } 588 if (pSetInfo->hbmpUnchecked) 589 { 590 pSetInfo->hbmpUnchecked = Imm32LoadBitmapFromBytes(pGotItem->abUnchecked); 591 } 592 if (pSetInfo->hbmpItem) 593 { 594 pSetInfo->hbmpItem = Imm32LoadBitmapFromBytes(pGotItem->abItem); 595 } 596 } 597 598 Quit: 599 RtlLeaveCriticalSection(&gcsImeDpi); 600 if (pView) 601 UnmapViewOfFile(pView); 602 if (hMapping) 603 CloseHandle(hMapping); 604 return ret; 605 } 606 607 // Win: ImmGetImeMenuItemsWorker 608 DWORD APIENTRY 609 ImmGetImeMenuItemsAW(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu, 610 LPVOID lpImeMenu, DWORD dwSize, BOOL bTargetIsAnsi) 611 { 612 DWORD ret = 0, cbTotal, dwProcessId, dwThreadId, iItem; 613 LPINPUTCONTEXT pIC; 614 PIMEDPI pImeDpi = NULL; 615 IMEMENUITEMINFOA ParentA; 616 IMEMENUITEMINFOW ParentW; 617 LPIMEMENUITEMINFOA pItemA; 618 LPIMEMENUITEMINFOW pItemW; 619 LPVOID pNewItems = NULL, pNewParent = NULL; 620 BOOL bImcIsAnsi; 621 HKL hKL; 622 623 if (IS_NULL_UNEXPECTEDLY(hIMC)) 624 return 0; 625 626 dwProcessId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTPROCESSID); 627 if (IS_ZERO_UNEXPECTEDLY(dwProcessId)) 628 return 0; 629 630 if (dwProcessId != GetCurrentProcessId()) 631 { 632 if (bTargetIsAnsi) 633 return 0; 634 return Imm32GetImeMenuItemWInterProcess(hIMC, dwFlags, dwType, lpImeParentMenu, 635 lpImeMenu, dwSize); 636 } 637 638 pIC = ImmLockIMC(hIMC); 639 if (IS_NULL_UNEXPECTEDLY(pIC)) 640 return 0; 641 642 dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); 643 if (IS_ZERO_UNEXPECTEDLY(dwThreadId)) 644 { 645 ImmUnlockIMC(hIMC); 646 return 0; 647 } 648 649 hKL = GetKeyboardLayout(dwThreadId); 650 pImeDpi = ImmLockImeDpi(hKL); 651 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 652 { 653 ImmUnlockIMC(hIMC); 654 return 0; 655 } 656 657 bImcIsAnsi = Imm32IsImcAnsi(hIMC); 658 659 if (bImcIsAnsi != bTargetIsAnsi) 660 { 661 if (bTargetIsAnsi) 662 { 663 if (lpImeParentMenu) 664 pNewParent = &ParentW; 665 666 if (lpImeMenu) 667 { 668 cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOA)) * sizeof(IMEMENUITEMINFOW)); 669 pNewItems = ImmLocalAlloc(0, cbTotal); 670 if (IS_NULL_UNEXPECTEDLY(pNewItems)) 671 goto Quit; 672 } 673 } 674 else 675 { 676 if (lpImeParentMenu) 677 pNewParent = &ParentA; 678 679 if (lpImeMenu) 680 { 681 cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOW)) * sizeof(IMEMENUITEMINFOA)); 682 pNewItems = ImmLocalAlloc(0, cbTotal); 683 if (IS_NULL_UNEXPECTEDLY(pNewItems)) 684 goto Quit; 685 } 686 } 687 } 688 else 689 { 690 pNewItems = lpImeMenu; 691 pNewParent = lpImeParentMenu; 692 } 693 694 ret = pImeDpi->ImeGetImeMenuItems(hIMC, dwFlags, dwType, pNewParent, pNewItems, dwSize); 695 if (IS_ZERO_UNEXPECTEDLY(ret) || !lpImeMenu) 696 goto Quit; 697 698 if (bImcIsAnsi != bTargetIsAnsi) 699 { 700 if (bTargetIsAnsi) 701 { 702 if (pNewParent) 703 Imm32ImeMenuWideToAnsi(pNewParent, lpImeParentMenu, pImeDpi->uCodePage); 704 705 pItemW = pNewItems; 706 pItemA = lpImeMenu; 707 for (iItem = 0; iItem < ret; ++iItem, ++pItemW, ++pItemA) 708 { 709 if (!Imm32ImeMenuWideToAnsi(pItemW, pItemA, pImeDpi->uCodePage)) 710 { 711 ERR("\n"); 712 ret = 0; 713 break; 714 } 715 } 716 } 717 else 718 { 719 if (pNewParent) 720 Imm32ImeMenuAnsiToWide(pNewParent, lpImeParentMenu, pImeDpi->uCodePage, TRUE); 721 722 pItemA = pNewItems; 723 pItemW = lpImeMenu; 724 for (iItem = 0; iItem < dwSize; ++iItem, ++pItemA, ++pItemW) 725 { 726 if (!Imm32ImeMenuAnsiToWide(pItemA, pItemW, pImeDpi->uCodePage, TRUE)) 727 { 728 ERR("\n"); 729 ret = 0; 730 break; 731 } 732 } 733 } 734 } 735 736 Quit: 737 if (pNewItems != lpImeMenu) 738 ImmLocalFree(pNewItems); 739 ImmUnlockImeDpi(pImeDpi); 740 ImmUnlockIMC(hIMC); 741 TRACE("ret: 0x%X\n", ret); 742 return ret; 743 } 744 745 /*********************************************************************** 746 * ImmInstallIMEA (IMM32.@) 747 */ 748 HKL WINAPI ImmInstallIMEA(LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText) 749 { 750 HKL hKL = NULL; 751 LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL; 752 753 TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)); 754 755 pszFileNameW = Imm32WideFromAnsi(CP_ACP, lpszIMEFileName); 756 if (IS_NULL_UNEXPECTEDLY(pszFileNameW)) 757 goto Quit; 758 759 pszLayoutTextW = Imm32WideFromAnsi(CP_ACP, lpszLayoutText); 760 if (IS_NULL_UNEXPECTEDLY(pszLayoutTextW)) 761 goto Quit; 762 763 hKL = ImmInstallIMEW(pszFileNameW, pszLayoutTextW); 764 765 Quit: 766 ImmLocalFree(pszFileNameW); 767 ImmLocalFree(pszLayoutTextW); 768 return hKL; 769 } 770 771 /*********************************************************************** 772 * ImmInstallIMEW (IMM32.@) 773 */ 774 HKL WINAPI ImmInstallIMEW(LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText) 775 { 776 WCHAR szImeFileName[MAX_PATH], szImeDestPath[MAX_PATH], szImeKey[20]; 777 IMEINFOEX InfoEx; 778 LPWSTR pchFilePart; 779 UINT iLayout, cLayouts; 780 HKL hNewKL; 781 WORD wLangID; 782 PREG_IME pLayouts = NULL; 783 784 TRACE("(%s, %s)\n", debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)); 785 786 GetFullPathNameW(lpszIMEFileName, _countof(szImeFileName), szImeFileName, &pchFilePart); 787 CharUpperW(szImeFileName); 788 if (IS_NULL_UNEXPECTEDLY(pchFilePart)) 789 return NULL; 790 791 /* Load the IME version info */ 792 InfoEx.hkl = hNewKL = NULL; 793 StringCchCopyW(InfoEx.wszImeFile, _countof(InfoEx.wszImeFile), pchFilePart); 794 if (!Imm32LoadImeVerInfo(&InfoEx) || !InfoEx.hkl) 795 { 796 ERR("\n"); 797 return NULL; 798 } 799 wLangID = LOWORD(InfoEx.hkl); 800 801 /* Get the IME layouts from registry */ 802 cLayouts = Imm32GetImeLayout(NULL, 0); 803 if (cLayouts) 804 { 805 pLayouts = ImmLocalAlloc(0, cLayouts * sizeof(REG_IME)); 806 if (IS_NULL_UNEXPECTEDLY(pLayouts)) 807 return NULL; 808 809 if (!Imm32GetImeLayout(pLayouts, cLayouts)) 810 { 811 ERR("\n"); 812 ImmLocalFree(pLayouts); 813 return NULL; 814 } 815 816 for (iLayout = 0; iLayout < cLayouts; ++iLayout) 817 { 818 if (lstrcmpiW(pLayouts[iLayout].szFileName, pchFilePart) == 0) 819 { 820 if (wLangID != LOWORD(pLayouts[iLayout].hKL)) 821 { 822 ERR("\n"); 823 goto Quit; /* The language is different */ 824 } 825 826 hNewKL = pLayouts[iLayout].hKL; /* Found */ 827 break; 828 } 829 } 830 } 831 832 /* If the IME for the specified filename is valid, then unload it now */ 833 if (ImmGetImeInfoEx(&InfoEx, ImeInfoExImeFileName, pchFilePart) && 834 !UnloadKeyboardLayout(InfoEx.hkl)) 835 { 836 ERR("\n"); 837 hNewKL = NULL; 838 goto Quit; 839 } 840 841 Imm32GetSystemLibraryPath(szImeDestPath, _countof(szImeDestPath), pchFilePart); 842 CharUpperW(szImeDestPath); 843 844 /* If the source and the destination pathnames were different, then copy the IME file */ 845 if (lstrcmpiW(szImeFileName, szImeDestPath) != 0 && 846 !Imm32CopyImeFile(szImeFileName, szImeDestPath)) 847 { 848 ERR("\n"); 849 hNewKL = NULL; 850 goto Quit; 851 } 852 853 if (hNewKL == NULL) 854 hNewKL = Imm32AssignNewLayout(cLayouts, pLayouts, wLangID); 855 856 if (hNewKL) 857 { 858 /* Write the IME layout to registry */ 859 if (Imm32WriteImeLayout(hNewKL, pchFilePart, lpszLayoutText)) 860 { 861 /* Load the keyboard layout */ 862 StringCchPrintfW(szImeKey, _countof(szImeKey), L"%08X", (DWORD)(DWORD_PTR)hNewKL); 863 hNewKL = LoadKeyboardLayoutW(szImeKey, KLF_REPLACELANG); 864 } 865 else 866 { 867 ERR("\n"); 868 hNewKL = NULL; 869 } 870 } 871 872 Quit: 873 ImmLocalFree(pLayouts); 874 return hNewKL; 875 } 876 877 /*********************************************************************** 878 * ImmIsIME (IMM32.@) 879 */ 880 BOOL WINAPI ImmIsIME(HKL hKL) 881 { 882 IMEINFOEX info; 883 TRACE("(%p)\n", hKL); 884 return !!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayoutTFS, &hKL); 885 } 886 887 /*********************************************************************** 888 * ImmGetDefaultIMEWnd (IMM32.@) 889 */ 890 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd) 891 { 892 if (!IS_IMM_MODE()) 893 { 894 TRACE("\n"); 895 return NULL; 896 } 897 898 if (hWnd == NULL) 899 return (HWND)NtUserGetThreadState(THREADSTATE_DEFAULTIMEWINDOW); 900 901 return (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_IME); 902 } 903 904 /*********************************************************************** 905 * ImmNotifyIME (IMM32.@) 906 */ 907 BOOL WINAPI ImmNotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) 908 { 909 HKL hKL; 910 PIMEDPI pImeDpi; 911 BOOL ret; 912 913 TRACE("(%p, %lu, %lu, %lu)\n", hIMC, dwAction, dwIndex, dwValue); 914 915 if (hIMC && IS_CROSS_THREAD_HIMC(hIMC)) 916 return FALSE; 917 918 hKL = GetKeyboardLayout(0); 919 pImeDpi = ImmLockImeDpi(hKL); 920 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 921 return FALSE; 922 923 ret = pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue); 924 ImmUnlockImeDpi(pImeDpi); 925 return ret; 926 } 927 928 /*********************************************************************** 929 * ImmDisableLegacyIME(IMM32.@) 930 */ 931 BOOL WINAPI ImmDisableLegacyIME(void) 932 { 933 FIXME("stub\n"); 934 return TRUE; 935 } 936 937 /*********************************************************************** 938 * ImmGetImeInfoEx (IMM32.@) 939 */ 940 BOOL WINAPI 941 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID pvSearchKey) 942 { 943 HKL hKL; 944 if (SearchType == ImeInfoExKeyboardLayout || SearchType == ImeInfoExKeyboardLayoutTFS) 945 { 946 hKL = *(HKL*)pvSearchKey; 947 pImeInfoEx->hkl = hKL; 948 949 if (SearchType == ImeInfoExKeyboardLayoutTFS) 950 { 951 if (!IS_IME_HKL(hKL)) 952 { 953 if (CtfImmIsTextFrameServiceDisabled() || !IS_CICERO_MODE() || IS_16BIT_MODE()) 954 { 955 TRACE("\n"); 956 return FALSE; 957 } 958 } 959 960 SearchType = ImeInfoExKeyboardLayout; 961 } 962 else 963 { 964 if (!IS_IME_HKL(hKL)) 965 { 966 TRACE("\n"); 967 return FALSE; 968 } 969 } 970 } 971 else if (SearchType == ImeInfoExImeFileName) 972 { 973 StringCchCopyW(pImeInfoEx->wszImeFile, _countof(pImeInfoEx->wszImeFile), 974 pvSearchKey); 975 } 976 else 977 { 978 return FALSE; 979 } 980 981 return NtUserGetImeInfoEx(pImeInfoEx, SearchType); 982 } 983 984 /*********************************************************************** 985 * ImmLockImeDpi (IMM32.@) 986 */ 987 PIMEDPI WINAPI ImmLockImeDpi(HKL hKL) 988 { 989 PIMEDPI pImeDpi = NULL; 990 991 TRACE("(%p)\n", hKL); 992 993 RtlEnterCriticalSection(&gcsImeDpi); 994 995 /* Find by hKL */ 996 for (pImeDpi = gpImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext) 997 { 998 if (pImeDpi->hKL == hKL) /* found */ 999 { 1000 /* lock if possible */ 1001 if (pImeDpi->dwFlags & IMEDPI_FLAG_UNLOADED) 1002 pImeDpi = NULL; 1003 else 1004 ++(pImeDpi->cLockObj); 1005 break; 1006 } 1007 } 1008 1009 RtlLeaveCriticalSection(&gcsImeDpi); 1010 return pImeDpi; 1011 } 1012 1013 /*********************************************************************** 1014 * ImmUnlockImeDpi (IMM32.@) 1015 */ 1016 VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi) 1017 { 1018 PIMEDPI *ppEntry; 1019 1020 TRACE("(%p)\n", pImeDpi); 1021 1022 if (pImeDpi == NULL) 1023 return; 1024 1025 RtlEnterCriticalSection(&gcsImeDpi); 1026 1027 /* unlock */ 1028 --(pImeDpi->cLockObj); 1029 if (pImeDpi->cLockObj != 0) 1030 { 1031 RtlLeaveCriticalSection(&gcsImeDpi); 1032 return; 1033 } 1034 1035 if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNLOADED) == 0) 1036 { 1037 if ((pImeDpi->dwFlags & IMEDPI_FLAG_LOCKED) == 0 || 1038 (pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD) == 0) 1039 { 1040 RtlLeaveCriticalSection(&gcsImeDpi); 1041 return; 1042 } 1043 } 1044 1045 /* Remove from list */ 1046 for (ppEntry = &gpImeDpiList; *ppEntry; ppEntry = &((*ppEntry)->pNext)) 1047 { 1048 if (*ppEntry == pImeDpi) /* found */ 1049 { 1050 *ppEntry = pImeDpi->pNext; 1051 break; 1052 } 1053 } 1054 1055 Imm32FreeIME(pImeDpi, TRUE); 1056 ImmLocalFree(pImeDpi); 1057 1058 RtlLeaveCriticalSection(&gcsImeDpi); 1059 } 1060 1061 /*********************************************************************** 1062 * ImmLoadIME (IMM32.@) 1063 */ 1064 BOOL WINAPI ImmLoadIME(HKL hKL) 1065 { 1066 PIMEDPI pImeDpi; 1067 1068 if (!IS_IME_HKL(hKL) && (!IS_CICERO_MODE() || IS_16BIT_MODE())) 1069 { 1070 TRACE("\n"); 1071 return FALSE; 1072 } 1073 1074 pImeDpi = Imm32FindImeDpi(hKL); 1075 if (pImeDpi == NULL) 1076 pImeDpi = Imm32LoadImeDpi(hKL, FALSE); 1077 return (pImeDpi != NULL); 1078 } 1079 1080 /*********************************************************************** 1081 * ImmDisableIME (IMM32.@) 1082 */ 1083 BOOL WINAPI ImmDisableIME(DWORD dwThreadId) 1084 { 1085 return NtUserDisableThreadIme(dwThreadId); 1086 } 1087 1088 /*********************************************************************** 1089 * ImmGetDescriptionA (IMM32.@) 1090 */ 1091 UINT WINAPI ImmGetDescriptionA(HKL hKL, LPSTR lpszDescription, UINT uBufLen) 1092 { 1093 IMEINFOEX info; 1094 size_t cch; 1095 1096 TRACE("(%p,%p,%d)\n", hKL, lpszDescription, uBufLen); 1097 1098 if (!IS_IME_HKL(hKL)) 1099 { 1100 TRACE("\n"); 1101 return 0; 1102 } 1103 1104 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL)) 1105 { 1106 ERR("\n"); 1107 return 0; 1108 } 1109 1110 StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch); 1111 cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeDescription, (INT)cch, 1112 lpszDescription, uBufLen, NULL, NULL); 1113 if (uBufLen) 1114 lpszDescription[cch] = 0; 1115 return (UINT)cch; 1116 } 1117 1118 /*********************************************************************** 1119 * ImmGetDescriptionW (IMM32.@) 1120 */ 1121 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen) 1122 { 1123 IMEINFOEX info; 1124 size_t cch; 1125 1126 TRACE("(%p, %p, %d)\n", hKL, lpszDescription, uBufLen); 1127 1128 if (!IS_IME_HKL(hKL)) 1129 { 1130 TRACE("\n"); 1131 return 0; 1132 } 1133 1134 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL)) 1135 { 1136 ERR("\n"); 1137 return 0; 1138 } 1139 1140 if (uBufLen != 0) 1141 StringCchCopyW(lpszDescription, uBufLen, info.wszImeDescription); 1142 1143 StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch); 1144 return (UINT)cch; 1145 } 1146 1147 /*********************************************************************** 1148 * ImmGetIMEFileNameA (IMM32.@) 1149 */ 1150 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen) 1151 { 1152 BOOL bDefUsed; 1153 IMEINFOEX info; 1154 size_t cch; 1155 1156 TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen); 1157 1158 if (!IS_IME_HKL(hKL)) 1159 { 1160 TRACE("\n"); 1161 if (uBufLen > 0) 1162 lpszFileName[0] = 0; 1163 return 0; 1164 } 1165 1166 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL)) 1167 { 1168 ERR("\n"); 1169 if (uBufLen > 0) 1170 lpszFileName[0] = 0; 1171 return 0; 1172 } 1173 1174 StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch); 1175 1176 cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeFile, (INT)cch, 1177 lpszFileName, uBufLen, NULL, &bDefUsed); 1178 if (uBufLen == 0) 1179 return (UINT)cch; 1180 1181 if (cch > uBufLen - 1) 1182 cch = uBufLen - 1; 1183 1184 lpszFileName[cch] = 0; 1185 return (UINT)cch; 1186 } 1187 1188 /*********************************************************************** 1189 * ImmGetIMEFileNameW (IMM32.@) 1190 */ 1191 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen) 1192 { 1193 IMEINFOEX info; 1194 size_t cch; 1195 1196 TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen); 1197 1198 if (!IS_IME_HKL(hKL)) 1199 { 1200 TRACE("\n"); 1201 if (uBufLen > 0) 1202 lpszFileName[0] = 0; 1203 return 0; 1204 } 1205 1206 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL)) 1207 { 1208 ERR("\n"); 1209 if (uBufLen > 0) 1210 lpszFileName[0] = 0; 1211 return 0; 1212 } 1213 1214 StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch); 1215 if (uBufLen == 0) 1216 return (UINT)cch; 1217 1218 StringCchCopyNW(lpszFileName, uBufLen, info.wszImeFile, cch); 1219 1220 if (cch > uBufLen - 1) 1221 cch = uBufLen - 1; 1222 1223 lpszFileName[cch] = 0; 1224 return (UINT)cch; 1225 } 1226 1227 /*********************************************************************** 1228 * ImmGetProperty (IMM32.@) 1229 */ 1230 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) 1231 { 1232 IMEINFOEX ImeInfoEx; 1233 LPIMEINFO pImeInfo; 1234 DWORD dwValue; 1235 PIMEDPI pImeDpi = NULL; 1236 1237 TRACE("(%p, %lu)\n", hKL, fdwIndex); 1238 1239 if (!IS_IME_HKL(hKL)) 1240 { 1241 TRACE("\n"); 1242 return FALSE; 1243 } 1244 1245 if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL)) 1246 { 1247 ERR("\n"); 1248 return FALSE; 1249 } 1250 1251 if (fdwIndex == IGP_GETIMEVERSION) 1252 return ImeInfoEx.dwImeWinVersion; 1253 1254 if (ImeInfoEx.fLoadFlag != 2) 1255 { 1256 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1257 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1258 return FALSE; 1259 1260 pImeInfo = &pImeDpi->ImeInfo; 1261 } 1262 else 1263 { 1264 pImeInfo = &ImeInfoEx.ImeInfo; 1265 } 1266 1267 switch (fdwIndex) 1268 { 1269 case IGP_PROPERTY: dwValue = pImeInfo->fdwProperty; break; 1270 case IGP_CONVERSION: dwValue = pImeInfo->fdwConversionCaps; break; 1271 case IGP_SENTENCE: dwValue = pImeInfo->fdwSentenceCaps; break; 1272 case IGP_UI: dwValue = pImeInfo->fdwUICaps; break; 1273 case IGP_SETCOMPSTR: dwValue = pImeInfo->fdwSCSCaps; break; 1274 case IGP_SELECT: dwValue = pImeInfo->fdwSelectCaps; break; 1275 default: dwValue = 0; break; 1276 } 1277 1278 if (pImeDpi) 1279 ImmUnlockImeDpi(pImeDpi); 1280 return dwValue; 1281 } 1282 1283 /*********************************************************************** 1284 * ImmEscapeA (IMM32.@) 1285 */ 1286 LRESULT WINAPI ImmEscapeA(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData) 1287 { 1288 LRESULT ret; 1289 PIMEDPI pImeDpi; 1290 INT cch; 1291 CHAR szA[MAX_IMM_FILENAME]; 1292 WCHAR szW[MAX_IMM_FILENAME]; 1293 1294 TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData); 1295 1296 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1297 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1298 return 0; 1299 1300 if (!ImeDpi_IsUnicode(pImeDpi) || !lpData) /* No conversion needed */ 1301 { 1302 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1303 ImmUnlockImeDpi(pImeDpi); 1304 return ret; 1305 } 1306 1307 switch (uSubFunc) 1308 { 1309 case IME_ESC_SEQUENCE_TO_INTERNAL: 1310 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1311 1312 cch = 0; 1313 if (HIWORD(ret)) 1314 szW[cch++] = HIWORD(ret); 1315 if (LOWORD(ret)) 1316 szW[cch++] = LOWORD(ret); 1317 1318 cch = WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, cch, szA, _countof(szA), 1319 NULL, NULL); 1320 switch (cch) 1321 { 1322 case 1: 1323 ret = MAKEWORD(szA[0], 0); 1324 break; 1325 case 2: 1326 ret = MAKEWORD(szA[1], szA[0]); 1327 break; 1328 case 3: 1329 ret = MAKELONG(MAKEWORD(szA[2], szA[1]), MAKEWORD(szA[0], 0)); 1330 break; 1331 case 4: 1332 ret = MAKELONG(MAKEWORD(szA[3], szA[2]), MAKEWORD(szA[1], szA[0])); 1333 break; 1334 default: 1335 ret = 0; 1336 break; 1337 } 1338 break; 1339 1340 case IME_ESC_GET_EUDC_DICTIONARY: 1341 case IME_ESC_IME_NAME: 1342 case IME_ESC_GETHELPFILENAME: 1343 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL); 1344 if (ret) 1345 { 1346 szW[_countof(szW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 1347 WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, -1, 1348 lpData, MAX_IMM_FILENAME, NULL, NULL); 1349 ((LPSTR)lpData)[MAX_IMM_FILENAME - 1] = 0; 1350 } 1351 break; 1352 1353 case IME_ESC_SET_EUDC_DICTIONARY: 1354 case IME_ESC_HANJA_MODE: 1355 MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, 1356 lpData, -1, szW, _countof(szW)); 1357 szW[_countof(szW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 1358 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL); 1359 break; 1360 1361 default: 1362 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1363 break; 1364 } 1365 1366 ImmUnlockImeDpi(pImeDpi); 1367 TRACE("ret: %p\n", ret); 1368 return ret; 1369 } 1370 1371 /*********************************************************************** 1372 * ImmEscapeW (IMM32.@) 1373 */ 1374 LRESULT WINAPI ImmEscapeW(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData) 1375 { 1376 LRESULT ret; 1377 PIMEDPI pImeDpi; 1378 INT cch; 1379 CHAR szA[MAX_IMM_FILENAME]; 1380 WCHAR szW[MAX_IMM_FILENAME]; 1381 WORD word; 1382 1383 TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData); 1384 1385 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1386 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1387 return 0; 1388 1389 if (ImeDpi_IsUnicode(pImeDpi) || !lpData) /* No conversion needed */ 1390 { 1391 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1392 ImmUnlockImeDpi(pImeDpi); 1393 return ret; 1394 } 1395 1396 switch (uSubFunc) 1397 { 1398 case IME_ESC_SEQUENCE_TO_INTERNAL: 1399 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1400 1401 word = LOWORD(ret); 1402 cch = 0; 1403 if (HIBYTE(word)) 1404 szA[cch++] = HIBYTE(word); 1405 if (LOBYTE(word)) 1406 szA[cch++] = LOBYTE(word); 1407 1408 cch = MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, 1409 szA, cch, szW, _countof(szW)); 1410 switch (cch) 1411 { 1412 case 1: ret = szW[0]; break; 1413 case 2: ret = MAKELONG(szW[1], szW[0]); break; 1414 default: ret = 0; break; 1415 } 1416 break; 1417 1418 case IME_ESC_GET_EUDC_DICTIONARY: 1419 case IME_ESC_IME_NAME: 1420 case IME_ESC_GETHELPFILENAME: 1421 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL); 1422 if (ret) 1423 { 1424 szA[_countof(szA) - 1] = 0; 1425 MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, 1426 szA, -1, lpData, MAX_IMM_FILENAME); 1427 ((LPWSTR)lpData)[MAX_IMM_FILENAME - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 1428 } 1429 break; 1430 1431 case IME_ESC_SET_EUDC_DICTIONARY: 1432 case IME_ESC_HANJA_MODE: 1433 WideCharToMultiByte(pImeDpi->uCodePage, 0, 1434 lpData, -1, szA, _countof(szA), NULL, NULL); 1435 szA[_countof(szA) - 1] = 0; 1436 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL); 1437 break; 1438 1439 default: 1440 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1441 break; 1442 } 1443 1444 ImmUnlockImeDpi(pImeDpi); 1445 TRACE("ret: %p\n", ret); 1446 return ret; 1447 } 1448 1449 /*********************************************************************** 1450 * ImmGetOpenStatus (IMM32.@) 1451 */ 1452 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC) 1453 { 1454 BOOL ret; 1455 LPINPUTCONTEXT pIC; 1456 1457 TRACE("(%p)\n", hIMC); 1458 1459 if (IS_NULL_UNEXPECTEDLY(hIMC)) 1460 return FALSE; 1461 1462 pIC = ImmLockIMC(hIMC); 1463 if (IS_NULL_UNEXPECTEDLY(pIC)) 1464 return FALSE; 1465 1466 ret = pIC->fOpen; 1467 ImmUnlockIMC(hIMC); 1468 TRACE("ret: %d\n", ret); 1469 return ret; 1470 } 1471 1472 /*********************************************************************** 1473 * ImmSetOpenStatus (IMM32.@) 1474 */ 1475 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) 1476 { 1477 DWORD dwConversion; 1478 LPINPUTCONTEXT pIC; 1479 HWND hWnd; 1480 BOOL bHasChange = FALSE; 1481 1482 TRACE("(%p, %d)\n", hIMC, fOpen); 1483 1484 if (IS_CROSS_THREAD_HIMC(hIMC)) 1485 return FALSE; 1486 1487 pIC = ImmLockIMC(hIMC); 1488 if (IS_NULL_UNEXPECTEDLY(pIC)) 1489 return FALSE; 1490 1491 if (pIC->fOpen != fOpen) 1492 { 1493 pIC->fOpen = fOpen; 1494 hWnd = pIC->hWnd; 1495 dwConversion = pIC->fdwConversion; 1496 bHasChange = TRUE; 1497 } 1498 1499 ImmUnlockIMC(hIMC); 1500 1501 if (bHasChange) 1502 { 1503 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, 1504 IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0); 1505 NtUserNotifyIMEStatus(hWnd, fOpen, dwConversion); 1506 } 1507 else 1508 { 1509 TRACE("No change.\n"); 1510 } 1511 1512 return TRUE; 1513 } 1514 1515 /*********************************************************************** 1516 * ImmGetStatusWindowPos (IMM32.@) 1517 */ 1518 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 1519 { 1520 LPINPUTCONTEXT pIC; 1521 BOOL ret; 1522 1523 TRACE("(%p, %p)\n", hIMC, lpptPos); 1524 1525 pIC = ImmLockIMC(hIMC); 1526 if (IS_NULL_UNEXPECTEDLY(pIC)) 1527 return FALSE; 1528 1529 ret = !!(pIC->fdwInit & INIT_STATUSWNDPOS); 1530 if (ret) 1531 *lpptPos = pIC->ptStatusWndPos; 1532 1533 ImmUnlockIMC(hIMC); 1534 return ret; 1535 } 1536 1537 /*********************************************************************** 1538 * ImmSetStatusWindowPos (IMM32.@) 1539 */ 1540 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 1541 { 1542 LPINPUTCONTEXT pIC; 1543 HWND hWnd; 1544 1545 TRACE("(%p, {%ld, %ld})\n", hIMC, lpptPos->x, lpptPos->y); 1546 1547 if (IS_CROSS_THREAD_HIMC(hIMC)) 1548 return FALSE; 1549 1550 pIC = ImmLockIMC(hIMC); 1551 if (IS_NULL_UNEXPECTEDLY(pIC)) 1552 return FALSE; 1553 1554 hWnd = pIC->hWnd; 1555 pIC->ptStatusWndPos = *lpptPos; 1556 pIC->fdwInit |= INIT_STATUSWNDPOS; 1557 1558 ImmUnlockIMC(hIMC); 1559 1560 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, 1561 IMC_SETSTATUSWINDOWPOS, IMN_SETSTATUSWINDOWPOS, 0); 1562 return TRUE; 1563 } 1564 1565 /*********************************************************************** 1566 * ImmGetCompositionWindow (IMM32.@) 1567 */ 1568 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 1569 { 1570 LPINPUTCONTEXT pIC; 1571 BOOL ret = FALSE; 1572 1573 TRACE("(%p, %p)\n", hIMC, lpCompForm); 1574 1575 pIC = ImmLockIMC(hIMC); 1576 if (IS_NULL_UNEXPECTEDLY(pIC)) 1577 return FALSE; 1578 1579 if (pIC->fdwInit & INIT_COMPFORM) 1580 { 1581 *lpCompForm = pIC->cfCompForm; 1582 ret = TRUE; 1583 } 1584 1585 ImmUnlockIMC(hIMC); 1586 return ret; 1587 } 1588 1589 /*********************************************************************** 1590 * ImmSetCompositionWindow (IMM32.@) 1591 */ 1592 BOOL WINAPI ImmSetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 1593 { 1594 LPINPUTCONTEXTDX pIC; 1595 HWND hWnd; 1596 1597 if (IS_CROSS_THREAD_HIMC(hIMC)) 1598 return FALSE; 1599 1600 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 1601 if (IS_NULL_UNEXPECTEDLY(pIC)) 1602 return FALSE; 1603 1604 pIC->cfCompForm = *lpCompForm; 1605 pIC->fdwInit |= INIT_COMPFORM; 1606 1607 if (pIC->dwUIFlags & 0x8) 1608 pIC->dwUIFlags &= ~0x8; 1609 else 1610 pIC->dwUIFlags &= ~0x2; 1611 1612 hWnd = pIC->hWnd; 1613 1614 ImmUnlockIMC(hIMC); 1615 1616 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, 1617 IMC_SETCOMPOSITIONWINDOW, IMN_SETCOMPOSITIONWINDOW, 0); 1618 return TRUE; 1619 } 1620 1621 /*********************************************************************** 1622 * ImmGetCompositionFontA (IMM32.@) 1623 */ 1624 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 1625 { 1626 PCLIENTIMC pClientImc; 1627 BOOL ret = FALSE, bWide; 1628 LPINPUTCONTEXT pIC; 1629 1630 TRACE("(%p, %p)\n", hIMC, lplf); 1631 1632 pClientImc = ImmLockClientImc(hIMC); 1633 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1634 return FALSE; 1635 1636 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1637 ImmUnlockClientImc(pClientImc); 1638 1639 pIC = ImmLockIMC(hIMC); 1640 if (IS_NULL_UNEXPECTEDLY(pIC)) 1641 return FALSE; 1642 1643 if (pIC->fdwInit & INIT_LOGFONT) 1644 { 1645 if (bWide) 1646 LogFontWideToAnsi(&pIC->lfFont.W, lplf); 1647 else 1648 *lplf = pIC->lfFont.A; 1649 1650 ret = TRUE; 1651 } 1652 1653 ImmUnlockIMC(hIMC); 1654 return ret; 1655 } 1656 1657 /*********************************************************************** 1658 * ImmGetCompositionFontW (IMM32.@) 1659 */ 1660 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 1661 { 1662 PCLIENTIMC pClientImc; 1663 BOOL bWide; 1664 LPINPUTCONTEXT pIC; 1665 BOOL ret = FALSE; 1666 1667 TRACE("(%p, %p)\n", hIMC, lplf); 1668 1669 pClientImc = ImmLockClientImc(hIMC); 1670 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1671 return FALSE; 1672 1673 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1674 ImmUnlockClientImc(pClientImc); 1675 1676 pIC = ImmLockIMC(hIMC); 1677 if (IS_NULL_UNEXPECTEDLY(pIC)) 1678 return FALSE; 1679 1680 if (pIC->fdwInit & INIT_LOGFONT) 1681 { 1682 if (bWide) 1683 *lplf = pIC->lfFont.W; 1684 else 1685 LogFontAnsiToWide(&pIC->lfFont.A, lplf); 1686 1687 ret = TRUE; 1688 } 1689 1690 ImmUnlockIMC(hIMC); 1691 return ret; 1692 } 1693 1694 /*********************************************************************** 1695 * ImmSetCompositionFontA (IMM32.@) 1696 */ 1697 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 1698 { 1699 LOGFONTW lfW; 1700 PCLIENTIMC pClientImc; 1701 BOOL bWide; 1702 LPINPUTCONTEXTDX pIC; 1703 LANGID LangID; 1704 HWND hWnd; 1705 1706 TRACE("(%p, %p)\n", hIMC, lplf); 1707 1708 if (IS_CROSS_THREAD_HIMC(hIMC)) 1709 return FALSE; 1710 1711 pClientImc = ImmLockClientImc(hIMC); 1712 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1713 return FALSE; 1714 1715 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1716 ImmUnlockClientImc(pClientImc); 1717 1718 if (bWide) 1719 { 1720 LogFontAnsiToWide(lplf, &lfW); 1721 return ImmSetCompositionFontW(hIMC, &lfW); 1722 } 1723 1724 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 1725 if (IS_NULL_UNEXPECTEDLY(pIC)) 1726 return FALSE; 1727 1728 if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* old version (3.x)? */ 1729 { 1730 LangID = LANGIDFROMLCID(GetSystemDefaultLCID()); 1731 if (PRIMARYLANGID(LangID) == LANG_JAPANESE && 1732 !(pIC->dwUIFlags & 2) && 1733 pIC->cfCompForm.dwStyle != CFS_DEFAULT) 1734 { 1735 PostMessageA(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0); 1736 } 1737 } 1738 1739 pIC->lfFont.A = *lplf; 1740 pIC->fdwInit |= INIT_LOGFONT; 1741 hWnd = pIC->hWnd; 1742 1743 ImmUnlockIMC(hIMC); 1744 1745 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT, 1746 IMN_SETCOMPOSITIONFONT, 0); 1747 return TRUE; 1748 } 1749 1750 /*********************************************************************** 1751 * ImmSetCompositionFontW (IMM32.@) 1752 */ 1753 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 1754 { 1755 LOGFONTA lfA; 1756 PCLIENTIMC pClientImc; 1757 BOOL bWide; 1758 HWND hWnd; 1759 LPINPUTCONTEXTDX pIC; 1760 LANGID LangID; 1761 1762 TRACE("(%p, %p)\n", hIMC, lplf); 1763 1764 if (IS_CROSS_THREAD_HIMC(hIMC)) 1765 return FALSE; 1766 1767 pClientImc = ImmLockClientImc(hIMC); 1768 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1769 return FALSE; 1770 1771 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1772 ImmUnlockClientImc(pClientImc); 1773 1774 if (!bWide) 1775 { 1776 LogFontWideToAnsi(lplf, &lfA); 1777 return ImmSetCompositionFontA(hIMC, &lfA); 1778 } 1779 1780 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 1781 if (IS_NULL_UNEXPECTEDLY(pIC)) 1782 return FALSE; 1783 1784 if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* old version (3.x)? */ 1785 { 1786 LangID = LANGIDFROMLCID(GetSystemDefaultLCID()); 1787 if (PRIMARYLANGID(LangID) == LANG_JAPANESE && 1788 !(pIC->dwUIFlags & 2) && 1789 pIC->cfCompForm.dwStyle != CFS_DEFAULT) 1790 { 1791 PostMessageW(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0); 1792 } 1793 } 1794 1795 pIC->lfFont.W = *lplf; 1796 pIC->fdwInit |= INIT_LOGFONT; 1797 hWnd = pIC->hWnd; 1798 1799 ImmUnlockIMC(hIMC); 1800 1801 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT, 1802 IMN_SETCOMPOSITIONFONT, 0); 1803 return TRUE; 1804 } 1805 1806 /*********************************************************************** 1807 * ImmGetConversionListA (IMM32.@) 1808 */ 1809 DWORD WINAPI 1810 ImmGetConversionListA(HKL hKL, HIMC hIMC, LPCSTR pSrc, LPCANDIDATELIST lpDst, 1811 DWORD dwBufLen, UINT uFlag) 1812 { 1813 DWORD ret = 0; 1814 UINT cb; 1815 LPWSTR pszSrcW = NULL; 1816 LPCANDIDATELIST pCL = NULL; 1817 PIMEDPI pImeDpi; 1818 1819 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_a(pSrc), 1820 lpDst, dwBufLen, uFlag); 1821 1822 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1823 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1824 return 0; 1825 1826 if (!ImeDpi_IsUnicode(pImeDpi)) /* No conversion needed */ 1827 { 1828 ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag); 1829 ImmUnlockImeDpi(pImeDpi); 1830 return ret; 1831 } 1832 1833 if (pSrc) 1834 { 1835 pszSrcW = Imm32WideFromAnsi(pImeDpi->uCodePage, pSrc); 1836 if (IS_NULL_UNEXPECTEDLY(pszSrcW)) 1837 goto Quit; 1838 } 1839 1840 cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, NULL, 0, uFlag); 1841 if (IS_ZERO_UNEXPECTEDLY(cb)) 1842 goto Quit; 1843 1844 pCL = ImmLocalAlloc(0, cb); 1845 if (IS_NULL_UNEXPECTEDLY(pCL)) 1846 goto Quit; 1847 1848 cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, pCL, cb, uFlag); 1849 if (IS_ZERO_UNEXPECTEDLY(cb)) 1850 goto Quit; 1851 1852 ret = CandidateListWideToAnsi(pCL, lpDst, dwBufLen, pImeDpi->uCodePage); 1853 1854 Quit: 1855 ImmLocalFree(pszSrcW); 1856 ImmLocalFree(pCL); 1857 ImmUnlockImeDpi(pImeDpi); 1858 TRACE("ret: 0x%X\n", ret); 1859 return ret; 1860 } 1861 1862 /*********************************************************************** 1863 * ImmGetConversionListW (IMM32.@) 1864 */ 1865 DWORD WINAPI 1866 ImmGetConversionListW(HKL hKL, HIMC hIMC, LPCWSTR pSrc, LPCANDIDATELIST lpDst, 1867 DWORD dwBufLen, UINT uFlag) 1868 { 1869 DWORD ret = 0; 1870 INT cb; 1871 PIMEDPI pImeDpi; 1872 LPCANDIDATELIST pCL = NULL; 1873 LPSTR pszSrcA = NULL; 1874 1875 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_w(pSrc), 1876 lpDst, dwBufLen, uFlag); 1877 1878 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1879 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1880 return 0; 1881 1882 if (ImeDpi_IsUnicode(pImeDpi)) /* No conversion needed */ 1883 { 1884 ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag); 1885 ImmUnlockImeDpi(pImeDpi); 1886 return ret; 1887 } 1888 1889 if (pSrc) 1890 { 1891 pszSrcA = Imm32AnsiFromWide(pImeDpi->uCodePage, pSrc); 1892 if (IS_NULL_UNEXPECTEDLY(pszSrcA)) 1893 goto Quit; 1894 } 1895 1896 cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, NULL, 0, uFlag); 1897 if (IS_ZERO_UNEXPECTEDLY(cb)) 1898 goto Quit; 1899 1900 pCL = ImmLocalAlloc(0, cb); 1901 if (IS_NULL_UNEXPECTEDLY(pCL)) 1902 goto Quit; 1903 1904 cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, pCL, cb, uFlag); 1905 if (IS_ZERO_UNEXPECTEDLY(cb)) 1906 goto Quit; 1907 1908 ret = CandidateListAnsiToWide(pCL, lpDst, dwBufLen, pImeDpi->uCodePage); 1909 1910 Quit: 1911 ImmLocalFree(pszSrcA); 1912 ImmLocalFree(pCL); 1913 ImmUnlockImeDpi(pImeDpi); 1914 TRACE("ret: 0x%X\n", ret); 1915 return ret; 1916 } 1917 1918 /*********************************************************************** 1919 * ImmGetConversionStatus (IMM32.@) 1920 */ 1921 BOOL WINAPI ImmGetConversionStatus(HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence) 1922 { 1923 LPINPUTCONTEXT pIC; 1924 1925 TRACE("(%p %p %p)\n", hIMC, lpfdwConversion, lpfdwSentence); 1926 1927 pIC = ImmLockIMC(hIMC); 1928 if (IS_NULL_UNEXPECTEDLY(pIC)) 1929 return FALSE; 1930 1931 if (lpfdwConversion) 1932 { 1933 *lpfdwConversion = pIC->fdwConversion; 1934 TRACE("0x%X\n", *lpfdwConversion); 1935 } 1936 1937 if (lpfdwSentence) 1938 { 1939 *lpfdwSentence = pIC->fdwSentence; 1940 TRACE("0x%X\n", *lpfdwSentence); 1941 } 1942 1943 ImmUnlockIMC(hIMC); 1944 return TRUE; 1945 } 1946 1947 /*********************************************************************** 1948 * ImmSetConversionStatus (IMM32.@) 1949 */ 1950 BOOL WINAPI ImmSetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) 1951 { 1952 HKL hKL; 1953 LPINPUTCONTEXT pIC; 1954 DWORD dwOldConversion, dwOldSentence; 1955 BOOL fOpen = FALSE, fConversionChange = FALSE, fSentenceChange = FALSE, fUseCicero = FALSE; 1956 HWND hWnd; 1957 1958 TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC, fdwConversion, fdwSentence); 1959 1960 hKL = GetKeyboardLayout(0); 1961 if (!IS_IME_HKL(hKL) && IS_CICERO_MODE() && !IS_16BIT_MODE()) 1962 fUseCicero = TRUE; 1963 1964 if (IS_CROSS_THREAD_HIMC(hIMC)) 1965 return FALSE; 1966 1967 pIC = ImmLockIMC(hIMC); 1968 if (IS_NULL_UNEXPECTEDLY(pIC)) 1969 return FALSE; 1970 1971 if (pIC->fdwConversion != fdwConversion) 1972 { 1973 dwOldConversion = pIC->fdwConversion; 1974 pIC->fdwConversion = fdwConversion; 1975 fConversionChange = TRUE; 1976 } 1977 1978 if (pIC->fdwSentence != fdwSentence) 1979 { 1980 dwOldSentence = pIC->fdwSentence; 1981 pIC->fdwSentence = fdwSentence; 1982 fSentenceChange = TRUE; 1983 } 1984 1985 hWnd = pIC->hWnd; 1986 fOpen = pIC->fOpen; 1987 ImmUnlockIMC(hIMC); 1988 1989 if (fConversionChange || fUseCicero) 1990 { 1991 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldConversion, 1992 IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0); 1993 if (fConversionChange) 1994 NtUserNotifyIMEStatus(hWnd, fOpen, fdwConversion); 1995 } 1996 1997 if (fSentenceChange || fUseCicero) 1998 { 1999 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldSentence, 2000 IMC_SETSENTENCEMODE, IMN_SETSENTENCEMODE, 0); 2001 } 2002 2003 return TRUE; 2004 } 2005 2006 /*********************************************************************** 2007 * ImmConfigureIMEA (IMM32.@) 2008 */ 2009 BOOL WINAPI ImmConfigureIMEA(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 2010 { 2011 BOOL ret = FALSE; 2012 PIMEDPI pImeDpi; 2013 REGISTERWORDW RegWordW; 2014 LPREGISTERWORDA pRegWordA; 2015 2016 TRACE("(%p, %p, 0x%lX, %p)\n", hKL, hWnd, dwMode, lpData); 2017 2018 if (IS_NULL_UNEXPECTEDLY(ValidateHwnd(hWnd)) || IS_CROSS_PROCESS_HWND(hWnd)) 2019 return FALSE; 2020 2021 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 2022 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 2023 return FALSE; 2024 2025 RtlZeroMemory(&RegWordW, sizeof(RegWordW)); 2026 2027 if (!ImeDpi_IsUnicode(pImeDpi) || !lpData || dwMode != IME_CONFIG_REGISTERWORD) 2028 goto DoIt; /* No conversion needed */ 2029 2030 pRegWordA = lpData; 2031 2032 if (pRegWordA->lpReading) 2033 { 2034 RegWordW.lpReading = Imm32WideFromAnsi(pImeDpi->uCodePage, pRegWordA->lpReading); 2035 if (IS_NULL_UNEXPECTEDLY(RegWordW.lpReading)) 2036 goto Quit; 2037 } 2038 2039 if (pRegWordA->lpWord) 2040 { 2041 RegWordW.lpWord = Imm32WideFromAnsi(pImeDpi->uCodePage, pRegWordA->lpWord); 2042 if (IS_NULL_UNEXPECTEDLY(RegWordW.lpWord)) 2043 goto Quit; 2044 } 2045 2046 lpData = &RegWordW; 2047 2048 DoIt: 2049 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1B, 0); 2050 ret = pImeDpi->ImeConfigure(hKL, hWnd, dwMode, lpData); 2051 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1A, 0); 2052 2053 Quit: 2054 ImmLocalFree(RegWordW.lpReading); 2055 ImmLocalFree(RegWordW.lpWord); 2056 ImmUnlockImeDpi(pImeDpi); 2057 TRACE("ret: %d\n", ret); 2058 return ret; 2059 } 2060 2061 /*********************************************************************** 2062 * ImmConfigureIMEW (IMM32.@) 2063 */ 2064 BOOL WINAPI ImmConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 2065 { 2066 BOOL ret = FALSE; 2067 PIMEDPI pImeDpi; 2068 REGISTERWORDA RegWordA; 2069 LPREGISTERWORDW pRegWordW; 2070 2071 TRACE("(%p, %p, 0x%lX, %p)\n", hKL, hWnd, dwMode, lpData); 2072 2073 if (IS_NULL_UNEXPECTEDLY(ValidateHwnd(hWnd)) || IS_CROSS_PROCESS_HWND(hWnd)) 2074 return FALSE; 2075 2076 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 2077 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 2078 return FALSE; 2079 2080 RtlZeroMemory(&RegWordA, sizeof(RegWordA)); 2081 2082 if (ImeDpi_IsUnicode(pImeDpi) || !lpData || dwMode != IME_CONFIG_REGISTERWORD) 2083 goto DoIt; /* No conversion needed */ 2084 2085 pRegWordW = lpData; 2086 2087 if (pRegWordW->lpReading) 2088 { 2089 RegWordA.lpReading = Imm32AnsiFromWide(pImeDpi->uCodePage, pRegWordW->lpReading); 2090 if (IS_NULL_UNEXPECTEDLY(RegWordA.lpReading)) 2091 goto Quit; 2092 } 2093 2094 if (pRegWordW->lpWord) 2095 { 2096 RegWordA.lpWord = Imm32AnsiFromWide(pImeDpi->uCodePage, pRegWordW->lpWord); 2097 if (IS_NULL_UNEXPECTEDLY(RegWordA.lpWord)) 2098 goto Quit; 2099 } 2100 2101 lpData = &RegWordA; 2102 2103 DoIt: 2104 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1B, 0); 2105 ret = pImeDpi->ImeConfigure(hKL, hWnd, dwMode, lpData); 2106 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1A, 0); 2107 2108 Quit: 2109 ImmLocalFree(RegWordA.lpReading); 2110 ImmLocalFree(RegWordA.lpWord); 2111 ImmUnlockImeDpi(pImeDpi); 2112 TRACE("ret: %d\n", ret); 2113 return ret; 2114 } 2115 2116 /*********************************************************************** 2117 * ImmGetImeMenuItemsA (IMM32.@) 2118 */ 2119 DWORD WINAPI 2120 ImmGetImeMenuItemsA(HIMC hIMC, DWORD dwFlags, DWORD dwType, 2121 LPIMEMENUITEMINFOA lpImeParentMenu, 2122 LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize) 2123 { 2124 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", 2125 hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize); 2126 return ImmGetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize, TRUE); 2127 } 2128 2129 /*********************************************************************** 2130 * ImmGetImeMenuItemsW (IMM32.@) 2131 */ 2132 DWORD WINAPI 2133 ImmGetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType, 2134 LPIMEMENUITEMINFOW lpImeParentMenu, 2135 LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize) 2136 { 2137 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", 2138 hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize); 2139 return ImmGetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize, FALSE); 2140 } 2141 2142 /*********************************************************************** 2143 * ImmWINNLSEnableIME (IMM32.@) 2144 */ 2145 BOOL WINAPI ImmWINNLSEnableIME(HWND hWnd, BOOL enable) 2146 { 2147 HIMC hIMC; 2148 PCLIENTIMC pClientImc; 2149 HWND hImeWnd; 2150 BOOL bImeWnd, ret; 2151 2152 TRACE("(%p, %d)\n", hWnd, enable); 2153 2154 if (!Imm32IsSystemJapaneseOrKorean()) 2155 { 2156 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2157 return FALSE; 2158 } 2159 2160 hIMC = (HIMC)NtUserGetThreadState(THREADSTATE_DEFAULTINPUTCONTEXT); 2161 if (IS_NULL_UNEXPECTEDLY(hIMC)) 2162 return FALSE; 2163 2164 pClientImc = ImmLockClientImc(hIMC); 2165 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 2166 return FALSE; 2167 2168 ret = !(pClientImc->dwFlags & CLIENTIMC_DISABLEIME); 2169 if (!!enable == ret) 2170 { 2171 TRACE("Same\n"); 2172 ImmUnlockClientImc(pClientImc); 2173 return ret; 2174 } 2175 2176 if (!IsWindow(hWnd)) 2177 hWnd = GetFocus(); 2178 2179 hImeWnd = ImmGetDefaultIMEWnd(hWnd); 2180 bImeWnd = IsWindow(hImeWnd); 2181 if (bImeWnd) 2182 ImmSetActiveContext(hWnd, (enable ? NULL : hIMC), FALSE); 2183 2184 if (enable) 2185 pClientImc->dwFlags &= ~CLIENTIMC_DISABLEIME; 2186 else 2187 pClientImc->dwFlags |= CLIENTIMC_DISABLEIME; 2188 2189 ImmUnlockClientImc(pClientImc); 2190 2191 if (bImeWnd) 2192 ImmSetActiveContext(hWnd, (enable ? hIMC : NULL), TRUE); 2193 2194 return ret; 2195 } 2196