[MSCTF][CICERO][DOC] Fork MSCTF from Wine (#8245)

JIRA issue: CORE-19361
- Delete msctf.c and add msctf.cpp.
- Modify precomp.h and enable precompiled header.
- Modify media/doc/WINESYNC.txt.
- Add cicMemReCalloc function to cicero.
This commit is contained in:
Katayama Hirofumi MZ 2025-07-13 18:30:42 +09:00 committed by GitHub
parent 853b446e38
commit a18a5734ac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 539 additions and 759 deletions

View file

@ -38,6 +38,25 @@ void operator delete[](void* ptr, size_t size) noexcept
cicMemFree(ptr);
}
LPVOID cicMemReCalloc(LPVOID mem, SIZE_T num, SIZE_T size) noexcept
{
SIZE_T old_size, new_size = num * size;
LPVOID ret;
if (!mem)
return cicMemAllocClear(new_size);
old_size = LocalSize(mem);
ret = cicMemReAlloc(mem, new_size);
if (!ret)
return NULL;
if (new_size > old_size)
ZeroMemory((PBYTE)ret + old_size, new_size - old_size);
return ret;
}
// FIXME
typedef enum _PROCESSINFOCLASS
{

View file

@ -17,19 +17,26 @@ static inline LPVOID cicMemAllocClear(SIZE_T size)
return LocalAlloc(LMEM_ZEROINIT, size);
}
static inline LPVOID cicMemReAlloc(LPVOID ptr, SIZE_T newSize)
{
if (!ptr)
return LocalAlloc(LMEM_ZEROINIT, newSize);
return LocalReAlloc(ptr, newSize, LMEM_ZEROINIT);
}
static inline void cicMemFree(LPVOID ptr)
{
if (ptr)
LocalFree(ptr);
}
static inline LPVOID cicMemReAlloc(LPVOID ptr, SIZE_T newSize)
{
if (!newSize)
{
cicMemFree(ptr);
return NULL;
}
if (!ptr)
return LocalAlloc(LMEM_ZEROINIT, newSize);
return LocalReAlloc(ptr, newSize, LMEM_ZEROINIT | LMEM_MOVEABLE);
}
LPVOID cicMemReCalloc(LPVOID mem, SIZE_T num, SIZE_T size) noexcept;
static inline bool cicIsNullPtr(LPCVOID ptr)
{
return !ptr;

View file

@ -5,11 +5,7 @@ add_definitions(-D_WIN32_WINNT=0x600)
spec2def(msctf.dll msctf.spec ADD_IMPORTLIB)
list(APPEND SOURCE
msctf.c
precomp.h
${CMAKE_CURRENT_BINARY_DIR}/msctf_stubs.c)
list(APPEND PCH_SKIP_SOURCE
categorymgr.cpp
compartmentmgr.cpp
context.cpp
@ -18,13 +14,14 @@ list(APPEND PCH_SKIP_SOURCE
inputprocessor.cpp
langbarmgr.cpp
mlng.cpp
msctf.cpp
range.cpp
threadmgr.cpp
utils.cpp)
utils.cpp
${CMAKE_CURRENT_BINARY_DIR}/msctf_stubs.c)
add_library(msctf MODULE
${SOURCE}
${PCH_SKIP_SOURCE}
version.rc
${CMAKE_CURRENT_BINARY_DIR}/msctf.def)

View file

@ -6,20 +6,7 @@
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <cguid.h>
#include <msctf.h>
#include <msctf_undoc.h>
// Cicero
#include <cicbase.h>
#include <cicreg.h>
#include <cicutb.h>
#include "msctf_internal.h"
#include "precomp.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
@ -106,9 +93,6 @@ CCategoryMgr::~CCategoryMgr()
TRACE("destroying %p\n", this);
}
////////////////////////////////////////////////////////////////////////////
// ** IUnknown methods **
STDMETHODIMP CCategoryMgr::QueryInterface(REFIID riid, void **ppvObj)
{
if (!ppvObj)
@ -119,11 +103,14 @@ STDMETHODIMP CCategoryMgr::QueryInterface(REFIID riid, void **ppvObj)
if (riid == IID_IUnknown || riid == IID_ITfCategoryMgr)
*ppvObj = this;
if (!*ppvObj)
return E_NOINTERFACE;
if (*ppvObj)
{
AddRef();
return S_OK;
}
AddRef();
return S_OK;
WARN("unsupported interface: %s\n", debugstr_guid(&riid));
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CCategoryMgr::AddRef()
@ -133,17 +120,12 @@ STDMETHODIMP_(ULONG) CCategoryMgr::AddRef()
STDMETHODIMP_(ULONG) CCategoryMgr::Release()
{
if (::InterlockedDecrement(&m_cRefs) == 0)
{
ULONG ret = ::InterlockedDecrement(&m_cRefs);
if (!ret)
delete this;
return 0;
}
return m_cRefs;
return ret;
}
////////////////////////////////////////////////////////////////////////////
// ** ITfCategoryMgr methods **
STDMETHODIMP CCategoryMgr::RegisterCategory(
_In_ REFCLSID rclsid,
_In_ REFGUID rcatid,
@ -161,19 +143,19 @@ STDMETHODIMP CCategoryMgr::RegisterCategory(
StringFromGUID2(rcatid, szCatid, _countof(szCatid));
StringFromGUID2(rguid, szGuid, _countof(szGuid));
swprintf(szFullKey, L"%s\\%s", szwSystemTIPKey, szClsid);
StringCchPrintfW(szFullKey, _countof(szFullKey), L"%s\\%s", szwSystemTIPKey, szClsid);
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ | KEY_WRITE, &hTipKey);
if (error != ERROR_SUCCESS)
return E_FAIL;
swprintf(szFullKey, L"Category\\Category\\%s\\%s", szCatid, szGuid);
StringCchPrintfW(szFullKey, _countof(szFullKey), L"Category\\Category\\%s\\%s", szCatid, szGuid);
error = RegCreateKeyExW(hTipKey, szFullKey, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL,
&hCatKey, NULL);
if (error == ERROR_SUCCESS)
{
RegCloseKey(hCatKey);
swprintf(szFullKey, L"Category\\Item\\%s\\%s", szGuid, szCatid);
StringCchPrintfW(szFullKey, _countof(szFullKey), L"Category\\Item\\%s\\%s", szGuid, szCatid);
error = RegCreateKeyExW(hTipKey, szFullKey, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL,
&hItemKey, NULL);
if (error == ERROR_SUCCESS)
@ -203,15 +185,15 @@ STDMETHODIMP CCategoryMgr::UnregisterCategory(
StringFromGUID2(rcatid, szCatid, _countof(szCatid));
StringFromGUID2(rguid, szGuid, _countof(szGuid));
swprintf(szFullKey, L"%s\\%s", szwSystemTIPKey, szClsid);
StringCchPrintfW(szFullKey, _countof(szFullKey), L"%s\\%s", szwSystemTIPKey, szClsid);
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ | KEY_WRITE, &hTipKey);
if (error != ERROR_SUCCESS)
return E_FAIL;
swprintf(szFullKey, L"Category\\Category\\%s\\%s", szCatid, szGuid);
StringCchPrintfW(szFullKey, _countof(szFullKey), L"Category\\Category\\%s\\%s", szCatid, szGuid);
RegDeleteTreeW(hTipKey, szFullKey);
swprintf(szFullKey, L"Category\\Item\\%s\\%s", szGuid, szCatid);
StringCchPrintfW(szFullKey, _countof(szFullKey), L"Category\\Item\\%s\\%s", szGuid, szCatid);
RegDeleteTreeW(hTipKey, szFullKey);
RegCloseKey(hTipKey);
@ -248,11 +230,11 @@ STDMETHODIMP CCategoryMgr::FindClosestCategory(
TRACE("(%p)\n", this);
if (!pcatid || (ulCount > 0 && ppcatidList == NULL))
if (!pcatid || (ulCount && !ppcatidList))
return E_INVALIDARG;
StringFromGUID2(rguid, szGuid, _countof(szGuid));
swprintf(szFullKey, L"%s\\%s\\Category\\Item\\%s", szwSystemTIPKey, szGuid, szGuid);
StringCchPrintfW(szFullKey, _countof(szFullKey), L"%s\\%s\\Category\\Item\\%s", szwSystemTIPKey, szGuid, szGuid);
*pcatid = GUID_NULL;
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szFullKey, 0, KEY_READ, &hKey);
@ -272,7 +254,8 @@ STDMETHODIMP CCategoryMgr::FindClosestCategory(
dwIndex++;
if (FAILED(CLSIDFromString(szCatidName, &currentCatid)))
HRESULT hr2 = CLSIDFromString(szCatidName, &currentCatid);
if (FAILED(hr2))
continue; // Skip invalid GUID strings
if (ulCount <= 0)
@ -362,19 +345,18 @@ STDMETHODIMP CCategoryMgr::RegisterGUID(
if (!pguidatom)
return E_INVALIDARG;
DWORD dwCookieId = 0;
DWORD dwEnumIndex = 0;
DWORD dwCookieId = 0, dwEnumIndex = 0;
do
{
dwCookieId = enumerate_Cookie(COOKIE_MAGIC_GUIDATOM, &dwEnumIndex);
if (dwCookieId != 0 && rguid == *(const GUID *)get_Cookie_data(dwCookieId))
if (dwCookieId && rguid == *(const GUID *)get_Cookie_data(dwCookieId))
{
*pguidatom = dwCookieId;
return S_OK;
}
} while (dwCookieId != 0);
GUID *pNewGuid = (GUID *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GUID));
GUID *pNewGuid = (GUID *)cicMemAlloc(sizeof(GUID));
if (!pNewGuid)
return E_OUTOFMEMORY;
@ -383,7 +365,7 @@ STDMETHODIMP CCategoryMgr::RegisterGUID(
dwCookieId = generate_Cookie(COOKIE_MAGIC_GUIDATOM, pNewGuid);
if (dwCookieId == 0)
{
HeapFree(GetProcessHeap(), 0, pNewGuid);
cicMemFree(pNewGuid);
return E_FAIL;
}
@ -437,7 +419,7 @@ HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
return CLASS_E_NOAGGREGATION;
CCategoryMgr *This = new(cicNoThrow) CCategoryMgr();
if (This == NULL)
if (!This)
return E_OUTOFMEMORY;
*ppOut = static_cast<ITfCategoryMgr *>(This);

View file

@ -6,22 +6,7 @@
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <cguid.h>
#include <olectl.h>
#include <oleauto.h>
#include <msctf.h>
#include <msctf_undoc.h>
// Cicero
#include <cicbase.h>
#include <cicreg.h>
#include <cicutb.h>
#include "msctf_internal.h"
#include "precomp.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
@ -102,7 +87,7 @@ class CCompartment
, public ITfSource
{
public:
CCompartment();
CCompartment(CompartmentValue *valueData);
virtual ~CCompartment();
static HRESULT CreateInstance(CompartmentValue *valueData, ITfCompartment **ppOut);
@ -148,7 +133,7 @@ CCompartmentMgr::~CCompartmentMgr()
CompartmentValue *value = LIST_ENTRY(cursor, CompartmentValue, entry);
list_remove(cursor);
value->compartment->Release();
HeapFree(GetProcessHeap(), 0, value);
cicMemFree(value);
}
}
@ -161,12 +146,12 @@ HRESULT CCompartmentMgr::CreateInstance(IUnknown *pUnkOuter, REFIID riid, IUnkno
return CLASS_E_NOAGGREGATION;
CCompartmentMgr *This = new(cicNoThrow) CCompartmentMgr(pUnkOuter);
if (This == NULL)
if (!This)
return E_OUTOFMEMORY;
if (pUnkOuter)
{
*ppOut = static_cast<IUnknown *>(This);
*ppOut = static_cast<ITfCompartmentMgr *>(This);
TRACE("returning %p\n", *ppOut);
return S_OK;
}
@ -211,12 +196,10 @@ STDMETHODIMP_(ULONG) CCompartmentMgr::Release()
{
if (m_pUnkOuter)
return m_pUnkOuter->Release();
if (::InterlockedDecrement(&m_cRefs) == 0)
{
ULONG ret = ::InterlockedDecrement(&m_cRefs);
if (!ret)
delete this;
return 0;
}
return m_cRefs;
return ret;
}
HRESULT CCompartmentMgr::GetCompartment(_In_ REFGUID rguid, _Out_ ITfCompartment **ppcomp)
@ -240,7 +223,7 @@ HRESULT CCompartmentMgr::GetCompartment(_In_ REFGUID rguid, _Out_ ITfCompartment
}
}
value = (CompartmentValue *)HeapAlloc(GetProcessHeap(), 0, sizeof(CompartmentValue));
value = (CompartmentValue *)cicMemAlloc(sizeof(CompartmentValue));
if (!value)
return E_OUTOFMEMORY;
@ -255,7 +238,7 @@ HRESULT CCompartmentMgr::GetCompartment(_In_ REFGUID rguid, _Out_ ITfCompartment
}
else
{
HeapFree(GetProcessHeap(), 0, value);
cicMemFree(value);
*ppcomp = NULL;
}
@ -277,7 +260,7 @@ HRESULT CCompartmentMgr::ClearCompartment(_In_ TfClientId tid, _In_ REFGUID rgui
return E_UNEXPECTED;
list_remove(cursor);
value->compartment->Release();
HeapFree(GetProcessHeap(), 0, value);
cicMemFree(value);
return S_OK;
}
}
@ -312,7 +295,7 @@ HRESULT
CCompartmentEnumGuid::CreateInstance(struct list *values, IEnumGUID **ppOut)
{
CCompartmentEnumGuid *This = new(cicNoThrow) CCompartmentEnumGuid();
if (This == NULL)
if (!This)
return E_OUTOFMEMORY;
This->m_values = values;
@ -327,7 +310,7 @@ HRESULT
CCompartmentEnumGuid::CreateInstance(struct list *values, IEnumGUID **ppOut, struct list *cursor)
{
CCompartmentEnumGuid *This = new(cicNoThrow) CCompartmentEnumGuid();
if (This == NULL)
if (!This)
return E_OUTOFMEMORY;
This->m_values = values;
@ -343,9 +326,7 @@ STDMETHODIMP CCompartmentEnumGuid::QueryInterface(REFIID iid, LPVOID *ppvObj)
*ppvObj = NULL;
if (iid == IID_IUnknown || iid == IID_IEnumGUID)
{
*ppvObj = static_cast<IEnumGUID *>(this);
}
if (*ppvObj)
{
@ -364,12 +345,10 @@ STDMETHODIMP_(ULONG) CCompartmentEnumGuid::AddRef()
STDMETHODIMP_(ULONG) CCompartmentEnumGuid::Release()
{
if (::InterlockedDecrement(&m_cRefs) == 0)
{
ULONG ret = ::InterlockedDecrement(&m_cRefs);
if (!ret)
delete this;
return 0;
}
return m_cRefs;
return ret;
}
STDMETHODIMP CCompartmentEnumGuid::Next(
@ -381,7 +360,7 @@ STDMETHODIMP CCompartmentEnumGuid::Next(
TRACE("(%p)\n", this);
if (rgelt == NULL)
if (!rgelt)
return E_POINTER;
while (fetched < celt && m_cursor)
@ -420,7 +399,7 @@ STDMETHODIMP CCompartmentEnumGuid::Clone(_Out_ IEnumGUID **ppenum)
{
TRACE("(%p)\n", this);
if (ppenum == NULL)
if (!ppenum)
return E_POINTER;
return CCompartmentEnumGuid::CreateInstance(m_values, ppenum, m_cursor);
@ -428,30 +407,27 @@ STDMETHODIMP CCompartmentEnumGuid::Clone(_Out_ IEnumGUID **ppenum)
////////////////////////////////////////////////////////////////////////////
CCompartment::CCompartment()
CCompartment::CCompartment(CompartmentValue *valueData)
: m_cRefs(1)
, m_valueData(NULL)
, m_valueData(valueData)
{
VariantInit(&m_variant);
list_init(&m_CompartmentEventSink);
}
CCompartment::~CCompartment()
{
TRACE("destroying %p\n", this);
VariantClear(&m_variant);
free_sinks(&m_CompartmentEventSink);
}
HRESULT CCompartment::CreateInstance(CompartmentValue *valueData, ITfCompartment **ppOut)
{
CCompartment *This = new(cicNoThrow) CCompartment();
if (This == NULL)
CCompartment *This = new(cicNoThrow) CCompartment(valueData);
if (!This)
return E_OUTOFMEMORY;
This->m_valueData = valueData;
VariantInit(&This->m_variant);
list_init(&This->m_CompartmentEventSink);
*ppOut = static_cast<ITfCompartment *>(This);
TRACE("returning %p\n", *ppOut);
return S_OK;
@ -483,12 +459,10 @@ STDMETHODIMP_(ULONG) CCompartment::AddRef()
STDMETHODIMP_(ULONG) CCompartment::Release()
{
if (::InterlockedDecrement(&m_cRefs) == 0)
{
ULONG ret = ::InterlockedDecrement(&m_cRefs);
if (!ret)
delete this;
return 0;
}
return m_cRefs;
return ret;
}
STDMETHODIMP CCompartment::SetValue(_In_ TfClientId tid, _In_ const VARIANT *pvarValue)
@ -501,8 +475,7 @@ STDMETHODIMP CCompartment::SetValue(_In_ TfClientId tid, _In_ const VARIANT *pva
if (!pvarValue)
return E_INVALIDARG;
if (!(V_VT(pvarValue) == VT_BSTR || V_VT(pvarValue) == VT_I4 ||
V_VT(pvarValue) == VT_UNKNOWN))
if (!(V_VT(pvarValue) == VT_BSTR || V_VT(pvarValue) == VT_I4 || V_VT(pvarValue) == VT_UNKNOWN))
return E_INVALIDARG;
if (!m_valueData->owner)

View file

@ -6,22 +6,7 @@
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <cguid.h>
#include <olectl.h>
#include <oleauto.h>
#include <msctf.h>
#include <msctf_undoc.h>
// Cicero
#include <cicbase.h>
#include <cicreg.h>
#include <cicutb.h>
#include "msctf_internal.h"
#include "precomp.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
@ -118,17 +103,17 @@ public:
_In_ TfEditCookie ecWrite,
_In_ ITfRange *pCompositionRange,
_In_ ITfCompositionSink *pSink,
_Out_ ITfComposition **ppComposition);
STDMETHODIMP EnumCompositions(_Out_ IEnumITfCompositionView **ppEnum);
_Out_ ITfComposition **ppComposition) override;
STDMETHODIMP EnumCompositions(_Out_ IEnumITfCompositionView **ppEnum) override;
STDMETHODIMP FindComposition(
_In_ TfEditCookie ecRead,
_In_ ITfRange *pTestRange,
_Out_ IEnumITfCompositionView **ppEnum);
_Out_ IEnumITfCompositionView **ppEnum) override;
STDMETHODIMP TakeOwnership(
_In_ TfEditCookie ecWrite,
_In_ ITfCompositionView *pComposition,
_In_ ITfCompositionSink *pSink,
_Out_ ITfComposition **ppComposition);
_Out_ ITfComposition **ppComposition) override;
STDMETHODIMP TerminateComposition(_In_ ITfCompositionView *pComposition) override;
// ** ITfInsertAtSelection methods **
@ -252,7 +237,7 @@ CContext::~CContext()
if (m_defaultCookie)
{
cookie = (EditCookie *)remove_Cookie(m_defaultCookie);
HeapFree(GetProcessHeap(), 0, cookie);
cicMemFree(cookie);
m_defaultCookie = 0;
}
@ -270,26 +255,28 @@ STDMETHODIMP CContext::QueryInterface(REFIID riid, void **ppvObj)
{
*ppvObj = NULL;
IUnknown *pUnk = NULL;
if (riid == IID_IUnknown || riid == IID_ITfContext)
*ppvObj = static_cast<ITfContext *>(this);
pUnk = static_cast<ITfContext *>(this);
else if (riid == IID_ITfSource)
*ppvObj = static_cast<ITfSource *>(this);
pUnk = static_cast<ITfSource *>(this);
else if (riid == IID_ITfContextOwnerCompositionServices)
*ppvObj = static_cast<ITfContextOwnerCompositionServices *>(this);
pUnk = static_cast<ITfContextOwnerCompositionServices *>(this);
else if (riid == IID_ITfInsertAtSelection)
*ppvObj = static_cast<ITfInsertAtSelection *>(this);
pUnk = static_cast<ITfInsertAtSelection *>(this);
else if (riid == IID_ITfCompartmentMgr)
*ppvObj = m_CompartmentMgr;
pUnk = m_CompartmentMgr;
else if (riid == IID_ITfSourceSingle)
*ppvObj = static_cast<ITfSourceSingle *>(this);
pUnk = static_cast<ITfSourceSingle *>(this);
else if (riid == IID_ITextStoreACPSink)
*ppvObj = static_cast<ITextStoreACPSink *>(this);
pUnk = static_cast<ITextStoreACPSink *>(this);
else if (riid == IID_ITextStoreACPServices)
*ppvObj = static_cast<ITextStoreACPServices *>(this);
pUnk = static_cast<ITextStoreACPServices *>(this);
if (*ppvObj)
if (pUnk)
{
AddRef();
pUnk->AddRef();
*ppvObj = pUnk;
return S_OK;
}
@ -377,7 +364,6 @@ STDMETHODIMP CContext::GetSelection(
_Out_ TF_SELECTION *pSelection,
_Out_ ULONG *pcFetched)
{
EditCookie *cookie;
ULONG count, i;
ULONG totalFetched = 0;
HRESULT hr = S_OK;
@ -399,8 +385,6 @@ STDMETHODIMP CContext::GetSelection(
return E_NOTIMPL;
}
cookie = (EditCookie *)get_Cookie_data(ec);
count = (ulIndex == (ULONG)TF_DEFAULT_SELECTION) ? 1 : ulCount;
for (i = 0; i < count; i++)
@ -416,7 +400,7 @@ STDMETHODIMP CContext::GetSelection(
pSelection[totalFetched].style.ase = (TfActiveSelEnd)acps.style.ase;
pSelection[totalFetched].style.fInterimChar = acps.style.fInterimChar;
Range_Constructor(this, m_pITextStoreACP, cookie->lockType, acps.acpStart, acps.acpEnd, &pSelection[totalFetched].range);
Range_Constructor(this, acps.acpStart, acps.acpEnd, &pSelection[totalFetched].range);
totalFetched++;
}
@ -445,7 +429,7 @@ CContext::SetSelection(
if (get_Cookie_magic(ec) != COOKIE_MAGIC_EDITCOOKIE)
return TF_E_NOLOCK;
acp = (TS_SELECTION_ACP *)HeapAlloc(GetProcessHeap(), 0, sizeof(TS_SELECTION_ACP) * ulCount);
acp = (TS_SELECTION_ACP *)cicMemAlloc(sizeof(TS_SELECTION_ACP) * ulCount);
if (!acp)
return E_OUTOFMEMORY;
@ -454,14 +438,14 @@ CContext::SetSelection(
if (FAILED(TF_SELECTION_to_TS_SELECTION_ACP(&pSelection[i], &acp[i])))
{
TRACE("Selection Conversion Failed\n");
HeapFree(GetProcessHeap(), 0 , acp);
cicMemFree(acp);
return E_FAIL;
}
}
hr = m_pITextStoreACP->SetSelection(ulCount, acp);
HeapFree(GetProcessHeap(), 0, acp);
cicMemFree(acp);
return hr;
}
@ -471,7 +455,6 @@ CContext::GetStart(
_In_ TfEditCookie ec,
_Out_ ITfRange **ppStart)
{
EditCookie *cookie;
TRACE("(%p) %i %p\n", this, ec, ppStart);
if (!ppStart)
@ -485,8 +468,7 @@ CContext::GetStart(
if (get_Cookie_magic(ec) != COOKIE_MAGIC_EDITCOOKIE)
return TF_E_NOLOCK;
cookie = (EditCookie *)get_Cookie_data(ec);
return Range_Constructor(this, m_pITextStoreACP, cookie->lockType, 0, 0, ppStart);
return Range_Constructor(this, 0, 0, ppStart);
}
STDMETHODIMP
@ -494,7 +476,6 @@ CContext::GetEnd(
_In_ TfEditCookie ec,
_Out_ ITfRange **ppEnd)
{
EditCookie *cookie;
LONG end;
TRACE("(%p) %i %p\n", this, ec, ppEnd);
@ -516,10 +497,9 @@ CContext::GetEnd(
return E_NOTIMPL;
}
cookie = (EditCookie *)get_Cookie_data(ec);
m_pITextStoreACP->GetEndACP(&end);
return Range_Constructor(this, m_pITextStoreACP, cookie->lockType, end, end, ppEnd);
return Range_Constructor(this, end, end, ppEnd);
}
STDMETHODIMP CContext::GetActiveView(_Out_ ITfContextView **ppView)
@ -715,7 +695,7 @@ STDMETHODIMP CContext::InsertTextAtSelection(
hr = m_pITextStoreACP->InsertTextAtSelection(dwFlags, pchText, cch, &acpStart, &acpEnd, &change);
if (SUCCEEDED(hr))
Range_Constructor(this, m_pITextStoreACP, cookie->lockType, change.acpStart, change.acpNewEnd, ppRange);
Range_Constructor(this, change.acpStart, change.acpNewEnd, ppRange);
return hr;
}
@ -814,14 +794,14 @@ STDMETHODIMP CContext::OnLockGranted(_In_ DWORD dwLockFlags)
return S_OK;
}
cookie = (EditCookie *)HeapAlloc(GetProcessHeap(), 0, sizeof(EditCookie));
cookie = (EditCookie *)cicMemAlloc(sizeof(EditCookie));
if (!cookie)
return E_OUTOFMEMORY;
sinkcookie = (EditCookie *)HeapAlloc(GetProcessHeap(), 0, sizeof(EditCookie));
sinkcookie = (EditCookie *)cicMemAlloc(sizeof(EditCookie));
if (!sinkcookie)
{
HeapFree(GetProcessHeap(), 0, cookie);
cicMemFree(cookie);
return E_OUTOFMEMORY;
}
@ -847,14 +827,14 @@ STDMETHODIMP CContext::OnLockGranted(_In_ DWORD dwLockFlags)
}
sinkcookie = (EditCookie *)remove_Cookie(sc);
}
HeapFree(GetProcessHeap(), 0, sinkcookie);
cicMemFree(sinkcookie);
m_currentEditSession->Release();
m_currentEditSession = NULL;
/* Edit Cookie is only valid during the edit session */
cookie = (EditCookie *)remove_Cookie(ec);
HeapFree(GetProcessHeap(), 0, cookie);
cicMemFree(cookie);
return hr;
}
@ -914,11 +894,11 @@ HRESULT CContext::CreateInstance(
TfEditCookie *pecTextStore)
{
CContext *This = new(cicNoThrow) CContext();
if (This == NULL)
if (!This)
return E_OUTOFMEMORY;
EditCookie *cookie = (EditCookie *)HeapAlloc(GetProcessHeap(), 0, sizeof(EditCookie));
if (cookie == NULL)
EditCookie *cookie = (EditCookie *)cicMemAlloc(sizeof(EditCookie));
if (!cookie)
{
delete This;
return E_OUTOFMEMORY;

View file

@ -6,26 +6,13 @@
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <msctf.h>
#include <msctf_undoc.h>
// Cicero
#include <cicbase.h>
#include <cicreg.h>
#include <cicutb.h>
#include "precomp.h"
#include "displayattributemgr.h"
#include "msctf_internal.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
////////////////////////////////////////////////////////////////////////////
// CDisplayAttributeMgr
CDisplayAttributeMgr::CDisplayAttributeMgr()
: m_cRefs(1)
@ -34,6 +21,7 @@ CDisplayAttributeMgr::CDisplayAttributeMgr()
CDisplayAttributeMgr::~CDisplayAttributeMgr()
{
TRACE("destroying %p\n", this);
}
BOOL CDisplayAttributeMgr::_IsInCollection(REFGUID rguid)
@ -57,9 +45,6 @@ void CDisplayAttributeMgr::_SetThis()
FIXME("()\n");
}
////////////////////////////////////////////////////////////////////////////
// ** IUnknown methods **
STDMETHODIMP
CDisplayAttributeMgr::QueryInterface(REFIID riid, void **ppvObj)
{
@ -68,13 +53,13 @@ CDisplayAttributeMgr::QueryInterface(REFIID riid, void **ppvObj)
*ppvObj = NULL;
if (IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID(riid, IID_ITfDisplayAttributeMgr) ||
IsEqualIID(riid, IID_CDisplayAttributeMgr))
if (riid == IID_IUnknown ||
riid == IID_ITfDisplayAttributeMgr ||
riid == IID_CDisplayAttributeMgr)
{
*ppvObj = this;
}
else if (IsEqualIID(riid, IID_ITfDisplayAttributeCollectionMgr))
else if (riid == IID_ITfDisplayAttributeCollectionMgr)
{
*ppvObj = static_cast<ITfDisplayAttributeCollectionMgr *>(this);
}
@ -95,17 +80,12 @@ CDisplayAttributeMgr::AddRef()
STDMETHODIMP_(ULONG)
CDisplayAttributeMgr::Release()
{
if (::InterlockedDecrement(&m_cRefs) == 0)
{
ULONG ret = ::InterlockedDecrement(&m_cRefs);
if (!ret)
delete this;
return 0;
}
return m_cRefs;
return ret;
}
////////////////////////////////////////////////////////////////////////////
// ** ITfDisplayAttributeMgr methods **
STDMETHODIMP CDisplayAttributeMgr::OnUpdateInfo()
{
FIXME("()\n");
@ -129,9 +109,6 @@ CDisplayAttributeMgr::GetDisplayAttributeInfo(
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////////
// ** ITfDisplayAttributeCollectionMgr methods **
STDMETHODIMP
CDisplayAttributeMgr::UnknownMethod(_In_ DWORD unused)
{

View file

@ -1,7 +1,5 @@
#pragma once
#include <cicarray.h>
DEFINE_GUID(IID_CDisplayAttributeMgr, 0xFF4619E8, 0xEA5E, 0x43E5, 0xB3, 0x08, 0x11, 0xCD, 0x26, 0xAB, 0x6B, 0x3A);
class CDisplayAttributeMgr

View file

@ -6,32 +6,18 @@
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <oleauto.h>
#include <msctf.h>
#include <msctf_undoc.h>
#include <wine/list.h>
// Cicero
#include <cicbase.h>
#include "precomp.h"
#include "documentmgr.h"
#include "msctf_internal.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
EXTERN_C
HRESULT EnumTfContext_Constructor(CDocumentMgr *mgr, IEnumTfContexts **ppOut);
////////////////////////////////////////////////////////////////////////////
// CDocumentMgr
CDocumentMgr::CDocumentMgr(ITfThreadMgrEventSink *threadMgrSink)
: m_cRefs(1)
, m_pCompartmentMgr(NULL)
, m_initialContext(NULL)
, m_pThreadMgrSink(threadMgrSink)
{
m_contextStack[1] = m_contextStack[0] = NULL;
@ -41,6 +27,9 @@ CDocumentMgr::CDocumentMgr(ITfThreadMgrEventSink *threadMgrSink)
ITfDocumentMgr *pDocMgr = static_cast<ITfDocumentMgr *>(this);
ITfCompartmentMgr **ppCompMgr = static_cast<ITfCompartmentMgr **>(&m_pCompartmentMgr);
CompartmentMgr_Constructor(pDocMgr, IID_IUnknown, reinterpret_cast<IUnknown **>(ppCompMgr));
DWORD cookie;
Context_Constructor(g_processId, NULL, pDocMgr, &m_initialContext, &cookie);
}
CDocumentMgr::~CDocumentMgr()
@ -55,17 +44,12 @@ CDocumentMgr::~CDocumentMgr()
tm->Release();
}
if (m_initialContext)
m_initialContext->Release();
if (m_contextStack[0])
{
m_contextStack[0]->Release();
m_contextStack[0] = NULL;
}
if (m_contextStack[1])
{
m_contextStack[1]->Release();
m_contextStack[1] = NULL;
}
free_sinks(&m_transitoryExtensionSink);
@ -110,20 +94,22 @@ STDMETHODIMP CDocumentMgr::QueryInterface(REFIID iid, LPVOID *ppvObject)
TRACE("%p -> (%s, %p)\n", this, wine_dbgstr_guid(&iid), ppvObject);
*ppvObject = NULL;
IUnknown *pUnk = NULL;
if (iid == IID_IUnknown || iid == IID_ITfDocumentMgr)
*ppvObject = static_cast<ITfDocumentMgr *>(this);
pUnk = static_cast<ITfDocumentMgr *>(this);
else if (iid == IID_ITfSource)
*ppvObject = static_cast<ITfSource *>(this);
pUnk = static_cast<ITfSource *>(this);
else if (iid == IID_ITfCompartmentMgr)
*ppvObject = m_pCompartmentMgr;
pUnk = m_pCompartmentMgr;
if (*ppvObject)
if (pUnk)
{
AddRef();
pUnk->AddRef();
*ppvObject = pUnk;
return S_OK;
}
ERR("E_NOINTERFACE: %s\n", wine_dbgstr_guid(&iid));
WARN("unsupported interface: %s\n", debugstr_guid(&iid));
return E_NOINTERFACE;
}
@ -248,10 +234,16 @@ STDMETHODIMP CDocumentMgr::GetTop(ITfContext **ppic)
return E_INVALIDARG;
}
ITfContext *target;
if (m_contextStack[0])
m_contextStack[0]->AddRef();
target = m_contextStack[0];
else
target = m_initialContext;
*ppic = m_contextStack[0];
if (target)
target->AddRef();
*ppic = target;
return S_OK;
}
@ -265,10 +257,18 @@ STDMETHODIMP CDocumentMgr::GetBase(ITfContext **ppic)
return E_INVALIDARG;
}
ITfContext *target = (m_contextStack[1] ? m_contextStack[1] : m_contextStack[0]);
*ppic = target;
ITfContext *target;
if (m_contextStack[1])
target = m_contextStack[1];
else if (m_contextStack[0])
target = m_contextStack[0];
else
target = m_initialContext;
if (target)
target->AddRef();
*ppic = target;
return S_OK;
}
@ -282,18 +282,18 @@ STDMETHODIMP CDocumentMgr::AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCoo
{
TRACE("%p -> (%s, %p, %p)\n", this, wine_dbgstr_guid(&riid), punk, pdwCookie);
if (!punk || !pdwCookie)
if (cicIsNullPtr(&riid) || !punk || !pdwCookie)
return E_INVALIDARG;
if (riid != IID_ITfTransitoryExtensionSink)
if (riid == IID_ITfTransitoryExtensionSink)
{
FIXME("E_NOTIMPL: %s\n", wine_dbgstr_guid(&riid));
return E_NOTIMPL;
WARN("semi-stub for ITfTransitoryExtensionSink: callback won't be used.\n");
return advise_sink(&m_transitoryExtensionSink, IID_ITfTransitoryExtensionSink,
COOKIE_MAGIC_DMSINK, punk, pdwCookie);
}
return advise_sink(&m_transitoryExtensionSink, IID_ITfTransitoryExtensionSink,
COOKIE_MAGIC_DMSINK, punk, pdwCookie);
FIXME("(%p) Unhandled Sink: %s\n", this, debugstr_guid(&riid));
return E_NOTIMPL;
}
STDMETHODIMP CDocumentMgr::UnadviseSink(DWORD pdwCookie)
@ -307,7 +307,6 @@ STDMETHODIMP CDocumentMgr::UnadviseSink(DWORD pdwCookie)
}
////////////////////////////////////////////////////////////////////////////
// CEnumTfContext
CEnumTfContext::CEnumTfContext(_In_opt_ CDocumentMgr *mgr)
: m_cRefs(1)
@ -336,7 +335,7 @@ HRESULT CEnumTfContext::CreateInstance(_In_opt_ CDocumentMgr *mgr, _Out_ IEnumTf
}
CEnumTfContext *This = new(cicNoThrow) CEnumTfContext(mgr);
if (This == NULL)
if (!This)
{
ERR("E_OUTOFMEMORY\n");
return E_OUTOFMEMORY;

View file

@ -51,11 +51,15 @@ public:
protected:
LONG m_cRefs;
ITfCompartmentMgr *m_pCompartmentMgr;
ITfContext *m_initialContext;
ITfContext *m_contextStack[2]; // limit of 2 contexts
ITfThreadMgrEventSink *m_pThreadMgrSink;
struct list m_transitoryExtensionSink;
};
EXTERN_C
HRESULT EnumTfContext_Constructor(CDocumentMgr *mgr, IEnumTfContexts **ppOut);
////////////////////////////////////////////////////////////////////////////
// CEnumTfContext

View file

@ -6,23 +6,7 @@
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <winnls.h>
#include <cguid.h>
#include <olectl.h>
#include <oleauto.h>
#include <msctf.h>
#include <msctf_undoc.h>
// Cicero
#include <cicbase.h>
#include <cicreg.h>
#include <cicutb.h>
#include "msctf_internal.h"
#include "precomp.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
@ -282,25 +266,25 @@ add_userkey(_In_ REFCLSID rclsid, _In_ LANGID langid, _In_ REFGUID guidProfile)
HKEY key;
WCHAR buf[39], buf2[39], fullkey[168];
DWORD disposition = 0;
ULONG res;
LSTATUS error;
TRACE("\n");
StringFromGUID2(rclsid, buf, _countof(buf));
StringFromGUID2(guidProfile, buf2, _countof(buf2));
swprintf(fullkey, L"%s\\%s\\%s\\0x%08x\\%s", szwSystemTIPKey, buf, L"LanguageProfile",
langid, buf2);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s\\%s\\0x%08x\\%s",
szwSystemTIPKey, buf, L"LanguageProfile", langid, buf2);
res = RegCreateKeyExW(HKEY_CURRENT_USER, fullkey, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &key, &disposition);
error = RegCreateKeyExW(HKEY_CURRENT_USER, fullkey, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &key, &disposition);
if (!res && disposition == REG_CREATED_NEW_KEY)
if (error == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
{
DWORD zero = 0x0;
RegSetValueExW(key, L"Enable", 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
DWORD zero = 0;
RegSetValueExW(key, L"Enable", 0, REG_DWORD, (PBYTE)&zero, sizeof(DWORD));
}
if (!res)
if (error == ERROR_SUCCESS)
RegCloseKey(key);
}
@ -361,7 +345,7 @@ STDMETHODIMP CInputProcessorProfiles::Register(_In_ REFCLSID rclsid)
TRACE("(%p) %s\n", this, debugstr_guid(&rclsid));
StringFromGUID2(rclsid, buf, _countof(buf));
swprintf(fullkey, L"%s\\%s", szwSystemTIPKey, buf);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s", szwSystemTIPKey, buf);
if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL,
&tipkey, NULL) != ERROR_SUCCESS)
@ -380,7 +364,7 @@ STDMETHODIMP CInputProcessorProfiles::Unregister(_In_ REFCLSID rclsid)
TRACE("(%p) %s\n", this, debugstr_guid(&rclsid));
StringFromGUID2(rclsid, buf, _countof(buf));
swprintf(fullkey, L"%s\\%s", szwSystemTIPKey, buf);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s", szwSystemTIPKey, buf);
RegDeleteTreeW(HKEY_LOCAL_MACHINE, fullkey);
RegDeleteTreeW(HKEY_CURRENT_USER, fullkey);
@ -407,14 +391,14 @@ STDMETHODIMP CInputProcessorProfiles::AddLanguageProfile(
debugstr_wn(pchIconFile, cchFile), uIconIndex);
StringFromGUID2(rclsid, buf, _countof(buf));
swprintf(fullkey, L"%s\\%s", szwSystemTIPKey, buf);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s", szwSystemTIPKey, buf);
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &tipkey);
if (error != ERROR_SUCCESS)
return E_FAIL;
StringFromGUID2(guidProfile, buf, _countof(buf));
swprintf(fullkey, L"%s\\0x%08x\\%s", L"LanguageProfile", langid, buf);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\0x%08x\\%s", L"LanguageProfile", langid, buf);
error = RegCreateKeyExW(tipkey, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
NULL, &fmtkey, &disposition);
@ -467,7 +451,8 @@ STDMETHODIMP CInputProcessorProfiles::GetDefaultLanguageProfile(
return E_INVALIDARG;
StringFromGUID2(catid, buf, _countof(buf));
swprintf(fullkey, L"%s\\%s\\0x%08x\\%s", szwSystemCTFKey, L"Assemblies", langid, buf);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s\\0x%08x\\%s", szwSystemCTFKey,
L"Assemblies", langid, buf);
error = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &hKey);
if (error != ERROR_SUCCESS)
@ -522,7 +507,7 @@ STDMETHODIMP CInputProcessorProfiles::SetDefaultLanguageProfile(
return E_FAIL;
StringFromGUID2(catid, buf, _countof(buf));
swprintf(fullkey, L"%s\\%s\\0x%08x\\%s", szwSystemCTFKey, L"Assemblies", langid, buf);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s\\0x%08x\\%s", szwSystemCTFKey, L"Assemblies", langid, buf);
error = RegCreateKeyExW(HKEY_CURRENT_USER, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
NULL, &hKey, NULL);
@ -678,7 +663,8 @@ STDMETHODIMP CInputProcessorProfiles::EnableLanguageProfile(
StringFromGUID2(rclsid, buf, _countof(buf));
StringFromGUID2(guidProfile, buf2, _countof(buf2));
swprintf(fullkey, L"%s\\%s\\%s\\0x%08x\\%s", szwSystemTIPKey, buf, L"LanguageProfile", langid, buf2);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s\\%s\\0x%08x\\%s", szwSystemTIPKey, buf,
L"LanguageProfile", langid, buf2);
error = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
if (error != ERROR_SUCCESS)
@ -706,7 +692,8 @@ STDMETHODIMP CInputProcessorProfiles::IsEnabledLanguageProfile(
StringFromGUID2(rclsid, buf, _countof(buf));
StringFromGUID2(guidProfile, buf2, _countof(buf2));
swprintf(fullkey, L"%s\\%s\\%s\\0x%08x\\%s", szwSystemTIPKey, buf, L"LanguageProfile", langid, buf2);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s\\%s\\0x%08x\\%s", szwSystemTIPKey,
buf, L"LanguageProfile", langid, buf2);
error = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
if (error == ERROR_SUCCESS)
@ -744,7 +731,8 @@ STDMETHODIMP CInputProcessorProfiles::EnableLanguageProfileByDefault(
StringFromGUID2(rclsid, buf, _countof(buf));
StringFromGUID2(guidProfile, buf2, _countof(buf2));
swprintf(fullkey, L"%s\\%s\\%s\\0x%08x\\%s", szwSystemTIPKey, buf, L"LanguageProfile", langid, buf2);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s\\%s\\0x%08x\\%s", szwSystemTIPKey,
buf, L"LanguageProfile", langid, buf2);
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
if (error != ERROR_SUCCESS)
@ -1127,7 +1115,8 @@ INT CEnumTfLanguageProfiles::next_LanguageProfile(CLSID clsid, TF_LANGUAGEPROFIL
if (!m_langkey)
{
swprintf(fullkey, L"%s\\%s\\0x%08x", m_szwCurrentClsid, L"LanguageProfile", m_langid);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s\\0x%08x", m_szwCurrentClsid,
L"LanguageProfile", m_langid);
error = RegOpenKeyExW(m_tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &m_langkey);
if (error != ERROR_SUCCESS)
{
@ -1175,7 +1164,7 @@ STDMETHODIMP CEnumTfLanguageProfiles::Next(
TRACE("(%p)\n", this);
if (pProfile == NULL)
if (!pProfile)
return E_POINTER;
if (m_tipkey)
@ -1256,7 +1245,7 @@ STDMETHODIMP CEnumTfLanguageProfiles::Clone(_Out_ IEnumTfLanguageProfiles **ppEn
if (m_langkey)
{
WCHAR fullkey[168];
swprintf(fullkey, L"%s\\%s\\0x%08x", m_szwCurrentClsid, L"LanguageProfile", m_langid);
StringCchPrintfW(fullkey, _countof(fullkey), L"%s\\%s\\0x%08x", m_szwCurrentClsid, L"LanguageProfile", m_langid);
RegOpenKeyExW(new_This->m_tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &new_This->m_langkey);
new_This->m_lang_index = m_lang_index;
}

View file

@ -6,19 +6,7 @@
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <msctf.h>
#include <msctf_undoc.h>
// Cicero
#include <cicbase.h>
#include <cicreg.h>
#include <cicutb.h>
#include "msctf_internal.h"
#include "precomp.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
@ -117,9 +105,6 @@ HRESULT CLangBarMgr::s_ShowFloating(_In_ DWORD dwFlags)
return E_NOTIMPL;
}
//*****************************************************************************************
// ** IUnknown interface **
STDMETHODIMP
CLangBarMgr::QueryInterface(
_In_ REFIID riid,
@ -128,37 +113,33 @@ CLangBarMgr::QueryInterface(
if (!ppvObj)
return E_INVALIDARG;
if (!IsEqualIID(riid, IID_IUnknown) &&
!IsEqualIID(riid, IID_ITfLangBarMgr) &&
!IsEqualIID(riid, IID_ITfLangBarMgr_P))
*ppvObj = NULL;
if (riid == IID_IUnknown || riid == IID_ITfLangBarMgr || riid == IID_ITfLangBarMgr_P)
*ppvObj = static_cast<ITfLangBarMgr_P *>(this);
if (*ppvObj)
{
*ppvObj = NULL;
return E_NOINTERFACE;
AddRef();
return S_OK;
}
*ppvObj = this;
AddRef();
return S_OK;
WARN("unsupported interface: %s\n", debugstr_guid(&riid));
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CLangBarMgr::AddRef()
{
return ++m_cRefs;
return ::InterlockedIncrement(&m_cRefs);
}
STDMETHODIMP_(ULONG) CLangBarMgr::Release()
{
if (!--m_cRefs)
{
ULONG ret = ::InterlockedDecrement(&m_cRefs);
if (!ret)
delete this;
return 0;
}
return m_cRefs;
return ret;
}
//*****************************************************************************************
// ** ITfLangBarMgr interface **
STDMETHODIMP
CLangBarMgr::AdviseEventSink(
_In_ ITfLangBarEventSink *pSink,
@ -252,9 +233,6 @@ CLangBarMgr::GetShowFloatingStatus(
return s_GetShowFloatingStatus(pdwFlags);
}
//*****************************************************************************************
// ** ITfLangBarMgr_P interface **
STDMETHODIMP
CLangBarMgr::GetPrevShowFloatingStatus(_Inout_ DWORD* pdwStatus)
{

View file

@ -1,31 +1,24 @@
/*
* PROJECT: ReactOS msctf.dll
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PROJECT: ReactOS CTF
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
* PURPOSE: Multi-language handling of Cicero
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#define WIN32_NO_STATUS
#include "precomp.h"
#include <windows.h>
#include <shellapi.h>
#include <imm.h>
#include <imm32_undoc.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <shlwapi_undoc.h>
#include <msctf.h>
#include <msctf_undoc.h>
#include <strsafe.h>
#include <assert.h>
#include <cicreg.h>
#include <cicarray.h>
#include <wine/debug.h>
#include "mlng.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
extern CRITICAL_SECTION g_cs;

View file

@ -1,6 +1,6 @@
/*
* PROJECT: ReactOS msctf.dll
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PROJECT: ReactOS CTF
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
* PURPOSE: Multi-language handling of Cicero
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/

View file

@ -1,42 +1,14 @@
/*
* MSCTF Server DLL
*
* Copyright 2008 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
* PROJECT: ReactOS CTF
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
* PURPOSE: MSCTF Server DLL
* COPYRIGHT: Copyright 2008 Aric Stewart, CodeWeavers
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <stdarg.h>
#include <stdio.h>
#define COBJMACROS
#include "wine/debug.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "shlguid.h"
#include "comcat.h"
#include "olectl.h"
#include "rpcproxy.h"
#include "msctf.h"
#include "inputscope.h"
#include "msctf_internal.h"
#include "precomp.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
static HINSTANCE MSCTF_hinstance;
@ -69,17 +41,14 @@ static UINT array_size;
static struct list AtsList = LIST_INIT(AtsList);
static UINT activated = 0;
DWORD tlsIndex = 0;
TfClientId processId = 0;
ITfCompartmentMgr *globalCompartmentMgr = NULL;
const WCHAR szwSystemTIPKey[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','C','T','F','\\','T','I','P',0};
const WCHAR szwSystemCTFKey[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','C','T','F',0};
DWORD g_tlsIndex = 0;
TfClientId g_processId = 0;
ITfCompartmentMgr *g_globalCompartmentMgr = NULL;
typedef HRESULT (*LPFNCONSTRUCTOR)(IUnknown *pUnkOuter, IUnknown **ppvOut);
static const struct {
REFCLSID clsid;
const CLSID *clsid;
LPFNCONSTRUCTOR ctor;
} ClassesTable[] = {
{&CLSID_TF_ThreadMgr, ThreadMgr_Constructor},
@ -90,95 +59,94 @@ static const struct {
{NULL, NULL}
};
typedef struct tagClassFactory
class CClassFactory
: public IClassFactory
{
IClassFactory IClassFactory_iface;
LONG ref;
LPFNCONSTRUCTOR ctor;
} ClassFactory;
public:
CClassFactory(LPFNCONSTRUCTOR ctor);
virtual ~CClassFactory();
static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface)
// ** IUnknown methods **
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// ** IClassFactory methods **
STDMETHODIMP CreateInstance(
_In_ IUnknown *pUnkOuter,
_In_ REFIID riid,
_Out_ void **ppvObject) override;
STDMETHODIMP LockServer(_In_ BOOL fLock) override;
protected:
LONG m_cRefs;
LPFNCONSTRUCTOR m_ctor;
};
CClassFactory::CClassFactory(LPFNCONSTRUCTOR ctor)
: m_cRefs(1)
, m_ctor(ctor)
{
return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
}
static void ClassFactory_Destructor(ClassFactory *This)
CClassFactory::~CClassFactory()
{
TRACE("Destroying class factory %p\n", This);
HeapFree(GetProcessHeap(),0,This);
TRACE("Destroying class factory %p\n", this);
}
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppvOut)
STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObj)
{
*ppvOut = NULL;
if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown)) {
IClassFactory_AddRef(iface);
*ppvOut = iface;
*ppvObj = NULL;
if (riid == IID_IClassFactory || riid == IID_IUnknown)
{
AddRef();
*ppvObj = static_cast<IClassFactory *>(this);
return S_OK;
}
WARN("Unknown interface %s\n", debugstr_guid(riid));
WARN("Unknown interface %s\n", debugstr_guid(&riid));
return E_NOINTERFACE;
}
static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
STDMETHODIMP_(ULONG) CClassFactory::AddRef()
{
ClassFactory *This = impl_from_IClassFactory(iface);
return InterlockedIncrement(&This->ref);
return ::InterlockedIncrement(&m_cRefs);
}
static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
STDMETHODIMP_(ULONG) CClassFactory::Release()
{
ClassFactory *This = impl_from_IClassFactory(iface);
ULONG ret = InterlockedDecrement(&This->ref);
if (ret == 0)
ClassFactory_Destructor(This);
ULONG ret = InterlockedDecrement(&m_cRefs);
if (!ret)
delete this;
return ret;
}
static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID iid, LPVOID *ppvOut)
STDMETHODIMP CClassFactory::CreateInstance(
_In_ IUnknown *pUnkOuter,
_In_ REFIID riid,
_Out_ void **ppvObject)
{
ClassFactory *This = impl_from_IClassFactory(iface);
HRESULT ret;
IUnknown *obj;
TRACE("(%p, %p, %s, %p)\n", this, pUnkOuter, debugstr_guid(&riid), ppvObject);
TRACE("(%p, %p, %s, %p)\n", iface, punkOuter, debugstr_guid(iid), ppvOut);
ret = This->ctor(punkOuter, &obj);
IUnknown *obj;
HRESULT ret = m_ctor(pUnkOuter, &obj);
if (FAILED(ret))
return ret;
ret = IUnknown_QueryInterface(obj, iid, ppvOut);
IUnknown_Release(obj);
ret = obj->QueryInterface(riid, ppvObject);
obj->Release();
return ret;
}
static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock)
STDMETHODIMP CClassFactory::LockServer(_In_ BOOL fLock)
{
ClassFactory *This = impl_from_IClassFactory(iface);
TRACE("(%p)->(%x)\n", This, fLock);
TRACE("(%p)->(%x)\n", this, fLock);
return S_OK;
}
static const IClassFactoryVtbl ClassFactoryVtbl = {
/* IUnknown */
ClassFactory_QueryInterface,
ClassFactory_AddRef,
ClassFactory_Release,
/* IClassFactory*/
ClassFactory_CreateInstance,
ClassFactory_LockServer
};
static HRESULT ClassFactory_Constructor(LPFNCONSTRUCTOR ctor, LPVOID *ppvOut)
{
ClassFactory *This = HeapAlloc(GetProcessHeap(),0,sizeof(ClassFactory));
This->IClassFactory_iface.lpVtbl = &ClassFactoryVtbl;
This->ref = 1;
This->ctor = ctor;
*ppvOut = &This->IClassFactory_iface;
CClassFactory *This = new(cicNoThrow) CClassFactory(ctor);
*ppvOut = static_cast<IClassFactory *>(This);
TRACE("Created class factory %p\n", This);
return S_OK;
}
@ -186,6 +154,7 @@ static HRESULT ClassFactory_Constructor(LPFNCONSTRUCTOR ctor, LPVOID *ppvOut)
/*************************************************************************
* DWORD Cookie Management
*/
EXTERN_C
DWORD generate_Cookie(DWORD magic, LPVOID data)
{
UINT i;
@ -198,7 +167,7 @@ DWORD generate_Cookie(DWORD magic, LPVOID data)
{
if (!array_size)
{
cookies = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CookieInternal) * 10);
cookies = (CookieInternal *)cicMemAllocClear(10 * sizeof(CookieInternal));
if (!cookies)
{
ERR("Out of memory, Unable to alloc cookies array\n");
@ -208,8 +177,9 @@ DWORD generate_Cookie(DWORD magic, LPVOID data)
}
else
{
CookieInternal *new_cookies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cookies,
sizeof(CookieInternal) * (array_size * 2));
ERR("cookies: %p, array_size: %d\n", cookies, array_size);
CookieInternal *new_cookies = (CookieInternal *)
cicMemReCalloc(cookies, array_size * 2, sizeof(CookieInternal));
if (!new_cookies)
{
ERR("Out of memory, Unable to realloc cookies array\n");
@ -230,6 +200,7 @@ DWORD generate_Cookie(DWORD magic, LPVOID data)
return cookies[i].id;
}
EXTERN_C
DWORD get_Cookie_magic(DWORD id)
{
UINT index = id - 1;
@ -243,6 +214,7 @@ DWORD get_Cookie_magic(DWORD id)
return cookies[index].magic;
}
EXTERN_C
LPVOID get_Cookie_data(DWORD id)
{
UINT index = id - 1;
@ -256,6 +228,7 @@ LPVOID get_Cookie_data(DWORD id)
return cookies[index].data;
}
EXTERN_C
LPVOID remove_Cookie(DWORD id)
{
UINT index = id - 1;
@ -270,6 +243,7 @@ LPVOID remove_Cookie(DWORD id)
return cookies[index].data;
}
EXTERN_C
DWORD enumerate_Cookie(DWORD magic, DWORD *index)
{
unsigned int i;
@ -282,17 +256,17 @@ DWORD enumerate_Cookie(DWORD magic, DWORD *index)
return 0x0;
}
EXTERN_C
HRESULT advise_sink(struct list *sink_list, REFIID riid, DWORD cookie_magic, IUnknown *unk, DWORD *cookie)
{
Sink *sink;
sink = HeapAlloc(GetProcessHeap(), 0, sizeof(*sink));
Sink *sink = (Sink *)cicMemAlloc(sizeof(*sink));
if (!sink)
return E_OUTOFMEMORY;
if (FAILED(IUnknown_QueryInterface(unk, riid, (void**)&sink->interfaces.pIUnknown)))
HRESULT hr = unk->QueryInterface(riid, (void **)&sink->interfaces.pIUnknown);
if (FAILED(hr))
{
HeapFree(GetProcessHeap(), 0, sink);
cicMemFree(sink);
return CONNECT_E_CANNOTCONNECT;
}
@ -305,15 +279,14 @@ HRESULT advise_sink(struct list *sink_list, REFIID riid, DWORD cookie_magic, IUn
static void free_sink(Sink *sink)
{
list_remove(&sink->entry);
IUnknown_Release(sink->interfaces.pIUnknown);
HeapFree(GetProcessHeap(), 0, sink);
sink->interfaces.pIUnknown->Release();
cicMemFree(sink);
}
EXTERN_C
HRESULT unadvise_sink(DWORD cookie)
{
Sink *sink;
sink = remove_Cookie(cookie);
Sink *sink = (Sink *)remove_Cookie(cookie);
if (!sink)
return CONNECT_E_NOCONNECTION;
@ -321,6 +294,7 @@ HRESULT unadvise_sink(DWORD cookie)
return S_OK;
}
EXTERN_C
void free_sinks(struct list *sink_list)
{
while(!list_empty(sink_list))
@ -341,20 +315,20 @@ static HRESULT activate_given_ts(ActivatedTextService *actsvr, ITfThreadMgrEx *t
if (actsvr->pITfTextInputProcessor)
return S_OK;
hr = CoCreateInstance (&actsvr->LanguageProfile.clsid, NULL, CLSCTX_INPROC_SERVER,
&IID_ITfTextInputProcessor, (void**)&actsvr->pITfTextInputProcessor);
hr = CoCreateInstance(actsvr->LanguageProfile.clsid, NULL, CLSCTX_INPROC_SERVER,
IID_ITfTextInputProcessor, (void **)&actsvr->pITfTextInputProcessor);
if (FAILED(hr)) return hr;
hr = ITfTextInputProcessor_Activate(actsvr->pITfTextInputProcessor, (ITfThreadMgr *)tm, actsvr->tid);
hr = actsvr->pITfTextInputProcessor->Activate((ITfThreadMgr *)tm, actsvr->tid);
if (FAILED(hr))
{
ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor);
actsvr->pITfTextInputProcessor->Release();
actsvr->pITfTextInputProcessor = NULL;
return hr;
}
actsvr->pITfThreadMgrEx = tm;
ITfThreadMgrEx_AddRef(tm);
tm->AddRef();
return hr;
}
@ -364,9 +338,9 @@ static HRESULT deactivate_given_ts(ActivatedTextService *actsvr)
if (actsvr->pITfTextInputProcessor)
{
hr = ITfTextInputProcessor_Deactivate(actsvr->pITfTextInputProcessor);
ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor);
ITfThreadMgrEx_Release(actsvr->pITfThreadMgrEx);
hr = actsvr->pITfTextInputProcessor->Deactivate();
actsvr->pITfTextInputProcessor->Release();
actsvr->pITfThreadMgrEx->Release();
actsvr->pITfTextInputProcessor = NULL;
actsvr->pITfThreadMgrEx = NULL;
}
@ -380,38 +354,41 @@ static void deactivate_remove_conflicting_ts(REFCLSID catid)
LIST_FOR_EACH_ENTRY_SAFE(ats, cursor2, &AtsList, AtsEntry, entry)
{
if (IsEqualCLSID(catid,&ats->ats->LanguageProfile.catid))
if (catid == ats->ats->LanguageProfile.catid)
{
deactivate_given_ts(ats->ats);
list_remove(&ats->entry);
HeapFree(GetProcessHeap(),0,ats->ats);
HeapFree(GetProcessHeap(),0,ats);
cicMemFree(ats->ats);
cicMemFree(ats);
/* we are guaranteeing there is only 1 */
break;
}
}
}
EXTERN_C
HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
{
ActivatedTextService *actsvr;
ITfCategoryMgr *catmgr;
AtsEntry *entry;
ITfThreadMgrEx *tm = TlsGetValue(tlsIndex);
ITfThreadMgrEx *tm = (ITfThreadMgrEx *)TlsGetValue(g_tlsIndex);
ITfClientId *clientid;
if (!tm) return E_UNEXPECTED;
if (!tm)
return E_UNEXPECTED;
actsvr = HeapAlloc(GetProcessHeap(),0,sizeof(ActivatedTextService));
if (!actsvr) return E_OUTOFMEMORY;
actsvr = (ActivatedTextService *)cicMemAlloc(sizeof(ActivatedTextService));
if (!actsvr)
return E_OUTOFMEMORY;
ITfThreadMgrEx_QueryInterface(tm, &IID_ITfClientId, (void **)&clientid);
ITfClientId_GetClientId(clientid, &lp->clsid, &actsvr->tid);
ITfClientId_Release(clientid);
tm->QueryInterface(IID_ITfClientId, (void **)&clientid);
clientid->GetClientId(lp->clsid, &actsvr->tid);
clientid->Release();
if (!actsvr->tid)
{
HeapFree(GetProcessHeap(),0,actsvr);
cicMemFree(actsvr);
return E_OUTOFMEMORY;
}
@ -420,15 +397,12 @@ HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
actsvr->pITfKeyEventSink = NULL;
/* get TIP category */
if (SUCCEEDED(CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr)))
if (SUCCEEDED(CategoryMgr_Constructor(NULL, (IUnknown**)&catmgr)))
{
static const GUID *list[3] = {&GUID_TFCAT_TIP_SPEECH, &GUID_TFCAT_TIP_KEYBOARD, &GUID_TFCAT_TIP_HANDWRITING};
ITfCategoryMgr_FindClosestCategory(catmgr,
&actsvr->LanguageProfile.clsid, &actsvr->LanguageProfile.catid,
list, 3);
ITfCategoryMgr_Release(catmgr);
catmgr->FindClosestCategory(actsvr->LanguageProfile.clsid, &actsvr->LanguageProfile.catid, list, 3);
catmgr->Release();
}
else
{
@ -436,17 +410,16 @@ HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
actsvr->LanguageProfile.catid = GUID_NULL;
}
if (!IsEqualGUID(&actsvr->LanguageProfile.catid,&GUID_NULL))
deactivate_remove_conflicting_ts(&actsvr->LanguageProfile.catid);
if (actsvr->LanguageProfile.catid != GUID_NULL)
deactivate_remove_conflicting_ts(actsvr->LanguageProfile.catid);
if (activated > 0)
activate_given_ts(actsvr, tm);
entry = HeapAlloc(GetProcessHeap(),0,sizeof(AtsEntry));
entry = (AtsEntry *)cicMemAlloc(sizeof(AtsEntry));
if (!entry)
{
HeapFree(GetProcessHeap(),0,actsvr);
cicMemFree(actsvr);
return E_OUTOFMEMORY;
}
@ -456,13 +429,14 @@ HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
return S_OK;
}
EXTERN_C
BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *profile)
{
AtsEntry *ats;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
{
if (IsEqualCLSID(rclsid,&ats->ats->LanguageProfile.clsid))
if (rclsid == ats->ats->LanguageProfile.clsid)
{
if (profile)
*profile = ats->ats->LanguageProfile;
@ -472,6 +446,7 @@ BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *profile)
return FALSE;
}
EXTERN_C
HRESULT activate_textservices(ITfThreadMgrEx *tm)
{
HRESULT hr = S_OK;
@ -490,6 +465,7 @@ HRESULT activate_textservices(ITfThreadMgrEx *tm)
return hr;
}
EXTERN_C
HRESULT deactivate_textservices(void)
{
AtsEntry *ats;
@ -498,52 +474,62 @@ HRESULT deactivate_textservices(void)
activated --;
if (activated == 0)
{
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
deactivate_given_ts(ats->ats);
}
return S_OK;
}
EXTERN_C
CLSID get_textservice_clsid(TfClientId tid)
{
AtsEntry *ats;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
{
if (ats->ats->tid == tid)
return ats->ats->LanguageProfile.clsid;
}
return GUID_NULL;
}
EXTERN_C
HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown **sink)
{
AtsEntry *ats;
if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink))
if (iid != IID_ITfKeyEventSink)
return E_NOINTERFACE;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
{
if (ats->ats->tid == tid)
{
*sink = (IUnknown*)ats->ats->pITfKeyEventSink;
return S_OK;
}
}
return E_FAIL;
}
EXTERN_C
HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink)
{
AtsEntry *ats;
if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink))
if (iid != IID_ITfKeyEventSink)
return E_NOINTERFACE;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
{
if (ats->ats->tid == tid)
{
ats->ats->pITfKeyEventSink = (ITfKeyEventSink*)sink;
return S_OK;
}
}
return E_FAIL;
}
@ -556,17 +542,13 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID fImpLoad)
TRACE("%p 0x%x %p\n", hinst, fdwReason, fImpLoad);
switch (fdwReason)
{
#ifndef __REACTOS__
case DLL_WINE_PREATTACH:
return FALSE; /* prefer native version */
#endif
case DLL_PROCESS_ATTACH:
MSCTF_hinstance = hinst;
tlsIndex = TlsAlloc();
g_tlsIndex = TlsAlloc();
break;
case DLL_PROCESS_DETACH:
if (fImpLoad) break;
TlsFree(tlsIndex);
TlsFree(g_tlsIndex);
break;
}
return TRUE;
@ -588,14 +570,15 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID *ppvOut)
int i;
*ppvOut = NULL;
if (!IsEqualIID(iid, &IID_IUnknown) && !IsEqualIID(iid, &IID_IClassFactory))
if (iid != IID_IUnknown && iid != IID_IClassFactory)
return E_NOINTERFACE;
for (i = 0; ClassesTable[i].clsid != NULL; i++)
if (IsEqualCLSID(ClassesTable[i].clsid, clsid)) {
for (i = 0; ClassesTable[i].clsid; i++)
{
if (*ClassesTable[i].clsid == clsid)
return ClassFactory_Constructor(ClassesTable[i].ctor, ppvOut);
}
FIXME("CLSID %s not supported\n", debugstr_guid(clsid));
}
FIXME("CLSID %s not supported\n", debugstr_guid(&clsid));
return CLASS_E_CLASSNOTAVAILABLE;
}
@ -621,7 +604,7 @@ HRESULT WINAPI DllUnregisterServer(void)
HRESULT WINAPI TF_CreateThreadMgr(ITfThreadMgr **pptim)
{
TRACE("\n");
return ThreadMgr_Constructor(NULL,(IUnknown**)pptim);
return ThreadMgr_Constructor(NULL, (IUnknown**)pptim);
}
/***********************************************************************
@ -630,10 +613,10 @@ HRESULT WINAPI TF_CreateThreadMgr(ITfThreadMgr **pptim)
HRESULT WINAPI TF_GetThreadMgr(ITfThreadMgr **pptim)
{
TRACE("\n");
*pptim = TlsGetValue(tlsIndex);
*pptim = (ITfThreadMgr *)TlsGetValue(g_tlsIndex);
if (*pptim)
ITfThreadMgr_AddRef(*pptim);
(*pptim)->AddRef();
return S_OK;
}
@ -643,7 +626,7 @@ HRESULT WINAPI TF_GetThreadMgr(ITfThreadMgr **pptim)
*/
HRESULT WINAPI SetInputScope(HWND hwnd, InputScope inputscope)
{
FIXME("STUB: %p %i\n",hwnd,inputscope);
FIXME("STUB: %p %i\n", hwnd, inputscope);
return S_OK;
}
@ -655,11 +638,11 @@ HRESULT WINAPI SetInputScopes(HWND hwnd, const InputScope *pInputScopes,
UINT cPhrases, WCHAR *pszRegExp, WCHAR *pszSRGS)
{
UINT i;
FIXME("STUB: %p ... %s %s\n",hwnd, debugstr_w(pszRegExp), debugstr_w(pszSRGS));
FIXME("STUB: %p ... %s %s\n", hwnd, debugstr_w(pszRegExp), debugstr_w(pszSRGS));
for (i = 0; i < cInputScopes; i++)
TRACE("\tScope[%u] = %i\n",i,pInputScopes[i]);
TRACE("\tScope[%u] = %i\n", i, pInputScopes[i]);
for (i = 0; i < cPhrases; i++)
TRACE("\tPhrase[%u] = %s\n",i,debugstr_w(ppszPhraseList[i]));
TRACE("\tPhrase[%u] = %s\n", i, debugstr_w(ppszPhraseList[i]));
return S_OK;
}
@ -670,7 +653,7 @@ HRESULT WINAPI SetInputScopes(HWND hwnd, const InputScope *pInputScopes,
HRESULT WINAPI TF_CreateInputProcessorProfiles(
ITfInputProcessorProfiles **ppipr)
{
return InputProcessorProfiles_Constructor(NULL,(IUnknown**)ppipr);
return InputProcessorProfiles_Constructor(NULL, (IUnknown**)ppipr);
}
/***********************************************************************
@ -688,9 +671,12 @@ HRESULT WINAPI TF_InvalidAssemblyListCacheIfExist(void)
HRESULT WINAPI TF_CreateLangBarMgr(ITfLangBarMgr **pppbm)
{
TRACE("\n");
return LangBarMgr_Constructor(NULL,(IUnknown**)pppbm);
return LangBarMgr_Constructor(NULL, (IUnknown**)pppbm);
}
/***********************************************************************
* TF_CreateLangBarItemMgr (MSCTF.@)
*/
HRESULT WINAPI TF_CreateLangBarItemMgr(ITfLangBarItemMgr **pplbim)
{
FIXME("stub %p\n", pplbim);
@ -698,14 +684,3 @@ HRESULT WINAPI TF_CreateLangBarItemMgr(ITfLangBarItemMgr **pplbim)
return E_NOTIMPL;
}
#ifndef __REACTOS__ /* See mlng.cpp */
/***********************************************************************
* TF_InitMlngInfo (MSCTF.@)
*/
HRESULT WINAPI TF_InitMlngInfo(void)
{
FIXME("stub\n");
return S_OK;
}
#endif

View file

@ -1,109 +0,0 @@
/*
* Internal header for msctf.dll
*
* Copyright 2008 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_MSCTF_I_H
#define __WINE_MSCTF_I_H
#include "wine/list.h"
#if defined(__REACTOS__) && defined(__cplusplus)
extern "C" {
#endif
#define COOKIE_MAGIC_TMSINK 0x0010
#define COOKIE_MAGIC_CONTEXTSINK 0x0020
#define COOKIE_MAGIC_GUIDATOM 0x0030
#define COOKIE_MAGIC_IPPSINK 0x0040
#define COOKIE_MAGIC_EDITCOOKIE 0x0050
#define COOKIE_MAGIC_COMPARTMENTSINK 0x0060
#define COOKIE_MAGIC_DMSINK 0x0070
#define COOKIE_MAGIC_THREADFOCUSSINK 0x0080
#define COOKIE_MAGIC_KEYTRACESINK 0x0090
#define COOKIE_MAGIC_UIELEMENTSINK 0x00a0
#define COOKIE_MAGIC_INPUTPROCESSORPROFILEACTIVATIONSINK 0x00b0
#define COOKIE_MAGIC_ACTIVELANGSINK 0x00c0
extern DWORD tlsIndex DECLSPEC_HIDDEN;
extern TfClientId processId DECLSPEC_HIDDEN;
extern ITfCompartmentMgr *globalCompartmentMgr DECLSPEC_HIDDEN;
extern HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) DECLSPEC_HIDDEN;
extern HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink*, ITfDocumentMgr **ppOut) DECLSPEC_HIDDEN;
extern HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore) DECLSPEC_HIDDEN;
extern HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) DECLSPEC_HIDDEN;
extern HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) DECLSPEC_HIDDEN;
extern HRESULT Range_Constructor(ITfContext *context, ITextStoreACP *textstore, DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut) DECLSPEC_HIDDEN;
extern HRESULT CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown **ppOut) DECLSPEC_HIDDEN;
extern HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *This) DECLSPEC_HIDDEN;
extern HRESULT LangBarMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) DECLSPEC_HIDDEN;
extern HRESULT DisplayAttributeMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) DECLSPEC_HIDDEN;
extern HRESULT Context_Initialize(ITfContext *cxt, ITfDocumentMgr *manager) DECLSPEC_HIDDEN;
extern HRESULT Context_Uninitialize(ITfContext *cxt) DECLSPEC_HIDDEN;
extern void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr) DECLSPEC_HIDDEN;
extern HRESULT TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp) DECLSPEC_HIDDEN;
/* cookie function */
extern DWORD generate_Cookie(DWORD magic, LPVOID data) DECLSPEC_HIDDEN;
extern DWORD get_Cookie_magic(DWORD id) DECLSPEC_HIDDEN;
extern LPVOID get_Cookie_data(DWORD id) DECLSPEC_HIDDEN;
extern LPVOID remove_Cookie(DWORD id) DECLSPEC_HIDDEN;
extern DWORD enumerate_Cookie(DWORD magic, DWORD *index) DECLSPEC_HIDDEN;
/* activated text services functions */
extern HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp) DECLSPEC_HIDDEN;
extern BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *lp) DECLSPEC_HIDDEN;
extern HRESULT activate_textservices(ITfThreadMgrEx *tm) DECLSPEC_HIDDEN;
extern HRESULT deactivate_textservices(void) DECLSPEC_HIDDEN;
extern CLSID get_textservice_clsid(TfClientId tid) DECLSPEC_HIDDEN;
extern HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown** sink) DECLSPEC_HIDDEN;
extern HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink) DECLSPEC_HIDDEN;
typedef struct {
struct list entry;
union {
IUnknown *pIUnknown;
ITfThreadMgrEventSink *pITfThreadMgrEventSink;
ITfCompartmentEventSink *pITfCompartmentEventSink;
ITfTextEditSink *pITfTextEditSink;
ITfLanguageProfileNotifySink *pITfLanguageProfileNotifySink;
ITfTransitoryExtensionSink *pITfTransitoryExtensionSink;
} interfaces;
} Sink;
#define SINK_ENTRY(cursor,type) (LIST_ENTRY(cursor,Sink,entry)->interfaces.p##type)
#define SINK_FOR_EACH(cursor,list,type,elem) \
for ((cursor) = (list)->next, elem = SINK_ENTRY(cursor,type); \
(cursor) != (list); \
(cursor) = (cursor)->next, elem = SINK_ENTRY(cursor,type))
HRESULT advise_sink(struct list *sink_list, REFIID riid, DWORD cookie_magic, IUnknown *unk, DWORD *cookie) DECLSPEC_HIDDEN;
HRESULT unadvise_sink(DWORD cookie) DECLSPEC_HIDDEN;
void free_sinks(struct list *sink_list) DECLSPEC_HIDDEN;
extern const WCHAR szwSystemTIPKey[] DECLSPEC_HIDDEN;
extern const WCHAR szwSystemCTFKey[] DECLSPEC_HIDDEN;
#if defined(__REACTOS__) && defined(__cplusplus)
} // extern "C"
#endif
#endif /* __WINE_MSCTF_I_H */

