https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8f719cb97e8e2148ef149edb984e60a9a95b30c2

commit 8f719cb97e8e2148ef149edb984e60a9a95b30c2
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sat Apr 23 07:11:48 2022 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sat Apr 23 07:11:48 2022 +0900

    [NTUSER][IMM32] Create the default IME window! (retry) (#4463)
    
    The default IME window has to be created for each top-level window in 
specific condition. It is needed for implementing Japanese input.
    - Add IntFocusSetInputContext helper function.
    - Call IntFocusSetInputContext after sending WM_KILLFOCUS message.
    - Add IntWantImeWindow, co_IntCreateDefaultImeWindow, and 
IntDestroyOwnedWindows helper functions.
    - Create the default IME window (spwndDefaultIme) for the specified window 
at IntCreateWindow.
    - Fix Imm32InternalLockIMC function.
    CORE-11700
---
 dll/win32/imm32/imm.c          |  19 ++++---
 sdk/include/ddk/immdev.h       |   5 ++
 win32ss/user/ntuser/focus.c    |  60 +++++++++++++++++++++-
 win32ss/user/ntuser/ime.c      | 112 +++++++++++++++++++++++++++++++++++++++--
 win32ss/user/ntuser/window.c   | 109 +++++++++++++++++++++++++++------------
 win32ss/user/ntuser/window.h   |   2 +
 win32ss/user/user32/misc/imm.c |   6 +--
 7 files changed, 265 insertions(+), 48 deletions(-)

diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c
index 5d199630229..45328abb595 100644
--- a/dll/win32/imm32/imm.c
+++ b/dll/win32/imm32/imm.c
@@ -830,7 +830,13 @@ LPINPUTCONTEXT APIENTRY Imm32InternalLockIMC(HIMC hIMC, 
BOOL fSelect)
     RtlEnterCriticalSection(&pClientImc->cs);
 
     if (pClientImc->hInputContext)
-        goto Finish;
+    {
+        pIC = LocalLock(pClientImc->hInputContext);
+        if (pIC)
+            goto Success;
+        else
+            goto Failure;
+    }
 
     dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID);
     if (dwThreadId == GetCurrentThreadId() && Imm32IsCiceroMode() && 
!Imm32Is16BitMode())
@@ -847,14 +853,14 @@ LPINPUTCONTEXT APIENTRY Imm32InternalLockIMC(HIMC hIMC, 
BOOL fSelect)
     }
 
     if (!NtUserQueryInputContext(hIMC, QIC_DEFAULTWINDOWIME))
-        goto Quit;
+        goto Failure;
 
     hIC = LocalAlloc(LHND, sizeof(INPUTCONTEXTDX));
     pIC = LocalLock(hIC);
     if (!pIC)
     {
         LocalFree(hIC);
-        goto Quit;
+        goto Failure;
     }
     pClientImc->hInputContext = hIC;
 
@@ -862,17 +868,17 @@ LPINPUTCONTEXT APIENTRY Imm32InternalLockIMC(HIMC hIMC, 
BOOL fSelect)
     if (!Imm32CreateInputContext(hIMC, pIC, pClientImc, hNewKL, fSelect))
     {
         pClientImc->hInputContext = LocalFree(pClientImc->hInputContext);
-        goto Quit;
+        goto Failure;
     }
 
-Finish:
+Success:
     CtfImmTIMCreateInputContext(hIMC);
     RtlLeaveCriticalSection(&pClientImc->cs);
     InterlockedIncrement(&pClientImc->cLockObj);
     ImmUnlockClientImc(pClientImc);
     return pIC;
 
-Quit:
+Failure:
     RtlLeaveCriticalSection(&pClientImc->cs);
     ImmUnlockClientImc(pClientImc);
     return NULL;
@@ -1243,6 +1249,7 @@ BOOL WINAPI ImmSetActiveContextConsoleIME(HWND hwnd, BOOL 
fFlag)
 
 BOOL WINAPI User32InitializeImmEntryTable(DWORD);
 
