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