[IMM32] Rewrite ImmEscapeA/W (#3959)
[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 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
10 * Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
11 */
12
13 #include "precomp.h"
14
15 WINE_DEFAULT_DEBUG_CHANNEL(imm);
16
17 RTL_CRITICAL_SECTION g_csImeDpi;
18 PIMEDPI g_pImeDpiList = NULL;
19
20 PIMEDPI APIENTRY Imm32FindImeDpi(HKL hKL)
21 {
22 PIMEDPI pImeDpi;
23
24 RtlEnterCriticalSection(&g_csImeDpi);
25 for (pImeDpi = g_pImeDpiList; pImeDpi != NULL; pImeDpi = pImeDpi->pNext)
26 {
27 if (pImeDpi->hKL == hKL)
28 break;
29 }
30 RtlLeaveCriticalSection(&g_csImeDpi);
31
32 return pImeDpi;
33 }
34
35 VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy)
36 {
37 if (pImeDpi->hInst == NULL)
38 return;
39 if (bDestroy)
40 pImeDpi->ImeDestroy(0);
41 FreeLibrary(pImeDpi->hInst);
42 pImeDpi->hInst = NULL;
43 }
44
45 BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi)
46 {
47 WCHAR szUIClass[64];
48 WNDCLASSW wcW;
49 DWORD dwSysInfoFlags = 0; // TODO: ???
50 LPIMEINFO pImeInfo = &pImeDpi->ImeInfo;
51
52 // TODO: NtUserGetThreadState(16);
53
54 if (!IS_IME_HKL(pImeDpi->hKL))
55 {
56 if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED) &&
57 pImeDpi->CtfImeInquireExW)
58 {
59 // TODO:
60 return FALSE;
61 }
62 }
63
64 if (!pImeDpi->ImeInquire(pImeInfo, szUIClass, dwSysInfoFlags))
65 return FALSE;
66
67 szUIClass[_countof(szUIClass) - 1] = 0;
68
69 if (pImeInfo->dwPrivateDataSize == 0)
70 pImeInfo->dwPrivateDataSize = 4;
71
72 #define VALID_IME_PROP (IME_PROP_AT_CARET | \
73 IME_PROP_SPECIAL_UI | \
74 IME_PROP_CANDLIST_START_FROM_1 | \
75 IME_PROP_UNICODE | \
76 IME_PROP_COMPLETE_ON_UNSELECT | \
77 IME_PROP_END_UNLOAD | \
78 IME_PROP_KBD_CHAR_FIRST | \
79 IME_PROP_IGNORE_UPKEYS | \
80 IME_PROP_NEED_ALTKEY | \
81 IME_PROP_NO_KEYS_ON_CLOSE | \
82 IME_PROP_ACCEPT_WIDE_VKEY)
83 #define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
84 IME_CMODE_NATIVE | \
85 IME_CMODE_KATAKANA | \
86 IME_CMODE_LANGUAGE | \
87 IME_CMODE_FULLSHAPE | \
88 IME_CMODE_ROMAN | \
89 IME_CMODE_CHARCODE | \
90 IME_CMODE_HANJACONVERT | \
91 IME_CMODE_SOFTKBD | \
92 IME_CMODE_NOCONVERSION | \
93 IME_CMODE_EUDC | \
94 IME_CMODE_SYMBOL | \
95 IME_CMODE_FIXED)
96 #define VALID_SMODE_CAPS (IME_SMODE_NONE | \
97 IME_SMODE_PLAURALCLAUSE | \
98 IME_SMODE_SINGLECONVERT | \
99 IME_SMODE_AUTOMATIC | \
100 IME_SMODE_PHRASEPREDICT | \
101 IME_SMODE_CONVERSATION)
102 #define VALID_UI_CAPS (UI_CAP_2700 | \
103 UI_CAP_ROT90 | \
104 UI_CAP_ROTANY | \
105 UI_CAP_SOFTKBD)
106 #define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \
107 SCS_CAP_MAKEREAD | \
108 SCS_CAP_SETRECONVERTSTRING)
109 #define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
110
111 if (pImeInfo->fdwProperty & ~VALID_IME_PROP)
112 return FALSE;
113 if (pImeInfo->fdwConversionCaps & ~VALID_CMODE_CAPS)
114 return FALSE;
115 if (pImeInfo->fdwSentenceCaps & ~VALID_SMODE_CAPS)
116 return FALSE;
117 if (pImeInfo->fdwUICaps & ~VALID_UI_CAPS)
118 return FALSE;
119 if (pImeInfo->fdwSCSCaps & ~VALID_SCS_CAPS)
120 return FALSE;
121 if (pImeInfo->fdwSelectCaps & ~VALID_SELECT_CAPS)
122 return FALSE;
123
124 #undef VALID_IME_PROP
125 #undef VALID_CMODE_CAPS
126 #undef VALID_SMODE_CAPS
127 #undef VALID_UI_CAPS
128 #undef VALID_SCS_CAPS
129 #undef VALID_SELECT_CAPS
130
131 if (pImeInfo->fdwProperty & IME_PROP_UNICODE)
132 {
133 StringCchCopyW(pImeDpi->szUIClass, _countof(pImeDpi->szUIClass), szUIClass);
134 }
135 else
136 {
137 if (pImeDpi->uCodePage != GetACP() && pImeDpi->uCodePage)
138 return FALSE;
139
140 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPSTR)szUIClass, -1,
141 pImeDpi->szUIClass, _countof(pImeDpi->szUIClass));
142 }
143
144 return GetClassInfoW(pImeDpi->hInst, pImeDpi->szUIClass, &wcW);
145 }
146
147 BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
148 {
149 WCHAR szPath[MAX_PATH];
150 HINSTANCE hIME;
151 FARPROC fn;
152
153 if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile))
154 return FALSE;
155
156 hIME = GetModuleHandleW(szPath);
157 if (hIME == NULL)
158 {
159 hIME = LoadLibraryW(szPath);
160 if (hIME == NULL)
161 {
162 ERR("Imm32LoadImeInfo: LoadLibraryW(%S) failed\n", szPath);
163 return FALSE;
164 }
165 }
166 pImeDpi->hInst = hIME;
167
168 #define DEFINE_IME_ENTRY(type, name, params, extended) \
169 do { \
170 fn = GetProcAddress(hIME, #name); \
171 if (fn) pImeDpi->name = (FN_##name)fn; \
172 else if (!extended) goto Failed; \
173 } while (0);
174 #include "../../../win32ss/include/imetable.h"
175 #undef DEFINE_IME_ENTRY
176
177 if (!Imm32InquireIme(pImeDpi))
178 {
179 ERR("Imm32LoadImeInfo: Imm32InquireIme failed\n");
180 goto Failed;
181 }
182
183 if (pImeInfoEx->fLoadFlag)
184 return TRUE;
185
186 NtUserSetImeOwnerWindow(pImeInfoEx, TRUE);
187 return TRUE;
188
189 Failed:
190 FreeLibrary(pImeDpi->hInst);
191 pImeDpi->hInst = NULL;
192 return FALSE;
193 }
194
195 PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock)
196 {
197 IMEINFOEX ImeInfoEx;
198 CHARSETINFO ci;
199 PIMEDPI pImeDpiNew, pImeDpiFound;
200 UINT uCodePage;
201 LCID lcid;
202
203 if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL) ||
204 ImeInfoEx.fLoadFlag == 1)
205 {
206 return NULL;
207 }
208
209 pImeDpiNew = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(IMEDPI));
210 if (pImeDpiNew == NULL)
211 return NULL;
212
213 pImeDpiNew->hKL = hKL;
214
215 lcid = LOWORD(hKL);
216 if (TranslateCharsetInfo((LPDWORD)(DWORD_PTR)lcid, &ci, TCI_SRCLOCALE))
217 uCodePage = ci.ciACP;
218 else
219 uCodePage = CP_ACP;
220 pImeDpiNew->uCodePage = uCodePage;
221
222 if (!Imm32LoadImeInfo(&ImeInfoEx, pImeDpiNew))
223 {
224 HeapFree(g_hImm32Heap, 0, pImeDpiNew);
225 return FALSE;
226 }
227
228 RtlEnterCriticalSection(&g_csImeDpi);
229
230 pImeDpiFound = Imm32FindImeDpi(hKL);
231 if (pImeDpiFound)
232 {
233 if (!bLock)
234 pImeDpiFound->dwFlags &= ~IMEDPI_FLAG_LOCKED;
235
236 RtlLeaveCriticalSection(&g_csImeDpi);
237
238 Imm32FreeImeDpi(pImeDpiNew, FALSE);
239 HeapFree(g_hImm32Heap, 0, pImeDpiNew);
240 return pImeDpiFound;
241 }
242 else
243 {
244 if (bLock)
245 {
246 pImeDpiNew->dwFlags |= IMEDPI_FLAG_LOCKED;
247 pImeDpiNew->cLockObj = 1;
248 }
249
250 pImeDpiNew->pNext = g_pImeDpiList;
251 g_pImeDpiList = pImeDpiNew;
252
253 RtlLeaveCriticalSection(&g_csImeDpi);
254 return pImeDpiNew;
255 }
256 }
257
258 PIMEDPI APIENTRY ImmLockOrLoadImeDpi(HKL hKL)
259 {
260 PW32CLIENTINFO pInfo;
261 PIMEDPI pImeDpi;
262
263 if (!IS_IME_HKL(hKL))
264 {
265 if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
266 return NULL;
267
268 pInfo = (PW32CLIENTINFO)(NtCurrentTeb()->Win32ClientInfo);
269 if ((pInfo->W32ClientInfo[0] & 2))
270 return NULL;
271 }
272
273 pImeDpi = ImmLockImeDpi(hKL);
274 if (pImeDpi == NULL)
275 pImeDpi = Ime32LoadImeDpi(hKL, TRUE);
276 return pImeDpi;
277 }
278
279 static LRESULT APIENTRY
280 ImeDpi_Escape(PIMEDPI pImeDpi, HIMC hIMC, UINT uSubFunc, LPVOID lpData, HKL hKL)
281 {
282 if (IS_IME_HKL(hKL))
283 return pImeDpi->ImeEscape(hIMC, uSubFunc, lpData);
284
285 if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
286 {
287 if (pImeDpi->CtfImeEscapeEx)
288 return pImeDpi->CtfImeEscapeEx(hIMC, uSubFunc, lpData, hKL);
289 }
290 return 0;
291 }
292
293 /***********************************************************************
294 * ImmIsIME (IMM32.@)
295 */
296 BOOL WINAPI ImmIsIME(HKL hKL)
297 {
298 IMEINFOEX info;
299 TRACE("(%p)\n", hKL);
300 return !!ImmGetImeInfoEx(&info, ImeInfoExImeWindow, &hKL);
301 }
302
303 /***********************************************************************
304 * ImmGetDefaultIMEWnd (IMM32.@)
305 */
306 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
307 {
308 if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
309 return NULL;
310
311 // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
312 if (hWnd == NULL)
313 return (HWND)NtUserGetThreadState(3);
314
315 return (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_IME);
316 }
317
318 /***********************************************************************
319 * ImmNotifyIME (IMM32.@)
320 */
321 BOOL WINAPI ImmNotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
322 {
323 HKL hKL;
324 PIMEDPI pImeDpi;
325 BOOL ret;
326
327 TRACE("(%p, %lu, %lu, %lu)\n", hIMC, dwAction, dwIndex, dwValue);
328
329 if (hIMC && Imm32IsCrossThreadAccess(hIMC))
330 return FALSE;
331
332 hKL = GetKeyboardLayout(0);
333 pImeDpi = ImmLockImeDpi(hKL);
334 if (pImeDpi == NULL)
335 return FALSE;
336
337 ret = pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
338 ImmUnlockImeDpi(pImeDpi);
339 return ret;
340 }
341
342 /***********************************************************************
343 * ImmDisableLegacyIME(IMM32.@)
344 */
345 BOOL WINAPI ImmDisableLegacyIME(void)
346 {
347 FIXME("stub\n");
348 return TRUE;
349 }
350
351 /***********************************************************************
352 * CtfImmIsTextFrameServiceDisabled(IMM32.@)
353 */
354 BOOL WINAPI CtfImmIsTextFrameServiceDisabled(VOID)
355 {
356 PTEB pTeb = NtCurrentTeb();
357 if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->CI_flags & CI_TFSDISABLED)
358 return TRUE;
359 return FALSE;
360 }
361
362 /***********************************************************************
363 * ImmGetImeInfoEx (IMM32.@)
364 */
365 BOOL WINAPI
366 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID pvSearchKey)
367 {
368 BOOL bDisabled = FALSE;
369 HKL hKL;
370 PTEB pTeb;
371
372 switch (SearchType)
373 {
374 case ImeInfoExKeyboardLayout:
375 break;
376
377 case ImeInfoExImeWindow:
378 bDisabled = CtfImmIsTextFrameServiceDisabled();
379 SearchType = ImeInfoExKeyboardLayout;
380 break;
381
382 case ImeInfoExImeFileName:
383 StringCchCopyW(pImeInfoEx->wszImeFile, _countof(pImeInfoEx->wszImeFile),
384 pvSearchKey);
385 goto Quit;
386 }
387
388 hKL = *(HKL*)pvSearchKey;
389 pImeInfoEx->hkl = hKL;
390
391 if (!IS_IME_HKL(hKL))
392 {
393 if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
394 {
395 pTeb = NtCurrentTeb();
396 if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->W32ClientInfo[0] & 2)
397 return FALSE;
398 if (!bDisabled)
399 goto Quit;
400 }
401 return FALSE;
402 }
403
404 Quit:
405 return NtUserGetImeInfoEx(pImeInfoEx, SearchType);
406 }
407
408 /***********************************************************************
409 * ImmLockImeDpi (IMM32.@)
410 */
411 PIMEDPI WINAPI ImmLockImeDpi(HKL hKL)
412 {
413 PIMEDPI pImeDpi = NULL;
414
415 TRACE("(%p)\n", hKL);
416
417 RtlEnterCriticalSection(&g_csImeDpi);
418
419 /* Find by hKL */
420 for (pImeDpi = g_pImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext)
421 {
422 if (pImeDpi->hKL == hKL) /* found */
423 {
424 /* lock if possible */
425 if (pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN)
426 pImeDpi = NULL;
427 else
428 ++(pImeDpi->cLockObj);
429 break;
430 }
431 }
432
433 RtlLeaveCriticalSection(&g_csImeDpi);
434 return pImeDpi;
435 }
436
437 /***********************************************************************
438 * ImmUnlockImeDpi (IMM32.@)
439 */
440 VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi)
441 {
442 PIMEDPI *ppEntry;
443
444 TRACE("(%p)\n", pImeDpi);
445
446 if (pImeDpi == NULL)
447 return;
448
449 RtlEnterCriticalSection(&g_csImeDpi);
450
451 /* unlock */
452 --(pImeDpi->cLockObj);
453 if (pImeDpi->cLockObj != 0)
454 {
455 RtlLeaveCriticalSection(&g_csImeDpi);
456 return;
457 }
458
459 if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN) == 0)
460 {
461 if ((pImeDpi->dwFlags & IMEDPI_FLAG_LOCKED) == 0 ||
462 (pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD) == 0)
463 {
464 RtlLeaveCriticalSection(&g_csImeDpi);
465 return;
466 }
467 }
468
469 /* Remove from list */
470 for (ppEntry = &g_pImeDpiList; *ppEntry; ppEntry = &((*ppEntry)->pNext))
471 {
472 if (*ppEntry == pImeDpi) /* found */
473 {
474 *ppEntry = pImeDpi->pNext;
475 break;
476 }
477 }
478
479 Imm32FreeImeDpi(pImeDpi, TRUE);
480 HeapFree(g_hImm32Heap, 0, pImeDpi);
481
482 RtlLeaveCriticalSection(&g_csImeDpi);
483 }
484
485 /***********************************************************************
486 * ImmLoadIME (IMM32.@)
487 */
488 BOOL WINAPI ImmLoadIME(HKL hKL)
489 {
490 PW32CLIENTINFO pInfo;
491 PIMEDPI pImeDpi;
492
493 if (!IS_IME_HKL(hKL))
494 {
495 if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
496 return FALSE;
497
498 pInfo = (PW32CLIENTINFO)(NtCurrentTeb()->Win32ClientInfo);
499 if ((pInfo->W32ClientInfo[0] & 2))
500 return FALSE;
501 }
502
503 pImeDpi = Imm32FindImeDpi(hKL);
504 if (pImeDpi == NULL)
505 pImeDpi = Ime32LoadImeDpi(hKL, FALSE);
506 return (pImeDpi != NULL);
507 }
508
509 /***********************************************************************
510 * ImmDisableIME (IMM32.@)
511 */
512 BOOL WINAPI ImmDisableIME(DWORD dwThreadId)
513 {
514 return NtUserDisableThreadIme(dwThreadId);
515 }
516
517 /***********************************************************************
518 * ImmGetDescriptionA (IMM32.@)
519 */
520 UINT WINAPI ImmGetDescriptionA(HKL hKL, LPSTR lpszDescription, UINT uBufLen)
521 {
522 IMEINFOEX info;
523 size_t cch;
524
525 TRACE("(%p,%p,%d)\n", hKL, lpszDescription, uBufLen);
526
527 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
528 return 0;
529
530 StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch);
531 cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeDescription, (INT)cch,
532 lpszDescription, uBufLen, NULL, NULL);
533 if (uBufLen)
534 lpszDescription[cch] = 0;
535 return (UINT)cch;
536 }
537
538 /***********************************************************************
539 * ImmGetDescriptionW (IMM32.@)
540 */
541 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
542 {
543 IMEINFOEX info;
544 size_t cch;
545
546 TRACE("(%p, %p, %d)\n", hKL, lpszDescription, uBufLen);
547
548 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
549 return 0;
550
551 if (uBufLen != 0)
552 StringCchCopyW(lpszDescription, uBufLen, info.wszImeDescription);
553
554 StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch);
555 return (UINT)cch;
556 }
557
558 /***********************************************************************
559 * ImmGetIMEFileNameA (IMM32.@)
560 */
561 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
562 {
563 BOOL bDefUsed;
564 IMEINFOEX info;
565 size_t cch;
566
567 TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
568
569 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
570 {
571 if (uBufLen > 0)
572 lpszFileName[0] = 0;
573 return 0;
574 }
575
576 StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
577
578 cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeFile, (INT)cch,
579 lpszFileName, uBufLen, NULL, &bDefUsed);
580 if (uBufLen == 0)
581 return (UINT)cch;
582
583 if (cch > uBufLen - 1)
584 cch = uBufLen - 1;
585
586 lpszFileName[cch] = 0;
587 return (UINT)cch;
588 }
589
590 /***********************************************************************
591 * ImmGetIMEFileNameW (IMM32.@)
592 */
593 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
594 {
595 IMEINFOEX info;
596 size_t cch;
597
598 TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
599
600 if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
601 {
602 if (uBufLen > 0)
603 lpszFileName[0] = 0;
604 return 0;
605 }
606
607 StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
608 if (uBufLen == 0)
609 return (UINT)cch;
610
611 StringCchCopyNW(lpszFileName, uBufLen, info.wszImeFile, cch);
612
613 if (cch > uBufLen - 1)
614 cch = uBufLen - 1;
615
616 lpszFileName[cch] = 0;
617 return (UINT)cch;
618 }
619
620 /***********************************************************************
621 * ImmGetProperty (IMM32.@)
622 */
623 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
624 {
625 IMEINFOEX ImeInfoEx;
626 LPIMEINFO pImeInfo;
627 DWORD dwValue;
628 PIMEDPI pImeDpi = NULL;
629
630 TRACE("(%p, %lu)\n", hKL, fdwIndex);
631
632 if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL))
633 return FALSE;
634
635 if (fdwIndex == IGP_GETIMEVERSION)
636 return ImeInfoEx.dwImeWinVersion;
637
638 if (ImeInfoEx.fLoadFlag != 2)
639 {
640 pImeDpi = ImmLockOrLoadImeDpi(hKL);
641 if (pImeDpi == NULL)
642 return FALSE;
643
644 pImeInfo = &pImeDpi->ImeInfo;
645 }
646 else
647 {
648 pImeInfo = &ImeInfoEx.ImeInfo;
649 }
650
651 switch (fdwIndex)
652 {
653 case IGP_PROPERTY: dwValue = pImeInfo->fdwProperty; break;
654 case IGP_CONVERSION: dwValue = pImeInfo->fdwConversionCaps; break;
655 case IGP_SENTENCE: dwValue = pImeInfo->fdwSentenceCaps; break;
656 case IGP_UI: dwValue = pImeInfo->fdwUICaps; break;
657 case IGP_SETCOMPSTR: dwValue = pImeInfo->fdwSCSCaps; break;
658 case IGP_SELECT: dwValue = pImeInfo->fdwSelectCaps; break;
659 default: dwValue = 0; break;
660 }
661
662 if (pImeDpi)
663 ImmUnlockImeDpi(pImeDpi);
664 return dwValue;
665 }
666
667 /***********************************************************************
668 * ImmEscapeA (IMM32.@)
669 */
670 LRESULT WINAPI ImmEscapeA(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData)
671 {
672 LRESULT ret;
673 PIMEDPI pImeDpi;
674 INT cch;
675 CHAR szA[MAX_IMM_FILENAME];
676 WCHAR szW[MAX_IMM_FILENAME];
677
678 TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData);
679
680 pImeDpi = ImmLockOrLoadImeDpi(hKL);
681 if (!pImeDpi)
682 return 0;
683
684 if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || !lpData)
685 {
686 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL);
687 ImmUnlockImeDpi(pImeDpi);
688 return ret;
689 }
690
691 switch (uSubFunc)
692 {
693 case IME_ESC_SEQUENCE_TO_INTERNAL:
694 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL);
695
696 cch = 0;
697 if (HIWORD(ret))
698 szW[cch++] = HIWORD(ret);
699 if (LOWORD(ret))
700 szW[cch++] = LOWORD(ret);
701
702 cch = WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, cch, szA, _countof(szA),
703 NULL, NULL);
704 switch (cch)
705 {
706 case 1:
707 ret = MAKEWORD(szA[0], 0);
708 break;
709 case 2:
710 ret = MAKEWORD(szA[1], szA[0]);
711 break;
712 case 3:
713 ret = MAKELONG(MAKEWORD(szA[2], szA[1]), MAKEWORD(szA[0], 0));
714 break;
715 case 4:
716 ret = MAKELONG(MAKEWORD(szA[3], szA[2]), MAKEWORD(szA[1], szA[0]));
717 break;
718 default:
719 ret = 0;
720 break;
721 }
722 break;
723
724 case IME_ESC_GET_EUDC_DICTIONARY:
725 case IME_ESC_IME_NAME:
726 case IME_ESC_GETHELPFILENAME:
727 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL);
728 if (ret)
729 {
730 szW[_countof(szW) - 1] = 0;
731 WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, -1,
732 lpData, MAX_IMM_FILENAME, NULL, NULL);
733 ((LPSTR)lpData)[MAX_IMM_FILENAME - 1] = 0;
734 }
735 break;
736
737 case IME_ESC_SET_EUDC_DICTIONARY:
738 case IME_ESC_HANJA_MODE:
739 MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED,
740 lpData, -1, szW, _countof(szW));
741 szW[_countof(szW) - 1] = 0;
742 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL);
743 break;
744
745 default:
746 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL);
747 break;
748 }
749
750 ImmUnlockImeDpi(pImeDpi);
751 return ret;
752 }
753
754 /***********************************************************************
755 * ImmEscapeW (IMM32.@)
756 */
757 LRESULT WINAPI ImmEscapeW(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData)
758 {
759 LRESULT ret;
760 PIMEDPI pImeDpi;
761 INT cch;
762 CHAR szA[MAX_IMM_FILENAME];
763 WCHAR szW[MAX_IMM_FILENAME];
764 WORD word;
765
766 TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData);
767
768 pImeDpi = ImmLockOrLoadImeDpi(hKL);
769 if (!pImeDpi)
770 return 0;
771
772 if ((pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || !lpData)
773 {
774 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL);
775 ImmUnlockImeDpi(pImeDpi);
776 return ret;
777 }
778
779 switch (uSubFunc)
780 {
781 case IME_ESC_SEQUENCE_TO_INTERNAL:
782 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL);
783
784 word = LOWORD(ret);
785 cch = 0;
786 if (HIBYTE(word))
787 szA[cch++] = HIBYTE(word);
788 if (LOBYTE(word))
789 szA[cch++] = LOBYTE(word);
790
791 cch = MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED,
792 szA, cch, szW, _countof(szW));
793 switch (cch)
794 {
795 case 1: ret = szW[0]; break;
796 case 2: ret = MAKELONG(szW[1], szW[0]); break;
797 default: ret = 0; break;
798 }
799 break;
800
801 case IME_ESC_GET_EUDC_DICTIONARY:
802 case IME_ESC_IME_NAME:
803 case IME_ESC_GETHELPFILENAME:
804 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL);
805 if (ret)
806 {
807 szA[_countof(szA) - 1] = 0;
808 MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED,
809 szA, -1, lpData, MAX_IMM_FILENAME);
810 ((LPWSTR)lpData)[MAX_IMM_FILENAME - 1] = 0;
811 }
812 break;
813
814 case IME_ESC_SET_EUDC_DICTIONARY:
815 case IME_ESC_HANJA_MODE:
816 WideCharToMultiByte(pImeDpi->uCodePage, 0,
817 lpData, -1, szA, _countof(szA), NULL, NULL);
818 szA[_countof(szA) - 1] = 0;
819 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL);
820 break;
821
822 default:
823 ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL);
824 break;
825 }
826
827 ImmUnlockImeDpi(pImeDpi);
828 return ret;
829 }
830
831 /***********************************************************************
832 * ImmGetOpenStatus (IMM32.@)
833 */
834 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
835 {
836 BOOL ret;
837 LPINPUTCONTEXT pIC;
838
839 TRACE("(%p)\n", hIMC);
840
841 if (!hIMC)
842 return FALSE;
843
844 pIC = ImmLockIMC(hIMC);
845 if (!pIC)
846 return FALSE;
847
848 ret = pIC->fOpen;
849
850 ImmUnlockIMC(hIMC);
851 return ret;
852 }
853
854 /***********************************************************************
855 * ImmSetOpenStatus (IMM32.@)
856 */
857 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
858 {
859 DWORD dwConversion;
860 LPINPUTCONTEXT pIC;
861 HWND hWnd;
862 BOOL bHasChange = FALSE;
863
864 TRACE("(%p, %d)\n", hIMC, fOpen);
865
866 if (Imm32IsCrossThreadAccess(hIMC))
867 return FALSE;
868
869 pIC = ImmLockIMC(hIMC);
870 if (pIC == NULL)
871 return FALSE;
872
873 if (pIC->fOpen != fOpen)
874 {
875 pIC->fOpen = fOpen;
876 hWnd = pIC->hWnd;
877 dwConversion = pIC->fdwConversion;
878 bHasChange = TRUE;
879 }
880
881 ImmUnlockIMC(hIMC);
882
883 if (bHasChange)
884 {
885 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
886 IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0);
887 NtUserNotifyIMEStatus(hWnd, hIMC, dwConversion);
888 }
889
890 return TRUE;
891 }
892
893 /***********************************************************************
894 * ImmGetStatusWindowPos (IMM32.@)
895 */
896 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
897 {
898 LPINPUTCONTEXT pIC;
899 BOOL ret;
900
901 TRACE("(%p, %p)\n", hIMC, lpptPos);
902
903 pIC = ImmLockIMC(hIMC);
904 if (pIC == NULL)
905 return FALSE;
906
907 ret = !!(pIC->fdwInit & INIT_STATUSWNDPOS);
908 if (ret)
909 *lpptPos = pIC->ptStatusWndPos;
910
911 ImmUnlockIMC(hIMC);
912 return ret;
913 }
914
915 /***********************************************************************
916 * ImmSetStatusWindowPos (IMM32.@)
917 */
918 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
919 {
920 LPINPUTCONTEXT pIC;
921 HWND hWnd;
922
923 TRACE("(%p, {%ld, %ld})\n", hIMC, lpptPos->x, lpptPos->y);
924
925 if (Imm32IsCrossThreadAccess(hIMC))
926 return FALSE;
927
928 pIC = ImmLockIMC(hIMC);
929 if (!pIC)
930 return FALSE;
931
932 hWnd = pIC->hWnd;
933 pIC->ptStatusWndPos = *lpptPos;
934 pIC->fdwInit |= INIT_STATUSWNDPOS;
935
936 ImmUnlockIMC(hIMC);
937
938 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
939 IMC_SETSTATUSWINDOWPOS, IMN_SETSTATUSWINDOWPOS, 0);
940 return TRUE;
941 }
942
943 /***********************************************************************
944 * ImmGetCompositionWindow (IMM32.@)
945 */
946 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
947 {
948 LPINPUTCONTEXT pIC;
949 BOOL ret = FALSE;
950
951 TRACE("(%p, %p)\n", hIMC, lpCompForm);
952
953 pIC = ImmLockIMC(hIMC);
954 if (!pIC)
955 return FALSE;
956
957 if (pIC->fdwInit & INIT_COMPFORM)
958 {
959 *lpCompForm = pIC->cfCompForm;
960 ret = TRUE;
961 }
962
963 ImmUnlockIMC(hIMC);
964 return ret;
965 }
966
967 /***********************************************************************
968 * ImmSetCompositionWindow (IMM32.@)
969 */
970 BOOL WINAPI ImmSetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
971 {
972 LPINPUTCONTEXT pIC;
973 HWND hWnd;
974
975 if (Imm32IsCrossThreadAccess(hIMC))
976 return FALSE;
977
978 pIC = ImmLockIMC(hIMC);
979 if (pIC == NULL)
980 return FALSE;
981
982 pIC->cfCompForm = *lpCompForm;
983 pIC->fdwInit |= INIT_COMPFORM;
984
985 hWnd = pIC->hWnd;
986
987 ImmUnlockIMC(hIMC);
988
989 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
990 IMC_SETCOMPOSITIONWINDOW, IMN_SETCOMPOSITIONWINDOW, 0);
991 return TRUE;
992 }
993
994 /***********************************************************************
995 * ImmGetCompositionFontA (IMM32.@)
996 */
997 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
998 {
999 PCLIENTIMC pClientImc;
1000 BOOL ret = FALSE, bWide;
1001 LPINPUTCONTEXT pIC;
1002
1003 TRACE("(%p, %p)\n", hIMC, lplf);
1004
1005 pClientImc = ImmLockClientImc(hIMC);
1006 if (pClientImc == NULL)
1007 return FALSE;
1008
1009 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
1010 ImmUnlockClientImc(pClientImc);
1011
1012 pIC = ImmLockIMC(hIMC);
1013 if (pIC == NULL)
1014 return FALSE;
1015
1016 if (pIC->fdwInit & INIT_LOGFONT)
1017 {
1018 if (bWide)
1019 LogFontWideToAnsi(&pIC->lfFont.W, lplf);
1020 else
1021 *lplf = pIC->lfFont.A;
1022
1023 ret = TRUE;
1024 }
1025
1026 ImmUnlockIMC(hIMC);
1027 return ret;
1028 }
1029
1030 /***********************************************************************
1031 * ImmGetCompositionFontW (IMM32.@)
1032 */
1033 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1034 {
1035 PCLIENTIMC pClientImc;
1036 BOOL bWide;
1037 LPINPUTCONTEXT pIC;
1038 BOOL ret = FALSE;
1039
1040 TRACE("(%p, %p)\n", hIMC, lplf);
1041
1042 pClientImc = ImmLockClientImc(hIMC);
1043 if (pClientImc == NULL)
1044 return FALSE;
1045
1046 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
1047 ImmUnlockClientImc(pClientImc);
1048
1049 pIC = ImmLockIMC(hIMC);
1050 if (pIC == NULL)
1051 return FALSE;
1052
1053 if (pIC->fdwInit & INIT_LOGFONT)
1054 {
1055 if (bWide)
1056 *lplf = pIC->lfFont.W;
1057 else
1058 LogFontAnsiToWide(&pIC->lfFont.A, lplf);
1059
1060 ret = TRUE;
1061 }
1062
1063 ImmUnlockIMC(hIMC);
1064 return ret;
1065 }
1066
1067 /***********************************************************************
1068 * ImmSetCompositionFontA (IMM32.@)
1069 */
1070 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1071 {
1072 LOGFONTW lfW;
1073 PCLIENTIMC pClientImc;
1074 BOOL bWide;
1075 LPINPUTCONTEXTDX pIC;
1076 LCID lcid;
1077 HWND hWnd;
1078 PTEB pTeb;
1079
1080 TRACE("(%p, %p)\n", hIMC, lplf);
1081
1082 if (Imm32IsCrossThreadAccess(hIMC))
1083 return FALSE;
1084
1085 pClientImc = ImmLockClientImc(hIMC);
1086 if (pClientImc == NULL)
1087 return FALSE;
1088
1089 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
1090 ImmUnlockClientImc(pClientImc);
1091
1092 if (bWide)
1093 {
1094 LogFontAnsiToWide(lplf, &lfW);
1095 return ImmSetCompositionFontW(hIMC, &lfW);
1096 }
1097
1098 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
1099 if (pIC == NULL)
1100 return FALSE;
1101
1102 pTeb = NtCurrentTeb();
1103 if (pTeb->Win32ClientInfo[2] < 0x400)
1104 {
1105 lcid = GetSystemDefaultLCID();
1106 if (PRIMARYLANGID(lcid) == LANG_JAPANESE && !(pIC->dwUIFlags & 2) &&
1107 pIC->cfCompForm.dwStyle != CFS_DEFAULT)
1108 {
1109 PostMessageA(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
1110 }
1111 }
1112
1113 pIC->lfFont.A = *lplf;
1114 pIC->fdwInit |= INIT_LOGFONT;
1115 hWnd = pIC->hWnd;
1116
1117 ImmUnlockIMC(hIMC);
1118
1119 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT,
1120 IMN_SETCOMPOSITIONFONT, 0);
1121 return TRUE;
1122 }
1123
1124 /***********************************************************************
1125 * ImmSetCompositionFontW (IMM32.@)
1126 */
1127 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1128 {
1129 LOGFONTA lfA;
1130 PCLIENTIMC pClientImc;
1131 BOOL bWide;
1132 HWND hWnd;
1133 LPINPUTCONTEXTDX pIC;
1134 PTEB pTeb;
1135 LCID lcid;
1136
1137 TRACE("(%p, %p)\n", hIMC, lplf);
1138
1139 if (Imm32IsCrossThreadAccess(hIMC))
1140 return FALSE;
1141
1142 pClientImc = ImmLockClientImc(hIMC);
1143 if (pClientImc == NULL)
1144 return FALSE;
1145
1146 bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
1147 ImmUnlockClientImc(pClientImc);
1148
1149 if (!bWide)
1150 {
1151 LogFontWideToAnsi(lplf, &lfA);
1152 return ImmSetCompositionFontA(hIMC, &lfA);
1153 }
1154
1155 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
1156 if (pIC == NULL)
1157 return FALSE;
1158
1159 pTeb = NtCurrentTeb();
1160 if (pTeb->Win32ClientInfo[2] < 0x400)
1161 {
1162 lcid = GetSystemDefaultLCID();
1163 if (PRIMARYLANGID(lcid) == LANG_JAPANESE &&
1164 !(pIC->dwUIFlags & 2) &&
1165 pIC->cfCompForm.dwStyle != CFS_DEFAULT)
1166 {
1167 PostMessageW(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
1168 }
1169 }
1170
1171 pIC->lfFont.W = *lplf;
1172 pIC->fdwInit |= INIT_LOGFONT;
1173 hWnd = pIC->hWnd;
1174
1175 ImmUnlockIMC(hIMC);
1176
1177 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT,
1178 IMN_SETCOMPOSITIONFONT, 0);
1179 return TRUE;
1180 }
1181
1182 /***********************************************************************
1183 * ImmGetConversionListA (IMM32.@)
1184 */
1185 DWORD WINAPI
1186 ImmGetConversionListA(HKL hKL, HIMC hIMC, LPCSTR pSrc, LPCANDIDATELIST lpDst,
1187 DWORD dwBufLen, UINT uFlag)
1188 {
1189 DWORD ret = 0;
1190 UINT cb;
1191 LPWSTR pszSrcW = NULL;
1192 LPCANDIDATELIST pCL = NULL;
1193 PIMEDPI pImeDpi;
1194
1195 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_a(pSrc),
1196 lpDst, dwBufLen, uFlag);
1197
1198 pImeDpi = ImmLockOrLoadImeDpi(hKL);
1199 if (pImeDpi == NULL)
1200 return 0;
1201
1202 if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
1203 {
1204 ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag);
1205 ImmUnlockImeDpi(pImeDpi);
1206 return ret;
1207 }
1208
1209 if (pSrc)
1210 {
1211 pszSrcW = Imm32WideFromAnsi(pSrc);
1212 if (pszSrcW == NULL)
1213 goto Quit;
1214 }
1215
1216 cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, NULL, 0, uFlag);
1217 if (cb == 0)
1218 goto Quit;
1219
1220 pCL = Imm32HeapAlloc(0, cb);
1221 if (pCL == NULL)
1222 goto Quit;
1223
1224 cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, pCL, cb, uFlag);
1225 if (cb == 0)
1226 goto Quit;
1227
1228 ret = CandidateListWideToAnsi(pCL, lpDst, dwBufLen, CP_ACP);
1229
1230 Quit:
1231 if (pszSrcW)
1232 HeapFree(g_hImm32Heap, 0, pszSrcW);
1233 if (pCL)
1234 HeapFree(g_hImm32Heap, 0, pCL);
1235 ImmUnlockImeDpi(pImeDpi);
1236 return ret;
1237 }
1238
1239 /***********************************************************************
1240 * ImmGetConversionListW (IMM32.@)
1241 */
1242 DWORD WINAPI
1243 ImmGetConversionListW(HKL hKL, HIMC hIMC, LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1244 DWORD dwBufLen, UINT uFlag)
1245 {
1246 DWORD ret = 0;
1247 INT cb;
1248 PIMEDPI pImeDpi;
1249 LPCANDIDATELIST pCL = NULL;
1250 LPSTR pszSrcA = NULL;
1251
1252 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_w(pSrc),
1253 lpDst, dwBufLen, uFlag);
1254
1255 pImeDpi = ImmLockOrLoadImeDpi(hKL);
1256 if (!pImeDpi)
1257 return 0;
1258
1259 if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
1260 {
1261 ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag);
1262 ImmUnlockImeDpi(pImeDpi);
1263 return ret;
1264 }
1265
1266 if (pSrc)
1267 {
1268 pszSrcA = Imm32AnsiFromWide(pSrc);
1269 if (pszSrcA == NULL)
1270 goto Quit;
1271 }
1272
1273 cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, NULL, 0, uFlag);
1274 if (cb == 0)
1275 goto Quit;
1276
1277 pCL = Imm32HeapAlloc(0, cb);
1278 if (!pCL)
1279 goto Quit;
1280
1281 cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, pCL, cb, uFlag);
1282 if (!cb)
1283 goto Quit;
1284
1285 ret = CandidateListAnsiToWide(pCL, lpDst, dwBufLen, CP_ACP);
1286
1287 Quit:
1288 if (pszSrcA)
1289 HeapFree(g_hImm32Heap, 0, pszSrcA);
1290 if (pCL)
1291 HeapFree(g_hImm32Heap, 0, pCL);
1292 ImmUnlockImeDpi(pImeDpi);
1293 return ret;
1294 }
1295
1296 /***********************************************************************
1297 * ImmGetConversionStatus (IMM32.@)
1298 */
1299 BOOL WINAPI ImmGetConversionStatus(HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1300 {
1301 LPINPUTCONTEXT pIC;
1302
1303 TRACE("(%p %p %p)\n", hIMC, lpfdwConversion, lpfdwSentence);
1304
1305 pIC = ImmLockIMC(hIMC);
1306 if (!pIC)
1307 return FALSE;
1308
1309 if (lpfdwConversion)
1310 *lpfdwConversion = pIC->fdwConversion;
1311 if (lpfdwSentence)
1312 *lpfdwSentence = pIC->fdwSentence;
1313
1314 ImmUnlockIMC(hIMC);
1315 return TRUE;
1316 }
1317
1318 /***********************************************************************
1319 * ImmSetConversionStatus (IMM32.@)
1320 */
1321 BOOL WINAPI ImmSetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
1322 {
1323 HKL hKL;
1324 LPINPUTCONTEXT pIC;
1325 DWORD dwOldConversion, dwOldSentence;
1326 BOOL fConversionChange = FALSE, fSentenceChange = FALSE;
1327 HWND hWnd;
1328
1329 TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC, fdwConversion, fdwSentence);
1330
1331 hKL = GetKeyboardLayout(0);
1332 if (!IS_IME_HKL(hKL))
1333 {
1334 if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
1335 {
1336 FIXME("Cicero\n");
1337 return FALSE;
1338 }
1339 }
1340
1341 if (Imm32IsCrossThreadAccess(hIMC))
1342 return FALSE;
1343
1344 pIC = ImmLockIMC(hIMC);
1345 if (pIC == NULL)
1346 return FALSE;
1347
1348 if (pIC->fdwConversion != fdwConversion)
1349 {
1350 dwOldConversion = pIC->fdwConversion;
1351 pIC->fdwConversion = fdwConversion;
1352 fConversionChange = TRUE;
1353 }
1354
1355 if (pIC->fdwSentence != fdwSentence)
1356 {
1357 dwOldSentence = pIC->fdwSentence;
1358 pIC->fdwSentence = fdwSentence;
1359 fSentenceChange = TRUE;
1360 }
1361
1362 hWnd = pIC->hWnd;
1363 ImmUnlockIMC(hIMC);
1364
1365 if (fConversionChange)
1366 {
1367 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldConversion,
1368 IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0);
1369 NtUserNotifyIMEStatus(hWnd, hIMC, fdwConversion);
1370 }
1371
1372 if (fSentenceChange)
1373 {
1374 Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldSentence,
1375 IMC_SETSENTENCEMODE, IMN_SETSENTENCEMODE, 0);
1376 }
1377
1378 return TRUE;
1379 }
1380
1381 /***********************************************************************
1382 * ImmConfigureIMEA (IMM32.@)
1383 */
1384 BOOL WINAPI ImmConfigureIMEA(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
1385 {
1386 BOOL ret = FALSE;
1387 PIMEDPI pImeDpi;
1388 REGISTERWORDW RegWordW;
1389 LPREGISTERWORDA pRegWordA;
1390
1391 TRACE("(%p, %p, 0x%lX, %p)", hKL, hWnd, dwMode, lpData);
1392
1393 if (!ValidateHwndNoErr(hWnd) || Imm32IsCrossProcessAccess(hWnd))
1394 return FALSE;
1395
1396 pImeDpi = ImmLockOrLoadImeDpi(hKL);
1397 if (!pImeDpi)
1398 return FALSE;
1399
1400 RtlZeroMemory(&RegWordW, sizeof(RegWordW));
1401
1402 if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || !lpData ||
1403 dwMode != IME_CONFIG_REGISTERWORD)
1404 {
1405 goto DoIt;
1406 }
1407
1408 pRegWordA = lpData;
1409
1410 if (pRegWordA->lpReading)
1411 {
1412 RegWordW.lpReading = Imm32WideFromAnsi(pRegWordA->lpReading);
1413 if (!RegWordW.lpReading)
1414 goto Quit;
1415 }
1416
1417 if (pRegWordA->lpWord)
1418 {
1419 RegWordW.lpWord = Imm32WideFromAnsi(pRegWordA->lpWord);
1420 if (!RegWordW.lpWord)
1421 goto Quit;
1422 }
1423
1424 lpData = &RegWordW;
1425
1426 DoIt:
1427 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1B, 0);
1428 ret = pImeDpi->ImeConfigure(hKL, hWnd, dwMode, lpData);
1429 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1A, 0);
1430
1431 Quit:
1432 if (RegWordW.lpReading)
1433 HeapFree(g_hImm32Heap, 0, RegWordW.lpReading);
1434 if (RegWordW.lpWord)
1435 HeapFree(g_hImm32Heap, 0, RegWordW.lpWord);
1436 ImmUnlockImeDpi(pImeDpi);
1437 return ret;
1438 }
1439
1440 /***********************************************************************
1441 * ImmConfigureIMEW (IMM32.@)
1442 */
1443 BOOL WINAPI ImmConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
1444 {
1445 BOOL ret = FALSE;
1446 PIMEDPI pImeDpi;
1447 REGISTERWORDA RegWordA;
1448 LPREGISTERWORDW pRegWordW;
1449
1450 TRACE("(%p, %p, 0x%lX, %p)", hKL, hWnd, dwMode, lpData);
1451
1452 if (!ValidateHwndNoErr(hWnd) || Imm32IsCrossProcessAccess(hWnd))
1453 return FALSE;
1454
1455 pImeDpi = ImmLockOrLoadImeDpi(hKL);
1456 if (!pImeDpi)
1457 return FALSE;
1458
1459 RtlZeroMemory(&RegWordA, sizeof(RegWordA));
1460
1461 if ((pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || !lpData ||
1462 dwMode != IME_CONFIG_REGISTERWORD)
1463 {
1464 goto DoIt;
1465 }
1466
1467 pRegWordW = lpData;
1468
1469 if (pRegWordW->lpReading)
1470 {
1471 RegWordA.lpReading = Imm32AnsiFromWide(pRegWordW->lpReading);
1472 if (!RegWordA.lpReading)
1473 goto Quit;
1474 }
1475
1476 if (pRegWordW->lpWord)
1477 {
1478 RegWordA.lpWord = Imm32AnsiFromWide(pRegWordW->lpWord);
1479 if (!RegWordA.lpWord)
1480 goto Quit;
1481 }
1482
1483 lpData = &RegWordA;
1484
1485 DoIt:
1486 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1B, 0);
1487 ret = pImeDpi->ImeConfigure(hKL, hWnd, dwMode, lpData);
1488 SendMessageW(hWnd, WM_IME_SYSTEM, 0x1A, 0);
1489
1490 Quit:
1491 if (RegWordA.lpReading)
1492 HeapFree(g_hImm32Heap, 0, RegWordA.lpReading);
1493 if (RegWordA.lpWord)
1494 HeapFree(g_hImm32Heap, 0, RegWordA.lpWord);
1495 ImmUnlockImeDpi(pImeDpi);
1496 return ret;
1497 }