+// Win: ImmDllInitialize
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
 {
     HKL hKL;
diff --git a/sdk/include/ddk/immdev.h b/sdk/include/ddk/immdev.h
index 61641ba1633..58bbc1dc1d6 100644
--- a/sdk/include/ddk/immdev.h
+++ b/sdk/include/ddk/immdev.h
@@ -24,6 +24,11 @@ extern "C" {
 #define IMC_GETSOFTKBDPOS               0x0013
 #define IMC_SETSOFTKBDPOS               0x0014
 
+/* wParam for WM_IME_SYSTEM */
+#define IMS_IMEACTIVATE         0x17
+#define IMS_IMEDEACTIVATE       0x18
+#define IMS_ACTIVATELAYOUT      0x19
+
 #define IMMGWL_IMC       0
 #define IMMGWL_PRIVATE   (sizeof(LONG))
 
diff --git a/win32ss/user/ntuser/focus.c b/win32ss/user/ntuser/focus.c
index a9ea0965177..7ecb9c88f73 100644
--- a/win32ss/user/ntuser/focus.c
+++ b/win32ss/user/ntuser/focus.c
@@ -7,6 +7,7 @@
  */
 
 #include <win32k.h>
+#include <ddk/immdev.h>
 DBG_DEFAULT_CHANNEL(UserFocus);
 
 PUSER_MESSAGE_QUEUE gpqForeground = NULL;
@@ -145,11 +146,47 @@ co_IntSendDeactivateMessages(HWND hWndPrev, HWND hWnd, 
BOOL Clear)
    return Ret;
 }
 
+// Win: xxxFocusSetInputContext
+VOID IntFocusSetInputContext(PWND pWnd, BOOL bActivate, BOOL bCallback)
+{
+    PTHREADINFO pti;
+    PWND pImeWnd;
+    USER_REFERENCE_ENTRY Ref;
+    HWND hImeWnd;
+    WPARAM wParam;
+    LPARAM lParam;
+
+    if (!pWnd || !pWnd->pcls || IS_WND_IMELIKE(pWnd))
+        return;
+
+    pti = pWnd->head.pti;
+    if (!pti || (pti->TIF_flags & TIF_INCLEANUP))
+        return;
+
+    pImeWnd = pti->spwndDefaultIme;
+    if (!pImeWnd)
+        return;
+
+    UserRefObjectCo(pImeWnd, &Ref);
+
+    hImeWnd = UserHMGetHandle(pImeWnd);
+    wParam = (bActivate ? IMS_IMEACTIVATE : IMS_IMEDEACTIVATE);
+    lParam = (LPARAM)UserHMGetHandle(pWnd);
+
+    if (bCallback)
+        co_IntSendMessageWithCallBack(hImeWnd, WM_IME_SYSTEM, wParam, lParam, 
NULL, 0, NULL);
+    else
+        co_IntSendMessage(hImeWnd, WM_IME_SYSTEM, wParam, lParam);
+
+    UserDerefObjectCo(pImeWnd);
+}
+
 //
 // Deactivating the foreground message queue.
 //
 // Release Active, Capture and Focus Windows associated with this message 
queue.
 //
+// Win: xxxDeactivate
 BOOL FASTCALL
 IntDeactivateWindow(PTHREADINFO pti, HANDLE tid)
 {
@@ -297,6 +334,10 @@ IntDeactivateWindow(PTHREADINFO pti, HANDLE tid)
 
       UserRefObjectCo(pwndFocus, &Ref);
       co_IntSendMessage(UserHMGetHandle(pwndFocus), WM_KILLFOCUS, 0, 0);
+      if (IS_IMM_MODE())
+      {
+         IntFocusSetInputContext(pwndFocus, FALSE, FALSE);
+      }
       UserDerefObjectCo(pwndFocus);
    }
 
@@ -569,11 +610,13 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, 
BOOL MouseActivate, BOO
    return InAAPM;
 }
 
