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