xref: /reactos/win32ss/user/ntuser/ime.c (revision 2ef605d4)
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;
449db44371SKatayama Hirofumi MZ 
455d5cc578SKatayama Hirofumi MZ typedef struct tagIMEHOTKEY
465d5cc578SKatayama Hirofumi MZ {
475d5cc578SKatayama Hirofumi MZ     struct tagIMEHOTKEY *pNext;
485d5cc578SKatayama Hirofumi MZ     DWORD  dwHotKeyId;
495d5cc578SKatayama Hirofumi MZ     UINT   uVirtualKey;
505d5cc578SKatayama Hirofumi MZ     UINT   uModifiers;
515d5cc578SKatayama Hirofumi MZ     HKL    hKL;
525d5cc578SKatayama Hirofumi MZ } IMEHOTKEY, *PIMEHOTKEY;
535d5cc578SKatayama Hirofumi MZ 
545df5ef2bSKatayama Hirofumi MZ PIMEHOTKEY gpImeHotKeyList = NULL; // Win: gpImeHotKeyListHeader
555df5ef2bSKatayama Hirofumi MZ LCID glcidSystem = 0; // Win: glcidSystem
56bbe5fd52SKatayama Hirofumi MZ 
575df5ef2bSKatayama Hirofumi MZ // Win: GetAppImeCompatFlags
58b5c9d532SKatayama Hirofumi MZ DWORD FASTCALL IntGetImeCompatFlags(PTHREADINFO pti)
59b5c9d532SKatayama Hirofumi MZ {
60b5c9d532SKatayama Hirofumi MZ     if (!pti)
61b5c9d532SKatayama Hirofumi MZ         pti = PsGetCurrentThreadWin32Thread();
62b5c9d532SKatayama Hirofumi MZ 
63b5c9d532SKatayama Hirofumi MZ     return pti->ppi->dwImeCompatFlags;
64b5c9d532SKatayama Hirofumi MZ }
65b5c9d532SKatayama Hirofumi MZ 
665df5ef2bSKatayama Hirofumi MZ // Win: GetLangIdMatchLevel
67bbe5fd52SKatayama Hirofumi MZ UINT FASTCALL IntGetImeHotKeyLanguageScore(HKL hKL, LANGID HotKeyLangId)
68bbe5fd52SKatayama Hirofumi MZ {
69bbe5fd52SKatayama Hirofumi MZ     LCID lcid;
70bbe5fd52SKatayama Hirofumi MZ 
71bbe5fd52SKatayama Hirofumi MZ     if (HotKeyLangId == LANGID_NEUTRAL || HotKeyLangId == LOWORD(hKL))
72bbe5fd52SKatayama Hirofumi MZ         return 3;
73bbe5fd52SKatayama Hirofumi MZ 
74bbe5fd52SKatayama Hirofumi MZ     _SEH2_TRY
75bbe5fd52SKatayama Hirofumi MZ     {
76bbe5fd52SKatayama Hirofumi MZ         lcid = NtCurrentTeb()->CurrentLocale;
77bbe5fd52SKatayama Hirofumi MZ     }
78bbe5fd52SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
79bbe5fd52SKatayama Hirofumi MZ     {
80bbe5fd52SKatayama Hirofumi MZ         lcid = MAKELCID(LANGID_NEUTRAL, SORT_DEFAULT);
81bbe5fd52SKatayama Hirofumi MZ     }
82bbe5fd52SKatayama Hirofumi MZ     _SEH2_END;
83bbe5fd52SKatayama Hirofumi MZ 
84bbe5fd52SKatayama Hirofumi MZ     if (HotKeyLangId == LANGIDFROMLCID(lcid))
85bbe5fd52SKatayama Hirofumi MZ         return 2;
86bbe5fd52SKatayama Hirofumi MZ 
875df5ef2bSKatayama Hirofumi MZ     if (glcidSystem == 0)
885df5ef2bSKatayama Hirofumi MZ         ZwQueryDefaultLocale(FALSE, &glcidSystem);
89bbe5fd52SKatayama Hirofumi MZ 
905df5ef2bSKatayama Hirofumi MZ     if (HotKeyLangId == LANGIDFROMLCID(glcidSystem))
91bbe5fd52SKatayama Hirofumi MZ         return 1;
92bbe5fd52SKatayama Hirofumi MZ 
93bbe5fd52SKatayama Hirofumi MZ     return 0;
94bbe5fd52SKatayama Hirofumi MZ }
95bbe5fd52SKatayama Hirofumi MZ 
965df5ef2bSKatayama Hirofumi MZ // Win: GetActiveHKL
97bbe5fd52SKatayama Hirofumi MZ HKL FASTCALL IntGetActiveKeyboardLayout(VOID)
98bbe5fd52SKatayama Hirofumi MZ {
99bbe5fd52SKatayama Hirofumi MZ     PTHREADINFO pti;
100bbe5fd52SKatayama Hirofumi MZ 
101bbe5fd52SKatayama Hirofumi MZ     if (gpqForeground && gpqForeground->spwndActive)
102bbe5fd52SKatayama Hirofumi MZ     {
103bbe5fd52SKatayama Hirofumi MZ         pti = gpqForeground->spwndActive->head.pti;
104bbe5fd52SKatayama Hirofumi MZ         if (pti && pti->KeyboardLayout)
105bbe5fd52SKatayama Hirofumi MZ             return pti->KeyboardLayout->hkl;
106bbe5fd52SKatayama Hirofumi MZ     }
107bbe5fd52SKatayama Hirofumi MZ 
108bbe5fd52SKatayama Hirofumi MZ     return UserGetKeyboardLayout(0);
109bbe5fd52SKatayama Hirofumi MZ }
1105d5cc578SKatayama Hirofumi MZ 
1115df5ef2bSKatayama Hirofumi MZ // Win: GetHotKeyLangID
1125d5cc578SKatayama Hirofumi MZ static LANGID FASTCALL IntGetImeHotKeyLangId(DWORD dwHotKeyId)
1135d5cc578SKatayama Hirofumi MZ {
1145d5cc578SKatayama Hirofumi MZ #define IME_CHOTKEY 0x10
1155d5cc578SKatayama Hirofumi MZ #define IME_JHOTKEY 0x30
1165d5cc578SKatayama Hirofumi MZ #define IME_KHOTKEY 0x50
1175d5cc578SKatayama Hirofumi MZ #define IME_THOTKEY 0x70
1185d5cc578SKatayama Hirofumi MZ #define IME_XHOTKEY 0x90
1195d5cc578SKatayama Hirofumi MZ     static const LANGID s_array[] =
1205d5cc578SKatayama Hirofumi MZ     {
1215d5cc578SKatayama Hirofumi MZ         /* 0x00 */ (WORD)-1,
1225d5cc578SKatayama Hirofumi MZ         /* 0x10 */ LANGID_CHINESE_SIMPLIFIED,
1235d5cc578SKatayama Hirofumi MZ         /* 0x20 */ LANGID_CHINESE_SIMPLIFIED,
1245d5cc578SKatayama Hirofumi MZ         /* 0x30 */ LANGID_JAPANESE,
1255d5cc578SKatayama Hirofumi MZ         /* 0x40 */ LANGID_JAPANESE,
1265d5cc578SKatayama Hirofumi MZ         /* 0x50 */ LANGID_KOREAN,
1275d5cc578SKatayama Hirofumi MZ         /* 0x60 */ LANGID_KOREAN,
1285d5cc578SKatayama Hirofumi MZ         /* 0x70 */ LANGID_CHINESE_TRADITIONAL,
1295d5cc578SKatayama Hirofumi MZ         /* 0x80 */ LANGID_CHINESE_TRADITIONAL
1305d5cc578SKatayama Hirofumi MZ     };
1315d5cc578SKatayama Hirofumi MZ 
1325d5cc578SKatayama Hirofumi MZ     if (IME_CHOTKEY <= dwHotKeyId && dwHotKeyId < IME_XHOTKEY)
1335d5cc578SKatayama Hirofumi MZ         return s_array[(dwHotKeyId & 0xF0) >> 4];
1345d5cc578SKatayama Hirofumi MZ     return LANGID_NEUTRAL;
1355d5cc578SKatayama Hirofumi MZ }
1365d5cc578SKatayama Hirofumi MZ 
1372f7775c6SKatayama Hirofumi MZ // Win: AddImeHotKey
1385d5cc578SKatayama Hirofumi MZ static VOID FASTCALL IntAddImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
1395d5cc578SKatayama Hirofumi MZ {
1405d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
1415d5cc578SKatayama Hirofumi MZ 
1425d5cc578SKatayama Hirofumi MZ     if (!*ppList)
1435d5cc578SKatayama Hirofumi MZ     {
1445d5cc578SKatayama Hirofumi MZ         *ppList = pHotKey;
1455d5cc578SKatayama Hirofumi MZ         return;
1465d5cc578SKatayama Hirofumi MZ     }
1475d5cc578SKatayama Hirofumi MZ 
1485d5cc578SKatayama Hirofumi MZ     for (pNode = *ppList; pNode; pNode = pNode->pNext)
1495d5cc578SKatayama Hirofumi MZ     {
1505d5cc578SKatayama Hirofumi MZ         if (!pNode->pNext)
1515d5cc578SKatayama Hirofumi MZ         {
1525d5cc578SKatayama Hirofumi MZ             pNode->pNext = pHotKey;
1535d5cc578SKatayama Hirofumi MZ             return;
1545d5cc578SKatayama Hirofumi MZ         }
1555d5cc578SKatayama Hirofumi MZ     }
1565d5cc578SKatayama Hirofumi MZ }
1575d5cc578SKatayama Hirofumi MZ 
1585df5ef2bSKatayama Hirofumi MZ // Win: FindImeHotKeyByID
1595d5cc578SKatayama Hirofumi MZ static PIMEHOTKEY FASTCALL IntGetImeHotKeyById(PIMEHOTKEY pList, DWORD dwHotKeyId)
1605d5cc578SKatayama Hirofumi MZ {
1615d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
1625d5cc578SKatayama Hirofumi MZ     for (pNode = pList; pNode; pNode = pNode->pNext)
1635d5cc578SKatayama Hirofumi MZ     {
1645d5cc578SKatayama Hirofumi MZ         if (pNode->dwHotKeyId == dwHotKeyId)
1655d5cc578SKatayama Hirofumi MZ             return pNode;
1665d5cc578SKatayama Hirofumi MZ     }
1675d5cc578SKatayama Hirofumi MZ     return NULL;
1685d5cc578SKatayama Hirofumi MZ }
1695d5cc578SKatayama Hirofumi MZ 
1705df5ef2bSKatayama Hirofumi MZ // Win: FindImeHotKeyByKeyWithLang
1715d5cc578SKatayama Hirofumi MZ static PIMEHOTKEY APIENTRY
1725d5cc578SKatayama Hirofumi MZ IntGetImeHotKeyByKeyAndLang(PIMEHOTKEY pList, UINT uModKeys, UINT uLeftRight,
1735d5cc578SKatayama Hirofumi MZ                             UINT uVirtualKey, LANGID TargetLangId)
1745d5cc578SKatayama Hirofumi MZ {
1755d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
1765d5cc578SKatayama Hirofumi MZ     LANGID LangID;
1775d5cc578SKatayama Hirofumi MZ     UINT uModifiers;
1785d5cc578SKatayama Hirofumi MZ 
1795d5cc578SKatayama Hirofumi MZ     for (pNode = pList; pNode; pNode = pNode->pNext)
1805d5cc578SKatayama Hirofumi MZ     {
1815d5cc578SKatayama Hirofumi MZ         if (pNode->uVirtualKey != uVirtualKey)
1825d5cc578SKatayama Hirofumi MZ             continue;
1835d5cc578SKatayama Hirofumi MZ 
1845d5cc578SKatayama Hirofumi MZ         LangID = IntGetImeHotKeyLangId(pNode->dwHotKeyId);
1855d5cc578SKatayama Hirofumi MZ         if (LangID != TargetLangId)
1865d5cc578SKatayama Hirofumi MZ             continue;
1875d5cc578SKatayama Hirofumi MZ 
1885d5cc578SKatayama Hirofumi MZ         uModifiers = pNode->uModifiers;
1895d5cc578SKatayama Hirofumi MZ         if (uModifiers & MOD_IGNORE_ALL_MODIFIER)
1905d5cc578SKatayama Hirofumi MZ             return pNode;
1915d5cc578SKatayama Hirofumi MZ 
1925d5cc578SKatayama Hirofumi MZ         if ((uModifiers & MOD_KEYS) != uModKeys)
1935d5cc578SKatayama Hirofumi MZ             continue;
1945d5cc578SKatayama Hirofumi MZ 
1955d5cc578SKatayama Hirofumi MZ         if ((uModifiers & uLeftRight) || (uModifiers & MOD_LEFT_RIGHT) == uLeftRight)
1965d5cc578SKatayama Hirofumi MZ             return pNode;
1975d5cc578SKatayama Hirofumi MZ     }
1985d5cc578SKatayama Hirofumi MZ 
1995d5cc578SKatayama Hirofumi MZ     return NULL;
2005d5cc578SKatayama Hirofumi MZ }
2015d5cc578SKatayama Hirofumi MZ 
2025df5ef2bSKatayama Hirofumi MZ // Win: DeleteImeHotKey
2035d5cc578SKatayama Hirofumi MZ static VOID FASTCALL IntDeleteImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
2045d5cc578SKatayama Hirofumi MZ {
2055d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
2065d5cc578SKatayama Hirofumi MZ 
2075d5cc578SKatayama Hirofumi MZ     if (*ppList == pHotKey)
2085d5cc578SKatayama Hirofumi MZ     {
2095d5cc578SKatayama Hirofumi MZ         *ppList = pHotKey->pNext;
2105d5cc578SKatayama Hirofumi MZ         ExFreePoolWithTag(pHotKey, USERTAG_IMEHOTKEY);
2115d5cc578SKatayama Hirofumi MZ         return;
2125d5cc578SKatayama Hirofumi MZ     }
2135d5cc578SKatayama Hirofumi MZ 
2145d5cc578SKatayama Hirofumi MZ     for (pNode = *ppList; pNode; pNode = pNode->pNext)
2155d5cc578SKatayama Hirofumi MZ     {
2165d5cc578SKatayama Hirofumi MZ         if (pNode->pNext == pHotKey)
2175d5cc578SKatayama Hirofumi MZ         {
2185d5cc578SKatayama Hirofumi MZ             pNode->pNext = pHotKey->pNext;
2195d5cc578SKatayama Hirofumi MZ             ExFreePoolWithTag(pHotKey, USERTAG_IMEHOTKEY);
2205d5cc578SKatayama Hirofumi MZ             return;
2215d5cc578SKatayama Hirofumi MZ         }
2225d5cc578SKatayama Hirofumi MZ     }
2235d5cc578SKatayama Hirofumi MZ }
2245d5cc578SKatayama Hirofumi MZ 
2255df5ef2bSKatayama Hirofumi MZ // Win: FindImeHotKeyByKey
226bbe5fd52SKatayama Hirofumi MZ PIMEHOTKEY
227bbe5fd52SKatayama Hirofumi MZ IntGetImeHotKeyByKey(PIMEHOTKEY pList, UINT uModKeys, UINT uLeftRight, UINT uVirtualKey)
228bbe5fd52SKatayama Hirofumi MZ {
229bbe5fd52SKatayama Hirofumi MZ     PIMEHOTKEY pNode, ret = NULL;
230bbe5fd52SKatayama Hirofumi MZ     PTHREADINFO pti = GetW32ThreadInfo();
231bbe5fd52SKatayama Hirofumi MZ     LANGID LangId;
232bbe5fd52SKatayama Hirofumi MZ     HKL hKL = IntGetActiveKeyboardLayout();
233bbe5fd52SKatayama Hirofumi MZ     BOOL fKorean = (PRIMARYLANGID(LOWORD(hKL)) == LANG_KOREAN);
234bbe5fd52SKatayama Hirofumi MZ     UINT nScore, nMaxScore = 0;
235bbe5fd52SKatayama Hirofumi MZ 
236bbe5fd52SKatayama Hirofumi MZ     for (pNode = pList; pNode; pNode = pNode->pNext)
237bbe5fd52SKatayama Hirofumi MZ     {
238bbe5fd52SKatayama Hirofumi MZ         if (pNode->uVirtualKey != uVirtualKey)
239bbe5fd52SKatayama Hirofumi MZ             continue;
240bbe5fd52SKatayama Hirofumi MZ 
241bbe5fd52SKatayama Hirofumi MZ         if ((pNode->uModifiers & MOD_IGNORE_ALL_MODIFIER))
242bbe5fd52SKatayama Hirofumi MZ         {
243bbe5fd52SKatayama Hirofumi MZ             ;
244bbe5fd52SKatayama Hirofumi MZ         }
245bbe5fd52SKatayama Hirofumi MZ         else if ((pNode->uModifiers & MOD_KEYS) != uModKeys)
246bbe5fd52SKatayama Hirofumi MZ         {
247bbe5fd52SKatayama Hirofumi MZ             continue;
248bbe5fd52SKatayama Hirofumi MZ         }
249bbe5fd52SKatayama Hirofumi MZ         else if ((pNode->uModifiers & uLeftRight) ||
250bbe5fd52SKatayama Hirofumi MZ                  (pNode->uModifiers & MOD_LEFT_RIGHT) == uLeftRight)
251bbe5fd52SKatayama Hirofumi MZ         {
252bbe5fd52SKatayama Hirofumi MZ             ;
253bbe5fd52SKatayama Hirofumi MZ         }
254bbe5fd52SKatayama Hirofumi MZ         else
255bbe5fd52SKatayama Hirofumi MZ         {
256bbe5fd52SKatayama Hirofumi MZ             continue;
257bbe5fd52SKatayama Hirofumi MZ         }
258bbe5fd52SKatayama Hirofumi MZ 
259bbe5fd52SKatayama Hirofumi MZ         LangId = IntGetImeHotKeyLangId(pNode->dwHotKeyId);
260bbe5fd52SKatayama Hirofumi MZ         nScore = IntGetImeHotKeyLanguageScore(hKL, LangId);
261bbe5fd52SKatayama Hirofumi MZ         if (nScore >= 3)
262bbe5fd52SKatayama Hirofumi MZ             return pNode;
263bbe5fd52SKatayama Hirofumi MZ 
264bbe5fd52SKatayama Hirofumi MZ         if (fKorean)
265bbe5fd52SKatayama Hirofumi MZ             continue;
266bbe5fd52SKatayama Hirofumi MZ 
267bbe5fd52SKatayama Hirofumi MZ         if (nScore == 0)
268bbe5fd52SKatayama Hirofumi MZ         {
269bbe5fd52SKatayama Hirofumi MZ             if (pNode->dwHotKeyId == IME_CHOTKEY_IME_NONIME_TOGGLE ||
270bbe5fd52SKatayama Hirofumi MZ                 pNode->dwHotKeyId == IME_THOTKEY_IME_NONIME_TOGGLE)
271bbe5fd52SKatayama Hirofumi MZ             {
272bbe5fd52SKatayama Hirofumi MZ                 if (LOWORD(pti->hklPrev) == LangId)
273bbe5fd52SKatayama Hirofumi MZ                     return pNode;
274bbe5fd52SKatayama Hirofumi MZ             }
275bbe5fd52SKatayama Hirofumi MZ         }
276bbe5fd52SKatayama Hirofumi MZ 
277bbe5fd52SKatayama Hirofumi MZ         if (nMaxScore < nScore)
278bbe5fd52SKatayama Hirofumi MZ         {
279bbe5fd52SKatayama Hirofumi MZ             nMaxScore = nScore;
280bbe5fd52SKatayama Hirofumi MZ             ret = pNode;
281bbe5fd52SKatayama Hirofumi MZ         }
282bbe5fd52SKatayama Hirofumi MZ     }
283bbe5fd52SKatayama Hirofumi MZ 
284bbe5fd52SKatayama Hirofumi MZ     return ret;
285bbe5fd52SKatayama Hirofumi MZ }
286bbe5fd52SKatayama Hirofumi MZ 
2872f7775c6SKatayama Hirofumi MZ // Win: CheckImeHotKey
288bbe5fd52SKatayama Hirofumi MZ PIMEHOTKEY IntCheckImeHotKey(PUSER_MESSAGE_QUEUE MessageQueue, UINT uVirtualKey, LPARAM lParam)
289bbe5fd52SKatayama Hirofumi MZ {
290bbe5fd52SKatayama Hirofumi MZ     PIMEHOTKEY pHotKey;
291bbe5fd52SKatayama Hirofumi MZ     UINT uModifiers;
292bbe5fd52SKatayama Hirofumi MZ     BOOL bKeyUp = (lParam & 0x80000000);
293bbe5fd52SKatayama Hirofumi MZ     const BYTE *KeyState = MessageQueue->afKeyState;
294bbe5fd52SKatayama Hirofumi MZ     static UINT s_uKeyUpVKey = 0;
295bbe5fd52SKatayama Hirofumi MZ 
296bbe5fd52SKatayama Hirofumi MZ     if (bKeyUp)
297bbe5fd52SKatayama Hirofumi MZ     {
298bbe5fd52SKatayama Hirofumi MZ         if (s_uKeyUpVKey != uVirtualKey)
299bbe5fd52SKatayama Hirofumi MZ         {
300bbe5fd52SKatayama Hirofumi MZ             s_uKeyUpVKey = 0;
301bbe5fd52SKatayama Hirofumi MZ             return NULL;
302bbe5fd52SKatayama Hirofumi MZ         }
303bbe5fd52SKatayama Hirofumi MZ 
304bbe5fd52SKatayama Hirofumi MZ         s_uKeyUpVKey = 0;
305bbe5fd52SKatayama Hirofumi MZ     }
306bbe5fd52SKatayama Hirofumi MZ 
307bbe5fd52SKatayama Hirofumi MZ     uModifiers = 0;
308bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_LSHIFT))   uModifiers |= (MOD_SHIFT | MOD_LEFT);
309bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_RSHIFT))   uModifiers |= (MOD_SHIFT | MOD_RIGHT);
310bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_LCONTROL)) uModifiers |= (MOD_CONTROL | MOD_LEFT);
311bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_RCONTROL)) uModifiers |= (MOD_CONTROL | MOD_RIGHT);
312bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_LMENU))    uModifiers |= (MOD_ALT | MOD_LEFT);
313bbe5fd52SKatayama Hirofumi MZ     if (IS_KEY_DOWN(KeyState, VK_RMENU))    uModifiers |= (MOD_ALT | MOD_RIGHT);
314bbe5fd52SKatayama Hirofumi MZ 
315bbe5fd52SKatayama Hirofumi MZ     pHotKey = IntGetImeHotKeyByKey(gpImeHotKeyList,
316bbe5fd52SKatayama Hirofumi MZ                                    (uModifiers & MOD_KEYS),
317bbe5fd52SKatayama Hirofumi MZ                                    (uModifiers & MOD_LEFT_RIGHT),
318bbe5fd52SKatayama Hirofumi MZ                                    uVirtualKey);
319bbe5fd52SKatayama Hirofumi MZ     if (pHotKey)
320bbe5fd52SKatayama Hirofumi MZ     {
321bbe5fd52SKatayama Hirofumi MZ         if (bKeyUp)
322bbe5fd52SKatayama Hirofumi MZ         {
323bbe5fd52SKatayama Hirofumi MZ             if (pHotKey->uModifiers & MOD_ON_KEYUP)
324bbe5fd52SKatayama Hirofumi MZ                 return pHotKey;
325bbe5fd52SKatayama Hirofumi MZ         }
326bbe5fd52SKatayama Hirofumi MZ         else
327bbe5fd52SKatayama Hirofumi MZ         {
328bbe5fd52SKatayama Hirofumi MZ             if (pHotKey->uModifiers & MOD_ON_KEYUP)
329bbe5fd52SKatayama Hirofumi MZ                 s_uKeyUpVKey = uVirtualKey;
330bbe5fd52SKatayama Hirofumi MZ             else
331bbe5fd52SKatayama Hirofumi MZ                 return pHotKey;
332bbe5fd52SKatayama Hirofumi MZ         }
333bbe5fd52SKatayama Hirofumi MZ     }
334bbe5fd52SKatayama Hirofumi MZ 
335bbe5fd52SKatayama Hirofumi MZ     return NULL;
336bbe5fd52SKatayama Hirofumi MZ }
337bbe5fd52SKatayama Hirofumi MZ 
3382f7775c6SKatayama Hirofumi MZ // Win: FreeImeHotKeys
3395d5cc578SKatayama Hirofumi MZ VOID FASTCALL IntFreeImeHotKeys(VOID)
3405d5cc578SKatayama Hirofumi MZ {
3415d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode, pNext;
3425d5cc578SKatayama Hirofumi MZ     for (pNode = gpImeHotKeyList; pNode; pNode = pNext)
3435d5cc578SKatayama Hirofumi MZ     {
3445d5cc578SKatayama Hirofumi MZ         pNext = pNode->pNext;
3455d5cc578SKatayama Hirofumi MZ         ExFreePoolWithTag(pNode, USERTAG_IMEHOTKEY);
3465d5cc578SKatayama Hirofumi MZ     }
3475d5cc578SKatayama Hirofumi MZ     gpImeHotKeyList = NULL;
3485d5cc578SKatayama Hirofumi MZ }
3495d5cc578SKatayama Hirofumi MZ 
3502f7775c6SKatayama Hirofumi MZ // Win: SetImeHotKey
3515d5cc578SKatayama Hirofumi MZ static BOOL APIENTRY
3525d5cc578SKatayama Hirofumi MZ IntSetImeHotKey(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DWORD dwAction)
3535d5cc578SKatayama Hirofumi MZ {
3545d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
3555d5cc578SKatayama Hirofumi MZ     LANGID LangId;
3565d5cc578SKatayama Hirofumi MZ 
3575d5cc578SKatayama Hirofumi MZ     switch (dwAction)
3585d5cc578SKatayama Hirofumi MZ     {
3595d5cc578SKatayama Hirofumi MZ         case SETIMEHOTKEY_DELETE:
3605d5cc578SKatayama Hirofumi MZ             pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
3615d5cc578SKatayama Hirofumi MZ             if (!pNode)
362b5c9d532SKatayama Hirofumi MZ             {
363b5c9d532SKatayama Hirofumi MZ                 ERR("dwHotKeyId: 0x%lX\n", dwHotKeyId);
3645d5cc578SKatayama Hirofumi MZ                 return FALSE;
365b5c9d532SKatayama Hirofumi MZ             }
3665d5cc578SKatayama Hirofumi MZ 
3675d5cc578SKatayama Hirofumi MZ             IntDeleteImeHotKey(&gpImeHotKeyList, pNode);
3685d5cc578SKatayama Hirofumi MZ             return TRUE;
3695d5cc578SKatayama Hirofumi MZ 
3705d5cc578SKatayama Hirofumi MZ         case SETIMEHOTKEY_ADD:
3715d5cc578SKatayama Hirofumi MZ             if (uVirtualKey == VK_PACKET)
3725d5cc578SKatayama Hirofumi MZ                 return FALSE;
3735d5cc578SKatayama Hirofumi MZ 
3745d5cc578SKatayama Hirofumi MZ             LangId = IntGetImeHotKeyLangId(dwHotKeyId);
3755d5cc578SKatayama Hirofumi MZ             if (LangId == LANGID_KOREAN)
3765d5cc578SKatayama Hirofumi MZ                 return FALSE;
3775d5cc578SKatayama Hirofumi MZ 
3785d5cc578SKatayama Hirofumi MZ             pNode = IntGetImeHotKeyByKeyAndLang(gpImeHotKeyList,
3795d5cc578SKatayama Hirofumi MZ                                                 (uModifiers & MOD_KEYS),
3805d5cc578SKatayama Hirofumi MZ                                                 (uModifiers & MOD_LEFT_RIGHT),
3815d5cc578SKatayama Hirofumi MZ                                                 uVirtualKey, LangId);
3825d5cc578SKatayama Hirofumi MZ             if (!pNode)
3835d5cc578SKatayama Hirofumi MZ                 pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
3845d5cc578SKatayama Hirofumi MZ 
3855d5cc578SKatayama Hirofumi MZ             if (pNode)
3865d5cc578SKatayama Hirofumi MZ             {
3875d5cc578SKatayama Hirofumi MZ                 pNode->uModifiers = uModifiers;
3885d5cc578SKatayama Hirofumi MZ                 pNode->uVirtualKey = uVirtualKey;
3895d5cc578SKatayama Hirofumi MZ                 pNode->hKL = hKL;
3905d5cc578SKatayama Hirofumi MZ                 return TRUE;
3915d5cc578SKatayama Hirofumi MZ             }
3925d5cc578SKatayama Hirofumi MZ 
3935d5cc578SKatayama Hirofumi MZ             pNode = ExAllocatePoolWithTag(PagedPool, sizeof(IMEHOTKEY), USERTAG_IMEHOTKEY);
3945d5cc578SKatayama Hirofumi MZ             if (!pNode)
3955d5cc578SKatayama Hirofumi MZ                 return FALSE;
3965d5cc578SKatayama Hirofumi MZ 
3975d5cc578SKatayama Hirofumi MZ             pNode->pNext = NULL;
3985d5cc578SKatayama Hirofumi MZ             pNode->dwHotKeyId = dwHotKeyId;
3995d5cc578SKatayama Hirofumi MZ             pNode->uModifiers = uModifiers;
4005d5cc578SKatayama Hirofumi MZ             pNode->uVirtualKey = uVirtualKey;
4015d5cc578SKatayama Hirofumi MZ             pNode->hKL = hKL;
4025d5cc578SKatayama Hirofumi MZ             IntAddImeHotKey(&gpImeHotKeyList, pNode);
4035d5cc578SKatayama Hirofumi MZ             return TRUE;
4045d5cc578SKatayama Hirofumi MZ 
4055d5cc578SKatayama Hirofumi MZ         case SETIMEHOTKEY_DELETEALL:
4065d5cc578SKatayama Hirofumi MZ             IntFreeImeHotKeys();
4075d5cc578SKatayama Hirofumi MZ             return TRUE;
4085d5cc578SKatayama Hirofumi MZ 
4095d5cc578SKatayama Hirofumi MZ         default:
4105d5cc578SKatayama Hirofumi MZ             return FALSE;
4115d5cc578SKatayama Hirofumi MZ     }
4125d5cc578SKatayama Hirofumi MZ }
4135d5cc578SKatayama Hirofumi MZ 
4145d5cc578SKatayama Hirofumi MZ BOOL NTAPI
4155d5cc578SKatayama Hirofumi MZ NtUserGetImeHotKey(DWORD dwHotKeyId, LPUINT lpuModifiers, LPUINT lpuVirtualKey, LPHKL lphKL)
4165d5cc578SKatayama Hirofumi MZ {
4175d5cc578SKatayama Hirofumi MZ     PIMEHOTKEY pNode = NULL;
4185d5cc578SKatayama Hirofumi MZ 
4195d5cc578SKatayama Hirofumi MZ     UserEnterExclusive();
4205d5cc578SKatayama Hirofumi MZ 
4215d5cc578SKatayama Hirofumi MZ     _SEH2_TRY
4225d5cc578SKatayama Hirofumi MZ     {
4235d5cc578SKatayama Hirofumi MZ         ProbeForWrite(lpuModifiers, sizeof(UINT), 1);
4245d5cc578SKatayama Hirofumi MZ         ProbeForWrite(lpuVirtualKey, sizeof(UINT), 1);
4255d5cc578SKatayama Hirofumi MZ         if (lphKL)
4265d5cc578SKatayama Hirofumi MZ             ProbeForWrite(lphKL, sizeof(HKL), 1);
4275d5cc578SKatayama Hirofumi MZ     }
4285d5cc578SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4295d5cc578SKatayama Hirofumi MZ     {
4305d5cc578SKatayama Hirofumi MZ         goto Quit;
4315d5cc578SKatayama Hirofumi MZ     }
4325d5cc578SKatayama Hirofumi MZ     _SEH2_END;
4335d5cc578SKatayama Hirofumi MZ 
4345d5cc578SKatayama Hirofumi MZ     pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
4355d5cc578SKatayama Hirofumi MZ     if (!pNode)
4365d5cc578SKatayama Hirofumi MZ         goto Quit;
4375d5cc578SKatayama Hirofumi MZ 
4385d5cc578SKatayama Hirofumi MZ     _SEH2_TRY
4395d5cc578SKatayama Hirofumi MZ     {
4405d5cc578SKatayama Hirofumi MZ         *lpuModifiers = pNode->uModifiers;
4415d5cc578SKatayama Hirofumi MZ         *lpuVirtualKey = pNode->uVirtualKey;
4425d5cc578SKatayama Hirofumi MZ         if (lphKL)
4435d5cc578SKatayama Hirofumi MZ             *lphKL = pNode->hKL;
4445d5cc578SKatayama Hirofumi MZ     }
4455d5cc578SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4465d5cc578SKatayama Hirofumi MZ     {
4475d5cc578SKatayama Hirofumi MZ         pNode = NULL;
4485d5cc578SKatayama Hirofumi MZ     }
4495d5cc578SKatayama Hirofumi MZ     _SEH2_END;
4505d5cc578SKatayama Hirofumi MZ 
4515d5cc578SKatayama Hirofumi MZ Quit:
4525d5cc578SKatayama Hirofumi MZ     UserLeave();
4535d5cc578SKatayama Hirofumi MZ     return !!pNode;
4545d5cc578SKatayama Hirofumi MZ }
4555d5cc578SKatayama Hirofumi MZ 
4565d5cc578SKatayama Hirofumi MZ BOOL
4575d5cc578SKatayama Hirofumi MZ NTAPI
4585d5cc578SKatayama Hirofumi MZ NtUserSetImeHotKey(
4595d5cc578SKatayama Hirofumi MZ     DWORD  dwHotKeyId,
4605d5cc578SKatayama Hirofumi MZ     UINT   uModifiers,
4615d5cc578SKatayama Hirofumi MZ     UINT   uVirtualKey,
4625d5cc578SKatayama Hirofumi MZ     HKL    hKL,
4635d5cc578SKatayama Hirofumi MZ     DWORD  dwAction)
4645d5cc578SKatayama Hirofumi MZ {
4655d5cc578SKatayama Hirofumi MZ     BOOL ret;
4665d5cc578SKatayama Hirofumi MZ     UserEnterExclusive();
4675d5cc578SKatayama Hirofumi MZ     ret = IntSetImeHotKey(dwHotKeyId, uModifiers, uVirtualKey, hKL, dwAction);
4685d5cc578SKatayama Hirofumi MZ     UserLeave();
4695d5cc578SKatayama Hirofumi MZ     return ret;
4705d5cc578SKatayama Hirofumi MZ }
4715d5cc578SKatayama Hirofumi MZ 
472bbe5fd52SKatayama Hirofumi MZ DWORD
473bbe5fd52SKatayama Hirofumi MZ NTAPI
474bbe5fd52SKatayama Hirofumi MZ NtUserCheckImeHotKey(UINT uVirtualKey, LPARAM lParam)
475bbe5fd52SKatayama Hirofumi MZ {
476bbe5fd52SKatayama Hirofumi MZ     PIMEHOTKEY pNode;
477bbe5fd52SKatayama Hirofumi MZ     DWORD ret = INVALID_HOTKEY;
478bbe5fd52SKatayama Hirofumi MZ 
479bbe5fd52SKatayama Hirofumi MZ     UserEnterExclusive();
480bbe5fd52SKatayama Hirofumi MZ 
481bbe5fd52SKatayama Hirofumi MZ     if (!gpqForeground || !IS_IMM_MODE())
482bbe5fd52SKatayama Hirofumi MZ         goto Quit;
483bbe5fd52SKatayama Hirofumi MZ 
484bbe5fd52SKatayama Hirofumi MZ     pNode = IntCheckImeHotKey(gpqForeground, uVirtualKey, lParam);
485bbe5fd52SKatayama Hirofumi MZ     if (pNode)
486bbe5fd52SKatayama Hirofumi MZ         ret = pNode->dwHotKeyId;
487bbe5fd52SKatayama Hirofumi MZ 
488bbe5fd52SKatayama Hirofumi MZ Quit:
489bbe5fd52SKatayama Hirofumi MZ     UserLeave();
490bbe5fd52SKatayama Hirofumi MZ     return ret;
491bbe5fd52SKatayama Hirofumi MZ }
492bbe5fd52SKatayama Hirofumi MZ 
4935df5ef2bSKatayama Hirofumi MZ // Win: GetTopLevelWindow
4940519ae0aSKatayama Hirofumi MZ PWND FASTCALL IntGetTopLevelWindow(PWND pwnd)
4950519ae0aSKatayama Hirofumi MZ {
4960519ae0aSKatayama Hirofumi MZ     if (!pwnd)
4970519ae0aSKatayama Hirofumi MZ         return NULL;
4980519ae0aSKatayama Hirofumi MZ 
4990519ae0aSKatayama Hirofumi MZ     while (pwnd->style & WS_CHILD)
5000519ae0aSKatayama Hirofumi MZ         pwnd = pwnd->spwndParent;
5010519ae0aSKatayama Hirofumi MZ 
5020519ae0aSKatayama Hirofumi MZ     return pwnd;
5030519ae0aSKatayama Hirofumi MZ }
5040519ae0aSKatayama Hirofumi MZ 
5052f7775c6SKatayama Hirofumi MZ // Win: AssociateInputContext
5061bc9dda5SKatayama Hirofumi MZ HIMC FASTCALL IntAssociateInputContext(PWND pWnd, PIMC pImc)
5071bc9dda5SKatayama Hirofumi MZ {
5081bc9dda5SKatayama Hirofumi MZ     HIMC hOldImc = pWnd->hImc;
5091bc9dda5SKatayama Hirofumi MZ     pWnd->hImc = (pImc ? UserHMGetHandle(pImc) : NULL);
5101bc9dda5SKatayama Hirofumi MZ     return hOldImc;
5111bc9dda5SKatayama Hirofumi MZ }
5121bc9dda5SKatayama Hirofumi MZ 
513470aa276SKatayama Hirofumi MZ DWORD
514e52ce89bSKatayama Hirofumi MZ NTAPI
515470aa276SKatayama Hirofumi MZ NtUserSetThreadLayoutHandles(HKL hNewKL, HKL hOldKL)
516470aa276SKatayama Hirofumi MZ {
517470aa276SKatayama Hirofumi MZ     PTHREADINFO pti;
518470aa276SKatayama Hirofumi MZ     PKL pOldKL, pNewKL;
519470aa276SKatayama Hirofumi MZ 
520470aa276SKatayama Hirofumi MZ     UserEnterExclusive();
521470aa276SKatayama Hirofumi MZ 
522470aa276SKatayama Hirofumi MZ     pti = GetW32ThreadInfo();
523470aa276SKatayama Hirofumi MZ     pOldKL = pti->KeyboardLayout;
524470aa276SKatayama Hirofumi MZ     if (pOldKL && pOldKL->hkl != hOldKL)
525470aa276SKatayama Hirofumi MZ         goto Quit;
526470aa276SKatayama Hirofumi MZ 
527470aa276SKatayama Hirofumi MZ     pNewKL = UserHklToKbl(hNewKL);
528470aa276SKatayama Hirofumi MZ     if (!pNewKL)
529470aa276SKatayama Hirofumi MZ         goto Quit;
530470aa276SKatayama Hirofumi MZ 
531470aa276SKatayama Hirofumi MZ     if (IS_IME_HKL(hNewKL) != IS_IME_HKL(hOldKL))
532470aa276SKatayama Hirofumi MZ         pti->hklPrev = hOldKL;
533470aa276SKatayama Hirofumi MZ 
5345df5ef2bSKatayama Hirofumi MZ     UserAssignmentLock((PVOID*)&pti->KeyboardLayout, pNewKL);
535470aa276SKatayama Hirofumi MZ 
536470aa276SKatayama Hirofumi MZ Quit:
537470aa276SKatayama Hirofumi MZ     UserLeave();
538470aa276SKatayama Hirofumi MZ     return 0;
539470aa276SKatayama Hirofumi MZ }
540470aa276SKatayama Hirofumi MZ 
5412f7775c6SKatayama Hirofumi MZ // Win: BuildHimcList
542ce6da820SKatayama Hirofumi MZ DWORD FASTCALL UserBuildHimcList(PTHREADINFO pti, DWORD dwCount, HIMC *phList)
543ce6da820SKatayama Hirofumi MZ {
544ce6da820SKatayama Hirofumi MZ     PIMC pIMC;
545ce6da820SKatayama Hirofumi MZ     DWORD dwRealCount = 0;
546ce6da820SKatayama Hirofumi MZ 
547ce6da820SKatayama Hirofumi MZ     if (pti)
548ce6da820SKatayama Hirofumi MZ     {
549ce6da820SKatayama Hirofumi MZ         for (pIMC = pti->spDefaultImc; pIMC; pIMC = pIMC->pImcNext)
550ce6da820SKatayama Hirofumi MZ         {
551ce6da820SKatayama Hirofumi MZ             if (dwRealCount < dwCount)
552ce6da820SKatayama Hirofumi MZ                 phList[dwRealCount] = UserHMGetHandle(pIMC);
553ce6da820SKatayama Hirofumi MZ 
554ce6da820SKatayama Hirofumi MZ             ++dwRealCount;
555ce6da820SKatayama Hirofumi MZ         }
556ce6da820SKatayama Hirofumi MZ     }
557ce6da820SKatayama Hirofumi MZ     else
558ce6da820SKatayama Hirofumi MZ     {
559ce6da820SKatayama Hirofumi MZ         for (pti = GetW32ThreadInfo()->ppi->ptiList; pti; pti = pti->ptiSibling)
560ce6da820SKatayama Hirofumi MZ         {
561ce6da820SKatayama Hirofumi MZ             for (pIMC = pti->spDefaultImc; pIMC; pIMC = pIMC->pImcNext)
562ce6da820SKatayama Hirofumi MZ             {
563ce6da820SKatayama Hirofumi MZ                 if (dwRealCount < dwCount)
564ce6da820SKatayama Hirofumi MZ                     phList[dwRealCount] = UserHMGetHandle(pIMC);
565ce6da820SKatayama Hirofumi MZ 
566ce6da820SKatayama Hirofumi MZ                 ++dwRealCount;
567ce6da820SKatayama Hirofumi MZ             }
568ce6da820SKatayama Hirofumi MZ         }
569ce6da820SKatayama Hirofumi MZ     }
570ce6da820SKatayama Hirofumi MZ 
571ce6da820SKatayama Hirofumi MZ     return dwRealCount;
572ce6da820SKatayama Hirofumi MZ }
573ce6da820SKatayama Hirofumi MZ 
5745df5ef2bSKatayama Hirofumi MZ // Win: xxxImmProcessKey
575c2c66affSColin Finck UINT FASTCALL
576b5c9d532SKatayama Hirofumi MZ IntImmProcessKey(PUSER_MESSAGE_QUEUE MessageQueue, PWND pWnd, UINT uMsg,
577b5c9d532SKatayama Hirofumi MZ                  WPARAM wParam, LPARAM lParam)
578c2c66affSColin Finck {
579b5c9d532SKatayama Hirofumi MZ     UINT uVirtualKey, ret = 0;
580b5c9d532SKatayama Hirofumi MZ     DWORD dwHotKeyId;
581b5c9d532SKatayama Hirofumi MZ     PKL pKL;
582b5c9d532SKatayama Hirofumi MZ     PIMC pIMC = NULL;
583b5c9d532SKatayama Hirofumi MZ     PIMEHOTKEY pImeHotKey;
584b5c9d532SKatayama Hirofumi MZ     HKL hKL;
585b5c9d532SKatayama Hirofumi MZ     HWND hWnd;
586c2c66affSColin Finck 
587c2c66affSColin Finck     ASSERT_REFS_CO(pWnd);
588c2c66affSColin Finck 
589b5c9d532SKatayama Hirofumi MZ     switch (uMsg)
590c2c66affSColin Finck     {
591b5c9d532SKatayama Hirofumi MZ         case WM_KEYDOWN:
592b5c9d532SKatayama Hirofumi MZ         case WM_KEYUP:
593b5c9d532SKatayama Hirofumi MZ         case WM_SYSKEYDOWN:
594b5c9d532SKatayama Hirofumi MZ         case WM_SYSKEYUP:
595b5c9d532SKatayama Hirofumi MZ             break;
596b5c9d532SKatayama Hirofumi MZ 
597b5c9d532SKatayama Hirofumi MZ         default:
598c2c66affSColin Finck             return 0;
599c2c66affSColin Finck     }
600c2c66affSColin Finck 
601b5c9d532SKatayama Hirofumi MZ     hWnd = UserHMGetHandle(pWnd);
602b5c9d532SKatayama Hirofumi MZ     pKL = pWnd->head.pti->KeyboardLayout;
603b5c9d532SKatayama Hirofumi MZ     if (!pKL)
604b5c9d532SKatayama Hirofumi MZ         return 0;
605b5c9d532SKatayama Hirofumi MZ 
606b5c9d532SKatayama Hirofumi MZ     uVirtualKey = LOBYTE(wParam);
607b5c9d532SKatayama Hirofumi MZ     pImeHotKey = IntCheckImeHotKey(MessageQueue, uVirtualKey, lParam);
608b5c9d532SKatayama Hirofumi MZ     if (pImeHotKey)
609b5c9d532SKatayama Hirofumi MZ     {
610b5c9d532SKatayama Hirofumi MZ         dwHotKeyId = pImeHotKey->dwHotKeyId;
611b5c9d532SKatayama Hirofumi MZ         hKL = pImeHotKey->hKL;
612b5c9d532SKatayama Hirofumi MZ     }
613b5c9d532SKatayama Hirofumi MZ     else
614b5c9d532SKatayama Hirofumi MZ     {
615b5c9d532SKatayama Hirofumi MZ         dwHotKeyId = INVALID_HOTKEY;
616b5c9d532SKatayama Hirofumi MZ         hKL = NULL;
617b5c9d532SKatayama Hirofumi MZ     }
618b5c9d532SKatayama Hirofumi MZ 
619b5c9d532SKatayama Hirofumi MZ     if (IME_HOTKEY_DSWITCH_FIRST <= dwHotKeyId && dwHotKeyId <= IME_HOTKEY_DSWITCH_LAST)
620b5c9d532SKatayama Hirofumi MZ     {
621b5c9d532SKatayama Hirofumi MZ         if (pKL->hkl != hKL)
622b5c9d532SKatayama Hirofumi MZ         {
623b5c9d532SKatayama Hirofumi MZ             UserPostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST,
624b5c9d532SKatayama Hirofumi MZ                             ((pKL->dwFontSigs & gSystemFS) ? INPUTLANGCHANGE_SYSCHARSET : 0),
625b5c9d532SKatayama Hirofumi MZ                             (LPARAM)hKL);
626b5c9d532SKatayama Hirofumi MZ         }
627b5c9d532SKatayama Hirofumi MZ 
628b5c9d532SKatayama Hirofumi MZ         if (IntGetImeCompatFlags(pWnd->head.pti) & 0x800000)
629b5c9d532SKatayama Hirofumi MZ             return 0;
630b5c9d532SKatayama Hirofumi MZ 
631b5c9d532SKatayama Hirofumi MZ         return IPHK_HOTKEY;
632b5c9d532SKatayama Hirofumi MZ     }
633b5c9d532SKatayama Hirofumi MZ 
634b5c9d532SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
635b5c9d532SKatayama Hirofumi MZ         return 0;
636b5c9d532SKatayama Hirofumi MZ 
637b5c9d532SKatayama Hirofumi MZ     if (dwHotKeyId == INVALID_HOTKEY)
638b5c9d532SKatayama Hirofumi MZ     {
639b5c9d532SKatayama Hirofumi MZ         if (!pKL->piiex)
640b5c9d532SKatayama Hirofumi MZ             return 0;
641b5c9d532SKatayama Hirofumi MZ 
642b5c9d532SKatayama Hirofumi MZ         if (pWnd->hImc)
643b5c9d532SKatayama Hirofumi MZ             pIMC = UserGetObject(gHandleTable, pWnd->hImc, TYPE_INPUTCONTEXT);
644b5c9d532SKatayama Hirofumi MZ         if (!pIMC)
645b5c9d532SKatayama Hirofumi MZ             return 0;
646b5c9d532SKatayama Hirofumi MZ 
647b5c9d532SKatayama Hirofumi MZ         if ((lParam & 0x80000000) &&
648b5c9d532SKatayama Hirofumi MZ             (pKL->piiex->ImeInfo.fdwProperty & IME_PROP_IGNORE_UPKEYS))
649b5c9d532SKatayama Hirofumi MZ         {
650b5c9d532SKatayama Hirofumi MZ             return 0;
651b5c9d532SKatayama Hirofumi MZ         }
652b5c9d532SKatayama Hirofumi MZ 
653b5c9d532SKatayama Hirofumi MZ         switch (uVirtualKey)
654b5c9d532SKatayama Hirofumi MZ         {
655b5c9d532SKatayama Hirofumi MZ             case VK_DBE_CODEINPUT:
656b5c9d532SKatayama Hirofumi MZ             case VK_DBE_ENTERCONFIGMODE:
657b5c9d532SKatayama Hirofumi MZ             case VK_DBE_ENTERWORDREGISTERMODE:
658b5c9d532SKatayama Hirofumi MZ             case VK_DBE_HIRAGANA:
659b5c9d532SKatayama Hirofumi MZ             case VK_DBE_KATAKANA:
660b5c9d532SKatayama Hirofumi MZ             case VK_DBE_NOCODEINPUT:
661b5c9d532SKatayama Hirofumi MZ             case VK_DBE_NOROMAN:
662b5c9d532SKatayama Hirofumi MZ             case VK_DBE_ROMAN:
663b5c9d532SKatayama Hirofumi MZ                 break;
664b5c9d532SKatayama Hirofumi MZ 
665b5c9d532SKatayama Hirofumi MZ             default:
666b5c9d532SKatayama Hirofumi MZ             {
667b5c9d532SKatayama Hirofumi MZ                 if (uMsg == WM_SYSKEYDOWN || uMsg == WM_SYSKEYUP)
668b5c9d532SKatayama Hirofumi MZ                 {
669b5c9d532SKatayama Hirofumi MZ                     if (uVirtualKey != VK_MENU && uVirtualKey != VK_F10)
670b5c9d532SKatayama Hirofumi MZ                         return 0;
671b5c9d532SKatayama Hirofumi MZ                 }
672b5c9d532SKatayama Hirofumi MZ 
673b5c9d532SKatayama Hirofumi MZ                 if (!(pKL->piiex->ImeInfo.fdwProperty & IME_PROP_NEED_ALTKEY))
674b5c9d532SKatayama Hirofumi MZ                 {
675b5c9d532SKatayama Hirofumi MZ                     if (uVirtualKey == VK_MENU || (lParam & 0x20000000))
676b5c9d532SKatayama Hirofumi MZ                         return 0;
677b5c9d532SKatayama Hirofumi MZ                 }
678b5c9d532SKatayama Hirofumi MZ                 break;
679b5c9d532SKatayama Hirofumi MZ             }
680b5c9d532SKatayama Hirofumi MZ         }
681b5c9d532SKatayama Hirofumi MZ     }
682b5c9d532SKatayama Hirofumi MZ 
683b5c9d532SKatayama Hirofumi MZ     if (LOBYTE(uVirtualKey) == VK_PACKET)
684b5c9d532SKatayama Hirofumi MZ         uVirtualKey = MAKELONG(wParam, GetW32ThreadInfo()->wchInjected);
685b5c9d532SKatayama Hirofumi MZ 
686b5c9d532SKatayama Hirofumi MZ     ret = co_IntImmProcessKey(hWnd, pKL->hkl, uVirtualKey, lParam, dwHotKeyId);
687b5c9d532SKatayama Hirofumi MZ 
688b5c9d532SKatayama Hirofumi MZ     if (IntGetImeCompatFlags(pWnd->head.pti) & 0x800000)
689b5c9d532SKatayama Hirofumi MZ         ret &= ~IPHK_HOTKEY;
690b5c9d532SKatayama Hirofumi MZ 
691b5c9d532SKatayama Hirofumi MZ     return ret;
692b5c9d532SKatayama Hirofumi MZ }
693b5c9d532SKatayama Hirofumi MZ 
694ce6da820SKatayama Hirofumi MZ NTSTATUS
695e52ce89bSKatayama Hirofumi MZ NTAPI
696ce6da820SKatayama Hirofumi MZ NtUserBuildHimcList(DWORD dwThreadId, DWORD dwCount, HIMC *phList, LPDWORD pdwCount)
697ce6da820SKatayama Hirofumi MZ {
698ce6da820SKatayama Hirofumi MZ     NTSTATUS ret = STATUS_UNSUCCESSFUL;
699ce6da820SKatayama Hirofumi MZ     DWORD dwRealCount;
700ce6da820SKatayama Hirofumi MZ     PTHREADINFO pti;
701ce6da820SKatayama Hirofumi MZ 
702ce6da820SKatayama Hirofumi MZ     UserEnterExclusive();
703ce6da820SKatayama Hirofumi MZ 
704ce6da820SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
705ce6da820SKatayama Hirofumi MZ     {
706b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
707ce6da820SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
708ce6da820SKatayama Hirofumi MZ         goto Quit;
709ce6da820SKatayama Hirofumi MZ     }
710ce6da820SKatayama Hirofumi MZ 
711ce6da820SKatayama Hirofumi MZ     if (dwThreadId == 0)
712ce6da820SKatayama Hirofumi MZ     {
713ce6da820SKatayama Hirofumi MZ         pti = GetW32ThreadInfo();
714ce6da820SKatayama Hirofumi MZ     }
715ce6da820SKatayama Hirofumi MZ     else if (dwThreadId == INVALID_THREAD_ID)
716ce6da820SKatayama Hirofumi MZ     {
717ce6da820SKatayama Hirofumi MZ         pti = NULL;
718ce6da820SKatayama Hirofumi MZ     }
719ce6da820SKatayama Hirofumi MZ     else
720ce6da820SKatayama Hirofumi MZ     {
721ce6da820SKatayama Hirofumi MZ         pti = IntTID2PTI(UlongToHandle(dwThreadId));
722ce6da820SKatayama Hirofumi MZ         if (!pti || !pti->rpdesk)
723ce6da820SKatayama Hirofumi MZ             goto Quit;
724ce6da820SKatayama Hirofumi MZ     }
725ce6da820SKatayama Hirofumi MZ 
726ce6da820SKatayama Hirofumi MZ     _SEH2_TRY
727ce6da820SKatayama Hirofumi MZ     {
728ce6da820SKatayama Hirofumi MZ         ProbeForWrite(phList, dwCount * sizeof(HIMC), 1);
729ce6da820SKatayama Hirofumi MZ         ProbeForWrite(pdwCount, sizeof(DWORD), 1);
730ce6da820SKatayama Hirofumi MZ         *pdwCount = dwRealCount = UserBuildHimcList(pti, dwCount, phList);
731ce6da820SKatayama Hirofumi MZ     }
732ce6da820SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
733ce6da820SKatayama Hirofumi MZ     {
734ce6da820SKatayama Hirofumi MZ         goto Quit;
735ce6da820SKatayama Hirofumi MZ     }
736ce6da820SKatayama Hirofumi MZ     _SEH2_END;
737ce6da820SKatayama Hirofumi MZ 
738ce6da820SKatayama Hirofumi MZ     if (dwCount < dwRealCount)
739ce6da820SKatayama Hirofumi MZ         ret = STATUS_BUFFER_TOO_SMALL;
740ce6da820SKatayama Hirofumi MZ     else
741ce6da820SKatayama Hirofumi MZ         ret = STATUS_SUCCESS;
742ce6da820SKatayama Hirofumi MZ 
743ce6da820SKatayama Hirofumi MZ Quit:
744ce6da820SKatayama Hirofumi MZ     UserLeave();
745ce6da820SKatayama Hirofumi MZ     return ret;
746ce6da820SKatayama Hirofumi MZ }
747ce6da820SKatayama Hirofumi MZ 
7485df5ef2bSKatayama Hirofumi MZ // Win: SetConvMode
7499db44371SKatayama Hirofumi MZ static VOID FASTCALL UserSetImeConversionKeyState(PTHREADINFO pti, DWORD dwConversion)
7509db44371SKatayama Hirofumi MZ {
7519db44371SKatayama Hirofumi MZ     HKL hKL;
7529db44371SKatayama Hirofumi MZ     LANGID LangID;
7539db44371SKatayama Hirofumi MZ     LPBYTE KeyState;
7549db44371SKatayama Hirofumi MZ     BOOL bAlphaNumeric, bKatakana, bHiragana, bFullShape, bRoman, bCharCode;
7559db44371SKatayama Hirofumi MZ 
7569db44371SKatayama Hirofumi MZ     if (!pti->KeyboardLayout)
7579db44371SKatayama Hirofumi MZ         return;
7589db44371SKatayama Hirofumi MZ 
7599db44371SKatayama Hirofumi MZ     hKL = pti->KeyboardLayout->hkl;
7609db44371SKatayama Hirofumi MZ     LangID = LOWORD(hKL);
7619db44371SKatayama Hirofumi MZ     KeyState = pti->MessageQueue->afKeyState;
7629db44371SKatayama Hirofumi MZ 
7639db44371SKatayama Hirofumi MZ     switch (PRIMARYLANGID(LangID))
7649db44371SKatayama Hirofumi MZ     {
7659db44371SKatayama Hirofumi MZ         case LANG_JAPANESE:
7669db44371SKatayama Hirofumi MZ             bAlphaNumeric = !(dwConversion & IME_CMODE_NATIVE);
7679db44371SKatayama Hirofumi MZ             bKatakana = !bAlphaNumeric && (dwConversion & IME_CMODE_KATAKANA);
7689db44371SKatayama Hirofumi MZ             bHiragana = !bAlphaNumeric && !(dwConversion & IME_CMODE_KATAKANA);
7699db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_ALPHANUMERIC, bAlphaNumeric);
7709db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_ALPHANUMERIC, bAlphaNumeric);
7719db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_HIRAGANA, bHiragana);
7729db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_HIRAGANA, bHiragana);
7739db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_KATAKANA, bKatakana);
7749db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_KATAKANA, bKatakana);
7759db44371SKatayama Hirofumi MZ 
7769db44371SKatayama Hirofumi MZ             bFullShape = (dwConversion & IME_CMODE_FULLSHAPE);
7779db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_DBCSCHAR, bFullShape);
7789db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_DBCSCHAR, bFullShape);
7799db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_SBCSCHAR, !bFullShape);
7809db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_SBCSCHAR, !bFullShape);
7819db44371SKatayama Hirofumi MZ 
7829db44371SKatayama Hirofumi MZ             bRoman = (dwConversion & IME_CMODE_ROMAN);
7839db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_ROMAN, bRoman);
7849db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_ROMAN, bRoman);
7859db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_NOROMAN, !bRoman);
7869db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_NOROMAN, !bRoman);
7879db44371SKatayama Hirofumi MZ 
7889db44371SKatayama Hirofumi MZ             bCharCode = (dwConversion & IME_CMODE_CHARCODE);
7899db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_CODEINPUT, bCharCode);
7909db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_CODEINPUT, bCharCode);
7919db44371SKatayama Hirofumi MZ             SET_KEY_DOWN(KeyState, VK_DBE_NOCODEINPUT, !bCharCode);
7929db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_DBE_NOCODEINPUT, !bCharCode);
7939db44371SKatayama Hirofumi MZ             break;
7949db44371SKatayama Hirofumi MZ 
7959db44371SKatayama Hirofumi MZ         case LANG_KOREAN:
7969db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_HANGUL, (dwConversion & IME_CMODE_NATIVE));
7979db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_JUNJA, (dwConversion & IME_CMODE_FULLSHAPE));
7989db44371SKatayama Hirofumi MZ             SET_KEY_LOCKED(KeyState, VK_HANJA, (dwConversion & IME_CMODE_HANJACONVERT));
7999db44371SKatayama Hirofumi MZ             break;
8009db44371SKatayama Hirofumi MZ 
8019db44371SKatayama Hirofumi MZ         default:
8029db44371SKatayama Hirofumi MZ             break;
8039db44371SKatayama Hirofumi MZ     }
8049db44371SKatayama Hirofumi MZ }
8059db44371SKatayama Hirofumi MZ 
806c2c66affSColin Finck DWORD
807e52ce89bSKatayama Hirofumi MZ NTAPI
8089adc538cSKatayama Hirofumi MZ NtUserNotifyIMEStatus(HWND hwnd, BOOL fOpen, DWORD dwConversion)
809c2c66affSColin Finck {
8109db44371SKatayama Hirofumi MZ     PWND pwnd;
8119db44371SKatayama Hirofumi MZ     PTHREADINFO pti;
8129db44371SKatayama Hirofumi MZ     HKL hKL;
8139db44371SKatayama Hirofumi MZ 
8149db44371SKatayama Hirofumi MZ     UserEnterExclusive();
8159db44371SKatayama Hirofumi MZ 
816b5c9d532SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
817b5c9d532SKatayama Hirofumi MZ     {
818b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
819b5c9d532SKatayama Hirofumi MZ         goto Quit;
820b5c9d532SKatayama Hirofumi MZ     }
821b5c9d532SKatayama Hirofumi MZ 
8229db44371SKatayama Hirofumi MZ     pwnd = ValidateHwndNoErr(hwnd);
823b5c9d532SKatayama Hirofumi MZ     if (!pwnd)
8249db44371SKatayama Hirofumi MZ         goto Quit;
8259db44371SKatayama Hirofumi MZ 
8269db44371SKatayama Hirofumi MZ     pti = pwnd->head.pti;
8279db44371SKatayama Hirofumi MZ     if (!pti || !gptiForeground)
8289db44371SKatayama Hirofumi MZ         goto Quit;
8299db44371SKatayama Hirofumi MZ     if (pti != gptiForeground && pti->MessageQueue != gptiForeground->MessageQueue)
8309db44371SKatayama Hirofumi MZ         goto Quit;
8319db44371SKatayama Hirofumi MZ     if (ghIMC == pwnd->hImc && gfImeOpen == !!fOpen && gdwImeConversion == dwConversion)
8329db44371SKatayama Hirofumi MZ         goto Quit;
8339db44371SKatayama Hirofumi MZ 
8349db44371SKatayama Hirofumi MZ     ghIMC = pwnd->hImc;
8359db44371SKatayama Hirofumi MZ     if (ghIMC)
8369db44371SKatayama Hirofumi MZ     {
8379db44371SKatayama Hirofumi MZ         gfImeOpen = !!fOpen;
8389db44371SKatayama Hirofumi MZ         gdwImeConversion = dwConversion;
8399db44371SKatayama Hirofumi MZ         UserSetImeConversionKeyState(pti, (fOpen ? dwConversion : IME_CMODE_ALPHANUMERIC));
8409db44371SKatayama Hirofumi MZ     }
8419db44371SKatayama Hirofumi MZ 
8429db44371SKatayama Hirofumi MZ     if (ISITHOOKED(WH_SHELL))
8439db44371SKatayama Hirofumi MZ     {
8449db44371SKatayama Hirofumi MZ         hKL = (pti->KeyboardLayout ? pti->KeyboardLayout->hkl : NULL);
8459db44371SKatayama Hirofumi MZ         co_HOOK_CallHooks(WH_SHELL, HSHELL_LANGUAGE, (WPARAM)hwnd, (LPARAM)hKL);
8469db44371SKatayama Hirofumi MZ     }
8479db44371SKatayama Hirofumi MZ 
8489db44371SKatayama Hirofumi MZ     // TODO:
8499db44371SKatayama Hirofumi MZ 
8509db44371SKatayama Hirofumi MZ Quit:
8519db44371SKatayama Hirofumi MZ     UserLeave();
852c2c66affSColin Finck     return 0;
853c2c66affSColin Finck }
854c2c66affSColin Finck 
855fcc222c2SKatayama Hirofumi MZ BOOL
856e52ce89bSKatayama Hirofumi MZ NTAPI
857c2c66affSColin Finck NtUserDisableThreadIme(
858fcc222c2SKatayama Hirofumi MZ     DWORD dwThreadID)
859c2c66affSColin Finck {
860fcc222c2SKatayama Hirofumi MZ     PTHREADINFO pti, ptiCurrent;
861fcc222c2SKatayama Hirofumi MZ     PPROCESSINFO ppi;
862fcc222c2SKatayama Hirofumi MZ     BOOL ret = FALSE;
863fcc222c2SKatayama Hirofumi MZ 
864fcc222c2SKatayama Hirofumi MZ     UserEnterExclusive();
865fcc222c2SKatayama Hirofumi MZ 
866fcc222c2SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
867fcc222c2SKatayama Hirofumi MZ     {
868b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
869fcc222c2SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
870fcc222c2SKatayama Hirofumi MZ         goto Quit;
871fcc222c2SKatayama Hirofumi MZ     }
872fcc222c2SKatayama Hirofumi MZ 
873fcc222c2SKatayama Hirofumi MZ     ptiCurrent = GetW32ThreadInfo();
874fcc222c2SKatayama Hirofumi MZ 
875fcc222c2SKatayama Hirofumi MZ     if (dwThreadID == INVALID_THREAD_ID)
876fcc222c2SKatayama Hirofumi MZ     {
877fcc222c2SKatayama Hirofumi MZ         ppi = ptiCurrent->ppi;
878fcc222c2SKatayama Hirofumi MZ         ppi->W32PF_flags |= W32PF_DISABLEIME;
879fcc222c2SKatayama Hirofumi MZ 
880fcc222c2SKatayama Hirofumi MZ Retry:
881fcc222c2SKatayama Hirofumi MZ         for (pti = ppi->ptiList; pti; pti = pti->ptiSibling)
882fcc222c2SKatayama Hirofumi MZ         {
883fcc222c2SKatayama Hirofumi MZ             pti->TIF_flags |= TIF_DISABLEIME;
884fcc222c2SKatayama Hirofumi MZ 
885fcc222c2SKatayama Hirofumi MZ             if (pti->spwndDefaultIme)
886fcc222c2SKatayama Hirofumi MZ             {
887fcc222c2SKatayama Hirofumi MZ                 co_UserDestroyWindow(pti->spwndDefaultIme);
888fcc222c2SKatayama Hirofumi MZ                 pti->spwndDefaultIme = NULL;
889fcc222c2SKatayama Hirofumi MZ                 goto Retry; /* The contents of ppi->ptiList may be changed. */
890fcc222c2SKatayama Hirofumi MZ             }
891fcc222c2SKatayama Hirofumi MZ         }
892fcc222c2SKatayama Hirofumi MZ     }
893fcc222c2SKatayama Hirofumi MZ     else
894fcc222c2SKatayama Hirofumi MZ     {
895fcc222c2SKatayama Hirofumi MZ         if (dwThreadID == 0)
896fcc222c2SKatayama Hirofumi MZ         {
897fcc222c2SKatayama Hirofumi MZ             pti = ptiCurrent;
898fcc222c2SKatayama Hirofumi MZ         }
899fcc222c2SKatayama Hirofumi MZ         else
900fcc222c2SKatayama Hirofumi MZ         {
901fcc222c2SKatayama Hirofumi MZ             pti = IntTID2PTI(UlongToHandle(dwThreadID));
902fcc222c2SKatayama Hirofumi MZ 
903fcc222c2SKatayama Hirofumi MZ             /* The thread needs to reside in the current process. */
904fcc222c2SKatayama Hirofumi MZ             if (!pti || pti->ppi != ptiCurrent->ppi)
905fcc222c2SKatayama Hirofumi MZ                 goto Quit;
906fcc222c2SKatayama Hirofumi MZ         }
907fcc222c2SKatayama Hirofumi MZ 
908fcc222c2SKatayama Hirofumi MZ         pti->TIF_flags |= TIF_DISABLEIME;
909fcc222c2SKatayama Hirofumi MZ 
910fcc222c2SKatayama Hirofumi MZ         if (pti->spwndDefaultIme)
911fcc222c2SKatayama Hirofumi MZ         {
912fcc222c2SKatayama Hirofumi MZ             co_UserDestroyWindow(pti->spwndDefaultIme);
913fcc222c2SKatayama Hirofumi MZ             pti->spwndDefaultIme = NULL;
914fcc222c2SKatayama Hirofumi MZ         }
915fcc222c2SKatayama Hirofumi MZ     }
916fcc222c2SKatayama Hirofumi MZ 
917fcc222c2SKatayama Hirofumi MZ     ret = TRUE;
918fcc222c2SKatayama Hirofumi MZ 
919fcc222c2SKatayama Hirofumi MZ Quit:
920fcc222c2SKatayama Hirofumi MZ     UserLeave();
921fcc222c2SKatayama Hirofumi MZ     return ret;
922c2c66affSColin Finck }
923c2c66affSColin Finck 
924c2c66affSColin Finck DWORD
925e52ce89bSKatayama Hirofumi MZ NTAPI
926f4bc74edSKatayama Hirofumi MZ NtUserGetAppImeLevel(HWND hWnd)
927c2c66affSColin Finck {
9289c8167e9SKatayama Hirofumi MZ     DWORD ret = 0;
9299c8167e9SKatayama Hirofumi MZ     PWND pWnd;
9309c8167e9SKatayama Hirofumi MZ     PTHREADINFO pti;
9319c8167e9SKatayama Hirofumi MZ 
9329c8167e9SKatayama Hirofumi MZ     UserEnterShared();
9339c8167e9SKatayama Hirofumi MZ 
9349c8167e9SKatayama Hirofumi MZ     pWnd = ValidateHwndNoErr(hWnd);
9359c8167e9SKatayama Hirofumi MZ     if (!pWnd)
9369c8167e9SKatayama Hirofumi MZ         goto Quit;
9379c8167e9SKatayama Hirofumi MZ 
9389c8167e9SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
9399c8167e9SKatayama Hirofumi MZ     {
940b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
9419c8167e9SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
9429c8167e9SKatayama Hirofumi MZ         goto Quit;
9439c8167e9SKatayama Hirofumi MZ     }
9449c8167e9SKatayama Hirofumi MZ 
9459c8167e9SKatayama Hirofumi MZ     pti = PsGetCurrentThreadWin32Thread();
9469c8167e9SKatayama Hirofumi MZ     if (pWnd->head.pti->ppi == pti->ppi)
9479c8167e9SKatayama Hirofumi MZ         ret = (DWORD)(ULONG_PTR)UserGetProp(pWnd, AtomImeLevel, TRUE);
9489c8167e9SKatayama Hirofumi MZ 
9499c8167e9SKatayama Hirofumi MZ Quit:
9509c8167e9SKatayama Hirofumi MZ     UserLeave();
9519c8167e9SKatayama Hirofumi MZ     return ret;
952c2c66affSColin Finck }
953c2c66affSColin Finck 
9542f7775c6SKatayama Hirofumi MZ // Win: GetImeInfoEx
95536740ca9SKatayama Hirofumi MZ BOOL FASTCALL UserGetImeInfoEx(LPVOID pUnknown, PIMEINFOEX pInfoEx, IMEINFOEXCLASS SearchType)
95636740ca9SKatayama Hirofumi MZ {
95736740ca9SKatayama Hirofumi MZ     PKL pkl, pklHead;
95836740ca9SKatayama Hirofumi MZ 
95936740ca9SKatayama Hirofumi MZ     if (!gspklBaseLayout)
96036740ca9SKatayama Hirofumi MZ         return FALSE;
96136740ca9SKatayama Hirofumi MZ 
96236740ca9SKatayama Hirofumi MZ     pkl = pklHead = gspklBaseLayout;
96336740ca9SKatayama Hirofumi MZ 
96436740ca9SKatayama Hirofumi MZ     /* Find the matching entry from the list and get info */
96536740ca9SKatayama Hirofumi MZ     if (SearchType == ImeInfoExKeyboardLayout)
96636740ca9SKatayama Hirofumi MZ     {
96736740ca9SKatayama Hirofumi MZ         do
96836740ca9SKatayama Hirofumi MZ         {
96928959a2dSKatayama Hirofumi MZ             if (pInfoEx->hkl == pkl->hkl)
97036740ca9SKatayama Hirofumi MZ             {
97136740ca9SKatayama Hirofumi MZ                 if (!pkl->piiex)
97236740ca9SKatayama Hirofumi MZ                     break;
97336740ca9SKatayama Hirofumi MZ 
97428959a2dSKatayama Hirofumi MZ                 *pInfoEx = *pkl->piiex;
97528959a2dSKatayama Hirofumi MZ                 return TRUE;
97636740ca9SKatayama Hirofumi MZ             }
97736740ca9SKatayama Hirofumi MZ 
97836740ca9SKatayama Hirofumi MZ             pkl = pkl->pklNext;
97936740ca9SKatayama Hirofumi MZ         } while (pkl != pklHead);
98036740ca9SKatayama Hirofumi MZ     }
98136740ca9SKatayama Hirofumi MZ     else if (SearchType == ImeInfoExImeFileName)
98236740ca9SKatayama Hirofumi MZ     {
98336740ca9SKatayama Hirofumi MZ         do
98436740ca9SKatayama Hirofumi MZ         {
98536740ca9SKatayama Hirofumi MZ             if (pkl->piiex &&
98636740ca9SKatayama Hirofumi MZ                 _wcsnicmp(pkl->piiex->wszImeFile, pInfoEx->wszImeFile,
98728959a2dSKatayama Hirofumi MZ                           RTL_NUMBER_OF(pkl->piiex->wszImeFile)) == 0)
98836740ca9SKatayama Hirofumi MZ             {
98928959a2dSKatayama Hirofumi MZ                 *pInfoEx = *pkl->piiex;
99028959a2dSKatayama Hirofumi MZ                 return TRUE;
99136740ca9SKatayama Hirofumi MZ             }
99236740ca9SKatayama Hirofumi MZ 
99336740ca9SKatayama Hirofumi MZ             pkl = pkl->pklNext;
99436740ca9SKatayama Hirofumi MZ         } while (pkl != pklHead);
99536740ca9SKatayama Hirofumi MZ     }
99636740ca9SKatayama Hirofumi MZ     else
99736740ca9SKatayama Hirofumi MZ     {
99836740ca9SKatayama Hirofumi MZ         /* Do nothing */
99936740ca9SKatayama Hirofumi MZ     }
100036740ca9SKatayama Hirofumi MZ 
100128959a2dSKatayama Hirofumi MZ     return FALSE;
100236740ca9SKatayama Hirofumi MZ }
100336740ca9SKatayama Hirofumi MZ 
10044b038ec8SKatayama Hirofumi MZ BOOL
1005e52ce89bSKatayama Hirofumi MZ NTAPI
1006c2c66affSColin Finck NtUserGetImeInfoEx(
1007c2c66affSColin Finck     PIMEINFOEX pImeInfoEx,
10084b038ec8SKatayama Hirofumi MZ     IMEINFOEXCLASS SearchType)
1009c2c66affSColin Finck {
101036740ca9SKatayama Hirofumi MZ     IMEINFOEX ImeInfoEx;
101136740ca9SKatayama Hirofumi MZ     BOOL ret = FALSE;
101236740ca9SKatayama Hirofumi MZ 
101336740ca9SKatayama Hirofumi MZ     UserEnterShared();
101436740ca9SKatayama Hirofumi MZ 
101536740ca9SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1016b5c9d532SKatayama Hirofumi MZ     {
1017b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
101836740ca9SKatayama Hirofumi MZ         goto Quit;
1019b5c9d532SKatayama Hirofumi MZ     }
102036740ca9SKatayama Hirofumi MZ 
102136740ca9SKatayama Hirofumi MZ     _SEH2_TRY
102236740ca9SKatayama Hirofumi MZ     {
102336740ca9SKatayama Hirofumi MZ         ProbeForWrite(pImeInfoEx, sizeof(*pImeInfoEx), 1);
102436740ca9SKatayama Hirofumi MZ         ImeInfoEx = *pImeInfoEx;
102536740ca9SKatayama Hirofumi MZ     }
102636740ca9SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
102736740ca9SKatayama Hirofumi MZ     {
102836740ca9SKatayama Hirofumi MZ         goto Quit;
102936740ca9SKatayama Hirofumi MZ     }
103036740ca9SKatayama Hirofumi MZ     _SEH2_END;
103136740ca9SKatayama Hirofumi MZ 
103236740ca9SKatayama Hirofumi MZ     ret = UserGetImeInfoEx(NULL, &ImeInfoEx, SearchType);
1033e52ce89bSKatayama Hirofumi MZ     if (!ret)
1034e52ce89bSKatayama Hirofumi MZ         goto Quit;
1035e52ce89bSKatayama Hirofumi MZ 
103636740ca9SKatayama Hirofumi MZ     _SEH2_TRY
103736740ca9SKatayama Hirofumi MZ     {
103836740ca9SKatayama Hirofumi MZ         *pImeInfoEx = ImeInfoEx;
103936740ca9SKatayama Hirofumi MZ     }
104036740ca9SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
104136740ca9SKatayama Hirofumi MZ     {
104236740ca9SKatayama Hirofumi MZ         ret = FALSE;
104336740ca9SKatayama Hirofumi MZ     }
104436740ca9SKatayama Hirofumi MZ     _SEH2_END;
1045c2c66affSColin Finck 
104636740ca9SKatayama Hirofumi MZ Quit:
104736740ca9SKatayama Hirofumi MZ     UserLeave();
104836740ca9SKatayama Hirofumi MZ     return ret;
104936740ca9SKatayama Hirofumi MZ }
1050c2c66affSColin Finck 
10519c8167e9SKatayama Hirofumi MZ BOOL
1052e52ce89bSKatayama Hirofumi MZ NTAPI
10539c8167e9SKatayama Hirofumi MZ NtUserSetAppImeLevel(HWND hWnd, DWORD dwLevel)
1054c2c66affSColin Finck {
10559c8167e9SKatayama Hirofumi MZ     BOOL ret = FALSE;
10569c8167e9SKatayama Hirofumi MZ     PWND pWnd;
10579c8167e9SKatayama Hirofumi MZ     PTHREADINFO pti;
10589c8167e9SKatayama Hirofumi MZ 
10599c8167e9SKatayama Hirofumi MZ     UserEnterExclusive();
10609c8167e9SKatayama Hirofumi MZ 
10619c8167e9SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
10629c8167e9SKatayama Hirofumi MZ     {
1063b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
10649c8167e9SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
10659c8167e9SKatayama Hirofumi MZ         goto Quit;
10669c8167e9SKatayama Hirofumi MZ     }
10679c8167e9SKatayama Hirofumi MZ 
1068b5c9d532SKatayama Hirofumi MZ     pWnd = ValidateHwndNoErr(hWnd);
1069b5c9d532SKatayama Hirofumi MZ     if (!pWnd)
1070b5c9d532SKatayama Hirofumi MZ         goto Quit;
1071b5c9d532SKatayama Hirofumi MZ 
10729c8167e9SKatayama Hirofumi MZ     pti = PsGetCurrentThreadWin32Thread();
10739c8167e9SKatayama Hirofumi MZ     if (pWnd->head.pti->ppi == pti->ppi)
10749c8167e9SKatayama Hirofumi MZ         ret = UserSetProp(pWnd, AtomImeLevel, (HANDLE)(ULONG_PTR)dwLevel, TRUE);
10759c8167e9SKatayama Hirofumi MZ 
10769c8167e9SKatayama Hirofumi MZ Quit:
10779c8167e9SKatayama Hirofumi MZ     UserLeave();
10789c8167e9SKatayama Hirofumi MZ     return ret;
1079c2c66affSColin Finck }
1080c2c66affSColin Finck 
10812f7775c6SKatayama Hirofumi MZ // Win: SetImeInfoEx
10821f446936SKatayama Hirofumi MZ BOOL FASTCALL UserSetImeInfoEx(LPVOID pUnknown, PIMEINFOEX pImeInfoEx)
1083c2c66affSColin Finck {
10841f446936SKatayama Hirofumi MZ     PKL pklHead, pkl;
10851f446936SKatayama Hirofumi MZ 
10861f446936SKatayama Hirofumi MZ     pkl = pklHead = gspklBaseLayout;
10871f446936SKatayama Hirofumi MZ 
10881f446936SKatayama Hirofumi MZ     do
10891f446936SKatayama Hirofumi MZ     {
10901f446936SKatayama Hirofumi MZ         if (pkl->hkl != pImeInfoEx->hkl)
10911f446936SKatayama Hirofumi MZ         {
10921f446936SKatayama Hirofumi MZ             pkl = pkl->pklNext;
10931f446936SKatayama Hirofumi MZ             continue;
10941f446936SKatayama Hirofumi MZ         }
10951f446936SKatayama Hirofumi MZ 
10961f446936SKatayama Hirofumi MZ         if (!pkl->piiex)
10971f446936SKatayama Hirofumi MZ             return FALSE;
10981f446936SKatayama Hirofumi MZ 
10991f446936SKatayama Hirofumi MZ         if (!pkl->piiex->fLoadFlag)
11001f446936SKatayama Hirofumi MZ             *pkl->piiex = *pImeInfoEx;
11011f446936SKatayama Hirofumi MZ 
11021f446936SKatayama Hirofumi MZ         return TRUE;
11031f446936SKatayama Hirofumi MZ     } while (pkl != pklHead);
11041f446936SKatayama Hirofumi MZ 
11051f446936SKatayama Hirofumi MZ     return FALSE;
11061f446936SKatayama Hirofumi MZ }
11071f446936SKatayama Hirofumi MZ 
11081f446936SKatayama Hirofumi MZ BOOL
1109e52ce89bSKatayama Hirofumi MZ NTAPI
11101f446936SKatayama Hirofumi MZ NtUserSetImeInfoEx(PIMEINFOEX pImeInfoEx)
11111f446936SKatayama Hirofumi MZ {
11121f446936SKatayama Hirofumi MZ     BOOL ret = FALSE;
11131f446936SKatayama Hirofumi MZ     IMEINFOEX ImeInfoEx;
11141f446936SKatayama Hirofumi MZ 
11151f446936SKatayama Hirofumi MZ     UserEnterExclusive();
11161f446936SKatayama Hirofumi MZ 
11171f446936SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1118b5c9d532SKatayama Hirofumi MZ     {
1119b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
11201f446936SKatayama Hirofumi MZ         goto Quit;
1121b5c9d532SKatayama Hirofumi MZ     }
11221f446936SKatayama Hirofumi MZ 
11231f446936SKatayama Hirofumi MZ     _SEH2_TRY
11241f446936SKatayama Hirofumi MZ     {
11251f446936SKatayama Hirofumi MZ         ProbeForRead(pImeInfoEx, sizeof(*pImeInfoEx), 1);
11261f446936SKatayama Hirofumi MZ         ImeInfoEx = *pImeInfoEx;
11271f446936SKatayama Hirofumi MZ     }
11281f446936SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
11291f446936SKatayama Hirofumi MZ     {
11301f446936SKatayama Hirofumi MZ         goto Quit;
11311f446936SKatayama Hirofumi MZ     }
11321f446936SKatayama Hirofumi MZ     _SEH2_END;
11331f446936SKatayama Hirofumi MZ 
11341f446936SKatayama Hirofumi MZ     ret = UserSetImeInfoEx(NULL, &ImeInfoEx);
11351f446936SKatayama Hirofumi MZ 
11361f446936SKatayama Hirofumi MZ Quit:
11371f446936SKatayama Hirofumi MZ     UserLeave();
11381f446936SKatayama Hirofumi MZ     return ret;
1139c2c66affSColin Finck }
1140c2c66affSColin Finck 
1141291a94cdSKatayama Hirofumi MZ // Choose the preferred owner of the IME window.
1142291a94cdSKatayama Hirofumi MZ // Win: ImeSetFutureOwner
1143291a94cdSKatayama Hirofumi MZ VOID FASTCALL IntImeSetFutureOwner(PWND pImeWnd, PWND pwndOwner)
1144291a94cdSKatayama Hirofumi MZ {
1145291a94cdSKatayama Hirofumi MZ     PWND pwndNode, pwndNextOwner, pwndParent, pwndSibling;
1146291a94cdSKatayama Hirofumi MZ     PTHREADINFO pti = pImeWnd->head.pti;
1147291a94cdSKatayama Hirofumi MZ 
1148291a94cdSKatayama Hirofumi MZ     if (!pwndOwner || (pwndOwner->style & WS_CHILD)) // invalid owner
1149291a94cdSKatayama Hirofumi MZ         return;
1150291a94cdSKatayama Hirofumi MZ 
1151291a94cdSKatayama Hirofumi MZ     // Get the top-level owner of the same thread
1152291a94cdSKatayama Hirofumi MZ     for (pwndNode = pwndOwner; ; pwndNode = pwndNextOwner)
1153291a94cdSKatayama Hirofumi MZ     {
1154291a94cdSKatayama Hirofumi MZ         pwndNextOwner = pwndNode->spwndOwner;
1155291a94cdSKatayama Hirofumi MZ         if (!pwndNextOwner || pwndNextOwner->head.pti != pti)
1156291a94cdSKatayama Hirofumi MZ             break;
1157291a94cdSKatayama Hirofumi MZ     }
1158291a94cdSKatayama Hirofumi MZ 
1159291a94cdSKatayama Hirofumi MZ     // Don't choose the IME-like windows and the bottom-most windows unless necessary.
1160291a94cdSKatayama Hirofumi MZ     if (IS_WND_IMELIKE(pwndNode) ||
1161291a94cdSKatayama Hirofumi MZ         ((pwndNode->state2 & WNDS2_BOTTOMMOST) && !(pwndOwner->state2 & WNDS2_BOTTOMMOST)))
1162291a94cdSKatayama Hirofumi MZ     {
1163291a94cdSKatayama Hirofumi MZ         pwndNode = pwndOwner;
1164291a94cdSKatayama Hirofumi MZ     }
1165291a94cdSKatayama Hirofumi MZ 
1166291a94cdSKatayama Hirofumi MZ     pwndParent = pwndNode->spwndParent;
1167291a94cdSKatayama Hirofumi MZ     if (!pwndParent || pwndOwner != pwndNode)
1168291a94cdSKatayama Hirofumi MZ     {
1169291a94cdSKatayama Hirofumi MZ         pImeWnd->spwndOwner = pwndNode;
1170291a94cdSKatayama Hirofumi MZ         return;
1171291a94cdSKatayama Hirofumi MZ     }
1172291a94cdSKatayama Hirofumi MZ 
1173291a94cdSKatayama Hirofumi MZ     for (pwndSibling = pwndParent->spwndChild; pwndSibling; pwndSibling = pwndSibling->spwndNext)
1174291a94cdSKatayama Hirofumi MZ     {
1175291a94cdSKatayama Hirofumi MZ         if (pwndNode->head.pti != pwndSibling->head.pti)
1176291a94cdSKatayama Hirofumi MZ             continue;
1177291a94cdSKatayama Hirofumi MZ 
1178291a94cdSKatayama Hirofumi MZ         if (IS_WND_MENU(pwndSibling) || IS_WND_IMELIKE(pwndSibling))
1179291a94cdSKatayama Hirofumi MZ             continue;
1180291a94cdSKatayama Hirofumi MZ 
1181291a94cdSKatayama Hirofumi MZ         if (pwndSibling->state2 & WNDS2_INDESTROY)
1182291a94cdSKatayama Hirofumi MZ             continue;
1183291a94cdSKatayama Hirofumi MZ 
1184291a94cdSKatayama Hirofumi MZ         if (pwndNode == pwndSibling || (pwndSibling->style & WS_CHILD))
1185291a94cdSKatayama Hirofumi MZ             continue;
1186291a94cdSKatayama Hirofumi MZ 
1187291a94cdSKatayama Hirofumi MZ         if (pwndSibling->spwndOwner == NULL ||
1188291a94cdSKatayama Hirofumi MZ             pwndSibling->head.pti != pwndSibling->spwndOwner->head.pti)
1189291a94cdSKatayama Hirofumi MZ         {
1190291a94cdSKatayama Hirofumi MZ             pwndNode = pwndSibling;
1191291a94cdSKatayama Hirofumi MZ             break;
1192291a94cdSKatayama Hirofumi MZ         }
1193291a94cdSKatayama Hirofumi MZ     }
1194291a94cdSKatayama Hirofumi MZ 
1195291a94cdSKatayama Hirofumi MZ     pImeWnd->spwndOwner = pwndNode;
1196291a94cdSKatayama Hirofumi MZ }
1197291a94cdSKatayama Hirofumi MZ 
1198291a94cdSKatayama Hirofumi MZ // Get the last non-IME-like top-most window on the desktop.
1199291a94cdSKatayama Hirofumi MZ // Win: GetLastTopMostWindowNoIME
1200291a94cdSKatayama Hirofumi MZ PWND FASTCALL IntGetLastTopMostWindowNoIME(PWND pImeWnd)
1201291a94cdSKatayama Hirofumi MZ {
1202291a94cdSKatayama Hirofumi MZ     PWND pwndNode, pwndOwner, pwndLastTopMost = NULL;
1203291a94cdSKatayama Hirofumi MZ     BOOL bFound;
1204291a94cdSKatayama Hirofumi MZ 
1205291a94cdSKatayama Hirofumi MZ     pwndNode = UserGetDesktopWindow();
1206291a94cdSKatayama Hirofumi MZ     if (!pwndNode || pwndNode->spwndChild == NULL)
1207291a94cdSKatayama Hirofumi MZ         return NULL;
1208291a94cdSKatayama Hirofumi MZ 
1209291a94cdSKatayama Hirofumi MZ     for (pwndNode = pwndNode->spwndChild;
1210291a94cdSKatayama Hirofumi MZ          pwndNode && (pwndNode->ExStyle & WS_EX_TOPMOST);
1211291a94cdSKatayama Hirofumi MZ          pwndNode = pwndNode->spwndNext)
1212291a94cdSKatayama Hirofumi MZ     {
1213291a94cdSKatayama Hirofumi MZ         bFound = FALSE;
1214291a94cdSKatayama Hirofumi MZ 
1215291a94cdSKatayama Hirofumi MZ         if (IS_WND_IMELIKE(pwndNode)) // An IME-like window
1216291a94cdSKatayama Hirofumi MZ         {
1217291a94cdSKatayama Hirofumi MZ             // Search the IME window from owners
1218291a94cdSKatayama Hirofumi MZ             for (pwndOwner = pwndNode; pwndOwner; pwndOwner = pwndOwner->spwndOwner)
1219291a94cdSKatayama Hirofumi MZ             {
1220291a94cdSKatayama Hirofumi MZ                 if (pImeWnd == pwndOwner)
1221291a94cdSKatayama Hirofumi MZ                 {
1222291a94cdSKatayama Hirofumi MZ                     bFound = TRUE;
1223291a94cdSKatayama Hirofumi MZ                     break;
1224291a94cdSKatayama Hirofumi MZ                 }
1225291a94cdSKatayama Hirofumi MZ             }
1226291a94cdSKatayama Hirofumi MZ         }
1227291a94cdSKatayama Hirofumi MZ 
1228291a94cdSKatayama Hirofumi MZ         if (!bFound)
1229291a94cdSKatayama Hirofumi MZ             pwndLastTopMost = pwndNode;
1230291a94cdSKatayama Hirofumi MZ     }
1231291a94cdSKatayama Hirofumi MZ 
1232291a94cdSKatayama Hirofumi MZ     return pwndLastTopMost;
1233291a94cdSKatayama Hirofumi MZ }
1234291a94cdSKatayama Hirofumi MZ 
1235291a94cdSKatayama Hirofumi MZ // Adjust the ordering of the windows around the IME window.
1236291a94cdSKatayama Hirofumi MZ // Win: ImeSetTopMost
1237291a94cdSKatayama Hirofumi MZ VOID FASTCALL IntImeSetTopMost(PWND pImeWnd, BOOL bTopMost, PWND pwndInsertBefore)
1238291a94cdSKatayama Hirofumi MZ {
1239291a94cdSKatayama Hirofumi MZ     PWND pwndParent, pwndChild, pwndNode, pwndNext, pwndInsertAfter = NULL;
1240291a94cdSKatayama Hirofumi MZ     PWND pwndInsertAfterSave;
1241291a94cdSKatayama Hirofumi MZ 
1242291a94cdSKatayama Hirofumi MZ     pwndParent = pImeWnd->spwndParent;
1243291a94cdSKatayama Hirofumi MZ     if (!pwndParent)
1244291a94cdSKatayama Hirofumi MZ         return;
1245291a94cdSKatayama Hirofumi MZ 
1246291a94cdSKatayama Hirofumi MZ     pwndChild = pwndParent->spwndChild;
1247291a94cdSKatayama Hirofumi MZ 
1248291a94cdSKatayama Hirofumi MZ     if (!bTopMost)
1249291a94cdSKatayama Hirofumi MZ     {
1250291a94cdSKatayama Hirofumi MZ         // Calculate pwndInsertAfter
1251291a94cdSKatayama Hirofumi MZ         pwndInsertAfter = IntGetLastTopMostWindowNoIME(pImeWnd);
1252291a94cdSKatayama Hirofumi MZ         if (pwndInsertBefore)
1253291a94cdSKatayama Hirofumi MZ         {
1254291a94cdSKatayama Hirofumi MZ             for (pwndNode = pwndInsertAfter; pwndNode; pwndNode = pwndNode->spwndNext)
1255291a94cdSKatayama Hirofumi MZ             {
1256291a94cdSKatayama Hirofumi MZ                 if (pwndNode->spwndNext == pwndInsertBefore)
1257291a94cdSKatayama Hirofumi MZ                     break;
1258291a94cdSKatayama Hirofumi MZ 
1259291a94cdSKatayama Hirofumi MZ                 if (pwndNode == pImeWnd)
1260291a94cdSKatayama Hirofumi MZ                     return;
1261291a94cdSKatayama Hirofumi MZ             }
1262291a94cdSKatayama Hirofumi MZ 
1263291a94cdSKatayama Hirofumi MZ             if (!pwndNode)
1264291a94cdSKatayama Hirofumi MZ                 return;
1265291a94cdSKatayama Hirofumi MZ 
1266291a94cdSKatayama Hirofumi MZ             pwndInsertAfter = pwndNode;
1267291a94cdSKatayama Hirofumi MZ         }
1268291a94cdSKatayama Hirofumi MZ 
1269291a94cdSKatayama Hirofumi MZ         // Adjust pwndInsertAfter if the owner is bottom-most
1270291a94cdSKatayama Hirofumi MZ         if (pImeWnd->spwndOwner->state2 & WNDS2_BOTTOMMOST)
1271291a94cdSKatayama Hirofumi MZ         {
1272291a94cdSKatayama Hirofumi MZ             for (pwndNode = pwndInsertAfter; pwndNode; pwndNode = pwndNode->spwndNext)
1273291a94cdSKatayama Hirofumi MZ             {
1274291a94cdSKatayama Hirofumi MZ                 if (pwndNode == pImeWnd->spwndOwner)
1275291a94cdSKatayama Hirofumi MZ                     break;
1276291a94cdSKatayama Hirofumi MZ 
1277291a94cdSKatayama Hirofumi MZ                 if (!IS_WND_IMELIKE(pwndNode))
1278291a94cdSKatayama Hirofumi MZ                     pwndInsertAfter = pwndNode;
1279291a94cdSKatayama Hirofumi MZ             }
1280291a94cdSKatayama Hirofumi MZ         }
1281291a94cdSKatayama Hirofumi MZ     }
1282291a94cdSKatayama Hirofumi MZ 
1283291a94cdSKatayama Hirofumi MZ     pwndInsertAfterSave = pwndInsertAfter;
1284291a94cdSKatayama Hirofumi MZ 
1285291a94cdSKatayama Hirofumi MZ     while (pwndChild)
1286291a94cdSKatayama Hirofumi MZ     {
1287291a94cdSKatayama Hirofumi MZ         pwndNext = pwndChild->spwndNext;
1288291a94cdSKatayama Hirofumi MZ 
1289291a94cdSKatayama Hirofumi MZ         // If pwndChild is a good IME-like window, ...
1290291a94cdSKatayama Hirofumi MZ         if (IS_WND_IMELIKE(pwndChild) && pwndChild != pwndInsertAfter &&
1291291a94cdSKatayama Hirofumi MZ             pwndChild->head.pti == pImeWnd->head.pti)
1292291a94cdSKatayama Hirofumi MZ         {
1293291a94cdSKatayama Hirofumi MZ             // Find pImeWnd from the owners
1294291a94cdSKatayama Hirofumi MZ             for (pwndNode = pwndChild; pwndNode; pwndNode = pwndNode->spwndOwner)
1295291a94cdSKatayama Hirofumi MZ             {
1296291a94cdSKatayama Hirofumi MZ                 if (pwndNode != pImeWnd)
1297291a94cdSKatayama Hirofumi MZ                     continue;
1298291a94cdSKatayama Hirofumi MZ 
1299291a94cdSKatayama Hirofumi MZ                 // Adjust the ordering and the linking
1300291a94cdSKatayama Hirofumi MZ                 IntUnlinkWindow(pwndChild);
1301291a94cdSKatayama Hirofumi MZ 
1302291a94cdSKatayama Hirofumi MZ                 if (bTopMost)
1303291a94cdSKatayama Hirofumi MZ                     pwndChild->ExStyle |= WS_EX_TOPMOST;
1304291a94cdSKatayama Hirofumi MZ                 else
1305291a94cdSKatayama Hirofumi MZ                     pwndChild->ExStyle &= ~WS_EX_TOPMOST;
1306291a94cdSKatayama Hirofumi MZ 
1307291a94cdSKatayama Hirofumi MZ                 if (!pwndInsertAfter)
1308291a94cdSKatayama Hirofumi MZ                     IntLinkHwnd(pwndChild, HWND_TOP);
1309291a94cdSKatayama Hirofumi MZ                 else
1310291a94cdSKatayama Hirofumi MZ                     IntLinkHwnd(pwndChild, UserHMGetHandle(pwndInsertAfter));
1311291a94cdSKatayama Hirofumi MZ 
1312291a94cdSKatayama Hirofumi MZ                 // Update the preferred position
1313291a94cdSKatayama Hirofumi MZ                 pwndInsertAfter = pwndChild;
1314291a94cdSKatayama Hirofumi MZ                 break;
1315291a94cdSKatayama Hirofumi MZ             }
1316291a94cdSKatayama Hirofumi MZ         }
1317291a94cdSKatayama Hirofumi MZ 
1318291a94cdSKatayama Hirofumi MZ         // Get the next child, with ignoring pwndInsertAfterSave
1319291a94cdSKatayama Hirofumi MZ         pwndChild = pwndNext;
1320291a94cdSKatayama Hirofumi MZ         if (pwndChild && pwndChild == pwndInsertAfterSave && pwndInsertAfter)
1321291a94cdSKatayama Hirofumi MZ             pwndChild = pwndInsertAfter->spwndNext;
1322291a94cdSKatayama Hirofumi MZ     }
1323291a94cdSKatayama Hirofumi MZ }
1324291a94cdSKatayama Hirofumi MZ 
1325291a94cdSKatayama Hirofumi MZ // Make the IME window top-most if necessary.
1326291a94cdSKatayama Hirofumi MZ // Win: ImeCheckTopmost
1327291a94cdSKatayama Hirofumi MZ VOID FASTCALL IntImeCheckTopmost(PWND pImeWnd)
1328291a94cdSKatayama Hirofumi MZ {
1329291a94cdSKatayama Hirofumi MZ     BOOL bTopMost;
1330291a94cdSKatayama Hirofumi MZ     PWND pwndOwner = pImeWnd->spwndOwner, pwndInsertBefore = NULL;
1331291a94cdSKatayama Hirofumi MZ 
1332291a94cdSKatayama Hirofumi MZ     if (!pwndOwner)
1333291a94cdSKatayama Hirofumi MZ         return;
1334291a94cdSKatayama Hirofumi MZ 
1335291a94cdSKatayama Hirofumi MZ     if (pImeWnd->head.pti != gptiForeground)
1336291a94cdSKatayama Hirofumi MZ         pwndInsertBefore = pwndOwner;
1337291a94cdSKatayama Hirofumi MZ 
1338291a94cdSKatayama Hirofumi MZ     bTopMost = !!(pwndOwner->ExStyle & WS_EX_TOPMOST);
1339291a94cdSKatayama Hirofumi MZ     IntImeSetTopMost(pImeWnd, bTopMost, pwndInsertBefore);
1340291a94cdSKatayama Hirofumi MZ }
1341291a94cdSKatayama Hirofumi MZ 
1342e52ce89bSKatayama Hirofumi MZ BOOL NTAPI
13438c6dcdcfSKatayama Hirofumi MZ NtUserSetImeOwnerWindow(HWND hImeWnd, HWND hwndFocus)
1344c2c66affSColin Finck {
13450519ae0aSKatayama Hirofumi MZ     BOOL ret = FALSE;
1346291a94cdSKatayama Hirofumi MZ     PWND pImeWnd, pwndFocus, pwndTopLevel, pwndNode, pwndActive;
13470519ae0aSKatayama Hirofumi MZ     PTHREADINFO ptiIme;
13480519ae0aSKatayama Hirofumi MZ 
13490519ae0aSKatayama Hirofumi MZ     UserEnterExclusive();
13500519ae0aSKatayama Hirofumi MZ 
1351b5c9d532SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1352b5c9d532SKatayama Hirofumi MZ     {
1353b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
1354b5c9d532SKatayama Hirofumi MZ         goto Quit;
1355b5c9d532SKatayama Hirofumi MZ     }
1356b5c9d532SKatayama Hirofumi MZ 
13570519ae0aSKatayama Hirofumi MZ     pImeWnd = ValidateHwndNoErr(hImeWnd);
1358b5c9d532SKatayama Hirofumi MZ     if (!pImeWnd || pImeWnd->fnid != FNID_IME)
13590519ae0aSKatayama Hirofumi MZ         goto Quit;
13600519ae0aSKatayama Hirofumi MZ 
13610519ae0aSKatayama Hirofumi MZ     pwndFocus = ValidateHwndNoErr(hwndFocus);
13620519ae0aSKatayama Hirofumi MZ     if (pwndFocus)
13630519ae0aSKatayama Hirofumi MZ     {
13640519ae0aSKatayama Hirofumi MZ         if (IS_WND_IMELIKE(pwndFocus))
13650519ae0aSKatayama Hirofumi MZ             goto Quit;
13660519ae0aSKatayama Hirofumi MZ 
13670519ae0aSKatayama Hirofumi MZ         pwndTopLevel = IntGetTopLevelWindow(pwndFocus);
13680519ae0aSKatayama Hirofumi MZ 
1369291a94cdSKatayama Hirofumi MZ         for (pwndNode = pwndTopLevel; pwndNode; pwndNode = pwndNode->spwndOwner)
13700519ae0aSKatayama Hirofumi MZ         {
1371291a94cdSKatayama Hirofumi MZ             if (pwndNode->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME])
13720519ae0aSKatayama Hirofumi MZ             {
13730519ae0aSKatayama Hirofumi MZ                 pwndTopLevel = NULL;
13740519ae0aSKatayama Hirofumi MZ                 break;
13750519ae0aSKatayama Hirofumi MZ             }
13760519ae0aSKatayama Hirofumi MZ         }
13770519ae0aSKatayama Hirofumi MZ 
13780519ae0aSKatayama Hirofumi MZ         pImeWnd->spwndOwner = pwndTopLevel;
1379291a94cdSKatayama Hirofumi MZ         IntImeCheckTopmost(pImeWnd);
13800519ae0aSKatayama Hirofumi MZ     }
13810519ae0aSKatayama Hirofumi MZ     else
13820519ae0aSKatayama Hirofumi MZ     {
13830519ae0aSKatayama Hirofumi MZ         ptiIme = pImeWnd->head.pti;
13840519ae0aSKatayama Hirofumi MZ         pwndActive = ptiIme->MessageQueue->spwndActive;
13850519ae0aSKatayama Hirofumi MZ 
13860519ae0aSKatayama Hirofumi MZ         if (!pwndActive || pwndActive != pImeWnd->spwndOwner)
13870519ae0aSKatayama Hirofumi MZ         {
13880519ae0aSKatayama Hirofumi MZ             if (pwndActive && ptiIme == pwndActive->head.pti && !IS_WND_IMELIKE(pwndActive))
13890519ae0aSKatayama Hirofumi MZ             {
13900519ae0aSKatayama Hirofumi MZ                 pImeWnd->spwndOwner = pwndActive;
13910519ae0aSKatayama Hirofumi MZ             }
13920519ae0aSKatayama Hirofumi MZ             else
13930519ae0aSKatayama Hirofumi MZ             {
1394291a94cdSKatayama Hirofumi MZ                 IntImeSetFutureOwner(pImeWnd, pImeWnd->spwndOwner);
13950519ae0aSKatayama Hirofumi MZ             }
13960519ae0aSKatayama Hirofumi MZ 
1397291a94cdSKatayama Hirofumi MZ             IntImeCheckTopmost(pImeWnd);
13980519ae0aSKatayama Hirofumi MZ         }
13990519ae0aSKatayama Hirofumi MZ     }
14000519ae0aSKatayama Hirofumi MZ 
14010519ae0aSKatayama Hirofumi MZ     ret = TRUE;
14020519ae0aSKatayama Hirofumi MZ 
14030519ae0aSKatayama Hirofumi MZ Quit:
14040519ae0aSKatayama Hirofumi MZ     UserLeave();
14050519ae0aSKatayama Hirofumi MZ     return ret;
1406c2c66affSColin Finck }
1407c2c66affSColin Finck 
14083d78601fSKatayama Hirofumi MZ PVOID
14093d78601fSKatayama Hirofumi MZ AllocInputContextObject(PDESKTOP pDesk,
14103d78601fSKatayama Hirofumi MZ                         PTHREADINFO pti,
14113d78601fSKatayama Hirofumi MZ                         SIZE_T Size,
14123d78601fSKatayama Hirofumi MZ                         PVOID* HandleOwner)
14133d78601fSKatayama Hirofumi MZ {
14143d78601fSKatayama Hirofumi MZ     PTHRDESKHEAD ObjHead;
14153d78601fSKatayama Hirofumi MZ 
14163d78601fSKatayama Hirofumi MZ     ASSERT(Size > sizeof(*ObjHead));
14173d78601fSKatayama Hirofumi MZ     ASSERT(pti != NULL);
14183d78601fSKatayama Hirofumi MZ 
1419cfeb498eSKatayama Hirofumi MZ     if (!pDesk)
1420cfeb498eSKatayama Hirofumi MZ         pDesk = pti->rpdesk;
1421cfeb498eSKatayama Hirofumi MZ 
1422cfeb498eSKatayama Hirofumi MZ     ObjHead = DesktopHeapAlloc(pDesk, Size);
14233d78601fSKatayama Hirofumi MZ     if (!ObjHead)
14243d78601fSKatayama Hirofumi MZ         return NULL;
14253d78601fSKatayama Hirofumi MZ 
14263d78601fSKatayama Hirofumi MZ     RtlZeroMemory(ObjHead, Size);
14273d78601fSKatayama Hirofumi MZ 
14283d78601fSKatayama Hirofumi MZ     ObjHead->pSelf = ObjHead;
14293d78601fSKatayama Hirofumi MZ     ObjHead->rpdesk = pDesk;
14303d78601fSKatayama Hirofumi MZ     ObjHead->pti = pti;
14313d78601fSKatayama Hirofumi MZ     IntReferenceThreadInfo(pti);
14323d78601fSKatayama Hirofumi MZ     *HandleOwner = pti;
14333d78601fSKatayama Hirofumi MZ     pti->ppi->UserHandleCount++;
14343d78601fSKatayama Hirofumi MZ 
14353d78601fSKatayama Hirofumi MZ     return ObjHead;
14363d78601fSKatayama Hirofumi MZ }
14373d78601fSKatayama Hirofumi MZ 
14383d78601fSKatayama Hirofumi MZ VOID UserFreeInputContext(PVOID Object)
14393d78601fSKatayama Hirofumi MZ {
1440cfeb498eSKatayama Hirofumi MZ     PTHRDESKHEAD ObjHead = Object;
1441cfeb498eSKatayama Hirofumi MZ     PDESKTOP pDesk = ObjHead->rpdesk;
1442eb902e5bSKatayama Hirofumi MZ     PIMC pNode, pIMC = Object;
1443757bed81SKatayama Hirofumi MZ     PTHREADINFO pti;
14443d78601fSKatayama Hirofumi MZ 
1445757bed81SKatayama Hirofumi MZ     if (!pIMC)
1446757bed81SKatayama Hirofumi MZ         return;
14473d78601fSKatayama Hirofumi MZ 
1448eb902e5bSKatayama Hirofumi MZ     // Remove pIMC from the list except spDefaultImc
1449757bed81SKatayama Hirofumi MZ     pti = pIMC->head.pti;
1450eb902e5bSKatayama Hirofumi MZ     for (pNode = pti->spDefaultImc; pNode; pNode = pNode->pImcNext)
14512b2366abSKatayama Hirofumi MZ     {
1452eb902e5bSKatayama Hirofumi MZ         if (pNode->pImcNext == pIMC)
14532b2366abSKatayama Hirofumi MZ         {
1454eb902e5bSKatayama Hirofumi MZ             pNode->pImcNext = pIMC->pImcNext;
14552b2366abSKatayama Hirofumi MZ             break;
14562b2366abSKatayama Hirofumi MZ         }
14572b2366abSKatayama Hirofumi MZ     }
1458757bed81SKatayama Hirofumi MZ 
1459cfeb498eSKatayama Hirofumi MZ     DesktopHeapFree(pDesk, Object);
146045a4e53fSKatayama Hirofumi MZ 
146145a4e53fSKatayama Hirofumi MZ     pti->ppi->UserHandleCount--;
146245a4e53fSKatayama Hirofumi MZ     IntDereferenceThreadInfo(pti);
146345a4e53fSKatayama Hirofumi MZ }
146445a4e53fSKatayama Hirofumi MZ 
146545a4e53fSKatayama Hirofumi MZ BOOLEAN UserDestroyInputContext(PVOID Object)
146645a4e53fSKatayama Hirofumi MZ {
14672b2366abSKatayama Hirofumi MZ     PIMC pIMC = Object;
14684a748a3aSKatayama Hirofumi MZ     if (!pIMC)
146945a4e53fSKatayama Hirofumi MZ         return TRUE;
147045a4e53fSKatayama Hirofumi MZ 
1471*2ef605d4SKatayama Hirofumi MZ     UserMarkObjectDestroy(pIMC);
14724a748a3aSKatayama Hirofumi MZ     UserDeleteObject(UserHMGetHandle(pIMC), TYPE_INPUTCONTEXT);
14734a748a3aSKatayama Hirofumi MZ     return TRUE;
14743d78601fSKatayama Hirofumi MZ }
14753d78601fSKatayama Hirofumi MZ 
1476eb902e5bSKatayama Hirofumi MZ // Win: DestroyInputContext
14770f1e19a7SKatayama Hirofumi MZ BOOL IntDestroyInputContext(PIMC pIMC)
14783d78601fSKatayama Hirofumi MZ {
14790f1e19a7SKatayama Hirofumi MZ     HIMC hIMC = UserHMGetHandle(pIMC);
1480eb902e5bSKatayama Hirofumi MZ     PTHREADINFO pti = pIMC->head.pti;
1481eb902e5bSKatayama Hirofumi MZ     PWND pwndChild;
1482eb902e5bSKatayama Hirofumi MZ     PWINDOWLIST pwl;
14831bc9dda5SKatayama Hirofumi MZ     HWND *phwnd;
14841bc9dda5SKatayama Hirofumi MZ     PWND pWnd;
14853d78601fSKatayama Hirofumi MZ 
14860f1e19a7SKatayama Hirofumi MZ     if (pti != gptiCurrent)
14873d78601fSKatayama Hirofumi MZ     {
1488eb902e5bSKatayama Hirofumi MZ         EngSetLastError(ERROR_ACCESS_DENIED);
1489eb902e5bSKatayama Hirofumi MZ         return FALSE;
14903d78601fSKatayama Hirofumi MZ     }
14913d78601fSKatayama Hirofumi MZ 
1492eb902e5bSKatayama Hirofumi MZ     if (pIMC == pti->spDefaultImc)
1493eb902e5bSKatayama Hirofumi MZ     {
1494eb902e5bSKatayama Hirofumi MZ         EngSetLastError(ERROR_INVALID_PARAMETER);
1495eb902e5bSKatayama Hirofumi MZ         return FALSE;
1496eb902e5bSKatayama Hirofumi MZ     }
14973d78601fSKatayama Hirofumi MZ 
1498eb902e5bSKatayama Hirofumi MZ     pwndChild = pti->rpdesk->pDeskInfo->spwnd->spwndChild;
1499eb902e5bSKatayama Hirofumi MZ     pwl = IntBuildHwndList(pwndChild, IACE_LIST | IACE_CHILDREN, pti);
15001bc9dda5SKatayama Hirofumi MZ     if (pwl)
15011bc9dda5SKatayama Hirofumi MZ     {
15021bc9dda5SKatayama Hirofumi MZ         for (phwnd = pwl->ahwnd; *phwnd != HWND_TERMINATOR; ++phwnd)
15031bc9dda5SKatayama Hirofumi MZ         {
1504eb902e5bSKatayama Hirofumi MZ             pWnd = UserGetObjectNoErr(gHandleTable, *phwnd, TYPE_WINDOW);
1505eb902e5bSKatayama Hirofumi MZ             if (pWnd && pWnd->hImc == hIMC)
15061bc9dda5SKatayama Hirofumi MZ                 IntAssociateInputContext(pWnd, pti->spDefaultImc);
15071bc9dda5SKatayama Hirofumi MZ         }
15081bc9dda5SKatayama Hirofumi MZ 
15091bc9dda5SKatayama Hirofumi MZ         IntFreeHwndList(pwl);
15101bc9dda5SKatayama Hirofumi MZ     }
15111bc9dda5SKatayama Hirofumi MZ 
1512eb902e5bSKatayama Hirofumi MZ     UserDeleteObject(hIMC, TYPE_INPUTCONTEXT);
1513eb902e5bSKatayama Hirofumi MZ     return TRUE;
1514eb902e5bSKatayama Hirofumi MZ }
1515eb902e5bSKatayama Hirofumi MZ 
1516eb902e5bSKatayama Hirofumi MZ BOOL NTAPI NtUserDestroyInputContext(HIMC hIMC)
1517eb902e5bSKatayama Hirofumi MZ {
1518eb902e5bSKatayama Hirofumi MZ     BOOL ret = FALSE;
1519eb902e5bSKatayama Hirofumi MZ     PIMC pIMC;
1520eb902e5bSKatayama Hirofumi MZ 
1521eb902e5bSKatayama Hirofumi MZ     UserEnterExclusive();
1522eb902e5bSKatayama Hirofumi MZ 
1523eb902e5bSKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1524eb902e5bSKatayama Hirofumi MZ     {
1525eb902e5bSKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1526eb902e5bSKatayama Hirofumi MZ         goto Quit;
1527eb902e5bSKatayama Hirofumi MZ     }
1528eb902e5bSKatayama Hirofumi MZ 
1529eb902e5bSKatayama Hirofumi MZ     pIMC = UserGetObjectNoErr(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
1530eb902e5bSKatayama Hirofumi MZ     if (pIMC)
1531eb902e5bSKatayama Hirofumi MZ         ret = IntDestroyInputContext(pIMC);
15321bc9dda5SKatayama Hirofumi MZ 
15331bc9dda5SKatayama Hirofumi MZ Quit:
15343d78601fSKatayama Hirofumi MZ     UserLeave();
15353d78601fSKatayama Hirofumi MZ     return ret;
15363d78601fSKatayama Hirofumi MZ }
1537c2c66affSColin Finck 
15382f7775c6SKatayama Hirofumi MZ // Win: CreateInputContext
1539470aa276SKatayama Hirofumi MZ PIMC FASTCALL UserCreateInputContext(ULONG_PTR dwClientImcData)
1540470aa276SKatayama Hirofumi MZ {
1541470aa276SKatayama Hirofumi MZ     PIMC pIMC;
1542470aa276SKatayama Hirofumi MZ     PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
1543470aa276SKatayama Hirofumi MZ     PDESKTOP pdesk = pti->rpdesk;
1544470aa276SKatayama Hirofumi MZ 
1545470aa276SKatayama Hirofumi MZ     if (!IS_IMM_MODE() || (pti->TIF_flags & TIF_DISABLEIME)) // Disabled?
1546b5c9d532SKatayama Hirofumi MZ     {
1547b5c9d532SKatayama Hirofumi MZ         ERR("IME is disabled\n");
1548470aa276SKatayama Hirofumi MZ         return NULL;
1549b5c9d532SKatayama Hirofumi MZ     }
1550470aa276SKatayama Hirofumi MZ 
1551470aa276SKatayama Hirofumi MZ     if (!pdesk) // No desktop?
1552470aa276SKatayama Hirofumi MZ         return NULL;
1553470aa276SKatayama Hirofumi MZ 
1554470aa276SKatayama Hirofumi MZ     // pti->spDefaultImc should be already set if non-first time.
1555470aa276SKatayama Hirofumi MZ     if (dwClientImcData && !pti->spDefaultImc)
1556470aa276SKatayama Hirofumi MZ         return NULL;
1557470aa276SKatayama Hirofumi MZ 
1558470aa276SKatayama Hirofumi MZ     // Create an input context user object.
1559470aa276SKatayama Hirofumi MZ     pIMC = UserCreateObject(gHandleTable, pdesk, pti, NULL, TYPE_INPUTCONTEXT, sizeof(IMC));
1560470aa276SKatayama Hirofumi MZ     if (!pIMC)
1561470aa276SKatayama Hirofumi MZ         return NULL;
1562470aa276SKatayama Hirofumi MZ 
1563470aa276SKatayama Hirofumi MZ     // Release the extra reference (UserCreateObject added 2 references).
1564470aa276SKatayama Hirofumi MZ     UserDereferenceObject(pIMC);
15654a748a3aSKatayama Hirofumi MZ     ASSERT(pIMC->head.cLockObj == 1);
1566470aa276SKatayama Hirofumi MZ 
1567470aa276SKatayama Hirofumi MZ     if (dwClientImcData) // Non-first time.
1568470aa276SKatayama Hirofumi MZ     {
1569470aa276SKatayama Hirofumi MZ         // Insert pIMC to the second position (non-default) of the list.
1570470aa276SKatayama Hirofumi MZ         pIMC->pImcNext = pti->spDefaultImc->pImcNext;
1571470aa276SKatayama Hirofumi MZ         pti->spDefaultImc->pImcNext = pIMC;
1572470aa276SKatayama Hirofumi MZ     }
1573470aa276SKatayama Hirofumi MZ     else // First time. It's the default IMC.
1574470aa276SKatayama Hirofumi MZ     {
1575470aa276SKatayama Hirofumi MZ         // Add the first one (default) to the list.
15767e138837SKatayama Hirofumi MZ         UserAssignmentLock((PVOID*)&pti->spDefaultImc, pIMC);
1577470aa276SKatayama Hirofumi MZ         pIMC->pImcNext = NULL;
15784a748a3aSKatayama Hirofumi MZ         ASSERT(pIMC->head.cLockObj == 2); // UserAssignmentUnlock'ed at ExitThreadCallback
1579470aa276SKatayama Hirofumi MZ     }
1580470aa276SKatayama Hirofumi MZ 
1581470aa276SKatayama Hirofumi MZ     pIMC->dwClientImcData = dwClientImcData; // Set it.
1582470aa276SKatayama Hirofumi MZ     return pIMC;
1583470aa276SKatayama Hirofumi MZ }
1584470aa276SKatayama Hirofumi MZ 
1585470aa276SKatayama Hirofumi MZ HIMC
1586e52ce89bSKatayama Hirofumi MZ NTAPI
1587470aa276SKatayama Hirofumi MZ NtUserCreateInputContext(ULONG_PTR dwClientImcData)
1588470aa276SKatayama Hirofumi MZ {
1589470aa276SKatayama Hirofumi MZ     PIMC pIMC;
1590470aa276SKatayama Hirofumi MZ     HIMC ret = NULL;
1591470aa276SKatayama Hirofumi MZ 
1592470aa276SKatayama Hirofumi MZ     UserEnterExclusive();
1593470aa276SKatayama Hirofumi MZ 
1594470aa276SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1595b5c9d532SKatayama Hirofumi MZ     {
1596b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
159788c1d8c7SKatayama Hirofumi MZ         EngSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
159888c1d8c7SKatayama Hirofumi MZ         goto Quit;
159988c1d8c7SKatayama Hirofumi MZ     }
160088c1d8c7SKatayama Hirofumi MZ 
160188c1d8c7SKatayama Hirofumi MZ     if (!dwClientImcData)
160288c1d8c7SKatayama Hirofumi MZ     {
160388c1d8c7SKatayama Hirofumi MZ         EngSetLastError(ERROR_INVALID_PARAMETER);
1604470aa276SKatayama Hirofumi MZ         goto Quit;
1605b5c9d532SKatayama Hirofumi MZ     }
1606470aa276SKatayama Hirofumi MZ 
1607470aa276SKatayama Hirofumi MZ     pIMC = UserCreateInputContext(dwClientImcData);
1608470aa276SKatayama Hirofumi MZ     if (pIMC)
1609470aa276SKatayama Hirofumi MZ         ret = UserHMGetHandle(pIMC);
1610470aa276SKatayama Hirofumi MZ 
1611470aa276SKatayama Hirofumi MZ Quit:
1612470aa276SKatayama Hirofumi MZ     UserLeave();
1613470aa276SKatayama Hirofumi MZ     return ret;
1614470aa276SKatayama Hirofumi MZ }
1615470aa276SKatayama Hirofumi MZ 
16162f7775c6SKatayama Hirofumi MZ // Win: AssociateInputContextEx
1617f2c3167dSKatayama Hirofumi MZ DWORD FASTCALL IntAssociateInputContextEx(PWND pWnd, PIMC pIMC, DWORD dwFlags)
1618f2c3167dSKatayama Hirofumi MZ {
1619f2c3167dSKatayama Hirofumi MZ     DWORD ret = 0;
1620f2c3167dSKatayama Hirofumi MZ     PWINDOWLIST pwl;
1621f2c3167dSKatayama Hirofumi MZ     BOOL bIgnoreNullImc = (dwFlags & IACE_IGNORENOCONTEXT);
1622f2c3167dSKatayama Hirofumi MZ     PTHREADINFO pti = pWnd->head.pti;
1623f2c3167dSKatayama Hirofumi MZ     PWND pwndTarget, pwndFocus = pti->MessageQueue->spwndFocus;
1624f2c3167dSKatayama Hirofumi MZ     HWND *phwnd;
1625f2c3167dSKatayama Hirofumi MZ     HIMC hIMC;
1626f2c3167dSKatayama Hirofumi MZ 
1627f2c3167dSKatayama Hirofumi MZ     if (dwFlags & IACE_DEFAULT)
1628f2c3167dSKatayama Hirofumi MZ     {
1629f2c3167dSKatayama Hirofumi MZ         pIMC = pti->spDefaultImc;
1630f2c3167dSKatayama Hirofumi MZ     }
1631f2c3167dSKatayama Hirofumi MZ     else
1632f2c3167dSKatayama Hirofumi MZ     {
1633f2c3167dSKatayama Hirofumi MZ         if (pIMC && pti != pIMC->head.pti)
1634f2c3167dSKatayama Hirofumi MZ             return 2;
1635f2c3167dSKatayama Hirofumi MZ     }
1636f2c3167dSKatayama Hirofumi MZ 
1637f2c3167dSKatayama Hirofumi MZ     if (pWnd->head.pti->ppi != GetW32ThreadInfo()->ppi ||
1638f2c3167dSKatayama Hirofumi MZ         (pIMC && pIMC->head.rpdesk != pWnd->head.rpdesk))
1639f2c3167dSKatayama Hirofumi MZ     {
1640f2c3167dSKatayama Hirofumi MZ         return 2;
1641f2c3167dSKatayama Hirofumi MZ     }
1642f2c3167dSKatayama Hirofumi MZ 
1643f2c3167dSKatayama Hirofumi MZ     if ((dwFlags & IACE_CHILDREN) && pWnd->spwndChild)
1644f2c3167dSKatayama Hirofumi MZ     {
1645f2c3167dSKatayama Hirofumi MZ         pwl = IntBuildHwndList(pWnd->spwndChild, IACE_CHILDREN | IACE_LIST, pti);
1646f2c3167dSKatayama Hirofumi MZ         if (pwl)
1647f2c3167dSKatayama Hirofumi MZ         {
1648f2c3167dSKatayama Hirofumi MZ             for (phwnd = pwl->ahwnd; *phwnd != HWND_TERMINATOR; ++phwnd)
1649f2c3167dSKatayama Hirofumi MZ             {
1650f2c3167dSKatayama Hirofumi MZ                 pwndTarget = ValidateHwndNoErr(*phwnd);
1651f2c3167dSKatayama Hirofumi MZ                 if (!pwndTarget)
1652f2c3167dSKatayama Hirofumi MZ                     continue;
1653f2c3167dSKatayama Hirofumi MZ 
1654f2c3167dSKatayama Hirofumi MZ                 hIMC = (pIMC ? UserHMGetHandle(pIMC) : NULL);
1655f2c3167dSKatayama Hirofumi MZ                 if (pwndTarget->hImc == hIMC || (bIgnoreNullImc && !pwndTarget->hImc))
1656f2c3167dSKatayama Hirofumi MZ                     continue;
1657f2c3167dSKatayama Hirofumi MZ 
1658f2c3167dSKatayama Hirofumi MZ                 IntAssociateInputContext(pwndTarget, pIMC);
1659f2c3167dSKatayama Hirofumi MZ                 if (pwndTarget == pwndFocus)
1660f2c3167dSKatayama Hirofumi MZ                     ret = 1;
1661f2c3167dSKatayama Hirofumi MZ             }
1662f2c3167dSKatayama Hirofumi MZ 
1663f2c3167dSKatayama Hirofumi MZ             IntFreeHwndList(pwl);
1664f2c3167dSKatayama Hirofumi MZ         }
1665f2c3167dSKatayama Hirofumi MZ     }
1666f2c3167dSKatayama Hirofumi MZ 
1667f2c3167dSKatayama Hirofumi MZ     if (!bIgnoreNullImc || pWnd->hImc)
1668f2c3167dSKatayama Hirofumi MZ     {
1669f2c3167dSKatayama Hirofumi MZ         hIMC = (pIMC ? UserHMGetHandle(pIMC) : NULL);
1670f2c3167dSKatayama Hirofumi MZ         if (pWnd->hImc != hIMC)
1671f2c3167dSKatayama Hirofumi MZ         {
1672f2c3167dSKatayama Hirofumi MZ             IntAssociateInputContext(pWnd, pIMC);
1673f2c3167dSKatayama Hirofumi MZ             if (pWnd == pwndFocus)
1674f2c3167dSKatayama Hirofumi MZ                 ret = 1;
1675f2c3167dSKatayama Hirofumi MZ         }
1676f2c3167dSKatayama Hirofumi MZ     }
1677f2c3167dSKatayama Hirofumi MZ 
1678f2c3167dSKatayama Hirofumi MZ     return ret;
1679f2c3167dSKatayama Hirofumi MZ }
1680f2c3167dSKatayama Hirofumi MZ 
1681470aa276SKatayama Hirofumi MZ DWORD
1682e52ce89bSKatayama Hirofumi MZ NTAPI
1683470aa276SKatayama Hirofumi MZ NtUserAssociateInputContext(HWND hWnd, HIMC hIMC, DWORD dwFlags)
1684470aa276SKatayama Hirofumi MZ {
1685f2c3167dSKatayama Hirofumi MZ     DWORD ret = 2;
1686f2c3167dSKatayama Hirofumi MZ     PWND pWnd;
1687f2c3167dSKatayama Hirofumi MZ     PIMC pIMC;
1688f2c3167dSKatayama Hirofumi MZ 
1689f2c3167dSKatayama Hirofumi MZ     UserEnterExclusive();
1690f2c3167dSKatayama Hirofumi MZ 
1691b5c9d532SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1692b5c9d532SKatayama Hirofumi MZ     {
1693b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
1694b5c9d532SKatayama Hirofumi MZ         goto Quit;
1695b5c9d532SKatayama Hirofumi MZ     }
1696b5c9d532SKatayama Hirofumi MZ 
1697f2c3167dSKatayama Hirofumi MZ     pWnd = ValidateHwndNoErr(hWnd);
1698b5c9d532SKatayama Hirofumi MZ     if (!pWnd)
1699f2c3167dSKatayama Hirofumi MZ         goto Quit;
1700f2c3167dSKatayama Hirofumi MZ 
1701f2c3167dSKatayama Hirofumi MZ     pIMC = (hIMC ? UserGetObjectNoErr(gHandleTable, hIMC, TYPE_INPUTCONTEXT) : NULL);
1702f2c3167dSKatayama Hirofumi MZ     ret = IntAssociateInputContextEx(pWnd, pIMC, dwFlags);
1703f2c3167dSKatayama Hirofumi MZ 
1704f2c3167dSKatayama Hirofumi MZ Quit:
1705f2c3167dSKatayama Hirofumi MZ     UserLeave();
1706f2c3167dSKatayama Hirofumi MZ     return ret;
1707470aa276SKatayama Hirofumi MZ }
1708470aa276SKatayama Hirofumi MZ 
17095df5ef2bSKatayama Hirofumi MZ // Win: UpdateInputContext
1710470aa276SKatayama Hirofumi MZ BOOL FASTCALL UserUpdateInputContext(PIMC pIMC, DWORD dwType, DWORD_PTR dwValue)
1711470aa276SKatayama Hirofumi MZ {
1712470aa276SKatayama Hirofumi MZ     PTHREADINFO pti = GetW32ThreadInfo();
1713470aa276SKatayama Hirofumi MZ     PTHREADINFO ptiIMC = pIMC->head.pti;
1714470aa276SKatayama Hirofumi MZ 
1715470aa276SKatayama Hirofumi MZ     if (pti->ppi != ptiIMC->ppi) // Different process?
1716470aa276SKatayama Hirofumi MZ         return FALSE;
1717470aa276SKatayama Hirofumi MZ 
1718470aa276SKatayama Hirofumi MZ     switch (dwType)
1719470aa276SKatayama Hirofumi MZ     {
1720470aa276SKatayama Hirofumi MZ         case UIC_CLIENTIMCDATA:
1721470aa276SKatayama Hirofumi MZ             if (pIMC->dwClientImcData)
1722470aa276SKatayama Hirofumi MZ                 return FALSE; // Already set
1723470aa276SKatayama Hirofumi MZ 
1724470aa276SKatayama Hirofumi MZ             pIMC->dwClientImcData = dwValue;
1725470aa276SKatayama Hirofumi MZ             break;
1726470aa276SKatayama Hirofumi MZ 
1727470aa276SKatayama Hirofumi MZ         case UIC_IMEWINDOW:
1728470aa276SKatayama Hirofumi MZ             if (!ValidateHwndNoErr((HWND)dwValue))
1729470aa276SKatayama Hirofumi MZ                 return FALSE; // Invalid HWND
1730470aa276SKatayama Hirofumi MZ 
1731470aa276SKatayama Hirofumi MZ             pIMC->hImeWnd = (HWND)dwValue;
1732470aa276SKatayama Hirofumi MZ             break;
1733470aa276SKatayama Hirofumi MZ 
1734470aa276SKatayama Hirofumi MZ         default:
1735470aa276SKatayama Hirofumi MZ             return FALSE;
1736470aa276SKatayama Hirofumi MZ     }
1737470aa276SKatayama Hirofumi MZ 
1738470aa276SKatayama Hirofumi MZ     return TRUE;
1739470aa276SKatayama Hirofumi MZ }
1740470aa276SKatayama Hirofumi MZ 
1741470aa276SKatayama Hirofumi MZ BOOL
1742e52ce89bSKatayama Hirofumi MZ NTAPI
1743470aa276SKatayama Hirofumi MZ NtUserUpdateInputContext(
1744470aa276SKatayama Hirofumi MZ     HIMC hIMC,
1745470aa276SKatayama Hirofumi MZ     DWORD dwType,
1746470aa276SKatayama Hirofumi MZ     DWORD_PTR dwValue)
1747470aa276SKatayama Hirofumi MZ {
1748470aa276SKatayama Hirofumi MZ     PIMC pIMC;
1749470aa276SKatayama Hirofumi MZ     BOOL ret = FALSE;
1750470aa276SKatayama Hirofumi MZ 
1751470aa276SKatayama Hirofumi MZ     UserEnterExclusive();
1752470aa276SKatayama Hirofumi MZ 
1753470aa276SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1754b5c9d532SKatayama Hirofumi MZ     {
1755b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
1756470aa276SKatayama Hirofumi MZ         goto Quit;
1757b5c9d532SKatayama Hirofumi MZ     }
1758470aa276SKatayama Hirofumi MZ 
1759470aa276SKatayama Hirofumi MZ     pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
1760470aa276SKatayama Hirofumi MZ     if (!pIMC)
1761470aa276SKatayama Hirofumi MZ         goto Quit;
1762470aa276SKatayama Hirofumi MZ 
1763470aa276SKatayama Hirofumi MZ     ret = UserUpdateInputContext(pIMC, dwType, dwValue);
1764470aa276SKatayama Hirofumi MZ 
1765470aa276SKatayama Hirofumi MZ Quit:
1766470aa276SKatayama Hirofumi MZ     UserLeave();
1767470aa276SKatayama Hirofumi MZ     return ret;
1768470aa276SKatayama Hirofumi MZ }
1769470aa276SKatayama Hirofumi MZ 
1770470aa276SKatayama Hirofumi MZ DWORD_PTR
1771e52ce89bSKatayama Hirofumi MZ NTAPI
1772470aa276SKatayama Hirofumi MZ NtUserQueryInputContext(HIMC hIMC, DWORD dwType)
1773470aa276SKatayama Hirofumi MZ {
1774470aa276SKatayama Hirofumi MZ     PIMC pIMC;
1775470aa276SKatayama Hirofumi MZ     PTHREADINFO ptiIMC;
1776470aa276SKatayama Hirofumi MZ     DWORD_PTR ret = 0;
1777470aa276SKatayama Hirofumi MZ 
1778470aa276SKatayama Hirofumi MZ     UserEnterExclusive();
1779470aa276SKatayama Hirofumi MZ 
1780470aa276SKatayama Hirofumi MZ     if (!IS_IMM_MODE())
1781b5c9d532SKatayama Hirofumi MZ     {
1782b5c9d532SKatayama Hirofumi MZ         ERR("!IS_IMM_MODE()\n");
1783470aa276SKatayama Hirofumi MZ         goto Quit;
1784b5c9d532SKatayama Hirofumi MZ     }
1785470aa276SKatayama Hirofumi MZ 
1786470aa276SKatayama Hirofumi MZ     pIMC = UserGetObject(gHandleTable, hIMC, TYPE_INPUTCONTEXT);
1787470aa276SKatayama Hirofumi MZ     if (!pIMC)
1788470aa276SKatayama Hirofumi MZ         goto Quit;
1789470aa276SKatayama Hirofumi MZ 
1790470aa276SKatayama Hirofumi MZ     ptiIMC = pIMC->head.pti;
1791470aa276SKatayama Hirofumi MZ 
1792470aa276SKatayama Hirofumi MZ     switch (dwType)
1793470aa276SKatayama Hirofumi MZ     {
1794470aa276SKatayama Hirofumi MZ         case QIC_INPUTPROCESSID:
1795470aa276SKatayama Hirofumi MZ             ret = (DWORD_PTR)PsGetThreadProcessId(ptiIMC->pEThread);
1796470aa276SKatayama Hirofumi MZ             break;
1797470aa276SKatayama Hirofumi MZ 
1798470aa276SKatayama Hirofumi MZ         case QIC_INPUTTHREADID:
1799470aa276SKatayama Hirofumi MZ             ret = (DWORD_PTR)PsGetThreadId(ptiIMC->pEThread);
1800470aa276SKatayama Hirofumi MZ             break;
1801470aa276SKatayama Hirofumi MZ 
1802470aa276SKatayama Hirofumi MZ         case QIC_DEFAULTWINDOWIME:
1803470aa276SKatayama Hirofumi MZ             if (ptiIMC->spwndDefaultIme)
1804470aa276SKatayama Hirofumi MZ                 ret = (DWORD_PTR)UserHMGetHandle(ptiIMC->spwndDefaultIme);
1805470aa276SKatayama Hirofumi MZ             break;
1806470aa276SKatayama Hirofumi MZ 
1807470aa276SKatayama Hirofumi MZ         case QIC_DEFAULTIMC:
1808470aa276SKatayama Hirofumi MZ             if (ptiIMC->spDefaultImc)
1809470aa276SKatayama Hirofumi MZ                 ret = (DWORD_PTR)UserHMGetHandle(ptiIMC->spDefaultImc);
1810470aa276SKatayama Hirofumi MZ             break;
1811470aa276SKatayama Hirofumi MZ     }
1812470aa276SKatayama Hirofumi MZ 
1813470aa276SKatayama Hirofumi MZ Quit:
1814470aa276SKatayama Hirofumi MZ     UserLeave();
1815470aa276SKatayama Hirofumi MZ     return ret;
1816470aa276SKatayama Hirofumi MZ }
1817470aa276SKatayama Hirofumi MZ 
18184bcf23d1SKatayama Hirofumi MZ // Searchs a non-IME-related window of the same thread of pwndTarget,
18194bcf23d1SKatayama Hirofumi MZ // other than pwndTarget, around pwndParent. Returns TRUE if found.
18204bcf23d1SKatayama Hirofumi MZ //
18214bcf23d1SKatayama Hirofumi MZ // Win: IsChildSameThread
18224bcf23d1SKatayama Hirofumi MZ BOOL IntFindNonImeRelatedWndOfSameThread(PWND pwndParent, PWND pwndTarget)
18234bcf23d1SKatayama Hirofumi MZ {
18244bcf23d1SKatayama Hirofumi MZ     PWND pwnd, pwndOwner, pwndNode;
18254bcf23d1SKatayama Hirofumi MZ     PTHREADINFO ptiTarget = pwndTarget->head.pti;
18264bcf23d1SKatayama Hirofumi MZ 
18274bcf23d1SKatayama Hirofumi MZ     // For all the children of pwndParent, ...
18284bcf23d1SKatayama Hirofumi MZ     for (pwnd = pwndParent->spwndChild; pwnd; pwnd = pwnd->spwndNext)
18294bcf23d1SKatayama Hirofumi MZ     {
18304bcf23d1SKatayama Hirofumi MZ         if (pwnd == pwndTarget || pwnd->head.pti != ptiTarget || IS_WND_MENU(pwnd))
18314bcf23d1SKatayama Hirofumi MZ             continue;
18324bcf23d1SKatayama Hirofumi MZ 
18334bcf23d1SKatayama Hirofumi MZ         if (!IS_WND_CHILD(pwnd))
18344bcf23d1SKatayama Hirofumi MZ         {
18354bcf23d1SKatayama Hirofumi MZ             // Check if any IME-like owner.
18364bcf23d1SKatayama Hirofumi MZ             BOOL bFound1 = FALSE;
18374bcf23d1SKatayama Hirofumi MZ             for (pwndOwner = pwnd; pwndOwner; pwndOwner = pwndOwner->spwndOwner)
18384bcf23d1SKatayama Hirofumi MZ             {
18394bcf23d1SKatayama Hirofumi MZ                 if (IS_WND_IMELIKE(pwndOwner))
18404bcf23d1SKatayama Hirofumi MZ                 {
18414bcf23d1SKatayama Hirofumi MZ                     bFound1 = TRUE;
18424bcf23d1SKatayama Hirofumi MZ                     break;
18434bcf23d1SKatayama Hirofumi MZ                 }
18444bcf23d1SKatayama Hirofumi MZ             }
18454bcf23d1SKatayama Hirofumi MZ             if (bFound1)
18464bcf23d1SKatayama Hirofumi MZ                 continue; // Skip if any IME-like owner.
18474bcf23d1SKatayama Hirofumi MZ         }
18484bcf23d1SKatayama Hirofumi MZ 
18494bcf23d1SKatayama Hirofumi MZ         pwndNode = pwnd;
18504bcf23d1SKatayama Hirofumi MZ 
18514bcf23d1SKatayama Hirofumi MZ         if (IS_WND_CHILD(pwndNode))
18524bcf23d1SKatayama Hirofumi MZ         {
18534bcf23d1SKatayama Hirofumi MZ             // Check if any same-thread IME-like ancestor.
18544bcf23d1SKatayama Hirofumi MZ             BOOL bFound2 = FALSE;
18554bcf23d1SKatayama Hirofumi MZ             for (; IS_WND_CHILD(pwndNode); pwndNode = pwndNode->spwndParent)
18564bcf23d1SKatayama Hirofumi MZ             {
18574bcf23d1SKatayama Hirofumi MZ                 if (pwndNode->head.pti != ptiTarget)
18584bcf23d1SKatayama Hirofumi MZ                     break;
18594bcf23d1SKatayama Hirofumi MZ 
18604bcf23d1SKatayama Hirofumi MZ                 if (IS_WND_IMELIKE(pwndNode))
18614bcf23d1SKatayama Hirofumi MZ                 {
18624bcf23d1SKatayama Hirofumi MZ                     bFound2 = TRUE;
18634bcf23d1SKatayama Hirofumi MZ                     break;
18644bcf23d1SKatayama Hirofumi MZ                 }
18654bcf23d1SKatayama Hirofumi MZ             }
18664bcf23d1SKatayama Hirofumi MZ             if (bFound2)
18674bcf23d1SKatayama Hirofumi MZ                 continue;
18684bcf23d1SKatayama Hirofumi MZ             // Now, pwndNode is non-child or non-same-thread window.
18694bcf23d1SKatayama Hirofumi MZ         }
18704bcf23d1SKatayama Hirofumi MZ 
18714bcf23d1SKatayama Hirofumi MZ         if (!IS_WND_CHILD(pwndNode)) // pwndNode is non-child
18724bcf23d1SKatayama Hirofumi MZ         {
18734bcf23d1SKatayama Hirofumi MZ             // Check if any same-thread IME-like owner.
18744bcf23d1SKatayama Hirofumi MZ             BOOL bFound3 = FALSE;
18754bcf23d1SKatayama Hirofumi MZ             for (; pwndNode; pwndNode = pwndNode->spwndOwner)
18764bcf23d1SKatayama Hirofumi MZ             {
18774bcf23d1SKatayama Hirofumi MZ                 if (pwndNode->head.pti != ptiTarget)
18784bcf23d1SKatayama Hirofumi MZ                     break;
18794bcf23d1SKatayama Hirofumi MZ 
18804bcf23d1SKatayama Hirofumi MZ                 if (IS_WND_IMELIKE(pwndNode))
18814bcf23d1SKatayama Hirofumi MZ                 {
18824bcf23d1SKatayama Hirofumi MZ                     bFound3 = TRUE;
18834bcf23d1SKatayama Hirofumi MZ                     break;
18844bcf23d1SKatayama Hirofumi MZ                 }
18854bcf23d1SKatayama Hirofumi MZ             }
18864bcf23d1SKatayama Hirofumi MZ             if (bFound3)
18874bcf23d1SKatayama Hirofumi MZ                 continue;
18884bcf23d1SKatayama Hirofumi MZ         }
18894bcf23d1SKatayama Hirofumi MZ 
18904bcf23d1SKatayama Hirofumi MZ         return TRUE;
18914bcf23d1SKatayama Hirofumi MZ     }
18924bcf23d1SKatayama Hirofumi MZ 
18934bcf23d1SKatayama Hirofumi MZ     return FALSE;
18944bcf23d1SKatayama Hirofumi MZ }
18954bcf23d1SKatayama Hirofumi MZ 
18968f719cb9SKatayama Hirofumi MZ // Determines whether the target window needs the IME window.
18978f719cb9SKatayama Hirofumi MZ // Win: WantImeWindow(pwndParent, pwndTarget)
18988f719cb9SKatayama Hirofumi MZ BOOL FASTCALL IntWantImeWindow(PWND pwndTarget)
18998f719cb9SKatayama Hirofumi MZ {
19008f719cb9SKatayama Hirofumi MZ     PDESKTOP rpdesk;
19018f719cb9SKatayama Hirofumi MZ     PWINSTATION_OBJECT rpwinstaParent;
19028f719cb9SKatayama Hirofumi MZ     PWND pwndNode, pwndParent = pwndTarget->spwndParent;
19038f719cb9SKatayama Hirofumi MZ 
19048f719cb9SKatayama Hirofumi MZ     if (gptiCurrent->TIF_flags & TIF_DISABLEIME)
19058f719cb9SKatayama Hirofumi MZ         return FALSE;
19068f719cb9SKatayama Hirofumi MZ 
19078f719cb9SKatayama Hirofumi MZ     if (IS_WND_IMELIKE(pwndTarget))
19088f719cb9SKatayama Hirofumi MZ         return FALSE;
19098f719cb9SKatayama Hirofumi MZ 
19108f719cb9SKatayama Hirofumi MZ     if (pwndTarget->fnid == FNID_DESKTOP || pwndTarget->fnid == FNID_MESSAGEWND)
19118f719cb9SKatayama Hirofumi MZ         return FALSE;
19128f719cb9SKatayama Hirofumi MZ 
19138f719cb9SKatayama Hirofumi MZ     if (pwndTarget->state & WNDS_SERVERSIDEWINDOWPROC)
19148f719cb9SKatayama Hirofumi MZ         return FALSE;
19158f719cb9SKatayama Hirofumi MZ 
19168f719cb9SKatayama Hirofumi MZ     rpdesk = pwndTarget->head.rpdesk;
19178f719cb9SKatayama Hirofumi MZ     if (!rpdesk)
19188f719cb9SKatayama Hirofumi MZ         return FALSE;
19198f719cb9SKatayama Hirofumi MZ 
19208f719cb9SKatayama Hirofumi MZ     rpwinstaParent = rpdesk->rpwinstaParent;
19218f719cb9SKatayama Hirofumi MZ     if (!rpwinstaParent || (rpwinstaParent->Flags & WSS_NOIO))
19228f719cb9SKatayama Hirofumi MZ         return FALSE;
19238f719cb9SKatayama Hirofumi MZ 
19248f719cb9SKatayama Hirofumi MZ     for (pwndNode = pwndParent; pwndNode; pwndNode = pwndNode->spwndParent)
19258f719cb9SKatayama Hirofumi MZ     {
19268f719cb9SKatayama Hirofumi MZ         if (rpdesk != pwndNode->head.rpdesk)
19278f719cb9SKatayama Hirofumi MZ             break;
19288f719cb9SKatayama Hirofumi MZ 
19298f719cb9SKatayama Hirofumi MZ         if (pwndNode == rpdesk->spwndMessage)
19308f719cb9SKatayama Hirofumi MZ             return FALSE;
19318f719cb9SKatayama Hirofumi MZ     }
19328f719cb9SKatayama Hirofumi MZ 
19338f719cb9SKatayama Hirofumi MZ     return TRUE;
19348f719cb9SKatayama Hirofumi MZ }
19358f719cb9SKatayama Hirofumi MZ 
19368f719cb9SKatayama Hirofumi MZ // Create the default IME window for the target window.
19378f719cb9SKatayama Hirofumi MZ // Win: xxxCreateDefaultImeWindow(pwndTarget, ATOM, hInst)
19388f719cb9SKatayama Hirofumi MZ PWND FASTCALL co_IntCreateDefaultImeWindow(PWND pwndTarget, HINSTANCE hInst)
19398f719cb9SKatayama Hirofumi MZ {
19408f719cb9SKatayama Hirofumi MZ     LARGE_UNICODE_STRING WindowName;
19418f719cb9SKatayama Hirofumi MZ     UNICODE_STRING ClassName;
19428f719cb9SKatayama Hirofumi MZ     PWND pImeWnd;
19438f719cb9SKatayama Hirofumi MZ     PIMEUI pimeui;
19448f719cb9SKatayama Hirofumi MZ     CREATESTRUCTW Cs;
19458f719cb9SKatayama Hirofumi MZ     USER_REFERENCE_ENTRY Ref;
19468f719cb9SKatayama Hirofumi MZ     PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
19478f719cb9SKatayama Hirofumi MZ     HANDLE pid = PsGetThreadProcessId(pti->pEThread);
19488f719cb9SKatayama Hirofumi MZ 
19498f719cb9SKatayama Hirofumi MZ     if (!(pti->spDefaultImc) && pid == gpidLogon)
19508f719cb9SKatayama Hirofumi MZ         UserCreateInputContext(0);
19518f719cb9SKatayama Hirofumi MZ 
19528f719cb9SKatayama Hirofumi MZ     if (!(pti->spDefaultImc) || IS_WND_IMELIKE(pwndTarget) || !(pti->rpdesk->pheapDesktop))
19538f719cb9SKatayama Hirofumi MZ         return NULL;
19548f719cb9SKatayama Hirofumi MZ 
19558f719cb9SKatayama Hirofumi MZ     if (IS_WND_CHILD(pwndTarget) && !(pwndTarget->style & WS_VISIBLE) &&
19568f719cb9SKatayama Hirofumi MZ         pwndTarget->spwndParent->head.pti->ppi != pti->ppi)
19578f719cb9SKatayama Hirofumi MZ     {
19588f719cb9SKatayama Hirofumi MZ         return NULL;
19598f719cb9SKatayama Hirofumi MZ     }
19608f719cb9SKatayama Hirofumi MZ 
19618f719cb9SKatayama Hirofumi MZ     RtlInitLargeUnicodeString(&WindowName, L"Default IME", 0);
19628f719cb9SKatayama Hirofumi MZ 
19638f719cb9SKatayama Hirofumi MZ     ClassName.Buffer = (PWCH)(ULONG_PTR)gpsi->atomSysClass[ICLS_IME];
19648f719cb9SKatayama Hirofumi MZ     ClassName.Length = 0;
19658f719cb9SKatayama Hirofumi MZ     ClassName.MaximumLength = 0;
19668f719cb9SKatayama Hirofumi MZ 
19678f719cb9SKatayama Hirofumi MZ     UserRefObjectCo(pwndTarget, &Ref);
19688f719cb9SKatayama Hirofumi MZ 
19698f719cb9SKatayama Hirofumi MZ     RtlZeroMemory(&Cs, sizeof(Cs));
19708f719cb9SKatayama Hirofumi MZ     Cs.style = WS_POPUP | WS_DISABLED;
19718f719cb9SKatayama Hirofumi MZ     Cs.hInstance = hInst;
19728f719cb9SKatayama Hirofumi MZ     Cs.hwndParent = UserHMGetHandle(pwndTarget);
19738f719cb9SKatayama Hirofumi MZ     Cs.lpszName = WindowName.Buffer;
19748f719cb9SKatayama Hirofumi MZ     Cs.lpszClass = ClassName.Buffer;
19758f719cb9SKatayama Hirofumi MZ 
19768f719cb9SKatayama Hirofumi MZ     // NOTE: LARGE_UNICODE_STRING is compatible to LARGE_STRING.
19778f719cb9SKatayama Hirofumi MZ     pImeWnd = co_UserCreateWindowEx(&Cs, &ClassName, (PLARGE_STRING)&WindowName, NULL, WINVER);
19788f719cb9SKatayama Hirofumi MZ     if (pImeWnd)
19798f719cb9SKatayama Hirofumi MZ     {
19808f719cb9SKatayama Hirofumi MZ         pimeui = ((PIMEWND)pImeWnd)->pimeui;
19818f719cb9SKatayama Hirofumi MZ         _SEH2_TRY
19828f719cb9SKatayama Hirofumi MZ         {
19838f719cb9SKatayama Hirofumi MZ             ProbeForWrite(pimeui, sizeof(IMEUI), 1);
19848f719cb9SKatayama Hirofumi MZ             pimeui->fDefault = TRUE;
19858f719cb9SKatayama Hirofumi MZ             if (IS_WND_CHILD(pwndTarget) && pwndTarget->spwndParent->head.pti != pti)
19868f719cb9SKatayama Hirofumi MZ                 pimeui->fChildThreadDef = TRUE;
19878f719cb9SKatayama Hirofumi MZ         }
19888f719cb9SKatayama Hirofumi MZ         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
19898f719cb9SKatayama Hirofumi MZ         {
19908f719cb9SKatayama Hirofumi MZ             NOTHING;
19918f719cb9SKatayama Hirofumi MZ         }
19928f719cb9SKatayama Hirofumi MZ         _SEH2_END;
19938f719cb9SKatayama Hirofumi MZ     }
19948f719cb9SKatayama Hirofumi MZ 
19958f719cb9SKatayama Hirofumi MZ     UserDerefObjectCo(pwndTarget);
19968f719cb9SKatayama Hirofumi MZ     return pImeWnd;
19978f719cb9SKatayama Hirofumi MZ }
19988f719cb9SKatayama Hirofumi MZ 
19998f719cb9SKatayama Hirofumi MZ // Determines whether the system can destroy the default IME window for the target child window.
20004bcf23d1SKatayama Hirofumi MZ // Win: ImeCanDestroyDefIMEforChild
20014bcf23d1SKatayama Hirofumi MZ BOOL FASTCALL IntImeCanDestroyDefIMEforChild(PWND pImeWnd, PWND pwndTarget)
20024bcf23d1SKatayama Hirofumi MZ {
20034bcf23d1SKatayama Hirofumi MZ     PWND pwndNode;
20044bcf23d1SKatayama Hirofumi MZ     PIMEUI pimeui;
20054bcf23d1SKatayama Hirofumi MZ     IMEUI SafeImeUI;
20064bcf23d1SKatayama Hirofumi MZ 
20074bcf23d1SKatayama Hirofumi MZ     pimeui = ((PIMEWND)pImeWnd)->pimeui;
20084bcf23d1SKatayama Hirofumi MZ     if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
20094bcf23d1SKatayama Hirofumi MZ         return FALSE;
20104bcf23d1SKatayama Hirofumi MZ 
20114bcf23d1SKatayama Hirofumi MZ     // Check IMEUI.fChildThreadDef
20124bcf23d1SKatayama Hirofumi MZ     _SEH2_TRY
20134bcf23d1SKatayama Hirofumi MZ     {
20144bcf23d1SKatayama Hirofumi MZ         ProbeForRead(pimeui, sizeof(IMEUI), 1);
20154bcf23d1SKatayama Hirofumi MZ         SafeImeUI = *pimeui;
20164bcf23d1SKatayama Hirofumi MZ         if (!SafeImeUI.fChildThreadDef)
20174bcf23d1SKatayama Hirofumi MZ             return FALSE;
20184bcf23d1SKatayama Hirofumi MZ     }
20194bcf23d1SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
20204bcf23d1SKatayama Hirofumi MZ     {
20218f719cb9SKatayama Hirofumi MZ         NOTHING;
20224bcf23d1SKatayama Hirofumi MZ     }
20234bcf23d1SKatayama Hirofumi MZ     _SEH2_END;
20244bcf23d1SKatayama Hirofumi MZ 
20254bcf23d1SKatayama Hirofumi MZ     // The parent of pwndTarget is NULL or of the same thread of pwndTarget?
20264bcf23d1SKatayama Hirofumi MZ     if (pwndTarget->spwndParent == NULL ||
20274bcf23d1SKatayama Hirofumi MZ         pwndTarget->head.pti == pwndTarget->spwndParent->head.pti)
20284bcf23d1SKatayama Hirofumi MZ     {
20294bcf23d1SKatayama Hirofumi MZ         return FALSE;
20304bcf23d1SKatayama Hirofumi MZ     }
20314bcf23d1SKatayama Hirofumi MZ 
20324bcf23d1SKatayama Hirofumi MZ     for (pwndNode = pwndTarget; pwndNode; pwndNode = pwndNode->spwndParent)
20334bcf23d1SKatayama Hirofumi MZ     {
20344bcf23d1SKatayama Hirofumi MZ         if (pwndNode == pwndNode->head.rpdesk->pDeskInfo->spwnd)
20354bcf23d1SKatayama Hirofumi MZ             break;
20364bcf23d1SKatayama Hirofumi MZ 
20374bcf23d1SKatayama Hirofumi MZ         if (IntFindNonImeRelatedWndOfSameThread(pwndNode->spwndParent, pwndTarget))
20384bcf23d1SKatayama Hirofumi MZ             return FALSE;
20394bcf23d1SKatayama Hirofumi MZ     }
20404bcf23d1SKatayama Hirofumi MZ 
20414bcf23d1SKatayama Hirofumi MZ     return TRUE;
20424bcf23d1SKatayama Hirofumi MZ }
20434bcf23d1SKatayama Hirofumi MZ 
20448f719cb9SKatayama Hirofumi MZ // Determines whether the system can destroy the default IME window for the non-child target window.
20454bcf23d1SKatayama Hirofumi MZ // Win: ImeCanDestroyDefIME
20464bcf23d1SKatayama Hirofumi MZ BOOL FASTCALL IntImeCanDestroyDefIME(PWND pImeWnd, PWND pwndTarget)
20474bcf23d1SKatayama Hirofumi MZ {
20484bcf23d1SKatayama Hirofumi MZ     PWND pwndNode;
20494bcf23d1SKatayama Hirofumi MZ     PIMEUI pimeui;
20504bcf23d1SKatayama Hirofumi MZ     IMEUI SafeImeUI;
20514bcf23d1SKatayama Hirofumi MZ 
20524bcf23d1SKatayama Hirofumi MZ     pimeui = ((PIMEWND)pImeWnd)->pimeui;
20534bcf23d1SKatayama Hirofumi MZ     if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
20544bcf23d1SKatayama Hirofumi MZ         return FALSE;
20554bcf23d1SKatayama Hirofumi MZ 
20564bcf23d1SKatayama Hirofumi MZ     // Check IMEUI.fDestroy
20574bcf23d1SKatayama Hirofumi MZ     _SEH2_TRY
20584bcf23d1SKatayama Hirofumi MZ     {
20594bcf23d1SKatayama Hirofumi MZ         ProbeForRead(pimeui, sizeof(IMEUI), 1);
20604bcf23d1SKatayama Hirofumi MZ         SafeImeUI = *pimeui;
20614bcf23d1SKatayama Hirofumi MZ         if (SafeImeUI.fDestroy)
20624bcf23d1SKatayama Hirofumi MZ             return FALSE;
20634bcf23d1SKatayama Hirofumi MZ     }
20644bcf23d1SKatayama Hirofumi MZ     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
20654bcf23d1SKatayama Hirofumi MZ     {
20668f719cb9SKatayama Hirofumi MZ         NOTHING;
20674bcf23d1SKatayama Hirofumi MZ     }
20684bcf23d1SKatayama Hirofumi MZ     _SEH2_END;
20694bcf23d1SKatayama Hirofumi MZ 
20704bcf23d1SKatayama Hirofumi MZ     // Any ancestor of pImeWnd is pwndTarget?
20714bcf23d1SKatayama Hirofumi MZ     if (pImeWnd->spwndOwner)
20724bcf23d1SKatayama Hirofumi MZ     {
20734bcf23d1SKatayama Hirofumi MZ         for (pwndNode = pImeWnd->spwndOwner; pwndNode; pwndNode = pwndNode->spwndOwner)
20744bcf23d1SKatayama Hirofumi MZ         {
20754bcf23d1SKatayama Hirofumi MZ             if (pwndNode == pwndTarget)
20764bcf23d1SKatayama Hirofumi MZ                 break;
20774bcf23d1SKatayama Hirofumi MZ         }
20784bcf23d1SKatayama Hirofumi MZ 
20794bcf23d1SKatayama Hirofumi MZ         if (!pwndNode)
20804bcf23d1SKatayama Hirofumi MZ             return FALSE;
20814bcf23d1SKatayama Hirofumi MZ     }
20824bcf23d1SKatayama Hirofumi MZ 
20834bcf23d1SKatayama Hirofumi MZ     // Any ancestor of pwndTarget is IME-like?
20844bcf23d1SKatayama Hirofumi MZ     for (pwndNode = pwndTarget; pwndNode; pwndNode = pwndNode->spwndOwner)
20854bcf23d1SKatayama Hirofumi MZ     {
20864bcf23d1SKatayama Hirofumi MZ         if (IS_WND_IMELIKE(pwndNode))
20874bcf23d1SKatayama Hirofumi MZ             return FALSE;
20884bcf23d1SKatayama Hirofumi MZ     }
20894bcf23d1SKatayama Hirofumi MZ 
20904bcf23d1SKatayama Hirofumi MZ     // Adjust the ordering and top-mode status
20914bcf23d1SKatayama Hirofumi MZ     IntImeSetFutureOwner(pImeWnd, pwndTarget);
20924bcf23d1SKatayama Hirofumi MZ     for (pwndNode = pImeWnd->spwndOwner; pwndNode; pwndNode = pwndNode->spwndNext)
20934bcf23d1SKatayama Hirofumi MZ     {
20944bcf23d1SKatayama Hirofumi MZ         if (pwndNode == pImeWnd)
20954bcf23d1SKatayama Hirofumi MZ             break;
20964bcf23d1SKatayama Hirofumi MZ     }
20974bcf23d1SKatayama Hirofumi MZ     if (pwndNode == pImeWnd)
20984bcf23d1SKatayama Hirofumi MZ         IntImeCheckTopmost(pImeWnd);
20994bcf23d1SKatayama Hirofumi MZ 
21004bcf23d1SKatayama Hirofumi MZ     // Is the owner of pImeWnd NULL or pwndTarget?
21014bcf23d1SKatayama Hirofumi MZ     if (pImeWnd->spwndOwner && pwndTarget != pImeWnd->spwndOwner)
21024bcf23d1SKatayama Hirofumi MZ         return FALSE;
21034bcf23d1SKatayama Hirofumi MZ 
21044bcf23d1SKatayama Hirofumi MZ     pImeWnd->spwndOwner = NULL;
21054bcf23d1SKatayama Hirofumi MZ     return TRUE;
21064bcf23d1SKatayama Hirofumi MZ }
21074bcf23d1SKatayama Hirofumi MZ 
2108c2c66affSColin Finck /* EOF */
2109