+// Win: xxxSendFocusMessages
 VOID FASTCALL
 IntSendFocusMessages( PTHREADINFO pti, PWND pWnd)
 {
    PWND pWndPrev;
    PUSER_MESSAGE_QUEUE ThreadQueue = pti->MessageQueue; // Queue can change...
+   HWND hwndPrev;
 
    ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE;
    if (!pWnd && ThreadQueue->spwndActive)
@@ -593,12 +636,22 @@ IntSendFocusMessages( PTHREADINFO pti, PWND pWnd)
       if (pWndPrev)
       {
          co_IntSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, 
(WPARAM)UserHMGetHandle(pWnd), 0);
+         if (IS_IMM_MODE())
+         {
+            IntFocusSetInputContext(pWndPrev, FALSE, FALSE);
+         }
       }
       if (ThreadQueue->spwndFocus == pWnd)
       {
+         if (IS_IMM_MODE())
+         {
+            IntFocusSetInputContext(pWnd, TRUE, FALSE);
+         }
+
          IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, 
CHILDID_SELF, 0);
 
-         co_IntSendMessage(UserHMGetHandle(pWnd), WM_SETFOCUS, 
(WPARAM)(pWndPrev ? UserHMGetHandle(pWndPrev) : NULL), 0);
+         hwndPrev = (pWndPrev ? UserHMGetHandle(pWndPrev) : NULL);
+         co_IntSendMessage(UserHMGetHandle(pWnd), WM_SETFOCUS, 
(WPARAM)hwndPrev, 0);
       }
    }
    else
@@ -608,6 +661,10 @@ IntSendFocusMessages( PTHREADINFO pti, PWND pWnd)
          IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, 
CHILDID_SELF, 0);
 
          co_IntSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, 0, 0);
+         if (IS_IMM_MODE())
+         {
+            IntFocusSetInputContext(pWndPrev, FALSE, FALSE);
+         }
       }
    }
 }
@@ -1241,6 +1298,7 @@ UserSetActiveWindow( _In_opt_ PWND Wnd )
   return FALSE;
 }
 
+// Win: PWND xxxSetFocus(Window)
 HWND FASTCALL
 co_UserSetFocus(PWND Window)
 {
diff --git a/win32ss/user/ntuser/ime.c b/win32ss/user/ntuser/ime.c
index e869608724f..f8cd3778512 100644
--- a/win32ss/user/ntuser/ime.c
+++ b/win32ss/user/ntuser/ime.c
@@ -1889,7 +1889,110 @@ BOOL IntFindNonImeRelatedWndOfSameThread(PWND 
pwndParent, PWND pwndTarget)
     return FALSE;
 }
 
