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