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