-// Can we destroy the default IME window for the target child window?
+// Determines whether the target window needs the IME window.
+// Win: WantImeWindow(pwndParent, pwndTarget)
+BOOL FASTCALL IntWantImeWindow(PWND pwndTarget)
+{
+    PDESKTOP rpdesk;
+    PWINSTATION_OBJECT rpwinstaParent;
+    PWND pwndNode, pwndParent = pwndTarget->spwndParent;
+
+    if (gptiCurrent->TIF_flags & TIF_DISABLEIME)
+        return FALSE;
+
+    if (IS_WND_IMELIKE(pwndTarget))
+        return FALSE;
+
+    if (pwndTarget->fnid == FNID_DESKTOP || pwndTarget->fnid == 
FNID_MESSAGEWND)
+        return FALSE;
+
+    if (pwndTarget->state & WNDS_SERVERSIDEWINDOWPROC)
+        return FALSE;
+
+    rpdesk = pwndTarget->head.rpdesk;
+    if (!rpdesk)
+        return FALSE;
+
+    rpwinstaParent = rpdesk->rpwinstaParent;
+    if (!rpwinstaParent || (rpwinstaParent->Flags & WSS_NOIO))
+        return FALSE;
+
+    for (pwndNode = pwndParent; pwndNode; pwndNode = pwndNode->spwndParent)
+    {
+        if (rpdesk != pwndNode->head.rpdesk)
+            break;
+
+        if (pwndNode == rpdesk->spwndMessage)
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+// Create the default IME window for the target window.
+// Win: xxxCreateDefaultImeWindow(pwndTarget, ATOM, hInst)
+PWND FASTCALL co_IntCreateDefaultImeWindow(PWND pwndTarget, HINSTANCE hInst)
+{
+    LARGE_UNICODE_STRING WindowName;
+    UNICODE_STRING ClassName;
+    PWND pImeWnd;
+    PIMEUI pimeui;
+    CREATESTRUCTW Cs;
+    USER_REFERENCE_ENTRY Ref;
+    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+    HANDLE pid = PsGetThreadProcessId(pti->pEThread);
+
+    if (!(pti->spDefaultImc) && pid == gpidLogon)
+        UserCreateInputContext(0);
+
+    if (!(pti->spDefaultImc) || IS_WND_IMELIKE(pwndTarget) || 
!(pti->rpdesk->pheapDesktop))
+        return NULL;
+
+    if (IS_WND_CHILD(pwndTarget) && !(pwndTarget->style & WS_VISIBLE) &&
+        pwndTarget->spwndParent->head.pti->ppi != pti->ppi)
+    {
+        return NULL;
+    }
+
+    RtlInitLargeUnicodeString(&WindowName, L"Default IME", 0);
+
+    ClassName.Buffer = (PWCH)(ULONG_PTR)gpsi->atomSysClass[ICLS_IME];
+    ClassName.Length = 0;
+    ClassName.MaximumLength = 0;
+
+    UserRefObjectCo(pwndTarget, &Ref);
+
+    RtlZeroMemory(&Cs, sizeof(Cs));
+    Cs.style = WS_POPUP | WS_DISABLED;
+    Cs.hInstance = hInst;
+    Cs.hwndParent = UserHMGetHandle(pwndTarget);
+    Cs.lpszName = WindowName.Buffer;
+    Cs.lpszClass = ClassName.Buffer;
+
+    // NOTE: LARGE_UNICODE_STRING is compatible to LARGE_STRING.
+    pImeWnd = co_UserCreateWindowEx(&Cs, &ClassName, 
(PLARGE_STRING)&WindowName, NULL, WINVER);
+    if (pImeWnd)
+    {
+        pimeui = ((PIMEWND)pImeWnd)->pimeui;
+        _SEH2_TRY
+        {
+            ProbeForWrite(pimeui, sizeof(IMEUI), 1);
+            pimeui->fDefault = TRUE;
+            if (IS_WND_CHILD(pwndTarget) && pwndTarget->spwndParent->head.pti 
!= pti)
+                pimeui->fChildThreadDef = TRUE;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            NOTHING;
+        }
+        _SEH2_END;
+    }
+
+    UserDerefObjectCo(pwndTarget);
+    return pImeWnd;
+}
+
+// Determines whether the system can destroy the default IME window for the 
target child window.
 // Win: ImeCanDestroyDefIMEforChild
 BOOL FASTCALL IntImeCanDestroyDefIMEforChild(PWND pImeWnd, PWND pwndTarget)
 {
@@ -1911,7 +2014,7 @@ BOOL FASTCALL IntImeCanDestroyDefIMEforChild(PWND 
pImeWnd, PWND pwndTarget)
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        ;
+        NOTHING;
     }
     _SEH2_END;
 
@@ -1934,8 +2037,7 @@ BOOL FASTCALL IntImeCanDestroyDefIMEforChild(PWND 
pImeWnd, PWND pwndTarget)
     return TRUE;
 }
 
-// Can we destroy the default IME window for the non-child target window?
-// If so, this function sets spwndOwner to NULL.
+// Determines whether the system can destroy the default IME window for the 
non-child target window.
 // Win: ImeCanDestroyDefIME
 BOOL FASTCALL IntImeCanDestroyDefIME(PWND pImeWnd, PWND pwndTarget)
 {
@@ -1957,7 +2059,7 @@ BOOL FASTCALL IntImeCanDestroyDefIME(PWND pImeWnd, PWND 
pwndTarget)
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        ;
+        NOTHING;
     }
     _SEH2_END;
 
diff --git a/win32ss/user/ntuser/window.c b/win32ss/user/ntuser/window.c
index 9ec554b4a24..a740fcc11e8 100644
--- a/win32ss/user/ntuser/window.c
+++ b/win32ss/user/ntuser/window.c
@@ -8,6 +8,7 @@
  */
 
 #include <win32k.h>
+#include <ddk/immdev.h>
 DBG_DEFAULT_CHANNEL(UserWnd);
 
 INT gNestedWindowLimit = 50;
@@ -658,8 +659,16 @@ LRESULT co_UserFreeWindow(PWND Window,
          ThreadData->rpdesk->rpwinstaParent->ShellListView = NULL;
    }
 
+   if (ThreadData->spwndDefaultIme &&
+       ThreadData->spwndDefaultIme->spwndOwner == Window)
+   {
+      ThreadData->spwndDefaultIme->spwndOwner = NULL;
+   }
+
    if (IS_IMM_MODE() && Window == ThreadData->spwndDefaultIme)
+   {
       UserAssignmentUnlock((PVOID*)&(ThreadData->spwndDefaultIme));
+   }
 
    /* Fixes dialog test_focus breakage due to r66237. */
    if (ThreadData->MessageQueue->spwndFocus == Window)
@@ -1775,7 +1784,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
 {
    PWND pWnd = NULL;
    HWND hWnd;
-   PTHREADINFO pti = NULL;
+   PTHREADINFO pti;
    BOOL MenuChanged;
    BOOL bUnicodeWindow;
    PCALLPROCDATA pcpd;
@@ -2027,6 +2036,28 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
       pWnd->strName.MaximumLength = WindowName->Length + sizeof(UNICODE_NULL);
    }
 
+   /* Create the IME window for pWnd */
+   if (IS_IMM_MODE() && !(pti->spwndDefaultIme) && IntWantImeWindow(pWnd))
+   {
+      PWND pwndDefaultIme = co_IntCreateDefaultImeWindow(pWnd, pWnd->hModule);
+      UserAssignmentLock((PVOID*)&(pti->spwndDefaultIme), pwndDefaultIme);
+
+      if (pwndDefaultIme && (pti->pClientInfo->CI_flags & CI_IMMACTIVATE))
+      {
+         USER_REFERENCE_ENTRY Ref;
+         HKL hKL;
+
+         UserRefObjectCo(pwndDefaultIme, &Ref);
+
+         hKL = pti->KeyboardLayout->hkl;
+         co_IntSendMessage(UserHMGetHandle(pwndDefaultIme), WM_IME_SYSTEM,
+                           IMS_ACTIVATELAYOUT, (LPARAM)hKL);
+         pti->pClientInfo->CI_flags &= ~CI_IMMACTIVATE;
+
+         UserDerefObjectCo(pwndDefaultIme);
+      }
+   }
+
    /* Correct the window style. */
    if ((pWnd->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
    {
@@ -2133,7 +2164,6 @@ Error:
 
 /*
  * @implemented
- * Win: xxxCreateWindowEx
  */
 PWND FASTCALL
 co_UserCreateWindowEx(CREATESTRUCTW* Cs,
@@ -2748,6 +2778,49 @@ cleanup:
    return hwnd;
 }
 
+// Win: xxxDW_DestroyOwnedWindows
+VOID FASTCALL IntDestroyOwnedWindows(PWND Window)
+{
+    HWND* List;
+    HWND* phWnd;
+    PWND pWnd;
+    PTHREADINFO pti = Window->head.pti;
+    USER_REFERENCE_ENTRY Ref;
+
+    List = IntWinListOwnedPopups(Window);
+    if (!List)
+        return;
+
+    for (phWnd = List; *phWnd; ++phWnd)
+    {
+        pWnd = ValidateHwndNoErr(*phWnd);
+        if (pWnd == NULL)
+            continue;
+        ASSERT(pWnd->spwndOwner == Window);
+        ASSERT(pWnd != Window);
+
+        if (IS_IMM_MODE() && !(pti->TIF_flags & TIF_INCLEANUP) &&
+            pWnd == pti->spwndDefaultIme)
+        {
+            continue;
+        }
+
+        pWnd->spwndOwner = NULL;
+        if (IntWndBelongsToThread(pWnd, PsGetCurrentThreadWin32Thread()))
+        {
+            UserRefObjectCo(pWnd, &Ref); // Temp HACK?
+            co_UserDestroyWindow(pWnd);
+            UserDerefObjectCo(pWnd); // Temp HACK?
+        }
+        else
+        {
+            ERR("IntWndBelongsToThread(0x%p) is FALSE, ignoring.\n", pWnd);
+        }
+    }
+
+    ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
+}
+
 // Win: xxxDestroyWindow
 BOOLEAN co_UserDestroyWindow(PVOID Object)
 {
@@ -2876,37 +2949,7 @@ BOOLEAN co_UserDestroyWindow(PVOID Object)
     /* Recursively destroy owned windows */
     if (!(Window->style & WS_CHILD))
     {
-        HWND* List;
-        HWND* phWnd;
-        PWND pWnd;
-
-        List = IntWinListOwnedPopups(Window);
-        if (List)
-        {
-            for (phWnd = List; *phWnd; ++phWnd)
-            {
-                pWnd = ValidateHwndNoErr(*phWnd);
-                if (pWnd == NULL)
-                    continue;
-                ASSERT(pWnd->spwndOwner == Window);
-                ASSERT(pWnd != Window);
-
-                pWnd->spwndOwner = NULL;
-                if (IntWndBelongsToThread(pWnd, 
PsGetCurrentThreadWin32Thread()))
-                {
-                    USER_REFERENCE_ENTRY Ref;
-                    UserRefObjectCo(pWnd, &Ref); // Temp HACK?
-                    co_UserDestroyWindow(pWnd);
-                    UserDerefObjectCo(pWnd); // Temp HACK?
-                }
-                else
-                {
-                    ERR("IntWndBelongsToThread(0x%p) is FALSE, ignoring.\n", 
pWnd);
-                }
-            }
-
-            ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
-        }
+        IntDestroyOwnedWindows(Window);
     }
 
     /* Generate mouse move message for the next window */
diff --git a/win32ss/user/ntuser/window.h b/win32ss/user/ntuser/window.h
index 86daff24d97..a093e4e4ee8 100644
--- a/win32ss/user/ntuser/window.h
+++ b/win32ss/user/ntuser/window.h
@@ -112,6 +112,8 @@ VOID FASTCALL IntFreeHwndList(PWINDOWLIST pwlTarget);
     (((pWnd)->pcls->style & CS_IME) || \
      ((pWnd)->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]))
 
+BOOL FASTCALL IntWantImeWindow(PWND pwndTarget);
+PWND FASTCALL co_IntCreateDefaultImeWindow(PWND pwndTarget, HINSTANCE hInst);
 BOOL FASTCALL IntImeCanDestroyDefIMEforChild(PWND pImeWnd, PWND pwndTarget);
 BOOL FASTCALL IntImeCanDestroyDefIME(PWND pImeWnd, PWND pwndTarget);
 
diff --git a/win32ss/user/user32/misc/imm.c b/win32ss/user/user32/misc/imm.c
index 6fa8eafd1d6..f14db5ddf15 100644
--- a/win32ss/user/user32/misc/imm.c
+++ b/win32ss/user/user32/misc/imm.c
@@ -664,15 +664,15 @@ static LRESULT ImeWnd_OnImeSystem(PIMEUI pimeui, WPARAM 
wParam, LPARAM lParam)
             // TODO:
             break;
 
-        case 0x17:
+        case IMS_IMEACTIVATE:
             User32SetImeActivenessOfWindow((HWND)lParam, TRUE);
             break;
 
-        case 0x18:
+        case IMS_IMEDEACTIVATE:
             User32SetImeActivenessOfWindow((HWND)lParam, FALSE);
             break;
 
-        case 0x19:
+        case IMS_ACTIVATELAYOUT:
             ret = IMM_FN(ImmActivateLayout)((HKL)lParam);
             break;
 

Reply via email to