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