View file

@ -1,27 +1,113 @@
/*
* PROJECT: ReactOS CTF
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
* PURPOSE: Precompiled header for msctf.dll
* COPYRIGHT: Copyright 2008 Aric Stewart, CodeWeavers
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#ifndef _MSCTF_PRECOMP_H
#define _MSCTF_PRECOMP_H
#include <stdarg.h>
#include <wchar.h>
#define WIN32_NO_STATUS
#define _INC_WINDOWS
#define COM_NO_WINDOWS_H
#define COBJMACROS
#pragma once
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <objbase.h>
#include <oleauto.h>
#include <olectl.h>
#include <cguid.h>
#include <msctf.h>
#include <shlwapi.h>
#include <msctf_undoc.h>
#include <tchar.h>
#include <strsafe.h>
#include <wine/list.h>
#include <wine/debug.h>
#include "msctf_internal.h"
// Cicero
#include <cicbase.h>
#include <cicarray.h>
#include <cicreg.h>
#include <cicutb.h>
#endif /* !_MSCTF_PRECOMP_H */
#ifdef __cplusplus
extern "C" {
#endif
#define COOKIE_MAGIC_TMSINK 0x0010
#define COOKIE_MAGIC_CONTEXTSINK 0x0020
#define COOKIE_MAGIC_GUIDATOM 0x0030
#define COOKIE_MAGIC_IPPSINK 0x0040
#define COOKIE_MAGIC_EDITCOOKIE 0x0050
#define COOKIE_MAGIC_COMPARTMENTSINK 0x0060
#define COOKIE_MAGIC_DMSINK 0x0070
#define COOKIE_MAGIC_THREADFOCUSSINK 0x0080
#define COOKIE_MAGIC_KEYTRACESINK 0x0090
#define COOKIE_MAGIC_UIELEMENTSINK 0x00a0
#define COOKIE_MAGIC_INPUTPROCESSORPROFILEACTIVATIONSINK 0x00b0
#define COOKIE_MAGIC_ACTIVELANGSINK 0x00c0
extern DWORD g_tlsIndex;
extern TfClientId g_processId;
extern ITfCompartmentMgr *g_globalCompartmentMgr;
HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut);
HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink*, ITfDocumentMgr **ppOut);
HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore);
HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut);
HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut);
HRESULT Range_Constructor(ITfContext *context, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut);
HRESULT CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown **ppOut);
HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *This);
HRESULT LangBarMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut);
HRESULT DisplayAttributeMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut);
HRESULT Context_Initialize(ITfContext *cxt, ITfDocumentMgr *manager);
HRESULT Context_Uninitialize(ITfContext *cxt);
void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr);
HRESULT TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp);
/* cookie function */
DWORD generate_Cookie(DWORD magic, LPVOID data);
DWORD get_Cookie_magic(DWORD id);
LPVOID get_Cookie_data(DWORD id);
LPVOID remove_Cookie(DWORD id);
DWORD enumerate_Cookie(DWORD magic, DWORD *index);
/* activated text services functions */
HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp);
BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *lp);
HRESULT activate_textservices(ITfThreadMgrEx *tm);
HRESULT deactivate_textservices(void);
CLSID get_textservice_clsid(TfClientId tid);
HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown** sink);
HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink);
typedef struct {
struct list entry;
union {
IUnknown *pIUnknown;
ITfThreadMgrEventSink *pITfThreadMgrEventSink;
ITfCompartmentEventSink *pITfCompartmentEventSink;
ITfTextEditSink *pITfTextEditSink;
ITfLanguageProfileNotifySink *pITfLanguageProfileNotifySink;
ITfTransitoryExtensionSink *pITfTransitoryExtensionSink;
} interfaces;
} Sink;
#define SINK_ENTRY(cursor,type) (LIST_ENTRY(cursor,Sink,entry)->interfaces.p##type)
#define SINK_FOR_EACH(cursor,list,type,elem) \
for ((cursor) = (list)->next, elem = SINK_ENTRY(cursor,type); \
(cursor) != (list); \
(cursor) = (cursor)->next, elem = SINK_ENTRY(cursor,type))
HRESULT advise_sink(struct list *sink_list, REFIID riid, DWORD cookie_magic, IUnknown *unk, DWORD *cookie);
HRESULT unadvise_sink(DWORD cookie);
void free_sinks(struct list *sink_list);
#define szwSystemTIPKey L"SOFTWARE\\Microsoft\\CTF\\TIP"
#define szwSystemCTFKey L"SOFTWARE\\Microsoft\\CTF"
HRESULT __wine_register_resources(HMODULE module);
HRESULT __wine_unregister_resources(HMODULE module);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -6,56 +6,40 @@
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <msctf.h>
#include <msctf_undoc.h>
// Cicero
#include <cicbase.h>
#include <cicreg.h>
#include <cicutb.h>
class CInputContext;
#include "precomp.h"
#include "range.h"
#include "msctf_internal.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
////////////////////////////////////////////////////////////////////////////
// CRange
CRange::CRange(
_In_ ITfContext *context,
_In_ ITextStoreACP *textstore,
_In_ DWORD lockType,
_In_ TfAnchor anchorStart,
_In_ TfAnchor anchorEnd
)
: m_pContext(context)
, m_pTextStore(textstore)
, m_dwLockType(lockType)
: m_cRefs(1)
, m_context(context)
, m_anchorStart(anchorStart)
, m_anchorEnd(anchorEnd)
, m_dwCookie(MAXDWORD)
, m_cRefs(1)
{
if (context)
context->AddRef();
}
CRange::~CRange()
{
TRACE("destroying %p\n", this);
if (m_context)
m_context->Release();
}
CRange *CRange::_Clone()
{
CRange *pRange = new(cicNoThrow) CRange(m_pContext, m_pTextStore, m_dwLockType,
m_anchorStart, m_anchorEnd);
CRange *pRange = new(cicNoThrow) CRange(m_context, m_anchorStart, m_anchorEnd);
if (!pRange)
return NULL;
pRange->m_dwCookie = m_dwCookie;
return pRange;
}
@ -90,24 +74,19 @@ HRESULT CRange::TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELE
return S_OK;
}
////////////////////////////////////////////////////////////////////////////
// ** IUnknown methods **
STDMETHODIMP CRange::QueryInterface(REFIID riid, void **ppvObj)
{
if (IsEqualGUID(riid, IID_PRIV_CRANGE))
if (riid == IID_PRIV_CRANGE)
{
*ppvObj = this;
return S_OK; // No AddRef
}
if (IsEqualGUID(riid, IID_ITfRange) || IsEqualGUID(riid, IID_IUnknown))
*ppvObj = this;
else if (IsEqualGUID(riid, IID_ITfRangeACP))
if (riid == IID_IUnknown || riid == IID_ITfRange || riid == IID_ITfRangeACP)
*ppvObj = static_cast<ITfRangeACP *>(this);
else if (IsEqualGUID(riid, IID_ITfRangeAnchor))
else if (riid == IID_ITfRangeAnchor)
*ppvObj = static_cast<ITfRangeAnchor *>(this);
else if (IsEqualGUID(riid, IID_ITfSource))
else if (riid == IID_ITfSource)
*ppvObj = static_cast<ITfSource *>(this);
else
*ppvObj = NULL;
@ -118,30 +97,25 @@ STDMETHODIMP CRange::QueryInterface(REFIID riid, void **ppvObj)
return S_OK;
}
ERR("E_NOINTERFACE: %s\n", wine_dbgstr_guid(&riid));
WARN("unsupported interface: %s\n", debugstr_guid(&riid));
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CRange::AddRef()
{
TRACE("%p -> ()\n", this);
return InterlockedIncrement(&m_cRefs);
return ::InterlockedIncrement(&m_cRefs);
}
STDMETHODIMP_(ULONG) CRange::Release()
{
TRACE("%p -> ()\n", this);
if (InterlockedDecrement(&m_cRefs) == 0)
{
ULONG ret = InterlockedDecrement(&m_cRefs);
if (!ret)
delete this;
return 0;
}
return m_cRefs;
return ret;
}
////////////////////////////////////////////////////////////////////////////
// ** ITfRange methods **
STDMETHODIMP CRange::GetText(
_In_ TfEditCookie ec,
_In_ DWORD dwFlags,
@ -351,9 +325,6 @@ STDMETHODIMP CRange::GetContext(
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////////
// ** ITfRangeACP methods **
STDMETHODIMP CRange::GetExtent(_Out_ LONG *pacpAnchor, _Out_ LONG *pcch)
{
FIXME("\n");
@ -366,9 +337,6 @@ STDMETHODIMP CRange::SetExtent(_In_ LONG acpAnchor, _In_ LONG cch)
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////////
// ** ITfRangeAnchor methods **
STDMETHODIMP CRange::GetExtent(_Out_ IAnchor **ppStart, _Out_ IAnchor **ppEnd)
{
FIXME("\n");
@ -381,9 +349,6 @@ STDMETHODIMP CRange::SetExtent(_In_ IAnchor *pAnchorStart, _In_ IAnchor *pAnchor
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////////
// ** ITfSource methods **
STDMETHODIMP CRange::AdviseSink(
_In_ REFIID riid,
_In_ IUnknown *punk,
@ -404,11 +369,9 @@ STDMETHODIMP CRange::UnadviseSink(
EXTERN_C
HRESULT
Range_Constructor(ITfContext *context, ITextStoreACP *textstore,
DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut)
Range_Constructor(ITfContext *context, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut)
{
CRange *This = new(cicNoThrow) CRange(context, textstore, lockType,
(TfAnchor)anchorStart, (TfAnchor)anchorEnd);
CRange *This = new(cicNoThrow) CRange(context, (TfAnchor)anchorStart, (TfAnchor)anchorEnd);
if (!This)
return E_OUTOFMEMORY;

View file

@ -7,20 +7,9 @@ class CRange
, public ITfRangeAnchor
, public ITfSource
{
protected:
ITfContext *m_pContext;
ITextStoreACP *m_pTextStore;
DWORD m_dwLockType;
TfAnchor m_anchorStart;
TfAnchor m_anchorEnd;
DWORD m_dwCookie;
LONG m_cRefs;
public:
CRange(
_In_ ITfContext *context,
_In_ ITextStoreACP *textstore,
_In_ DWORD lockType,
_In_ TfAnchor anchorStart,
_In_ TfAnchor anchorEnd);
virtual ~CRange();
@ -129,6 +118,13 @@ public:
STDMETHODIMP UnadviseSink(_In_ DWORD dwCookie) override;
protected:
LONG m_cRefs;
ITfContext *m_context;
DWORD m_dwLockType;
TfAnchor m_anchorStart;
TfAnchor m_anchorEnd;
DWORD m_dwCookie;
CRange *_Clone();
HRESULT _IsEqualX(TfEditCookie ec, BOOL bEnd, ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual);

View file

@ -6,20 +6,7 @@
* Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <initguid.h>
#include <windef.h>
#include <winbase.h>
#include <oleauto.h>
#include <olectl.h>
#include <cguid.h>
#include <msctf.h>
#include <msctf_undoc.h>
#include <wine/list.h>
// Cicero
#include <cicbase.h>
#include "msctf_internal.h"
#include "precomp.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
@ -321,7 +308,7 @@ CThreadMgr::~CThreadMgr()
if (m_focusHook)
UnhookWindowsHookEx(m_focusHook);
TlsSetValue(tlsIndex, NULL);
TlsSetValue(g_tlsIndex, NULL);
TRACE("destroying %p\n", this);
if (m_focus)
@ -340,8 +327,8 @@ CThreadMgr::~CThreadMgr()
{
PreservedKey* key = LIST_ENTRY(cursor, PreservedKey, entry);
list_remove(cursor);
HeapFree(GetProcessHeap(), 0, key->description);
HeapFree(GetProcessHeap(), 0, key);
cicMemFree(key->description);
cicMemFree(key);
}
LIST_FOR_EACH_SAFE(cursor, cursor2, &m_CreatedDocumentMgrs)
@ -349,14 +336,14 @@ CThreadMgr::~CThreadMgr()
DocumentMgrEntry *mgr = LIST_ENTRY(cursor, DocumentMgrEntry, entry);
list_remove(cursor);
FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n");
HeapFree(GetProcessHeap(), 0, mgr);
cicMemFree(mgr);
}
LIST_FOR_EACH_SAFE(cursor, cursor2, &m_AssociatedFocusWindows)
{
AssociatedWindow *wnd = LIST_ENTRY(cursor, AssociatedWindow, entry);
list_remove(cursor);
HeapFree(GetProcessHeap(), 0, wnd);
cicMemFree(wnd);
}
m_CompartmentMgr->Release();
@ -444,7 +431,7 @@ STDMETHODIMP CThreadMgr::CreateDocumentMgr(_Out_ ITfDocumentMgr **ppdim)
if (!ppdim)
return E_INVALIDARG;
DocumentMgrEntry *mgrentry = (DocumentMgrEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(DocumentMgrEntry));
DocumentMgrEntry *mgrentry = (DocumentMgrEntry *)cicMemAlloc(sizeof(DocumentMgrEntry));
if (!mgrentry)
return E_OUTOFMEMORY;
@ -456,7 +443,7 @@ STDMETHODIMP CThreadMgr::CreateDocumentMgr(_Out_ ITfDocumentMgr **ppdim)
}
else
{
HeapFree(GetProcessHeap(), 0, mgrentry);
cicMemFree(mgrentry);
}
return hr;
@ -483,7 +470,7 @@ STDMETHODIMP CThreadMgr::GetFocus(_Out_ ITfDocumentMgr **ppdimFocus)
TRACE("->%p\n", m_focus);
if (m_focus == NULL)
if (!m_focus)
return S_FALSE;
m_focus->AddRef();
@ -540,7 +527,7 @@ LRESULT CThreadMgr::_ThreadFocusHookProc(INT nCode, WPARAM wParam, LPARAM lParam
LRESULT CALLBACK CThreadMgr::ThreadFocusHookProc(INT nCode, WPARAM wParam, LPARAM lParam)
{
CThreadMgr *This = (CThreadMgr *)TlsGetValue(tlsIndex);
CThreadMgr *This = (CThreadMgr *)TlsGetValue(g_tlsIndex);
if (!This)
{
ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n");
@ -594,7 +581,7 @@ STDMETHODIMP CThreadMgr::AssociateFocus(
}
}
wnd = (AssociatedWindow *)HeapAlloc(GetProcessHeap(), 0, sizeof(AssociatedWindow));
wnd = (AssociatedWindow *)cicMemAlloc(sizeof(AssociatedWindow));
wnd->hwnd = hwnd;
wnd->docmgr = pdimNew;
list_add_head(&m_AssociatedFocusWindows, &wnd->entry);
@ -614,7 +601,7 @@ STDMETHODIMP CThreadMgr::IsThreadFocus(_Out_ BOOL *pfThreadFocus)
return E_INVALIDARG;
HWND focus = ::GetFocus();
*pfThreadFocus = (focus == NULL);
*pfThreadFocus = !focus;
return S_OK;
}
@ -640,15 +627,15 @@ STDMETHODIMP CThreadMgr::GetGlobalCompartment(_Out_ ITfCompartmentMgr **ppCompMg
if (!ppCompMgr)
return E_INVALIDARG;
if (!globalCompartmentMgr)
if (!g_globalCompartmentMgr)
{
hr = CompartmentMgr_Constructor(NULL, IID_ITfCompartmentMgr, (IUnknown **)&globalCompartmentMgr);
hr = CompartmentMgr_Constructor(NULL, IID_ITfCompartmentMgr, (IUnknown **)&g_globalCompartmentMgr);
if (FAILED(hr))
return hr;
}
globalCompartmentMgr->AddRef();
*ppCompMgr = globalCompartmentMgr;
g_globalCompartmentMgr->AddRef();
*ppCompMgr = g_globalCompartmentMgr;
return S_OK;
}
@ -664,16 +651,16 @@ STDMETHODIMP CThreadMgr::ActivateEx(
if (flags)
FIXME("Unimplemented flags %#x\n", flags);
if (!processId)
if (!g_processId)
{
GUID guid;
CoCreateGuid(&guid);
GetClientId(guid, &processId);
GetClientId(guid, &g_processId);
}
activate_textservices(this);
++m_activationCount;
*id = processId;
*id = g_processId;
return S_OK;
}
@ -941,7 +928,7 @@ STDMETHODIMP CThreadMgr::PreserveKey(
return TF_E_ALREADY_EXISTS;
}
PreservedKey *newkey = (PreservedKey *)HeapAlloc(GetProcessHeap(), 0, sizeof(PreservedKey));
PreservedKey *newkey = (PreservedKey *)cicMemAlloc(sizeof(PreservedKey));
if (!newkey)
return E_OUTOFMEMORY;
@ -951,10 +938,10 @@ STDMETHODIMP CThreadMgr::PreserveKey(
newkey->description = NULL;
if (cchDesc)
{
newkey->description = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (cchDesc + 1) * sizeof(WCHAR));
newkey->description = (LPWSTR)cicMemAlloc((cchDesc + 1) * sizeof(WCHAR));
if (!newkey->description)
{
HeapFree(GetProcessHeap(), 0, newkey);
cicMemFree(newkey);
return E_OUTOFMEMORY;
}
CopyMemory(newkey->description, pchDesc, cchDesc * sizeof(WCHAR));
@ -988,8 +975,8 @@ STDMETHODIMP CThreadMgr::UnpreserveKey(
return CONNECT_E_NOCONNECTION;
list_remove(&key->entry);
HeapFree(GetProcessHeap(), 0, key->description);
HeapFree(GetProcessHeap(), 0, key);
cicMemFree(key->description);
cicMemFree(key);
return S_OK;
}
@ -1228,7 +1215,7 @@ HRESULT CThreadMgr::CreateInstance(IUnknown *pUnkOuter, CThreadMgr **ppOut)
return CLASS_E_NOAGGREGATION;
/* Only 1 ThreadMgr is created per thread */
CThreadMgr *This = (CThreadMgr *)TlsGetValue(tlsIndex);
CThreadMgr *This = (CThreadMgr *)TlsGetValue(g_tlsIndex);
if (This)
{
This->AddRef();
@ -1240,7 +1227,7 @@ HRESULT CThreadMgr::CreateInstance(IUnknown *pUnkOuter, CThreadMgr **ppOut)
if (!This)
return E_OUTOFMEMORY;
TlsSetValue(tlsIndex, This);
TlsSetValue(g_tlsIndex, This);
ITfCompartmentMgr *pCompMgr = NULL;
CompartmentMgr_Constructor(static_cast<ITfThreadMgrEx *>(This), IID_IUnknown, (IUnknown **)&pCompMgr);
@ -1260,7 +1247,7 @@ void CThreadMgr::OnDocumentMgrDestruction(ITfDocumentMgr *mgr)
if (mgrentry->docmgr == mgr)
{
list_remove(cursor);
HeapFree(GetProcessHeap(), 0, mgrentry);
cicMemFree(mgrentry);
return;
}
}
@ -1306,7 +1293,7 @@ STDMETHODIMP_(ULONG) CEnumTfDocumentMgr::AddRef()
STDMETHODIMP_(ULONG) CEnumTfDocumentMgr::Release()
{
ULONG ret = InterlockedDecrement(&m_cRefs);
if (ret == 0)
if (!ret)
delete this;
return ret;
}

View file

@ -1,31 +1,17 @@
/*
* PROJECT: ReactOS msctf.dll
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PROJECT: ReactOS CTF
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
* PURPOSE: Text Framework Services
* COPYRIGHT: Copyright 2023-2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include <stdlib.h>
#include "precomp.h"
#define WIN32_LEAN_AND_MEAN
#define WIN32_NO_STATUS
#define COBJMACROS
#define INITGUID
#define _EXTYPES_H
#include <windows.h>
#include <sddl.h>
#include <imm.h>
#include <cguid.h>
#include <tchar.h>
#include <msctf.h>
#include <msctf_undoc.h>
#include <ctffunc.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <cicarray.h>
#include <cicreg.h>
#include <cicmutex.h>
#include <cicfmap.h>
@ -284,7 +270,7 @@ EXTERN_C HANDLE WINAPI
TF_CreateCicLoadMutex(_Out_ LPBOOL pfWinLogon)
{
FIXME("(%p)\n", pfWinLogon);
if (pfWinLogon == NULL)
if (!pfWinLogon)
return NULL;
*pfWinLogon = FALSE;
return NULL;
@ -489,7 +475,7 @@ TF_RegisterLangBarAddIn(
{
TRACE("(%s, %s, 0x%lX)\n", debugstr_guid(&rguid), debugstr_w(pszFilePath), dwFlags);
if (!pszFilePath || IsEqualGUID(rguid, GUID_NULL))
if (!pszFilePath || rguid == GUID_NULL)
{
ERR("E_INVALIDARG\n");
return E_INVALIDARG;
@ -525,7 +511,7 @@ TF_UnregisterLangBarAddIn(
{
TRACE("(%s, 0x%lX)\n", debugstr_guid(&rguid), dwFlags);
if (IsEqualGUID(rguid, GUID_NULL))
if (rguid == GUID_NULL)
{
ERR("E_INVALIDARG\n");
return E_INVALIDARG;

View file

@ -15,7 +15,7 @@ wine-patches@winehq.com and ros-dev@reactos.org
The following build tools are shared with Wine.
base/ctf/msctf # Synced to WineStaging-4.18
base/ctf/msctf # Forked at Wine-10.12
sdk/tools/unicode # Synced to WineStaging-4.18
sdk/tools/widl # Synced to WineStaging-4.0