diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index 0ffa9ea15d9..dee47c9e9e7 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -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( diff --git a/win32ss/user/ntuser/ime.c b/win32ss/user/ntuser/ime.c index ec84f155e27..d897c67369c 100644 --- a/win32ss/user/ntuser/ime.c +++ b/win32ss/user/ntuser/ime.c @@ -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) diff --git a/win32ss/user/user32/controls/regcontrol.c b/win32ss/user/user32/controls/regcontrol.c index 3360841ffc6..6d80f6c25dc 100644 --- a/win32ss/user/user32/controls/regcontrol.c +++ b/win32ss/user/user32/controls/regcontrol.c @@ -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; } diff --git a/win32ss/user/user32/include/regcontrol.h b/win32ss/user/user32/include/regcontrol.h index f1b3b69bf03..c84ee0d9694 100644 --- a/win32ss/user/user32/include/regcontrol.h +++ b/win32ss/user/user32/include/regcontrol.h @@ -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); diff --git a/win32ss/user/user32/misc/imm.c b/win32ss/user/user32/misc/imm.c index 44c88d52c4e..4a455b864f9 100644 --- a/win32ss/user/user32/misc/imm.c +++ b/win32ss/user/user32/misc/imm.c @@ -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