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