1 /*
2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing IMM32 keys and messages
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-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
10 */
11
12 #include "precomp.h"
13 #include <jpnvkeys.h>
14
15 WINE_DEFAULT_DEBUG_CHANNEL(imm);
16
17 /* Win: IMENonIMEToggle */
Imm32ImeNonImeToggle(HIMC hIMC,HKL hKL,HWND hWnd,BOOL bNowIME,LANGID LangID)18 BOOL APIENTRY Imm32ImeNonImeToggle(HIMC hIMC, HKL hKL, HWND hWnd, BOOL bNowIME, LANGID LangID)
19 {
20 HKL hOldKL, LayoutList[32], hFoundKL = NULL;
21 UINT iLayout, nLayoutCount;
22
23 /* Get the previous layout */
24 hOldKL = (HKL)NtUserGetThreadState(THREADSTATE_OLDKEYBOARDLAYOUT);
25
26 /* Get the layout list */
27 nLayoutCount = GetKeyboardLayoutList(_countof(LayoutList), LayoutList);
28
29 /* Is there hOldKL in the list in the specified language ID? */
30 if (hOldKL && (LangID == 0 || LOWORD(hOldKL) == LangID))
31 {
32 for (iLayout = 0; iLayout < nLayoutCount; ++iLayout)
33 {
34 if (LayoutList[iLayout] == hOldKL)
35 {
36 hFoundKL = hOldKL;
37 break;
38 }
39 }
40 }
41
42 if (hFoundKL == NULL) /* Not found? */
43 {
44 /* Is there the keyboard layout of another kind in LangID? */
45 for (iLayout = 0; iLayout < nLayoutCount; ++iLayout)
46 {
47 if (bNowIME == ImmIsIME(LayoutList[iLayout])) /* Same kind? */
48 continue;
49
50 if (LangID == 0 || LangID == LOWORD(LayoutList[iLayout]))
51 {
52 hFoundKL = LayoutList[iLayout];
53 break;
54 }
55 }
56 }
57
58 if (hFoundKL && hKL != hFoundKL) /* Found and different layout */
59 {
60 PostMessageW(hWnd, WM_INPUTLANGCHANGEREQUEST, 1, (LPARAM)hFoundKL);
61 }
62
63 return ImmIsIME(hFoundKL);
64 }
65
66 /* Open or close the IME on Chinese or Taiwanese */
67 /* Win: CIMENonIMEToggle */
Imm32CImeNonImeToggle(HIMC hIMC,HKL hKL,HWND hWnd,LANGID LangID)68 BOOL APIENTRY Imm32CImeNonImeToggle(HIMC hIMC, HKL hKL, HWND hWnd, LANGID LangID)
69 {
70 LPINPUTCONTEXT pIC;
71 BOOL fOpen;
72
73 if (IS_NULL_UNEXPECTEDLY(hWnd))
74 return FALSE;
75
76 if (LOWORD(hKL) != LangID || !ImmIsIME(hKL))
77 {
78 Imm32ImeNonImeToggle(hIMC, hKL, hWnd, FALSE, LangID);
79 return TRUE;
80 }
81
82 pIC = ImmLockIMC(hIMC);
83 if (IS_NULL_UNEXPECTEDLY(pIC))
84 return TRUE;
85
86 fOpen = pIC->fOpen;
87 ImmUnlockIMC(hIMC);
88
89 if (fOpen)
90 Imm32ImeNonImeToggle(hIMC, hKL, hWnd, TRUE, 0);
91 else
92 ImmSetOpenStatus(hIMC, TRUE);
93
94 return TRUE;
95 }
96
97 /* Toggle shape mode on Chinese or Taiwanese */
98 /* Win: TShapeToggle */
Imm32CShapeToggle(HIMC hIMC,HKL hKL,HWND hWnd)99 BOOL APIENTRY Imm32CShapeToggle(HIMC hIMC, HKL hKL, HWND hWnd)
100 {
101 LPINPUTCONTEXT pIC;
102 BOOL fOpen;
103 DWORD dwConversion, dwSentence;
104
105 if (hWnd == NULL || !ImmIsIME(hKL))
106 return FALSE;
107
108 pIC = ImmLockIMC(hIMC);
109 if (IS_NULL_UNEXPECTEDLY(pIC))
110 return TRUE;
111
112 fOpen = pIC->fOpen;
113 if (fOpen)
114 {
115 dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
116 dwSentence = pIC->fdwSentence;
117 }
118
119 ImmUnlockIMC(hIMC);
120
121 if (fOpen)
122 ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
123 else
124 ImmSetOpenStatus(hIMC, TRUE);
125
126 return TRUE;
127 }
128
129 /* Win: CSymbolToggle */
Imm32CSymbolToggle(HIMC hIMC,HKL hKL,HWND hWnd)130 BOOL APIENTRY Imm32CSymbolToggle(HIMC hIMC, HKL hKL, HWND hWnd)
131 {
132 LPINPUTCONTEXT pIC;
133 BOOL fOpen;
134 DWORD dwConversion, dwSentence;
135
136 if (hWnd == NULL || !ImmIsIME(hKL))
137 return FALSE;
138
139 pIC = ImmLockIMC(hIMC);
140 if (IS_NULL_UNEXPECTEDLY(pIC))
141 return TRUE;
142
143 fOpen = pIC->fOpen;
144 if (fOpen)
145 {
146 dwConversion = (pIC->fdwConversion ^ IME_CMODE_SYMBOL);
147 dwSentence = pIC->fdwSentence;
148 }
149
150 ImmUnlockIMC(hIMC);
151
152 if (fOpen)
153 ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
154 else
155 ImmSetOpenStatus(hIMC, TRUE);
156
157 return TRUE;
158 }
159
160 /* Open or close Japanese IME */
Imm32JCloseOpen(HIMC hIMC,HKL hKL,HWND hWnd)161 BOOL APIENTRY Imm32JCloseOpen(HIMC hIMC, HKL hKL, HWND hWnd)
162 {
163 BOOL fOpen;
164 LPINPUTCONTEXTDX pIC;
165
166 if (LOWORD(hKL) == LANGID_JAPANESE && ImmIsIME(hKL)) /* Japanese IME is selected */
167 {
168 fOpen = ImmGetOpenStatus(hIMC);
169 ImmSetOpenStatus(hIMC, !fOpen);
170 return TRUE;
171 }
172
173 /* Japanese IME is not selected. Select now */
174 if (Imm32ImeNonImeToggle(hIMC, hKL, hWnd, FALSE, LANGID_JAPANESE))
175 {
176 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
177 if (pIC)
178 {
179 pIC->dwChange |= INPUTCONTEXTDX_CHANGE_FORCE_OPEN;
180 ImmUnlockIMC(hIMC);
181 }
182 }
183
184 return TRUE;
185 }
186
187 /* Win: KShapeToggle */
Imm32KShapeToggle(HIMC hIMC)188 BOOL APIENTRY Imm32KShapeToggle(HIMC hIMC)
189 {
190 LPINPUTCONTEXT pIC;
191 DWORD dwConversion, dwSentence;
192
193 pIC = ImmLockIMC(hIMC);
194 if (IS_NULL_UNEXPECTEDLY(pIC))
195 return FALSE;
196
197 dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
198 dwSentence = pIC->fdwSentence;
199 ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
200
201 if (pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE))
202 ImmSetOpenStatus(hIMC, TRUE);
203 else
204 ImmSetOpenStatus(hIMC, FALSE);
205
206 ImmUnlockIMC(hIMC);
207 return TRUE;
208 }
209
210 /* Win: KHanjaConvert */
Imm32KHanjaConvert(HIMC hIMC)211 BOOL APIENTRY Imm32KHanjaConvert(HIMC hIMC)
212 {
213 LPINPUTCONTEXT pIC;
214 DWORD dwConversion, dwSentence;
215
216 pIC = ImmLockIMC(hIMC);
217 if (IS_NULL_UNEXPECTEDLY(pIC))
218 return FALSE;
219
220 dwConversion = (pIC->fdwConversion ^ IME_CMODE_HANJACONVERT);
221 dwSentence = pIC->fdwSentence;
222 ImmUnlockIMC(hIMC);
223
224 ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
225 return TRUE;
226 }
227
228 /* Win: KEnglishHangul */
Imm32KEnglish(HIMC hIMC)229 BOOL APIENTRY Imm32KEnglish(HIMC hIMC)
230 {
231 LPINPUTCONTEXT pIC;
232 DWORD dwConversion, dwSentence;
233 BOOL fOpen;
234
235 pIC = ImmLockIMC(hIMC);
236 if (IS_NULL_UNEXPECTEDLY(pIC))
237 return FALSE;
238
239 dwConversion = (pIC->fdwConversion ^ IME_CMODE_NATIVE);
240 dwSentence = pIC->fdwSentence;
241 ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
242
243 fOpen = ((pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE)) != 0);
244 ImmSetOpenStatus(hIMC, fOpen);
245
246 ImmUnlockIMC(hIMC);
247 return TRUE;
248 }
249
250 /* Win: HotKeyIDDispatcher */
Imm32ProcessHotKey(HWND hWnd,HIMC hIMC,HKL hKL,DWORD dwHotKeyID)251 BOOL APIENTRY Imm32ProcessHotKey(HWND hWnd, HIMC hIMC, HKL hKL, DWORD dwHotKeyID)
252 {
253 PIMEDPI pImeDpi;
254 BOOL ret;
255
256 if (hIMC && IS_CROSS_THREAD_HIMC(hIMC))
257 return FALSE;
258
259 switch (dwHotKeyID)
260 {
261 case IME_CHOTKEY_IME_NONIME_TOGGLE:
262 return Imm32CImeNonImeToggle(hIMC, hKL, hWnd, LANGID_CHINESE_SIMPLIFIED);
263
264 case IME_CHOTKEY_SHAPE_TOGGLE:
265 return Imm32CShapeToggle(hIMC, hKL, hWnd);
266
267 case IME_CHOTKEY_SYMBOL_TOGGLE:
268 return Imm32CSymbolToggle(hIMC, hKL, hWnd);
269
270 case IME_JHOTKEY_CLOSE_OPEN:
271 return Imm32JCloseOpen(hIMC, hKL, hWnd);
272
273 case IME_KHOTKEY_SHAPE_TOGGLE:
274 return Imm32KShapeToggle(hIMC);
275
276 case IME_KHOTKEY_HANJACONVERT:
277 return Imm32KHanjaConvert(hIMC);
278
279 case IME_KHOTKEY_ENGLISH:
280 return Imm32KEnglish(hIMC);
281
282 case IME_THOTKEY_IME_NONIME_TOGGLE:
283 return Imm32CImeNonImeToggle(hIMC, hKL, hWnd, LANGID_CHINESE_TRADITIONAL);
284
285 case IME_THOTKEY_SHAPE_TOGGLE:
286 return Imm32CShapeToggle(hIMC, hKL, hWnd);
287
288 case IME_THOTKEY_SYMBOL_TOGGLE:
289 return Imm32CSymbolToggle(hIMC, hKL, hWnd);
290
291 default:
292 WARN("0x%X\n", dwHotKeyID);
293 break;
294 }
295
296 if (dwHotKeyID < IME_HOTKEY_PRIVATE_FIRST || IME_HOTKEY_PRIVATE_LAST < dwHotKeyID)
297 return FALSE;
298
299 pImeDpi = ImmLockImeDpi(hKL);
300 if (IS_NULL_UNEXPECTEDLY(pImeDpi))
301 return FALSE;
302
303 ret = (BOOL)pImeDpi->ImeEscape(hIMC, IME_ESC_PRIVATE_HOTKEY, &dwHotKeyID);
304 ImmUnlockImeDpi(pImeDpi);
305 return ret;
306 }
307
308 /* Win: ImmIsUIMessageWorker */
309 static BOOL APIENTRY
ImmIsUIMessageAW(HWND hWndIME,UINT msg,WPARAM wParam,LPARAM lParam,BOOL bAnsi)310 ImmIsUIMessageAW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAnsi)
311 {
312 switch (msg)
313 {
314 case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION:
315 case WM_IME_COMPOSITION: case WM_IME_SETCONTEXT: case WM_IME_NOTIFY:
316 case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: case WM_IME_SYSTEM:
317 break;
318 default:
319 return FALSE;
320 }
321
322 if (IS_NULL_UNEXPECTEDLY(hWndIME))
323 return TRUE;
324
325 if (bAnsi)
326 SendMessageA(hWndIME, msg, wParam, lParam);
327 else
328 SendMessageW(hWndIME, msg, wParam, lParam);
329
330 return TRUE;
331 }
332
333 static BOOL CALLBACK
Imm32SendNotificationProc(_In_ HIMC hIMC,_In_ LPARAM lParam)334 Imm32SendNotificationProc(
335 _In_ HIMC hIMC,
336 _In_ LPARAM lParam)
337 {
338 HWND hWnd;
339 LPINPUTCONTEXTDX pIC;
340
341 UNREFERENCED_PARAMETER(lParam);
342
343 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
344 if (IS_NULL_UNEXPECTEDLY(pIC))
345 return TRUE;
346
347 hWnd = pIC->hWnd;
348 if (!IsWindow(hWnd))
349 goto Quit;
350
351 TRACE("dwChange: 0x%08X\n", pIC->dwChange);
352
353 if (pIC->dwChange & INPUTCONTEXTDX_CHANGE_OPEN)
354 SendMessageW(hWnd, WM_IME_NOTIFY, IMN_SETOPENSTATUS, 0);
355 if (pIC->dwChange & INPUTCONTEXTDX_CHANGE_CONVERSION)
356 SendMessageW(hWnd, WM_IME_NOTIFY, IMN_SETCONVERSIONMODE, 0);
357 if (pIC->dwChange & (INPUTCONTEXTDX_CHANGE_OPEN | INPUTCONTEXTDX_CHANGE_CONVERSION))
358 NtUserNotifyIMEStatus(hWnd, pIC->fOpen, pIC->fdwConversion);
359 if (pIC->dwChange & INPUTCONTEXTDX_CHANGE_SENTENCE)
360 SendMessageW(hWnd, WM_IME_NOTIFY, IMN_SETSENTENCEMODE, 0);
361 Quit:
362 pIC->dwChange = 0;
363 ImmUnlockIMC(hIMC); // ??? Windows doesn't unlock here
364 return TRUE;
365 }
366
Imm32SendNotification(BOOL bProcess)367 BOOL APIENTRY Imm32SendNotification(BOOL bProcess)
368 {
369 return ImmEnumInputContext((bProcess ? -1 : 0), Imm32SendNotificationProc, 0);
370 }
371
372 LRESULT APIENTRY
Imm32ProcessRequest(HIMC hIMC,PWND pWnd,DWORD dwCommand,LPVOID pData,BOOL bAnsiAPI)373 Imm32ProcessRequest(HIMC hIMC, PWND pWnd, DWORD dwCommand, LPVOID pData, BOOL bAnsiAPI)
374 {
375 HWND hWnd;
376 DWORD ret = 0, dwCharPos, cchCompStr, dwSize;
377 LPVOID pCS, pTempData = pData;
378 LPRECONVERTSTRING pRS;
379 LPIMECHARPOSITION pICP;
380 PCLIENTIMC pClientImc;
381 UINT uCodePage = CP_ACP;
382 BOOL bAnsiWnd = !!(pWnd->state & WNDS_ANSIWINDOWPROC);
383 static const size_t acbData[7 * 2] =
384 {
385 /* UNICODE */
386 sizeof(COMPOSITIONFORM), sizeof(CANDIDATEFORM), sizeof(LOGFONTW),
387 sizeof(RECONVERTSTRING), sizeof(RECONVERTSTRING),
388 sizeof(IMECHARPOSITION), sizeof(RECONVERTSTRING),
389 /* ANSI */
390 sizeof(COMPOSITIONFORM), sizeof(CANDIDATEFORM), sizeof(LOGFONTA),
391 sizeof(RECONVERTSTRING), sizeof(RECONVERTSTRING),
392 sizeof(IMECHARPOSITION), sizeof(RECONVERTSTRING),
393 };
394
395 if (dwCommand == 0 || dwCommand > IMR_DOCUMENTFEED)
396 {
397 ERR("Out of boundary\n");
398 return 0; /* Out of range */
399 }
400
401 dwSize = acbData[bAnsiAPI * 7 + dwCommand - 1];
402 if (pData && IsBadWritePtr(pData, dwSize))
403 {
404 ERR("\n");
405 return 0; /* Invalid pointer */
406 }
407
408 /* Sanity check */
409 switch (dwCommand)
410 {
411 case IMR_RECONVERTSTRING: case IMR_DOCUMENTFEED:
412 pRS = pData;
413 if (pRS && (pRS->dwVersion != 0 || pRS->dwSize < sizeof(RECONVERTSTRING)))
414 {
415 ERR("Invalid pRS\n");
416 return 0;
417 }
418 break;
419
420 case IMR_CONFIRMRECONVERTSTRING:
421 pRS = pData;
422 if (!pRS || pRS->dwVersion != 0)
423 {
424 ERR("Invalid pRS\n");
425 return 0;
426 }
427 break;
428
429 default:
430 if (IS_NULL_UNEXPECTEDLY(pData))
431 return 0;
432 break;
433 }
434
435 pClientImc = ImmLockClientImc(hIMC);
436 if (pClientImc)
437 {
438 uCodePage = pClientImc->uCodePage;
439 ImmUnlockClientImc(pClientImc);
440 }
441
442 /* Prepare */
443 switch (dwCommand)
444 {
445 case IMR_COMPOSITIONFONT:
446 if (bAnsiAPI == bAnsiWnd)
447 goto DoIt; /* No conversion needed */
448
449 if (bAnsiWnd)
450 pTempData = ImmLocalAlloc(0, sizeof(LOGFONTA));
451 else
452 pTempData = ImmLocalAlloc(0, sizeof(LOGFONTW));
453
454 if (IS_NULL_UNEXPECTEDLY(pTempData))
455 return 0;
456 break;
457
458 case IMR_RECONVERTSTRING: case IMR_CONFIRMRECONVERTSTRING: case IMR_DOCUMENTFEED:
459 if (bAnsiAPI == bAnsiWnd || !pData)
460 goto DoIt; /* No conversion needed */
461
462 if (bAnsiWnd)
463 ret = Imm32ReconvertAnsiFromWide(NULL, pData, uCodePage);
464 else
465 ret = Imm32ReconvertWideFromAnsi(NULL, pData, uCodePage);
466
467 pTempData = ImmLocalAlloc(0, ret + sizeof(WCHAR));
468 if (IS_NULL_UNEXPECTEDLY(pTempData))
469 return 0;
470
471 pRS = pTempData;
472 pRS->dwSize = ret;
473 pRS->dwVersion = 0;
474
475 if (dwCommand == IMR_CONFIRMRECONVERTSTRING)
476 {
477 if (bAnsiWnd)
478 ret = Imm32ReconvertAnsiFromWide(pTempData, pData, uCodePage);
479 else
480 ret = Imm32ReconvertWideFromAnsi(pTempData, pData, uCodePage);
481 }
482 break;
483
484 case IMR_QUERYCHARPOSITION:
485 if (bAnsiAPI == bAnsiWnd)
486 goto DoIt; /* No conversion needed */
487
488 pICP = pData;
489 dwCharPos = pICP->dwCharPos;
490
491 if (bAnsiAPI)
492 {
493 cchCompStr = ImmGetCompositionStringA(hIMC, GCS_COMPSTR, NULL, 0);
494 if (IS_ZERO_UNEXPECTEDLY(cchCompStr))
495 return 0;
496
497 pCS = ImmLocalAlloc(0, (cchCompStr + 1) * sizeof(CHAR));
498 if (IS_NULL_UNEXPECTEDLY(pCS))
499 return 0;
500
501 ImmGetCompositionStringA(hIMC, GCS_COMPSTR, pCS, cchCompStr);
502 pICP->dwCharPos = IchWideFromAnsi(pICP->dwCharPos, pCS, uCodePage);
503 }
504 else
505 {
506 cchCompStr = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
507 if (IS_ZERO_UNEXPECTEDLY(cchCompStr))
508 return 0;
509
510 pCS = ImmLocalAlloc(0, (cchCompStr + 1) * sizeof(WCHAR));
511 if (IS_NULL_UNEXPECTEDLY(pCS))
512 return 0;
513
514 ImmGetCompositionStringW(hIMC, GCS_COMPSTR, pCS, cchCompStr);
515 pICP->dwCharPos = IchAnsiFromWide(pICP->dwCharPos, pCS, uCodePage);
516 }
517
518 ImmLocalFree(pCS);
519 break;
520
521 default:
522 WARN("0x%X\n", dwCommand);
523 break;
524 }
525
526 DoIt:
527 /* The main task */
528 hWnd = pWnd->head.h;
529 if (bAnsiWnd)
530 ret = SendMessageA(hWnd, WM_IME_REQUEST, dwCommand, (LPARAM)pTempData);
531 else
532 ret = SendMessageW(hWnd, WM_IME_REQUEST, dwCommand, (LPARAM)pTempData);
533
534 if (bAnsiAPI == bAnsiWnd)
535 goto Quit; /* No conversion needed */
536
537 /* Get back to caller */
538 switch (dwCommand)
539 {
540 case IMR_COMPOSITIONFONT:
541 if (bAnsiAPI)
542 LogFontWideToAnsi(pTempData, pData);
543 else
544 LogFontAnsiToWide(pTempData, pData);
545 break;
546
547 case IMR_RECONVERTSTRING: case IMR_DOCUMENTFEED:
548 if (!ret)
549 break;
550
551 if (ret < sizeof(RECONVERTSTRING))
552 {
553 ret = 0;
554 break;
555 }
556
557 if (pTempData)
558 {
559 if (bAnsiWnd)
560 ret = Imm32ReconvertWideFromAnsi(pData, pTempData, uCodePage);
561 else
562 ret = Imm32ReconvertAnsiFromWide(pData, pTempData, uCodePage);
563 }
564 break;
565
566 case IMR_QUERYCHARPOSITION:
567 pICP->dwCharPos = dwCharPos;
568 break;
569
570 default:
571 WARN("0x%X\n", dwCommand);
572 break;
573 }
574
575 Quit:
576 if (pTempData != pData)
577 ImmLocalFree(pTempData);
578 return ret;
579 }
580
581 /* Win: ImmRequestMessageWorker */
ImmRequestMessageAW(HIMC hIMC,WPARAM wParam,LPARAM lParam,BOOL bAnsi)582 LRESULT APIENTRY ImmRequestMessageAW(HIMC hIMC, WPARAM wParam, LPARAM lParam, BOOL bAnsi)
583 {
584 LRESULT ret = 0;
585 LPINPUTCONTEXT pIC;
586 HWND hWnd;
587 PWND pWnd = NULL;
588
589 if (IS_NULL_UNEXPECTEDLY(hIMC) || IS_CROSS_THREAD_HIMC(hIMC))
590 return FALSE;
591
592 pIC = ImmLockIMC(hIMC);
593 if (IS_NULL_UNEXPECTEDLY(pIC))
594 return FALSE;
595
596 hWnd = pIC->hWnd;
597 if (hWnd)
598 pWnd = ValidateHwnd(hWnd);
599
600 if (pWnd && pWnd->head.pti == Imm32CurrentPti())
601 ret = Imm32ProcessRequest(hIMC, pWnd, (DWORD)wParam, (LPVOID)lParam, bAnsi);
602
603 ImmUnlockIMC(hIMC);
604 return ret;
605 }
606
607 /***********************************************************************
608 * ImmIsUIMessageA (IMM32.@)
609 */
ImmIsUIMessageA(HWND hWndIME,UINT msg,WPARAM wParam,LPARAM lParam)610 BOOL WINAPI ImmIsUIMessageA(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
611 {
612 TRACE("(%p, 0x%X, %p, %p)\n", hWndIME, msg, wParam, lParam);
613 return ImmIsUIMessageAW(hWndIME, msg, wParam, lParam, TRUE);
614 }
615
616 /***********************************************************************
617 * ImmIsUIMessageW (IMM32.@)
618 */
ImmIsUIMessageW(HWND hWndIME,UINT msg,WPARAM wParam,LPARAM lParam)619 BOOL WINAPI ImmIsUIMessageW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
620 {
621 TRACE("(%p, 0x%X, %p, %p)\n", hWndIME, msg, wParam, lParam);
622 return ImmIsUIMessageAW(hWndIME, msg, wParam, lParam, FALSE);
623 }
624
625 /***********************************************************************
626 * ImmGetHotKey(IMM32.@)
627 */
628 BOOL WINAPI
ImmGetHotKey(IN DWORD dwHotKey,OUT LPUINT lpuModifiers,OUT LPUINT lpuVKey,OUT LPHKL lphKL)629 ImmGetHotKey(IN DWORD dwHotKey, OUT LPUINT lpuModifiers, OUT LPUINT lpuVKey,
630 OUT LPHKL lphKL)
631 {
632 TRACE("(0x%lX, %p, %p, %p)\n", dwHotKey, lpuModifiers, lpuVKey, lphKL);
633 if (lpuModifiers && lpuVKey)
634 return NtUserGetImeHotKey(dwHotKey, lpuModifiers, lpuVKey, lphKL);
635 return FALSE;
636 }
637
638 /***********************************************************************
639 * ImmWINNLSGetIMEHotkey (IMM32.@)
640 */
ImmWINNLSGetIMEHotkey(HWND hwndIme)641 UINT WINAPI ImmWINNLSGetIMEHotkey(HWND hwndIme)
642 {
643 TRACE("(%p)\n", hwndIme);
644 UNREFERENCED_PARAMETER(hwndIme);
645 return 0; /* This is correct. This function of Windows just returns zero. */
646 }
647
648 /***********************************************************************
649 * ImmSimulateHotKey (IMM32.@)
650 */
ImmSimulateHotKey(HWND hWnd,DWORD dwHotKeyID)651 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
652 {
653 HIMC hIMC;
654 DWORD dwThreadId;
655 HKL hKL;
656 BOOL ret;
657
658 TRACE("(%p, 0x%lX)\n", hWnd, dwHotKeyID);
659
660 hIMC = ImmGetContext(hWnd);
661 dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
662 hKL = GetKeyboardLayout(dwThreadId);
663 ret = Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID);
664 ImmReleaseContext(hWnd, hIMC);
665 return ret;
666 }
667
668 /***********************************************************************
669 * ImmGetVirtualKey (IMM32.@)
670 */
ImmGetVirtualKey(HWND hWnd)671 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
672 {
673 HIMC hIMC;
674 LPINPUTCONTEXTDX pIC;
675 UINT ret = VK_PROCESSKEY;
676
677 TRACE("(%p)\n", hWnd);
678
679 hIMC = ImmGetContext(hWnd);
680 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
681 if (IS_NULL_UNEXPECTEDLY(pIC))
682 return ret;
683
684 if (pIC->bNeedsTrans)
685 ret = pIC->nVKey;
686
687 ImmUnlockIMC(hIMC);
688 return ret;
689 }
690
691 /***********************************************************************
692 * ImmGetAppCompatFlags (IMM32.@)
693 */
ImmGetAppCompatFlags(HIMC hIMC)694 DWORD WINAPI ImmGetAppCompatFlags(HIMC hIMC)
695 {
696 PCLIENTIMC pClientIMC;
697 DWORD dwFlags;
698
699 TRACE("(%p)\n", hIMC);
700
701 pClientIMC = ImmLockClientImc(hIMC);
702 if (IS_NULL_UNEXPECTEDLY(pClientIMC))
703 return 0;
704
705 dwFlags = pClientIMC->dwCompatFlags;
706 ImmUnlockClientImc(pClientIMC);
707 return (dwFlags | g_aimm_compat_flags);
708 }
709
710 /***********************************************************************
711 * ImmProcessKey(IMM32.@)
712 * ( Undocumented, called from user32.dll )
713 */
714 DWORD WINAPI
ImmProcessKey(HWND hWnd,HKL hKL,UINT vKey,LPARAM lParam,DWORD dwHotKeyID)715 ImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID)
716 {
717 DWORD ret = 0;
718 HIMC hIMC;
719 PIMEDPI pImeDpi;
720 LPINPUTCONTEXTDX pIC;
721 BYTE KeyState[256];
722 BOOL bLowWordOnly = FALSE, bSkipThisKey = FALSE, bHotKeyDone = TRUE;
723
724 TRACE("(%p, %p, 0x%X, %p, 0x%lX)\n", hWnd, hKL, vKey, lParam, dwHotKeyID);
725
726 /* Process the key by the IME */
727 hIMC = ImmGetContext(hWnd);
728 pImeDpi = ImmLockImeDpi(hKL);
729 if (pImeDpi)
730 {
731 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
732 if (pIC)
733 {
734 if ((LOBYTE(vKey) == VK_PACKET) &&
735 !(pImeDpi->ImeInfo.fdwProperty & IME_PROP_ACCEPT_WIDE_VKEY))
736 {
737 if (ImeDpi_IsUnicode(pImeDpi))
738 {
739 bLowWordOnly = TRUE;
740 }
741 else
742 {
743 if (pIC->fOpen)
744 ret |= IPHK_SKIPTHISKEY;
745
746 bSkipThisKey = TRUE;
747 }
748 }
749
750 if (!bSkipThisKey && GetKeyboardState(KeyState))
751 {
752 UINT vk = (bLowWordOnly ? LOWORD(vKey) : vKey);
753 if (pImeDpi->ImeProcessKey(hIMC, vk, lParam, KeyState))
754 {
755 pIC->bNeedsTrans = TRUE;
756 pIC->nVKey = vKey;
757 ret |= IPHK_PROCESSBYIME;
758 }
759 }
760
761 ImmUnlockIMC(hIMC);
762 }
763
764 ImmUnlockImeDpi(pImeDpi);
765 }
766
767 /* Process the hot-key if necessary */
768 if (!CtfImmIsCiceroStartedInThread()) /* Not Cicero? */
769 {
770 /* Process IMM IME hotkey */
771 if ((dwHotKeyID == INVALID_HOTKEY_ID) || !Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID))
772 bHotKeyDone = FALSE;
773 }
774 else if (!CtfImeProcessCicHotkey(hIMC, vKey, lParam)) /* CTF IME not processed the hotkey? */
775 {
776 /* Process IMM IME hotkey */
777 if (!IS_IME_HKL(hKL) ||
778 ((dwHotKeyID == INVALID_HOTKEY_ID) || !Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID)))
779 {
780 bHotKeyDone = FALSE;
781 }
782 }
783
784 if (bHotKeyDone && ((vKey != VK_KANJI) || (dwHotKeyID != IME_JHOTKEY_CLOSE_OPEN)))
785 ret |= IPHK_HOTKEY;
786
787 if ((ret & IPHK_PROCESSBYIME) && (ImmGetAppCompatFlags(hIMC) & 0x10000))
788 {
789 /* The key has been processed by IME's ImeProcessKey */
790 LANGID wLangID = LANGIDFROMLCID(GetSystemDefaultLCID());
791 if ((PRIMARYLANGID(wLangID) == LANG_KOREAN) &&
792 ((vKey == VK_PROCESSKEY) || (ret & IPHK_HOTKEY)))
793 {
794 /* Korean don't want VK_PROCESSKEY and IME hot-keys */
795 }
796 else
797 {
798 /* Add WM_KEYDOWN:VK_PROCESSKEY message */
799 ImmTranslateMessage(hWnd, WM_KEYDOWN, VK_PROCESSKEY, lParam);
800
801 ret &= ~IPHK_PROCESSBYIME;
802 ret |= IPHK_SKIPTHISKEY;
803 }
804 }
805
806 ImmReleaseContext(hWnd, hIMC);
807 return ret; /* Returns IPHK_... flags */
808 }
809
810 /***********************************************************************
811 * ImmSystemHandler(IMM32.@)
812 */
ImmSystemHandler(HIMC hIMC,WPARAM wParam,LPARAM lParam)813 LRESULT WINAPI ImmSystemHandler(HIMC hIMC, WPARAM wParam, LPARAM lParam)
814 {
815 TRACE("(%p, %p, %p)\n", hIMC, wParam, lParam);
816
817 switch (wParam)
818 {
819 case IMS_SENDNOTIFICATION:
820 Imm32SendNotification((BOOL)lParam);
821 return 0;
822
823 case IMS_COMPLETECOMPSTR:
824 ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
825 return 0;
826
827 case IMS_SETLANGBAND:
828 case IMS_UNSETLANGBAND:
829 return CtfImmSetLangBand((HWND)lParam, (wParam == IMS_SETLANGBAND));
830
831 default:
832 WARN("%p\n", wParam);
833 return 0;
834 }
835 }
836
837 /***********************************************************************
838 * ImmGenerateMessage(IMM32.@)
839 */
ImmGenerateMessage(HIMC hIMC)840 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
841 {
842 PCLIENTIMC pClientImc;
843 LPINPUTCONTEXT pIC;
844 LPTRANSMSG pMsgs, pTrans = NULL, pItem;
845 HWND hWnd;
846 DWORD dwIndex, dwCount, cbTrans;
847 HIMCC hMsgBuf = NULL;
848 BOOL bAnsi;
849
850 TRACE("(%p)\n", hIMC);
851
852 if (IS_CROSS_THREAD_HIMC(hIMC))
853 return FALSE;
854
855 pClientImc = ImmLockClientImc(hIMC);
856 if (IS_NULL_UNEXPECTEDLY(pClientImc))
857 return FALSE;
858
859 bAnsi = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
860 ImmUnlockClientImc(pClientImc);
861
862 pIC = ImmLockIMC(hIMC);
863 if (IS_NULL_UNEXPECTEDLY(pIC))
864 return FALSE;
865
866 dwCount = pIC->dwNumMsgBuf;
867 if (dwCount == 0)
868 goto Quit;
869
870 hMsgBuf = pIC->hMsgBuf;
871 pMsgs = ImmLockIMCC(hMsgBuf);
872 if (IS_NULL_UNEXPECTEDLY(pMsgs))
873 goto Quit;
874
875 cbTrans = dwCount * sizeof(TRANSMSG);
876 pTrans = ImmLocalAlloc(0, cbTrans);
877 if (IS_NULL_UNEXPECTEDLY(pTrans))
878 goto Quit;
879
880 RtlCopyMemory(pTrans, pMsgs, cbTrans);
881
882 #ifdef IMM_WIN3_SUPPORT
883 if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* old version (3.x)? */
884 {
885 LANGID LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
886 WORD wLang = PRIMARYLANGID(LangID);
887
888 /* translate the messages if Japanese or Korean */
889 if (wLang == LANG_JAPANESE ||
890 (wLang == LANG_KOREAN && NtUserGetAppImeLevel(pIC->hWnd) == 3))
891 {
892 dwCount = WINNLSTranslateMessage(dwCount, pTrans, hIMC, bAnsi, wLang);
893 }
894 }
895 #endif
896
897 /* send them */
898 hWnd = pIC->hWnd;
899 pItem = pTrans;
900 for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pItem)
901 {
902 if (bAnsi)
903 SendMessageA(hWnd, pItem->message, pItem->wParam, pItem->lParam);
904 else
905 SendMessageW(hWnd, pItem->message, pItem->wParam, pItem->lParam);
906 }
907
908 Quit:
909 ImmLocalFree(pTrans);
910 if (hMsgBuf)
911 ImmUnlockIMCC(hMsgBuf);
912 pIC->dwNumMsgBuf = 0; /* done */
913 ImmUnlockIMC(hIMC);
914 return TRUE;
915 }
916
917 VOID APIENTRY
ImmPostMessages(HWND hwnd,HIMC hIMC,DWORD dwCount,LPTRANSMSG lpTransMsg)918 ImmPostMessages(HWND hwnd, HIMC hIMC, DWORD dwCount, LPTRANSMSG lpTransMsg)
919 {
920 DWORD dwIndex;
921 PCLIENTIMC pClientImc;
922 LPTRANSMSG pNewTransMsg = lpTransMsg, pItem;
923 BOOL bAnsi;
924
925 pClientImc = ImmLockClientImc(hIMC);
926 if (IS_NULL_UNEXPECTEDLY(pClientImc))
927 return;
928
929 bAnsi = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
930 ImmUnlockClientImc(pClientImc);
931
932 #ifdef IMM_WIN3_SUPPORT
933 if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* old version (3.x)? */
934 {
935 LANGID LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
936 WORD Lang = PRIMARYLANGID(LangID);
937
938 /* translate the messages if Japanese or Korean */
939 if (Lang == LANG_JAPANESE ||
940 (Lang == LANG_KOREAN && NtUserGetAppImeLevel(hwnd) == 3))
941 {
942 DWORD cbTransMsg = dwCount * sizeof(TRANSMSG);
943 pNewTransMsg = ImmLocalAlloc(0, cbTransMsg);
944 if (pNewTransMsg)
945 {
946 RtlCopyMemory(pNewTransMsg, lpTransMsg, cbTransMsg);
947 dwCount = WINNLSTranslateMessage(dwCount, pNewTransMsg, hIMC, bAnsi, Lang);
948 }
949 else
950 {
951 pNewTransMsg = lpTransMsg;
952 }
953 }
954 }
955 #endif
956
957 /* post them */
958 pItem = pNewTransMsg;
959 for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pItem)
960 {
961 if (bAnsi)
962 PostMessageA(hwnd, pItem->message, pItem->wParam, pItem->lParam);
963 else
964 PostMessageW(hwnd, pItem->message, pItem->wParam, pItem->lParam);
965 }
966
967 #ifdef IMM_WIN3_SUPPORT
968 if (pNewTransMsg != lpTransMsg)
969 ImmLocalFree(pNewTransMsg);
970 #endif
971 }
972
973 /***********************************************************************
974 * ImmTranslateMessage(IMM32.@)
975 * ( Undocumented, call internally and from user32.dll )
976 */
ImmTranslateMessage(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lKeyData)977 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
978 {
979 #define MSG_COUNT 0x100
980 BOOL ret = FALSE;
981 INT kret;
982 LPINPUTCONTEXTDX pIC;
983 PIMEDPI pImeDpi = NULL;
984 LPTRANSMSGLIST pList = NULL;
985 LPTRANSMSG pTransMsg;
986 BYTE abKeyState[256];
987 HIMC hIMC;
988 HKL hKL;
989 UINT vk;
990 DWORD dwThreadId, dwCount, cbList;
991 WCHAR wch;
992 WORD wChar;
993
994 TRACE("(%p, 0x%X, %p, %p)\n", hwnd, msg, wParam, lKeyData);
995
996 /* filter the message */
997 switch (msg)
998 {
999 case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP:
1000 break;
1001 default:
1002 return FALSE;
1003 }
1004
1005 hIMC = ImmGetContext(hwnd);
1006 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
1007 if (IS_NULL_UNEXPECTEDLY(pIC))
1008 {
1009 ImmReleaseContext(hwnd, hIMC);
1010 return FALSE;
1011 }
1012
1013 if (!pIC->bNeedsTrans) /* is translation needed? */
1014 {
1015 /* directly post them */
1016 dwCount = pIC->dwNumMsgBuf;
1017 if (dwCount == 0)
1018 goto Quit;
1019
1020 pTransMsg = ImmLockIMCC(pIC->hMsgBuf);
1021 if (pTransMsg)
1022 {
1023 ImmPostMessages(hwnd, hIMC, dwCount, pTransMsg);
1024 ImmUnlockIMCC(pIC->hMsgBuf);
1025 ret = TRUE;
1026 }
1027 pIC->dwNumMsgBuf = 0; /* done */
1028 goto Quit;
1029 }
1030 pIC->bNeedsTrans = FALSE; /* clear the flag */
1031
1032 dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
1033 hKL = GetKeyboardLayout(dwThreadId);
1034 pImeDpi = ImmLockImeDpi(hKL);
1035 if (IS_NULL_UNEXPECTEDLY(pImeDpi))
1036 goto Quit;
1037
1038 if (!GetKeyboardState(abKeyState)) /* get keyboard ON/OFF status */
1039 {
1040 WARN("\n");
1041 goto Quit;
1042 }
1043
1044 /* convert a virtual key if IME_PROP_KBD_CHAR_FIRST */
1045 vk = pIC->nVKey;
1046 if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
1047 {
1048 if (ImeDpi_IsUnicode(pImeDpi))
1049 {
1050 wch = 0;
1051 kret = ToUnicode(vk, HIWORD(lKeyData), abKeyState, &wch, 1, 0);
1052 if (kret == 1)
1053 vk = MAKELONG(LOBYTE(vk), wch);
1054 }
1055 else
1056 {
1057 wChar = 0;
1058 kret = ToAsciiEx(vk, HIWORD(lKeyData), abKeyState, &wChar, 0, hKL);
1059 if (kret > 0)
1060 {
1061 if ((BYTE)vk == VK_PACKET)
1062 {
1063 vk &= 0xFF;
1064 vk |= (wChar << 8);
1065 }
1066 else
1067 {
1068 vk = MAKEWORD(vk, wChar);
1069 }
1070 }
1071 }
1072 }
1073
1074 /* allocate a list */
1075 cbList = offsetof(TRANSMSGLIST, TransMsg) + MSG_COUNT * sizeof(TRANSMSG);
1076 pList = ImmLocalAlloc(0, cbList);
1077 if (IS_NULL_UNEXPECTEDLY(pList))
1078 goto Quit;
1079
1080 /* use IME conversion engine and convert the list */
1081 pList->uMsgCount = MSG_COUNT;
1082 kret = pImeDpi->ImeToAsciiEx(vk, HIWORD(lKeyData), abKeyState, pList, 0, hIMC);
1083 if (kret <= 0)
1084 goto Quit;
1085
1086 /* post them */
1087 if (kret <= MSG_COUNT)
1088 {
1089 ImmPostMessages(hwnd, hIMC, kret, pList->TransMsg);
1090 ret = TRUE;
1091 }
1092 else
1093 {
1094 pTransMsg = ImmLockIMCC(pIC->hMsgBuf);
1095 if (IS_NULL_UNEXPECTEDLY(pTransMsg))
1096 goto Quit;
1097 ImmPostMessages(hwnd, hIMC, kret, pTransMsg);
1098 ImmUnlockIMCC(pIC->hMsgBuf);
1099 }
1100
1101 Quit:
1102 ImmLocalFree(pList);
1103 ImmUnlockImeDpi(pImeDpi);
1104 ImmUnlockIMC(hIMC);
1105 ImmReleaseContext(hwnd, hIMC);
1106 TRACE("ret: %d\n", ret);
1107 return ret;
1108 #undef MSG_COUNT
1109 }
1110
1111 /***********************************************************************
1112 * ImmRequestMessageA(IMM32.@)
1113 */
ImmRequestMessageA(HIMC hIMC,WPARAM wParam,LPARAM lParam)1114 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
1115 {
1116 TRACE("(%p, %p, %p)\n", hIMC, wParam, lParam);
1117 return ImmRequestMessageAW(hIMC, wParam, lParam, TRUE);
1118 }
1119
1120 /***********************************************************************
1121 * ImmRequestMessageW(IMM32.@)
1122 */
ImmRequestMessageW(HIMC hIMC,WPARAM wParam,LPARAM lParam)1123 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
1124 {
1125 TRACE("(%p, %p, %p)\n", hIMC, wParam, lParam);
1126 return ImmRequestMessageAW(hIMC, wParam, lParam, FALSE);
1127 }
1128
1129 /***********************************************************************
1130 * ImmCallImeConsoleIME (IMM32.@)
1131 */
1132 DWORD WINAPI
ImmCallImeConsoleIME(_In_ HWND hWnd,_In_ UINT uMsg,_In_ WPARAM wParam,_In_ LPARAM lParam,_Out_ LPUINT puVK)1133 ImmCallImeConsoleIME(
1134 _In_ HWND hWnd,
1135 _In_ UINT uMsg,
1136 _In_ WPARAM wParam,
1137 _In_ LPARAM lParam,
1138 _Out_ LPUINT puVK)
1139 {
1140 DWORD dwThreadId, ret = 0;
1141 HKL hKL;
1142 PWND pWnd = NULL;
1143 HIMC hIMC;
1144 PIMEDPI pImeDpi;
1145 UINT uVK;
1146 PIMC pIMC;
1147
1148 switch (uMsg)
1149 {
1150 case WM_KEYDOWN:
1151 case WM_KEYUP:
1152 case WM_SYSKEYDOWN:
1153 case WM_SYSKEYUP:
1154 break;
1155
1156 default:
1157 return 0;
1158 }
1159
1160 dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
1161 hKL = GetKeyboardLayout(dwThreadId);
1162
1163 if (hWnd && gpsi)
1164 pWnd = ValidateHwndNoErr(hWnd);
1165 if (IS_NULL_UNEXPECTEDLY(pWnd))
1166 return 0;
1167
1168 hIMC = ImmGetContext(hWnd);
1169 if (IS_NULL_UNEXPECTEDLY(hIMC))
1170 return 0;
1171
1172 uVK = *puVK = (wParam & 0xFF);
1173
1174 pIMC = ValidateHandleNoErr(hIMC, TYPE_INPUTCONTEXT);
1175 if (IS_NULL_UNEXPECTEDLY(pIMC))
1176 return 0;
1177
1178 pImeDpi = ImmLockImeDpi(hKL);
1179 if (IS_NULL_UNEXPECTEDLY(pImeDpi))
1180 return 0;
1181
1182 if ((lParam & MAKELPARAM(0, KF_UP)) && (pImeDpi->ImeInfo.fdwProperty & IME_PROP_IGNORE_UPKEYS))
1183 goto Quit;
1184
1185 switch (uVK)
1186 {
1187 case VK_DBE_ROMAN:
1188 case VK_DBE_NOROMAN:
1189 case VK_DBE_HIRAGANA:
1190 case VK_DBE_KATAKANA:
1191 case VK_DBE_CODEINPUT:
1192 case VK_DBE_NOCODEINPUT:
1193 case VK_DBE_ENTERWORDREGISTERMODE:
1194 case VK_DBE_ENTERCONFIGMODE:
1195 break;
1196
1197 default:
1198 {
1199 if (uMsg == WM_SYSKEYDOWN || uMsg == WM_SYSKEYUP)
1200 {
1201 if (uVK != VK_MENU && uVK != VK_F10)
1202 goto Quit;
1203 }
1204
1205 if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_NEED_ALTKEY))
1206 {
1207 if (uVK == VK_MENU || (lParam & MAKELPARAM(0, KF_ALTDOWN)))
1208 goto Quit;
1209 }
1210 }
1211 }
1212
1213 ret = ImmProcessKey(hWnd, hKL, uVK, lParam, INVALID_HOTKEY_ID);
1214
1215 Quit:
1216 ImmUnlockImeDpi(pImeDpi);
1217 return ret;
1218 }
1219