diff --git a/dll/win32/imm32/CMakeLists.txt b/dll/win32/imm32/CMakeLists.txt index b765ec172ab..60b146b10fa 100644 --- a/dll/win32/imm32/CMakeLists.txt +++ b/dll/win32/imm32/CMakeLists.txt @@ -45,6 +45,6 @@ list(APPEND imm32_rc_deps add_library(imm32 MODULE ${SOURCE} imm32.rc) set_module_type(imm32 win32dll UNICODE ENTRYPOINT ImmDllInitialize 12) set_source_files_properties(imm32.rc PROPERTIES OBJECT_DEPENDS "${imm32_rc_deps}") -target_link_libraries(imm32 wine win32ksys) +target_link_libraries(imm32 wine win32ksys uuid) add_importlibs(imm32 advapi32 user32 gdi32 kernel32 ntdll) add_cd_file(TARGET imm32 DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/imm32/ctf.c b/dll/win32/imm32/ctf.c index dd325d472f7..be1853f02c3 100644 --- a/dll/win32/imm32/ctf.c +++ b/dll/win32/imm32/ctf.c @@ -6,11 +6,83 @@ */ #include "precomp.h" -#include -#include +#include /* for ITfLangBarMgr */ +#include /* for IInitializeSpy */ WINE_DEFAULT_DEBUG_CHANNEL(imm); +/* FIXME: Use RTL */ +static BOOL WINAPI RtlDllShutdownInProgress(VOID) +{ + return FALSE; +} + +static BOOL Imm32InsideLoaderLock(VOID) +{ + return NtCurrentTeb()->ProcessEnvironmentBlock->LoaderLock->OwningThread == + NtCurrentTeb()->ClientId.UniqueThread; +} + +static BOOL +Imm32IsInteractiveUserLogon(VOID) +{ + BOOL bOK, IsMember = FALSE; + PSID pSid; + SID_IDENTIFIER_AUTHORITY IdentAuth = { SECURITY_NT_AUTHORITY }; + + if (!AllocateAndInitializeSid(&IdentAuth, 1, SECURITY_INTERACTIVE_RID, + 0, 0, 0, 0, 0, 0, 0, &pSid)) + { + ERR("Error: %ld\n", GetLastError()); + return FALSE; + } + + bOK = CheckTokenMembership(NULL, pSid, &IsMember); + + if (pSid) + FreeSid(pSid); + + return bOK && IsMember; +} + +static BOOL +Imm32IsRunningInMsoobe(VOID) +{ + LPWSTR pchFilePart = NULL; + WCHAR Buffer[MAX_PATH], FileName[MAX_PATH]; + + if (!GetModuleFileNameW(NULL, FileName, _countof(FileName))) + return FALSE; + + GetFullPathNameW(FileName, _countof(Buffer), Buffer, &pchFilePart); + if (!pchFilePart) + return FALSE; + + return lstrcmpiW(pchFilePart, L"msoobe.exe") == 0; +} + +static BOOL +Imm32IsCUASEnabledInRegistry(VOID) +{ + HKEY hKey; + LSTATUS error; + DWORD dwType, dwData, cbData; + + error = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\CTF\\SystemShared", &hKey); + if (error != ERROR_SUCCESS) + return FALSE; + + dwData = 0; + cbData = sizeof(dwData); + error = RegQueryValueExW(hKey, L"CUAS", NULL, &dwType, (LPBYTE)&dwData, &cbData); + RegCloseKey(hKey); + + if (error != ERROR_SUCCESS || dwType != REG_DWORD) + return FALSE; + + return !!dwData; +} + BOOL Imm32GetFn( _Inout_opt_ FARPROC *ppfn, @@ -110,6 +182,8 @@ FN_TF_InvalidAssemblyListCacheIfExist MSCTF_FN(TF_InvalidAssemblyListCacheIfExis HRESULT Imm32TF_CreateLangBarMgr(_Inout_ ITfLangBarMgr **ppBarMgr) { + TRACE("TF_CreateLangBarMgr(%p)\n", ppBarMgr); + if (!Imm32GetMsctfFn(TF_CreateLangBarMgr)) return E_FAIL; @@ -118,6 +192,8 @@ HRESULT Imm32TF_CreateLangBarMgr(_Inout_ ITfLangBarMgr **ppBarMgr) VOID Imm32TF_InvalidAssemblyListCacheIfExist(VOID) { + TRACE("TF_InvalidAssemblyListCacheIfExist()\n"); + if (!Imm32GetMsctfFn(TF_InvalidAssemblyListCacheIfExist)) return; @@ -141,6 +217,9 @@ VOID Imm32TF_InvalidAssemblyListCacheIfExist(VOID) /* "Active IMM" compatibility flags */ DWORD g_aimm_compat_flags = 0; +/* Disable CUAS? */ +BOOL g_disable_CUAS_flag = FALSE; + /* The instance of the CTF IME file */ HINSTANCE g_hCtfIme = NULL; @@ -203,6 +282,384 @@ Imm32CheckAndApplyAppCompat( return pApphelpCheckIME(pszAppName); } +/*********************************************************************** + * TLS (Thread-Local Storage) + * + * See: TlsAlloc + */ + +DWORD g_dwTLSIndex = -1; + +/* IMM Thread-Local Storage (TLS) data */ +typedef struct IMMTLSDATA +{ + IInitializeSpy *pSpy; /* CoInitialize Spy */ + DWORD dwUnknown1; + ULARGE_INTEGER uliCookie; /* Spy requires a cookie for revoking */ + BOOL bDoCount; /* Is it counting? */ + DWORD dwSkipCount; /* The skipped count */ + BOOL bUninitializing; /* Is it uninitializing? */ + DWORD dwUnknown2; +} IMMTLSDATA, *PIMMTLSDATA; + +static VOID +Imm32InitTLS(VOID) +{ + RtlEnterCriticalSection(&gcsImeDpi); + + if (g_dwTLSIndex == -1) + g_dwTLSIndex = TlsAlloc(); + + RtlLeaveCriticalSection(&gcsImeDpi); +} + +static IMMTLSDATA* +Imm32AllocateTLS(VOID) +{ + IMMTLSDATA *pData; + + if (g_dwTLSIndex == -1) + return NULL; + + pData = (IMMTLSDATA*)TlsGetValue(g_dwTLSIndex); + if (pData) + return pData; + + pData = (IMMTLSDATA*)ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(IMMTLSDATA)); + if (IS_NULL_UNEXPECTEDLY(pData)) + return NULL; + + if (IS_FALSE_UNEXPECTEDLY(TlsSetValue(g_dwTLSIndex, pData))) + { + ImmLocalFree(pData); + return NULL; + } + + return pData; +} + +static IMMTLSDATA* +Imm32GetTLS(VOID) +{ + if (g_dwTLSIndex == -1) + return NULL; + + return (IMMTLSDATA*)TlsGetValue(g_dwTLSIndex); +} + +/* Get */ +static DWORD +Imm32GetCoInitCountSkip(VOID) +{ + IMMTLSDATA *pData = Imm32GetTLS(); + if (!pData) + return 0; + return pData->dwSkipCount; +} + +/* Increment */ +static DWORD +Imm32IncCoInitCountSkip(VOID) +{ + IMMTLSDATA *pData; + DWORD dwOldSkipCount; + + pData = Imm32GetTLS(); + if (!pData) + return 0; + + dwOldSkipCount = pData->dwSkipCount; + if (pData->bDoCount) + pData->dwSkipCount = dwOldSkipCount + 1; + + return dwOldSkipCount; +} + +/* Decrement */ +static DWORD +Imm32DecCoInitCountSkip(VOID) +{ + DWORD dwSkipCount; + IMMTLSDATA *pData; + + pData = Imm32GetTLS();; + if (!pData) + return 0; + + dwSkipCount = pData->dwSkipCount; + if (pData->bDoCount) + { + if (dwSkipCount) + pData->dwSkipCount = dwSkipCount - 1; + } + + return dwSkipCount; +} + +/*********************************************************************** + * CtfImmEnterCoInitCountSkipMode (IMM32.@) + */ +VOID WINAPI CtfImmEnterCoInitCountSkipMode(VOID) +{ + IMMTLSDATA *pData; + + TRACE("()\n"); + + pData = Imm32GetTLS(); + if (pData) + ++(pData->bDoCount); +} + +/*********************************************************************** + * CtfImmLeaveCoInitCountSkipMode (IMM32.@) + */ +BOOL WINAPI CtfImmLeaveCoInitCountSkipMode(VOID) +{ + IMMTLSDATA *pData; + + TRACE("()\n"); + + pData = Imm32GetTLS(); + if (!pData || !pData->bDoCount) + return FALSE; + + --(pData->bDoCount); + return TRUE; +} + +/*********************************************************************** + * ISPY (I am not spy!) + * + * ISPY watches CoInitialize[Ex] / CoUninitialize to manage COM initialization status. + */ + +typedef struct ISPY +{ + const IInitializeSpyVtbl *m_pSpyVtbl; + LONG m_cRefs; +} ISPY, *PISPY; + +static STDMETHODIMP +ISPY_QueryInterface( + _Inout_ IInitializeSpy *pThis, + _In_ REFIID riid, + _Inout_ LPVOID *ppvObj) +{ + ISPY *pSpy = (ISPY*)pThis; + + if (!ppvObj) + return E_INVALIDARG; + + *ppvObj = NULL; + + if (!IsEqualIID(riid, &IID_IUnknown) && !IsEqualIID(riid, &IID_IInitializeSpy)) + return E_NOINTERFACE; + + ++(pSpy->m_cRefs); + *ppvObj = pSpy; + return S_OK; +} + +static STDMETHODIMP_(ULONG) +ISPY_AddRef( + _Inout_ IInitializeSpy *pThis) +{ + ISPY *pSpy = (ISPY*)pThis; + return ++pSpy->m_cRefs; +} + +static STDMETHODIMP_(ULONG) +ISPY_Release( + _Inout_ IInitializeSpy *pThis) +{ + ISPY *pSpy = (ISPY*)pThis; + if (--pSpy->m_cRefs == 0) + { + ImmLocalFree(pSpy); + return 0; + } + return pSpy->m_cRefs; +} + +/* + * (Pre/Post)(Initialize/Uninitialize) will be automatically called from OLE32 + * as the results of watching. + */ + +static STDMETHODIMP +ISPY_PreInitialize( + _Inout_ IInitializeSpy *pThis, + _In_ DWORD dwCoInit, + _In_ DWORD dwCurThreadAptRefs) +{ + DWORD cCount; + + UNREFERENCED_PARAMETER(pThis); + + cCount = Imm32IncCoInitCountSkip(); + if (!dwCoInit && + (dwCurThreadAptRefs == cCount + 1) && + (GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) + { + Imm32ActivateOrDeactivateTIM(FALSE); + CtfImmCoUninitialize(); + } + + return S_OK; +} + +static STDMETHODIMP +ISPY_PostInitialize( + _Inout_ IInitializeSpy *pThis, + _In_ HRESULT hrCoInit, + _In_ DWORD dwCoInit, + _In_ DWORD dwNewThreadAptRefs) +{ + DWORD CoInitCountSkip; + + UNREFERENCED_PARAMETER(pThis); + UNREFERENCED_PARAMETER(dwCoInit); + + CoInitCountSkip = Imm32GetCoInitCountSkip(); + + if ((hrCoInit != S_FALSE) || + (dwNewThreadAptRefs != CoInitCountSkip + 2) || + !(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) + { + return hrCoInit; + } + + return S_OK; +} + +static STDMETHODIMP +ISPY_PreUninitialize( + _Inout_ IInitializeSpy *pThis, + _In_ DWORD dwCurThreadAptRefs) +{ + UNREFERENCED_PARAMETER(pThis); + + if (dwCurThreadAptRefs == 1 && + !RtlDllShutdownInProgress() && + !Imm32InsideLoaderLock() && + (GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) + { + IMMTLSDATA *pData = Imm32GetTLS(); + if (pData && !pData->bUninitializing) + Imm32CoInitializeEx(); + } + + return S_OK; +} + +static STDMETHODIMP +ISPY_PostUninitialize( + _In_ IInitializeSpy *pThis, + _In_ DWORD dwNewThreadAptRefs) +{ + UNREFERENCED_PARAMETER(pThis); + UNREFERENCED_PARAMETER(dwNewThreadAptRefs); + Imm32DecCoInitCountSkip(); + return S_OK; +} + +static const IInitializeSpyVtbl g_vtblISPY = +{ + ISPY_QueryInterface, + ISPY_AddRef, + ISPY_Release, + ISPY_PreInitialize, + ISPY_PostInitialize, + ISPY_PreUninitialize, + ISPY_PostUninitialize, +}; + +static ISPY* +Imm32AllocIMMISPY(VOID) +{ + ISPY *pSpy = (ISPY*)ImmLocalAlloc(0, sizeof(ISPY)); + if (!pSpy) + return NULL; + + pSpy->m_pSpyVtbl = &g_vtblISPY; + pSpy->m_cRefs = 1; + return pSpy; +} + +#define Imm32DeleteIMMISPY(pSpy) ImmLocalFree(pSpy) + +/*********************************************************************** + * CtfImmCoInitialize (Not exported) + */ +HRESULT +CtfImmCoInitialize(VOID) +{ + HRESULT hr; + IMMTLSDATA *pData; + ISPY *pSpy; + + if (GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT) + return S_OK; /* Already initialized */ + + hr = Imm32CoInitializeEx(); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; /* CoInitializeEx failed */ + + GetWin32ClientInfo()->CI_flags |= CI_CTFCOINIT; + Imm32InitTLS(); + + pData = Imm32AllocateTLS(); + if (!pData || pData->pSpy) + return S_OK; /* Cannot allocate or already it has a spy */ + + pSpy = Imm32AllocIMMISPY(); + pData->pSpy = (IInitializeSpy*)pSpy; + if (IS_NULL_UNEXPECTEDLY(pSpy)) + return S_OK; /* Cannot allocate a spy */ + + if (FAILED_UNEXPECTEDLY(Imm32CoRegisterInitializeSpy(pData->pSpy, &pData->uliCookie))) + { + /* Failed to register the spy */ + Imm32DeleteIMMISPY(pData->pSpy); + pData->pSpy = NULL; + pData->uliCookie.QuadPart = 0; + } + + return S_OK; +} + +/*********************************************************************** + * CtfImmCoUninitialize (IMM32.@) + */ +VOID WINAPI +CtfImmCoUninitialize(VOID) +{ + IMMTLSDATA *pData; + + if (!(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) + return; /* Not CoInitialize'd */ + + pData = Imm32GetTLS(); + if (pData) + { + pData->bUninitializing = TRUE; + Imm32CoUninitialize(); /* Do CoUninitialize */ + pData->bUninitializing = FALSE; + + GetWin32ClientInfo()->CI_flags &= ~CI_CTFCOINIT; + } + + pData = Imm32AllocateTLS(); + if (!pData || !pData->pSpy) + return; /* There were no spy */ + + /* Our work is done. We don't need spies like you anymore. */ + Imm32CoRevokeInitializeSpy(pData->uliCookie); + ISPY_Release(pData->pSpy); + pData->pSpy = NULL; + pData->uliCookie.QuadPart = 0; +} + /*********************************************************************** * This function loads the CTF IME file if necessary and establishes * communication with the CTF IME. @@ -286,6 +743,8 @@ Imm32LoadCtfIme(VOID) HRESULT CtfImeCreateThreadMgr(VOID) { + TRACE("()\n"); + if (!Imm32LoadCtfIme()) return E_FAIL; @@ -298,6 +757,8 @@ CtfImeCreateThreadMgr(VOID) HRESULT CtfImeDestroyThreadMgr(VOID) { + TRACE("()\n"); + if (!Imm32LoadCtfIme()) return E_FAIL; @@ -362,6 +823,8 @@ HRESULT CtfImeCreateInputContext( _In_ HIMC hIMC) { + TRACE("(%p)\n", hIMC); + if (!Imm32LoadCtfIme()) return E_FAIL; @@ -374,6 +837,8 @@ CtfImeCreateInputContext( HRESULT CtfImeDestroyInputContext(_In_ HIMC hIMC) { + TRACE("(%p)\n", hIMC); + if (!Imm32LoadCtfIme()) return E_FAIL; @@ -394,8 +859,61 @@ Imm32EnumCreateCtfICProc( } /*********************************************************************** - * This function calls CtfImeDestroyInputContext if possible. + * Thread Input Manager (TIM) */ + +static BOOL +Imm32IsTIMDisabledInRegistry(VOID) +{ + DWORD dwData, cbData; + HKEY hKey; + LSTATUS error; + + error = RegOpenKeyW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\CTF", &hKey); + if (error != ERROR_SUCCESS) + return FALSE; + + dwData = 0; + cbData = sizeof(dwData); + RegQueryValueExW(hKey, L"Disable Thread Input Manager", NULL, NULL, (LPBYTE)&dwData, &cbData); + RegCloseKey(hKey); + return !!dwData; +} + +HRESULT +Imm32ActivateOrDeactivateTIM( + _In_ BOOL bCreate) +{ + HRESULT hr = S_OK; + + if (!IS_CICERO_MODE() || IS_16BIT_MODE() || + !(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) + { + return S_OK; /* No need to activate/de-activate TIM */ + } + + if (bCreate) + { + if (!(GetWin32ClientInfo()->CI_flags & CI_CTFTIM)) + { + hr = CtfImeCreateThreadMgr(); + if (SUCCEEDED(hr)) + GetWin32ClientInfo()->CI_flags |= CI_CTFTIM; + } + } + else /* Destroy */ + { + if (GetWin32ClientInfo()->CI_flags & CI_CTFTIM) + { + hr = CtfImeDestroyThreadMgr(); + if (SUCCEEDED(hr)) + GetWin32ClientInfo()->CI_flags &= ~CI_CTFTIM; + } + } + + return hr; +} + HRESULT CtfImmTIMDestroyInputContext( _In_ HIMC hIMC) @@ -422,34 +940,34 @@ CtfImmTIMCreateInputContext( if (GetWin32ClientInfo()->CI_flags & CI_AIMMACTIVATED) { - if (!pClientImc->bUnknown4) + if (!pClientImc->bCtfIme) { dwImeThreadId = NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); dwCurrentThreadId = GetCurrentThreadId(); if (dwImeThreadId == dwCurrentThreadId) { - pClientImc->bUnknown4 = 1; + pClientImc->bCtfIme = TRUE; hr = CtfImeCreateInputContext(hIMC); - if (FAILED(hr)) - pClientImc->bUnknown4 = 0; + if (FAILED_UNEXPECTEDLY(hr)) + pClientImc->bCtfIme = FALSE; } } } else { - if (!(GetWin32ClientInfo()->CI_flags & 0x100)) + if (!(GetWin32ClientInfo()->CI_flags & CI_CTFTIM)) return S_OK; - if (!pClientImc->bUnknown4) + if (!pClientImc->bCtfIme) { dwImeThreadId = NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); dwCurrentThreadId = GetCurrentThreadId(); if ((dwImeThreadId == dwCurrentThreadId) && IS_CICERO_MODE() && !IS_16BIT_MODE()) { - pClientImc->bUnknown4 = 1; + pClientImc->bCtfIme = TRUE; hr = CtfImeCreateInputContext(hIMC); - if (FAILED(hr)) - pClientImc->bUnknown4 = 0; + if (FAILED_UNEXPECTEDLY(hr)) + pClientImc->bCtfIme = FALSE; } } } @@ -458,6 +976,19 @@ CtfImmTIMCreateInputContext( return hr; } +/*********************************************************************** + * CtfImmLastEnabledWndDestroy (IMM32.@) + * + * Same as Imm32ActivateOrDeactivateTIM but its naming is improper. + */ +HRESULT WINAPI +CtfImmLastEnabledWndDestroy( + _In_ BOOL bCreate) +{ + TRACE("(%d)\n", bCreate); + return Imm32ActivateOrDeactivateTIM(bCreate); +} + /*********************************************************************** * CtfAImmActivate (IMM32.@) * @@ -529,7 +1060,7 @@ CtfImmIsCiceroEnabled(VOID) } /*********************************************************************** - * CtfImmIsTextFrameServiceDisabled(IMM32.@) + * CtfImmIsTextFrameServiceDisabled (IMM32.@) * * @return TRUE if TSF is disabled. */ @@ -540,17 +1071,123 @@ CtfImmIsTextFrameServiceDisabled(VOID) } /*********************************************************************** - * CtfImmTIMActivate(IMM32.@) + * ImmDisableTextFrameService (IMM32.@) + */ +BOOL WINAPI +ImmDisableTextFrameService(_In_ DWORD dwThreadId) +{ + HRESULT hr = S_OK; + + TRACE("(0x%lX)\n", dwThreadId); + + if (dwThreadId == -1) + g_disable_CUAS_flag = TRUE; + + if ((dwThreadId && !g_disable_CUAS_flag) || (GetWin32ClientInfo()->CI_flags & CI_TSFDISABLED)) + return TRUE; + + GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; + + if (IS_CICERO_MODE() && !IS_16BIT_MODE() && + (GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT) && + (GetWin32ClientInfo()->CI_flags & CI_CTFTIM)) + { + hr = CtfImeDestroyThreadMgr(); + if (SUCCEEDED(hr)) + { + GetWin32ClientInfo()->CI_flags &= ~CI_CTFTIM; + CtfImmCoUninitialize(); + } + } + + return hr == S_OK; +} + +/*********************************************************************** + * CtfImmTIMActivate (IMM32.@) + * + * Activates Thread Input Manager (TIM) in the thread. */ HRESULT WINAPI CtfImmTIMActivate(_In_ HKL hKL) { - FIXME("(%p)\n", hKL); - return E_NOTIMPL; + HRESULT hr = S_OK; + + TRACE("(%p)\n", hKL); + + if (g_disable_CUAS_flag) + { + TRACE("g_disable_CUAS_flag\n"); + GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; + return FALSE; + } + + if (GetWin32ClientInfo()->CI_flags & CI_TSFDISABLED) + { + TRACE("CI_TSFDISABLED\n"); + return FALSE; + } + + if (Imm32IsTIMDisabledInRegistry()) + { + TRACE("TIM is disabled in registry\n"); + GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; + return FALSE; + } + + if (!Imm32IsInteractiveUserLogon() || Imm32IsRunningInMsoobe()) + { + TRACE("TIM is disabled due to LOGON or MSOBE\n"); + return FALSE; + } + + if (!Imm32IsCUASEnabledInRegistry()) + { + TRACE("CUAS is disabled in registry\n"); + GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; + return FALSE; + } + + if (NtCurrentTeb()->ProcessEnvironmentBlock->AppCompatFlags.LowPart & 0x100) + { + TRACE("CUAS is disabled by AppCompatFlags\n"); + GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; + return FALSE; + } + + if (RtlIsThreadWithinLoaderCallout() || Imm32InsideLoaderLock()) + { + TRACE("TIM is disabled by Loader\n"); + return FALSE; + } + + if (!IS_CICERO_MODE() || IS_16BIT_MODE()) + { + TRACE("TIM is disabled because CICERO mode is unset\n"); + return FALSE; + } + + if (IS_IME_HKL(hKL)) + hKL = (HKL)UlongToHandle(MAKELONG(LOWORD(hKL), LOWORD(hKL))); + + if (!ImmLoadIME(hKL)) + Imm32TF_InvalidAssemblyListCacheIfExist(); + + CtfImmCoInitialize(); + + if ((GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT) && + !(GetWin32ClientInfo()->CI_flags & CI_CTFTIM)) + { + hr = CtfImeCreateThreadMgr(); + if (SUCCEEDED(hr)) + GetWin32ClientInfo()->CI_flags |= CI_CTFTIM; + } + + return hr; } /*********************************************************************** - * CtfImmGenerateMessage(IMM32.@) + * CtfImmGenerateMessage (IMM32.@) */ BOOL WINAPI CtfImmGenerateMessage( @@ -638,7 +1275,7 @@ CtfImmGenerateMessage( } /*********************************************************************** - * CtfImmHideToolbarWnd(IMM32.@) + * CtfImmHideToolbarWnd (IMM32.@) * * Used with CtfImmRestoreToolbarWnd. */ @@ -667,7 +1304,7 @@ CtfImmHideToolbarWnd(VOID) } /*********************************************************************** - * CtfImmRestoreToolbarWnd(IMM32.@) + * CtfImmRestoreToolbarWnd (IMM32.@) * * Used with CtfImmHideToolbarWnd. */ @@ -684,7 +1321,7 @@ CtfImmRestoreToolbarWnd( TRACE("(%p, 0x%X)\n", pUnused, dwShowFlags); hr = Imm32TF_CreateLangBarMgr(&pBarMgr); - if (FAILED(hr)) + if (FAILED_UNEXPECTEDLY(hr)) return; if (dwShowFlags) @@ -693,20 +1330,8 @@ CtfImmRestoreToolbarWnd( pBarMgr->lpVtbl->Release(pBarMgr); } -BOOL Imm32InsideLoaderLock(VOID) -{ - return (NtCurrentTeb()->ProcessEnvironmentBlock->LoaderLock->OwningThread == - NtCurrentTeb()->ClientId.UniqueThread); -} - -/* FIXME: Use RTL */ -BOOL WINAPI RtlDllShutdownInProgress(VOID) -{ - return FALSE; -} - /*********************************************************************** - * CtfImmDispatchDefImeMessage(IMM32.@) + * CtfImmDispatchDefImeMessage (IMM32.@) */ LRESULT WINAPI CtfImmDispatchDefImeMessage( @@ -724,7 +1349,7 @@ CtfImmDispatchDefImeMessage( } /*********************************************************************** - * CtfImmIsGuidMapEnable(IMM32.@) + * CtfImmIsGuidMapEnable (IMM32.@) */ BOOL WINAPI CtfImmIsGuidMapEnable( @@ -757,7 +1382,7 @@ CtfImmIsGuidMapEnable( } /*********************************************************************** - * CtfImmGetGuidAtom(IMM32.@) + * CtfImmGetGuidAtom (IMM32.@) */ HRESULT WINAPI CtfImmGetGuidAtom( diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c index 39d4cd3b1ef..5723fde1a59 100644 --- a/dll/win32/imm32/imm.c +++ b/dll/win32/imm32/imm.c @@ -1103,15 +1103,6 @@ BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC) return TRUE; // Do nothing. This is correct. } -/*********************************************************************** -* ImmDisableTextFrameService(IMM32.@) -*/ -BOOL WINAPI ImmDisableTextFrameService(DWORD dwThreadId) -{ - FIXME("Stub\n"); - return FALSE; -} - /*********************************************************************** * ImmEnumInputContext(IMM32.@) */ diff --git a/dll/win32/imm32/imm32.spec b/dll/win32/imm32/imm32.spec index 14044ca710b..2e84d6a143c 100644 --- a/dll/win32/imm32/imm32.spec +++ b/dll/win32/imm32/imm32.spec @@ -1,7 +1,9 @@ @ stdcall CtfAImmActivate(ptr) @ stdcall CtfAImmDeactivate(long) @ stdcall CtfAImmIsIME(ptr) +@ stdcall CtfImmCoUninitialize() @ stdcall CtfImmDispatchDefImeMessage(ptr long ptr ptr) +@ stdcall CtfImmEnterCoInitCountSkipMode() @ stdcall CtfImmGenerateMessage(ptr long) @ stdcall CtfImmGetGuidAtom(ptr long ptr) @ stdcall CtfImmHideToolbarWnd() @@ -9,6 +11,8 @@ @ stdcall CtfImmIsCiceroStartedInThread() @ stdcall CtfImmIsGuidMapEnable(ptr) @ stdcall CtfImmIsTextFrameServiceDisabled() +@ stdcall CtfImmLastEnabledWndDestroy(long) +@ stdcall CtfImmLeaveCoInitCountSkipMode() @ stdcall CtfImmRestoreToolbarWnd(ptr long) @ stdcall CtfImmSetAppCompatFlags(long) @ stdcall CtfImmSetCiceroStartInThread(long) diff --git a/dll/win32/imm32/precomp.h b/dll/win32/imm32/precomp.h index 8fc4b27d4b7..3f667d1d6f5 100644 --- a/dll/win32/imm32/precomp.h +++ b/dll/win32/imm32/precomp.h @@ -112,12 +112,17 @@ BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC); * --- Examine the condition, and then generate trace log if necessary. */ #ifdef NDEBUG /* on Release */ +#define FAILED_UNEXPECTEDLY(hr) (FAILED(hr)) #define IS_NULL_UNEXPECTEDLY(p) (!(p)) #define IS_ZERO_UNEXPECTEDLY(p) (!(p)) #define IS_TRUE_UNEXPECTEDLY(x) (x) #define IS_FALSE_UNEXPECTEDLY(x) (!(x)) #define IS_ERROR_UNEXPECTEDLY(x) (!(x)) #else /* on Debug */ +#define FAILED_UNEXPECTEDLY(hr) \ + (FAILED(hr) ? (ros_dbg_log(__WINE_DBCL_ERR, __wine_dbch___default, \ + __FILE__, __FUNCTION__, __LINE__, "FAILED(%s)\n", #hr), UNEXPECTED(), TRUE) \ + : FALSE) #define IS_NULL_UNEXPECTEDLY(p) \ (!(p) ? (ros_dbg_log(__WINE_DBCL_ERR, __wine_dbch___default, \ __FILE__, __FUNCTION__, __LINE__, "%s was NULL\n", #p), UNEXPECTED(), TRUE) \ @@ -192,3 +197,7 @@ BOOL Imm32StoreBitmapToBytes(HBITMAP hbm, LPBYTE pbData, DWORD cbDataMax); HRESULT CtfImmTIMCreateInputContext(_In_ HIMC hIMC); HRESULT CtfImmTIMDestroyInputContext(_In_ HIMC hIMC); +HRESULT CtfImmCoInitialize(VOID); +HRESULT CtfImeCreateThreadMgr(VOID); +HRESULT CtfImeDestroyThreadMgr(VOID); +HRESULT Imm32ActivateOrDeactivateTIM(_In_ BOOL bCreate); diff --git a/sdk/include/ddk/immdev.h b/sdk/include/ddk/immdev.h index b553838888f..e36ff688666 100644 --- a/sdk/include/ddk/immdev.h +++ b/sdk/include/ddk/immdev.h @@ -17,6 +17,8 @@ extern "C" { #endif +BOOL WINAPI ImmDisableTextFrameService(_In_ DWORD dwThreadId); + typedef struct tagSOFTKBDDATA { UINT uCount; @@ -317,7 +319,7 @@ typedef struct tagCLIENTIMC RTL_CRITICAL_SECTION cs; UINT uCodePage; HKL hKL; - BOOL bUnknown4; + BOOL bCtfIme; } CLIENTIMC, *PCLIENTIMC; #ifndef _WIN64 diff --git a/sdk/include/reactos/imm32_undoc.h b/sdk/include/reactos/imm32_undoc.h index 28039bcb857..08be32a2dcd 100644 --- a/sdk/include/reactos/imm32_undoc.h +++ b/sdk/include/reactos/imm32_undoc.h @@ -31,6 +31,10 @@ VOID WINAPI CtfImmSetAppCompatFlags(_In_ DWORD dwFlags); DWORD WINAPI CtfImmHideToolbarWnd(VOID); VOID WINAPI CtfImmRestoreToolbarWnd(_In_ LPVOID pUnused, _In_ DWORD dwShowFlags); BOOL WINAPI CtfImmGenerateMessage(_In_ HIMC hIMC, _In_ BOOL bSend); +VOID WINAPI CtfImmCoUninitialize(VOID); +VOID WINAPI CtfImmEnterCoInitCountSkipMode(VOID); +BOOL WINAPI CtfImmLeaveCoInitCountSkipMode(VOID); +HRESULT WINAPI CtfImmLastEnabledWndDestroy(_In_ BOOL bCreate); LRESULT WINAPI CtfImmDispatchDefImeMessage( diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index f501babb00a..2763b4b24cc 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -303,6 +303,8 @@ typedef struct _CALLBACKWND #define CI_CURTHPRHOOK 0x00000010 #define CI_CLASSESREGISTERED 0x00000020 #define CI_IMMACTIVATE 0x00000040 /* IMM/IME (Asian input) */ +#define CI_CTFCOINIT 0x00000080 /* Did CTF CoInitialize? */ +#define CI_CTFTIM 0x00000100 /* CTF Thread Input Manager (TIM) */ #define CI_TSFDISABLED 0x00000400 /* TSF (Text Services Framework a.k.a. Cicero) */ #define CI_AIMMACTIVATED 0x00000800 /* Active IMM (AIMM) */