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