xref: /reactos/win32ss/user/ntuser/ime.c (revision ef20cc08)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:        See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:          ReactOS Win32k subsystem
4c2c66affSColin Finck  * PURPOSE:          Input Method Editor and Input Method Manager support
5c2c66affSColin Finck  * FILE:             win32ss/user/ntuser/ime.c
63d78601fSKatayama Hirofumi MZ  * PROGRAMERS:       Casper S. Hornstrup (chorns@users.sourceforge.net)
73d78601fSKatayama Hirofumi MZ  *                   Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck #include <win32k.h>
11c2c66affSColin Finck DBG_DEFAULT_CHANNEL(UserMisc);
12c2c66affSColin Finck 
13fcc222c2SKatayama Hirofumi MZ #define INVALID_THREAD_ID  ((ULONG)-1)
14bbe5fd52SKatayama Hirofumi MZ #define INVALID_HOTKEY     ((UINT)-1)
155d5cc578SKatayama Hirofumi MZ #define MOD_KEYS           (MOD_CONTROL | MOD_SHIFT | MOD_ALT | MOD_WIN)
165d5cc578SKatayama Hirofumi MZ #define MOD_LEFT_RIGHT     (MOD_LEFT | MOD_RIGHT)
175d5cc578SKatayama Hirofumi MZ 
185d5cc578SKatayama Hirofumi MZ #define LANGID_CHINESE_SIMPLIFIED   MAKELANGID(LANG_CHINESE,  SUBLANG_CHINESE_SIMPLIFIED)
195d5cc578SKatayama Hirofumi MZ #define LANGID_JAPANESE             MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
205d5cc578SKatayama Hirofumi MZ #define LANGID_KOREAN               MAKELANGID(LANG_KOREAN,   SUBLANG_KOREAN)
215d5cc578SKatayama Hirofumi MZ #define LANGID_CHINESE_TRADITIONAL  MAKELANGID(LANG_CHINESE,  SUBLANG_CHINESE_TRADITIONAL)
225d5cc578SKatayama Hirofumi MZ #define LANGID_NEUTRAL              MAKELANGID(LANG_NEUTRAL,  SUBLANG_NEUTRAL)
23c2c66affSColin Finck 
249db44371SKatayama Hirofumi MZ // The special virtual keys for Japanese: Used for key states.
259db44371SKatayama Hirofumi MZ // https://www.kthree.co.jp/kihelp/index.html?page=app/vkey&type=html
269db44371SKatayama Hirofumi MZ #define VK_DBE_ALPHANUMERIC 0xF0
279db44371SKatayama Hirofumi MZ #define VK_DBE_KATAKANA 0xF1
289db44371SKatayama Hirofumi MZ #define VK_DBE_HIRAGANA 0xF2
299db44371SKatayama Hirofumi MZ #define VK_DBE_SBCSCHAR 0xF3
309db44371SKatayama Hirofumi MZ #define VK_DBE_DBCSCHAR 0xF4
319db44371SKatayama Hirofumi MZ #define VK_DBE_ROMAN 0xF5
329db44371SKatayama Hirofumi MZ #define VK_DBE_NOROMAN 0xF6
339db44371SKatayama Hirofumi MZ #define VK_DBE_ENTERWORDREGISTERMODE 0xF7
349db44371SKatayama Hirofumi MZ #define VK_DBE_ENTERCONFIGMODE 0xF8
359db44371SKatayama Hirofumi MZ #define VK_DBE_FLUSHSTRING 0xF9
369db44371SKatayama Hirofumi MZ #define VK_DBE_CODEINPUT 0xFA
379db44371SKatayama Hirofumi MZ #define VK_DBE_NOCODEINPUT 0xFB
389db44371SKatayama Hirofumi MZ #define VK_DBE_DETERINESTRING 0xFC
399db44371SKatayama Hirofumi MZ #define VK_DBE_ENTERDLGCONVERSIONMODE 0xFD
409db44371SKatayama Hirofumi MZ 
419db44371SKatayama Hirofumi MZ HIMC ghIMC = NULL;
429db44371SKatayama Hirofumi MZ BOOL gfImeOpen = (BOOL)-1;
439db44371SKatayama Hirofumi MZ DWORD gdwImeConversion = (DWORD)-1;
44242e0b43SKatayama Hirofumi MZ BOOL gfIMEShowStatus = (BOOL)-1;
459db44371SKatayama Hirofumi MZ 
465d5cc578SKatayama Hirofumi MZ typedef struct tagIMEHOTKEY
475d5cc578SKatayama Hirofumi MZ {
485d5cc578SKatayama Hirofumi MZ     struct tagIMEHOTKEY *pNext;
495d5cc578SKatayama Hirofumi MZ     DWORD  dwHotKeyId;
505d5cc578SKatayama Hirofumi MZ     UINT   uVirtualKey;
515d5cc578SKatayama Hirofumi MZ     UINT   uModifiers;
525d5cc578SKatayama Hirofumi MZ     HKL    hKL;
535d5cc578SKatayama Hirofumi MZ } IMEHOTKEY, *PIMEHOTKEY;
545d5cc578SKatayama Hirofumi MZ 
555df5ef2bSKatayama Hirofumi MZ PIMEHOTKEY gpImeHotKeyList = NULL; // Win: gpImeHotKeyListHeader
565df5ef2bSKatayama Hirofumi MZ LCID glcidSystem = 0; // Win: glcidSystem
57bbe5fd52SKatayama Hirofumi MZ 
585df5ef2bSKatayama Hirofumi MZ // Win: GetAppImeCompatFlags
59b5c9d532SKatayama Hirofumi MZ DWORD FASTCALL IntGetImeCompatFlags(PTHREADINFO pti)
60b5c9d532SKatayama Hirofumi MZ {
61b5c9d532SKatayama Hirofumi MZ     if (!pti)
62b5c9d532SKatayama Hirofumi MZ         pti = PsGetCurrentThreadWin32Thread();
63b5c9d532SKatayama Hirofumi MZ 
64b5c9d532SKatayama Hirofumi MZ     return pti->ppi->dwImeCompatFlags;
65b5c9d532SKatayama Hirofumi MZ }
66b5c9d532SKatayama Hirofumi MZ 
675df5ef2bSKatayama Hirofumi MZ // Win: GetLangIdMatchLevel
68bbe5fd52SKatayama Hirofumi MZ UINT FASTCALL IntGetImeHotKeyLanguageScore(HKL hKL, LANGID HotKeyLangId)
69bbe5fd52SKatayama Hirofumi MZ {
70bbe5fd52SKatayama Hirofumi MZ     LCID lcid;
71bbe5fd52SKatayama Hirofumi MZ 
72bbe5fd52SKatayama Hirofumi MZ     if (HotKeyLangId == LANGID_NEUTRAL || HotKeyLangId == LOWORD(hKL))
73bbe5fd52SKatayama Hirofumi MZ         return 3;
74bbe5fd52SKatayama Hirofumi MZ 
75bbe5fd52SKatayama Hirofumi MZ     _SEH2_TRY
76bbe5fd52SKatayama Hirofumi MZ     {
77bbe5fd52SKatayama Hirofumi MZ         lcid = NtCurrentTeb()->CurrentLocale;
78bbe5fd52SKatayama Hirofumi MZ     }
79bbe5fd52SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
80bbe5fd52SKatayama Hirofumi MZ     {
81bbe5fd52SKatayama Hirofumi MZ         lcid = MAKELCID(LANGID_NEUTRAL, SORT_DEFAULT);
82bbe5fd52SKatayama Hirofumi MZ     }
83bbe5fd52SKatayama Hirofumi MZ     _SEH2_END;
84bbe5fd52SKatayama Hirofumi MZ 
85bbe5fd52SKatayama Hirofumi MZ     if (HotKeyLangId == LANGIDFROMLCID(lcid))
86bbe5fd52SKatayama Hirofumi MZ         return 2;
87bbe5fd52SKatayama Hirofumi MZ 
885df5ef2bSKatayama Hirofumi MZ     if (glcidSystem == 0)
895df5ef2bSKatayama Hirofumi MZ         ZwQueryDefaultLocale(FALSE, &glcidSystem);
90bbe5fd52SKatayama Hirofumi MZ 
915df5ef2bSKatayama Hirofumi MZ     if (HotKeyLangId == LANGIDFROMLCID(glcidSystem))
92bbe5fd52SKatayama Hirofumi MZ         return 1;
93bbe5fd52SKatayama Hirofumi MZ 
94bbe5fd52SKatayama Hirofumi MZ     return 0;
95bbe5fd52SKatayama Hirofumi MZ }
96bbe5fd52SKatayama Hirofumi MZ 
975df5ef2bSKatayama Hirofumi MZ // Win: GetActiveHKL
98bbe5fd52SKatayama Hirofumi MZ HKL FASTCALL IntGetActiveKeyboardLayout(VOID)
99bbe5fd52SKatayama Hirofumi MZ {
100bbe5fd52SKatayama Hirofumi MZ     PTHREADINFO pti;
101bbe5fd52SKatayama Hirofumi MZ 
102bbe5fd52SKatayama Hirofumi MZ     if (gpqForeground && gpqForeground->spwndActive)
103bbe5fd52SKatayama Hirofumi MZ     {
104bbe5fd52SKatayama Hirofumi MZ         pti = gpqForeground->spwndActive->head.pti;
105bbe5fd52SKatayama Hirofumi MZ         if (pti && pti->KeyboardLayout)
106bbe5fd52SKatayama Hirofumi MZ             return pti->KeyboardLayout->hkl;
107bbe5fd52SKatayama Hirofumi MZ     }
108bbe5fd52SKatayama Hirofumi MZ 
109bbe5fd52SKatayama Hirofumi MZ     return UserGetKeyboardLayout(0);
110bbe5fd52SKatayama Hirofumi MZ }
1115d5cc578SKatayama Hirofumi MZ 
1125df5ef2bSKatayama Hirofumi MZ // Win: GetHotKeyLangID
1135d5cc578SKatayama Hirofumi MZ static LANGID FASTCALL IntGetImeHotKeyLangId(DWORD dwHotKeyId)
1145d5cc578SKatayama Hirofumi MZ {
1155d5cc578SKatayama Hirofumi MZ #define IME_CHOTKEY 0x10
1165d5cc578SKatayama Hirofumi MZ #define IME_JHOTKEY 0x30
1175d5cc578SKatayama Hirofumi MZ #define IME_KHOTKEY 0x50
1185d5cc578SKatayama Hirofumi MZ #define IME_THOTKEY 0x70
1195d5cc578SKatayama Hirofumi MZ #define IME_XHOTKEY 0x90
1205d5cc578SKatayama Hirofumi MZ     static const LANGID s_array[] =
1215d5cc578SKatayama Hirofumi MZ     {
1225d5cc578SKatayama Hirofumi MZ         /* 0x00 */ (WORD)-1,
1235d5cc578SKatayama Hirofumi MZ         /* 0x10 */ LANGID_CHINESE_SIMPLIFIED,
1245d5cc578SKatayama Hirofumi MZ         /* 0x20 */ LANGID_CHINESE_SIMPLIFIED,
1255d5cc578SKatayama Hirofumi MZ         /* 0x30 */ LANGID_JAPANESE,
1265d5cc578SKatayama Hirofumi MZ         /* 0x40 */ LANGID_JAPANESE,
1275d5cc578SKatayama Hirofumi MZ         /* 0x50 */ LANGID_KOREAN,
1285d5cc578SKatayama Hirofumi MZ         /* 0x60 */ LANGID_KOREAN,
1295d5cc578SKatayama Hirofumi MZ         /* 0x70 */ LANGID_CHINESE_TRADITIONAL,
1305d5cc578SKatayama Hirofumi MZ         /* 0x80 */ LANGID_CHINESE_TRADITIONAL
1315d5cc578SKatayama Hirofumi MZ     };
1325d5cc578SKatayama Hirofumi MZ 
1335d5cc578SKatayama Hirofumi MZ     if (IME_CHOTKEY <= dwHotKeyId && dwHotKeyId < IME_XHOTKEY)
1345d5cc578SKatayama Hirofumi MZ         return s_array[(dwHotKeyId & 0xF0) >> 4];
1355d5cc578SKatayama Hirofumi MZ     return LANGID_NEUTRAL;
1365d5cc578SKatayama Hirofumi MZ }
1375d5cc578SKatayama Hirofumi MZ 
1382f7775c6SKatayama Hirofumi MZ // Win: AddImeHotKey
1395d5cc578SKatayama Hirofumi MZ static VOID FASTCALL IntAddImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
1405d5cc578SKatayama Hirofumi MZ {
1415d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
1425d5cc578SKatayama Hirofumi MZ 
1435d5cc578SKatayama Hirofumi MZ     if (!*ppList)
1445d5cc578SKatayama Hirofumi MZ     {
1455d5cc578SKatayama Hirofumi MZ         *ppList = pHotKey;
1465d5cc578SKatayama Hirofumi MZ         return;
1475d5cc578SKatayama Hirofumi MZ     }
1485d5cc578SKatayama Hirofumi MZ 
1495d5cc578SKatayama Hirofumi MZ     for (pNode = *ppList; pNode; pNode = pNode->pNext)
1505d5cc578SKatayama Hirofumi MZ     {
1515d5cc578SKatayama Hirofumi MZ         if (!pNode->pNext)
1525d5cc578SKatayama Hirofumi MZ         {
1535d5cc578SKatayama Hirofumi MZ             pNode->pNext = pHotKey;
1545d5cc578SKatayama Hirofumi MZ             return;
1555d5cc578SKatayama Hirofumi MZ         }
1565d5cc578SKatayama Hirofumi MZ     }
1575d5cc578SKatayama Hirofumi MZ }
1585d5cc578SKatayama Hirofumi MZ 
1595df5ef2bSKatayama Hirofumi MZ // Win: FindImeHotKeyByID
1605d5cc578SKatayama Hirofumi MZ static PIMEHOTKEY FASTCALL IntGetImeHotKeyById(PIMEHOTKEY pList, DWORD dwHotKeyId)
1615d5cc578SKatayama Hirofumi MZ {
1625d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
1635d5cc578SKatayama Hirofumi MZ     for (pNode = pList; pNode; pNode = pNode->pNext)
1645d5cc578SKatayama Hirofumi MZ     {
1655d5cc578SKatayama Hirofumi MZ         if (pNode->dwHotKeyId == dwHotKeyId)
1665d5cc578SKatayama Hirofumi MZ             return pNode;
1675d5cc578SKatayama Hirofumi MZ     }
1685d5cc578SKatayama Hirofumi MZ     return NULL;
1695d5cc578SKatayama Hirofumi MZ }
1705d5cc578SKatayama Hirofumi MZ 
1715df5ef2bSKatayama Hirofumi MZ // Win: FindImeHotKeyByKeyWithLang
1725d5cc578SKatayama Hirofumi MZ static PIMEHOTKEY APIENTRY
1735d5cc578SKatayama Hirofumi MZ IntGetImeHotKeyByKeyAndLang(PIMEHOTKEY pList, UINT uModKeys, UINT uLeftRight,
1745d5cc578SKatayama Hirofumi MZ                             UINT uVirtualKey, LANGID TargetLangId)
1755d5cc578SKatayama Hirofumi MZ {
1765d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
1775d5cc578SKatayama Hirofumi MZ     LANGID LangID;
1785d5cc578SKatayama Hirofumi MZ     UINT uModifiers;
1795d5cc578SKatayama Hirofumi MZ 
1805d5cc578SKatayama Hirofumi MZ     for (pNode = pList; pNode; pNode = pNode->pNext)
1815d5cc578SKatayama Hirofumi MZ     {
1825d5cc578SKatayama Hirofumi MZ         if (pNode->uVirtualKey != uVirtualKey)
1835d5cc578SKatayama Hirofumi MZ             continue;
1845d5cc578SKatayama Hirofumi MZ 
1855d5cc578SKatayama Hirofumi MZ         LangID = IntGetImeHotKeyLangId(pNode->dwHotKeyId);
18639fe905eSKatayama Hirofumi MZ         if (LangID != TargetLangId && LangID != 0)
1875d5cc578SKatayama Hirofumi MZ             continue;
1885d5cc578SKatayama Hirofumi MZ 
1895d5cc578SKatayama Hirofumi MZ         uModifiers = pNode->uModifiers;
1905d5cc578SKatayama Hirofumi MZ         if (uModifiers & MOD_IGNORE_ALL_MODIFIER)
1915d5cc578SKatayama Hirofumi MZ             return pNode;
1925d5cc578SKatayama Hirofumi MZ 
1935d5cc578SKatayama Hirofumi MZ         if ((uModifiers & MOD_KEYS) != uModKeys)
1945d5cc578SKatayama Hirofumi MZ             continue;
1955d5cc578SKatayama Hirofumi MZ 
1965d5cc578SKatayama Hirofumi MZ         if ((uModifiers & uLeftRight) || (uModifiers & MOD_LEFT_RIGHT) == uLeftRight)
1975d5cc578SKatayama Hirofumi MZ             return pNode;
1985d5cc578SKatayama Hirofumi MZ     }
1995d5cc578SKatayama Hirofumi MZ 
2005d5cc578SKatayama Hirofumi MZ     return NULL;
2015d5cc578SKatayama Hirofumi MZ }
2025d5cc578SKatayama Hirofumi MZ 
2035df5ef2bSKatayama Hirofumi MZ // Win: DeleteImeHotKey
2045d5cc578SKatayama Hirofumi MZ static VOID FASTCALL IntDeleteImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
2055d5cc578SKatayama Hirofumi MZ {
2065d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
2075d5cc578SKatayama Hirofumi MZ 
2085d5cc578SKatayama Hirofumi MZ     if (*ppList == pHotKey)
2095d5cc578SKatayama Hirofumi MZ     {
2105d5cc578SKatayama Hirofumi MZ         *ppList = pHotKey->pNext;
2115d5cc578SKatayama Hirofumi MZ         ExFreePoolWithTag(pHotKey, USERTAG_IMEHOTKEY);
2125d5cc578SKatayama Hirofumi MZ         return;
2135d5cc578SKatayama Hirofumi MZ     }
2145d5cc578SKatayama Hirofumi MZ 
2155d5cc578SKatayama Hirofumi MZ     for (pNode = *ppList; pNode; pNode = pNode->pNext)
2165d5cc578SKatayama Hirofumi MZ     {
2175d5cc578SKatayama Hirofumi MZ         if (pNode->pNext == pHotKey)
2185d5cc578SKatayama Hirofumi MZ         {
2195d5cc578SKatayama Hirofumi MZ             pNode->pNext = pHotKey->pNext;
2205d5cc578SKatayama Hirofumi MZ             ExFreePoolWithTag(pHotKey, USERTAG_IMEHOTKEY);
2215d5cc578SKatayama Hirofumi MZ             return;
2225d5cc578SKatayama Hirofumi MZ         }
2235d5cc578SKatayama Hirofumi MZ     }
2245d5cc578SKatayama Hirofumi MZ }
2255d5cc578SKatayama Hirofumi MZ 
2265df5ef2bSKatayama Hirofumi MZ // Win: FindImeHotKeyByKey
227bbe5fd52SKatayama Hirofumi MZ PIMEHOTKEY
228bbe5fd52SKatayama Hirofumi MZ IntGetImeHotKeyByKey(PIMEHOTKEY pList, UINT uModKeys, UINT uLeftRight, UINT uVirtualKey)
229bbe5fd52SKatayama Hirofumi MZ {
230bbe5fd52SKatayama Hirofumi MZ     PIMEHOTKEY pNode, ret = NULL;
231bbe5fd52SKatayama Hirofumi MZ     PTHREADINFO pti = GetW32ThreadInfo();
232bbe5fd52SKatayama Hirofumi MZ     LANGID LangId;
233bbe5fd52SKatayama Hirofumi MZ     HKL hKL = IntGetActiveKeyboardLayout();
234bbe5fd52SKatayama Hirofumi MZ     BOOL fKorean = (PRIMARYLANGID(LOWORD(hKL)) == LANG_KOREAN);
235bbe5fd52SKatayama Hirofumi MZ     UINT nScore, nMaxScore = 0;
236bbe5fd52SKatayama Hirofumi MZ 
237bbe5fd52SKatayama Hirofumi MZ     for (pNode = pList; pNode; pNode = pNode->pNext)
238bbe5fd52SKatayama Hirofumi MZ     {
239bbe5fd52SKatayama Hirofumi MZ         if (pNode->uVirtualKey != uVirtualKey)
240bbe5fd52SKatayama Hirofumi MZ             continue;
241bbe5fd52SKatayama Hirofumi MZ 
242bbe5fd52SKatayama Hirofumi MZ         if ((pNode->uModifiers & MOD_IGNORE_ALL_MODIFIER))
243bbe5fd52SKatayama Hirofumi MZ         {
244bbe5fd52SKatayama Hirofumi MZ             ;
245bbe5fd52SKatayama Hirofumi MZ         }
246bbe5fd52SKatayama Hirofumi MZ         else if ((pNode->uModifiers & MOD_KEYS) != uModKeys)
247bbe5fd52SKatayama Hirofumi MZ         {
248bbe5fd52SKatayama Hirofumi MZ             continue;
249bbe5fd52SKatayama Hirofumi MZ         }
250bbe5fd52SKatayama Hirofumi MZ         else if ((pNode->uModifiers & uLeftRight) ||
251bbe5fd52SKatayama Hirofumi MZ                  (pNode->uModifiers & MOD_LEFT_RIGHT) == uLeftRight)
252bbe5fd52SKatayama Hirofumi MZ         {
253bbe5fd52SKatayama Hirofumi MZ             ;
254bbe5fd52SKatayama Hirofumi MZ         }
255bbe5fd52SKatayama Hirofumi MZ         else
256bbe5fd52SKatayama Hirofumi MZ         {
257bbe5fd52SKatayama Hirofumi MZ             continue;
258bbe5fd52SKatayama Hirofumi MZ         }
259bbe5fd52SKatayama Hirofumi MZ 
260bbe5fd52SKatayama Hirofumi MZ         LangId = IntGetImeHotKeyLangId(pNode->dwHotKeyId);
261bbe5fd52SKatayama Hirofumi MZ         nScore = IntGetImeHotKeyLanguageScore(hKL, LangId);
262bbe5fd52SKatayama Hirofumi MZ         if (nScore >= 3)
263bbe5fd52SKatayama Hirofumi MZ             return pNode;
264bbe5fd52SKatayama Hirofumi MZ 
265bbe5fd52SKatayama Hirofumi MZ         if (fKorean)
266bbe5fd52SKatayama Hirofumi MZ             continue;
267bbe5fd52SKatayama Hirofumi MZ 
268bbe5fd52SKatayama Hirofumi MZ         if (nScore == 0)
269bbe5fd52SKatayama Hirofumi MZ         {
270bbe5fd52SKatayama Hirofumi MZ             if (pNode->dwHotKeyId == IME_CHOTKEY_IME_NONIME_TOGGLE ||
271bbe5fd52SKatayama Hirofumi MZ                 pNode->dwHotKeyId == IME_THOTKEY_IME_NONIME_TOGGLE)
272bbe5fd52SKatayama Hirofumi MZ             {
273bbe5fd52SKatayama Hirofumi MZ                 if (LOWORD(pti->hklPrev) == LangId)
274bbe5fd52SKatayama Hirofumi MZ                     return pNode;
275bbe5fd52SKatayama Hirofumi MZ             }
276bbe5fd52SKatayama Hirofumi MZ         }
277bbe5fd52SKatayama Hirofumi MZ 
278bbe5fd52SKatayama Hirofumi MZ         if (nMaxScore < nScore)
279bbe5fd52SKatayama Hirofumi MZ         {
280bbe5fd52SKatayama Hirofumi MZ             nMaxScore = nScore;
281bbe5fd52SKatayama Hirofumi MZ             ret = pNode;
282bbe5fd52SKatayama Hirofumi MZ         }
283bbe5fd52SKatayama Hirofumi MZ     }
284bbe5fd52SKatayama Hirofumi MZ 
285bbe5fd52SKatayama Hirofumi MZ     return ret;
286bbe5fd52SKatayama Hirofumi MZ }
287bbe5fd52SKatayama Hirofumi MZ 
2882f7775c6SKatayama Hirofumi MZ // Win: CheckImeHotKey
289bbe5fd52SKatayama Hirofumi MZ PIMEHOTKEY IntCheckImeHotKey(PUSER_MESSAGE_QUEUE MessageQueue, UINT uVirtualKey, LPARAM lParam)
290bbe5fd52SKatayama Hirofumi MZ {
291bbe5fd52SKatayama Hirofumi MZ     PIMEHOTKEY pHotKey;
292bbe5fd52SKatayama Hirofumi MZ     UINT uModifiers;
293bbe5fd52SKatayama Hirofumi MZ     BOOL bKeyUp = (lParam & 0x80000000);
294bbe5fd52SKatayama Hirofumi MZ     const BYTE *KeyState = MessageQueue->afKeyState;
295bbe5fd52SKatayama Hirofumi MZ     static UINT s_uKeyUpVKey = 0;
296bbe5fd52SKatayama Hirofumi MZ 
297bbe5fd52SKatayama Hirofumi MZ     if (bKeyUp)
298bbe5fd52SKatayama Hirofumi MZ     {
299bbe5fd52SKatayama Hirofumi MZ         if (s_uKeyUpVKey != uVirtualKey)
300bbe5fd52SKatayama Hirofumi MZ         {
301bbe5fd52SKatayama Hirofumi MZ             s_uKeyUpVKey = 0;
302bbe5fd52SKatayama Hirofumi MZ             return NULL;
303bbe5fd52SKatayama Hirofumi MZ         }
304bbe5fd52SKatayama Hirofumi MZ 
305bbe5fd52SKatayama Hirofumi MZ         s_uKeyUpVKey = 0;
306bbe5fd52SKatayama Hirofumi MZ     }
307bbe5fd52SKatayama Hirofumi MZ 
308bbe5fd52SKatayama Hirofumi MZ     uModifiers = 0;
309bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_LSHIFT))   uModifiers |= (MOD_SHIFT | MOD_LEFT);
310bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_RSHIFT))   uModifiers |= (MOD_SHIFT | MOD_RIGHT);
311bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_LCONTROL)) uModifiers |= (MOD_CONTROL | MOD_LEFT);
312bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_RCONTROL)) uModifiers |= (MOD_CONTROL | MOD_RIGHT);
313bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_LMENU))    uModifiers |= (MOD_ALT | MOD_LEFT);
314bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_RMENU))    uModifiers |= (MOD_ALT | MOD_RIGHT);
315bbe5fd52SKatayama Hirofumi MZ 
316bbe5fd52SKatayama Hirofumi MZ     pHotKey = IntGetImeHotKeyByKey(gpImeHotKeyList,
317bbe5fd52SKatayama Hirofumi MZ                                    (uModifiers & MOD_KEYS),
318bbe5fd52SKatayama Hirofumi MZ                                    (uModifiers & MOD_LEFT_RIGHT),
319bbe5fd52SKatayama Hirofumi MZ                                    uVirtualKey);
320bbe5fd52SKatayama Hirofumi MZ     if (pHotKey)
321bbe5fd52SKatayama Hirofumi MZ     {
322bbe5fd52SKatayama Hirofumi MZ         if (bKeyUp)
323bbe5fd52SKatayama Hirofumi MZ         {
324bbe5fd52SKatayama Hirofumi MZ             if (pHotKey->uModifiers & MOD_ON_KEYUP)
325bbe5fd52SKatayama Hirofumi MZ                 return pHotKey;
326bbe5fd52SKatayama Hirofumi MZ         }
327bbe5fd52SKatayama Hirofumi MZ         else
328bbe5fd52SKatayama Hirofumi MZ         {
329bbe5fd52SKatayama Hirofumi MZ             if (pHotKey->uModifiers & MOD_ON_KEYUP)
330bbe5fd52SKatayama Hirofumi MZ                 s_uKeyUpVKey = uVirtualKey;
331bbe5fd52SKatayama Hirofumi MZ             else
332bbe5fd52SKatayama Hirofumi MZ                 return pHotKey;
333bbe5fd52SKatayama Hirofumi MZ         }
334bbe5fd52SKatayama Hirofumi MZ     }
335bbe5fd52SKatayama Hirofumi MZ 
336bbe5fd52SKatayama Hirofumi MZ     return NULL;
337bbe5fd52SKatayama Hirofumi MZ }
338bbe5fd52SKatayama Hirofumi MZ 
3392f7775c6SKatayama Hirofumi MZ // Win: FreeImeHotKeys
3405d5cc578SKatayama Hirofumi MZ VOID FASTCALL IntFreeImeHotKeys(VOID)
3415d5cc578SKatayama Hirofumi MZ {
3425d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode, pNext;
3435d5cc578SKatayama Hirofumi MZ     for (pNode = gpImeHotKeyList; pNode; pNode = pNext)
3445d5cc578SKatayama Hirofumi MZ     {
3455d5cc578SKatayama Hirofumi MZ         pNext = pNode->pNext;
3465d5cc578SKatayama Hirofumi MZ         ExFreePoolWithTag(pNode, USERTAG_IMEHOTKEY);
3475d5cc578SKatayama Hirofumi MZ     }
3485d5cc578SKatayama Hirofumi MZ     gpImeHotKeyList = NULL;
3495d5cc578SKatayama Hirofumi MZ }
3505d5cc578SKatayama Hirofumi MZ 
3512f7775c6SKatayama Hirofumi MZ // Win: SetImeHotKey
3525d5cc578SKatayama Hirofumi MZ static BOOL APIENTRY
3535d5cc578SKatayama Hirofumi MZ IntSetImeHotKey(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DWORD dwAction)
3545d5cc578SKatayama Hirofumi MZ {
3555d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
3565d5cc578SKatayama Hirofumi MZ     LANGID LangId;
3575d5cc578SKatayama Hirofumi MZ 
3585d5cc578SKatayama Hirofumi MZ     switch (dwAction)
3595d5cc578SKatayama Hirofumi MZ     {
3605d5cc578SKatayama Hirofumi MZ         case SETIMEHOTKEY_DELETE:
36139fe905eSKatayama Hirofumi MZ             pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId); /* Find hotkey by ID */
3625d5cc578SKatayama Hirofumi MZ             if (!pNode)
363b5c9d532SKatayama Hirofumi MZ             {
364b5c9d532SKatayama Hirofumi MZ                 ERR("dwHotKeyId: 0x%lX\n", dwHotKeyId);
3655d5cc578SKatayama Hirofumi MZ                 return FALSE;
366b5c9d532SKatayama Hirofumi MZ             }
3675d5cc578SKatayama Hirofumi MZ 
36839fe905eSKatayama Hirofumi MZ             IntDeleteImeHotKey(&gpImeHotKeyList, pNode); /* Delete it */
3695d5cc578SKatayama Hirofumi MZ             return TRUE;
3705d5cc578SKatayama Hirofumi MZ 
3715d5cc578SKatayama Hirofumi MZ         case SETIMEHOTKEY_ADD:
37239fe905eSKatayama Hirofumi MZ             if (LOWORD(uVirtualKey) == VK_PACKET) /* In case of VK_PACKET */
3735d5cc578SKatayama Hirofumi MZ                 return FALSE;
3745d5cc578SKatayama Hirofumi MZ 
3755d5cc578SKatayama Hirofumi MZ             LangId = IntGetImeHotKeyLangId(dwHotKeyId);
3765d5cc578SKatayama Hirofumi MZ             if (LangId == LANGID_KOREAN)
37739fe905eSKatayama Hirofumi MZ                 return FALSE; /* Korean can't add IME hotkeys */
3785d5cc578SKatayama Hirofumi MZ 
37939fe905eSKatayama Hirofumi MZ             /* Find hotkey by key and language */
3805d5cc578SKatayama Hirofumi MZ             pNode = IntGetImeHotKeyByKeyAndLang(gpImeHotKeyList,
3815d5cc578SKatayama Hirofumi MZ                                                 (uModifiers & MOD_KEYS),
3825d5cc578SKatayama Hirofumi MZ                                                 (uModifiers & MOD_LEFT_RIGHT),
3835d5cc578SKatayama Hirofumi MZ                                                 uVirtualKey, LangId);
38439fe905eSKatayama Hirofumi MZ             if (pNode == NULL) /* If not found */
38539fe905eSKatayama Hirofumi MZ                 pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId); /* Find by ID */
3865d5cc578SKatayama Hirofumi MZ 
38739fe905eSKatayama Hirofumi MZ             if (pNode) /* Already exists */
3885d5cc578SKatayama Hirofumi MZ             {
3895d5cc578SKatayama Hirofumi MZ                 pNode->uModifiers = uModifiers;
3905d5cc578SKatayama Hirofumi MZ                 pNode->uVirtualKey = uVirtualKey;
3915d5cc578SKatayama Hirofumi MZ                 pNode->hKL = hKL;
3925d5cc578SKatayama Hirofumi MZ                 return TRUE;
3935d5cc578SKatayama Hirofumi MZ             }
3945d5cc578SKatayama Hirofumi MZ 
39539fe905eSKatayama Hirofumi MZ             /* Allocate new hotkey */
3965d5cc578SKatayama Hirofumi MZ             pNode = ExAllocatePoolWithTag(PagedPool, sizeof(IMEHOTKEY), USERTAG_IMEHOTKEY);
3975d5cc578SKatayama Hirofumi MZ             if (!pNode)
3985d5cc578SKatayama Hirofumi MZ                 return FALSE;
3995d5cc578SKatayama Hirofumi MZ 
40039fe905eSKatayama Hirofumi MZ             /* Populate */
4015d5cc578SKatayama Hirofumi MZ             pNode->pNext = NULL;
4025d5cc578SKatayama Hirofumi MZ             pNode->dwHotKeyId = dwHotKeyId;
4035d5cc578SKatayama Hirofumi MZ             pNode->uModifiers = uModifiers;
4045d5cc578SKatayama Hirofumi MZ             pNode->uVirtualKey = uVirtualKey;
4055d5cc578SKatayama Hirofumi MZ             pNode->hKL = hKL;
40639fe905eSKatayama Hirofumi MZ             IntAddImeHotKey(&gpImeHotKeyList, pNode); /* Add it */
4075d5cc578SKatayama Hirofumi MZ             return TRUE;
4085d5cc578SKatayama Hirofumi MZ 
409dff4579bSKatayama Hirofumi MZ         case SETIMEHOTKEY_INITIALIZE:
41039fe905eSKatayama Hirofumi MZ             IntFreeImeHotKeys(); /* Delete all the IME hotkeys */
4115d5cc578SKatayama Hirofumi MZ             return TRUE;
4125d5cc578SKatayama Hirofumi MZ 
4135d5cc578SKatayama Hirofumi MZ         default:
41439fe905eSKatayama Hirofumi MZ             ERR("0x%lX\n", dwAction);
4155d5cc578SKatayama Hirofumi MZ             return FALSE;
4165d5cc578SKatayama Hirofumi MZ     }
4175d5cc578SKatayama Hirofumi MZ }
4185d5cc578SKatayama Hirofumi MZ 
4195d5cc578SKatayama Hirofumi MZ BOOL NTAPI
4205d5cc578SKatayama Hirofumi MZ NtUserGetImeHotKey(DWORD dwHotKeyId, LPUINT lpuModifiers, LPUINT lpuVirtualKey, LPHKL lphKL)
4215d5cc578SKatayama Hirofumi MZ {
4225d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode = NULL;
4235d5cc578SKatayama Hirofumi MZ 
4245d5cc578SKatayama Hirofumi MZ     UserEnterExclusive();
4255d5cc578SKatayama Hirofumi MZ 
4265d5cc578SKatayama Hirofumi MZ     _SEH2_TRY
4275d5cc578SKatayama Hirofumi MZ     {
4285d5cc578SKatayama Hirofumi MZ         ProbeForWrite(lpuModifiers, sizeof(UINT), 1);
4295d5cc578SKatayama Hirofumi MZ         ProbeForWrite(lpuVirtualKey, sizeof(UINT), 1);
4305d5cc578SKatayama Hirofumi MZ         if (lphKL)
4315d5cc578SKatayama Hirofumi MZ             ProbeForWrite(lphKL, sizeof(HKL), 1);
4325d5cc578SKatayama Hirofumi MZ     }
4335d5cc578SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4345d5cc578SKatayama Hirofumi MZ     {
435b3013335SKatayama Hirofumi MZ         ERR("!!!\n");
436b3013335SKatayama Hirofumi MZ         _SEH2_YIELD(goto Quit);
4375d5cc578SKatayama Hirofumi MZ     }
4385d5cc578SKatayama Hirofumi MZ     _SEH2_END;
4395d5cc578SKatayama Hirofumi MZ 
4405d5cc578SKatayama Hirofumi MZ     pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
4415d5cc578SKatayama Hirofumi MZ     if (!pNode)
4425d5cc578SKatayama Hirofumi MZ         goto Quit;
4435d5cc578SKatayama Hirofumi MZ 
4445d5cc578SKatayama Hirofumi MZ     _SEH2_TRY
4455d5cc578SKatayama Hirofumi MZ     {
4465d5cc578SKatayama Hirofumi MZ         *lpuModifiers = pNode->uModifiers;
4475d5cc578SKatayama Hirofumi MZ         *lpuVirtualKey = pNode->uVirtualKey;
4485d5cc578SKatayama Hirofumi MZ         if (lphKL)
4495d5cc578SKatayama Hirofumi MZ             *lphKL = pNode->hKL;
4505d5cc578SKatayama Hirofumi MZ     }
4515d5cc578SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4525d5cc578SKatayama Hirofumi MZ     {
453b3013335SKatayama Hirofumi MZ         ERR("!!!\n");
4545d5cc578SKatayama Hirofumi MZ         pNode = NULL;
4555d5cc578SKatayama Hirofumi MZ     }
4565d5cc578SKatayama Hirofumi MZ     _SEH2_END;
4575d5cc578SKatayama Hirofumi MZ 
4585d5cc578SKatayama Hirofumi MZ Quit:
4595d5cc578SKatayama Hirofumi MZ     UserLeave();
4605d5cc578SKatayama Hirofumi MZ     return !!pNode;
4615d5cc578SKatayama Hirofumi MZ }
4625d5cc578SKatayama Hirofumi MZ 
4635d5cc578SKatayama Hirofumi MZ BOOL
4645d5cc578SKatayama Hirofumi MZ NTAPI
4655d5cc578SKatayama Hirofumi MZ NtUserSetImeHotKey(
4665d5cc578SKatayama Hirofumi MZ     DWORD  dwHotKeyId,
4675d5cc578SKatayama Hirofumi MZ     UINT   uModifiers,
4685d5cc578SKatayama Hirofumi MZ     UINT   uVirtualKey,
4695d5cc578SKatayama Hirofumi MZ     HKL    hKL,
4705d5cc578SKatayama Hirofumi MZ     DWORD  dwAction)
4715d5cc578SKatayama Hirofumi MZ {
4725d5cc578SKatayama Hirofumi MZ     BOOL ret;
4735d5cc578SKatayama Hirofumi MZ     UserEnterExclusive();
4745d5cc578SKatayama Hirofumi MZ     ret = IntSetImeHotKey(dwHotKeyId, uModifiers, uVirtualKey, hKL, dwAction);
4755d5cc578SKatayama Hirofumi MZ     UserLeave();
4765d5cc578SKatayama Hirofumi MZ     return ret;
4775d5cc578SKatayama Hirofumi MZ }
4785d5cc578SKatayama Hirofumi MZ 
479bbe5fd52SKatayama Hirofumi MZ DWORD
480bbe5fd52SKatayama Hirofumi MZ NTAPI
481bbe5fd52SKatayama Hirofumi MZ NtUserCheckImeHotKey(UINT uVirtualKey, LPARAM lParam)
482bbe5fd52SKatayama Hirofumi MZ {
483bbe5fd52SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
484bbe5fd52SKatayama Hirofumi MZ     DWORD ret = INVALID_HOTKEY;
485bbe5fd52SKatayama Hirofumi MZ 
486bbe5fd52SKatayama Hirofumi MZ     UserEnterExclusive();
487bbe5fd52SKatayama Hirofumi MZ 
488bbe5fd52SKatayama Hirofumi MZ     if (!gpqForeground || !IS_IMM_MODE())
489bbe5fd52SKatayama Hirofumi MZ         goto Quit;
490bbe5fd52SKatayama Hirofumi MZ 
491bbe5fd52SKatayama Hirofumi MZ     pNode = IntCheckImeHotKey(gpqForeground, uVirtualKey, lParam);
492bbe5fd52SKatayama Hirofumi MZ     if (pNode)
493bbe5fd52SKatayama Hirofumi MZ         ret = pNode->dwHotKeyId;
494bbe5fd52SKatayama Hirofumi MZ 
495bbe5fd52SKatayama Hirofumi MZ Quit:
496bbe5fd52SKatayama Hirofumi MZ     UserLeave();
497bbe5fd52SKatayama Hirofumi MZ     return ret;
498bbe5fd52SKatayama Hirofumi MZ }
499bbe5fd52SKatayama Hirofumi MZ 
5005df5ef2bSKatayama Hirofumi MZ // Win: GetTopLevelWindow
5010519ae0aSKatayama Hirofumi MZ PWND FASTCALL IntGetTopLevelWindow(PWND pwnd)
5020519ae0aSKatayama Hirofumi MZ {
5030519ae0aSKatayama Hirofumi MZ     if (!pwnd)
5040519ae0aSKatayama Hirofumi MZ         return NULL;
5050519ae0aSKatayama Hirofumi MZ 
5060519ae0aSKatayama Hirofumi MZ     while (pwnd->style & WS_CHILD)
5070519ae0aSKatayama Hirofumi MZ         pwnd = pwnd->spwndParent;
5080519ae0aSKatayama Hirofumi MZ 
5090519ae0aSKatayama Hirofumi MZ     return pwnd;
5100519ae0aSKatayama Hirofumi MZ }
5110519ae0aSKatayama Hirofumi MZ 
5122f7775c6SKatayama Hirofumi MZ // Win: AssociateInputContext
5131bc9dda5SKatayama Hirofumi MZ HIMC FASTCALL IntAssociateInputContext(PWND pWnd, PIMC pImc)
5141bc9dda5SKatayama Hirofumi MZ {
5151bc9dda5SKatayama Hirofumi MZ     HIMC hOldImc = pWnd->hImc;
5161bc9dda5SKatayama Hirofumi MZ     pWnd->hImc = (pImc ? UserHMGetHandle(pImc) : NULL);
5171bc9dda5SKatayama Hirofumi MZ     return hOldImc;
5181bc9dda5SKatayama Hirofumi MZ }
5191bc9dda5SKatayama Hirofumi MZ 
520470aa276SKatayama Hirofumi MZ DWORD
521e52ce89bSKatayama Hirofumi MZ NTAPI
522470aa276SKatayama Hirofumi MZ NtUserSetThreadLayoutHandles(HKL hNewKL, HKL hOldKL)
523470aa276SKatayama Hirofumi MZ {
524470aa276SKatayama Hirofumi MZ     PTHREADINFO pti;
525470aa276SKatayama Hirofumi MZ     PKL pOldKL, pNewKL;
526470aa276SKatayama Hirofumi MZ 
527470aa276SKatayama Hirofumi MZ     UserEnterExclusive();
528470aa276SKatayama Hirofumi MZ 
529470aa276SKatayama Hirofumi MZ     pti = GetW32ThreadInfo();
530470aa276SKatayama Hirofumi MZ     pOldKL = pti->KeyboardLayout;
531470aa276SKatayama Hirofumi MZ     if (pOldKL && pOldKL->hkl != hOldKL)
532470aa276SKatayama Hirofumi MZ         goto Quit;
533470aa276SKatayama Hirofumi MZ 
534470aa276SKatayama Hirofumi MZ     pNewKL = UserHklToKbl(hNewKL);
535470aa276SKatayama Hirofumi MZ     if (!pNewKL)
536470aa276SKatayama Hirofumi MZ         goto Quit;
537470aa276SKatayama Hirofumi MZ 
538470aa276SKatayama Hirofumi MZ     if (IS_IME_HKL(hNewKL) != IS_IME_HKL(hOldKL))
539470aa276SKatayama Hirofumi MZ         pti->hklPrev = hOldKL;
540470aa276SKatayama Hirofumi MZ 
5415df5ef2bSKatayama Hirofumi MZ     UserAssignmentLock((PVOID*)&pti->KeyboardLayout, pNewKL);
542f34b8460SKatayama Hirofumi MZ     pti->pClientInfo->hKL = pNewKL->hkl;
543470aa276SKatayama Hirofumi MZ 
544470aa276SKatayama Hirofumi MZ Quit:
545470aa276SKatayama Hirofumi MZ     UserLeave();
546470aa276SKatayama Hirofumi MZ     return 0;
547470aa276SKatayama Hirofumi MZ }
548470aa276SKatayama Hirofumi MZ 
5492f7775c6SKatayama Hirofumi MZ // Win: BuildHimcList
550ce6da820SKatayama Hirofumi MZ DWORD FASTCALL UserBuildHimcList(PTHREADINFO pti, DWORD dwCount, HIMC *phList)
551ce6da820SKatayama Hirofumi MZ {
552ce6da820SKatayama Hirofumi MZ     PIMC pIMC;
553ce6da820SKatayama Hirofumi MZ     DWORD dwRealCount = 0;
554ce6da820SKatayama Hirofumi MZ 
555ce6da820SKatayama Hirofumi MZ     if (pti)
556ce6da820SKatayama Hirofumi MZ     {
557ce6da820SKatayama Hirofumi MZ         for (pIMC = pti->spDefaultImc; pIMC; pIMC = pIMC->pImcNext)
558ce6da820SKatayama Hirofumi MZ         {
559ce6da820SKatayama Hirofumi MZ             if (dwRealCount < dwCount)
560ce6da820SKatayama Hirofumi MZ                 phList[dwRealCount] = UserHMGetHandle(pIMC);
561ce6da820SKatayama Hirofumi MZ 
562ce6da820SKatayama Hirofumi MZ             ++dwRealCount;
563ce6da820SKatayama Hirofumi MZ         }
564ce6da820SKatayama Hirofumi MZ     }
565ce6da820SKatayama Hirofumi MZ     else
566ce6da820SKatayama Hirofumi MZ     {
567a2c6af0dSKatayama Hirofumi MZ         for (pti = gptiCurrent->ppi->ptiList; pti; pti = pti->ptiSibling)
568ce6da820SKatayama Hirofumi MZ         {
569ce6da820SKatayama Hirofumi MZ             for (pIMC = pti->spDefaultImc; pIMC; pIMC = pIMC->pImcNext)
570ce6da820SKatayama Hirofumi MZ             {
571ce6da820SKatayama Hirofumi MZ                 if (dwRealCount < dwCount)
572ce6da820SKatayama Hirofumi MZ                     phList[dwRealCount] = UserHMGetHandle(pIMC);
573ce6da820SKatayama Hirofumi MZ 
574ce6da820SKatayama Hirofumi MZ                 ++dwRealCount;
575ce6da820SKatayama Hirofumi MZ             }
576ce6da820SKatayama Hirofumi MZ         }
577ce6da820SKatayama Hirofumi MZ     }
578ce6da820SKatayama Hirofumi MZ 
579ce6da820SKatayama Hirofumi MZ     return dwRealCount;
580ce6da820SKatayama Hirofumi MZ }
581ce6da820SKatayama Hirofumi MZ 
5825df5ef2bSKatayama Hirofumi MZ // Win: xxxImmProcessKey
583c2c66affSColin Finck UINT FASTCALL
584b5c9d532SKatayama Hirofumi MZ IntImmProcessKey(PUSER_MESSAGE_QUEUE MessageQueue, PWND pWnd, UINT uMsg,
585b5c9d532SKatayama Hirofumi MZ                  WPARAM wParam, LPARAM lParam)
586c2c66affSColin Finck {
587b5c9d532SKatayama Hirofumi MZ     UINT uVirtualKey, ret = 0;
588b5c9d532SKatayama Hirofumi MZ     DWORD dwHotKeyId;
589b5c9d532SKatayama Hirofumi MZ     PKL pKL;
590b5c9d532SKatayama Hirofumi MZ     PIMC pIMC = NULL;
591b5c9d532SKatayama Hirofumi MZ     PIMEHOTKEY pImeHotKey;
592b5c9d532SKatayama Hirofumi MZ     HKL hKL;
593b5c9d532SKatayama Hirofumi MZ     HWND hWnd;
594c2c66affSColin Finck 
595c2c66affSColin Finck     ASSERT_REFS_CO(pWnd);
596c2c66affSColin Finck 
597b5c9d532SKatayama Hirofumi MZ     switch (uMsg)
598c2c66affSColin Finck     {
599b5c9d532SKatayama Hirofumi MZ         case WM_KEYDOWN:
600b5c9d532SKatayama Hirofumi MZ         case WM_KEYUP:
601b5c9d532SKatayama Hirofumi MZ         case WM_SYSKEYDOWN:
602b5c9d532SKatayama Hirofumi MZ         case WM_SYSKEYUP:
603b5c9d532SKatayama Hirofumi MZ             break;
604b5c9d532SKatayama Hirofumi MZ 
605b5c9d532SKatayama Hirofumi MZ         default:
606c2c66affSColin Finck             return 0;
607c2c66affSColin Finck     }
608c2c66affSColin Finck 
609b5c9d532SKatayama Hirofumi MZ     hWnd = UserHMGetHandle(pWnd);
610b5c9d532SKatayama Hirofumi MZ     pKL = pWnd->head.pti->KeyboardLayout;
611b5c9d532SKatayama Hirofumi MZ     if (!pKL)
612b5c9d532SKatayama Hirofumi MZ         return 0;
613b5c9d532SKatayama Hirofumi MZ 
614b5c9d532SKatayama Hirofumi MZ     uVirtualKey = LOBYTE(wParam);
615b5c9d532SKatayama Hirofumi MZ     pImeHotKey = IntCheckImeHotKey(MessageQueue, uVirtualKey, lParam);
616b5c9d532SKatayama Hirofumi MZ     if (pImeHotKey)
617b5c9d532SKatayama Hirofumi MZ     {
618b5c9d532SKatayama Hirofumi MZ         dwHotKeyId = pImeHotKey->dwHotKeyId;
619b5c9d532SKatayama Hirofumi MZ         hKL = pImeHotKey->hKL;
620b5c9d532SKatayama Hirofumi MZ     }
621b5c9d532SKatayama Hirofumi MZ     else
622b5c9d532SKatayama Hirofumi MZ     {
623b5c9d532SKatayama Hirofumi MZ         dwHotKeyId = INVALID_HOTKEY;
624b5c9d532SKatayama Hirofumi MZ         hKL = NULL;
625b5c9d532SKatayama Hirofumi MZ     }
626b5c9d532SKatayama Hirofumi MZ 
627b5c9d532SKatayama Hirofumi MZ     if (IME_HOTKEY_DSWITCH_FIRST <= dwHotKeyId && dwHotKeyId <= IME_HOTKEY_DSWITCH_LAST)
628b5c9d532SKatayama Hirofumi MZ     {
629b5c9d532SKatayama Hirofumi MZ         if (pKL->hkl != hKL)
630b5c9d532SKatayama Hirofumi MZ         {
631b5c9d532SKatayama Hirofumi MZ             UserPostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST,
632b5c9d532SKatayama Hirofumi MZ                             ((pKL->dwFontSigs & gSystemFS) ? INPUTLANGCHANGE_SYSCHARSET : 0),
633b5c9d532SKatayama Hirofumi MZ                             (LPARAM)hKL);
634b5c9d532SKatayama Hirofumi MZ         }
635b5c9d532SKatayama Hirofumi MZ 
636b5c9d532SKatayama Hirofumi MZ         if (IntGetImeCompatFlags(pWnd->head.pti) & 0x800000)
637b5c9d532SKatayama Hirofumi MZ             return 0;
638b5c9d532SKatayama Hirofumi MZ 
639b5c9d532SKatayama Hirofumi MZ         return IPHK_HOTKEY;
640b5c9d532SKatayama Hirofumi MZ     }
641b5c9d532SKatayama Hirofumi MZ 
642b5c9d532SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
643b5c9d532SKatayama Hirofumi MZ         return 0;
644b5c9d532SKatayama Hirofumi MZ 
645b5c9d532SKatayama Hirofumi MZ     if (dwHotKeyId == INVALID_HOTKEY)
646b5c9d532SKatayama Hirofumi MZ     {
647b5c9d532SKatayama Hirofumi MZ         if (!pKL->piiex)
648b5c9d532SKatayama Hirofumi MZ             return 0;
649b5c9d532SKatayama Hirofumi MZ 
650b5c9d532SKatayama Hirofumi MZ         if (pWnd->hImc)
651b5c9d532SKatayama Hirofumi MZ             pIMC = UserGetObject(gHandleTable, pWnd->hImc, TYPE_INPUTCONTEXT);
652b5c9d532SKatayama Hirofumi MZ         if (!pIMC)
653b5c9d532SKatayama Hirofumi MZ             return 0;
654b5c9d532SKatayama Hirofumi MZ 
655b5c9d532SKatayama Hirofumi MZ         if ((lParam & 0x80000000) &&
656b5c9d532SKatayama Hirofumi MZ             (pKL->piiex->ImeInfo.fdwProperty & IME_PROP_IGNORE_UPKEYS))
657b5c9d532SKatayama Hirofumi MZ         {
658b5c9d532SKatayama Hirofumi MZ             return 0;
659b5c9d532SKatayama Hirofumi MZ         }
660b5c9d532SKatayama Hirofumi MZ 
661b5c9d532SKatayama Hirofumi MZ         switch (uVirtualKey)
662b5c9d532SKatayama Hirofumi MZ         {
663b5c9d532SKatayama Hirofumi MZ             case VK_DBE_CODEINPUT:
664b5c9d532SKatayama Hirofumi MZ             case VK_DBE_ENTERCONFIGMODE:
665b5c9d532SKatayama Hirofumi MZ             case VK_DBE_ENTERWORDREGISTERMODE:
666b5c9d532SKatayama Hirofumi MZ             case VK_DBE_HIRAGANA:
667b5c9d532SKatayama Hirofumi MZ             case VK_DBE_KATAKANA:
668b5c9d532SKatayama Hirofumi MZ             case VK_DBE_NOCODEINPUT:
669b5c9d532SKatayama Hirofumi MZ             case VK_DBE_NOROMAN:
670b5c9d532SKatayama Hirofumi MZ             case VK_DBE_ROMAN:
671b5c9d532SKatayama Hirofumi MZ                 break;
672b5c9d532SKatayama Hirofumi MZ 
673b5c9d532SKatayama Hirofumi MZ             default:
674b5c9d532SKatayama Hirofumi MZ             {
675b5c9d532SKatayama Hirofumi MZ                 if (uMsg == WM_SYSKEYDOWN || uMsg == WM_SYSKEYUP)
676b5c9d532SKatayama Hirofumi MZ                 {
677b5c9d532SKatayama Hirofumi MZ                     if (uVirtualKey != VK_MENU && uVirtualKey != VK_F10)
678b5c9d532SKatayama Hirofumi MZ                         return 0;
679b5c9d532SKatayama Hirofumi MZ                 }
680b5c9d532SKatayama Hirofumi MZ 
681b5c9d532SKatayama Hirofumi MZ                 if (!(pKL->piiex->ImeInfo.fdwProperty & IME_PROP_NEED_ALTKEY))
682b5c9d532SKatayama Hirofumi MZ                 {
683b5c9d532SKatayama Hirofumi MZ                     if (uVirtualKey == VK_MENU || (lParam & 0x20000000))
684b5c9d532SKatayama Hirofumi MZ                         return 0;
685b5c9d532SKatayama Hirofumi MZ                 }
686b5c9d532SKatayama Hirofumi MZ                 break;
687b5c9d532SKatayama Hirofumi MZ             }
688b5c9d532SKatayama Hirofumi MZ         }
689b5c9d532SKatayama Hirofumi MZ     }
690b5c9d532SKatayama Hirofumi MZ 
691b5c9d532SKatayama Hirofumi MZ     if (LOBYTE(uVirtualKey) == VK_PACKET)
692b5c9d532SKatayama Hirofumi MZ         uVirtualKey = MAKELONG(wParam, GetW32ThreadInfo()->wchInjected);
693b5c9d532SKatayama Hirofumi MZ 
694b5c9d532SKatayama Hirofumi MZ     ret = co_IntImmProcessKey(hWnd, pKL->hkl, uVirtualKey, lParam, dwHotKeyId);
695b5c9d532SKatayama Hirofumi MZ 
696b5c9d532SKatayama Hirofumi MZ     if (IntGetImeCompatFlags(pWnd->head.pti) & 0x800000)
697b5c9d532SKatayama Hirofumi MZ         ret &= ~IPHK_HOTKEY;
698b5c9d532SKatayama Hirofumi MZ 
699b5c9d532SKatayama Hirofumi MZ     return ret;
700b5c9d532SKatayama Hirofumi MZ }
701b5c9d532SKatayama Hirofumi MZ 
702ce6da820SKatayama Hirofumi MZ NTSTATUS
703e52ce89bSKatayama Hirofumi MZ NTAPI
704ce6da820SKatayama Hirofumi MZ NtUserBuildHimcList(DWORD dwThreadId, DWORD dwCount, HIMC *phList, LPDWORD pdwCount)
705ce6da820SKatayama Hirofumi MZ {
706ce6da820SKatayama Hirofumi MZ     NTSTATUS ret = STATUS_UNSUCCESSFUL;
707ce6da820SKatayama Hirofumi MZ     DWORD dwRealCount;
708ce6da820SKatayama Hirofumi MZ     PTHREADINFO pti;
709ce6da820SKatayama Hirofumi MZ 
710ce6da820SKatayama Hirofumi MZ     UserEnterExclusive();
711ce6da820SKatayama Hirofumi MZ 
712ce6da820SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
713ce6da820SKatayama Hirofumi MZ     {
714b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
715ce6da820SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
716ce6da820SKatayama Hirofumi MZ         goto Quit;
717ce6da820SKatayama Hirofumi MZ     }
718ce6da820SKatayama Hirofumi MZ 
719ce6da820SKatayama Hirofumi MZ     if (dwThreadId == 0)
720ce6da820SKatayama Hirofumi MZ     {
721a2c6af0dSKatayama Hirofumi MZ         pti = gptiCurrent;
722ce6da820SKatayama Hirofumi MZ     }
723ce6da820SKatayama Hirofumi MZ     else if (dwThreadId == INVALID_THREAD_ID)
724ce6da820SKatayama Hirofumi MZ     {
725ce6da820SKatayama Hirofumi MZ         pti = NULL;
726ce6da820SKatayama Hirofumi MZ     }
727ce6da820SKatayama Hirofumi MZ     else
728ce6da820SKatayama Hirofumi MZ     {
729ce6da820SKatayama Hirofumi MZ         pti = IntTID2PTI(UlongToHandle(dwThreadId));
730ce6da820SKatayama Hirofumi MZ         if (!pti || !pti->rpdesk)
731ce6da820SKatayama Hirofumi MZ             goto Quit;
732ce6da820SKatayama Hirofumi MZ     }
733ce6da820SKatayama Hirofumi MZ 
734ce6da820SKatayama Hirofumi MZ     _SEH2_TRY
735ce6da820SKatayama Hirofumi MZ     {
736ce6da820SKatayama Hirofumi MZ         ProbeForWrite(phList, dwCount * sizeof(HIMC), 1);
737ce6da820SKatayama Hirofumi MZ         ProbeForWrite(pdwCount, sizeof(DWORD), 1);
738ce6da820SKatayama Hirofumi MZ         *pdwCount = dwRealCount = UserBuildHimcList(pti, dwCount, phList);
739ce6da820SKatayama Hirofumi MZ     }
740ce6da820SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
741ce6da820SKatayama Hirofumi MZ     {
742*ef20cc08SKatayama Hirofumi MZ         ERR("!!!\n");
743*ef20cc08SKatayama Hirofumi MZ         _SEH2_YIELD(goto Quit);
744ce6da820SKatayama Hirofumi MZ     }
745ce6da820SKatayama Hirofumi MZ     _SEH2_END;
746ce6da820SKatayama Hirofumi MZ 
747ce6da820SKatayama Hirofumi MZ     if (dwCount < dwRealCount)
748ce6da820SKatayama Hirofumi MZ         ret = STATUS_BUFFER_TOO_SMALL;
749ce6da820SKatayama Hirofumi MZ     else
750ce6da820SKatayama Hirofumi MZ         ret = STATUS_SUCCESS;
751ce6da820SKatayama Hirofumi MZ 
752ce6da820SKatayama Hirofumi MZ Quit:
753ce6da820SKatayama Hirofumi MZ     UserLeave();
754ce6da820SKatayama Hirofumi MZ     return ret;
755ce6da820SKatayama Hirofumi MZ }
756ce6da820SKatayama Hirofumi MZ 
7575df5ef2bSKatayama Hirofumi MZ // Win: SetConvMode
7589db44371SKatayama Hirofumi MZ static VOID FASTCALL UserSetImeConversionKeyState(PTHREADINFO pti, DWORD dwConversion)
7599db44371SKatayama Hirofumi MZ {
7609db44371SKatayama Hirofumi MZ     HKL hKL;
7619db44371SKatayama Hirofumi MZ     LANGID LangID;
7629db44371SKatayama Hirofumi MZ     LPBYTE KeyState;
7639db44371SKatayama Hirofumi MZ     BOOL bAlphaNumeric, bKatakana, bHiragana, bFullShape, bRoman, bCharCode;
7649db44371SKatayama Hirofumi MZ 
7659db44371SKatayama Hirofumi MZ     if (!pti->KeyboardLayout)
7669db44371SKatayama Hirofumi MZ         return;
7679db44371SKatayama Hirofumi MZ 
7689db44371SKatayama Hirofumi MZ     hKL = pti->KeyboardLayout->hkl;
7699db44371SKatayama Hirofumi MZ     LangID = LOWORD(hKL);
7709db44371SKatayama Hirofumi MZ     KeyState = pti->MessageQueue->afKeyState;
7719db44371SKatayama Hirofumi MZ 
7729db44371SKatayama Hirofumi MZ     switch (PRIMARYLANGID(LangID))
7739db44371SKatayama Hirofumi MZ     {
7749db44371SKatayama Hirofumi MZ         case LANG_JAPANESE:
7759db44371SKatayama Hirofumi MZ             bAlphaNumeric = !(dwConversion & IME_CMODE_NATIVE);
7769db44371SKatayama Hirofumi MZ             bKatakana = !bAlphaNumeric && (dwConversion & IME_CMODE_KATAKANA);
7779db44371SKatayama Hirofumi MZ             bHiragana = !bAlphaNumeric && !(dwConversion & IME_CMODE_KATAKANA);
7789db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_ALPHANUMERIC, bAlphaNumeric);
7799db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_ALPHANUMERIC, bAlphaNumeric);
7809db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_HIRAGANA, bHiragana);
7819db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_HIRAGANA, bHiragana);
7829db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_KATAKANA, bKatakana);
7839db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_KATAKANA, bKatakana);
7849db44371SKatayama Hirofumi MZ 
7859db44371SKatayama Hirofumi MZ             bFullShape = (dwConversion & IME_CMODE_FULLSHAPE);
7869db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_DBCSCHAR, bFullShape);
7879db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_DBCSCHAR, bFullShape);
7889db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_SBCSCHAR, !bFullShape);
7899db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_SBCSCHAR, !bFullShape);
7909db44371SKatayama Hirofumi MZ 
7919db44371SKatayama Hirofumi MZ             bRoman = (dwConversion & IME_CMODE_ROMAN);
7929db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_ROMAN, bRoman);
7939db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_ROMAN, bRoman);
7949db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_NOROMAN, !bRoman);
7959db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_NOROMAN, !bRoman);
7969db44371SKatayama Hirofumi MZ 
7979db44371SKatayama Hirofumi MZ             bCharCode = (dwConversion & IME_CMODE_CHARCODE);
7989db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_CODEINPUT, bCharCode);
7999db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_CODEINPUT, bCharCode);
8009db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_NOCODEINPUT, !bCharCode);
8019db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_NOCODEINPUT, !bCharCode);
8029db44371SKatayama Hirofumi MZ             break;
8039db44371SKatayama Hirofumi MZ 
8049db44371SKatayama Hirofumi MZ         case LANG_KOREAN:
8059db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_HANGUL, (dwConversion & IME_CMODE_NATIVE));
8069db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_JUNJA, (dwConversion & IME_CMODE_FULLSHAPE));
8079db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_HANJA, (dwConversion & IME_CMODE_HANJACONVERT));
8089db44371SKatayama Hirofumi MZ             break;
8099db44371SKatayama Hirofumi MZ 
8109db44371SKatayama Hirofumi MZ         default:
8119db44371SKatayama Hirofumi MZ             break;
8129db44371SKatayama Hirofumi MZ     }
8139db44371SKatayama Hirofumi MZ }
8149db44371SKatayama Hirofumi MZ 
815c2c66affSColin Finck DWORD
816e52ce89bSKatayama Hirofumi MZ NTAPI
8179adc538cSKatayama Hirofumi MZ NtUserNotifyIMEStatus(HWND hwnd, BOOL fOpen, DWORD dwConversion)
818c2c66affSColin Finck {
8199db44371SKatayama Hirofumi MZ     PWND pwnd;
8209db44371SKatayama Hirofumi MZ     PTHREADINFO pti;
8219db44371SKatayama Hirofumi MZ     HKL hKL;
8229db44371SKatayama Hirofumi MZ 
8239db44371SKatayama Hirofumi MZ     UserEnterExclusive();
8249db44371SKatayama Hirofumi MZ 
825b5c9d532SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
826b5c9d532SKatayama Hirofumi MZ     {
827b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
828b5c9d532SKatayama Hirofumi MZ         goto Quit;
829b5c9d532SKatayama Hirofumi MZ     }
830b5c9d532SKatayama Hirofumi MZ 
8319db44371SKatayama Hirofumi MZ     pwnd = ValidateHwndNoErr(hwnd);
832b5c9d532SKatayama Hirofumi MZ     if (!pwnd)
8339db44371SKatayama Hirofumi MZ         goto Quit;
8349db44371SKatayama Hirofumi MZ 
8359db44371SKatayama Hirofumi MZ     pti = pwnd->head.pti;
8369db44371SKatayama Hirofumi MZ     if (!pti || !gptiForeground)
8379db44371SKatayama Hirofumi MZ         goto Quit;
8389db44371SKatayama Hirofumi MZ     if (pti != gptiForeground && pti->MessageQueue != gptiForeground->MessageQueue)
8399db44371SKatayama Hirofumi MZ         goto Quit;
8409db44371SKatayama Hirofumi MZ     if (ghIMC == pwnd->hImc && gfImeOpen == !!fOpen && gdwImeConversion == dwConversion)
8419db44371SKatayama Hirofumi MZ         goto Quit;
8429db44371SKatayama Hirofumi MZ 
8439db44371SKatayama Hirofumi MZ     ghIMC = pwnd->hImc;
8449db44371SKatayama Hirofumi MZ     if (ghIMC)
8459db44371SKatayama Hirofumi MZ     {
8469db44371SKatayama Hirofumi MZ         gfImeOpen = !!fOpen;
8479db44371SKatayama Hirofumi MZ         gdwImeConversion = dwConversion;
8489db44371SKatayama Hirofumi MZ         UserSetImeConversionKeyState(pti, (fOpen ? dwConversion : IME_CMODE_ALPHANUMERIC));
8499db44371SKatayama Hirofumi MZ     }
8509db44371SKatayama Hirofumi MZ 
8519db44371SKatayama Hirofumi MZ     if (ISITHOOKED(WH_SHELL))
8529db44371SKatayama Hirofumi MZ     {
8539db44371SKatayama Hirofumi MZ         hKL = (pti->KeyboardLayout ? pti->KeyboardLayout->hkl : NULL);
8549db44371SKatayama Hirofumi MZ         co_HOOK_CallHooks(WH_SHELL, HSHELL_LANGUAGE, (WPARAM)hwnd, (LPARAM)hKL);
8559db44371SKatayama Hirofumi MZ     }
8569db44371SKatayama Hirofumi MZ 
8579db44371SKatayama Hirofumi MZ     // TODO:
8589db44371SKatayama Hirofumi MZ 
8599db44371SKatayama Hirofumi MZ Quit:
8609db44371SKatayama Hirofumi MZ     UserLeave();
861c2c66affSColin Finck     return 0;
862c2c66affSColin Finck }
863c2c66affSColin Finck 
864fcc222c2SKatayama Hirofumi MZ BOOL
865e52ce89bSKatayama Hirofumi MZ NTAPI
866c2c66affSColin Finck NtUserDisableThreadIme(
867fcc222c2SKatayama Hirofumi MZ     DWORD dwThreadID)
868c2c66affSColin Finck {
869fcc222c2SKatayama Hirofumi MZ     PTHREADINFO pti, ptiCurrent;
870fcc222c2SKatayama Hirofumi MZ     PPROCESSINFO ppi;
871fcc222c2SKatayama Hirofumi MZ     BOOL ret = FALSE;
872fcc222c2SKatayama Hirofumi MZ 
873fcc222c2SKatayama Hirofumi MZ     UserEnterExclusive();
874fcc222c2SKatayama Hirofumi MZ 
875fcc222c2SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
876fcc222c2SKatayama Hirofumi MZ     {
877b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
878fcc222c2SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
879fcc222c2SKatayama Hirofumi MZ         goto Quit;
880fcc222c2SKatayama Hirofumi MZ     }
881fcc222c2SKatayama Hirofumi MZ 
882fcc222c2SKatayama Hirofumi MZ     ptiCurrent = GetW32ThreadInfo();
883fcc222c2SKatayama Hirofumi MZ 
884fcc222c2SKatayama Hirofumi MZ     if (dwThreadID == INVALID_THREAD_ID)
885fcc222c2SKatayama Hirofumi MZ     {
886fcc222c2SKatayama Hirofumi MZ         ppi = ptiCurrent->ppi;
887fcc222c2SKatayama Hirofumi MZ         ppi->W32PF_flags |= W32PF_DISABLEIME;
888fcc222c2SKatayama Hirofumi MZ 
889fcc222c2SKatayama Hirofumi MZ Retry:
890fcc222c2SKatayama Hirofumi MZ         for (pti = ppi->ptiList; pti; pti = pti->ptiSibling)
891fcc222c2SKatayama Hirofumi MZ         {
892fcc222c2SKatayama Hirofumi MZ             pti->TIF_flags |= TIF_DISABLEIME;
893fcc222c2SKatayama Hirofumi MZ 
894fcc222c2SKatayama Hirofumi MZ             if (pti->spwndDefaultIme)
895fcc222c2SKatayama Hirofumi MZ             {
896fcc222c2SKatayama Hirofumi MZ                 co_UserDestroyWindow(pti->spwndDefaultIme);
897fcc222c2SKatayama Hirofumi MZ                 pti->spwndDefaultIme = NULL;
898fcc222c2SKatayama Hirofumi MZ                 goto Retry; /* The contents of ppi->ptiList may be changed. */
899fcc222c2SKatayama Hirofumi MZ             }
900fcc222c2SKatayama Hirofumi MZ         }
901fcc222c2SKatayama Hirofumi MZ     }
902fcc222c2SKatayama Hirofumi MZ     else
903fcc222c2SKatayama Hirofumi MZ     {
904fcc222c2SKatayama Hirofumi MZ         if (dwThreadID == 0)
905fcc222c2SKatayama Hirofumi MZ         {
906fcc222c2SKatayama Hirofumi MZ             pti = ptiCurrent;
907fcc222c2SKatayama Hirofumi MZ         }
908fcc222c2SKatayama Hirofumi MZ         else
909fcc222c2SKatayama Hirofumi MZ         {
910fcc222c2SKatayama Hirofumi MZ             pti = IntTID2PTI(UlongToHandle(dwThreadID));
911fcc222c2SKatayama Hirofumi MZ 
912fcc222c2SKatayama Hirofumi MZ             /* The thread needs to reside in the current process. */
913fcc222c2SKatayama Hirofumi MZ             if (!pti || pti->ppi != ptiCurrent->ppi)
914fcc222c2SKatayama Hirofumi MZ                 goto Quit;
915fcc222c2SKatayama Hirofumi MZ         }
916fcc222c2SKatayama Hirofumi MZ 
917fcc222c2SKatayama Hirofumi MZ         pti->TIF_flags |= TIF_DISABLEIME;
918fcc222c2SKatayama Hirofumi MZ 
919fcc222c2SKatayama Hirofumi MZ         if (pti->spwndDefaultIme)
920fcc222c2SKatayama Hirofumi MZ         {
921fcc222c2SKatayama Hirofumi MZ             co_UserDestroyWindow(pti->spwndDefaultIme);
922fcc222c2SKatayama Hirofumi MZ             pti->spwndDefaultIme = NULL;
923fcc222c2SKatayama Hirofumi MZ         }
924fcc222c2SKatayama Hirofumi MZ     }
925fcc222c2SKatayama Hirofumi MZ 
926fcc222c2SKatayama Hirofumi MZ     ret = TRUE;
927fcc222c2SKatayama Hirofumi MZ 
928fcc222c2SKatayama Hirofumi MZ Quit:
929fcc222c2SKatayama Hirofumi MZ     UserLeave();
930fcc222c2SKatayama Hirofumi MZ     return ret;
931c2c66affSColin Finck }
932c2c66affSColin Finck 
933c2c66affSColin Finck DWORD
934e52ce89bSKatayama Hirofumi MZ NTAPI
935f4bc74edSKatayama Hirofumi MZ NtUserGetAppImeLevel(HWND hWnd)
936c2c66affSColin Finck {
9379c8167e9SKatayama Hirofumi MZ     DWORD ret = 0;
9389c8167e9SKatayama Hirofumi MZ     PWND pWnd;
9399c8167e9SKatayama Hirofumi MZ     PTHREADINFO pti;
9409c8167e9SKatayama Hirofumi MZ 
9419c8167e9SKatayama Hirofumi MZ     UserEnterShared();
9429c8167e9SKatayama Hirofumi MZ 
9439c8167e9SKatayama Hirofumi MZ     pWnd = ValidateHwndNoErr(hWnd);
9449c8167e9SKatayama Hirofumi MZ     if (!pWnd)
9459c8167e9SKatayama Hirofumi MZ         goto Quit;
9469c8167e9SKatayama Hirofumi MZ 
9479c8167e9SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
9489c8167e9SKatayama Hirofumi MZ     {
949b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
9509c8167e9SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
9519c8167e9SKatayama Hirofumi MZ         goto Quit;
9529c8167e9SKatayama Hirofumi MZ     }
9539c8167e9SKatayama Hirofumi MZ 
9549c8167e9SKatayama Hirofumi MZ     pti = PsGetCurrentThreadWin32Thread();
9559c8167e9SKatayama Hirofumi MZ     if (pWnd->head.pti->ppi == pti->ppi)
9569c8167e9SKatayama Hirofumi MZ         ret = (DWORD)(ULONG_PTR)UserGetProp(pWnd, AtomImeLevel, TRUE);
9579c8167e9SKatayama Hirofumi MZ 
9589c8167e9SKatayama Hirofumi MZ Quit:
9599c8167e9SKatayama Hirofumi MZ     UserLeave();
9609c8167e9SKatayama Hirofumi MZ     return ret;
961c2c66affSColin Finck }
962c2c66affSColin Finck 
9632f7775c6SKatayama Hirofumi MZ // Win: GetImeInfoEx
9649e7c2ba4SKatayama Hirofumi MZ BOOL FASTCALL
9659e7c2ba4SKatayama Hirofumi MZ UserGetImeInfoEx(
9669e7c2ba4SKatayama Hirofumi MZ     _Inout_ PWINSTATION_OBJECT pWinSta,
9679e7c2ba4SKatayama Hirofumi MZ     _Inout_ PIMEINFOEX pInfoEx,
9689e7c2ba4SKatayama Hirofumi MZ     _In_ IMEINFOEXCLASS SearchType)
96936740ca9SKatayama Hirofumi MZ {
97036740ca9SKatayama Hirofumi MZ     PKL pkl, pklHead;
97136740ca9SKatayama Hirofumi MZ 
9729e7c2ba4SKatayama Hirofumi MZ     if (!pWinSta || !gspklBaseLayout)
97336740ca9SKatayama Hirofumi MZ         return FALSE;
97436740ca9SKatayama Hirofumi MZ 
97536740ca9SKatayama Hirofumi MZ     pkl = pklHead = gspklBaseLayout;
97636740ca9SKatayama Hirofumi MZ 
97736740ca9SKatayama Hirofumi MZ     /* Find the matching entry from the list and get info */
97836740ca9SKatayama Hirofumi MZ     if (SearchType == ImeInfoExKeyboardLayout)
97936740ca9SKatayama Hirofumi MZ     {
98036740ca9SKatayama Hirofumi MZ         do
98136740ca9SKatayama Hirofumi MZ         {
98228959a2dSKatayama Hirofumi MZ             if (pInfoEx->hkl == pkl->hkl)
98336740ca9SKatayama Hirofumi MZ             {
98436740ca9SKatayama Hirofumi MZ                 if (!pkl->piiex)
9859e7c2ba4SKatayama Hirofumi MZ                 {
9869e7c2ba4SKatayama Hirofumi MZ                     ERR("!pkl->piiex at %p\n", pkl->hkl);
98736740ca9SKatayama Hirofumi MZ                     break;
9889e7c2ba4SKatayama Hirofumi MZ                 }
98936740ca9SKatayama Hirofumi MZ 
99028959a2dSKatayama Hirofumi MZ                 *pInfoEx = *pkl->piiex;
99128959a2dSKatayama Hirofumi MZ                 return TRUE;
99236740ca9SKatayama Hirofumi MZ             }
99336740ca9SKatayama Hirofumi MZ 
99436740ca9SKatayama Hirofumi MZ             pkl = pkl->pklNext;
99536740ca9SKatayama Hirofumi MZ         } while (pkl != pklHead);
99636740ca9SKatayama Hirofumi MZ     }
99736740ca9SKatayama Hirofumi MZ     else if (SearchType == ImeInfoExImeFileName)
99836740ca9SKatayama Hirofumi MZ     {
99936740ca9SKatayama Hirofumi MZ         do
100036740ca9SKatayama Hirofumi MZ         {
1001c7ba53e3SKatayama Hirofumi MZ             if (pkl->piiex &&
1002c7ba53e3SKatayama Hirofumi MZ                 _wcsnicmp(pkl->piiex->wszImeFile, pInfoEx->wszImeFile,
100328959a2dSKatayama Hirofumi MZ                           RTL_NUMBER_OF(pkl->piiex->wszImeFile)) == 0)
100436740ca9SKatayama Hirofumi MZ             {
100528959a2dSKatayama Hirofumi MZ                 *pInfoEx = *pkl->piiex;
100628959a2dSKatayama Hirofumi MZ                 return TRUE;
100736740ca9SKatayama Hirofumi MZ             }
100836740ca9SKatayama Hirofumi MZ 
100936740ca9SKatayama Hirofumi MZ             pkl = pkl->pklNext;
101036740ca9SKatayama Hirofumi MZ         } while (pkl != pklHead);
101136740ca9SKatayama Hirofumi MZ     }
101236740ca9SKatayama Hirofumi MZ     else
101336740ca9SKatayama Hirofumi MZ     {
1014c7ba53e3SKatayama Hirofumi MZ         ERR("SearchType: %d\n", SearchType);
101536740ca9SKatayama Hirofumi MZ     }
101636740ca9SKatayama Hirofumi MZ 
101728959a2dSKatayama Hirofumi MZ     return FALSE;
101836740ca9SKatayama Hirofumi MZ }
101936740ca9SKatayama Hirofumi MZ 
10204b038ec8SKatayama Hirofumi MZ BOOL
1021e52ce89bSKatayama Hirofumi MZ NTAPI
1022c2c66affSColin Finck NtUserGetImeInfoEx(
1023c2c66affSColin Finck     PIMEINFOEX pImeInfoEx,
10244b038ec8SKatayama Hirofumi MZ     IMEINFOEXCLASS SearchType)
1025c2c66affSColin Finck {
102636740ca9SKatayama Hirofumi MZ     IMEINFOEX ImeInfoEx;
102736740ca9SKatayama Hirofumi MZ     BOOL ret = FALSE;
10289e7c2ba4SKatayama Hirofumi MZ     PWINSTATION_OBJECT pWinSta;
102936740ca9SKatayama Hirofumi MZ 
103036740ca9SKatayama Hirofumi MZ     UserEnterShared();
103136740ca9SKatayama Hirofumi MZ 
103236740ca9SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1033b5c9d532SKatayama Hirofumi MZ     {
1034b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
103536740ca9SKatayama Hirofumi MZ         goto Quit;
1036b5c9d532SKatayama Hirofumi MZ     }
103736740ca9SKatayama Hirofumi MZ 
103836740ca9SKatayama Hirofumi MZ     _SEH2_TRY
103936740ca9SKatayama Hirofumi MZ     {
104036740ca9SKatayama Hirofumi MZ         ProbeForWrite(pImeInfoEx, sizeof(*pImeInfoEx), 1);
104136740ca9SKatayama Hirofumi MZ         ImeInfoEx = *pImeInfoEx;
104236740ca9SKatayama Hirofumi MZ     }
104336740ca9SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
104436740ca9SKatayama Hirofumi MZ     {
104536740ca9SKatayama Hirofumi MZ         goto Quit;
104636740ca9SKatayama Hirofumi MZ     }
104736740ca9SKatayama Hirofumi MZ     _SEH2_END;
104836740ca9SKatayama Hirofumi MZ 
10499e7c2ba4SKatayama Hirofumi MZ     pWinSta = IntGetProcessWindowStation(NULL);
10509e7c2ba4SKatayama Hirofumi MZ     ret = UserGetImeInfoEx(pWinSta, &ImeInfoEx, SearchType);
1051e52ce89bSKatayama Hirofumi MZ     if (!ret)
1052e52ce89bSKatayama Hirofumi MZ         goto Quit;
1053e52ce89bSKatayama Hirofumi MZ 
105436740ca9SKatayama Hirofumi MZ     _SEH2_TRY
105536740ca9SKatayama Hirofumi MZ     {
105636740ca9SKatayama Hirofumi MZ         *pImeInfoEx = ImeInfoEx;
105736740ca9SKatayama Hirofumi MZ     }
105836740ca9SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
105936740ca9SKatayama Hirofumi MZ     {
106036740ca9SKatayama Hirofumi MZ         ret = FALSE;
106136740ca9SKatayama Hirofumi MZ     }
106236740ca9SKatayama Hirofumi MZ     _SEH2_END;
1063c2c66affSColin Finck 
106436740ca9SKatayama Hirofumi MZ Quit:
106536740ca9SKatayama Hirofumi MZ     UserLeave();
106636740ca9SKatayama Hirofumi MZ     return ret;
106736740ca9SKatayama Hirofumi MZ }
1068c2c66affSColin Finck 
10699c8167e9SKatayama Hirofumi MZ BOOL
1070e52ce89bSKatayama Hirofumi MZ NTAPI
10719c8167e9SKatayama Hirofumi MZ NtUserSetAppImeLevel(HWND hWnd, DWORD dwLevel)
1072c2c66affSColin Finck {
10739c8167e9SKatayama Hirofumi MZ     BOOL ret = FALSE;
10749c8167e9SKatayama Hirofumi MZ     PWND pWnd;
10759c8167e9SKatayama Hirofumi MZ     PTHREADINFO pti;
10769c8167e9SKatayama Hirofumi MZ 
10779c8167e9SKatayama Hirofumi MZ     UserEnterExclusive();
10789c8167e9SKatayama Hirofumi MZ 
10799c8167e9SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
10809c8167e9SKatayama Hirofumi MZ     {
1081b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
10829c8167e9SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
10839c8167e9SKatayama Hirofumi MZ         goto Quit;
10849c8167e9SKatayama Hirofumi MZ     }
10859c8167e9SKatayama Hirofumi MZ 
1086b5c9d532SKatayama Hirofumi MZ     pWnd = ValidateHwndNoErr(hWnd);
1087b5c9d532SKatayama Hirofumi MZ     if (!pWnd)
1088b5c9d532SKatayama Hirofumi MZ         goto Quit;
1089b5c9d532SKatayama Hirofumi MZ 
10909c8167e9SKatayama Hirofumi MZ     pti = PsGetCurrentThreadWin32Thread();
10919c8167e9SKatayama Hirofumi MZ     if (pWnd->head.pti->ppi == pti->ppi)
10929c8167e9SKatayama Hirofumi MZ         ret = UserSetProp(pWnd, AtomImeLevel, (HANDLE)(ULONG_PTR)dwLevel, TRUE);
10939c8167e9SKatayama Hirofumi MZ 
10949c8167e9SKatayama Hirofumi MZ Quit:
10959c8167e9SKatayama Hirofumi MZ     UserLeave();
10969c8167e9SKatayama Hirofumi MZ     return ret;
1097c2c66affSColin Finck }
1098c2c66affSColin Finck 
10992f7775c6SKatayama Hirofumi MZ // Win: SetImeInfoEx
11009e7c2ba4SKatayama Hirofumi MZ BOOL FASTCALL
11019e7c2ba4SKatayama Hirofumi MZ UserSetImeInfoEx(
11029e7c2ba4SKatayama Hirofumi MZ     _Inout_ PWINSTATION_OBJECT pWinSta,
11039e7c2ba4SKatayama Hirofumi MZ     _Inout_ PIMEINFOEX pImeInfoEx)
1104c2c66affSColin Finck {
11051f446936SKatayama Hirofumi MZ     PKL pklHead, pkl;
11061f446936SKatayama Hirofumi MZ 
11079e7c2ba4SKatayama Hirofumi MZ     if (!pWinSta || !gspklBaseLayout)
11089e7c2ba4SKatayama Hirofumi MZ         return FALSE;
11099e7c2ba4SKatayama Hirofumi MZ 
11101f446936SKatayama Hirofumi MZ     pkl = pklHead = gspklBaseLayout;
11111f446936SKatayama Hirofumi MZ 
11121f446936SKatayama Hirofumi MZ     do
11131f446936SKatayama Hirofumi MZ     {
11141f446936SKatayama Hirofumi MZ         if (pkl->hkl != pImeInfoEx->hkl)
11151f446936SKatayama Hirofumi MZ         {
11161f446936SKatayama Hirofumi MZ             pkl = pkl->pklNext;
11171f446936SKatayama Hirofumi MZ             continue;
11181f446936SKatayama Hirofumi MZ         }
11191f446936SKatayama Hirofumi MZ 
11201f446936SKatayama Hirofumi MZ         if (!pkl->piiex)
11219e7c2ba4SKatayama Hirofumi MZ         {
11229e7c2ba4SKatayama Hirofumi MZ             ERR("!pkl->piiex at %p\n", pkl->hkl);
11231f446936SKatayama Hirofumi MZ             return FALSE;
11249e7c2ba4SKatayama Hirofumi MZ         }
11251f446936SKatayama Hirofumi MZ 
11261f446936SKatayama Hirofumi MZ         if (!pkl->piiex->fLoadFlag)
11271f446936SKatayama Hirofumi MZ             *pkl->piiex = *pImeInfoEx;
11281f446936SKatayama Hirofumi MZ 
11291f446936SKatayama Hirofumi MZ         return TRUE;
11301f446936SKatayama Hirofumi MZ     } while (pkl != pklHead);
11311f446936SKatayama Hirofumi MZ 
11321f446936SKatayama Hirofumi MZ     return FALSE;
11331f446936SKatayama Hirofumi MZ }
11341f446936SKatayama Hirofumi MZ 
11351f446936SKatayama Hirofumi MZ BOOL
1136e52ce89bSKatayama Hirofumi MZ NTAPI
11371f446936SKatayama Hirofumi MZ NtUserSetImeInfoEx(PIMEINFOEX pImeInfoEx)
11381f446936SKatayama Hirofumi MZ {
11391f446936SKatayama Hirofumi MZ     BOOL ret = FALSE;
11401f446936SKatayama Hirofumi MZ     IMEINFOEX ImeInfoEx;
11419e7c2ba4SKatayama Hirofumi MZ     PWINSTATION_OBJECT pWinSta;
11421f446936SKatayama Hirofumi MZ 
11431f446936SKatayama Hirofumi MZ     UserEnterExclusive();
11441f446936SKatayama Hirofumi MZ 
11451f446936SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1146b5c9d532SKatayama Hirofumi MZ     {
1147b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
11481f446936SKatayama Hirofumi MZ         goto Quit;
1149b5c9d532SKatayama Hirofumi MZ     }
11501f446936SKatayama Hirofumi MZ 
11511f446936SKatayama Hirofumi MZ     _SEH2_TRY
11521f446936SKatayama Hirofumi MZ     {
11531f446936SKatayama Hirofumi MZ         ProbeForRead(pImeInfoEx, sizeof(*pImeInfoEx), 1);
11541f446936SKatayama Hirofumi MZ         ImeInfoEx = *pImeInfoEx;
11551f446936SKatayama Hirofumi MZ     }
11561f446936SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
11571f446936SKatayama Hirofumi MZ     {
11581f446936SKatayama Hirofumi MZ         goto Quit;
11591f446936SKatayama Hirofumi MZ     }
11601f446936SKatayama Hirofumi MZ     _SEH2_END;
11611f446936SKatayama Hirofumi MZ 
11629e7c2ba4SKatayama Hirofumi MZ     pWinSta = IntGetProcessWindowStation(NULL);
11639e7c2ba4SKatayama Hirofumi MZ     ret = UserSetImeInfoEx(pWinSta, &ImeInfoEx);
11641f446936SKatayama Hirofumi MZ 
11651f446936SKatayama Hirofumi MZ Quit:
11661f446936SKatayama Hirofumi MZ     UserLeave();
11671f446936SKatayama Hirofumi MZ     return ret;
1168c2c66affSColin Finck }
1169c2c66affSColin Finck 
1170291a94cdSKatayama Hirofumi MZ // Choose the preferred owner of the IME window.
1171291a94cdSKatayama Hirofumi MZ // Win: ImeSetFutureOwner
1172291a94cdSKatayama Hirofumi MZ VOID FASTCALL IntImeSetFutureOwner(PWND pImeWnd, PWND pwndOwner)
1173291a94cdSKatayama Hirofumi MZ {
1174291a94cdSKatayama Hirofumi MZ     PWND pwndNode, pwndNextOwner, pwndParent, pwndSibling;
1175291a94cdSKatayama Hirofumi MZ     PTHREADINFO pti = pImeWnd->head.pti;
1176291a94cdSKatayama Hirofumi MZ 
1177291a94cdSKatayama Hirofumi MZ     if (!pwndOwner || (pwndOwner->style & WS_CHILD)) // invalid owner
1178291a94cdSKatayama Hirofumi MZ         return;
1179291a94cdSKatayama Hirofumi MZ 
1180291a94cdSKatayama Hirofumi MZ     // Get the top-level owner of the same thread
1181291a94cdSKatayama Hirofumi MZ     for (pwndNode = pwndOwner; ; pwndNode = pwndNextOwner)
1182291a94cdSKatayama Hirofumi MZ     {
1183291a94cdSKatayama Hirofumi MZ         pwndNextOwner = pwndNode->spwndOwner;
1184291a94cdSKatayama Hirofumi MZ         if (!pwndNextOwner || pwndNextOwner->head.pti != pti)
1185291a94cdSKatayama Hirofumi MZ             break;
1186291a94cdSKatayama Hirofumi MZ     }
1187291a94cdSKatayama Hirofumi MZ 
1188291a94cdSKatayama Hirofumi MZ     // Don't choose the IME-like windows and the bottom-most windows unless necessary.
1189291a94cdSKatayama Hirofumi MZ     if (IS_WND_IMELIKE(pwndNode) ||
1190291a94cdSKatayama Hirofumi MZ         ((pwndNode->state2 & WNDS2_BOTTOMMOST) && !(pwndOwner->state2 & WNDS2_BOTTOMMOST)))
1191291a94cdSKatayama Hirofumi MZ     {
1192291a94cdSKatayama Hirofumi MZ         pwndNode = pwndOwner;
1193291a94cdSKatayama Hirofumi MZ     }
1194291a94cdSKatayama Hirofumi MZ 
1195291a94cdSKatayama Hirofumi MZ     pwndParent = pwndNode->spwndParent;
1196291a94cdSKatayama Hirofumi MZ     if (!pwndParent || pwndOwner != pwndNode)
1197291a94cdSKatayama Hirofumi MZ     {
1198e56da485STimo Kreuzer         WndSetOwner(pImeWnd, pwndNode);
1199291a94cdSKatayama Hirofumi MZ         return;
1200291a94cdSKatayama Hirofumi MZ     }
1201291a94cdSKatayama Hirofumi MZ 
1202291a94cdSKatayama Hirofumi MZ     for (pwndSibling = pwndParent->spwndChild; pwndSibling; pwndSibling = pwndSibling->spwndNext)
1203291a94cdSKatayama Hirofumi MZ     {
1204291a94cdSKatayama Hirofumi MZ         if (pwndNode->head.pti != pwndSibling->head.pti)
1205291a94cdSKatayama Hirofumi MZ             continue;
1206291a94cdSKatayama Hirofumi MZ 
1207291a94cdSKatayama Hirofumi MZ         if (IS_WND_MENU(pwndSibling) || IS_WND_IMELIKE(pwndSibling))
1208291a94cdSKatayama Hirofumi MZ             continue;
1209291a94cdSKatayama Hirofumi MZ 
1210291a94cdSKatayama Hirofumi MZ         if (pwndSibling->state2 & WNDS2_INDESTROY)
1211291a94cdSKatayama Hirofumi MZ             continue;
1212291a94cdSKatayama Hirofumi MZ 
1213291a94cdSKatayama Hirofumi MZ         if (pwndNode == pwndSibling || (pwndSibling->style & WS_CHILD))
1214291a94cdSKatayama Hirofumi MZ             continue;
1215291a94cdSKatayama Hirofumi MZ 
1216291a94cdSKatayama Hirofumi MZ         if (pwndSibling->spwndOwner == NULL ||
1217291a94cdSKatayama Hirofumi MZ             pwndSibling->head.pti != pwndSibling->spwndOwner->head.pti)
1218291a94cdSKatayama Hirofumi MZ         {
1219291a94cdSKatayama Hirofumi MZ             pwndNode = pwndSibling;
1220291a94cdSKatayama Hirofumi MZ             break;
1221291a94cdSKatayama Hirofumi MZ         }
1222291a94cdSKatayama Hirofumi MZ     }
1223291a94cdSKatayama Hirofumi MZ 
1224e56da485STimo Kreuzer     WndSetOwner(pImeWnd, pwndNode);
1225291a94cdSKatayama Hirofumi MZ }
1226291a94cdSKatayama Hirofumi MZ 
1227291a94cdSKatayama Hirofumi MZ // Get the last non-IME-like top-most window on the desktop.
1228291a94cdSKatayama Hirofumi MZ // Win: GetLastTopMostWindowNoIME
1229291a94cdSKatayama Hirofumi MZ PWND FASTCALL IntGetLastTopMostWindowNoIME(PWND pImeWnd)
1230291a94cdSKatayama Hirofumi MZ {
1231291a94cdSKatayama Hirofumi MZ     PWND pwndNode, pwndOwner, pwndLastTopMost = NULL;
1232291a94cdSKatayama Hirofumi MZ     BOOL bFound;
1233291a94cdSKatayama Hirofumi MZ 
1234291a94cdSKatayama Hirofumi MZ     pwndNode = UserGetDesktopWindow();
1235291a94cdSKatayama Hirofumi MZ     if (!pwndNode || pwndNode->spwndChild == NULL)
1236291a94cdSKatayama Hirofumi MZ         return NULL;
1237291a94cdSKatayama Hirofumi MZ 
1238291a94cdSKatayama Hirofumi MZ     for (pwndNode = pwndNode->spwndChild;
1239291a94cdSKatayama Hirofumi MZ          pwndNode && (pwndNode->ExStyle & WS_EX_TOPMOST);
1240291a94cdSKatayama Hirofumi MZ          pwndNode = pwndNode->spwndNext)
1241291a94cdSKatayama Hirofumi MZ     {
1242291a94cdSKatayama Hirofumi MZ         bFound = FALSE;
1243291a94cdSKatayama Hirofumi MZ 
1244291a94cdSKatayama Hirofumi MZ         if (IS_WND_IMELIKE(pwndNode)) // An IME-like window
1245291a94cdSKatayama Hirofumi MZ         {
1246291a94cdSKatayama Hirofumi MZ             // Search the IME window from owners
1247291a94cdSKatayama Hirofumi MZ             for (pwndOwner = pwndNode; pwndOwner; pwndOwner = pwndOwner->spwndOwner)
1248291a94cdSKatayama Hirofumi MZ             {
1249291a94cdSKatayama Hirofumi MZ                 if (pImeWnd == pwndOwner)
1250291a94cdSKatayama Hirofumi MZ                 {
1251291a94cdSKatayama Hirofumi MZ                     bFound = TRUE;
1252291a94cdSKatayama Hirofumi MZ                     break;
1253291a94cdSKatayama Hirofumi MZ                 }
1254291a94cdSKatayama Hirofumi MZ             }
1255291a94cdSKatayama Hirofumi MZ         }
1256291a94cdSKatayama Hirofumi MZ 
1257291a94cdSKatayama Hirofumi MZ         if (!bFound)
1258291a94cdSKatayama Hirofumi MZ             pwndLastTopMost = pwndNode;
1259291a94cdSKatayama Hirofumi MZ     }
1260291a94cdSKatayama Hirofumi MZ 
1261291a94cdSKatayama Hirofumi MZ     return pwndLastTopMost;
1262291a94cdSKatayama Hirofumi MZ }
1263291a94cdSKatayama Hirofumi MZ 
1264291a94cdSKatayama Hirofumi MZ // Adjust the ordering of the windows around the IME window.
1265291a94cdSKatayama Hirofumi MZ // Win: ImeSetTopMost
1266291a94cdSKatayama Hirofumi MZ VOID FASTCALL IntImeSetTopMost(PWND pImeWnd, BOOL bTopMost, PWND pwndInsertBefore)
1267291a94cdSKatayama Hirofumi MZ {
1268291a94cdSKatayama Hirofumi MZ     PWND pwndParent, pwndChild, pwndNode, pwndNext, pwndInsertAfter = NULL;
1269291a94cdSKatayama Hirofumi MZ     PWND pwndInsertAfterSave;
1270291a94cdSKatayama Hirofumi MZ 
1271291a94cdSKatayama Hirofumi MZ     pwndParent = pImeWnd->spwndParent;
1272291a94cdSKatayama Hirofumi MZ     if (!pwndParent)
1273291a94cdSKatayama Hirofumi MZ         return;
1274291a94cdSKatayama Hirofumi MZ 
1275291a94cdSKatayama Hirofumi MZ     pwndChild = pwndParent->spwndChild;
1276291a94cdSKatayama Hirofumi MZ 
1277291a94cdSKatayama Hirofumi MZ     if (!bTopMost)
1278291a94cdSKatayama Hirofumi MZ     {
1279291a94cdSKatayama Hirofumi MZ         // Calculate pwndInsertAfter
1280291a94cdSKatayama Hirofumi MZ         pwndInsertAfter = IntGetLastTopMostWindowNoIME(pImeWnd);
1281291a94cdSKatayama Hirofumi MZ         if (pwndInsertBefore)
1282291a94cdSKatayama Hirofumi MZ         {
1283291a94cdSKatayama Hirofumi MZ             for (pwndNode = pwndInsertAfter; pwndNode; pwndNode = pwndNode->spwndNext)
1284291a94cdSKatayama Hirofumi MZ             {
1285291a94cdSKatayama Hirofumi MZ                 if (pwndNode->spwndNext == pwndInsertBefore)
1286291a94cdSKatayama Hirofumi MZ                     break;
1287291a94cdSKatayama Hirofumi MZ 
1288291a94cdSKatayama Hirofumi MZ                 if (pwndNode == pImeWnd)
1289291a94cdSKatayama Hirofumi MZ                     return;
1290291a94cdSKatayama Hirofumi MZ             }
1291291a94cdSKatayama Hirofumi MZ 
1292291a94cdSKatayama Hirofumi MZ             if (!pwndNode)
1293291a94cdSKatayama Hirofumi MZ                 return;
1294291a94cdSKatayama Hirofumi MZ 
1295291a94cdSKatayama Hirofumi MZ             pwndInsertAfter = pwndNode;
1296291a94cdSKatayama Hirofumi MZ         }
1297291a94cdSKatayama Hirofumi MZ 
1298291a94cdSKatayama Hirofumi MZ         // Adjust pwndInsertAfter if the owner is bottom-most
1299291a94cdSKatayama Hirofumi MZ         if (pImeWnd->spwndOwner->state2 & WNDS2_BOTTOMMOST)
1300291a94cdSKatayama Hirofumi MZ         {
1301291a94cdSKatayama Hirofumi MZ             for (pwndNode = pwndInsertAfter; pwndNode; pwndNode = pwndNode->spwndNext)
1302291a94cdSKatayama Hirofumi MZ             {
1303291a94cdSKatayama Hirofumi MZ                 if (pwndNode == pImeWnd->spwndOwner)
1304291a94cdSKatayama Hirofumi MZ                     break;
1305291a94cdSKatayama Hirofumi MZ 
1306291a94cdSKatayama Hirofumi MZ                 if (!IS_WND_IMELIKE(pwndNode))
1307291a94cdSKatayama Hirofumi MZ                     pwndInsertAfter = pwndNode;
1308291a94cdSKatayama Hirofumi MZ             }
1309291a94cdSKatayama Hirofumi MZ         }
1310291a94cdSKatayama Hirofumi MZ     }
1311291a94cdSKatayama Hirofumi MZ 
1312291a94cdSKatayama Hirofumi MZ     pwndInsertAfterSave = pwndInsertAfter;
1313291a94cdSKatayama Hirofumi MZ 
1314291a94cdSKatayama Hirofumi MZ     while (pwndChild)
1315291a94cdSKatayama Hirofumi MZ     {
1316291a94cdSKatayama Hirofumi MZ         pwndNext = pwndChild->spwndNext;
1317291a94cdSKatayama Hirofumi MZ 
1318291a94cdSKatayama Hirofumi MZ         // If pwndChild is a good IME-like window, ...
1319291a94cdSKatayama Hirofumi MZ         if (IS_WND_IMELIKE(pwndChild) && pwndChild != pwndInsertAfter &&
1320291a94cdSKatayama Hirofumi MZ             pwndChild->head.pti == pImeWnd->head.pti)
1321291a94cdSKatayama Hirofumi MZ         {
1322291a94cdSKatayama Hirofumi MZ             // Find pImeWnd from the owners
1323291a94cdSKatayama Hirofumi MZ             for (pwndNode = pwndChild; pwndNode; pwndNode = pwndNode->spwndOwner)
1324291a94cdSKatayama Hirofumi MZ             {
1325291a94cdSKatayama Hirofumi MZ                 if (pwndNode != pImeWnd)
1326291a94cdSKatayama Hirofumi MZ                     continue;
1327291a94cdSKatayama Hirofumi MZ 
1328291a94cdSKatayama Hirofumi MZ                 // Adjust the ordering and the linking
1329291a94cdSKatayama Hirofumi MZ                 IntUnlinkWindow(pwndChild);
1330291a94cdSKatayama Hirofumi MZ 
1331291a94cdSKatayama Hirofumi MZ                 if (bTopMost)
1332291a94cdSKatayama Hirofumi MZ                     pwndChild->ExStyle |= WS_EX_TOPMOST;
1333291a94cdSKatayama Hirofumi MZ                 else
1334291a94cdSKatayama Hirofumi MZ                     pwndChild->ExStyle &= ~WS_EX_TOPMOST;
1335291a94cdSKatayama Hirofumi MZ 
1336291a94cdSKatayama Hirofumi MZ                 if (!pwndInsertAfter)
1337291a94cdSKatayama Hirofumi MZ                     IntLinkHwnd(pwndChild, HWND_TOP);
1338291a94cdSKatayama Hirofumi MZ                 else
1339291a94cdSKatayama Hirofumi MZ                     IntLinkHwnd(pwndChild, UserHMGetHandle(pwndInsertAfter));
1340291a94cdSKatayama Hirofumi MZ 
1341291a94cdSKatayama Hirofumi MZ                 // Update the preferred position
1342291a94cdSKatayama Hirofumi MZ                 pwndInsertAfter = pwndChild;
1343291a94cdSKatayama Hirofumi MZ                 break;
1344291a94cdSKatayama Hirofumi MZ             }
1345291a94cdSKatayama Hirofumi MZ         }
1346291a94cdSKatayama Hirofumi MZ 
1347291a94cdSKatayama Hirofumi MZ         // Get the next child, with ignoring pwndInsertAfterSave
1348291a94cdSKatayama Hirofumi MZ         pwndChild = pwndNext;
1349291a94cdSKatayama Hirofumi MZ         if (pwndChild && pwndChild == pwndInsertAfterSave && pwndInsertAfter)
1350291a94cdSKatayama Hirofumi MZ             pwndChild = pwndInsertAfter->spwndNext;
1351291a94cdSKatayama Hirofumi MZ     }
1352291a94cdSKatayama Hirofumi MZ }
1353291a94cdSKatayama Hirofumi MZ 
1354291a94cdSKatayama Hirofumi MZ // Make the IME window top-most if necessary.
1355291a94cdSKatayama Hirofumi MZ // Win: ImeCheckTopmost
1356291a94cdSKatayama Hirofumi MZ VOID FASTCALL IntImeCheckTopmost(PWND pImeWnd)
1357291a94cdSKatayama Hirofumi MZ {
1358291a94cdSKatayama Hirofumi MZ     BOOL bTopMost;
1359291a94cdSKatayama Hirofumi MZ     PWND pwndOwner = pImeWnd->spwndOwner, pwndInsertBefore = NULL;
1360291a94cdSKatayama Hirofumi MZ 
1361291a94cdSKatayama Hirofumi MZ     if (!pwndOwner)
1362291a94cdSKatayama Hirofumi MZ         return;
1363291a94cdSKatayama Hirofumi MZ 
1364291a94cdSKatayama Hirofumi MZ     if (pImeWnd->head.pti != gptiForeground)
1365291a94cdSKatayama Hirofumi MZ         pwndInsertBefore = pwndOwner;
1366291a94cdSKatayama Hirofumi MZ 
1367291a94cdSKatayama Hirofumi MZ     bTopMost = !!(pwndOwner->ExStyle & WS_EX_TOPMOST);
1368291a94cdSKatayama Hirofumi MZ     IntImeSetTopMost(pImeWnd, bTopMost, pwndInsertBefore);
1369291a94cdSKatayama Hirofumi MZ }
1370291a94cdSKatayama Hirofumi MZ 
1371e52ce89bSKatayama Hirofumi MZ BOOL NTAPI
13728c6dcdcfSKatayama Hirofumi MZ NtUserSetImeOwnerWindow(HWND hImeWnd, HWND hwndFocus)
1373c2c66affSColin Finck {
13740519ae0aSKatayama Hirofumi MZ     BOOL ret = FALSE;
1375291a94cdSKatayama Hirofumi MZ     PWND pImeWnd, pwndFocus, pwndTopLevel, pwndNode, pwndActive;
13760519ae0aSKatayama Hirofumi MZ     PTHREADINFO ptiIme;
13770519ae0aSKatayama Hirofumi MZ 
13780519ae0aSKatayama Hirofumi MZ     UserEnterExclusive();
13790519ae0aSKatayama Hirofumi MZ 
1380b5c9d532SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1381b5c9d532SKatayama Hirofumi MZ     {
1382b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
1383b5c9d532SKatayama Hirofumi MZ         goto Quit;
1384b5c9d532SKatayama Hirofumi MZ     }
1385b5c9d532SKatayama Hirofumi MZ 
13860519ae0aSKatayama Hirofumi MZ     pImeWnd = ValidateHwndNoErr(hImeWnd);
1387b5c9d532SKatayama Hirofumi MZ     if (!pImeWnd || pImeWnd->fnid != FNID_IME)
13880519ae0aSKatayama Hirofumi MZ         goto Quit;
13890519ae0aSKatayama Hirofumi MZ 
13900519ae0aSKatayama Hirofumi MZ     pwndFocus = ValidateHwndNoErr(hwndFocus);
13910519ae0aSKatayama Hirofumi MZ     if (pwndFocus)
13920519ae0aSKatayama Hirofumi MZ     {
13930519ae0aSKatayama Hirofumi MZ         if (IS_WND_IMELIKE(pwndFocus))
13940519ae0aSKatayama Hirofumi MZ             goto Quit;
13950519ae0aSKatayama Hirofumi MZ 
13960519ae0aSKatayama Hirofumi MZ         pwndTopLevel = IntGetTopLevelWindow(pwndFocus);
13970519ae0aSKatayama Hirofumi MZ 
1398291a94cdSKatayama Hirofumi MZ         for (pwndNode = pwndTopLevel; pwndNode; pwndNode = pwndNode->spwndOwner)
13990519ae0aSKatayama Hirofumi MZ         {
1400291a94cdSKatayama Hirofumi MZ             if (pwndNode->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME])
14010519ae0aSKatayama Hirofumi MZ             {
14020519ae0aSKatayama Hirofumi MZ                 pwndTopLevel = NULL;
14030519ae0aSKatayama Hirofumi MZ                 break;
14040519ae0aSKatayama Hirofumi MZ             }
14050519ae0aSKatayama Hirofumi MZ         }
14060519ae0aSKatayama Hirofumi MZ 
1407e56da485STimo Kreuzer         WndSetOwner(pImeWnd, pwndTopLevel);
1408291a94cdSKatayama Hirofumi MZ         IntImeCheckTopmost(pImeWnd);
14090519ae0aSKatayama Hirofumi MZ     }
14100519ae0aSKatayama Hirofumi MZ     else
14110519ae0aSKatayama Hirofumi MZ     {
14120519ae0aSKatayama Hirofumi MZ         ptiIme = pImeWnd->head.pti;
14130519ae0aSKatayama Hirofumi MZ         pwndActive = ptiIme->MessageQueue->spwndActive;
14140519ae0aSKatayama Hirofumi MZ 
14150519ae0aSKatayama Hirofumi MZ         if (!pwndActive || pwndActive != pImeWnd->spwndOwner)
14160519ae0aSKatayama Hirofumi MZ         {
14170519ae0aSKatayama Hirofumi MZ             if (pwndActive && ptiIme == pwndActive->head.pti && !IS_WND_IMELIKE(pwndActive))
14180519ae0aSKatayama Hirofumi MZ             {
1419e56da485STimo Kreuzer                 WndSetOwner(pImeWnd, pwndActive);
14200519ae0aSKatayama Hirofumi MZ             }
14210519ae0aSKatayama Hirofumi MZ             else
14220519ae0aSKatayama Hirofumi MZ             {
1423291a94cdSKatayama Hirofumi MZ                 IntImeSetFutureOwner(pImeWnd, pImeWnd->spwndOwner);
14240519ae0aSKatayama Hirofumi MZ             }
14250519ae0aSKatayama Hirofumi MZ 
1426291a94cdSKatayama Hirofumi MZ             IntImeCheckTopmost(pImeWnd);
14270519ae0aSKatayama Hirofumi MZ         }
14280519ae0aSKatayama Hirofumi MZ     }
14290519ae0aSKatayama Hirofumi MZ 
14300519ae0aSKatayama Hirofumi MZ     ret = TRUE;
14310519ae0aSKatayama Hirofumi MZ 
14320519ae0aSKatayama Hirofumi MZ Quit:
14330519ae0aSKatayama Hirofumi MZ     UserLeave();
14340519ae0aSKatayama Hirofumi MZ     return ret;
1435c2c66affSColin Finck }
1436c2c66affSColin Finck 
14373d78601fSKatayama Hirofumi MZ PVOID
14383d78601fSKatayama Hirofumi MZ AllocInputContextObject(PDESKTOP pDesk,
14393d78601fSKatayama Hirofumi MZ                         PTHREADINFO pti,
14403d78601fSKatayama Hirofumi MZ                         SIZE_T Size,
14413d78601fSKatayama Hirofumi MZ                         PVOID* HandleOwner)
14423d78601fSKatayama Hirofumi MZ {
14433d78601fSKatayama Hirofumi MZ     PTHRDESKHEAD ObjHead;
14443d78601fSKatayama Hirofumi MZ 
14453d78601fSKatayama Hirofumi MZ     ASSERT(Size > sizeof(*ObjHead));
14463d78601fSKatayama Hirofumi MZ     ASSERT(pti != NULL);
14473d78601fSKatayama Hirofumi MZ 
1448cfeb498eSKatayama Hirofumi MZ     if (!pDesk)
1449cfeb498eSKatayama Hirofumi MZ         pDesk = pti->rpdesk;
1450cfeb498eSKatayama Hirofumi MZ 
1451cfeb498eSKatayama Hirofumi MZ     ObjHead = DesktopHeapAlloc(pDesk, Size);
14523d78601fSKatayama Hirofumi MZ     if (!ObjHead)
14533d78601fSKatayama Hirofumi MZ         return NULL;
14543d78601fSKatayama Hirofumi MZ 
14553d78601fSKatayama Hirofumi MZ     RtlZeroMemory(ObjHead, Size);
14563d78601fSKatayama Hirofumi MZ 
14573d78601fSKatayama Hirofumi MZ     ObjHead->pSelf = ObjHead;
14583d78601fSKatayama Hirofumi MZ     ObjHead->rpdesk = pDesk;
14593d78601fSKatayama Hirofumi MZ     ObjHead->pti = pti;
14603d78601fSKatayama Hirofumi MZ     IntReferenceThreadInfo(pti);
14613d78601fSKatayama Hirofumi MZ     *HandleOwner = pti;
14623d78601fSKatayama Hirofumi MZ     pti->ppi->UserHandleCount++;
14633d78601fSKatayama Hirofumi MZ 
14643d78601fSKatayama Hirofumi MZ     return ObjHead;
14653d78601fSKatayama Hirofumi MZ }
14663d78601fSKatayama Hirofumi MZ 
14673d78601fSKatayama Hirofumi MZ VOID UserFreeInputContext(PVOID Object)
14683d78601fSKatayama Hirofumi MZ {
1469cfeb498eSKatayama Hirofumi MZ     PTHRDESKHEAD ObjHead = Object;
1470cfeb498eSKatayama Hirofumi MZ     PDESKTOP pDesk = ObjHead->rpdesk;
1471eb902e5bSKatayama Hirofumi MZ     PIMC pNode, pIMC = Object;
1472757bed81SKatayama Hirofumi MZ     PTHREADINFO pti;
14733d78601fSKatayama Hirofumi MZ 
1474757bed81SKatayama Hirofumi MZ     if (!pIMC)
1475757bed81SKatayama Hirofumi MZ         return;
14763d78601fSKatayama Hirofumi MZ 
1477eb902e5bSKatayama Hirofumi MZ     // Remove pIMC from the list except spDefaultImc
1478757bed81SKatayama Hirofumi MZ     pti = pIMC->head.pti;
1479eb902e5bSKatayama Hirofumi MZ     for (pNode = pti->spDefaultImc; pNode; pNode = pNode->pImcNext)
14802b2366abSKatayama Hirofumi MZ     {
1481eb902e5bSKatayama Hirofumi MZ         if (pNode->pImcNext == pIMC)
14822b2366abSKatayama Hirofumi MZ         {
1483eb902e5bSKatayama Hirofumi MZ             pNode->pImcNext = pIMC->pImcNext;
14842b2366abSKatayama Hirofumi MZ             break;
14852b2366abSKatayama Hirofumi MZ         }
14862b2366abSKatayama Hirofumi MZ     }
1487757bed81SKatayama Hirofumi MZ 
1488cfeb498eSKatayama Hirofumi MZ     DesktopHeapFree(pDesk, Object);
148945a4e53fSKatayama Hirofumi MZ 
149045a4e53fSKatayama Hirofumi MZ     pti->ppi->UserHandleCount--;
149145a4e53fSKatayama Hirofumi MZ     IntDereferenceThreadInfo(pti);
149245a4e53fSKatayama Hirofumi MZ }
149345a4e53fSKatayama Hirofumi MZ 
149445a4e53fSKatayama Hirofumi MZ BOOLEAN UserDestroyInputContext(PVOID Object)
149545a4e53fSKatayama Hirofumi MZ {
14962b2366abSKatayama Hirofumi MZ     PIMC pIMC = Object;
14974a748a3aSKatayama Hirofumi MZ     if (!pIMC)
149845a4e53fSKatayama Hirofumi MZ         return TRUE;
149945a4e53fSKatayama Hirofumi MZ 
15002ef605d4SKatayama Hirofumi MZ     UserMarkObjectDestroy(pIMC);
15014a748a3aSKatayama Hirofumi MZ     UserDeleteObject(UserHMGetHandle(pIMC), TYPE_INPUTCONTEXT);
15024a748a3aSKatayama Hirofumi MZ     return TRUE;
15033d78601fSKatayama Hirofumi MZ }
15043d78601fSKatayama Hirofumi MZ 
1505eb902e5bSKatayama Hirofumi MZ // Win: DestroyInputContext
15060f1e19a7SKatayama Hirofumi MZ BOOL IntDestroyInputContext(PIMC pIMC)
15073d78601fSKatayama Hirofumi MZ {
15080f1e19a7SKatayama Hirofumi MZ     HIMC hIMC = UserHMGetHandle(pIMC);
1509eb902e5bSKatayama Hirofumi MZ     PTHREADINFO pti = pIMC->head.pti;
1510eb902e5bSKatayama Hirofumi MZ     PWND pwndChild;
1511eb902e5bSKatayama Hirofumi MZ     PWINDOWLIST pwl;
15121bc9dda5SKatayama Hirofumi MZ     HWND *phwnd;
15131bc9dda5SKatayama Hirofumi MZ     PWND pWnd;
15143d78601fSKatayama Hirofumi MZ 
15150f1e19a7SKatayama Hirofumi MZ     if (pti != gptiCurrent)
15163d78601fSKatayama Hirofumi MZ     {
1517eb902e5bSKatayama Hirofumi MZ         EngSetLastError(ERROR_ACCESS_DENIED);
1518eb902e5bSKatayama Hirofumi MZ         return FALSE;
15193d78601fSKatayama Hirofumi MZ     }
15203d78601fSKatayama Hirofumi MZ 
1521eb902e5bSKatayama Hirofumi MZ     if (pIMC == pti->spDefaultImc)
1522eb902e5bSKatayama Hirofumi MZ     {
1523eb902e5bSKatayama Hirofumi MZ         EngSetLastError(ERROR_INVALID_PARAMETER);
1524eb902e5bSKatayama Hirofumi MZ         return FALSE;
1525eb902e5bSKatayama Hirofumi MZ     }
15263d78601fSKatayama Hirofumi MZ 
1527eb902e5bSKatayama Hirofumi MZ     pwndChild = pti->rpdesk->pDeskInfo->spwnd->spwndChild;
1528eb902e5bSKatayama Hirofumi MZ     pwl = IntBuildHwndList(pwndChild, IACE_LIST | IACE_CHILDREN, pti);
15291bc9dda5SKatayama Hirofumi MZ     if (pwl)
15301bc9dda5SKatayama Hirofumi MZ     {
15311bc9dda5SKatayama Hirofumi MZ         for (phwnd = pwl->ahwnd; *phwnd != HWND_TERMINATOR; ++phwnd)
15321bc9dda5SKatayama Hirofumi MZ         {
1533eb902e5bSKatayama Hirofumi MZ             pWnd = UserGetObjectNoErr(gHandleTable, *phwnd, TYPE_WINDOW);
1534eb902e5bSKatayama Hirofumi MZ             if (pWnd && pWnd->hImc == hIMC)
15351bc9dda5SKatayama Hirofumi MZ                 IntAssociateInputContext(pWnd, pti->spDefaultImc);
15361bc9dda5SKatayama Hirofumi MZ         }
15371bc9dda5SKatayama Hirofumi MZ 
15381bc9dda5SKatayama Hirofumi MZ         IntFreeHwndList(pwl);
15391bc9dda5SKatayama Hirofumi MZ     }
15401bc9dda5SKatayama Hirofumi MZ 
1541eb902e5bSKatayama Hirofumi MZ     UserDeleteObject(hIMC, TYPE_INPUTCONTEXT);
1542eb902e5bSKatayama Hirofumi MZ     return TRUE;
1543eb902e5bSKatayama Hirofumi MZ }
1544eb902e5bSKatayama Hirofumi MZ 
1545eb902e5bSKatayama Hirofumi MZ BOOL NTAPI NtUserDestroyInputContext(HIMC hIMC)
1546eb902e5bSKatayama Hirofumi MZ {
1547eb902e5bSKatayama Hirofumi MZ     BOOL ret = FALSE;
1548eb902e5bSKatayama Hirofumi MZ     PIMC pIMC;
1549eb902e5bSKatayama Hirofumi MZ 
1550eb902e5bSKatayama Hirofumi MZ     UserEnterExclusive();
1551eb902e5bSKatayama Hirofumi MZ 
1552eb902e5bSKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1553eb902e5bSKatayama Hirofumi MZ     {
1554eb902e5bSKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1555eb902e5bSKatayama Hirofumi MZ         goto Quit;
1556eb902e5bSKatayama Hirofumi MZ     }
1557eb902e5bSKatayama Hirofumi MZ 
1558eb902e5bSKatayama Hirofumi MZ     pIMC = UserGetObjectNoErr(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
1559eb902e5bSKatayama Hirofumi MZ     if (pIMC)
1560eb902e5bSKatayama Hirofumi MZ         ret = IntDestroyInputContext(pIMC);
15611bc9dda5SKatayama Hirofumi MZ 
15621bc9dda5SKatayama Hirofumi MZ Quit:
15633d78601fSKatayama Hirofumi MZ     UserLeave();
15643d78601fSKatayama Hirofumi MZ     return ret;
15653d78601fSKatayama Hirofumi MZ }
1566c2c66affSColin Finck 
15672f7775c6SKatayama Hirofumi MZ // Win: CreateInputContext
1568470aa276SKatayama Hirofumi MZ PIMC FASTCALL UserCreateInputContext(ULONG_PTR dwClientImcData)
1569470aa276SKatayama Hirofumi MZ {
1570470aa276SKatayama Hirofumi MZ     PIMC pIMC;
1571470aa276SKatayama Hirofumi MZ     PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
1572470aa276SKatayama Hirofumi MZ     PDESKTOP pdesk = pti->rpdesk;
1573470aa276SKatayama Hirofumi MZ 
1574470aa276SKatayama Hirofumi MZ     if (!IS_IMM_MODE() || (pti->TIF_flags & TIF_DISABLEIME)) // Disabled?
1575b5c9d532SKatayama Hirofumi MZ     {
1576b5c9d532SKatayama Hirofumi MZ         ERR("IME is disabled\n");
1577470aa276SKatayama Hirofumi MZ         return NULL;
1578b5c9d532SKatayama Hirofumi MZ     }
1579470aa276SKatayama Hirofumi MZ 
1580470aa276SKatayama Hirofumi MZ     if (!pdesk) // No desktop?
1581470aa276SKatayama Hirofumi MZ         return NULL;
1582470aa276SKatayama Hirofumi MZ 
1583470aa276SKatayama Hirofumi MZ     // pti->spDefaultImc should be already set if non-first time.
1584470aa276SKatayama Hirofumi MZ     if (dwClientImcData && !pti->spDefaultImc)
1585470aa276SKatayama Hirofumi MZ         return NULL;
1586470aa276SKatayama Hirofumi MZ 
1587470aa276SKatayama Hirofumi MZ     // Create an input context user object.
1588470aa276SKatayama Hirofumi MZ     pIMC = UserCreateObject(gHandleTable, pdesk, pti, NULL, TYPE_INPUTCONTEXT, sizeof(IMC));
1589470aa276SKatayama Hirofumi MZ     if (!pIMC)
1590470aa276SKatayama Hirofumi MZ         return NULL;
1591470aa276SKatayama Hirofumi MZ 
1592470aa276SKatayama Hirofumi MZ     // Release the extra reference (UserCreateObject added 2 references).
1593470aa276SKatayama Hirofumi MZ     UserDereferenceObject(pIMC);
15944a748a3aSKatayama Hirofumi MZ     ASSERT(pIMC->head.cLockObj == 1);
1595470aa276SKatayama Hirofumi MZ 
1596470aa276SKatayama Hirofumi MZ     if (dwClientImcData) // Non-first time.
1597470aa276SKatayama Hirofumi MZ     {
1598470aa276SKatayama Hirofumi MZ         // Insert pIMC to the second position (non-default) of the list.
1599470aa276SKatayama Hirofumi MZ         pIMC->pImcNext = pti->spDefaultImc->pImcNext;
1600470aa276SKatayama Hirofumi MZ         pti->spDefaultImc->pImcNext = pIMC;
1601470aa276SKatayama Hirofumi MZ     }
1602470aa276SKatayama Hirofumi MZ     else // First time. It's the default IMC.
1603470aa276SKatayama Hirofumi MZ     {
1604470aa276SKatayama Hirofumi MZ         // Add the first one (default) to the list.
16057e138837SKatayama Hirofumi MZ         UserAssignmentLock((PVOID*)&pti->spDefaultImc, pIMC);
1606470aa276SKatayama Hirofumi MZ         pIMC->pImcNext = NULL;
16074a748a3aSKatayama Hirofumi MZ         ASSERT(pIMC->head.cLockObj == 2); // UserAssignmentUnlock'ed at ExitThreadCallback
1608470aa276SKatayama Hirofumi MZ     }
1609470aa276SKatayama Hirofumi MZ 
1610470aa276SKatayama Hirofumi MZ     pIMC->dwClientImcData = dwClientImcData; // Set it.
1611470aa276SKatayama Hirofumi MZ     return pIMC;
1612470aa276SKatayama Hirofumi MZ }
1613470aa276SKatayama Hirofumi MZ 
1614470aa276SKatayama Hirofumi MZ HIMC
1615e52ce89bSKatayama Hirofumi MZ NTAPI
1616470aa276SKatayama Hirofumi MZ NtUserCreateInputContext(ULONG_PTR dwClientImcData)
1617470aa276SKatayama Hirofumi MZ {
1618470aa276SKatayama Hirofumi MZ     PIMC pIMC;
1619470aa276SKatayama Hirofumi MZ     HIMC ret = NULL;
1620470aa276SKatayama Hirofumi MZ 
1621470aa276SKatayama Hirofumi MZ     UserEnterExclusive();
1622470aa276SKatayama Hirofumi MZ 
1623470aa276SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1624b5c9d532SKatayama Hirofumi MZ     {
1625b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
162688c1d8c7SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
162788c1d8c7SKatayama Hirofumi MZ         goto Quit;
162888c1d8c7SKatayama Hirofumi MZ     }
162988c1d8c7SKatayama Hirofumi MZ 
163088c1d8c7SKatayama Hirofumi MZ     if (!dwClientImcData)
163188c1d8c7SKatayama Hirofumi MZ     {
163288c1d8c7SKatayama Hirofumi MZ         EngSetLastError(ERROR_INVALID_PARAMETER);
1633470aa276SKatayama Hirofumi MZ         goto Quit;
1634b5c9d532SKatayama Hirofumi MZ     }
1635470aa276SKatayama Hirofumi MZ 
1636470aa276SKatayama Hirofumi MZ     pIMC = UserCreateInputContext(dwClientImcData);
1637470aa276SKatayama Hirofumi MZ     if (pIMC)
1638470aa276SKatayama Hirofumi MZ         ret = UserHMGetHandle(pIMC);
1639470aa276SKatayama Hirofumi MZ 
1640470aa276SKatayama Hirofumi MZ Quit:
1641470aa276SKatayama Hirofumi MZ     UserLeave();
1642470aa276SKatayama Hirofumi MZ     return ret;
1643470aa276SKatayama Hirofumi MZ }
1644470aa276SKatayama Hirofumi MZ 
16452f7775c6SKatayama Hirofumi MZ // Win: AssociateInputContextEx
1646f2c3167dSKatayama Hirofumi MZ DWORD FASTCALL IntAssociateInputContextEx(PWND pWnd, PIMC pIMC, DWORD dwFlags)
1647f2c3167dSKatayama Hirofumi MZ {
1648f2c3167dSKatayama Hirofumi MZ     DWORD ret = 0;
1649f2c3167dSKatayama Hirofumi MZ     PWINDOWLIST pwl;
1650f2c3167dSKatayama Hirofumi MZ     BOOL bIgnoreNullImc = (dwFlags & IACE_IGNORENOCONTEXT);
1651f2c3167dSKatayama Hirofumi MZ     PTHREADINFO pti = pWnd->head.pti;
1652f2c3167dSKatayama Hirofumi MZ     PWND pwndTarget, pwndFocus = pti->MessageQueue->spwndFocus;
1653f2c3167dSKatayama Hirofumi MZ     HWND *phwnd;
1654f2c3167dSKatayama Hirofumi MZ     HIMC hIMC;
1655f2c3167dSKatayama Hirofumi MZ 
1656f2c3167dSKatayama Hirofumi MZ     if (dwFlags & IACE_DEFAULT)
1657f2c3167dSKatayama Hirofumi MZ     {
1658f2c3167dSKatayama Hirofumi MZ         pIMC = pti->spDefaultImc;
1659f2c3167dSKatayama Hirofumi MZ     }
1660f2c3167dSKatayama Hirofumi MZ     else
1661f2c3167dSKatayama Hirofumi MZ     {
1662f2c3167dSKatayama Hirofumi MZ         if (pIMC && pti != pIMC->head.pti)
1663f2c3167dSKatayama Hirofumi MZ             return 2;
1664f2c3167dSKatayama Hirofumi MZ     }
1665f2c3167dSKatayama Hirofumi MZ 
1666f2c3167dSKatayama Hirofumi MZ     if (pWnd->head.pti->ppi != GetW32ThreadInfo()->ppi ||
1667f2c3167dSKatayama Hirofumi MZ         (pIMC && pIMC->head.rpdesk != pWnd->head.rpdesk))
1668f2c3167dSKatayama Hirofumi MZ     {
1669f2c3167dSKatayama Hirofumi MZ         return 2;
1670f2c3167dSKatayama Hirofumi MZ     }
1671f2c3167dSKatayama Hirofumi MZ 
1672f2c3167dSKatayama Hirofumi MZ     if ((dwFlags & IACE_CHILDREN) && pWnd->spwndChild)
1673f2c3167dSKatayama Hirofumi MZ     {
1674f2c3167dSKatayama Hirofumi MZ         pwl = IntBuildHwndList(pWnd->spwndChild, IACE_CHILDREN | IACE_LIST, pti);
1675f2c3167dSKatayama Hirofumi MZ         if (pwl)
1676f2c3167dSKatayama Hirofumi MZ         {
1677f2c3167dSKatayama Hirofumi MZ             for (phwnd = pwl->ahwnd; *phwnd != HWND_TERMINATOR; ++phwnd)
1678f2c3167dSKatayama Hirofumi MZ             {
1679f2c3167dSKatayama Hirofumi MZ                 pwndTarget = ValidateHwndNoErr(*phwnd);
1680f2c3167dSKatayama Hirofumi MZ                 if (!pwndTarget)
1681f2c3167dSKatayama Hirofumi MZ                     continue;
1682f2c3167dSKatayama Hirofumi MZ 
1683f2c3167dSKatayama Hirofumi MZ                 hIMC = (pIMC ? UserHMGetHandle(pIMC) : NULL);
1684f2c3167dSKatayama Hirofumi MZ                 if (pwndTarget->hImc == hIMC || (bIgnoreNullImc && !pwndTarget->hImc))
1685f2c3167dSKatayama Hirofumi MZ                     continue;
1686f2c3167dSKatayama Hirofumi MZ 
1687f2c3167dSKatayama Hirofumi MZ                 IntAssociateInputContext(pwndTarget, pIMC);
1688f2c3167dSKatayama Hirofumi MZ                 if (pwndTarget == pwndFocus)
1689f2c3167dSKatayama Hirofumi MZ                     ret = 1;
1690f2c3167dSKatayama Hirofumi MZ             }
1691f2c3167dSKatayama Hirofumi MZ 
1692f2c3167dSKatayama Hirofumi MZ             IntFreeHwndList(pwl);
1693f2c3167dSKatayama Hirofumi MZ         }
1694f2c3167dSKatayama Hirofumi MZ     }
1695f2c3167dSKatayama Hirofumi MZ 
1696f2c3167dSKatayama Hirofumi MZ     if (!bIgnoreNullImc || pWnd->hImc)
1697f2c3167dSKatayama Hirofumi MZ     {
1698f2c3167dSKatayama Hirofumi MZ         hIMC = (pIMC ? UserHMGetHandle(pIMC) : NULL);
1699f2c3167dSKatayama Hirofumi MZ         if (pWnd->hImc != hIMC)
1700f2c3167dSKatayama Hirofumi MZ         {
1701f2c3167dSKatayama Hirofumi MZ             IntAssociateInputContext(pWnd, pIMC);
1702f2c3167dSKatayama Hirofumi MZ             if (pWnd == pwndFocus)
1703f2c3167dSKatayama Hirofumi MZ                 ret = 1;
1704f2c3167dSKatayama Hirofumi MZ         }
1705f2c3167dSKatayama Hirofumi MZ     }
1706f2c3167dSKatayama Hirofumi MZ 
1707f2c3167dSKatayama Hirofumi MZ     return ret;
1708f2c3167dSKatayama Hirofumi MZ }
1709f2c3167dSKatayama Hirofumi MZ 
1710470aa276SKatayama Hirofumi MZ DWORD
1711e52ce89bSKatayama Hirofumi MZ NTAPI
1712470aa276SKatayama Hirofumi MZ NtUserAssociateInputContext(HWND hWnd, HIMC hIMC, DWORD dwFlags)
1713470aa276SKatayama Hirofumi MZ {
1714f2c3167dSKatayama Hirofumi MZ     DWORD ret = 2;
1715f2c3167dSKatayama Hirofumi MZ     PWND pWnd;
1716f2c3167dSKatayama Hirofumi MZ     PIMC pIMC;
1717f2c3167dSKatayama Hirofumi MZ 
1718f2c3167dSKatayama Hirofumi MZ     UserEnterExclusive();
1719f2c3167dSKatayama Hirofumi MZ 
1720b5c9d532SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1721b5c9d532SKatayama Hirofumi MZ     {
1722b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
1723b5c9d532SKatayama Hirofumi MZ         goto Quit;
1724b5c9d532SKatayama Hirofumi MZ     }
1725b5c9d532SKatayama Hirofumi MZ 
1726f2c3167dSKatayama Hirofumi MZ     pWnd = ValidateHwndNoErr(hWnd);
1727b5c9d532SKatayama Hirofumi MZ     if (!pWnd)
1728f2c3167dSKatayama Hirofumi MZ         goto Quit;
1729f2c3167dSKatayama Hirofumi MZ 
1730f2c3167dSKatayama Hirofumi MZ     pIMC = (hIMC ? UserGetObjectNoErr(gHandleTable, hIMC, TYPE_INPUTCONTEXT) : NULL);
1731f2c3167dSKatayama Hirofumi MZ     ret = IntAssociateInputContextEx(pWnd, pIMC, dwFlags);
1732f2c3167dSKatayama Hirofumi MZ 
1733f2c3167dSKatayama Hirofumi MZ Quit:
1734f2c3167dSKatayama Hirofumi MZ     UserLeave();
1735f2c3167dSKatayama Hirofumi MZ     return ret;
1736470aa276SKatayama Hirofumi MZ }
1737470aa276SKatayama Hirofumi MZ 
17385df5ef2bSKatayama Hirofumi MZ // Win: UpdateInputContext
1739470aa276SKatayama Hirofumi MZ BOOL FASTCALL UserUpdateInputContext(PIMC pIMC, DWORD dwType, DWORD_PTR dwValue)
1740470aa276SKatayama Hirofumi MZ {
1741470aa276SKatayama Hirofumi MZ     PTHREADINFO pti = GetW32ThreadInfo();
1742470aa276SKatayama Hirofumi MZ     PTHREADINFO ptiIMC = pIMC->head.pti;
1743470aa276SKatayama Hirofumi MZ 
1744470aa276SKatayama Hirofumi MZ     if (pti->ppi != ptiIMC->ppi) // Different process?
1745470aa276SKatayama Hirofumi MZ         return FALSE;
1746470aa276SKatayama Hirofumi MZ 
1747470aa276SKatayama Hirofumi MZ     switch (dwType)
1748470aa276SKatayama Hirofumi MZ     {
1749470aa276SKatayama Hirofumi MZ         case UIC_CLIENTIMCDATA:
1750470aa276SKatayama Hirofumi MZ             if (pIMC->dwClientImcData)
1751470aa276SKatayama Hirofumi MZ                 return FALSE; // Already set
1752470aa276SKatayama Hirofumi MZ 
1753470aa276SKatayama Hirofumi MZ             pIMC->dwClientImcData = dwValue;
1754470aa276SKatayama Hirofumi MZ             break;
1755470aa276SKatayama Hirofumi MZ 
1756470aa276SKatayama Hirofumi MZ         case UIC_IMEWINDOW:
1757470aa276SKatayama Hirofumi MZ             if (!ValidateHwndNoErr((HWND)dwValue))
1758470aa276SKatayama Hirofumi MZ                 return FALSE; // Invalid HWND
1759470aa276SKatayama Hirofumi MZ 
1760470aa276SKatayama Hirofumi MZ             pIMC->hImeWnd = (HWND)dwValue;
1761470aa276SKatayama Hirofumi MZ             break;
1762470aa276SKatayama Hirofumi MZ 
1763470aa276SKatayama Hirofumi MZ         default:
1764470aa276SKatayama Hirofumi MZ             return FALSE;
1765470aa276SKatayama Hirofumi MZ     }
1766470aa276SKatayama Hirofumi MZ 
1767470aa276SKatayama Hirofumi MZ     return TRUE;
1768470aa276SKatayama Hirofumi MZ }
1769470aa276SKatayama Hirofumi MZ 
1770470aa276SKatayama Hirofumi MZ BOOL
1771e52ce89bSKatayama Hirofumi MZ NTAPI
1772470aa276SKatayama Hirofumi MZ NtUserUpdateInputContext(
1773470aa276SKatayama Hirofumi MZ     HIMC hIMC,
1774470aa276SKatayama Hirofumi MZ     DWORD dwType,
1775470aa276SKatayama Hirofumi MZ     DWORD_PTR dwValue)
1776470aa276SKatayama Hirofumi MZ {
1777470aa276SKatayama Hirofumi MZ     PIMC pIMC;
1778470aa276SKatayama Hirofumi MZ     BOOL ret = FALSE;
1779470aa276SKatayama Hirofumi MZ 
1780470aa276SKatayama Hirofumi MZ     UserEnterExclusive();
1781470aa276SKatayama Hirofumi MZ 
1782470aa276SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1783b5c9d532SKatayama Hirofumi MZ     {
1784b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
1785470aa276SKatayama Hirofumi MZ         goto Quit;
1786b5c9d532SKatayama Hirofumi MZ     }
1787470aa276SKatayama Hirofumi MZ 
1788470aa276SKatayama Hirofumi MZ     pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
1789470aa276SKatayama Hirofumi MZ     if (!pIMC)
1790470aa276SKatayama Hirofumi MZ         goto Quit;
1791470aa276SKatayama Hirofumi MZ 
1792470aa276SKatayama Hirofumi MZ     ret = UserUpdateInputContext(pIMC, dwType, dwValue);
1793470aa276SKatayama Hirofumi MZ 
1794470aa276SKatayama Hirofumi MZ Quit:
1795470aa276SKatayama Hirofumi MZ     UserLeave();
1796470aa276SKatayama Hirofumi MZ     return ret;
1797470aa276SKatayama Hirofumi MZ }
1798470aa276SKatayama Hirofumi MZ 
1799470aa276SKatayama Hirofumi MZ DWORD_PTR
1800e52ce89bSKatayama Hirofumi MZ NTAPI
1801470aa276SKatayama Hirofumi MZ NtUserQueryInputContext(HIMC hIMC, DWORD dwType)
1802470aa276SKatayama Hirofumi MZ {
1803470aa276SKatayama Hirofumi MZ     PIMC pIMC;
1804470aa276SKatayama Hirofumi MZ     PTHREADINFO ptiIMC;
1805470aa276SKatayama Hirofumi MZ     DWORD_PTR ret = 0;
1806470aa276SKatayama Hirofumi MZ 
1807470aa276SKatayama Hirofumi MZ     UserEnterExclusive();
1808470aa276SKatayama Hirofumi MZ 
1809470aa276SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1810b5c9d532SKatayama Hirofumi MZ     {
1811b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
1812470aa276SKatayama Hirofumi MZ         goto Quit;
1813b5c9d532SKatayama Hirofumi MZ     }
1814470aa276SKatayama Hirofumi MZ 
1815470aa276SKatayama Hirofumi MZ     pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
1816470aa276SKatayama Hirofumi MZ     if (!pIMC)
1817470aa276SKatayama Hirofumi MZ         goto Quit;
1818470aa276SKatayama Hirofumi MZ 
1819470aa276SKatayama Hirofumi MZ     ptiIMC = pIMC->head.pti;
1820470aa276SKatayama Hirofumi MZ 
1821470aa276SKatayama Hirofumi MZ     switch (dwType)
1822470aa276SKatayama Hirofumi MZ     {
1823470aa276SKatayama Hirofumi MZ         case QIC_INPUTPROCESSID:
1824470aa276SKatayama Hirofumi MZ             ret = (DWORD_PTR)PsGetThreadProcessId(ptiIMC->pEThread);
1825470aa276SKatayama Hirofumi MZ             break;
1826470aa276SKatayama Hirofumi MZ 
1827470aa276SKatayama Hirofumi MZ         case QIC_INPUTTHREADID:
1828470aa276SKatayama Hirofumi MZ             ret = (DWORD_PTR)PsGetThreadId(ptiIMC->pEThread);
1829470aa276SKatayama Hirofumi MZ             break;
1830470aa276SKatayama Hirofumi MZ 
1831470aa276SKatayama Hirofumi MZ         case QIC_DEFAULTWINDOWIME:
1832470aa276SKatayama Hirofumi MZ             if (ptiIMC->spwndDefaultIme)
1833470aa276SKatayama Hirofumi MZ                 ret = (DWORD_PTR)UserHMGetHandle(ptiIMC->spwndDefaultIme);
1834470aa276SKatayama Hirofumi MZ             break;
1835470aa276SKatayama Hirofumi MZ 
1836470aa276SKatayama Hirofumi MZ         case QIC_DEFAULTIMC:
1837470aa276SKatayama Hirofumi MZ             if (ptiIMC->spDefaultImc)
1838470aa276SKatayama Hirofumi MZ                 ret = (DWORD_PTR)UserHMGetHandle(ptiIMC->spDefaultImc);
1839470aa276SKatayama Hirofumi MZ             break;
1840470aa276SKatayama Hirofumi MZ     }
1841470aa276SKatayama Hirofumi MZ 
1842470aa276SKatayama Hirofumi MZ Quit:
1843470aa276SKatayama Hirofumi MZ     UserLeave();
1844470aa276SKatayama Hirofumi MZ     return ret;
1845470aa276SKatayama Hirofumi MZ }
1846470aa276SKatayama Hirofumi MZ 
18474bcf23d1SKatayama Hirofumi MZ // Searchs a non-IME-related window of the same thread of pwndTarget,
18484bcf23d1SKatayama Hirofumi MZ // other than pwndTarget, around pwndParent. Returns TRUE if found.
18494bcf23d1SKatayama Hirofumi MZ //
18504bcf23d1SKatayama Hirofumi MZ // Win: IsChildSameThread
18514bcf23d1SKatayama Hirofumi MZ BOOL IntFindNonImeRelatedWndOfSameThread(PWND pwndParent, PWND pwndTarget)
18524bcf23d1SKatayama Hirofumi MZ {
18534bcf23d1SKatayama Hirofumi MZ     PWND pwnd, pwndOwner, pwndNode;
18544bcf23d1SKatayama Hirofumi MZ     PTHREADINFO ptiTarget = pwndTarget->head.pti;
18554bcf23d1SKatayama Hirofumi MZ 
18564bcf23d1SKatayama Hirofumi MZ     // For all the children of pwndParent, ...
18574bcf23d1SKatayama Hirofumi MZ     for (pwnd = pwndParent->spwndChild; pwnd; pwnd = pwnd->spwndNext)
18584bcf23d1SKatayama Hirofumi MZ     {
18594bcf23d1SKatayama Hirofumi MZ         if (pwnd == pwndTarget || pwnd->head.pti != ptiTarget || IS_WND_MENU(pwnd))
18604bcf23d1SKatayama Hirofumi MZ             continue;
18614bcf23d1SKatayama Hirofumi MZ 
18624bcf23d1SKatayama Hirofumi MZ         if (!IS_WND_CHILD(pwnd))
18634bcf23d1SKatayama Hirofumi MZ         {
18644bcf23d1SKatayama Hirofumi MZ             // Check if any IME-like owner.
18654bcf23d1SKatayama Hirofumi MZ             BOOL bFound1 = FALSE;
18664bcf23d1SKatayama Hirofumi MZ             for (pwndOwner = pwnd; pwndOwner; pwndOwner = pwndOwner->spwndOwner)
18674bcf23d1SKatayama Hirofumi MZ             {
18684bcf23d1SKatayama Hirofumi MZ                 if (IS_WND_IMELIKE(pwndOwner))
18694bcf23d1SKatayama Hirofumi MZ                 {
18704bcf23d1SKatayama Hirofumi MZ                     bFound1 = TRUE;
18714bcf23d1SKatayama Hirofumi MZ                     break;
18724bcf23d1SKatayama Hirofumi MZ                 }
18734bcf23d1SKatayama Hirofumi MZ             }
18744bcf23d1SKatayama Hirofumi MZ             if (bFound1)
18754bcf23d1SKatayama Hirofumi MZ                 continue; // Skip if any IME-like owner.
18764bcf23d1SKatayama Hirofumi MZ         }
18774bcf23d1SKatayama Hirofumi MZ 
18784bcf23d1SKatayama Hirofumi MZ         pwndNode = pwnd;
18794bcf23d1SKatayama Hirofumi MZ 
18804bcf23d1SKatayama Hirofumi MZ         if (IS_WND_CHILD(pwndNode))
18814bcf23d1SKatayama Hirofumi MZ         {
18824bcf23d1SKatayama Hirofumi MZ             // Check if any same-thread IME-like ancestor.
18834bcf23d1SKatayama Hirofumi MZ             BOOL bFound2 = FALSE;
18844bcf23d1SKatayama Hirofumi MZ             for (; IS_WND_CHILD(pwndNode); pwndNode = pwndNode->spwndParent)
18854bcf23d1SKatayama Hirofumi MZ             {
18864bcf23d1SKatayama Hirofumi MZ                 if (pwndNode->head.pti != ptiTarget)
18874bcf23d1SKatayama Hirofumi MZ                     break;
18884bcf23d1SKatayama Hirofumi MZ 
18894bcf23d1SKatayama Hirofumi MZ                 if (IS_WND_IMELIKE(pwndNode))
18904bcf23d1SKatayama Hirofumi MZ                 {
18914bcf23d1SKatayama Hirofumi MZ                     bFound2 = TRUE;
18924bcf23d1SKatayama Hirofumi MZ                     break;
18934bcf23d1SKatayama Hirofumi MZ                 }
18944bcf23d1SKatayama Hirofumi MZ             }
18954bcf23d1SKatayama Hirofumi MZ             if (bFound2)
18964bcf23d1SKatayama Hirofumi MZ                 continue;
18974bcf23d1SKatayama Hirofumi MZ             // Now, pwndNode is non-child or non-same-thread window.
18984bcf23d1SKatayama Hirofumi MZ         }
18994bcf23d1SKatayama Hirofumi MZ 
19004bcf23d1SKatayama Hirofumi MZ         if (!IS_WND_CHILD(pwndNode)) // pwndNode is non-child
19014bcf23d1SKatayama Hirofumi MZ         {
19024bcf23d1SKatayama Hirofumi MZ             // Check if any same-thread IME-like owner.
19034bcf23d1SKatayama Hirofumi MZ             BOOL bFound3 = FALSE;
19044bcf23d1SKatayama Hirofumi MZ             for (; pwndNode; pwndNode = pwndNode->spwndOwner)
19054bcf23d1SKatayama Hirofumi MZ             {
19064bcf23d1SKatayama Hirofumi MZ                 if (pwndNode->head.pti != ptiTarget)
19074bcf23d1SKatayama Hirofumi MZ                     break;
19084bcf23d1SKatayama Hirofumi MZ 
19094bcf23d1SKatayama Hirofumi MZ                 if (IS_WND_IMELIKE(pwndNode))
19104bcf23d1SKatayama Hirofumi MZ                 {
19114bcf23d1SKatayama Hirofumi MZ                     bFound3 = TRUE;
19124bcf23d1SKatayama Hirofumi MZ                     break;
19134bcf23d1SKatayama Hirofumi MZ                 }
19144bcf23d1SKatayama Hirofumi MZ             }
19154bcf23d1SKatayama Hirofumi MZ             if (bFound3)
19164bcf23d1SKatayama Hirofumi MZ                 continue;
19174bcf23d1SKatayama Hirofumi MZ         }
19184bcf23d1SKatayama Hirofumi MZ 
19194bcf23d1SKatayama Hirofumi MZ         return TRUE;
19204bcf23d1SKatayama Hirofumi MZ     }
19214bcf23d1SKatayama Hirofumi MZ 
19224bcf23d1SKatayama Hirofumi MZ     return FALSE;
19234bcf23d1SKatayama Hirofumi MZ }
19244bcf23d1SKatayama Hirofumi MZ 
19258f719cb9SKatayama Hirofumi MZ // Determines whether the target window needs the IME window.
19268f719cb9SKatayama Hirofumi MZ // Win: WantImeWindow(pwndParent, pwndTarget)
19278f719cb9SKatayama Hirofumi MZ BOOL FASTCALL IntWantImeWindow(PWND pwndTarget)
19288f719cb9SKatayama Hirofumi MZ {
19298f719cb9SKatayama Hirofumi MZ     PDESKTOP rpdesk;
19308f719cb9SKatayama Hirofumi MZ     PWINSTATION_OBJECT rpwinstaParent;
19318f719cb9SKatayama Hirofumi MZ     PWND pwndNode, pwndParent = pwndTarget->spwndParent;
19328f719cb9SKatayama Hirofumi MZ 
19338f719cb9SKatayama Hirofumi MZ     if (gptiCurrent->TIF_flags & TIF_DISABLEIME)
19348f719cb9SKatayama Hirofumi MZ         return FALSE;
19358f719cb9SKatayama Hirofumi MZ 
19368f719cb9SKatayama Hirofumi MZ     if (IS_WND_IMELIKE(pwndTarget))
19378f719cb9SKatayama Hirofumi MZ         return FALSE;
19388f719cb9SKatayama Hirofumi MZ 
19398f719cb9SKatayama Hirofumi MZ     if (pwndTarget->fnid == FNID_DESKTOP || pwndTarget->fnid == FNID_MESSAGEWND)
19408f719cb9SKatayama Hirofumi MZ         return FALSE;
19418f719cb9SKatayama Hirofumi MZ 
19428f719cb9SKatayama Hirofumi MZ     if (pwndTarget->state & WNDS_SERVERSIDEWINDOWPROC)
19438f719cb9SKatayama Hirofumi MZ         return FALSE;
19448f719cb9SKatayama Hirofumi MZ 
19458f719cb9SKatayama Hirofumi MZ     rpdesk = pwndTarget->head.rpdesk;
19468f719cb9SKatayama Hirofumi MZ     if (!rpdesk)
19478f719cb9SKatayama Hirofumi MZ         return FALSE;
19488f719cb9SKatayama Hirofumi MZ 
19498f719cb9SKatayama Hirofumi MZ     rpwinstaParent = rpdesk->rpwinstaParent;
19508f719cb9SKatayama Hirofumi MZ     if (!rpwinstaParent || (rpwinstaParent->Flags & WSS_NOIO))
19518f719cb9SKatayama Hirofumi MZ         return FALSE;
19528f719cb9SKatayama Hirofumi MZ 
19538f719cb9SKatayama Hirofumi MZ     for (pwndNode = pwndParent; pwndNode; pwndNode = pwndNode->spwndParent)
19548f719cb9SKatayama Hirofumi MZ     {
19558f719cb9SKatayama Hirofumi MZ         if (rpdesk != pwndNode->head.rpdesk)
19568f719cb9SKatayama Hirofumi MZ             break;
19578f719cb9SKatayama Hirofumi MZ 
19588f719cb9SKatayama Hirofumi MZ         if (pwndNode == rpdesk->spwndMessage)
19598f719cb9SKatayama Hirofumi MZ             return FALSE;
19608f719cb9SKatayama Hirofumi MZ     }
19618f719cb9SKatayama Hirofumi MZ 
19628f719cb9SKatayama Hirofumi MZ     return TRUE;
19638f719cb9SKatayama Hirofumi MZ }
19648f719cb9SKatayama Hirofumi MZ 
19658f719cb9SKatayama Hirofumi MZ // Create the default IME window for the target window.
19668f719cb9SKatayama Hirofumi MZ // Win: xxxCreateDefaultImeWindow(pwndTarget, ATOM, hInst)
19678f719cb9SKatayama Hirofumi MZ PWND FASTCALL co_IntCreateDefaultImeWindow(PWND pwndTarget, HINSTANCE hInst)
19688f719cb9SKatayama Hirofumi MZ {
19698f719cb9SKatayama Hirofumi MZ     LARGE_UNICODE_STRING WindowName;
19708f719cb9SKatayama Hirofumi MZ     UNICODE_STRING ClassName;
19718f719cb9SKatayama Hirofumi MZ     PWND pImeWnd;
19728f719cb9SKatayama Hirofumi MZ     PIMEUI pimeui;
19738f719cb9SKatayama Hirofumi MZ     CREATESTRUCTW Cs;
19748f719cb9SKatayama Hirofumi MZ     USER_REFERENCE_ENTRY Ref;
19758f719cb9SKatayama Hirofumi MZ     PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
19768f719cb9SKatayama Hirofumi MZ     HANDLE pid = PsGetThreadProcessId(pti->pEThread);
19778f719cb9SKatayama Hirofumi MZ 
19788f719cb9SKatayama Hirofumi MZ     if (!(pti->spDefaultImc) && pid == gpidLogon)
19798f719cb9SKatayama Hirofumi MZ         UserCreateInputContext(0);
19808f719cb9SKatayama Hirofumi MZ 
19818f719cb9SKatayama Hirofumi MZ     if (!(pti->spDefaultImc) || IS_WND_IMELIKE(pwndTarget) || !(pti->rpdesk->pheapDesktop))
19828f719cb9SKatayama Hirofumi MZ         return NULL;
19838f719cb9SKatayama Hirofumi MZ 
19848f719cb9SKatayama Hirofumi MZ     if (IS_WND_CHILD(pwndTarget) && !(pwndTarget->style & WS_VISIBLE) &&
19858f719cb9SKatayama Hirofumi MZ         pwndTarget->spwndParent->head.pti->ppi != pti->ppi)
19868f719cb9SKatayama Hirofumi MZ     {
19878f719cb9SKatayama Hirofumi MZ         return NULL;
19888f719cb9SKatayama Hirofumi MZ     }
19898f719cb9SKatayama Hirofumi MZ 
19908f719cb9SKatayama Hirofumi MZ     RtlInitLargeUnicodeString(&WindowName, L"Default IME", 0);
19918f719cb9SKatayama Hirofumi MZ 
19928f719cb9SKatayama Hirofumi MZ     ClassName.Buffer = (PWCH)(ULONG_PTR)gpsi->atomSysClass[ICLS_IME];
19938f719cb9SKatayama Hirofumi MZ     ClassName.Length = 0;
19948f719cb9SKatayama Hirofumi MZ     ClassName.MaximumLength = 0;
19958f719cb9SKatayama Hirofumi MZ 
19968f719cb9SKatayama Hirofumi MZ     UserRefObjectCo(pwndTarget, &Ref);
19978f719cb9SKatayama Hirofumi MZ 
19988f719cb9SKatayama Hirofumi MZ     RtlZeroMemory(&Cs, sizeof(Cs));
19998f719cb9SKatayama Hirofumi MZ     Cs.style = WS_POPUP | WS_DISABLED;
20008f719cb9SKatayama Hirofumi MZ     Cs.hInstance = hInst;
20018f719cb9SKatayama Hirofumi MZ     Cs.hwndParent = UserHMGetHandle(pwndTarget);
20028f719cb9SKatayama Hirofumi MZ     Cs.lpszName = WindowName.Buffer;
20038f719cb9SKatayama Hirofumi MZ     Cs.lpszClass = ClassName.Buffer;
20048f719cb9SKatayama Hirofumi MZ 
20058f719cb9SKatayama Hirofumi MZ     // NOTE: LARGE_UNICODE_STRING is compatible to LARGE_STRING.
20068f719cb9SKatayama Hirofumi MZ     pImeWnd = co_UserCreateWindowEx(&Cs, &ClassName, (PLARGE_STRING)&WindowName, NULL, WINVER);
20078f719cb9SKatayama Hirofumi MZ     if (pImeWnd)
20088f719cb9SKatayama Hirofumi MZ     {
20098f719cb9SKatayama Hirofumi MZ         pimeui = ((PIMEWND)pImeWnd)->pimeui;
20108f719cb9SKatayama Hirofumi MZ         _SEH2_TRY
20118f719cb9SKatayama Hirofumi MZ         {
20128f719cb9SKatayama Hirofumi MZ             ProbeForWrite(pimeui, sizeof(IMEUI), 1);
20138f719cb9SKatayama Hirofumi MZ             pimeui->fDefault = TRUE;
20148f719cb9SKatayama Hirofumi MZ             if (IS_WND_CHILD(pwndTarget) && pwndTarget->spwndParent->head.pti != pti)
20158f719cb9SKatayama Hirofumi MZ                 pimeui->fChildThreadDef = TRUE;
20168f719cb9SKatayama Hirofumi MZ         }
20178f719cb9SKatayama Hirofumi MZ         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
20188f719cb9SKatayama Hirofumi MZ         {
20198f719cb9SKatayama Hirofumi MZ             NOTHING;
20208f719cb9SKatayama Hirofumi MZ         }
20218f719cb9SKatayama Hirofumi MZ         _SEH2_END;
20228f719cb9SKatayama Hirofumi MZ     }
20238f719cb9SKatayama Hirofumi MZ 
20248f719cb9SKatayama Hirofumi MZ     UserDerefObjectCo(pwndTarget);
20258f719cb9SKatayama Hirofumi MZ     return pImeWnd;
20268f719cb9SKatayama Hirofumi MZ }
20278f719cb9SKatayama Hirofumi MZ 
20288f719cb9SKatayama Hirofumi MZ // Determines whether the system can destroy the default IME window for the target child window.
20294bcf23d1SKatayama Hirofumi MZ // Win: ImeCanDestroyDefIMEforChild
20304bcf23d1SKatayama Hirofumi MZ BOOL FASTCALL IntImeCanDestroyDefIMEforChild(PWND pImeWnd, PWND pwndTarget)
20314bcf23d1SKatayama Hirofumi MZ {
20324bcf23d1SKatayama Hirofumi MZ     PWND pwndNode;
20334bcf23d1SKatayama Hirofumi MZ     PIMEUI pimeui;
20344bcf23d1SKatayama Hirofumi MZ     IMEUI SafeImeUI;
20354bcf23d1SKatayama Hirofumi MZ 
20364bcf23d1SKatayama Hirofumi MZ     pimeui = ((PIMEWND)pImeWnd)->pimeui;
20374bcf23d1SKatayama Hirofumi MZ     if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
20384bcf23d1SKatayama Hirofumi MZ         return FALSE;
20394bcf23d1SKatayama Hirofumi MZ 
20404bcf23d1SKatayama Hirofumi MZ     // Check IMEUI.fChildThreadDef
20414bcf23d1SKatayama Hirofumi MZ     _SEH2_TRY
20424bcf23d1SKatayama Hirofumi MZ     {
20434bcf23d1SKatayama Hirofumi MZ         ProbeForRead(pimeui, sizeof(IMEUI), 1);
20444bcf23d1SKatayama Hirofumi MZ         SafeImeUI = *pimeui;
20454bcf23d1SKatayama Hirofumi MZ         if (!SafeImeUI.fChildThreadDef)
20464bcf23d1SKatayama Hirofumi MZ             return FALSE;
20474bcf23d1SKatayama Hirofumi MZ     }
20484bcf23d1SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
20494bcf23d1SKatayama Hirofumi MZ     {
20508f719cb9SKatayama Hirofumi MZ         NOTHING;
20514bcf23d1SKatayama Hirofumi MZ     }
20524bcf23d1SKatayama Hirofumi MZ     _SEH2_END;
20534bcf23d1SKatayama Hirofumi MZ 
20544bcf23d1SKatayama Hirofumi MZ     // The parent of pwndTarget is NULL or of the same thread of pwndTarget?
20554bcf23d1SKatayama Hirofumi MZ     if (pwndTarget->spwndParent == NULL ||
20564bcf23d1SKatayama Hirofumi MZ         pwndTarget->head.pti == pwndTarget->spwndParent->head.pti)
20574bcf23d1SKatayama Hirofumi MZ     {
20584bcf23d1SKatayama Hirofumi MZ         return FALSE;
20594bcf23d1SKatayama Hirofumi MZ     }
20604bcf23d1SKatayama Hirofumi MZ 
20614bcf23d1SKatayama Hirofumi MZ     for (pwndNode = pwndTarget; pwndNode; pwndNode = pwndNode->spwndParent)
20624bcf23d1SKatayama Hirofumi MZ     {
20634bcf23d1SKatayama Hirofumi MZ         if (pwndNode == pwndNode->head.rpdesk->pDeskInfo->spwnd)
20644bcf23d1SKatayama Hirofumi MZ             break;
20654bcf23d1SKatayama Hirofumi MZ 
20664bcf23d1SKatayama Hirofumi MZ         if (IntFindNonImeRelatedWndOfSameThread(pwndNode->spwndParent, pwndTarget))
20674bcf23d1SKatayama Hirofumi MZ             return FALSE;
20684bcf23d1SKatayama Hirofumi MZ     }
20694bcf23d1SKatayama Hirofumi MZ 
20704bcf23d1SKatayama Hirofumi MZ     return TRUE;
20714bcf23d1SKatayama Hirofumi MZ }
20724bcf23d1SKatayama Hirofumi MZ 
20738f719cb9SKatayama Hirofumi MZ // Determines whether the system can destroy the default IME window for the non-child target window.
20744bcf23d1SKatayama Hirofumi MZ // Win: ImeCanDestroyDefIME
20754bcf23d1SKatayama Hirofumi MZ BOOL FASTCALL IntImeCanDestroyDefIME(PWND pImeWnd, PWND pwndTarget)
20764bcf23d1SKatayama Hirofumi MZ {
20774bcf23d1SKatayama Hirofumi MZ     PWND pwndNode;
20784bcf23d1SKatayama Hirofumi MZ     PIMEUI pimeui;
20794bcf23d1SKatayama Hirofumi MZ     IMEUI SafeImeUI;
20804bcf23d1SKatayama Hirofumi MZ 
20814bcf23d1SKatayama Hirofumi MZ     pimeui = ((PIMEWND)pImeWnd)->pimeui;
20824bcf23d1SKatayama Hirofumi MZ     if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
20834bcf23d1SKatayama Hirofumi MZ         return FALSE;
20844bcf23d1SKatayama Hirofumi MZ 
20854bcf23d1SKatayama Hirofumi MZ     // Check IMEUI.fDestroy
20864bcf23d1SKatayama Hirofumi MZ     _SEH2_TRY
20874bcf23d1SKatayama Hirofumi MZ     {
20884bcf23d1SKatayama Hirofumi MZ         ProbeForRead(pimeui, sizeof(IMEUI), 1);
20894bcf23d1SKatayama Hirofumi MZ         SafeImeUI = *pimeui;
20904bcf23d1SKatayama Hirofumi MZ         if (SafeImeUI.fDestroy)
20914bcf23d1SKatayama Hirofumi MZ             return FALSE;
20924bcf23d1SKatayama Hirofumi MZ     }
20934bcf23d1SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
20944bcf23d1SKatayama Hirofumi MZ     {
20958f719cb9SKatayama Hirofumi MZ         NOTHING;
20964bcf23d1SKatayama Hirofumi MZ     }
20974bcf23d1SKatayama Hirofumi MZ     _SEH2_END;
20984bcf23d1SKatayama Hirofumi MZ 
20994bcf23d1SKatayama Hirofumi MZ     // Any ancestor of pImeWnd is pwndTarget?
21004bcf23d1SKatayama Hirofumi MZ     if (pImeWnd->spwndOwner)
21014bcf23d1SKatayama Hirofumi MZ     {
21024bcf23d1SKatayama Hirofumi MZ         for (pwndNode = pImeWnd->spwndOwner; pwndNode; pwndNode = pwndNode->spwndOwner)
21034bcf23d1SKatayama Hirofumi MZ         {
21044bcf23d1SKatayama Hirofumi MZ             if (pwndNode == pwndTarget)
21054bcf23d1SKatayama Hirofumi MZ                 break;
21064bcf23d1SKatayama Hirofumi MZ         }
21074bcf23d1SKatayama Hirofumi MZ 
21084bcf23d1SKatayama Hirofumi MZ         if (!pwndNode)
21094bcf23d1SKatayama Hirofumi MZ             return FALSE;
21104bcf23d1SKatayama Hirofumi MZ     }
21114bcf23d1SKatayama Hirofumi MZ 
21124bcf23d1SKatayama Hirofumi MZ     // Any ancestor of pwndTarget is IME-like?
21134bcf23d1SKatayama Hirofumi MZ     for (pwndNode = pwndTarget; pwndNode; pwndNode = pwndNode->spwndOwner)
21144bcf23d1SKatayama Hirofumi MZ     {
21154bcf23d1SKatayama Hirofumi MZ         if (IS_WND_IMELIKE(pwndNode))
21164bcf23d1SKatayama Hirofumi MZ             return FALSE;
21174bcf23d1SKatayama Hirofumi MZ     }
21184bcf23d1SKatayama Hirofumi MZ 
21194bcf23d1SKatayama Hirofumi MZ     // Adjust the ordering and top-mode status
21204bcf23d1SKatayama Hirofumi MZ     IntImeSetFutureOwner(pImeWnd, pwndTarget);
21214bcf23d1SKatayama Hirofumi MZ     for (pwndNode = pImeWnd->spwndOwner; pwndNode; pwndNode = pwndNode->spwndNext)
21224bcf23d1SKatayama Hirofumi MZ     {
21234bcf23d1SKatayama Hirofumi MZ         if (pwndNode == pImeWnd)
21244bcf23d1SKatayama Hirofumi MZ             break;
21254bcf23d1SKatayama Hirofumi MZ     }
21264bcf23d1SKatayama Hirofumi MZ     if (pwndNode == pImeWnd)
21274bcf23d1SKatayama Hirofumi MZ         IntImeCheckTopmost(pImeWnd);
21284bcf23d1SKatayama Hirofumi MZ 
21294bcf23d1SKatayama Hirofumi MZ     // Is the owner of pImeWnd NULL or pwndTarget?
21304bcf23d1SKatayama Hirofumi MZ     if (pImeWnd->spwndOwner && pwndTarget != pImeWnd->spwndOwner)
21314bcf23d1SKatayama Hirofumi MZ         return FALSE;
21324bcf23d1SKatayama Hirofumi MZ 
2133e56da485STimo Kreuzer     WndSetOwner(pImeWnd, NULL);
21344bcf23d1SKatayama Hirofumi MZ     return TRUE;
21354bcf23d1SKatayama Hirofumi MZ }
21364bcf23d1SKatayama Hirofumi MZ 
2137242e0b43SKatayama Hirofumi MZ // Update IMEUI.fShowStatus flags and Send the WM_IME_NOTIFY messages.
2138242e0b43SKatayama Hirofumi MZ // Win: xxxCheckImeShowStatus
2139242e0b43SKatayama Hirofumi MZ BOOL FASTCALL IntCheckImeShowStatus(PWND pwndIme, PTHREADINFO pti)
2140242e0b43SKatayama Hirofumi MZ {
2141242e0b43SKatayama Hirofumi MZ     BOOL ret = FALSE, bDifferent;
2142242e0b43SKatayama Hirofumi MZ     PWINDOWLIST pwl;
2143242e0b43SKatayama Hirofumi MZ     HWND *phwnd;
2144242e0b43SKatayama Hirofumi MZ     PWND pwndNode, pwndIMC;
2145242e0b43SKatayama Hirofumi MZ     PTHREADINFO ptiCurrent = GetW32ThreadInfo();
2146242e0b43SKatayama Hirofumi MZ     PIMEUI pimeui;
2147242e0b43SKatayama Hirofumi MZ     IMEUI SafeImeUI;
2148242e0b43SKatayama Hirofumi MZ 
2149242e0b43SKatayama Hirofumi MZ     if (pwndIme->state2 & WNDS2_INDESTROY)
2150242e0b43SKatayama Hirofumi MZ         return FALSE;
2151242e0b43SKatayama Hirofumi MZ 
2152242e0b43SKatayama Hirofumi MZ     // Build a window list
2153242e0b43SKatayama Hirofumi MZ     pwl = IntBuildHwndList(pwndIme->spwndParent->spwndChild, IACE_LIST, NULL);
2154242e0b43SKatayama Hirofumi MZ     if (!pwl)
2155242e0b43SKatayama Hirofumi MZ         return FALSE;
2156242e0b43SKatayama Hirofumi MZ 
2157242e0b43SKatayama Hirofumi MZ     ret = TRUE;
2158242e0b43SKatayama Hirofumi MZ     for (phwnd = pwl->ahwnd; *phwnd != HWND_TERMINATOR; ++phwnd)
2159242e0b43SKatayama Hirofumi MZ     {
2160242e0b43SKatayama Hirofumi MZ         pwndNode = ValidateHwndNoErr(*phwnd);
2161242e0b43SKatayama Hirofumi MZ 
2162242e0b43SKatayama Hirofumi MZ         if (!pwndNode || pwndIme == pwndNode)
2163242e0b43SKatayama Hirofumi MZ             continue;
2164242e0b43SKatayama Hirofumi MZ 
2165242e0b43SKatayama Hirofumi MZ         if (pwndNode->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME] ||
2166242e0b43SKatayama Hirofumi MZ             (pwndNode->state2 & WNDS2_INDESTROY))
2167242e0b43SKatayama Hirofumi MZ         {
2168242e0b43SKatayama Hirofumi MZ             continue;
2169242e0b43SKatayama Hirofumi MZ         }
2170242e0b43SKatayama Hirofumi MZ 
2171242e0b43SKatayama Hirofumi MZ         pimeui = ((PIMEWND)pwndNode)->pimeui;
2172242e0b43SKatayama Hirofumi MZ         if (!pimeui || pimeui == (PIMEUI)-1)
2173242e0b43SKatayama Hirofumi MZ             continue;
2174242e0b43SKatayama Hirofumi MZ 
2175242e0b43SKatayama Hirofumi MZ         if (pti && pti != pwndNode->head.pti)
2176242e0b43SKatayama Hirofumi MZ             continue;
2177242e0b43SKatayama Hirofumi MZ 
2178242e0b43SKatayama Hirofumi MZ         // Attach to the process if necessary
2179242e0b43SKatayama Hirofumi MZ         bDifferent = FALSE;
2180242e0b43SKatayama Hirofumi MZ         if (pwndNode->head.pti->ppi != ptiCurrent->ppi)
2181242e0b43SKatayama Hirofumi MZ         {
2182242e0b43SKatayama Hirofumi MZ             KeAttachProcess(&(pwndNode->head.pti->ppi->peProcess->Pcb));
2183242e0b43SKatayama Hirofumi MZ             bDifferent = TRUE;
2184242e0b43SKatayama Hirofumi MZ         }
2185242e0b43SKatayama Hirofumi MZ 
2186242e0b43SKatayama Hirofumi MZ         // Get pwndIMC and update IMEUI.fShowStatus flag
2187242e0b43SKatayama Hirofumi MZ         _SEH2_TRY
2188242e0b43SKatayama Hirofumi MZ         {
2189242e0b43SKatayama Hirofumi MZ             ProbeForWrite(pimeui, sizeof(IMEUI), 1);
2190242e0b43SKatayama Hirofumi MZ             SafeImeUI = *pimeui;
2191242e0b43SKatayama Hirofumi MZ             if (SafeImeUI.fShowStatus)
2192242e0b43SKatayama Hirofumi MZ             {
2193242e0b43SKatayama Hirofumi MZ                 pwndIMC = ValidateHwndNoErr(pimeui->hwndIMC);
2194242e0b43SKatayama Hirofumi MZ                 if (pwndIMC)
2195242e0b43SKatayama Hirofumi MZ                     pimeui->fShowStatus = FALSE;
2196242e0b43SKatayama Hirofumi MZ             }
2197242e0b43SKatayama Hirofumi MZ             else
2198242e0b43SKatayama Hirofumi MZ             {
2199242e0b43SKatayama Hirofumi MZ                 pwndIMC = NULL;
2200242e0b43SKatayama Hirofumi MZ             }
2201242e0b43SKatayama Hirofumi MZ         }
2202242e0b43SKatayama Hirofumi MZ         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2203242e0b43SKatayama Hirofumi MZ         {
2204242e0b43SKatayama Hirofumi MZ             pwndIMC = NULL;
2205242e0b43SKatayama Hirofumi MZ         }
2206242e0b43SKatayama Hirofumi MZ         _SEH2_END;
2207242e0b43SKatayama Hirofumi MZ 
2208242e0b43SKatayama Hirofumi MZ         // Detach from the process if necessary
2209242e0b43SKatayama Hirofumi MZ         if (bDifferent)
2210242e0b43SKatayama Hirofumi MZ             KeDetachProcess();
2211242e0b43SKatayama Hirofumi MZ 
2212242e0b43SKatayama Hirofumi MZ         // Send the WM_IME_NOTIFY message
2213242e0b43SKatayama Hirofumi MZ         if (pwndIMC && pwndIMC->head.pti && !(pwndIMC->head.pti->TIF_flags & TIF_INCLEANUP))
2214242e0b43SKatayama Hirofumi MZ         {
2215242e0b43SKatayama Hirofumi MZ             HWND hImeWnd;
2216242e0b43SKatayama Hirofumi MZ             USER_REFERENCE_ENTRY Ref;
2217242e0b43SKatayama Hirofumi MZ 
2218242e0b43SKatayama Hirofumi MZ             UserRefObjectCo(pwndIMC, &Ref);
2219242e0b43SKatayama Hirofumi MZ 
2220242e0b43SKatayama Hirofumi MZ             hImeWnd = UserHMGetHandle(pwndIMC);
2221242e0b43SKatayama Hirofumi MZ             co_IntSendMessage(hImeWnd, WM_IME_NOTIFY, IMN_CLOSESTATUSWINDOW, 0);
2222242e0b43SKatayama Hirofumi MZ 
2223242e0b43SKatayama Hirofumi MZ             UserDerefObjectCo(pwndIMC);
2224242e0b43SKatayama Hirofumi MZ         }
2225242e0b43SKatayama Hirofumi MZ     }
2226242e0b43SKatayama Hirofumi MZ 
2227242e0b43SKatayama Hirofumi MZ     // Free the window list
2228242e0b43SKatayama Hirofumi MZ     IntFreeHwndList(pwl);
2229242e0b43SKatayama Hirofumi MZ     return ret;
2230242e0b43SKatayama Hirofumi MZ }
2231242e0b43SKatayama Hirofumi MZ 
2232242e0b43SKatayama Hirofumi MZ // Send a UI message.
2233242e0b43SKatayama Hirofumi MZ LRESULT FASTCALL
2234242e0b43SKatayama Hirofumi MZ IntSendMessageToUI(PTHREADINFO ptiIME, PIMEUI pimeui, UINT uMsg, WPARAM wParam, LPARAM lParam)
2235242e0b43SKatayama Hirofumi MZ {
2236242e0b43SKatayama Hirofumi MZ     PWND pwndUI;
2237242e0b43SKatayama Hirofumi MZ     LRESULT ret = 0;
2238242e0b43SKatayama Hirofumi MZ     IMEUI SafeImeUI;
2239242e0b43SKatayama Hirofumi MZ     BOOL bDifferent = FALSE;
2240242e0b43SKatayama Hirofumi MZ     USER_REFERENCE_ENTRY Ref;
2241242e0b43SKatayama Hirofumi MZ 
2242242e0b43SKatayama Hirofumi MZ     // Attach to the process if necessary
2243242e0b43SKatayama Hirofumi MZ     if (ptiIME != GetW32ThreadInfo())
2244242e0b43SKatayama Hirofumi MZ     {
2245242e0b43SKatayama Hirofumi MZ         bDifferent = TRUE;
2246242e0b43SKatayama Hirofumi MZ         KeAttachProcess(&(ptiIME->ppi->peProcess->Pcb));
2247242e0b43SKatayama Hirofumi MZ     }
2248242e0b43SKatayama Hirofumi MZ 
2249242e0b43SKatayama Hirofumi MZ     // Get the pwndUI
2250242e0b43SKatayama Hirofumi MZ     _SEH2_TRY
2251242e0b43SKatayama Hirofumi MZ     {
2252242e0b43SKatayama Hirofumi MZ         ProbeForRead(pimeui, sizeof(IMEUI), 1);
2253242e0b43SKatayama Hirofumi MZ         SafeImeUI = *pimeui;
2254242e0b43SKatayama Hirofumi MZ         pwndUI = ValidateHwndNoErr(SafeImeUI.hwndUI);
2255242e0b43SKatayama Hirofumi MZ     }
2256242e0b43SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2257242e0b43SKatayama Hirofumi MZ     {
22589751d03cSKatayama Hirofumi MZ         ERR("!!!\n");
2259242e0b43SKatayama Hirofumi MZ         pwndUI = NULL;
2260242e0b43SKatayama Hirofumi MZ     }
2261242e0b43SKatayama Hirofumi MZ     _SEH2_END;
2262242e0b43SKatayama Hirofumi MZ 
2263242e0b43SKatayama Hirofumi MZ     if (!pwndUI)
2264242e0b43SKatayama Hirofumi MZ         goto Quit;
2265242e0b43SKatayama Hirofumi MZ 
2266242e0b43SKatayama Hirofumi MZ     // Increment the recursion count of the IME procedure.
2267242e0b43SKatayama Hirofumi MZ     // See also ImeWndProc_common of user32.
2268242e0b43SKatayama Hirofumi MZ     _SEH2_TRY
2269242e0b43SKatayama Hirofumi MZ     {
2270242e0b43SKatayama Hirofumi MZ         ProbeForWrite(&pimeui->nCntInIMEProc, sizeof(LONG), 1);
2271242e0b43SKatayama Hirofumi MZ         InterlockedIncrement(&pimeui->nCntInIMEProc);
2272242e0b43SKatayama Hirofumi MZ     }
2273242e0b43SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2274242e0b43SKatayama Hirofumi MZ     {
22759751d03cSKatayama Hirofumi MZ         ERR("!!!\n");
22769751d03cSKatayama Hirofumi MZ         _SEH2_YIELD(goto Quit);
2277242e0b43SKatayama Hirofumi MZ     }
2278242e0b43SKatayama Hirofumi MZ     _SEH2_END;
2279242e0b43SKatayama Hirofumi MZ 
2280242e0b43SKatayama Hirofumi MZ     // Detach from the process if necessary
2281242e0b43SKatayama Hirofumi MZ     if (bDifferent)
2282242e0b43SKatayama Hirofumi MZ         KeDetachProcess();
2283242e0b43SKatayama Hirofumi MZ 
2284242e0b43SKatayama Hirofumi MZ     UserRefObjectCo(pwndUI, &Ref);
2285242e0b43SKatayama Hirofumi MZ     ret = co_IntSendMessage(UserHMGetHandle(pwndUI), uMsg, wParam, lParam);
2286242e0b43SKatayama Hirofumi MZ     UserDerefObjectCo(pwndUI);
2287242e0b43SKatayama Hirofumi MZ 
2288242e0b43SKatayama Hirofumi MZ     // Attach to the process if necessary
2289242e0b43SKatayama Hirofumi MZ     if (bDifferent)
2290242e0b43SKatayama Hirofumi MZ         KeAttachProcess(&(ptiIME->ppi->peProcess->Pcb));
2291242e0b43SKatayama Hirofumi MZ 
2292242e0b43SKatayama Hirofumi MZ     // Decrement the recursion count of the IME procedure
2293242e0b43SKatayama Hirofumi MZ     _SEH2_TRY
2294242e0b43SKatayama Hirofumi MZ     {
2295242e0b43SKatayama Hirofumi MZ         ProbeForWrite(&pimeui->nCntInIMEProc, sizeof(LONG), 1);
2296242e0b43SKatayama Hirofumi MZ         InterlockedDecrement(&pimeui->nCntInIMEProc);
2297242e0b43SKatayama Hirofumi MZ     }
2298242e0b43SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2299242e0b43SKatayama Hirofumi MZ     {
23009751d03cSKatayama Hirofumi MZ         ERR("!!!\n");
23019751d03cSKatayama Hirofumi MZ         _SEH2_YIELD(goto Quit);
2302242e0b43SKatayama Hirofumi MZ     }
2303242e0b43SKatayama Hirofumi MZ     _SEH2_END;
2304242e0b43SKatayama Hirofumi MZ 
2305242e0b43SKatayama Hirofumi MZ Quit:
2306242e0b43SKatayama Hirofumi MZ     // Detach from the process if necessary
2307242e0b43SKatayama Hirofumi MZ     if (bDifferent)
2308242e0b43SKatayama Hirofumi MZ         KeDetachProcess();
2309242e0b43SKatayama Hirofumi MZ 
2310242e0b43SKatayama Hirofumi MZ     return ret;
2311242e0b43SKatayama Hirofumi MZ }
2312242e0b43SKatayama Hirofumi MZ 
2313242e0b43SKatayama Hirofumi MZ // Send the open status notification.
2314242e0b43SKatayama Hirofumi MZ // Win: xxxSendOpenStatusNotify
2315242e0b43SKatayama Hirofumi MZ VOID FASTCALL
2316242e0b43SKatayama Hirofumi MZ IntSendOpenStatusNotify(PTHREADINFO ptiIME, PIMEUI pimeui, PWND pWnd, BOOL bOpen)
2317242e0b43SKatayama Hirofumi MZ {
2318242e0b43SKatayama Hirofumi MZ     WPARAM wParam = (bOpen ? IMN_OPENSTATUSWINDOW : IMN_CLOSESTATUSWINDOW);
2319242e0b43SKatayama Hirofumi MZ     PTHREADINFO ptiWnd = pWnd->head.pti;
2320242e0b43SKatayama Hirofumi MZ     USER_REFERENCE_ENTRY Ref;
2321242e0b43SKatayama Hirofumi MZ 
2322242e0b43SKatayama Hirofumi MZ     if (ptiWnd->dwExpWinVer >= WINVER_WINNT4 && pWnd->hImc)
2323242e0b43SKatayama Hirofumi MZ     {
2324242e0b43SKatayama Hirofumi MZ         UserRefObjectCo(pWnd, &Ref);
2325242e0b43SKatayama Hirofumi MZ         co_IntSendMessage(UserHMGetHandle(pWnd), WM_IME_NOTIFY, wParam, 0);
2326242e0b43SKatayama Hirofumi MZ         UserDerefObjectCo(pWnd);
2327242e0b43SKatayama Hirofumi MZ     }
2328242e0b43SKatayama Hirofumi MZ     else
2329242e0b43SKatayama Hirofumi MZ     {
2330242e0b43SKatayama Hirofumi MZ         IntSendMessageToUI(ptiIME, pimeui, WM_IME_NOTIFY, wParam, 0);
2331242e0b43SKatayama Hirofumi MZ     }
2332242e0b43SKatayama Hirofumi MZ }
2333242e0b43SKatayama Hirofumi MZ 
2334242e0b43SKatayama Hirofumi MZ // Update the IME status and send a notification.
2335242e0b43SKatayama Hirofumi MZ VOID FASTCALL IntNotifyImeShowStatus(PWND pImeWnd)
2336242e0b43SKatayama Hirofumi MZ {
2337242e0b43SKatayama Hirofumi MZ     PIMEUI pimeui;
2338242e0b43SKatayama Hirofumi MZ     PWND pWnd;
2339242e0b43SKatayama Hirofumi MZ     PTHREADINFO pti, ptiIME;
2340242e0b43SKatayama Hirofumi MZ     BOOL bShow, bSendNotify = FALSE;
2341242e0b43SKatayama Hirofumi MZ     IMEUI SafeImeUI;
2342242e0b43SKatayama Hirofumi MZ 
2343242e0b43SKatayama Hirofumi MZ     if (!IS_IMM_MODE() || (pImeWnd->state2 & WNDS2_INDESTROY))
2344242e0b43SKatayama Hirofumi MZ         return;
2345242e0b43SKatayama Hirofumi MZ 
2346242e0b43SKatayama Hirofumi MZ     pti = PsGetCurrentThreadWin32Thread();
2347242e0b43SKatayama Hirofumi MZ     ptiIME = pImeWnd->head.pti;
2348242e0b43SKatayama Hirofumi MZ 
2349242e0b43SKatayama Hirofumi MZ     // Attach to the process if necessary
2350242e0b43SKatayama Hirofumi MZ     if (pti != ptiIME)
2351242e0b43SKatayama Hirofumi MZ         KeAttachProcess(&(ptiIME->ppi->peProcess->Pcb));
2352242e0b43SKatayama Hirofumi MZ 
2353242e0b43SKatayama Hirofumi MZ     // Get an IMEUI and check whether hwndIMC is valid and update fShowStatus
2354242e0b43SKatayama Hirofumi MZ     _SEH2_TRY
2355242e0b43SKatayama Hirofumi MZ     {
2356242e0b43SKatayama Hirofumi MZ         ProbeForWrite(pImeWnd, sizeof(IMEWND), 1);
2357242e0b43SKatayama Hirofumi MZ         pimeui = ((PIMEWND)pImeWnd)->pimeui;
2358242e0b43SKatayama Hirofumi MZ         SafeImeUI = *pimeui;
2359242e0b43SKatayama Hirofumi MZ 
2360242e0b43SKatayama Hirofumi MZ         bShow = (gfIMEShowStatus == TRUE) && SafeImeUI.fCtrlShowStatus;
2361242e0b43SKatayama Hirofumi MZ 
2362242e0b43SKatayama Hirofumi MZ         pWnd = ValidateHwndNoErr(SafeImeUI.hwndIMC);
2363242e0b43SKatayama Hirofumi MZ         if (!pWnd)
2364242e0b43SKatayama Hirofumi MZ             pWnd = ptiIME->MessageQueue->spwndFocus;
2365242e0b43SKatayama Hirofumi MZ 
2366242e0b43SKatayama Hirofumi MZ         if (pWnd)
2367242e0b43SKatayama Hirofumi MZ         {
2368242e0b43SKatayama Hirofumi MZ             bSendNotify = TRUE;
2369242e0b43SKatayama Hirofumi MZ             pimeui->fShowStatus = bShow;
2370242e0b43SKatayama Hirofumi MZ         }
2371242e0b43SKatayama Hirofumi MZ     }
2372242e0b43SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2373242e0b43SKatayama Hirofumi MZ     {
23744ab7c93bSKatayama Hirofumi MZ         ERR("!!!\n");
23754ab7c93bSKatayama Hirofumi MZ 
2376242e0b43SKatayama Hirofumi MZ         if (pti != ptiIME)
2377242e0b43SKatayama Hirofumi MZ             KeDetachProcess();
23784ab7c93bSKatayama Hirofumi MZ 
23794ab7c93bSKatayama Hirofumi MZ         _SEH2_YIELD(return);
2380242e0b43SKatayama Hirofumi MZ     }
2381242e0b43SKatayama Hirofumi MZ     _SEH2_END;
2382242e0b43SKatayama Hirofumi MZ 
2383242e0b43SKatayama Hirofumi MZ     // Detach from the process if necessary
2384242e0b43SKatayama Hirofumi MZ     if (pti != ptiIME)
2385242e0b43SKatayama Hirofumi MZ         KeDetachProcess();
2386242e0b43SKatayama Hirofumi MZ 
2387242e0b43SKatayama Hirofumi MZ     if (bSendNotify)
2388242e0b43SKatayama Hirofumi MZ         IntSendOpenStatusNotify(ptiIME, &SafeImeUI, pWnd, bShow);
2389242e0b43SKatayama Hirofumi MZ 
2390242e0b43SKatayama Hirofumi MZ     if (!(pImeWnd->state2 & WNDS2_INDESTROY))
2391242e0b43SKatayama Hirofumi MZ         IntCheckImeShowStatus(pImeWnd, NULL);
2392242e0b43SKatayama Hirofumi MZ }
2393242e0b43SKatayama Hirofumi MZ 
2394242e0b43SKatayama Hirofumi MZ // Win: xxxBroadcastImeShowStatusChange
2395242e0b43SKatayama Hirofumi MZ BOOL FASTCALL IntBroadcastImeShowStatusChange(PWND pImeWnd, BOOL bShow)
2396242e0b43SKatayama Hirofumi MZ {
2397242e0b43SKatayama Hirofumi MZ     if (gfIMEShowStatus == bShow || !IS_IMM_MODE())
2398242e0b43SKatayama Hirofumi MZ         return TRUE;
2399242e0b43SKatayama Hirofumi MZ 
2400242e0b43SKatayama Hirofumi MZ     gfIMEShowStatus = bShow;
2401242e0b43SKatayama Hirofumi MZ     IntNotifyImeShowStatus(pImeWnd);
2402242e0b43SKatayama Hirofumi MZ     return TRUE;
2403242e0b43SKatayama Hirofumi MZ }
2404242e0b43SKatayama Hirofumi MZ 
24057cc89e52SKatayama Hirofumi MZ /* Win: xxxCheckImeShowStatusInThread */
24067cc89e52SKatayama Hirofumi MZ VOID FASTCALL IntCheckImeShowStatusInThread(PWND pImeWnd)
24077cc89e52SKatayama Hirofumi MZ {
24087cc89e52SKatayama Hirofumi MZ     if (IS_IMM_MODE() && !(pImeWnd->state2 & WNDS2_INDESTROY))
24097cc89e52SKatayama Hirofumi MZ         IntCheckImeShowStatus(pImeWnd, pImeWnd->head.pti);
24107cc89e52SKatayama Hirofumi MZ }
24117cc89e52SKatayama Hirofumi MZ 
2412c2c66affSColin Finck /* EOF */
2413