mirror of
https://github.com/reactos/reactos.git
synced 2026-06-03 01:41:13 +08:00
[NTUSER][USER32] Fix IME UI exception (#8227)
Fix BSoD when toggling visibility of the IME status window (IME Toolbar). JIRA issue: CORE-20261 - Add IntGetImeUIFromWnd helper function. - Fix exception in IntNotifyImeShowStatus function. - Fix initialization of IME UI in ImeWndProc_common function. - Delete RegisterIMEClass function.
This commit is contained in:
committed by
GitHub
parent
38d07d3a24
commit
e7358c5930
@@ -1235,13 +1235,17 @@ typedef struct tagIMEUI
|
||||
DWORD dwLastStatus;
|
||||
} IMEUI, *PIMEUI;
|
||||
|
||||
/* Window Extra data container. */
|
||||
typedef struct _IMEWND
|
||||
typedef struct tagIMEWND
|
||||
{
|
||||
WND wnd;
|
||||
PIMEUI pimeui;
|
||||
} IMEWND, *PIMEWND;
|
||||
|
||||
#define GWLP_IMEWND_PIMEUI 0
|
||||
|
||||
/* IMEWND and GWLP_IMEWND_PIMEUI assume this alignment */
|
||||
C_ASSERT(sizeof(WND) % sizeof(PVOID) == 0);
|
||||
|
||||
DWORD
|
||||
NTAPI
|
||||
NtUserAssociateInputContext(
|
||||
|
||||
@@ -40,6 +40,13 @@ typedef struct tagIMEHOTKEY
|
||||
PIMEHOTKEY gpImeHotKeyList = NULL;
|
||||
LCID glcidSystem = 0;
|
||||
|
||||
static inline PIMEUI FASTCALL IntGetImeUIFromWnd(_In_ PWND pWnd)
|
||||
{
|
||||
ASSERT(pWnd->cbwndExtra >= sizeof(PIMEUI));
|
||||
PIMEWND pImeWnd = (PIMEWND)pWnd;
|
||||
return pImeWnd->pimeui;
|
||||
}
|
||||
|
||||
static DWORD FASTCALL
|
||||
IntGetImeCompatFlags(_In_opt_ PTHREADINFO pti)
|
||||
{
|
||||
@@ -2089,10 +2096,11 @@ co_IntCreateDefaultImeWindow(
|
||||
pImeWnd = co_UserCreateWindowEx(&Cs, &ClassName, (PLARGE_STRING)&WindowName, NULL, WINVER);
|
||||
if (pImeWnd)
|
||||
{
|
||||
pimeui = ((PIMEWND)pImeWnd)->pimeui;
|
||||
pimeui = IntGetImeUIFromWnd(pImeWnd);
|
||||
ASSERT(pimeui);
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite(pimeui, sizeof(IMEUI), 1);
|
||||
ProbeForWrite(pimeui, sizeof(*pimeui), 1);
|
||||
pimeui->fDefault = TRUE;
|
||||
if (IS_WND_CHILD(pwndTarget) && pwndTarget->spwndParent->head.pti != pti)
|
||||
pimeui->fChildThreadDef = TRUE;
|
||||
@@ -2118,8 +2126,8 @@ IntImeCanDestroyDefIMEforChild(
|
||||
PIMEUI pimeui;
|
||||
IMEUI SafeImeUI;
|
||||
|
||||
pimeui = ((PIMEWND)pImeWnd)->pimeui;
|
||||
if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
|
||||
pimeui = IntGetImeUIFromWnd(pImeWnd);
|
||||
if (!pimeui)
|
||||
return FALSE;
|
||||
|
||||
// Check IMEUI.fChildThreadDef
|
||||
@@ -2165,8 +2173,8 @@ IntImeCanDestroyDefIME(
|
||||
PIMEUI pimeui;
|
||||
IMEUI SafeImeUI;
|
||||
|
||||
pimeui = ((PIMEWND)pImeWnd)->pimeui;
|
||||
if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
|
||||
pimeui = IntGetImeUIFromWnd(pImeWnd);
|
||||
if (!pimeui)
|
||||
return FALSE;
|
||||
|
||||
// Check IMEUI.fDestroy
|
||||
@@ -2257,8 +2265,8 @@ IntCheckImeShowStatus(
|
||||
continue;
|
||||
}
|
||||
|
||||
pimeui = ((PIMEWND)pwndNode)->pimeui;
|
||||
if (!pimeui || pimeui == (PIMEUI)-1)
|
||||
pimeui = IntGetImeUIFromWnd(pwndNode);
|
||||
if (!pimeui)
|
||||
continue;
|
||||
|
||||
if (pti && pti != pwndNode->head.pti)
|
||||
@@ -2425,7 +2433,7 @@ IntSendOpenStatusNotify(PTHREADINFO ptiIME, PIMEUI pimeui, PWND pWnd, BOOL bOpen
|
||||
}
|
||||
}
|
||||
|
||||
// Update the IME status and send a notification.
|
||||
// Update the IME toolbar visibility and send a notification
|
||||
VOID FASTCALL
|
||||
IntNotifyImeShowStatus(_In_ PWND pImeWnd)
|
||||
{
|
||||
@@ -2441,6 +2449,13 @@ IntNotifyImeShowStatus(_In_ PWND pImeWnd)
|
||||
pti = PsGetCurrentThreadWin32Thread();
|
||||
ptiIME = pImeWnd->head.pti;
|
||||
|
||||
pimeui = IntGetImeUIFromWnd(pImeWnd);
|
||||
if (!pimeui)
|
||||
{
|
||||
ERR("Invalid IMEWND %p\n", pImeWnd);
|
||||
return;
|
||||
}
|
||||
|
||||
// Attach to the process if necessary
|
||||
if (pti != ptiIME)
|
||||
KeAttachProcess(&(ptiIME->ppi->peProcess->Pcb));
|
||||
@@ -2448,8 +2463,7 @@ IntNotifyImeShowStatus(_In_ PWND pImeWnd)
|
||||
// Get an IMEUI and check whether hwndIMC is valid and update fShowStatus
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite(pImeWnd, sizeof(IMEWND), 1);
|
||||
pimeui = ((PIMEWND)pImeWnd)->pimeui;
|
||||
ProbeForWrite(pimeui, sizeof(*pimeui), 1);
|
||||
SafeImeUI = *pimeui;
|
||||
|
||||
bShow = (gfIMEShowStatus == TRUE) && SafeImeUI.fCtrlShowStatus;
|
||||
@@ -2466,7 +2480,7 @@ IntNotifyImeShowStatus(_In_ PWND pImeWnd)
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
ERR("Exception in IntNotifyImeShowStatus: %p, %p, %p, %d, %d\n",
|
||||
ERR("Exception in IntNotifyImeShowStatus: %p, %p, %p, %d, %d\n",
|
||||
pImeWnd, pimeui, ptiIME, SafeImeUI.fCtrlShowStatus, gfIMEShowStatus);
|
||||
|
||||
if (pti != ptiIME)
|
||||
|
||||
@@ -65,6 +65,7 @@ static const struct
|
||||
/* { &ICONTITLE_builtin_class, FNID_ICONTITLE, ICLS_ICONTITLE}, // moved to win32k */
|
||||
{ &STATIC_builtin_class, FNID_STATIC, ICLS_STATIC},
|
||||
{ &GHOST_builtin_class, FNID_GHOST, ICLS_GHOST},
|
||||
{ &IME_builtin_class, FNID_IME, ICLS_IME},
|
||||
};
|
||||
|
||||
BOOL WINAPI RegisterSystemControls(VOID)
|
||||
@@ -81,6 +82,12 @@ BOOL WINAPI RegisterSystemControls(VOID)
|
||||
|
||||
for (i = 0; i != sizeof(g_SysClasses) / sizeof(g_SysClasses[0]); i++)
|
||||
{
|
||||
if (g_SysClasses[i].fnid == FNID_IME)
|
||||
{
|
||||
if (!IS_IMM_MODE() || (RegisterDefaultClasses & ICLASS_TO_MASK(ICLS_IME)))
|
||||
continue;
|
||||
}
|
||||
|
||||
WndClass.lpszClassName = g_SysClasses[i].desc->name;
|
||||
|
||||
// Set Global bit!
|
||||
@@ -99,12 +106,6 @@ BOOL WINAPI RegisterSystemControls(VOID)
|
||||
RegisterDefaultClasses |= ICLASS_TO_MASK(g_SysClasses[i].ClsId);
|
||||
}
|
||||
|
||||
if ( //gpsi->dwSRVIFlags & SRVINFO_IMM32 && Not supported yet, need NlsMbCodePageTag working in Win32k.
|
||||
!(RegisterDefaultClasses & ICLASS_TO_MASK(ICLS_IME))) // So, work like XP.
|
||||
{
|
||||
RegisterIMEClass();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ extern const struct builtin_class_descr MENU_builtin_class;
|
||||
extern const struct builtin_class_descr SCROLL_builtin_class;
|
||||
extern const struct builtin_class_descr STATIC_builtin_class;
|
||||
extern const struct builtin_class_descr GHOST_builtin_class;
|
||||
extern const struct builtin_class_descr IME_builtin_class;
|
||||
|
||||
ATOM WINAPI RegisterClassExWOWW(WNDCLASSEXW *,LPDWORD,WORD,DWORD,BOOL);
|
||||
BOOL FASTCALL VersionRegisterClass(PCWSTR,LPCWSTR,HANDLE,HMODULE *);
|
||||
@@ -46,4 +47,3 @@ BOOL FASTCALL VersionRegisterClass(PCWSTR,LPCWSTR,HANDLE,HMODULE *);
|
||||
LRESULT WINAPI ImeWndProc_common(HWND,UINT,WPARAM,LPARAM,BOOL);
|
||||
LRESULT WINAPI ImeWndProcA(HWND,UINT,WPARAM,LPARAM);
|
||||
LRESULT WINAPI ImeWndProcW(HWND,UINT,WPARAM,LPARAM);
|
||||
BOOL WINAPI RegisterIMEClass(VOID);
|
||||
|
||||
@@ -1009,20 +1009,27 @@ ImeWndProc_common(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicod
|
||||
return 0;
|
||||
}
|
||||
|
||||
pimeui = (PIMEUI)GetWindowLongPtrW(hwnd, 0);
|
||||
if (pimeui == NULL)
|
||||
if (msg == WM_NCCREATE)
|
||||
{
|
||||
pimeui = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMEUI));
|
||||
if (pimeui == NULL)
|
||||
if (!pimeui)
|
||||
{
|
||||
ERR("HeapAlloc failed\n");
|
||||
NtUserSetWindowFNID(hwnd, FNID_DESTROY);
|
||||
DestroyWindow(hwnd);
|
||||
return FALSE;
|
||||
}
|
||||
pimeui->spwnd = pWnd;
|
||||
SetWindowLongPtrW(hwnd, GWLP_IMEWND_PIMEUI, (LONG_PTR)pimeui);
|
||||
}
|
||||
else
|
||||
{
|
||||
pimeui = (PIMEUI)GetWindowLongPtrW(hwnd, GWLP_IMEWND_PIMEUI);
|
||||
if (!pimeui)
|
||||
{
|
||||
ERR("Invalid IMEWND\n");
|
||||
NtUserSetWindowFNID(hwnd, FNID_DESTROY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SetWindowLongPtrW(hwnd, 0, (LONG_PTR)pimeui);
|
||||
pimeui->spwnd = pWnd;
|
||||
}
|
||||
|
||||
if (IS_CICERO_MODE())
|
||||
@@ -1173,30 +1180,16 @@ BOOL WINAPI UpdatePerUserImmEnabling(VOID)
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
RegisterIMEClass(VOID)
|
||||
const struct builtin_class_descr IME_builtin_class =
|
||||
{
|
||||
ATOM atom;
|
||||
WNDCLASSEXW WndClass = { sizeof(WndClass) };
|
||||
|
||||
WndClass.lpszClassName = L"IME";
|
||||
WndClass.style = CS_GLOBALCLASS;
|
||||
WndClass.lpfnWndProc = ImeWndProcW;
|
||||
WndClass.cbWndExtra = sizeof(LONG_PTR);
|
||||
WndClass.hCursor = LoadCursorW(NULL, IDC_ARROW);
|
||||
|
||||
atom = RegisterClassExWOWW(&WndClass, 0, FNID_IME, 0, FALSE);
|
||||
if (!atom)
|
||||
{
|
||||
ERR("Failed to register IME Class!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RegisterDefaultClasses |= ICLASS_TO_MASK(ICLS_IME);
|
||||
TRACE("RegisterIMEClass atom = %u\n", atom);
|
||||
return TRUE;
|
||||
}
|
||||
L"IME", /* name */
|
||||
CS_GLOBALCLASS, /* style */
|
||||
ImeWndProcA, /* procA */
|
||||
ImeWndProcW, /* procW */
|
||||
sizeof(IMEWND) - sizeof(WND), /* extra */
|
||||
IDC_ARROW, /* cursor */
|
||||
NULL /* brush */
|
||||
};
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
|
||||
Reference in New Issue
Block a user