ReactOS 0.4.16-dev-88-ga65b6ae
ime.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Input Method Editor and Input Method Manager support
5 * FILE: win32ss/user/ntuser/ime.c
6 * PROGRAMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
8 */
9
10#include <win32k.h>
11#include <jpnvkeys.h>
12
14
15#define INVALID_THREAD_ID ((ULONG)-1)
16#define INVALID_HOTKEY ((UINT)-1)
17#define MOD_KEYS (MOD_CONTROL | MOD_SHIFT | MOD_ALT | MOD_WIN)
18#define MOD_LEFT_RIGHT (MOD_LEFT | MOD_RIGHT)
19
20#define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
21#define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
22#define LANGID_KOREAN MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN)
23#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
24#define LANGID_NEUTRAL MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
25
30
31typedef struct tagIMEHOTKEY
32{
39
40PIMEHOTKEY gpImeHotKeyList = NULL; // Win: gpImeHotKeyListHeader
41LCID glcidSystem = 0; // Win: glcidSystem
42
43// Win: GetAppImeCompatFlags
45{
46 if (!pti)
48
49 return pti->ppi->dwImeCompatFlags;
50}
51
52// Win: GetLangIdMatchLevel
54{
55 LCID lcid;
56
57 if (HotKeyLangId == LANGID_NEUTRAL || HotKeyLangId == LOWORD(hKL))
58 return 3;
59
61 {
62 lcid = NtCurrentTeb()->CurrentLocale;
63 }
65 {
66 ERR("%p\n", NtCurrentTeb());
68 }
70
71 if (HotKeyLangId == LANGIDFROMLCID(lcid))
72 return 2;
73
74 if (glcidSystem == 0)
76
77 if (HotKeyLangId == LANGIDFROMLCID(glcidSystem))
78 return 1;
79
80 return 0;
81}
82
83// Win: GetActiveHKL
85{
86 PTHREADINFO pti;
87
89 {
90 pti = gpqForeground->spwndActive->head.pti;
91 if (pti && pti->KeyboardLayout)
92 return pti->KeyboardLayout->hkl;
93 }
94
95 return UserGetKeyboardLayout(0);
96}
97
98// Win: GetHotKeyLangID
100{
101#define IME_CHOTKEY 0x10
102#define IME_JHOTKEY 0x30
103#define IME_KHOTKEY 0x50
104#define IME_THOTKEY 0x70
105#define IME_XHOTKEY 0x90
106 static const LANGID s_array[] =
107 {
108 /* 0x00 */ (WORD)-1,
109 /* 0x10 */ LANGID_CHINESE_SIMPLIFIED,
110 /* 0x20 */ LANGID_CHINESE_SIMPLIFIED,
111 /* 0x30 */ LANGID_JAPANESE,
112 /* 0x40 */ LANGID_JAPANESE,
113 /* 0x50 */ LANGID_KOREAN,
114 /* 0x60 */ LANGID_KOREAN,
117 };
118
120 return s_array[(dwHotKeyId & 0xF0) >> 4];
121 return LANGID_NEUTRAL;
122}
123
124// Win: AddImeHotKey
126{
127 PIMEHOTKEY pNode;
128
129 if (!*ppList)
130 {
131 *ppList = pHotKey;
132 return;
133 }
134
135 for (pNode = *ppList; pNode; pNode = pNode->pNext)
136 {
137 if (!pNode->pNext)
138 {
139 pNode->pNext = pHotKey;
140 return;
141 }
142 }
143}
144
145// Win: FindImeHotKeyByID
147{
148 PIMEHOTKEY pNode;
149 for (pNode = pList; pNode; pNode = pNode->pNext)
150 {
151 if (pNode->dwHotKeyId == dwHotKeyId)
152 return pNode;
153 }
154 return NULL;
155}
156
157// Win: FindImeHotKeyByKeyWithLang
158static PIMEHOTKEY APIENTRY
160 UINT uVirtualKey, LANGID TargetLangId)
161{
162 PIMEHOTKEY pNode;
165
166 for (pNode = pList; pNode; pNode = pNode->pNext)
167 {
168 if (pNode->uVirtualKey != uVirtualKey)
169 continue;
170
172 if (LangID != TargetLangId && LangID != 0)
173 continue;
174
175 uModifiers = pNode->uModifiers;
177 return pNode;
178
179 if ((uModifiers & MOD_KEYS) != uModKeys)
180 continue;
181
182 if ((uModifiers & uLeftRight) || (uModifiers & MOD_LEFT_RIGHT) == uLeftRight)
183 return pNode;
184 }
185
186 return NULL;
187}
188
189// Win: DeleteImeHotKey
191{
192 PIMEHOTKEY pNode;
193
194 if (*ppList == pHotKey)
195 {
196 *ppList = pHotKey->pNext;
198 return;
199 }
200
201 for (pNode = *ppList; pNode; pNode = pNode->pNext)
202 {
203 if (pNode->pNext == pHotKey)
204 {
205 pNode->pNext = pHotKey->pNext;
207 return;
208 }
209 }
210}
211
212// Win: FindImeHotKeyByKey
215{
216 PIMEHOTKEY pNode, ret = NULL;
218 LANGID LangId;
220 BOOL fKorean = (PRIMARYLANGID(LOWORD(hKL)) == LANG_KOREAN);
221 UINT nScore, nMaxScore = 0;
222
223 for (pNode = pList; pNode; pNode = pNode->pNext)
224 {
225 if (pNode->uVirtualKey != uVirtualKey)
226 continue;
227
228 if ((pNode->uModifiers & MOD_IGNORE_ALL_MODIFIER))
229 {
230 ;
231 }
232 else if ((pNode->uModifiers & MOD_KEYS) != uModKeys)
233 {
234 continue;
235 }
236 else if ((pNode->uModifiers & uLeftRight) ||
237 (pNode->uModifiers & MOD_LEFT_RIGHT) == uLeftRight)
238 {
239 ;
240 }
241 else
242 {
243 continue;
244 }
245
246 LangId = IntGetImeHotKeyLangId(pNode->dwHotKeyId);
247 nScore = IntGetImeHotKeyLanguageScore(hKL, LangId);
248 if (nScore >= 3)
249 return pNode;
250
251 if (fKorean)
252 continue;
253
254 if (nScore == 0)
255 {
258 {
259 if (LOWORD(pti->hklPrev) == LangId)
260 return pNode;
261 }
262 }
263
264 if (nMaxScore < nScore)
265 {
266 nMaxScore = nScore;
267 ret = pNode;
268 }
269 }
270
271 return ret;
272}
273
274// Win: CheckImeHotKey
276{
277 PIMEHOTKEY pHotKey;
279 BOOL bKeyUp = (lParam & 0x80000000);
280 const BYTE *KeyState = MessageQueue->afKeyState;
281 static UINT s_uKeyUpVKey = 0;
282
283 if (bKeyUp)
284 {
285 if (s_uKeyUpVKey != uVirtualKey)
286 {
287 s_uKeyUpVKey = 0;
288 return NULL;
289 }
290
291 s_uKeyUpVKey = 0;
292 }
293
294 uModifiers = 0;
295 if (IS_KEY_DOWN(KeyState, VK_LSHIFT)) uModifiers |= (MOD_SHIFT | MOD_LEFT);
296 if (IS_KEY_DOWN(KeyState, VK_RSHIFT)) uModifiers |= (MOD_SHIFT | MOD_RIGHT);
299 if (IS_KEY_DOWN(KeyState, VK_LMENU)) uModifiers |= (MOD_ALT | MOD_LEFT);
300 if (IS_KEY_DOWN(KeyState, VK_RMENU)) uModifiers |= (MOD_ALT | MOD_RIGHT);
301
306 if (pHotKey)
307 {
308 if (bKeyUp)
309 {
310 if (pHotKey->uModifiers & MOD_ON_KEYUP)
311 return pHotKey;
312 }
313 else
314 {
315 if (pHotKey->uModifiers & MOD_ON_KEYUP)
316 s_uKeyUpVKey = uVirtualKey;
317 else
318 return pHotKey;
319 }
320 }
321
322 return NULL;
323}
324
325// Win: FreeImeHotKeys
327{
328 PIMEHOTKEY pNode, pNext;
329 for (pNode = gpImeHotKeyList; pNode; pNode = pNext)
330 {
331 pNext = pNode->pNext;
333 }
335}
336
337// Win: SetImeHotKey
338static BOOL APIENTRY
340{
341 PIMEHOTKEY pNode;
342 LANGID LangId;
343
344 switch (dwAction)
345 {
347 pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId); /* Find hotkey by ID */
348 if (!pNode)
349 {
350 ERR("dwHotKeyId: 0x%lX\n", dwHotKeyId);
351 return FALSE;
352 }
353
354 IntDeleteImeHotKey(&gpImeHotKeyList, pNode); /* Delete it */
355 return TRUE;
356
357 case SETIMEHOTKEY_ADD:
358 if (LOWORD(uVirtualKey) == VK_PACKET) /* In case of VK_PACKET */
359 return FALSE;
360
362 if (LangId == LANGID_KOREAN)
363 return FALSE; /* Korean can't add IME hotkeys */
364
365 /* Find hotkey by key and language */
369 uVirtualKey, LangId);
370 if (pNode == NULL) /* If not found */
371 pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId); /* Find by ID */
372
373 if (pNode) /* Already exists */
374 {
375 pNode->uModifiers = uModifiers;
376 pNode->uVirtualKey = uVirtualKey;
377 pNode->hKL = hKL;
378 return TRUE;
379 }
380
381 /* Allocate new hotkey */
383 if (!pNode)
384 return FALSE;
385
386 /* Populate */
387 pNode->pNext = NULL;
388 pNode->dwHotKeyId = dwHotKeyId;
389 pNode->uModifiers = uModifiers;
390 pNode->uVirtualKey = uVirtualKey;
391 pNode->hKL = hKL;
392 IntAddImeHotKey(&gpImeHotKeyList, pNode); /* Add it */
393 return TRUE;
394
396 IntFreeImeHotKeys(); /* Delete all the IME hotkeys */
397 return TRUE;
398
399 default:
400 ERR("0x%lX\n", dwAction);
401 return FALSE;
402 }
403}
404
406NtUserGetImeHotKey(DWORD dwHotKeyId, LPUINT lpuModifiers, LPUINT lpuVirtualKey, LPHKL lphKL)
407{
408 PIMEHOTKEY pNode = NULL;
409
411
413 {
414 ProbeForWrite(lpuModifiers, sizeof(UINT), 1);
415 ProbeForWrite(lpuVirtualKey, sizeof(UINT), 1);
416 if (lphKL)
417 ProbeForWrite(lphKL, sizeof(HKL), 1);
418 }
420 {
421 ERR("%p, %p, %p\n", lpuModifiers, lpuVirtualKey, lphKL);
422 _SEH2_YIELD(goto Quit);
423 }
424 _SEH2_END;
425
427 if (!pNode)
428 goto Quit;
429
431 {
432 *lpuModifiers = pNode->uModifiers;
433 *lpuVirtualKey = pNode->uVirtualKey;
434 if (lphKL)
435 *lphKL = pNode->hKL;
436 }
438 {
439 ERR("%p, %p, %p, %p\n", pNode, lpuModifiers, lpuVirtualKey, lphKL);
440 pNode = NULL;
441 }
442 _SEH2_END;
443
444Quit:
445 UserLeave();
446 return !!pNode;
447}
448
449BOOL
450NTAPI
455 HKL hKL,
456 DWORD dwAction)
457{
458 BOOL ret;
461 UserLeave();
462 return ret;
463}
464
465DWORD
466NTAPI
468{
469 PIMEHOTKEY pNode;
471
473
474 if (!gpqForeground || !IS_IMM_MODE())
475 goto Quit;
476
478 if (pNode)
479 ret = pNode->dwHotKeyId;
480
481Quit:
482 UserLeave();
483 return ret;
484}
485
486// Win: GetTopLevelWindow
488{
489 if (!pwnd)
490 return NULL;
491
492 while (pwnd->style & WS_CHILD)
493 pwnd = pwnd->spwndParent;
494
495 return pwnd;
496}
497
498// Win: AssociateInputContext
500{
501 HIMC hOldImc = pWnd->hImc;
502 pWnd->hImc = (pImc ? UserHMGetHandle(pImc) : NULL);
503 return hOldImc;
504}
505
506DWORD
507NTAPI
509{
510 PTHREADINFO pti;
511 PKL pOldKL, pNewKL;
512
514
515 pti = GetW32ThreadInfo();
516 pOldKL = pti->KeyboardLayout;
517 if (pOldKL && pOldKL->hkl != hOldKL)
518 goto Quit;
519
520 pNewKL = UserHklToKbl(hNewKL);
521 if (!pNewKL)
522 goto Quit;
523
524 if (IS_IME_HKL(hNewKL) != IS_IME_HKL(hOldKL))
525 pti->hklPrev = hOldKL;
526
527 UserAssignmentLock((PVOID*)&pti->KeyboardLayout, pNewKL);
528 pti->pClientInfo->hKL = pNewKL->hkl;
529
530Quit:
531 UserLeave();
532 return 0;
533}
534
535// Win: BuildHimcList
537{
538 PIMC pIMC;
539 DWORD dwRealCount = 0;
540
541 if (pti)
542 {
543 for (pIMC = pti->spDefaultImc; pIMC; pIMC = pIMC->pImcNext)
544 {
545 if (dwRealCount < dwCount)
546 phList[dwRealCount] = UserHMGetHandle(pIMC);
547
548 ++dwRealCount;
549 }
550 }
551 else
552 {
553 for (pti = gptiCurrent->ppi->ptiList; pti; pti = pti->ptiSibling)
554 {
555 for (pIMC = pti->spDefaultImc; pIMC; pIMC = pIMC->pImcNext)
556 {
557 if (dwRealCount < dwCount)
558 phList[dwRealCount] = UserHMGetHandle(pIMC);
559
560 ++dwRealCount;
561 }
562 }
563 }
564
565 return dwRealCount;
566}
567
571{
574 PKL pKL;
575 PIMC pIMC;
576 PIMEHOTKEY pImeHotKey;
577 HKL hKL;
578 HWND hWnd;
579
580 ASSERT_REFS_CO(pWnd);
581
582 switch (uMsg)
583 {
584 case WM_KEYDOWN:
585 case WM_KEYUP:
586 case WM_SYSKEYDOWN:
587 case WM_SYSKEYUP:
588 break;
589
590 default:
591 return 0;
592 }
593
594 pIMC = NULL;
595 hWnd = UserHMGetHandle(pWnd);
596 pKL = pWnd->head.pti->KeyboardLayout;
597 if (!pKL)
598 return 0;
599
601 pImeHotKey = IntCheckImeHotKey(MessageQueue, uVirtualKey, lParam);
602 if (pImeHotKey)
603 {
604 dwHotKeyId = pImeHotKey->dwHotKeyId;
605 hKL = pImeHotKey->hKL;
606 }
607 else
608 {
610 hKL = NULL;
611 }
612
614 {
615 if (pKL->hkl != hKL)
616 {
617 UserPostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST,
618 ((pKL->dwFontSigs & gSystemFS) ? INPUTLANGCHANGE_SYSCHARSET : 0),
619 (LPARAM)hKL);
620 }
621
622 if (IntGetImeCompatFlags(pWnd->head.pti) & 0x800000)
623 return 0;
624
625 return IPHK_HOTKEY;
626 }
627
628 if (!IS_IMM_MODE())
629 return 0;
630
632 {
633 if (!pKL->piiex)
634 return 0;
635
636 if (pWnd->hImc)
638 if (!pIMC)
639 return 0;
640
641 if ((lParam & (KF_UP << 16)) &&
643 {
644 return 0;
645 }
646
647 switch (uVirtualKey)
648 {
649 case VK_DBE_CODEINPUT:
652 case VK_DBE_HIRAGANA:
653 case VK_DBE_KATAKANA:
655 case VK_DBE_NOROMAN:
656 case VK_DBE_ROMAN:
657 break;
658
659 default:
660 {
661 if (uMsg == WM_SYSKEYDOWN || uMsg == WM_SYSKEYUP)
662 {
664 return 0;
665 }
666
668 {
669 if (uVirtualKey == VK_MENU || (lParam & 0x20000000))
670 return 0;
671 }
672 break;
673 }
674 }
675 }
676
677 if (LOBYTE(uVirtualKey) == VK_PACKET)
678 uVirtualKey = MAKELONG(wParam, GetW32ThreadInfo()->wchInjected);
679
681
682 if (IntGetImeCompatFlags(pWnd->head.pti) & 0x800000)
683 ret &= ~IPHK_HOTKEY;
684
685 return ret;
686}
687
689NTAPI
691{
693 DWORD dwRealCount;
694 PTHREADINFO pti;
695
697
698 if (!IS_IMM_MODE())
699 {
700 ERR("!IS_IMM_MODE()\n");
702 goto Quit;
703 }
704
705 if (dwThreadId == 0)
706 {
707 pti = gptiCurrent;
708 }
709 else if (dwThreadId == INVALID_THREAD_ID)
710 {
711 pti = NULL;
712 }
713 else
714 {
716 if (!pti || !pti->rpdesk)
717 goto Quit;
718 }
719
721 {
722 ProbeForWrite(phList, dwCount * sizeof(HIMC), 1);
723 ProbeForWrite(pdwCount, sizeof(DWORD), 1);
724 *pdwCount = dwRealCount = UserBuildHimcList(pti, dwCount, phList);
725 }
727 {
728 ERR("%p, %p\n", phList, pdwCount);
729 _SEH2_YIELD(goto Quit);
730 }
731 _SEH2_END;
732
733 if (dwCount < dwRealCount)
735 else
737
738Quit:
739 UserLeave();
740 return ret;
741}
742
743// Win: SetConvMode
745{
746 HKL hKL;
748 LPBYTE KeyState;
749 BOOL bAlphaNumeric, bKatakana, bHiragana, bFullShape, bRoman, bCharCode;
750
751 if (!pti->KeyboardLayout)
752 return;
753
754 hKL = pti->KeyboardLayout->hkl;
755 LangID = LOWORD(hKL);
756 KeyState = pti->MessageQueue->afKeyState;
757
758 switch (PRIMARYLANGID(LangID))
759 {
760 case LANG_JAPANESE:
761 bAlphaNumeric = !(dwConversion & IME_CMODE_NATIVE);
762 bKatakana = !bAlphaNumeric && (dwConversion & IME_CMODE_KATAKANA);
763 bHiragana = !bAlphaNumeric && !(dwConversion & IME_CMODE_KATAKANA);
764 SET_KEY_DOWN(KeyState, VK_DBE_ALPHANUMERIC, bAlphaNumeric);
765 SET_KEY_LOCKED(KeyState, VK_DBE_ALPHANUMERIC, bAlphaNumeric);
766 SET_KEY_DOWN(KeyState, VK_DBE_HIRAGANA, bHiragana);
767 SET_KEY_LOCKED(KeyState, VK_DBE_HIRAGANA, bHiragana);
768 SET_KEY_DOWN(KeyState, VK_DBE_KATAKANA, bKatakana);
769 SET_KEY_LOCKED(KeyState, VK_DBE_KATAKANA, bKatakana);
770
771 bFullShape = (dwConversion & IME_CMODE_FULLSHAPE);
772 SET_KEY_DOWN(KeyState, VK_DBE_DBCSCHAR, bFullShape);
773 SET_KEY_LOCKED(KeyState, VK_DBE_DBCSCHAR, bFullShape);
774 SET_KEY_DOWN(KeyState, VK_DBE_SBCSCHAR, !bFullShape);
775 SET_KEY_LOCKED(KeyState, VK_DBE_SBCSCHAR, !bFullShape);
776
777 bRoman = (dwConversion & IME_CMODE_ROMAN);
778 SET_KEY_DOWN(KeyState, VK_DBE_ROMAN, bRoman);
779 SET_KEY_LOCKED(KeyState, VK_DBE_ROMAN, bRoman);
780 SET_KEY_DOWN(KeyState, VK_DBE_NOROMAN, !bRoman);
781 SET_KEY_LOCKED(KeyState, VK_DBE_NOROMAN, !bRoman);
782
783 bCharCode = (dwConversion & IME_CMODE_CHARCODE);
784 SET_KEY_DOWN(KeyState, VK_DBE_CODEINPUT, bCharCode);
785 SET_KEY_LOCKED(KeyState, VK_DBE_CODEINPUT, bCharCode);
786 SET_KEY_DOWN(KeyState, VK_DBE_NOCODEINPUT, !bCharCode);
787 SET_KEY_LOCKED(KeyState, VK_DBE_NOCODEINPUT, !bCharCode);
788 break;
789
790 case LANG_KOREAN:
791 SET_KEY_LOCKED(KeyState, VK_HANGUL, (dwConversion & IME_CMODE_NATIVE));
792 SET_KEY_LOCKED(KeyState, VK_JUNJA, (dwConversion & IME_CMODE_FULLSHAPE));
793 SET_KEY_LOCKED(KeyState, VK_HANJA, (dwConversion & IME_CMODE_HANJACONVERT));
794 break;
795
796 default:
797 break;
798 }
799}
800
801DWORD
802NTAPI
804{
805 PWND pwnd;
806 PTHREADINFO pti;
807 HKL hKL;
808
810
811 if (!IS_IMM_MODE())
812 {
813 ERR("!IS_IMM_MODE()\n");
814 goto Quit;
815 }
816
817 pwnd = ValidateHwndNoErr(hwnd);
818 if (!pwnd)
819 goto Quit;
820
821 pti = pwnd->head.pti;
822 if (!pti || !gptiForeground)
823 goto Quit;
825 goto Quit;
826 if (ghIMC == pwnd->hImc && gfImeOpen == !!fOpen && gdwImeConversion == dwConversion)
827 goto Quit;
828
829 ghIMC = pwnd->hImc;
830 if (ghIMC)
831 {
832 gfImeOpen = !!fOpen;
833 gdwImeConversion = dwConversion;
834 UserSetImeConversionKeyState(pti, (fOpen ? dwConversion : IME_CMODE_ALPHANUMERIC));
835 }
836
837 if (ISITHOOKED(WH_SHELL))
838 {
839 hKL = (pti->KeyboardLayout ? pti->KeyboardLayout->hkl : NULL);
840 co_HOOK_CallHooks(WH_SHELL, HSHELL_LANGUAGE, (WPARAM)hwnd, (LPARAM)hKL);
841 }
842
843 // TODO:
844
845Quit:
846 UserLeave();
847 return 0;
848}
849
850BOOL
851NTAPI
853 DWORD dwThreadID)
854{
855 PTHREADINFO pti, ptiCurrent;
856 PPROCESSINFO ppi;
857 BOOL ret = FALSE;
858
860
861 if (!IS_IMM_MODE())
862 {
863 ERR("!IS_IMM_MODE()\n");
865 goto Quit;
866 }
867
868 ptiCurrent = GetW32ThreadInfo();
869
870 if (dwThreadID == INVALID_THREAD_ID)
871 {
872 ppi = ptiCurrent->ppi;
873 ppi->W32PF_flags |= W32PF_DISABLEIME;
874
875Retry:
876 for (pti = ppi->ptiList; pti; pti = pti->ptiSibling)
877 {
879
880 if (pti->spwndDefaultIme)
881 {
883 pti->spwndDefaultIme = NULL;
884 goto Retry; /* The contents of ppi->ptiList may be changed. */
885 }
886 }
887 }
888 else
889 {
890 if (dwThreadID == 0)
891 {
892 pti = ptiCurrent;
893 }
894 else
895 {
896 pti = IntTID2PTI(UlongToHandle(dwThreadID));
897
898 /* The thread needs to reside in the current process. */
899 if (!pti || pti->ppi != ptiCurrent->ppi)
900 goto Quit;
901 }
902
904
905 if (pti->spwndDefaultIme)
906 {
908 pti->spwndDefaultIme = NULL;
909 }
910 }
911
912 ret = TRUE;
913
914Quit:
915 UserLeave();
916 return ret;
917}
918
919DWORD
920NTAPI
922{
923 DWORD ret = 0;
924 PWND pWnd;
925 PTHREADINFO pti;
926
928
929 pWnd = ValidateHwndNoErr(hWnd);
930 if (!pWnd)
931 goto Quit;
932
933 if (!IS_IMM_MODE())
934 {
935 ERR("!IS_IMM_MODE()\n");
937 goto Quit;
938 }
939
941 if (pWnd->head.pti->ppi == pti->ppi)
943
944Quit:
945 UserLeave();
946 return ret;
947}
948
949// Win: GetImeInfoEx
953 _Inout_ PIMEINFOEX pInfoEx,
954 _In_ IMEINFOEXCLASS SearchType)
955{
956 PKL pkl, pklHead;
957
958 if (!pWinSta || !gspklBaseLayout)
959 return FALSE;
960
961 pkl = pklHead = gspklBaseLayout;
962
963 /* Find the matching entry from the list and get info */
964 if (SearchType == ImeInfoExKeyboardLayout)
965 {
966 do
967 {
968 if (pInfoEx->hkl == pkl->hkl)
969 {
970 if (!pkl->piiex)
971 {
972 ERR("!pkl->piiex at %p\n", pkl->hkl);
973 break;
974 }
975
976 *pInfoEx = *pkl->piiex;
977 return TRUE;
978 }
979
980 pkl = pkl->pklNext;
981 } while (pkl != pklHead);
982 }
983 else if (SearchType == ImeInfoExImeFileName)
984 {
985 do
986 {
987 if (pkl->piiex &&
988 _wcsnicmp(pkl->piiex->wszImeFile, pInfoEx->wszImeFile,
989 RTL_NUMBER_OF(pkl->piiex->wszImeFile)) == 0)
990 {
991 *pInfoEx = *pkl->piiex;
992 return TRUE;
993 }
994
995 pkl = pkl->pklNext;
996 } while (pkl != pklHead);
997 }
998 else
999 {
1000 ERR("SearchType: %d\n", SearchType);
1001 }
1002
1003 return FALSE;
1004}
1005
1006BOOL
1007NTAPI
1009 PIMEINFOEX pImeInfoEx,
1010 IMEINFOEXCLASS SearchType)
1011{
1012 IMEINFOEX ImeInfoEx;
1013 BOOL ret = FALSE;
1014 PWINSTATION_OBJECT pWinSta;
1015
1017
1018 if (!IS_IMM_MODE())
1019 {
1020 ERR("!IS_IMM_MODE()\n");
1021 goto Quit;
1022 }
1023
1024 _SEH2_TRY
1025 {
1026 ProbeForRead(pImeInfoEx, sizeof(*pImeInfoEx), 1);
1027 ImeInfoEx = *pImeInfoEx;
1028 }
1030 {
1031 ERR("%p\n", pImeInfoEx);
1032 _SEH2_YIELD(goto Quit);
1033 }
1034 _SEH2_END;
1035
1037 ret = UserGetImeInfoEx(pWinSta, &ImeInfoEx, SearchType);
1038 if (!ret)
1039 goto Quit;
1040
1041 _SEH2_TRY
1042 {
1043 ProbeForWrite(pImeInfoEx, sizeof(*pImeInfoEx), 1);
1044 *pImeInfoEx = ImeInfoEx;
1045 }
1047 {
1048 ERR("%p\n", pImeInfoEx);
1049 ret = FALSE;
1050 }
1051 _SEH2_END;
1052
1053Quit:
1054 UserLeave();
1055 return ret;
1056}
1057
1058BOOL
1059NTAPI
1061{
1062 BOOL ret = FALSE;
1063 PWND pWnd;
1064 PTHREADINFO pti;
1065
1067
1068 if (!IS_IMM_MODE())
1069 {
1070 ERR("!IS_IMM_MODE()\n");
1072 goto Quit;
1073 }
1074
1075 pWnd = ValidateHwndNoErr(hWnd);
1076 if (!pWnd)
1077 goto Quit;
1078
1080 if (pWnd->head.pti->ppi == pti->ppi)
1081 ret = UserSetProp(pWnd, AtomImeLevel, UlongToHandle(dwLevel), TRUE);
1082
1083Quit:
1084 UserLeave();
1085 return ret;
1086}
1087
1088// Win: SetImeInfoEx
1092 _Inout_ PIMEINFOEX pImeInfoEx)
1093{
1094 PKL pklHead, pkl;
1095
1096 if (!pWinSta || !gspklBaseLayout)
1097 return FALSE;
1098
1099 pkl = pklHead = gspklBaseLayout;
1100
1101 do
1102 {
1103 if (pkl->hkl != pImeInfoEx->hkl)
1104 {
1105 pkl = pkl->pklNext;
1106 continue;
1107 }
1108
1109 if (!pkl->piiex)
1110 {
1111 ERR("!pkl->piiex at %p\n", pkl->hkl);
1112 return FALSE;
1113 }
1114
1115 if (!pkl->piiex->fLoadFlag)
1116 *pkl->piiex = *pImeInfoEx;
1117
1118 return TRUE;
1119 } while (pkl != pklHead);
1120
1121 return FALSE;
1122}
1123
1124BOOL
1125NTAPI
1127{
1128 BOOL ret = FALSE;
1129 IMEINFOEX ImeInfoEx;
1130 PWINSTATION_OBJECT pWinSta;
1131
1133
1134 if (!IS_IMM_MODE())
1135 {
1136 ERR("!IS_IMM_MODE()\n");
1137 goto Quit;
1138 }
1139
1140 _SEH2_TRY
1141 {
1142 ProbeForRead(pImeInfoEx, sizeof(*pImeInfoEx), 1);
1143 ImeInfoEx = *pImeInfoEx;
1144 }
1146 {
1147 ERR("%p\n", pImeInfoEx);
1148 _SEH2_YIELD(goto Quit);
1149 }
1150 _SEH2_END;
1151
1153 ret = UserSetImeInfoEx(pWinSta, &ImeInfoEx);
1154
1155Quit:
1156 UserLeave();
1157 return ret;
1158}
1159
1160// Choose the preferred owner of the IME window.
1161// Win: ImeSetFutureOwner
1163{
1164 PWND pwndNode, pwndNextOwner, pwndParent, pwndSibling;
1165 PTHREADINFO pti = pImeWnd->head.pti;
1166
1167 if (!pwndOwner || (pwndOwner->style & WS_CHILD)) // invalid owner
1168 return;
1169
1170 // Get the top-level owner of the same thread
1171 for (pwndNode = pwndOwner; ; pwndNode = pwndNextOwner)
1172 {
1173 pwndNextOwner = pwndNode->spwndOwner;
1174 if (!pwndNextOwner || pwndNextOwner->head.pti != pti)
1175 break;
1176 }
1177
1178 // Don't choose the IME-like windows and the bottom-most windows unless necessary.
1179 if (IS_WND_IMELIKE(pwndNode) ||
1180 ((pwndNode->state2 & WNDS2_BOTTOMMOST) && !(pwndOwner->state2 & WNDS2_BOTTOMMOST)))
1181 {
1182 pwndNode = pwndOwner;
1183 }
1184
1185 pwndParent = pwndNode->spwndParent;
1186 if (!pwndParent || pwndOwner != pwndNode)
1187 {
1188 WndSetOwner(pImeWnd, pwndNode);
1189 return;
1190 }
1191
1192 for (pwndSibling = pwndParent->spwndChild; pwndSibling; pwndSibling = pwndSibling->spwndNext)
1193 {
1194 if (pwndNode->head.pti != pwndSibling->head.pti)
1195 continue;
1196
1197 if (IS_WND_MENU(pwndSibling) || IS_WND_IMELIKE(pwndSibling))
1198 continue;
1199
1200 if (pwndSibling->state2 & WNDS2_INDESTROY)
1201 continue;
1202
1203 if (pwndNode == pwndSibling || (pwndSibling->style & WS_CHILD))
1204 continue;
1205
1206 if (pwndSibling->spwndOwner == NULL ||
1207 pwndSibling->head.pti != pwndSibling->spwndOwner->head.pti)
1208 {
1209 pwndNode = pwndSibling;
1210 break;
1211 }
1212 }
1213
1214 WndSetOwner(pImeWnd, pwndNode);
1215}
1216
1217// Get the last non-IME-like top-most window on the desktop.
1218// Win: GetLastTopMostWindowNoIME
1220{
1221 PWND pwndNode, pwndOwner, pwndLastTopMost = NULL;
1222 BOOL bFound;
1223
1224 pwndNode = UserGetDesktopWindow();
1225 if (!pwndNode || pwndNode->spwndChild == NULL)
1226 return NULL;
1227
1228 for (pwndNode = pwndNode->spwndChild;
1229 pwndNode && (pwndNode->ExStyle & WS_EX_TOPMOST);
1230 pwndNode = pwndNode->spwndNext)
1231 {
1232 bFound = FALSE;
1233
1234 if (IS_WND_IMELIKE(pwndNode)) // An IME-like window
1235 {
1236 // Search the IME window from owners
1237 for (pwndOwner = pwndNode; pwndOwner; pwndOwner = pwndOwner->spwndOwner)
1238 {
1239 if (pImeWnd == pwndOwner)
1240 {
1241 bFound = TRUE;
1242 break;
1243 }
1244 }
1245 }
1246
1247 if (!bFound)
1248 pwndLastTopMost = pwndNode;
1249 }
1250
1251 return pwndLastTopMost;
1252}
1253
1254// Adjust the ordering of the windows around the IME window.
1255// Win: ImeSetTopMost
1256VOID FASTCALL IntImeSetTopMost(PWND pImeWnd, BOOL bTopMost, PWND pwndInsertBefore)
1257{
1258 PWND pwndParent, pwndChild, pwndNode, pwndNext, pwndInsertAfter = NULL;
1259 PWND pwndInsertAfterSave;
1260
1261 pwndParent = pImeWnd->spwndParent;
1262 if (!pwndParent)
1263 return;
1264
1265 pwndChild = pwndParent->spwndChild;
1266
1267 if (!bTopMost)
1268 {
1269 // Calculate pwndInsertAfter
1270 pwndInsertAfter = IntGetLastTopMostWindowNoIME(pImeWnd);
1271 if (pwndInsertBefore)
1272 {
1273 for (pwndNode = pwndInsertAfter; pwndNode; pwndNode = pwndNode->spwndNext)
1274 {
1275 if (pwndNode->spwndNext == pwndInsertBefore)
1276 break;
1277
1278 if (pwndNode == pImeWnd)
1279 return;
1280 }
1281
1282 if (!pwndNode)
1283 return;
1284
1285 pwndInsertAfter = pwndNode;
1286 }
1287
1288 // Adjust pwndInsertAfter if the owner is bottom-most
1289 if (pImeWnd->spwndOwner->state2 & WNDS2_BOTTOMMOST)
1290 {
1291 for (pwndNode = pwndInsertAfter; pwndNode; pwndNode = pwndNode->spwndNext)
1292 {
1293 if (pwndNode == pImeWnd->spwndOwner)
1294 break;
1295
1296 if (!IS_WND_IMELIKE(pwndNode))
1297 pwndInsertAfter = pwndNode;
1298 }
1299 }
1300 }
1301
1302 pwndInsertAfterSave = pwndInsertAfter;
1303
1304 while (pwndChild)
1305 {
1306 pwndNext = pwndChild->spwndNext;
1307
1308 // If pwndChild is a good IME-like window, ...
1309 if (IS_WND_IMELIKE(pwndChild) && pwndChild != pwndInsertAfter &&
1310 pwndChild->head.pti == pImeWnd->head.pti)
1311 {
1312 // Find pImeWnd from the owners
1313 for (pwndNode = pwndChild; pwndNode; pwndNode = pwndNode->spwndOwner)
1314 {
1315 if (pwndNode != pImeWnd)
1316 continue;
1317
1318 // Adjust the ordering and the linking
1319 IntUnlinkWindow(pwndChild);
1320
1321 if (bTopMost)
1322 pwndChild->ExStyle |= WS_EX_TOPMOST;
1323 else
1324 pwndChild->ExStyle &= ~WS_EX_TOPMOST;
1325
1326 if (!pwndInsertAfter)
1327 IntLinkHwnd(pwndChild, HWND_TOP);
1328 else
1329 IntLinkHwnd(pwndChild, UserHMGetHandle(pwndInsertAfter));
1330
1331 // Update the preferred position
1332 pwndInsertAfter = pwndChild;
1333 break;
1334 }
1335 }
1336
1337 // Get the next child, with ignoring pwndInsertAfterSave
1338 pwndChild = pwndNext;
1339 if (pwndChild && pwndChild == pwndInsertAfterSave && pwndInsertAfter)
1340 pwndChild = pwndInsertAfter->spwndNext;
1341 }
1342}
1343
1344// Make the IME window top-most if necessary.
1345// Win: ImeCheckTopmost
1347{
1348 BOOL bTopMost;
1349 PWND pwndOwner = pImeWnd->spwndOwner, pwndInsertBefore = NULL;
1350
1351 if (!pwndOwner)
1352 return;
1353
1354 if (pImeWnd->head.pti != gptiForeground)
1355 pwndInsertBefore = pwndOwner;
1356
1357 bTopMost = !!(pwndOwner->ExStyle & WS_EX_TOPMOST);
1358 IntImeSetTopMost(pImeWnd, bTopMost, pwndInsertBefore);
1359}
1360
1361BOOL NTAPI
1363{
1364 BOOL ret = FALSE;
1365 PWND pImeWnd, pwndFocus, pwndTopLevel, pwndNode, pwndActive;
1366 PTHREADINFO ptiIme;
1367
1369
1370 if (!IS_IMM_MODE())
1371 {
1372 ERR("!IS_IMM_MODE()\n");
1373 goto Quit;
1374 }
1375
1376 pImeWnd = ValidateHwndNoErr(hImeWnd);
1377 if (!pImeWnd || pImeWnd->fnid != FNID_IME)
1378 goto Quit;
1379
1380 pwndFocus = ValidateHwndNoErr(hwndFocus);
1381 if (pwndFocus)
1382 {
1383 if (IS_WND_IMELIKE(pwndFocus))
1384 goto Quit;
1385
1386 pwndTopLevel = IntGetTopLevelWindow(pwndFocus);
1387
1388 for (pwndNode = pwndTopLevel; pwndNode; pwndNode = pwndNode->spwndOwner)
1389 {
1390 if (pwndNode->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME])
1391 {
1392 pwndTopLevel = NULL;
1393 break;
1394 }
1395 }
1396
1397 WndSetOwner(pImeWnd, pwndTopLevel);
1398 IntImeCheckTopmost(pImeWnd);
1399 }
1400 else
1401 {
1402 ptiIme = pImeWnd->head.pti;
1403 pwndActive = ptiIme->MessageQueue->spwndActive;
1404
1405 if (!pwndActive || pwndActive != pImeWnd->spwndOwner)
1406 {
1407 if (pwndActive && ptiIme == pwndActive->head.pti && !IS_WND_IMELIKE(pwndActive))
1408 {
1409 WndSetOwner(pImeWnd, pwndActive);
1410 }
1411 else
1412 {
1413 IntImeSetFutureOwner(pImeWnd, pImeWnd->spwndOwner);
1414 }
1415
1416 IntImeCheckTopmost(pImeWnd);
1417 }
1418 }
1419
1420 ret = TRUE;
1421
1422Quit:
1423 UserLeave();
1424 return ret;
1425}
1426
1427PVOID
1429 PTHREADINFO pti,
1430 SIZE_T Size,
1431 PVOID* HandleOwner)
1432{
1433 PTHRDESKHEAD ObjHead;
1434
1435 ASSERT(Size > sizeof(*ObjHead));
1436 ASSERT(pti != NULL);
1437
1438 if (!pDesk)
1439 pDesk = pti->rpdesk;
1440
1441 ObjHead = DesktopHeapAlloc(pDesk, Size);
1442 if (!ObjHead)
1443 return NULL;
1444
1445 RtlZeroMemory(ObjHead, Size);
1446
1447 ObjHead->pSelf = ObjHead;
1448 ObjHead->rpdesk = pDesk;
1449 ObjHead->pti = pti;
1451 *HandleOwner = pti;
1452 pti->ppi->UserHandleCount++;
1453
1454 return ObjHead;
1455}
1456
1458{
1459 PTHRDESKHEAD ObjHead = Object;
1460 PDESKTOP pDesk = ObjHead->rpdesk;
1461 PIMC pNode, pIMC = Object;
1462 PTHREADINFO pti;
1463
1464 if (!pIMC)
1465 return;
1466
1467 // Remove pIMC from the list except spDefaultImc
1468 pti = pIMC->head.pti;
1469 for (pNode = pti->spDefaultImc; pNode; pNode = pNode->pImcNext)
1470 {
1471 if (pNode->pImcNext == pIMC)
1472 {
1473 pNode->pImcNext = pIMC->pImcNext;
1474 break;
1475 }
1476 }
1477
1478 DesktopHeapFree(pDesk, Object);
1479
1480 pti->ppi->UserHandleCount--;
1482}
1483
1485{
1486 PIMC pIMC = Object;
1487 if (!pIMC)
1488 return TRUE;
1489
1492 return TRUE;
1493}
1494
1495// Win: DestroyInputContext
1497{
1498 HIMC hIMC = UserHMGetHandle(pIMC);
1499 PTHREADINFO pti = pIMC->head.pti;
1500 PWND pwndChild;
1501 PWINDOWLIST pwl;
1502 HWND *phwnd;
1503 PWND pWnd;
1504
1505 if (pti != gptiCurrent)
1506 {
1508 return FALSE;
1509 }
1510
1511 if (pIMC == pti->spDefaultImc)
1512 {
1514 return FALSE;
1515 }
1516
1517 pwndChild = pti->rpdesk->pDeskInfo->spwnd->spwndChild;
1518 pwl = IntBuildHwndList(pwndChild, IACE_LIST | IACE_CHILDREN, pti);
1519 if (pwl)
1520 {
1521 for (phwnd = pwl->ahwnd; *phwnd != HWND_TERMINATOR; ++phwnd)
1522 {
1524 if (pWnd && pWnd->hImc == hIMC)
1526 }
1527
1528 IntFreeHwndList(pwl);
1529 }
1530
1532 return TRUE;
1533}
1534
1536{
1537 BOOL ret = FALSE;
1538 PIMC pIMC;
1539
1541
1542 if (!IS_IMM_MODE())
1543 {
1545 goto Quit;
1546 }
1547
1549 if (pIMC)
1551
1552Quit:
1553 UserLeave();
1554 return ret;
1555}
1556
1557// Win: CreateInputContext
1559{
1560 PIMC pIMC;
1562 PDESKTOP pdesk = pti->rpdesk;
1563
1564 if (!IS_IMM_MODE() || (pti->TIF_flags & TIF_DISABLEIME)) // Disabled?
1565 {
1566 ERR("IME is disabled\n");
1567 return NULL;
1568 }
1569
1570 if (!pdesk) // No desktop?
1571 return NULL;
1572
1573 // pti->spDefaultImc should be already set if non-first time.
1574 if (dwClientImcData && !pti->spDefaultImc)
1575 return NULL;
1576
1577 // Create an input context user object.
1578 pIMC = UserCreateObject(gHandleTable, pdesk, pti, NULL, TYPE_INPUTCONTEXT, sizeof(IMC));
1579 if (!pIMC)
1580 return NULL;
1581
1582 // Release the extra reference (UserCreateObject added 2 references).
1584 ASSERT(pIMC->head.cLockObj == 1);
1585
1586 if (dwClientImcData) // Non-first time.
1587 {
1588 // Insert pIMC to the second position (non-default) of the list.
1589 pIMC->pImcNext = pti->spDefaultImc->pImcNext;
1590 pti->spDefaultImc->pImcNext = pIMC;
1591 }
1592 else // First time. It's the default IMC.
1593 {
1594 // Add the first one (default) to the list.
1595 UserAssignmentLock((PVOID*)&pti->spDefaultImc, pIMC);
1596 pIMC->pImcNext = NULL;
1597 ASSERT(pIMC->head.cLockObj == 2); // UserAssignmentUnlock'ed at ExitThreadCallback
1598 }
1599
1600 pIMC->dwClientImcData = dwClientImcData; // Set it.
1601 return pIMC;
1602}
1603
1604HIMC
1605NTAPI
1607{
1608 PIMC pIMC;
1609 HIMC ret = NULL;
1610
1612
1613 if (!IS_IMM_MODE())
1614 {
1615 ERR("!IS_IMM_MODE()\n");
1617 goto Quit;
1618 }
1619
1620 if (!dwClientImcData)
1621 {
1623 goto Quit;
1624 }
1625
1626 pIMC = UserCreateInputContext(dwClientImcData);
1627 if (pIMC)
1628 ret = UserHMGetHandle(pIMC);
1629
1630Quit:
1631 UserLeave();
1632 return ret;
1633}
1634
1635// Win: AssociateInputContextEx
1637{
1638 DWORD ret = 0;
1639 PWINDOWLIST pwl;
1640 BOOL bIgnoreNullImc = (dwFlags & IACE_IGNORENOCONTEXT);
1641 PTHREADINFO pti = pWnd->head.pti;
1642 PWND pwndTarget, pwndFocus = pti->MessageQueue->spwndFocus;
1643 HWND *phwnd;
1644 HIMC hIMC;
1645
1646 if (dwFlags & IACE_DEFAULT)
1647 {
1648 pIMC = pti->spDefaultImc;
1649 }
1650 else
1651 {
1652 if (pIMC && pti != pIMC->head.pti)
1653 return 2;
1654 }
1655
1656 if (pWnd->head.pti->ppi != GetW32ThreadInfo()->ppi ||
1657 (pIMC && pIMC->head.rpdesk != pWnd->head.rpdesk))
1658 {
1659 return 2;
1660 }
1661
1662 if ((dwFlags & IACE_CHILDREN) && pWnd->spwndChild)
1663 {
1664 pwl = IntBuildHwndList(pWnd->spwndChild, IACE_CHILDREN | IACE_LIST, pti);
1665 if (pwl)
1666 {
1667 for (phwnd = pwl->ahwnd; *phwnd != HWND_TERMINATOR; ++phwnd)
1668 {
1669 pwndTarget = ValidateHwndNoErr(*phwnd);
1670 if (!pwndTarget)
1671 continue;
1672
1673 hIMC = (pIMC ? UserHMGetHandle(pIMC) : NULL);
1674 if (pwndTarget->hImc == hIMC || (bIgnoreNullImc && !pwndTarget->hImc))
1675 continue;
1676
1677 IntAssociateInputContext(pwndTarget, pIMC);
1678 if (pwndTarget == pwndFocus)
1679 ret = 1;
1680 }
1681
1682 IntFreeHwndList(pwl);
1683 }
1684 }
1685
1686 if (!bIgnoreNullImc || pWnd->hImc)
1687 {
1688 hIMC = (pIMC ? UserHMGetHandle(pIMC) : NULL);
1689 if (pWnd->hImc != hIMC)
1690 {
1691 IntAssociateInputContext(pWnd, pIMC);
1692 if (pWnd == pwndFocus)
1693 ret = 1;
1694 }
1695 }
1696
1697 return ret;
1698}
1699
1700DWORD
1701NTAPI
1703{
1704 DWORD ret = 2;
1705 PWND pWnd;
1706 PIMC pIMC;
1707
1709
1710 if (!IS_IMM_MODE())
1711 {
1712 ERR("!IS_IMM_MODE()\n");
1713 goto Quit;
1714 }
1715
1716 pWnd = ValidateHwndNoErr(hWnd);
1717 if (!pWnd)
1718 goto Quit;
1719
1720 pIMC = (hIMC ? UserGetObjectNoErr(gHandleTable, hIMC, TYPE_INPUTCONTEXT) : NULL);
1721 ret = IntAssociateInputContextEx(pWnd, pIMC, dwFlags);
1722
1723Quit:
1724 UserLeave();
1725 return ret;
1726}
1727
1728// Win: UpdateInputContext
1730{
1732 PTHREADINFO ptiIMC = pIMC->head.pti;
1733
1734 if (pti->ppi != ptiIMC->ppi) // Different process?
1735 return FALSE;
1736
1737 switch (dwType)
1738 {
1739 case UIC_CLIENTIMCDATA:
1740 if (pIMC->dwClientImcData)
1741 return FALSE; // Already set
1742
1743 pIMC->dwClientImcData = dwValue;
1744 break;
1745
1746 case UIC_IMEWINDOW:
1747 if (!ValidateHwndNoErr((HWND)dwValue))
1748 return FALSE; // Invalid HWND
1749
1750 pIMC->hImeWnd = (HWND)dwValue;
1751 break;
1752
1753 default:
1754 return FALSE;
1755 }
1756
1757 return TRUE;
1758}
1759
1760BOOL
1761NTAPI
1763 HIMC hIMC,
1764 DWORD dwType,
1765 DWORD_PTR dwValue)
1766{
1767 PIMC pIMC;
1768 BOOL ret = FALSE;
1769
1771
1772 if (!IS_IMM_MODE())
1773 {
1774 ERR("!IS_IMM_MODE()\n");
1775 goto Quit;
1776 }
1777
1779 if (!pIMC)
1780 goto Quit;
1781
1782 ret = UserUpdateInputContext(pIMC, dwType, dwValue);
1783
1784Quit:
1785 UserLeave();
1786 return ret;
1787}
1788
1790NTAPI
1792{
1793 PIMC pIMC;
1794 PTHREADINFO ptiIMC;
1795 DWORD_PTR ret = 0;
1796
1798
1799 if (!IS_IMM_MODE())
1800 goto Quit;
1801
1803 if (!pIMC)
1804 goto Quit;
1805
1806 ptiIMC = pIMC->head.pti;
1807
1808 switch (dwType)
1809 {
1810 case QIC_INPUTPROCESSID:
1811 ret = (DWORD_PTR)PsGetThreadProcessId(ptiIMC->pEThread);
1812 break;
1813
1814 case QIC_INPUTTHREADID:
1815 ret = (DWORD_PTR)PsGetThreadId(ptiIMC->pEThread);
1816 break;
1817
1819 if (ptiIMC->spwndDefaultIme)
1821 break;
1822
1823 case QIC_DEFAULTIMC:
1824 if (ptiIMC->spDefaultImc)
1826 break;
1827 }
1828
1829Quit:
1830 UserLeave();
1831 return ret;
1832}
1833
1834// Searchs a non-IME-related window of the same thread of pwndTarget,
1835// other than pwndTarget, around pwndParent. Returns TRUE if found.
1836//
1837// Win: IsChildSameThread
1839{
1840 PWND pwnd, pwndOwner, pwndNode;
1841 PTHREADINFO ptiTarget = pwndTarget->head.pti;
1842
1843 // For all the children of pwndParent, ...
1844 for (pwnd = pwndParent->spwndChild; pwnd; pwnd = pwnd->spwndNext)
1845 {
1846 if (pwnd == pwndTarget || pwnd->head.pti != ptiTarget || IS_WND_MENU(pwnd))
1847 continue;
1848
1849 if (!IS_WND_CHILD(pwnd))
1850 {
1851 // Check if any IME-like owner.
1852 BOOL bFound1 = FALSE;
1853 for (pwndOwner = pwnd; pwndOwner; pwndOwner = pwndOwner->spwndOwner)
1854 {
1855 if (IS_WND_IMELIKE(pwndOwner))
1856 {
1857 bFound1 = TRUE;
1858 break;
1859 }
1860 }
1861 if (bFound1)
1862 continue; // Skip if any IME-like owner.
1863 }
1864
1865 pwndNode = pwnd;
1866
1867 if (IS_WND_CHILD(pwndNode))
1868 {
1869 // Check if any same-thread IME-like ancestor.
1870 BOOL bFound2 = FALSE;
1871 for (; IS_WND_CHILD(pwndNode); pwndNode = pwndNode->spwndParent)
1872 {
1873 if (pwndNode->head.pti != ptiTarget)
1874 break;
1875
1876 if (IS_WND_IMELIKE(pwndNode))
1877 {
1878 bFound2 = TRUE;
1879 break;
1880 }
1881 }
1882 if (bFound2)
1883 continue;
1884 // Now, pwndNode is non-child or non-same-thread window.
1885 }
1886
1887 if (!IS_WND_CHILD(pwndNode)) // pwndNode is non-child
1888 {
1889 // Check if any same-thread IME-like owner.
1890 BOOL bFound3 = FALSE;
1891 for (; pwndNode; pwndNode = pwndNode->spwndOwner)
1892 {
1893 if (pwndNode->head.pti != ptiTarget)
1894 break;
1895
1896 if (IS_WND_IMELIKE(pwndNode))
1897 {
1898 bFound3 = TRUE;
1899 break;
1900 }
1901 }
1902 if (bFound3)
1903 continue;
1904 }
1905
1906 return TRUE;
1907 }
1908
1909 return FALSE;
1910}
1911
1912// Determines whether the target window needs the IME window.
1913// Win: WantImeWindow(pwndParent, pwndTarget)
1915{
1916 PDESKTOP rpdesk;
1917 PWINSTATION_OBJECT rpwinstaParent;
1918 PWND pwndNode, pwndParent = pwndTarget->spwndParent;
1919
1921 return FALSE;
1922
1923 if (IS_WND_IMELIKE(pwndTarget))
1924 return FALSE;
1925
1926 if (pwndTarget->fnid == FNID_DESKTOP || pwndTarget->fnid == FNID_MESSAGEWND)
1927 return FALSE;
1928
1929 if (pwndTarget->state & WNDS_SERVERSIDEWINDOWPROC)
1930 return FALSE;
1931
1932 rpdesk = pwndTarget->head.rpdesk;
1933 if (!rpdesk)
1934 return FALSE;
1935
1936 rpwinstaParent = rpdesk->rpwinstaParent;
1937 if (!rpwinstaParent || (rpwinstaParent->Flags & WSS_NOIO))
1938 return FALSE;
1939
1940 for (pwndNode = pwndParent; pwndNode; pwndNode = pwndNode->spwndParent)
1941 {
1942 if (rpdesk != pwndNode->head.rpdesk)
1943 break;
1944
1945 if (pwndNode == rpdesk->spwndMessage)
1946 return FALSE;
1947 }
1948
1949 return TRUE;
1950}
1951
1952// Create the default IME window for the target window.
1953// Win: xxxCreateDefaultImeWindow(pwndTarget, ATOM, hInst)
1955{
1956 LARGE_UNICODE_STRING WindowName;
1957 UNICODE_STRING ClassName;
1958 PWND pImeWnd;
1959 PIMEUI pimeui;
1960 CREATESTRUCTW Cs;
1963 HANDLE pid = PsGetThreadProcessId(pti->pEThread);
1964
1965 if (!(pti->spDefaultImc) && pid == gpidLogon)
1967
1968 if (!(pti->spDefaultImc) || IS_WND_IMELIKE(pwndTarget) || !(pti->rpdesk->pheapDesktop))
1969 return NULL;
1970
1971 if (IS_WND_CHILD(pwndTarget) && !(pwndTarget->style & WS_VISIBLE) &&
1972 pwndTarget->spwndParent->head.pti->ppi != pti->ppi)
1973 {
1974 return NULL;
1975 }
1976
1977 RtlInitLargeUnicodeString(&WindowName, L"Default IME", 0);
1978
1980 ClassName.Length = 0;
1981 ClassName.MaximumLength = 0;
1982
1983 UserRefObjectCo(pwndTarget, &Ref);
1984
1985 RtlZeroMemory(&Cs, sizeof(Cs));
1986 Cs.style = WS_POPUP | WS_DISABLED;
1987 Cs.hInstance = hInst;
1988 Cs.hwndParent = UserHMGetHandle(pwndTarget);
1989 Cs.lpszName = WindowName.Buffer;
1990 Cs.lpszClass = ClassName.Buffer;
1991
1992 // NOTE: LARGE_UNICODE_STRING is compatible to LARGE_STRING.
1993 pImeWnd = co_UserCreateWindowEx(&Cs, &ClassName, (PLARGE_STRING)&WindowName, NULL, WINVER);
1994 if (pImeWnd)
1995 {
1996 pimeui = ((PIMEWND)pImeWnd)->pimeui;
1997 _SEH2_TRY
1998 {
1999 ProbeForWrite(pimeui, sizeof(IMEUI), 1);
2000 pimeui->fDefault = TRUE;
2001 if (IS_WND_CHILD(pwndTarget) && pwndTarget->spwndParent->head.pti != pti)
2002 pimeui->fChildThreadDef = TRUE;
2003 }
2005 {
2006 ERR("%p\n", pimeui);
2007 }
2008 _SEH2_END;
2009 }
2010
2011 UserDerefObjectCo(pwndTarget);
2012 return pImeWnd;
2013}
2014
2015// Determines whether the system can destroy the default IME window for the target child window.
2016// Win: ImeCanDestroyDefIMEforChild
2018{
2019 PWND pwndNode;
2020 PIMEUI pimeui;
2021 IMEUI SafeImeUI;
2022
2023 pimeui = ((PIMEWND)pImeWnd)->pimeui;
2024 if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
2025 return FALSE;
2026
2027 // Check IMEUI.fChildThreadDef
2028 _SEH2_TRY
2029 {
2030 ProbeForRead(pimeui, sizeof(IMEUI), 1);
2031 SafeImeUI = *pimeui;
2032 if (!SafeImeUI.fChildThreadDef)
2033 return FALSE;
2034 }
2036 {
2037 ERR("%p\n", pimeui);
2038 }
2039 _SEH2_END;
2040
2041 // The parent of pwndTarget is NULL or of the same thread of pwndTarget?
2042 if (pwndTarget->spwndParent == NULL ||
2043 pwndTarget->head.pti == pwndTarget->spwndParent->head.pti)
2044 {
2045 return FALSE;
2046 }
2047
2048 for (pwndNode = pwndTarget; pwndNode; pwndNode = pwndNode->spwndParent)
2049 {
2050 if (pwndNode == pwndNode->head.rpdesk->pDeskInfo->spwnd)
2051 break;
2052
2053 if (IntFindNonImeRelatedWndOfSameThread(pwndNode->spwndParent, pwndTarget))
2054 return FALSE;
2055 }
2056
2057 return TRUE;
2058}
2059
2060// Determines whether the system can destroy the default IME window for the non-child target window.
2061// Win: ImeCanDestroyDefIME
2063{
2064 PWND pwndNode;
2065 PIMEUI pimeui;
2066 IMEUI SafeImeUI;
2067
2068 pimeui = ((PIMEWND)pImeWnd)->pimeui;
2069 if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
2070 return FALSE;
2071
2072 // Check IMEUI.fDestroy
2073 _SEH2_TRY
2074 {
2075 ProbeForRead(pimeui, sizeof(IMEUI), 1);
2076 SafeImeUI = *pimeui;
2077 if (SafeImeUI.fDestroy)
2078 return FALSE;
2079 }
2081 {
2082 ERR("%p\n", pimeui);
2083 }
2084 _SEH2_END;
2085
2086 // Any ancestor of pImeWnd is pwndTarget?
2087 if (pImeWnd->spwndOwner)
2088 {
2089 for (pwndNode = pImeWnd->spwndOwner; pwndNode; pwndNode = pwndNode->spwndOwner)
2090 {
2091 if (pwndNode == pwndTarget)
2092 break;
2093 }
2094
2095 if (!pwndNode)
2096 return FALSE;
2097 }
2098
2099 // Any ancestor of pwndTarget is IME-like?
2100 for (pwndNode = pwndTarget; pwndNode; pwndNode = pwndNode->spwndOwner)
2101 {
2102 if (IS_WND_IMELIKE(pwndNode))
2103 return FALSE;
2104 }
2105
2106 // Adjust the ordering and top-mode status
2107 IntImeSetFutureOwner(pImeWnd, pwndTarget);
2108 for (pwndNode = pImeWnd->spwndOwner; pwndNode; pwndNode = pwndNode->spwndNext)
2109 {
2110 if (pwndNode == pImeWnd)
2111 break;
2112 }
2113 if (pwndNode == pImeWnd)
2114 IntImeCheckTopmost(pImeWnd);
2115
2116 // Is the owner of pImeWnd NULL or pwndTarget?
2117 if (pImeWnd->spwndOwner && pwndTarget != pImeWnd->spwndOwner)
2118 return FALSE;
2119
2120 WndSetOwner(pImeWnd, NULL);
2121 return TRUE;
2122}
2123
2124// Update IMEUI.fShowStatus flags and Send the WM_IME_NOTIFY messages.
2125// Win: xxxCheckImeShowStatus
2127{
2128 BOOL ret = FALSE, bDifferent;
2129 PWINDOWLIST pwl;
2130 HWND *phwnd;
2131 PWND pwndNode, pwndIMC;
2132 PTHREADINFO ptiCurrent = GetW32ThreadInfo();
2133 PIMEUI pimeui;
2134 IMEUI SafeImeUI;
2135
2136 if (pwndIme->state2 & WNDS2_INDESTROY)
2137 return FALSE;
2138
2139 // Build a window list
2140 pwl = IntBuildHwndList(pwndIme->spwndParent->spwndChild, IACE_LIST, NULL);
2141 if (!pwl)
2142 return FALSE;
2143
2144 ret = TRUE;
2145 for (phwnd = pwl->ahwnd; *phwnd != HWND_TERMINATOR; ++phwnd)
2146 {
2147 pwndNode = ValidateHwndNoErr(*phwnd);
2148
2149 if (!pwndNode || pwndIme == pwndNode)
2150 continue;
2151
2152 if (pwndNode->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME] ||
2153 (pwndNode->state2 & WNDS2_INDESTROY))
2154 {
2155 continue;
2156 }
2157
2158 pimeui = ((PIMEWND)pwndNode)->pimeui;
2159 if (!pimeui || pimeui == (PIMEUI)-1)
2160 continue;
2161
2162 if (pti && pti != pwndNode->head.pti)
2163 continue;
2164
2165 // Attach to the process if necessary
2166 bDifferent = FALSE;
2167 if (pwndNode->head.pti->ppi != ptiCurrent->ppi)
2168 {
2169 KeAttachProcess(&(pwndNode->head.pti->ppi->peProcess->Pcb));
2170 bDifferent = TRUE;
2171 }
2172
2173 // Get pwndIMC and update IMEUI.fShowStatus flag
2174 _SEH2_TRY
2175 {
2176 ProbeForWrite(pimeui, sizeof(IMEUI), 1);
2177 SafeImeUI = *pimeui;
2178 if (SafeImeUI.fShowStatus)
2179 {
2180 pwndIMC = ValidateHwndNoErr(pimeui->hwndIMC);
2181 if (pwndIMC)
2182 pimeui->fShowStatus = FALSE;
2183 }
2184 else
2185 {
2186 pwndIMC = NULL;
2187 }
2188 }
2190 {
2191 ERR("%p\n", pimeui);
2192 pwndIMC = NULL;
2193 }
2194 _SEH2_END;
2195
2196 // Detach from the process if necessary
2197 if (bDifferent)
2199
2200 // Send the WM_IME_NOTIFY message
2201 if (pwndIMC && pwndIMC->head.pti && !(pwndIMC->head.pti->TIF_flags & TIF_INCLEANUP))
2202 {
2203 HWND hImeWnd;
2205
2206 UserRefObjectCo(pwndIMC, &Ref);
2207
2208 hImeWnd = UserHMGetHandle(pwndIMC);
2210
2211 UserDerefObjectCo(pwndIMC);
2212 }
2213 }
2214
2215 // Free the window list
2216 IntFreeHwndList(pwl);
2217 return ret;
2218}
2219
2220// Send a UI message.
2223{
2224 PWND pwndUI;
2225 LRESULT ret = 0;
2226 IMEUI SafeImeUI;
2227 BOOL bDifferent = FALSE;
2229
2230 // Attach to the process if necessary
2231 if (ptiIME != GetW32ThreadInfo())
2232 {
2233 bDifferent = TRUE;
2234 KeAttachProcess(&(ptiIME->ppi->peProcess->Pcb));
2235 }
2236
2237 // Get the pwndUI
2238 _SEH2_TRY
2239 {
2240 ProbeForRead(pimeui, sizeof(IMEUI), 1);
2241 SafeImeUI = *pimeui;
2242 pwndUI = ValidateHwndNoErr(SafeImeUI.hwndUI);
2243 }
2245 {
2246 ERR("%p\n", pimeui);
2247 pwndUI = NULL;
2248 }
2249 _SEH2_END;
2250
2251 if (!pwndUI)
2252 goto Quit;
2253
2254 // Increment the recursion count of the IME procedure.
2255 // See also ImeWndProc_common of user32.
2256 _SEH2_TRY
2257 {
2258 ProbeForWrite(&pimeui->nCntInIMEProc, sizeof(LONG), 1);
2260 }
2262 {
2263 ERR("%p\n", pimeui);
2264 _SEH2_YIELD(goto Quit);
2265 }
2266 _SEH2_END;
2267
2268 // Detach from the process if necessary
2269 if (bDifferent)
2271
2272 UserRefObjectCo(pwndUI, &Ref);
2274 UserDerefObjectCo(pwndUI);
2275
2276 // Attach to the process if necessary
2277 if (bDifferent)
2278 KeAttachProcess(&(ptiIME->ppi->peProcess->Pcb));
2279
2280 // Decrement the recursion count of the IME procedure
2281 _SEH2_TRY
2282 {
2283 ProbeForWrite(&pimeui->nCntInIMEProc, sizeof(LONG), 1);
2285 }
2287 {
2288 ERR("%p\n", pimeui);
2289 _SEH2_YIELD(goto Quit);
2290 }
2291 _SEH2_END;
2292
2293Quit:
2294 // Detach from the process if necessary
2295 if (bDifferent)
2297
2298 return ret;
2299}
2300
2301// Send the open status notification.
2302// Win: xxxSendOpenStatusNotify
2305{
2307 PTHREADINFO ptiWnd = pWnd->head.pti;
2309
2310 if (ptiWnd->dwExpWinVer >= WINVER_WINNT4 && pWnd->hImc)
2311 {
2312 UserRefObjectCo(pWnd, &Ref);
2314 UserDerefObjectCo(pWnd);
2315 }
2316 else
2317 {
2318 IntSendMessageToUI(ptiIME, pimeui, WM_IME_NOTIFY, wParam, 0);
2319 }
2320}
2321
2322// Update the IME status and send a notification.
2324{
2325 PIMEUI pimeui;
2326 PWND pWnd;
2327 PTHREADINFO pti, ptiIME;
2328 BOOL bShow, bSendNotify = FALSE;
2329 IMEUI SafeImeUI;
2330
2331 if (!IS_IMM_MODE() || (pImeWnd->state2 & WNDS2_INDESTROY))
2332 return;
2333
2335 ptiIME = pImeWnd->head.pti;
2336
2337 // Attach to the process if necessary
2338 if (pti != ptiIME)
2339 KeAttachProcess(&(ptiIME->ppi->peProcess->Pcb));
2340
2341 // Get an IMEUI and check whether hwndIMC is valid and update fShowStatus
2342 _SEH2_TRY
2343 {
2344 ProbeForWrite(pImeWnd, sizeof(IMEWND), 1);
2345 pimeui = ((PIMEWND)pImeWnd)->pimeui;
2346 SafeImeUI = *pimeui;
2347
2348 bShow = (gfIMEShowStatus == TRUE) && SafeImeUI.fCtrlShowStatus;
2349
2350 pWnd = ValidateHwndNoErr(SafeImeUI.hwndIMC);
2351 if (!pWnd)
2352 pWnd = ptiIME->MessageQueue->spwndFocus;
2353
2354 if (pWnd)
2355 {
2356 bSendNotify = TRUE;
2357 pimeui->fShowStatus = bShow;
2358 }
2359 }
2361 {
2362 ERR("%p, %p\n", pImeWnd, pimeui);
2363
2364 if (pti != ptiIME)
2366
2367 _SEH2_YIELD(return);
2368 }
2369 _SEH2_END;
2370
2371 // Detach from the process if necessary
2372 if (pti != ptiIME)
2374
2375 if (bSendNotify)
2376 IntSendOpenStatusNotify(ptiIME, &SafeImeUI, pWnd, bShow);
2377
2378 if (!(pImeWnd->state2 & WNDS2_INDESTROY))
2379 IntCheckImeShowStatus(pImeWnd, NULL);
2380}
2381
2382// Win: xxxBroadcastImeShowStatusChange
2384{
2385 if (gfIMEShowStatus == bShow || !IS_IMM_MODE())
2386 return TRUE;
2387
2388 gfIMEShowStatus = bShow;
2389 IntNotifyImeShowStatus(pImeWnd);
2390 return TRUE;
2391}
2392
2393/* Win: xxxCheckImeShowStatusInThread */
2395{
2396 if (IS_IMM_MODE() && !(pImeWnd->state2 & WNDS2_INDESTROY))
2397 IntCheckImeShowStatus(pImeWnd, pImeWnd->head.pti);
2398}
2399
2400/* EOF */
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define HandleToUlong(h)
Definition: basetsd.h:79
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
DWORD HIMC
Definition: dimm.idl:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define APIENTRY
Definition: api.h:79
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
HANDLE HWND
Definition: compat.h:19
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
PSERVERINFO gpsi
Definition: imm.c:18
#define ValidateHwndNoErr(hwnd)
Definition: precomp.h:84
#define UlongToPtr(u)
Definition: config.h:106
HINSTANCE hInst
Definition: dxdiag.c:13
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
DWORD dwThreadId
Definition: fdebug.c:31
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
PUSER_MESSAGE_QUEUE gpqForeground
Definition: focus.c:13
FxChildList * pList
#define ISITHOOKED(HookId)
Definition: hook.h:6
#define IS_IME_HKL(hKL)
Definition: imm32_undoc.h:20
IMEINFOEXCLASS
Definition: imm32_undoc.h:51
@ ImeInfoExImeFileName
Definition: imm32_undoc.h:55
@ ImeInfoExKeyboardLayout
Definition: imm32_undoc.h:52
#define IME_CMODE_KATAKANA
Definition: imm.h:343
#define IME_CMODE_ROMAN
Definition: imm.h:346
HKL FAR * LPHKL
Definition: imm.h:24
#define IME_CMODE_NATIVE
Definition: imm.h:337
#define MOD_LEFT
Definition: imm.h:188
#define MOD_ON_KEYUP
Definition: imm.h:191
#define IME_CMODE_HANJACONVERT
Definition: imm.h:348
#define IME_THOTKEY_IME_NONIME_TOGGLE
Definition: imm.h:207
#define MOD_IGNORE_ALL_MODIFIER
Definition: imm.h:192
#define MOD_ALT
Definition: imm.h:184
#define IME_CHOTKEY_IME_NONIME_TOGGLE
Definition: imm.h:195
#define MOD_SHIFT
Definition: imm.h:186
#define MOD_CONTROL
Definition: imm.h:185
#define IME_HOTKEY_DSWITCH_LAST
Definition: imm.h:213
#define IME_CMODE_CHARCODE
Definition: imm.h:347
#define IME_CMODE_ALPHANUMERIC
Definition: imm.h:336
#define IMN_OPENSTATUSWINDOW
Definition: imm.h:373
#define IME_HOTKEY_DSWITCH_FIRST
Definition: imm.h:212
#define IMN_CLOSESTATUSWINDOW
Definition: imm.h:372
#define IME_CMODE_FULLSHAPE
Definition: imm.h:345
#define MOD_RIGHT
Definition: imm.h:189
#define IME_PROP_NEED_ALTKEY
Definition: immdev.h:387
#define IME_PROP_IGNORE_UPKEYS
Definition: immdev.h:386
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ICLS_IME
Definition: ntuser.h:927
#define TIF_INCLEANUP
Definition: ntuser.h:263
#define FNID_DESKTOP
Definition: ntuser.h:862
#define WNDS_SERVERSIDEWINDOWPROC
Definition: ntuser.h:623
#define WNDS2_BOTTOMMOST
Definition: ntuser.h:646
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
DWORD NTAPI NtUserNotifyIMEStatus(HWND hwnd, BOOL fOpen, DWORD dwConversion)
Definition: ime.c:803
BOOL NTAPI NtUserDisableThreadIme(DWORD dwThreadID)
Definition: ime.c:852
#define TIF_DISABLEIME
Definition: ntuser.h:288
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:807
#define IS_IMM_MODE()
Definition: ntuser.h:1209
BOOL NTAPI NtUserSetImeInfoEx(PIMEINFOEX pImeInfoEx)
Definition: ime.c:1126
DWORD_PTR NTAPI NtUserQueryInputContext(HIMC hIMC, DWORD dwType)
Definition: ime.c:1791
@ TYPE_WINDOW
Definition: ntuser.h:41
@ TYPE_INPUTCONTEXT
Definition: ntuser.h:57
#define FNID_IME
Definition: ntuser.h:874
struct _IMEWND * PIMEWND
VOID NTAPI RtlInitLargeUnicodeString(IN OUT PLARGE_UNICODE_STRING, IN PCWSTR, IN INT)
Definition: rtlstr.c:42
#define WNDS2_INDESTROY
Definition: ntuser.h:648
#define FNID_MESSAGEWND
Definition: ntuser.h:864
BOOL NTAPI NtUserGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType)
Definition: ime.c:1008
#define NtCurrentTeb
#define LOBYTE(W)
Definition: jmemdos.c:487
#define VK_DBE_ROMAN
Definition: jpnvkeys.h:19
#define VK_DBE_DBCSCHAR
Definition: jpnvkeys.h:18
#define VK_DBE_ALPHANUMERIC
Definition: jpnvkeys.h:14
#define VK_DBE_HIRAGANA
Definition: jpnvkeys.h:16
#define VK_DBE_CODEINPUT
Definition: jpnvkeys.h:24
#define VK_DBE_NOROMAN
Definition: jpnvkeys.h:20
#define VK_DBE_SBCSCHAR
Definition: jpnvkeys.h:17
#define VK_DBE_KATAKANA
Definition: jpnvkeys.h:15
#define VK_DBE_ENTERCONFIGMODE
Definition: jpnvkeys.h:22
#define VK_DBE_ENTERWORDREGISTERMODE
Definition: jpnvkeys.h:21
#define VK_DBE_NOCODEINPUT
Definition: jpnvkeys.h:25
USHORT LANGID
Definition: mui.h:9
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
UINT_PTR HKL
Definition: msctf.idl:143
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI ZwQueryDefaultLocale(_In_ BOOLEAN UserProfile, _Out_ PLCID DefaultLocaleId)
#define BOOL
Definition: nt_native.h:43
#define FASTCALL
Definition: nt_native.h:50
#define DWORD
Definition: nt_native.h:44
#define SORT_DEFAULT
#define MAKELCID(lgid, srtid)
HANDLE NTAPI PsGetThreadId(IN PETHREAD Thread)
Definition: thread.c:705
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
HANDLE NTAPI PsGetThreadProcessId(IN PETHREAD Thread)
Definition: thread.c:745
LRESULT APIENTRY co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
Definition: hook.c:1102
PWINSTATION_OBJECT FASTCALL IntGetProcessWindowStation(HWINSTA *phWinSta OPTIONAL)
Definition: winsta.c:400
ATOM AtomImeLevel
Definition: ntuser.c:28
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
PTHREADINFO gptiCurrent
Definition: ntuser.c:15
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:242
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
#define L(x)
Definition: ntvdm.h:50
static __inline VOID UserDerefObjectCo(PVOID obj)
Definition: object.h:40
static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)
Definition: object.h:27
#define LOWORD(l)
Definition: pedump.c:82
#define WS_CHILD
Definition: pedump.c:617
#define WS_POPUP
Definition: pedump.c:616
#define WS_VISIBLE
Definition: pedump.c:620
#define WS_EX_TOPMOST
Definition: pedump.c:647
long LONG
Definition: pedump.c:60
#define WS_DISABLED
Definition: pedump.c:621
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:621
VOID NTAPI KeAttachProcess(IN PKPROCESS Process)
Definition: procobj.c:582
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define LANGIDFROMLCID(l)
Definition: nls.h:18
DWORD LCID
Definition: nls.h:13
#define LANG_JAPANESE
Definition: nls.h:76
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define LANG_KOREAN
Definition: nls.h:84
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
HANDLE gpidLogon
Definition: simplecall.c:15
RTL_ATOM atomClassName
Definition: ntuser.h:568
struct _WINSTATION_OBJECT * rpwinstaParent
Definition: desktop.h:11
PWND spwndMessage
Definition: desktop.h:20
DWORD dwImeCompatFlags
Definition: win32.h:276
PTHREADINFO ptiList
Definition: win32.h:256
struct _DESKTOP * rpdesk
Definition: ntuser.h:194
PVOID pSelf
Definition: ntuser.h:195
PPROCESSINFO ppi
Definition: win32.h:88
DWORD dwExpWinVer
Definition: win32.h:112
PTHREADINFO ptiSibling
Definition: win32.h:116
struct _CLIENTINFO * pClientInfo
Definition: win32.h:94
struct tagIMC * spDefaultImc
Definition: win32.h:132
HKL hklPrev
Definition: win32.h:133
struct tagKL * KeyboardLayout
Definition: win32.h:90
FLONG TIF_flags
Definition: win32.h:95
struct _DESKTOP * rpdesk
Definition: win32.h:92
struct _WND * spwndDefaultIme
Definition: win32.h:131
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:89
USHORT MaximumLength
Definition: env_spec_w32.h:370
BYTE afKeyState[256 *2/8]
Definition: msgqueue.h:84
Definition: object.h:4
Definition: ntuser.h:694
DWORD ExStyle
Definition: ntuser.h:704
PCLS pcls
Definition: ntuser.h:720
struct _WND * spwndOwner
Definition: ntuser.h:715
THRDESKHEAD head
Definition: ntuser.h:695
DWORD style
Definition: ntuser.h:706
DWORD state2
Definition: ntuser.h:702
struct _WND * spwndChild
Definition: ntuser.h:714
DWORD fnid
Definition: ntuser.h:709
HIMC hImc
Definition: ntuser.h:740
DWORD state
Definition: ntuser.h:701
struct _WND * spwndNext
Definition: ntuser.h:711
struct _WND * spwndParent
Definition: ntuser.h:713
DWORD fdwProperty
Definition: immdev.h:22
LPCWSTR lpszClass
Definition: winuser.h:2968
LPCWSTR lpszName
Definition: winuser.h:2967
HINSTANCE hInstance
Definition: winuser.h:2959
Definition: ntuser.h:199
THRDESKHEAD head
Definition: ntuser.h:200
struct tagIMC * pImcNext
Definition: ntuser.h:201
HWND hImeWnd
Definition: ntuser.h:203
ULONG_PTR dwClientImcData
Definition: ntuser.h:202
UINT uModifiers
Definition: ime.c:36
HKL hKL
Definition: ime.c:37
DWORD dwHotKeyId
Definition: ime.c:34
UINT uVirtualKey
Definition: ime.c:35
struct tagIMEHOTKEY * pNext
Definition: ime.c:33
IMEINFO ImeInfo
Definition: imm32_undoc.h:34
WCHAR wszImeFile[80]
Definition: imm32_undoc.h:42
UINT fDefault
Definition: ntuser.h:1225
UINT fCtrlShowStatus
Definition: ntuser.h:1227
HWND hwndIMC
Definition: ntuser.h:1217
UINT fShowStatus
Definition: ntuser.h:1222
HWND hwndUI
Definition: ntuser.h:1219
LONG nCntInIMEProc
Definition: ntuser.h:1220
UINT fDestroy
Definition: ntuser.h:1224
UINT fChildThreadDef
Definition: ntuser.h:1226
Definition: input.h:27
PIMEINFOEX piiex
Definition: input.h:38
DWORD dwFontSigs
Definition: input.h:34
HKL hkl
Definition: input.h:32
struct tagKL * pklNext
Definition: input.h:29
ATOM atomSysClass[ICLS_NOTUSED+1]
Definition: ntuser.h:1060
HWND ahwnd[ANYSIZE_ARRAY]
Definition: window.h:91
#define WINVER
Definition: targetver.h:11
#define LONG_PTR
Definition: treelist.c:79
#define DWORD_PTR
Definition: treelist.c:76
uint32_t DWORD_PTR
Definition: typedefs.h:65
unsigned char * LPBYTE
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t * LPDWORD
Definition: typedefs.h:59
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MAKELONG(a, b)
Definition: typedefs.h:249
uint32_t * LPUINT
Definition: typedefs.h:59
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
@ UIC_CLIENTIMCDATA
Definition: undocuser.h:309
@ UIC_IMEWINDOW
Definition: undocuser.h:310
#define IPHK_HOTKEY
Definition: undocuser.h:139
@ QIC_DEFAULTWINDOWIME
Definition: undocuser.h:400
@ QIC_DEFAULTIMC
Definition: undocuser.h:401
@ QIC_INPUTTHREADID
Definition: undocuser.h:399
@ QIC_INPUTPROCESSID
Definition: undocuser.h:398
@ SETIMEHOTKEY_INITIALIZE
Definition: undocuser.h:409
@ SETIMEHOTKEY_ADD
Definition: undocuser.h:408
@ SETIMEHOTKEY_DELETE
Definition: undocuser.h:407
#define ASSERT_REFS_CO(_obj_)
Definition: userfuncs.h:14
BOOLEAN co_UserDestroyWindow(PVOID Object)
Definition: window.c:2855
int ret
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_writes_opt_ NumCharacters PUSHORT _Inout_ PUSHORT _In_ UCHAR _In_opt_ USHORT LangID
Definition: wdfusb.h:1083
#define IntDereferenceThreadInfo(pti)
Definition: win32.h:171
#define IntReferenceThreadInfo(pti)
Definition: win32.h:166
#define W32PF_DISABLEIME
Definition: win32.h:28
DWORD APIENTRY co_IntImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID)
Definition: callback.c:1253
PWND FASTCALL UserGetDesktopWindow(VOID)
Definition: desktop.c:1403
PTHREADINFO gptiForeground
Definition: focus.c:15
static __inline PVOID DesktopHeapAlloc(IN PDESKTOP Desktop, IN SIZE_T Bytes)
Definition: desktop.h:204
static __inline BOOL DesktopHeapFree(IN PDESKTOP Desktop, IN PVOID lpMem)
Definition: desktop.h:215
LCID glcidSystem
Definition: ime.c:41
#define LANGID_KOREAN
Definition: ime.c:22
BOOL IntFindNonImeRelatedWndOfSameThread(PWND pwndParent, PWND pwndTarget)
Definition: ime.c:1838
static PIMEHOTKEY FASTCALL IntGetImeHotKeyById(PIMEHOTKEY pList, DWORD dwHotKeyId)
Definition: ime.c:146
#define INVALID_HOTKEY
Definition: ime.c:16
#define INVALID_THREAD_ID
Definition: ime.c:15
VOID FASTCALL IntFreeImeHotKeys(VOID)
Definition: ime.c:326
#define LANGID_JAPANESE
Definition: ime.c:21
#define LANGID_CHINESE_SIMPLIFIED
Definition: ime.c:20
#define IME_XHOTKEY
DWORD FASTCALL IntAssociateInputContextEx(PWND pWnd, PIMC pIMC, DWORD dwFlags)
Definition: ime.c:1636
struct tagIMEHOTKEY IMEHOTKEY
BOOL NTAPI NtUserSetImeHotKey(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DWORD dwAction)
Definition: ime.c:451
PIMEHOTKEY IntGetImeHotKeyByKey(PIMEHOTKEY pList, UINT uModKeys, UINT uLeftRight, UINT uVirtualKey)
Definition: ime.c:214
PWND FASTCALL IntGetTopLevelWindow(PWND pwnd)
Definition: ime.c:487
LRESULT FASTCALL IntSendMessageToUI(PTHREADINFO ptiIME, PIMEUI pimeui, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: ime.c:2222
#define LANGID_NEUTRAL
Definition: ime.c:24
DWORD NTAPI NtUserSetThreadLayoutHandles(HKL hNewKL, HKL hOldKL)
Definition: ime.c:508
static VOID FASTCALL IntDeleteImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
Definition: ime.c:190
PVOID AllocInputContextObject(PDESKTOP pDesk, PTHREADINFO pti, SIZE_T Size, PVOID *HandleOwner)
Definition: ime.c:1428
BOOL FASTCALL IntImeCanDestroyDefIME(PWND pImeWnd, PWND pwndTarget)
Definition: ime.c:2062
DWORD NTAPI NtUserGetAppImeLevel(HWND hWnd)
Definition: ime.c:921
static BOOL APIENTRY IntSetImeHotKey(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DWORD dwAction)
Definition: ime.c:339
static LANGID FASTCALL IntGetImeHotKeyLangId(DWORD dwHotKeyId)
Definition: ime.c:99
#define MOD_LEFT_RIGHT
Definition: ime.c:18
DWORD FASTCALL UserBuildHimcList(PTHREADINFO pti, DWORD dwCount, HIMC *phList)
Definition: ime.c:536
#define MOD_KEYS
Definition: ime.c:17
BOOL IntDestroyInputContext(PIMC pIMC)
Definition: ime.c:1496
DWORD NTAPI NtUserCheckImeHotKey(UINT uVirtualKey, LPARAM lParam)
Definition: ime.c:467
VOID FASTCALL IntSendOpenStatusNotify(PTHREADINFO ptiIME, PIMEUI pimeui, PWND pWnd, BOOL bOpen)
Definition: ime.c:2304
BOOL gfIMEShowStatus
Definition: ime.c:29
BOOL FASTCALL IntCheckImeShowStatus(PWND pwndIme, PTHREADINFO pti)
Definition: ime.c:2126
BOOL NTAPI NtUserSetAppImeLevel(HWND hWnd, DWORD dwLevel)
Definition: ime.c:1060
BOOL FASTCALL UserUpdateInputContext(PIMC pIMC, DWORD dwType, DWORD_PTR dwValue)
Definition: ime.c:1729
BOOL NTAPI NtUserSetImeOwnerWindow(HWND hImeWnd, HWND hwndFocus)
Definition: ime.c:1362
#define IME_CHOTKEY
VOID FASTCALL IntCheckImeShowStatusInThread(PWND pImeWnd)
Definition: ime.c:2394
BOOL NTAPI NtUserDestroyInputContext(HIMC hIMC)
Definition: ime.c:1535
PIMEHOTKEY gpImeHotKeyList
Definition: ime.c:40
PWND FASTCALL co_IntCreateDefaultImeWindow(PWND pwndTarget, HINSTANCE hInst)
Definition: ime.c:1954
HIMC ghIMC
Definition: ime.c:26
DWORD gdwImeConversion
Definition: ime.c:28
BOOL NTAPI NtUserGetImeHotKey(DWORD dwHotKeyId, LPUINT lpuModifiers, LPUINT lpuVirtualKey, LPHKL lphKL)
Definition: ime.c:406
#define LANGID_CHINESE_TRADITIONAL
Definition: ime.c:23
PIMC FASTCALL UserCreateInputContext(ULONG_PTR dwClientImcData)
Definition: ime.c:1558
BOOL FASTCALL IntImeCanDestroyDefIMEforChild(PWND pImeWnd, PWND pwndTarget)
Definition: ime.c:2017
HIMC FASTCALL IntAssociateInputContext(PWND pWnd, PIMC pImc)
Definition: ime.c:499
VOID FASTCALL IntImeSetFutureOwner(PWND pImeWnd, PWND pwndOwner)
Definition: ime.c:1162
BOOL FASTCALL IntWantImeWindow(PWND pwndTarget)
Definition: ime.c:1914
BOOL FASTCALL UserGetImeInfoEx(_Inout_ PWINSTATION_OBJECT pWinSta, _Inout_ PIMEINFOEX pInfoEx, _In_ IMEINFOEXCLASS SearchType)
Definition: ime.c:951
VOID FASTCALL IntImeSetTopMost(PWND pImeWnd, BOOL bTopMost, PWND pwndInsertBefore)
Definition: ime.c:1256
PWND FASTCALL IntGetLastTopMostWindowNoIME(PWND pImeWnd)
Definition: ime.c:1219
BOOLEAN UserDestroyInputContext(PVOID Object)
Definition: ime.c:1484
NTSTATUS NTAPI NtUserBuildHimcList(DWORD dwThreadId, DWORD dwCount, HIMC *phList, LPDWORD pdwCount)
Definition: ime.c:690
UINT FASTCALL IntGetImeHotKeyLanguageScore(HKL hKL, LANGID HotKeyLangId)
Definition: ime.c:53
HKL FASTCALL IntGetActiveKeyboardLayout(VOID)
Definition: ime.c:84
HIMC NTAPI NtUserCreateInputContext(ULONG_PTR dwClientImcData)
Definition: ime.c:1606
BOOL FASTCALL UserSetImeInfoEx(_Inout_ PWINSTATION_OBJECT pWinSta, _Inout_ PIMEINFOEX pImeInfoEx)
Definition: ime.c:1090
VOID FASTCALL IntImeCheckTopmost(PWND pImeWnd)
Definition: ime.c:1346
static VOID FASTCALL UserSetImeConversionKeyState(PTHREADINFO pti, DWORD dwConversion)
Definition: ime.c:744
VOID FASTCALL IntNotifyImeShowStatus(PWND pImeWnd)
Definition: ime.c:2323
VOID UserFreeInputContext(PVOID Object)
Definition: ime.c:1457
BOOL NTAPI NtUserUpdateInputContext(HIMC hIMC, DWORD dwType, DWORD_PTR dwValue)
Definition: ime.c:1762
BOOL FASTCALL IntBroadcastImeShowStatusChange(PWND pImeWnd, BOOL bShow)
Definition: ime.c:2383
struct tagIMEHOTKEY * PIMEHOTKEY
PIMEHOTKEY IntCheckImeHotKey(PUSER_MESSAGE_QUEUE MessageQueue, UINT uVirtualKey, LPARAM lParam)
Definition: ime.c:275
DWORD FASTCALL IntGetImeCompatFlags(PTHREADINFO pti)
Definition: ime.c:44
BOOL gfImeOpen
Definition: ime.c:27
DWORD NTAPI NtUserAssociateInputContext(HWND hWnd, HIMC hIMC, DWORD dwFlags)
Definition: ime.c:1702
UINT FASTCALL IntImmProcessKey(PUSER_MESSAGE_QUEUE MessageQueue, PWND pWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: ime.c:569
static VOID FASTCALL IntAddImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
Definition: ime.c:125
static PIMEHOTKEY APIENTRY IntGetImeHotKeyByKeyAndLang(PIMEHOTKEY pList, UINT uModKeys, UINT uLeftRight, UINT uVirtualKey, LANGID TargetLangId)
Definition: ime.c:159
#define SET_KEY_DOWN(ks, vk, down)
Definition: input.h:100
DWORD gSystemFS
Definition: kbdlayout.c:24
PKL gspklBaseLayout
Definition: kbdlayout.c:22
PKL NTAPI UserHklToKbl(HKL hKl)
Definition: kbdlayout.c:539
#define IS_KEY_DOWN(ks, vk)
Definition: input.h:98
#define SET_KEY_LOCKED(ks, vk, down)
Definition: input.h:103
HKL FASTCALL UserGetKeyboardLayout(DWORD dwThreadId)
Definition: kbdlayout.c:995
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1395
LRESULT FASTCALL co_IntSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1495
PTHREADINFO FASTCALL IntTID2PTI(HANDLE id)
Definition: misc.c:42
PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:495
BOOL FASTCALL UserMarkObjectDestroy(PVOID Object)
Definition: object.c:621
PVOID FASTCALL UserAssignmentLock(PVOID *ppvObj, PVOID pvNew)
Definition: object.c:839
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
BOOL FASTCALL UserDeleteObject(HANDLE h, HANDLE_TYPE type)
Definition: object.c:717
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, PDESKTOP pDesktop, PTHREADINFO pti, HANDLE *h, HANDLE_TYPE type, ULONG size)
Definition: object.c:568
PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:481
HANDLE FASTCALL UserGetProp(_In_ PWND Window, _In_ ATOM Atom, _In_ BOOLEAN SystemProp)
Definition: prop.c:46
#define USERTAG_IMEHOTKEY
Definition: tags.h:239
VOID FASTCALL IntFreeHwndList(PWINDOWLIST pwlTarget)
Definition: window.c:1472
VOID FASTCALL IntUnlinkWindow(PWND Wnd)
Definition: window.c:1356
PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW *Cs, PUNICODE_STRING ClassName, PLARGE_STRING WindowName, PVOID acbiBuffer, DWORD dwVer)
Definition: window.c:2175
PWINDOWLIST FASTCALL IntBuildHwndList(PWND pwnd, DWORD dwFlags, PTHREADINFO pti)
Definition: window.c:1426
VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
Definition: window.c:985
static VOID WndSetOwner(_Inout_ PWND pwnd, _In_opt_ PWND pwndOwner)
Definition: window.h:150
#define IS_WND_MENU(pWnd)
Definition: window.h:109
#define WINVER_WINNT4
Definition: window.h:57
#define IS_WND_IMELIKE(pWnd)
Definition: window.h:114
#define HWND_TERMINATOR
Definition: window.h:83
#define IS_WND_CHILD(pWnd)
Definition: window.h:108
#define IACE_LIST
Definition: window.h:106
#define WSS_NOIO
Definition: winsta.h:9
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define WM_KEYUP
Definition: winuser.h:1719
#define WM_IME_NOTIFY
Definition: winuser.h:1833
#define VK_F10
Definition: winuser.h:2267
#define VK_HANGUL
Definition: winuser.h:2212
#define VK_RSHIFT
Definition: winuser.h:2286
#define WH_SHELL
Definition: winuser.h:40
#define VK_LSHIFT
Definition: winuser.h:2285
#define VK_LCONTROL
Definition: winuser.h:2287
#define VK_RCONTROL
Definition: winuser.h:2288
#define KF_UP
Definition: winuser.h:2454
#define HWND_TOP
Definition: winuser.h:1210
#define VK_RMENU
Definition: winuser.h:2290
#define WM_SYSKEYUP
Definition: winuser.h:1723
#define VK_JUNJA
Definition: winuser.h:2213
#define WM_KEYDOWN
Definition: winuser.h:1718
#define VK_HANJA
Definition: winuser.h:2215
#define WM_SYSKEYDOWN
Definition: winuser.h:1722
#define VK_LMENU
Definition: winuser.h:2289
#define VK_MENU
Definition: winuser.h:2207
unsigned char BYTE
Definition: xxhash.c:193