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_ISWINLOGON)) 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) != S_OK) 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(UlongToPtr(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", HandleToUlong(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_PTR 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 * ImmGetImeInfoEx (IMM32.@) 930 */ 931 BOOL WINAPI 932 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID pvSearchKey) 933 { 934 HKL hKL; 935 if (SearchType == ImeInfoExKeyboardLayout || SearchType == ImeInfoExKeyboardLayoutTFS) 936 { 937 hKL = *(HKL*)pvSearchKey; 938 pImeInfoEx->hkl = hKL; 939 940 if (SearchType == ImeInfoExKeyboardLayoutTFS) 941 { 942 if (!IS_IME_HKL(hKL)) 943 { 944 if (CtfImmIsTextFrameServiceDisabled() || !IS_CICERO_MODE() || IS_16BIT_MODE()) 945 { 946 TRACE("\n"); 947 return FALSE; 948 } 949 } 950 951 SearchType = ImeInfoExKeyboardLayout; 952 } 953 else 954 { 955 if (!IS_IME_HKL(hKL)) 956 { 957 TRACE("\n"); 958 return FALSE; 959 } 960 } 961 } 962 else if (SearchType == ImeInfoExImeFileName) 963 { 964 StringCchCopyW(pImeInfoEx->wszImeFile, _countof(pImeInfoEx->wszImeFile), 965 pvSearchKey); 966 } 967 else 968 { 969 return FALSE; 970 } 971 972 return NtUserGetImeInfoEx(pImeInfoEx, SearchType); 973 } 974 975 /*********************************************************************** 976 * ImmLockImeDpi (IMM32.@) 977 */ 978 PIMEDPI WINAPI ImmLockImeDpi(HKL hKL) 979 { 980 PIMEDPI pImeDpi = NULL; 981 982 TRACE("(%p)\n", hKL); 983 984 RtlEnterCriticalSection(&gcsImeDpi); 985 986 /* Find by hKL */ 987 for (pImeDpi = gpImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext) 988 { 989 if (pImeDpi->hKL == hKL) /* found */ 990 { 991 /* lock if possible */ 992 if (pImeDpi->dwFlags & IMEDPI_FLAG_UNLOADED) 993 pImeDpi = NULL; 994 else 995 ++(pImeDpi->cLockObj); 996 break; 997 } 998 } 999 1000 RtlLeaveCriticalSection(&gcsImeDpi); 1001 return pImeDpi; 1002 } 1003 1004 /*********************************************************************** 1005 * ImmUnlockImeDpi (IMM32.@) 1006 */ 1007 VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi) 1008 { 1009 PIMEDPI *ppEntry; 1010 1011 TRACE("(%p)\n", pImeDpi); 1012 1013 if (pImeDpi == NULL) 1014 return; 1015 1016 RtlEnterCriticalSection(&gcsImeDpi); 1017 1018 /* unlock */ 1019 --(pImeDpi->cLockObj); 1020 if (pImeDpi->cLockObj != 0) 1021 { 1022 RtlLeaveCriticalSection(&gcsImeDpi); 1023 return; 1024 } 1025 1026 if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNLOADED) == 0) 1027 { 1028 if ((pImeDpi->dwFlags & IMEDPI_FLAG_LOCKED) == 0 || 1029 (pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD) == 0) 1030 { 1031 RtlLeaveCriticalSection(&gcsImeDpi); 1032 return; 1033 } 1034 } 1035 1036 /* Remove from list */ 1037 for (ppEntry = &gpImeDpiList; *ppEntry; ppEntry = &((*ppEntry)->pNext)) 1038 { 1039 if (*ppEntry == pImeDpi) /* found */ 1040 { 1041 *ppEntry = pImeDpi->pNext; 1042 break; 1043 } 1044 } 1045 1046 Imm32FreeIME(pImeDpi, TRUE); 1047 ImmLocalFree(pImeDpi); 1048 1049 RtlLeaveCriticalSection(&gcsImeDpi); 1050 } 1051 1052 /*********************************************************************** 1053 * ImmLoadIME (IMM32.@) 1054 */ 1055 BOOL WINAPI ImmLoadIME(HKL hKL) 1056 { 1057 PIMEDPI pImeDpi; 1058 1059 if (!IS_IME_HKL(hKL) && (!IS_CICERO_MODE() || IS_16BIT_MODE())) 1060 { 1061 TRACE("\n"); 1062 return FALSE; 1063 } 1064 1065 pImeDpi = Imm32FindImeDpi(hKL); 1066 if (pImeDpi == NULL) 1067 pImeDpi = Imm32LoadImeDpi(hKL, FALSE); 1068 return (pImeDpi != NULL); 1069 } 1070 1071 /*********************************************************************** 1072 * ImmDisableIME (IMM32.@) 1073 */ 1074 BOOL WINAPI ImmDisableIME(DWORD dwThreadId) 1075 { 1076 return NtUserDisableThreadIme(dwThreadId); 1077 } 1078 1079 /*********************************************************************** 1080 * ImmGetDescriptionA (IMM32.@) 1081 */ 1082 UINT WINAPI ImmGetDescriptionA(HKL hKL, LPSTR lpszDescription, UINT uBufLen) 1083 { 1084 IMEINFOEX info; 1085 size_t cch; 1086 1087 TRACE("(%p,%p,%d)\n", hKL, lpszDescription, uBufLen); 1088 1089 if (!IS_IME_HKL(hKL)) 1090 { 1091 TRACE("\n"); 1092 return 0; 1093 } 1094 1095 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL)) 1096 { 1097 ERR("\n"); 1098 return 0; 1099 } 1100 1101 StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch); 1102 cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeDescription, (INT)cch, 1103 lpszDescription, uBufLen, NULL, NULL); 1104 if (uBufLen) 1105 lpszDescription[cch] = 0; 1106 return (UINT)cch; 1107 } 1108 1109 /*********************************************************************** 1110 * ImmGetDescriptionW (IMM32.@) 1111 */ 1112 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen) 1113 { 1114 IMEINFOEX info; 1115 size_t cch; 1116 1117 TRACE("(%p, %p, %d)\n", hKL, lpszDescription, uBufLen); 1118 1119 if (!IS_IME_HKL(hKL)) 1120 { 1121 TRACE("\n"); 1122 return 0; 1123 } 1124 1125 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL)) 1126 { 1127 ERR("\n"); 1128 return 0; 1129 } 1130 1131 if (uBufLen != 0) 1132 StringCchCopyW(lpszDescription, uBufLen, info.wszImeDescription); 1133 1134 StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch); 1135 return (UINT)cch; 1136 } 1137 1138 /*********************************************************************** 1139 * ImmGetIMEFileNameA (IMM32.@) 1140 */ 1141 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen) 1142 { 1143 BOOL bDefUsed; 1144 IMEINFOEX info; 1145 size_t cch; 1146 1147 TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen); 1148 1149 if (!IS_IME_HKL(hKL)) 1150 { 1151 TRACE("\n"); 1152 if (uBufLen > 0) 1153 lpszFileName[0] = 0; 1154 return 0; 1155 } 1156 1157 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL)) 1158 { 1159 ERR("\n"); 1160 if (uBufLen > 0) 1161 lpszFileName[0] = 0; 1162 return 0; 1163 } 1164 1165 StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch); 1166 1167 cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeFile, (INT)cch, 1168 lpszFileName, uBufLen, NULL, &bDefUsed); 1169 if (uBufLen == 0) 1170 return (UINT)cch; 1171 1172 if (cch > uBufLen - 1) 1173 cch = uBufLen - 1; 1174 1175 lpszFileName[cch] = 0; 1176 return (UINT)cch; 1177 } 1178 1179 /*********************************************************************** 1180 * ImmGetIMEFileNameW (IMM32.@) 1181 */ 1182 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen) 1183 { 1184 IMEINFOEX info; 1185 size_t cch; 1186 1187 TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen); 1188 1189 if (!IS_IME_HKL(hKL)) 1190 { 1191 TRACE("\n"); 1192 if (uBufLen > 0) 1193 lpszFileName[0] = 0; 1194 return 0; 1195 } 1196 1197 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL)) 1198 { 1199 ERR("\n"); 1200 if (uBufLen > 0) 1201 lpszFileName[0] = 0; 1202 return 0; 1203 } 1204 1205 StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch); 1206 if (uBufLen == 0) 1207 return (UINT)cch; 1208 1209 StringCchCopyNW(lpszFileName, uBufLen, info.wszImeFile, cch); 1210 1211 if (cch > uBufLen - 1) 1212 cch = uBufLen - 1; 1213 1214 lpszFileName[cch] = 0; 1215 return (UINT)cch; 1216 } 1217 1218 /*********************************************************************** 1219 * ImmGetProperty (IMM32.@) 1220 */ 1221 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) 1222 { 1223 IMEINFOEX ImeInfoEx; 1224 LPIMEINFO pImeInfo; 1225 DWORD dwValue; 1226 PIMEDPI pImeDpi = NULL; 1227 1228 TRACE("(%p, %lu)\n", hKL, fdwIndex); 1229 1230 if (!IS_IME_HKL(hKL)) 1231 { 1232 TRACE("\n"); 1233 return FALSE; 1234 } 1235 1236 if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL)) 1237 { 1238 ERR("\n"); 1239 return FALSE; 1240 } 1241 1242 if (fdwIndex == IGP_GETIMEVERSION) 1243 return ImeInfoEx.dwImeWinVersion; 1244 1245 if (ImeInfoEx.fLoadFlag != 2) 1246 { 1247 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1248 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1249 return FALSE; 1250 1251 pImeInfo = &pImeDpi->ImeInfo; 1252 } 1253 else 1254 { 1255 pImeInfo = &ImeInfoEx.ImeInfo; 1256 } 1257 1258 switch (fdwIndex) 1259 { 1260 case IGP_PROPERTY: dwValue = pImeInfo->fdwProperty; break; 1261 case IGP_CONVERSION: dwValue = pImeInfo->fdwConversionCaps; break; 1262 case IGP_SENTENCE: dwValue = pImeInfo->fdwSentenceCaps; break; 1263 case IGP_UI: dwValue = pImeInfo->fdwUICaps; break; 1264 case IGP_SETCOMPSTR: dwValue = pImeInfo->fdwSCSCaps; break; 1265 case IGP_SELECT: dwValue = pImeInfo->fdwSelectCaps; break; 1266 default: dwValue = 0; break; 1267 } 1268 1269 if (pImeDpi) 1270 ImmUnlockImeDpi(pImeDpi); 1271 return dwValue; 1272 } 1273 1274 /*********************************************************************** 1275 * ImmEscapeA (IMM32.@) 1276 */ 1277 LRESULT WINAPI ImmEscapeA(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData) 1278 { 1279 LRESULT ret; 1280 PIMEDPI pImeDpi; 1281 INT cch; 1282 CHAR szA[MAX_IMM_FILENAME]; 1283 WCHAR szW[MAX_IMM_FILENAME]; 1284 1285 TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData); 1286 1287 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1288 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1289 return 0; 1290 1291 if (!ImeDpi_IsUnicode(pImeDpi) || !lpData) /* No conversion needed */ 1292 { 1293 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1294 ImmUnlockImeDpi(pImeDpi); 1295 return ret; 1296 } 1297 1298 switch (uSubFunc) 1299 { 1300 case IME_ESC_SEQUENCE_TO_INTERNAL: 1301 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1302 1303 cch = 0; 1304 if (HIWORD(ret)) 1305 szW[cch++] = HIWORD(ret); 1306 if (LOWORD(ret)) 1307 szW[cch++] = LOWORD(ret); 1308 1309 cch = WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, cch, szA, _countof(szA), 1310 NULL, NULL); 1311 switch (cch) 1312 { 1313 case 1: 1314 ret = MAKEWORD(szA[0], 0); 1315 break; 1316 case 2: 1317 ret = MAKEWORD(szA[1], szA[0]); 1318 break; 1319 case 3: 1320 ret = MAKELONG(MAKEWORD(szA[2], szA[1]), MAKEWORD(szA[0], 0)); 1321 break; 1322 case 4: 1323 ret = MAKELONG(MAKEWORD(szA[3], szA[2]), MAKEWORD(szA[1], szA[0])); 1324 break; 1325 default: 1326 ret = 0; 1327 break; 1328 } 1329 break; 1330 1331 case IME_ESC_GET_EUDC_DICTIONARY: 1332 case IME_ESC_IME_NAME: 1333 case IME_ESC_GETHELPFILENAME: 1334 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL); 1335 if (ret) 1336 { 1337 szW[_countof(szW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 1338 WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, -1, 1339 lpData, MAX_IMM_FILENAME, NULL, NULL); 1340 ((LPSTR)lpData)[MAX_IMM_FILENAME - 1] = 0; 1341 } 1342 break; 1343 1344 case IME_ESC_SET_EUDC_DICTIONARY: 1345 case IME_ESC_HANJA_MODE: 1346 MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, 1347 lpData, -1, szW, _countof(szW)); 1348 szW[_countof(szW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 1349 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL); 1350 break; 1351 1352 default: 1353 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1354 break; 1355 } 1356 1357 ImmUnlockImeDpi(pImeDpi); 1358 TRACE("ret: %p\n", ret); 1359 return ret; 1360 } 1361 1362 /*********************************************************************** 1363 * ImmEscapeW (IMM32.@) 1364 */ 1365 LRESULT WINAPI ImmEscapeW(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData) 1366 { 1367 LRESULT ret; 1368 PIMEDPI pImeDpi; 1369 INT cch; 1370 CHAR szA[MAX_IMM_FILENAME]; 1371 WCHAR szW[MAX_IMM_FILENAME]; 1372 WORD word; 1373 1374 TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData); 1375 1376 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1377 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1378 return 0; 1379 1380 if (ImeDpi_IsUnicode(pImeDpi) || !lpData) /* No conversion needed */ 1381 { 1382 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1383 ImmUnlockImeDpi(pImeDpi); 1384 return ret; 1385 } 1386 1387 switch (uSubFunc) 1388 { 1389 case IME_ESC_SEQUENCE_TO_INTERNAL: 1390 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1391 1392 word = LOWORD(ret); 1393 cch = 0; 1394 if (HIBYTE(word)) 1395 szA[cch++] = HIBYTE(word); 1396 if (LOBYTE(word)) 1397 szA[cch++] = LOBYTE(word); 1398 1399 cch = MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, 1400 szA, cch, szW, _countof(szW)); 1401 switch (cch) 1402 { 1403 case 1: ret = szW[0]; break; 1404 case 2: ret = MAKELONG(szW[1], szW[0]); break; 1405 default: ret = 0; break; 1406 } 1407 break; 1408 1409 case IME_ESC_GET_EUDC_DICTIONARY: 1410 case IME_ESC_IME_NAME: 1411 case IME_ESC_GETHELPFILENAME: 1412 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL); 1413 if (ret) 1414 { 1415 szA[_countof(szA) - 1] = 0; 1416 MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, 1417 szA, -1, lpData, MAX_IMM_FILENAME); 1418 ((LPWSTR)lpData)[MAX_IMM_FILENAME - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 1419 } 1420 break; 1421 1422 case IME_ESC_SET_EUDC_DICTIONARY: 1423 case IME_ESC_HANJA_MODE: 1424 WideCharToMultiByte(pImeDpi->uCodePage, 0, 1425 lpData, -1, szA, _countof(szA), NULL, NULL); 1426 szA[_countof(szA) - 1] = 0; 1427 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL); 1428 break; 1429 1430 default: 1431 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); 1432 break; 1433 } 1434 1435 ImmUnlockImeDpi(pImeDpi); 1436 TRACE("ret: %p\n", ret); 1437 return ret; 1438 } 1439 1440 /*********************************************************************** 1441 * ImmGetOpenStatus (IMM32.@) 1442 */ 1443 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC) 1444 { 1445 BOOL ret; 1446 LPINPUTCONTEXT pIC; 1447 1448 TRACE("(%p)\n", hIMC); 1449 1450 if (IS_NULL_UNEXPECTEDLY(hIMC)) 1451 return FALSE; 1452 1453 pIC = ImmLockIMC(hIMC); 1454 if (IS_NULL_UNEXPECTEDLY(pIC)) 1455 return FALSE; 1456 1457 ret = pIC->fOpen; 1458 ImmUnlockIMC(hIMC); 1459 TRACE("ret: %d\n", ret); 1460 return ret; 1461 } 1462 1463 /*********************************************************************** 1464 * ImmSetOpenStatus (IMM32.@) 1465 */ 1466 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) 1467 { 1468 DWORD dwConversion; 1469 LPINPUTCONTEXT pIC; 1470 HWND hWnd; 1471 BOOL bHasChange = FALSE; 1472 1473 TRACE("(%p, %d)\n", hIMC, fOpen); 1474 1475 if (IS_CROSS_THREAD_HIMC(hIMC)) 1476 return FALSE; 1477 1478 pIC = ImmLockIMC(hIMC); 1479 if (IS_NULL_UNEXPECTEDLY(pIC)) 1480 return FALSE; 1481 1482 if (pIC->fOpen != fOpen) 1483 { 1484 pIC->fOpen = fOpen; 1485 hWnd = pIC->hWnd; 1486 dwConversion = pIC->fdwConversion; 1487 bHasChange = TRUE; 1488 } 1489 1490 ImmUnlockIMC(hIMC); 1491 1492 if (bHasChange) 1493 { 1494 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, 1495 IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0); 1496 NtUserNotifyIMEStatus(hWnd, fOpen, dwConversion); 1497 } 1498 else 1499 { 1500 TRACE("No change.\n"); 1501 } 1502 1503 return TRUE; 1504 } 1505 1506 /*********************************************************************** 1507 * ImmGetStatusWindowPos (IMM32.@) 1508 */ 1509 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 1510 { 1511 LPINPUTCONTEXT pIC; 1512 BOOL ret; 1513 1514 TRACE("(%p, %p)\n", hIMC, lpptPos); 1515 1516 pIC = ImmLockIMC(hIMC); 1517 if (IS_NULL_UNEXPECTEDLY(pIC)) 1518 return FALSE; 1519 1520 ret = !!(pIC->fdwInit & INIT_STATUSWNDPOS); 1521 if (ret) 1522 *lpptPos = pIC->ptStatusWndPos; 1523 1524 ImmUnlockIMC(hIMC); 1525 return ret; 1526 } 1527 1528 /*********************************************************************** 1529 * ImmSetStatusWindowPos (IMM32.@) 1530 */ 1531 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) 1532 { 1533 LPINPUTCONTEXT pIC; 1534 HWND hWnd; 1535 1536 TRACE("(%p, {%ld, %ld})\n", hIMC, lpptPos->x, lpptPos->y); 1537 1538 if (IS_CROSS_THREAD_HIMC(hIMC)) 1539 return FALSE; 1540 1541 pIC = ImmLockIMC(hIMC); 1542 if (IS_NULL_UNEXPECTEDLY(pIC)) 1543 return FALSE; 1544 1545 hWnd = pIC->hWnd; 1546 pIC->ptStatusWndPos = *lpptPos; 1547 pIC->fdwInit |= INIT_STATUSWNDPOS; 1548 1549 ImmUnlockIMC(hIMC); 1550 1551 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, 1552 IMC_SETSTATUSWINDOWPOS, IMN_SETSTATUSWINDOWPOS, 0); 1553 return TRUE; 1554 } 1555 1556 /*********************************************************************** 1557 * ImmGetCompositionWindow (IMM32.@) 1558 */ 1559 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 1560 { 1561 LPINPUTCONTEXT pIC; 1562 BOOL ret = FALSE; 1563 1564 TRACE("(%p, %p)\n", hIMC, lpCompForm); 1565 1566 pIC = ImmLockIMC(hIMC); 1567 if (IS_NULL_UNEXPECTEDLY(pIC)) 1568 return FALSE; 1569 1570 if (pIC->fdwInit & INIT_COMPFORM) 1571 { 1572 *lpCompForm = pIC->cfCompForm; 1573 ret = TRUE; 1574 } 1575 1576 ImmUnlockIMC(hIMC); 1577 return ret; 1578 } 1579 1580 /*********************************************************************** 1581 * ImmSetCompositionWindow (IMM32.@) 1582 */ 1583 BOOL WINAPI ImmSetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) 1584 { 1585 LPINPUTCONTEXTDX pIC; 1586 HWND hWnd; 1587 1588 if (Imm32IsCrossThreadAccess(hIMC)) 1589 return FALSE; 1590 1591 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 1592 if (IS_NULL_UNEXPECTEDLY(pIC)) 1593 return FALSE; 1594 1595 pIC->cfCompForm = *lpCompForm; 1596 pIC->fdwInit |= INIT_COMPFORM; 1597 1598 if (pIC->dwUIFlags & 0x8) 1599 pIC->dwUIFlags &= ~0x8; 1600 else 1601 pIC->dwUIFlags &= ~0x2; 1602 1603 hWnd = pIC->hWnd; 1604 1605 ImmUnlockIMC(hIMC); 1606 1607 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, 1608 IMC_SETCOMPOSITIONWINDOW, IMN_SETCOMPOSITIONWINDOW, 0); 1609 return TRUE; 1610 } 1611 1612 /*********************************************************************** 1613 * ImmGetCompositionFontA (IMM32.@) 1614 */ 1615 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 1616 { 1617 PCLIENTIMC pClientImc; 1618 BOOL ret = FALSE, bWide; 1619 LPINPUTCONTEXT pIC; 1620 1621 TRACE("(%p, %p)\n", hIMC, lplf); 1622 1623 pClientImc = ImmLockClientImc(hIMC); 1624 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1625 return FALSE; 1626 1627 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1628 ImmUnlockClientImc(pClientImc); 1629 1630 pIC = ImmLockIMC(hIMC); 1631 if (IS_NULL_UNEXPECTEDLY(pIC)) 1632 return FALSE; 1633 1634 if (pIC->fdwInit & INIT_LOGFONT) 1635 { 1636 if (bWide) 1637 LogFontWideToAnsi(&pIC->lfFont.W, lplf); 1638 else 1639 *lplf = pIC->lfFont.A; 1640 1641 ret = TRUE; 1642 } 1643 1644 ImmUnlockIMC(hIMC); 1645 return ret; 1646 } 1647 1648 /*********************************************************************** 1649 * ImmGetCompositionFontW (IMM32.@) 1650 */ 1651 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 1652 { 1653 PCLIENTIMC pClientImc; 1654 BOOL bWide; 1655 LPINPUTCONTEXT pIC; 1656 BOOL ret = FALSE; 1657 1658 TRACE("(%p, %p)\n", hIMC, lplf); 1659 1660 pClientImc = ImmLockClientImc(hIMC); 1661 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1662 return FALSE; 1663 1664 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1665 ImmUnlockClientImc(pClientImc); 1666 1667 pIC = ImmLockIMC(hIMC); 1668 if (IS_NULL_UNEXPECTEDLY(pIC)) 1669 return FALSE; 1670 1671 if (pIC->fdwInit & INIT_LOGFONT) 1672 { 1673 if (bWide) 1674 *lplf = pIC->lfFont.W; 1675 else 1676 LogFontAnsiToWide(&pIC->lfFont.A, lplf); 1677 1678 ret = TRUE; 1679 } 1680 1681 ImmUnlockIMC(hIMC); 1682 return ret; 1683 } 1684 1685 /*********************************************************************** 1686 * ImmSetCompositionFontA (IMM32.@) 1687 */ 1688 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) 1689 { 1690 LOGFONTW lfW; 1691 PCLIENTIMC pClientImc; 1692 BOOL bWide; 1693 LPINPUTCONTEXTDX pIC; 1694 LANGID LangID; 1695 HWND hWnd; 1696 1697 TRACE("(%p, %p)\n", hIMC, lplf); 1698 1699 if (IS_CROSS_THREAD_HIMC(hIMC)) 1700 return FALSE; 1701 1702 pClientImc = ImmLockClientImc(hIMC); 1703 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1704 return FALSE; 1705 1706 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1707 ImmUnlockClientImc(pClientImc); 1708 1709 if (bWide) 1710 { 1711 LogFontAnsiToWide(lplf, &lfW); 1712 return ImmSetCompositionFontW(hIMC, &lfW); 1713 } 1714 1715 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 1716 if (IS_NULL_UNEXPECTEDLY(pIC)) 1717 return FALSE; 1718 1719 if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* old version (3.x)? */ 1720 { 1721 LangID = LANGIDFROMLCID(GetSystemDefaultLCID()); 1722 if (PRIMARYLANGID(LangID) == LANG_JAPANESE && 1723 !(pIC->dwUIFlags & 2) && 1724 pIC->cfCompForm.dwStyle != CFS_DEFAULT) 1725 { 1726 PostMessageA(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0); 1727 } 1728 } 1729 1730 pIC->lfFont.A = *lplf; 1731 pIC->fdwInit |= INIT_LOGFONT; 1732 hWnd = pIC->hWnd; 1733 1734 ImmUnlockIMC(hIMC); 1735 1736 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT, 1737 IMN_SETCOMPOSITIONFONT, 0); 1738 return TRUE; 1739 } 1740 1741 /*********************************************************************** 1742 * ImmSetCompositionFontW (IMM32.@) 1743 */ 1744 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) 1745 { 1746 LOGFONTA lfA; 1747 PCLIENTIMC pClientImc; 1748 BOOL bWide; 1749 HWND hWnd; 1750 LPINPUTCONTEXTDX pIC; 1751 LANGID LangID; 1752 1753 TRACE("(%p, %p)\n", hIMC, lplf); 1754 1755 if (IS_CROSS_THREAD_HIMC(hIMC)) 1756 return FALSE; 1757 1758 pClientImc = ImmLockClientImc(hIMC); 1759 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1760 return FALSE; 1761 1762 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 1763 ImmUnlockClientImc(pClientImc); 1764 1765 if (!bWide) 1766 { 1767 LogFontWideToAnsi(lplf, &lfA); 1768 return ImmSetCompositionFontA(hIMC, &lfA); 1769 } 1770 1771 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 1772 if (IS_NULL_UNEXPECTEDLY(pIC)) 1773 return FALSE; 1774 1775 if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* old version (3.x)? */ 1776 { 1777 LangID = LANGIDFROMLCID(GetSystemDefaultLCID()); 1778 if (PRIMARYLANGID(LangID) == LANG_JAPANESE && 1779 !(pIC->dwUIFlags & 2) && 1780 pIC->cfCompForm.dwStyle != CFS_DEFAULT) 1781 { 1782 PostMessageW(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0); 1783 } 1784 } 1785 1786 pIC->lfFont.W = *lplf; 1787 pIC->fdwInit |= INIT_LOGFONT; 1788 hWnd = pIC->hWnd; 1789 1790 ImmUnlockIMC(hIMC); 1791 1792 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT, 1793 IMN_SETCOMPOSITIONFONT, 0); 1794 return TRUE; 1795 } 1796 1797 /*********************************************************************** 1798 * ImmGetConversionListA (IMM32.@) 1799 */ 1800 DWORD WINAPI 1801 ImmGetConversionListA(HKL hKL, HIMC hIMC, LPCSTR pSrc, LPCANDIDATELIST lpDst, 1802 DWORD dwBufLen, UINT uFlag) 1803 { 1804 DWORD ret = 0; 1805 UINT cb; 1806 LPWSTR pszSrcW = NULL; 1807 LPCANDIDATELIST pCL = NULL; 1808 PIMEDPI pImeDpi; 1809 1810 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_a(pSrc), 1811 lpDst, dwBufLen, uFlag); 1812 1813 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1814 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1815 return 0; 1816 1817 if (!ImeDpi_IsUnicode(pImeDpi)) /* No conversion needed */ 1818 { 1819 ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag); 1820 ImmUnlockImeDpi(pImeDpi); 1821 return ret; 1822 } 1823 1824 if (pSrc) 1825 { 1826 pszSrcW = Imm32WideFromAnsi(pImeDpi->uCodePage, pSrc); 1827 if (IS_NULL_UNEXPECTEDLY(pszSrcW)) 1828 goto Quit; 1829 } 1830 1831 cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, NULL, 0, uFlag); 1832 if (IS_ZERO_UNEXPECTEDLY(cb)) 1833 goto Quit; 1834 1835 pCL = ImmLocalAlloc(0, cb); 1836 if (IS_NULL_UNEXPECTEDLY(pCL)) 1837 goto Quit; 1838 1839 cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, pCL, cb, uFlag); 1840 if (IS_ZERO_UNEXPECTEDLY(cb)) 1841 goto Quit; 1842 1843 ret = CandidateListWideToAnsi(pCL, lpDst, dwBufLen, pImeDpi->uCodePage); 1844 1845 Quit: 1846 ImmLocalFree(pszSrcW); 1847 ImmLocalFree(pCL); 1848 ImmUnlockImeDpi(pImeDpi); 1849 TRACE("ret: 0x%X\n", ret); 1850 return ret; 1851 } 1852 1853 /*********************************************************************** 1854 * ImmGetConversionListW (IMM32.@) 1855 */ 1856 DWORD WINAPI 1857 ImmGetConversionListW(HKL hKL, HIMC hIMC, LPCWSTR pSrc, LPCANDIDATELIST lpDst, 1858 DWORD dwBufLen, UINT uFlag) 1859 { 1860 DWORD ret = 0; 1861 INT cb; 1862 PIMEDPI pImeDpi; 1863 LPCANDIDATELIST pCL = NULL; 1864 LPSTR pszSrcA = NULL; 1865 1866 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_w(pSrc), 1867 lpDst, dwBufLen, uFlag); 1868 1869 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1870 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1871 return 0; 1872 1873 if (ImeDpi_IsUnicode(pImeDpi)) /* No conversion needed */ 1874 { 1875 ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag); 1876 ImmUnlockImeDpi(pImeDpi); 1877 return ret; 1878 } 1879 1880 if (pSrc) 1881 { 1882 pszSrcA = Imm32AnsiFromWide(pImeDpi->uCodePage, pSrc); 1883 if (IS_NULL_UNEXPECTEDLY(pszSrcA)) 1884 goto Quit; 1885 } 1886 1887 cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, NULL, 0, uFlag); 1888 if (IS_ZERO_UNEXPECTEDLY(cb)) 1889 goto Quit; 1890 1891 pCL = ImmLocalAlloc(0, cb); 1892 if (IS_NULL_UNEXPECTEDLY(pCL)) 1893 goto Quit; 1894 1895 cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, pCL, cb, uFlag); 1896 if (IS_ZERO_UNEXPECTEDLY(cb)) 1897 goto Quit; 1898 1899 ret = CandidateListAnsiToWide(pCL, lpDst, dwBufLen, pImeDpi->uCodePage); 1900 1901 Quit: 1902 ImmLocalFree(pszSrcA); 1903 ImmLocalFree(pCL); 1904 ImmUnlockImeDpi(pImeDpi); 1905 TRACE("ret: 0x%X\n", ret); 1906 return ret; 1907 } 1908 1909 /*********************************************************************** 1910 * ImmGetConversionStatus (IMM32.@) 1911 */ 1912 BOOL WINAPI ImmGetConversionStatus(HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence) 1913 { 1914 LPINPUTCONTEXT pIC; 1915 1916 TRACE("(%p %p %p)\n", hIMC, lpfdwConversion, lpfdwSentence); 1917 1918 pIC = ImmLockIMC(hIMC); 1919 if (IS_NULL_UNEXPECTEDLY(pIC)) 1920 return FALSE; 1921 1922 if (lpfdwConversion) 1923 { 1924 *lpfdwConversion = pIC->fdwConversion; 1925 TRACE("0x%X\n", *lpfdwConversion); 1926 } 1927 1928 if (lpfdwSentence) 1929 { 1930 *lpfdwSentence = pIC->fdwSentence; 1931 TRACE("0x%X\n", *lpfdwSentence); 1932 } 1933 1934 ImmUnlockIMC(hIMC); 1935 return TRUE; 1936 } 1937 1938 /*********************************************************************** 1939 * ImmSetConversionStatus (IMM32.@) 1940 */ 1941 BOOL WINAPI ImmSetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) 1942 { 1943 HKL hKL; 1944 LPINPUTCONTEXT pIC; 1945 DWORD dwOldConversion, dwOldSentence; 1946 BOOL fOpen = FALSE, fConversionChange = FALSE, fSentenceChange = FALSE, fUseCicero = FALSE; 1947 HWND hWnd; 1948 1949 TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC, fdwConversion, fdwSentence); 1950 1951 hKL = GetKeyboardLayout(0); 1952 if (!IS_IME_HKL(hKL) && IS_CICERO_MODE() && !IS_16BIT_MODE()) 1953 fUseCicero = TRUE; 1954 1955 if (IS_CROSS_THREAD_HIMC(hIMC)) 1956 return FALSE; 1957 1958 pIC = ImmLockIMC(hIMC); 1959 if (IS_NULL_UNEXPECTEDLY(pIC)) 1960 return FALSE; 1961 1962 if (pIC->fdwConversion != fdwConversion) 1963 { 1964 dwOldConversion = pIC->fdwConversion; 1965 pIC->fdwConversion = fdwConversion; 1966 fConversionChange = TRUE; 1967 } 1968 1969 if (pIC->fdwSentence != fdwSentence) 1970 { 1971 dwOldSentence = pIC->fdwSentence; 1972 pIC->fdwSentence = fdwSentence; 1973 fSentenceChange = TRUE; 1974 } 1975 1976 hWnd = pIC->hWnd; 1977 fOpen = pIC->fOpen; 1978 ImmUnlockIMC(hIMC); 1979 1980 if (fConversionChange || fUseCicero) 1981 { 1982 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldConversion, 1983 IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0); 1984 if (fConversionChange) 1985 NtUserNotifyIMEStatus(hWnd, fOpen, fdwConversion); 1986 } 1987 1988 if (fSentenceChange || fUseCicero) 1989 { 1990 Imm32MakeIMENotify(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldSentence, 1991 IMC_SETSENTENCEMODE, IMN_SETSENTENCEMODE, 0); 1992 } 1993 1994 return TRUE; 1995 } 1996 1997 /*********************************************************************** 1998 * ImmConfigureIMEA (IMM32.@) 1999 */ 2000 BOOL WINAPI ImmConfigureIMEA(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 2001 { 2002 BOOL ret = FALSE; 2003 PIMEDPI pImeDpi; 2004 REGISTERWORDW RegWordW; 2005 LPREGISTERWORDA pRegWordA; 2006 2007 TRACE("(%p, %p, 0x%lX, %p)\n", hKL, hWnd, dwMode, lpData); 2008 2009 if (IS_NULL_UNEXPECTEDLY(ValidateHwnd(hWnd)) || IS_CROSS_PROCESS_HWND(hWnd)) 2010 return FALSE; 2011 2012 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 2013 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 2014 return FALSE; 2015 2016 RtlZeroMemory(&RegWordW, sizeof(RegWordW)); 2017 2018 if (!ImeDpi_IsUnicode(pImeDpi) || !lpData || dwMode != IME_CONFIG_REGISTERWORD) 2019 goto DoIt; /* No conversion needed */ 2020 2021 pRegWordA = lpData; 2022 2023 if (pRegWordA->lpReading) 2024 { 2025 RegWordW.lpReading = Imm32WideFromAnsi(pImeDpi->uCodePage, pRegWordA->lpReading); 2026 if (IS_NULL_UNEXPECTEDLY(RegWordW.lpReading)) 2027 goto Quit; 2028 } 2029 2030 if (pRegWordA->lpWord) 2031 { 2032 RegWordW.lpWord = Imm32WideFromAnsi(pImeDpi->uCodePage, pRegWordA->lpWord); 2033 if (IS_NULL_UNEXPECTEDLY(RegWordW.lpWord)) 2034 goto Quit; 2035 } 2036 2037 lpData = &RegWordW; 2038 2039 DoIt: 2040 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1B, 0); 2041 ret = pImeDpi->ImeConfigure(hKL, hWnd, dwMode, lpData); 2042 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1A, 0); 2043 2044 Quit: 2045 ImmLocalFree(RegWordW.lpReading); 2046 ImmLocalFree(RegWordW.lpWord); 2047 ImmUnlockImeDpi(pImeDpi); 2048 TRACE("ret: %d\n", ret); 2049 return ret; 2050 } 2051 2052 /*********************************************************************** 2053 * ImmConfigureIMEW (IMM32.@) 2054 */ 2055 BOOL WINAPI ImmConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) 2056 { 2057 BOOL ret = FALSE; 2058 PIMEDPI pImeDpi; 2059 REGISTERWORDA RegWordA; 2060 LPREGISTERWORDW pRegWordW; 2061 2062 TRACE("(%p, %p, 0x%lX, %p)\n", hKL, hWnd, dwMode, lpData); 2063 2064 if (IS_NULL_UNEXPECTEDLY(ValidateHwnd(hWnd)) || IS_CROSS_PROCESS_HWND(hWnd)) 2065 return FALSE; 2066 2067 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 2068 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 2069 return FALSE; 2070 2071 RtlZeroMemory(&RegWordA, sizeof(RegWordA)); 2072 2073 if (ImeDpi_IsUnicode(pImeDpi) || !lpData || dwMode != IME_CONFIG_REGISTERWORD) 2074 goto DoIt; /* No conversion needed */ 2075 2076 pRegWordW = lpData; 2077 2078 if (pRegWordW->lpReading) 2079 { 2080 RegWordA.lpReading = Imm32AnsiFromWide(pImeDpi->uCodePage, pRegWordW->lpReading); 2081 if (IS_NULL_UNEXPECTEDLY(RegWordA.lpReading)) 2082 goto Quit; 2083 } 2084 2085 if (pRegWordW->lpWord) 2086 { 2087 RegWordA.lpWord = Imm32AnsiFromWide(pImeDpi->uCodePage, pRegWordW->lpWord); 2088 if (IS_NULL_UNEXPECTEDLY(RegWordA.lpWord)) 2089 goto Quit; 2090 } 2091 2092 lpData = &RegWordA; 2093 2094 DoIt: 2095 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1B, 0); 2096 ret = pImeDpi->ImeConfigure(hKL, hWnd, dwMode, lpData); 2097 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1A, 0); 2098 2099 Quit: 2100 ImmLocalFree(RegWordA.lpReading); 2101 ImmLocalFree(RegWordA.lpWord); 2102 ImmUnlockImeDpi(pImeDpi); 2103 TRACE("ret: %d\n", ret); 2104 return ret; 2105 } 2106 2107 /*********************************************************************** 2108 * ImmGetImeMenuItemsA (IMM32.@) 2109 */ 2110 DWORD WINAPI 2111 ImmGetImeMenuItemsA(HIMC hIMC, DWORD dwFlags, DWORD dwType, 2112 LPIMEMENUITEMINFOA lpImeParentMenu, 2113 LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize) 2114 { 2115 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", 2116 hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize); 2117 return ImmGetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize, TRUE); 2118 } 2119 2120 /*********************************************************************** 2121 * ImmGetImeMenuItemsW (IMM32.@) 2122 */ 2123 DWORD WINAPI 2124 ImmGetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType, 2125 LPIMEMENUITEMINFOW lpImeParentMenu, 2126 LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize) 2127 { 2128 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", 2129 hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize); 2130 return ImmGetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize, FALSE); 2131 } 2132 2133 /*********************************************************************** 2134 * ImmWINNLSEnableIME (IMM32.@) 2135 */ 2136 BOOL WINAPI ImmWINNLSEnableIME(HWND hWnd, BOOL enable) 2137 { 2138 HIMC hIMC; 2139 PCLIENTIMC pClientImc; 2140 HWND hImeWnd; 2141 BOOL bImeWnd, ret; 2142 2143 TRACE("(%p, %d)\n", hWnd, enable); 2144 2145 if (!Imm32IsSystemJapaneseOrKorean()) 2146 { 2147 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2148 return FALSE; 2149 } 2150 2151 hIMC = (HIMC)NtUserGetThreadState(THREADSTATE_DEFAULTINPUTCONTEXT); 2152 if (IS_NULL_UNEXPECTEDLY(hIMC)) 2153 return FALSE; 2154 2155 pClientImc = ImmLockClientImc(hIMC); 2156 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 2157 return FALSE; 2158 2159 ret = !(pClientImc->dwFlags & CLIENTIMC_DISABLEIME); 2160 if (!!enable == ret) 2161 { 2162 TRACE("Same\n"); 2163 ImmUnlockClientImc(pClientImc); 2164 return ret; 2165 } 2166 2167 if (!IsWindow(hWnd)) 2168 hWnd = GetFocus(); 2169 2170 hImeWnd = ImmGetDefaultIMEWnd(hWnd); 2171 bImeWnd = IsWindow(hImeWnd); 2172 if (bImeWnd) 2173 ImmSetActiveContext(hWnd, (enable ? NULL : hIMC), FALSE); 2174 2175 if (enable) 2176 pClientImc->dwFlags &= ~CLIENTIMC_DISABLEIME; 2177 else 2178 pClientImc->dwFlags |= CLIENTIMC_DISABLEIME; 2179 2180 ImmUnlockClientImc(pClientImc); 2181 2182 if (bImeWnd) 2183 ImmSetActiveContext(hWnd, (enable ? hIMC : NULL), TRUE); 2184 2185 return ret; 2186 } 2187