[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
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); 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 // FIXME
typedef enum _PROCESSINFOCLASS typedef enum _PROCESSINFOCLASS
{ {

View File

@@ -17,19 +17,26 @@ static inline LPVOID cicMemAllocClear(SIZE_T size)
return LocalAlloc(LMEM_ZEROINIT, 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) static inline void cicMemFree(LPVOID ptr)
{ {
if (ptr) if (ptr)
LocalFree(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) static inline bool cicIsNullPtr(LPCVOID ptr)
{ {
return !ptr; return !ptr;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,42 +1,14 @@
/* /*
* MSCTF Server DLL * PROJECT: ReactOS CTF
* * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
* Copyright 2008 Aric Stewart, CodeWeavers * PURPOSE: MSCTF Server DLL
* * COPYRIGHT: Copyright 2008 Aric Stewart, CodeWeavers
* This library is free software; you can redistribute it and/or * Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
* 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
*/ */
#include <stdarg.h> #include "precomp.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 <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf); WINE_DEFAULT_DEBUG_CHANNEL(msctf);
static HINSTANCE MSCTF_hinstance; static HINSTANCE MSCTF_hinstance;
@@ -69,17 +41,14 @@ static UINT array_size;
static struct list AtsList = LIST_INIT(AtsList); static struct list AtsList = LIST_INIT(AtsList);
static UINT activated = 0; static UINT activated = 0;
DWORD tlsIndex = 0; DWORD g_tlsIndex = 0;
TfClientId processId = 0; TfClientId g_processId = 0;
ITfCompartmentMgr *globalCompartmentMgr = NULL; ITfCompartmentMgr *g_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};
typedef HRESULT (*LPFNCONSTRUCTOR)(IUnknown *pUnkOuter, IUnknown **ppvOut); typedef HRESULT (*LPFNCONSTRUCTOR)(IUnknown *pUnkOuter, IUnknown **ppvOut);
static const struct { static const struct {
REFCLSID clsid; const CLSID *clsid;
LPFNCONSTRUCTOR ctor; LPFNCONSTRUCTOR ctor;
} ClassesTable[] = { } ClassesTable[] = {
{&CLSID_TF_ThreadMgr, ThreadMgr_Constructor}, {&CLSID_TF_ThreadMgr, ThreadMgr_Constructor},
@@ -90,95 +59,94 @@ static const struct {
{NULL, NULL} {NULL, NULL}
}; };
typedef struct tagClassFactory class CClassFactory
: public IClassFactory
{ {
IClassFactory IClassFactory_iface; public:
LONG ref; CClassFactory(LPFNCONSTRUCTOR ctor);
LPFNCONSTRUCTOR ctor; virtual ~CClassFactory();
} ClassFactory;
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); TRACE("Destroying class factory %p\n", this);
HeapFree(GetProcessHeap(),0,This);
} }
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppvOut) STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObj)
{ {
*ppvOut = NULL; *ppvObj = NULL;
if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown)) { if (riid == IID_IClassFactory || riid == IID_IUnknown)
IClassFactory_AddRef(iface); {
*ppvOut = iface; AddRef();
*ppvObj = static_cast<IClassFactory *>(this);
return S_OK; return S_OK;
} }
WARN("Unknown interface %s\n", debugstr_guid(riid)); WARN("Unknown interface %s\n", debugstr_guid(&riid));
return E_NOINTERFACE; return E_NOINTERFACE;
} }
static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) STDMETHODIMP_(ULONG) CClassFactory::AddRef()
{ {
ClassFactory *This = impl_from_IClassFactory(iface); return ::InterlockedIncrement(&m_cRefs);
return InterlockedIncrement(&This->ref);
} }
static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) STDMETHODIMP_(ULONG) CClassFactory::Release()
{ {
ClassFactory *This = impl_from_IClassFactory(iface); ULONG ret = InterlockedDecrement(&m_cRefs);
ULONG ret = InterlockedDecrement(&This->ref); if (!ret)
delete this;
if (ret == 0)
ClassFactory_Destructor(This);
return ret; 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); TRACE("(%p, %p, %s, %p)\n", this, pUnkOuter, debugstr_guid(&riid), ppvObject);
HRESULT ret;
IUnknown *obj;
TRACE("(%p, %p, %s, %p)\n", iface, punkOuter, debugstr_guid(iid), ppvOut); IUnknown *obj;
ret = This->ctor(punkOuter, &obj); HRESULT ret = m_ctor(pUnkOuter, &obj);
if (FAILED(ret)) if (FAILED(ret))
return ret; return ret;
ret = IUnknown_QueryInterface(obj, iid, ppvOut); ret = obj->QueryInterface(riid, ppvObject);
IUnknown_Release(obj); obj->Release();
return ret; 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; 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) static HRESULT ClassFactory_Constructor(LPFNCONSTRUCTOR ctor, LPVOID *ppvOut)
{ {
ClassFactory *This = HeapAlloc(GetProcessHeap(),0,sizeof(ClassFactory)); CClassFactory *This = new(cicNoThrow) CClassFactory(ctor);
This->IClassFactory_iface.lpVtbl = &ClassFactoryVtbl; *ppvOut = static_cast<IClassFactory *>(This);
This->ref = 1;
This->ctor = ctor;
*ppvOut = &This->IClassFactory_iface;
TRACE("Created class factory %p\n", This); TRACE("Created class factory %p\n", This);
return S_OK; return S_OK;
} }
@@ -186,6 +154,7 @@ static HRESULT ClassFactory_Constructor(LPFNCONSTRUCTOR ctor, LPVOID *ppvOut)
/************************************************************************* /*************************************************************************
* DWORD Cookie Management * DWORD Cookie Management
*/ */
EXTERN_C
DWORD generate_Cookie(DWORD magic, LPVOID data) DWORD generate_Cookie(DWORD magic, LPVOID data)
{ {
UINT i; UINT i;
@@ -198,7 +167,7 @@ DWORD generate_Cookie(DWORD magic, LPVOID data)
{ {
if (!array_size) if (!array_size)
{ {
cookies = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CookieInternal) * 10); cookies = (CookieInternal *)cicMemAllocClear(10 * sizeof(CookieInternal));
if (!cookies) if (!cookies)
{ {
ERR("Out of memory, Unable to alloc cookies array\n"); ERR("Out of memory, Unable to alloc cookies array\n");
@@ -208,8 +177,9 @@ DWORD generate_Cookie(DWORD magic, LPVOID data)
} }
else else
{ {
CookieInternal *new_cookies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cookies, ERR("cookies: %p, array_size: %d\n", cookies, array_size);
sizeof(CookieInternal) * (array_size * 2)); CookieInternal *new_cookies = (CookieInternal *)
cicMemReCalloc(cookies, array_size * 2, sizeof(CookieInternal));
if (!new_cookies) if (!new_cookies)
{ {
ERR("Out of memory, Unable to realloc cookies array\n"); 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; return cookies[i].id;
} }
EXTERN_C
DWORD get_Cookie_magic(DWORD id) DWORD get_Cookie_magic(DWORD id)
{ {
UINT index = id - 1; UINT index = id - 1;
@@ -243,6 +214,7 @@ DWORD get_Cookie_magic(DWORD id)
return cookies[index].magic; return cookies[index].magic;
} }
EXTERN_C
LPVOID get_Cookie_data(DWORD id) LPVOID get_Cookie_data(DWORD id)
{ {
UINT index = id - 1; UINT index = id - 1;
@@ -256,6 +228,7 @@ LPVOID get_Cookie_data(DWORD id)
return cookies[index].data; return cookies[index].data;
} }
EXTERN_C
LPVOID remove_Cookie(DWORD id) LPVOID remove_Cookie(DWORD id)
{ {
UINT index = id - 1; UINT index = id - 1;
@@ -270,6 +243,7 @@ LPVOID remove_Cookie(DWORD id)
return cookies[index].data; return cookies[index].data;
} }
EXTERN_C
DWORD enumerate_Cookie(DWORD magic, DWORD *index) DWORD enumerate_Cookie(DWORD magic, DWORD *index)
{ {
unsigned int i; unsigned int i;
@@ -282,17 +256,17 @@ DWORD enumerate_Cookie(DWORD magic, DWORD *index)
return 0x0; return 0x0;
} }
EXTERN_C
HRESULT advise_sink(struct list *sink_list, REFIID riid, DWORD cookie_magic, IUnknown *unk, DWORD *cookie) HRESULT advise_sink(struct list *sink_list, REFIID riid, DWORD cookie_magic, IUnknown *unk, DWORD *cookie)
{ {
Sink *sink; Sink *sink = (Sink *)cicMemAlloc(sizeof(*sink));
sink = HeapAlloc(GetProcessHeap(), 0, sizeof(*sink));
if (!sink) if (!sink)
return E_OUTOFMEMORY; 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; 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) static void free_sink(Sink *sink)
{ {
list_remove(&sink->entry); list_remove(&sink->entry);
IUnknown_Release(sink->interfaces.pIUnknown); sink->interfaces.pIUnknown->Release();
HeapFree(GetProcessHeap(), 0, sink); cicMemFree(sink);
} }
EXTERN_C
HRESULT unadvise_sink(DWORD cookie) HRESULT unadvise_sink(DWORD cookie)
{ {
Sink *sink; Sink *sink = (Sink *)remove_Cookie(cookie);
sink = remove_Cookie(cookie);
if (!sink) if (!sink)
return CONNECT_E_NOCONNECTION; return CONNECT_E_NOCONNECTION;
@@ -321,6 +294,7 @@ HRESULT unadvise_sink(DWORD cookie)
return S_OK; return S_OK;
} }
EXTERN_C
void free_sinks(struct list *sink_list) void free_sinks(struct list *sink_list)
{ {
while(!list_empty(sink_list)) while(!list_empty(sink_list))
@@ -341,20 +315,20 @@ static HRESULT activate_given_ts(ActivatedTextService *actsvr, ITfThreadMgrEx *t
if (actsvr->pITfTextInputProcessor) if (actsvr->pITfTextInputProcessor)
return S_OK; return S_OK;
hr = CoCreateInstance (&actsvr->LanguageProfile.clsid, NULL, CLSCTX_INPROC_SERVER, hr = CoCreateInstance(actsvr->LanguageProfile.clsid, NULL, CLSCTX_INPROC_SERVER,
&IID_ITfTextInputProcessor, (void**)&actsvr->pITfTextInputProcessor); IID_ITfTextInputProcessor, (void **)&actsvr->pITfTextInputProcessor);
if (FAILED(hr)) return hr; 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)) if (FAILED(hr))
{ {
ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor); actsvr->pITfTextInputProcessor->Release();
actsvr->pITfTextInputProcessor = NULL; actsvr->pITfTextInputProcessor = NULL;
return hr; return hr;
} }
actsvr->pITfThreadMgrEx = tm; actsvr->pITfThreadMgrEx = tm;
ITfThreadMgrEx_AddRef(tm); tm->AddRef();
return hr; return hr;
} }
@@ -364,9 +338,9 @@ static HRESULT deactivate_given_ts(ActivatedTextService *actsvr)
if (actsvr->pITfTextInputProcessor) if (actsvr->pITfTextInputProcessor)
{ {
hr = ITfTextInputProcessor_Deactivate(actsvr->pITfTextInputProcessor); hr = actsvr->pITfTextInputProcessor->Deactivate();
ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor); actsvr->pITfTextInputProcessor->Release();
ITfThreadMgrEx_Release(actsvr->pITfThreadMgrEx); actsvr->pITfThreadMgrEx->Release();
actsvr->pITfTextInputProcessor = NULL; actsvr->pITfTextInputProcessor = NULL;
actsvr->pITfThreadMgrEx = 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) 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); deactivate_given_ts(ats->ats);
list_remove(&ats->entry); list_remove(&ats->entry);
HeapFree(GetProcessHeap(),0,ats->ats); cicMemFree(ats->ats);
HeapFree(GetProcessHeap(),0,ats); cicMemFree(ats);
/* we are guaranteeing there is only 1 */ /* we are guaranteeing there is only 1 */
break; break;
} }
} }
} }
EXTERN_C
HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp) HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
{ {
ActivatedTextService *actsvr; ActivatedTextService *actsvr;
ITfCategoryMgr *catmgr; ITfCategoryMgr *catmgr;
AtsEntry *entry; AtsEntry *entry;
ITfThreadMgrEx *tm = TlsGetValue(tlsIndex); ITfThreadMgrEx *tm = (ITfThreadMgrEx *)TlsGetValue(g_tlsIndex);
ITfClientId *clientid; ITfClientId *clientid;
if (!tm) return E_UNEXPECTED; if (!tm)
return E_UNEXPECTED;
actsvr = HeapAlloc(GetProcessHeap(),0,sizeof(ActivatedTextService)); actsvr = (ActivatedTextService *)cicMemAlloc(sizeof(ActivatedTextService));
if (!actsvr) return E_OUTOFMEMORY; if (!actsvr)
return E_OUTOFMEMORY;
ITfThreadMgrEx_QueryInterface(tm, &IID_ITfClientId, (void **)&clientid); tm->QueryInterface(IID_ITfClientId, (void **)&clientid);
ITfClientId_GetClientId(clientid, &lp->clsid, &actsvr->tid); clientid->GetClientId(lp->clsid, &actsvr->tid);
ITfClientId_Release(clientid); clientid->Release();
if (!actsvr->tid) if (!actsvr->tid)
{ {
HeapFree(GetProcessHeap(),0,actsvr); cicMemFree(actsvr);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
@@ -420,15 +397,12 @@ HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
actsvr->pITfKeyEventSink = NULL; actsvr->pITfKeyEventSink = NULL;
/* get TIP category */ /* 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}; static const GUID *list[3] = {&GUID_TFCAT_TIP_SPEECH, &GUID_TFCAT_TIP_KEYBOARD, &GUID_TFCAT_TIP_HANDWRITING};
ITfCategoryMgr_FindClosestCategory(catmgr, catmgr->FindClosestCategory(actsvr->LanguageProfile.clsid, &actsvr->LanguageProfile.catid, list, 3);
&actsvr->LanguageProfile.clsid, &actsvr->LanguageProfile.catid, catmgr->Release();
list, 3);
ITfCategoryMgr_Release(catmgr);
} }
else else
{ {
@@ -436,17 +410,16 @@ HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
actsvr->LanguageProfile.catid = GUID_NULL; actsvr->LanguageProfile.catid = GUID_NULL;
} }
if (!IsEqualGUID(&actsvr->LanguageProfile.catid,&GUID_NULL)) if (actsvr->LanguageProfile.catid != GUID_NULL)
deactivate_remove_conflicting_ts(&actsvr->LanguageProfile.catid); deactivate_remove_conflicting_ts(actsvr->LanguageProfile.catid);
if (activated > 0) if (activated > 0)
activate_given_ts(actsvr, tm); activate_given_ts(actsvr, tm);
entry = HeapAlloc(GetProcessHeap(),0,sizeof(AtsEntry)); entry = (AtsEntry *)cicMemAlloc(sizeof(AtsEntry));
if (!entry) if (!entry)
{ {
HeapFree(GetProcessHeap(),0,actsvr); cicMemFree(actsvr);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
@@ -456,13 +429,14 @@ HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
return S_OK; return S_OK;
} }
EXTERN_C
BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *profile) BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *profile)
{ {
AtsEntry *ats; AtsEntry *ats;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
{ {
if (IsEqualCLSID(rclsid,&ats->ats->LanguageProfile.clsid)) if (rclsid == ats->ats->LanguageProfile.clsid)
{ {
if (profile) if (profile)
*profile = ats->ats->LanguageProfile; *profile = ats->ats->LanguageProfile;
@@ -472,6 +446,7 @@ BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *profile)
return FALSE; return FALSE;
} }
EXTERN_C
HRESULT activate_textservices(ITfThreadMgrEx *tm) HRESULT activate_textservices(ITfThreadMgrEx *tm)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
@@ -490,6 +465,7 @@ HRESULT activate_textservices(ITfThreadMgrEx *tm)
return hr; return hr;
} }
EXTERN_C
HRESULT deactivate_textservices(void) HRESULT deactivate_textservices(void)
{ {
AtsEntry *ats; AtsEntry *ats;
@@ -498,52 +474,62 @@ HRESULT deactivate_textservices(void)
activated --; activated --;
if (activated == 0) if (activated == 0)
{
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
deactivate_given_ts(ats->ats); deactivate_given_ts(ats->ats);
}
return S_OK; return S_OK;
} }
EXTERN_C
CLSID get_textservice_clsid(TfClientId tid) CLSID get_textservice_clsid(TfClientId tid)
{ {
AtsEntry *ats; AtsEntry *ats;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
{
if (ats->ats->tid == tid) if (ats->ats->tid == tid)
return ats->ats->LanguageProfile.clsid; return ats->ats->LanguageProfile.clsid;
}
return GUID_NULL; return GUID_NULL;
} }
EXTERN_C
HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown **sink) HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown **sink)
{ {
AtsEntry *ats; AtsEntry *ats;
if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink)) if (iid != IID_ITfKeyEventSink)
return E_NOINTERFACE; return E_NOINTERFACE;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
{
if (ats->ats->tid == tid) if (ats->ats->tid == tid)
{ {
*sink = (IUnknown*)ats->ats->pITfKeyEventSink; *sink = (IUnknown*)ats->ats->pITfKeyEventSink;
return S_OK; return S_OK;
} }
}
return E_FAIL; return E_FAIL;
} }
EXTERN_C
HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink) HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink)
{ {
AtsEntry *ats; AtsEntry *ats;
if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink)) if (iid != IID_ITfKeyEventSink)
return E_NOINTERFACE; return E_NOINTERFACE;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
{
if (ats->ats->tid == tid) if (ats->ats->tid == tid)
{ {
ats->ats->pITfKeyEventSink = (ITfKeyEventSink*)sink; ats->ats->pITfKeyEventSink = (ITfKeyEventSink*)sink;
return S_OK; return S_OK;
} }
}
return E_FAIL; 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); TRACE("%p 0x%x %p\n", hinst, fdwReason, fImpLoad);
switch (fdwReason) switch (fdwReason)
{ {
#ifndef __REACTOS__
case DLL_WINE_PREATTACH:
return FALSE; /* prefer native version */
#endif
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
MSCTF_hinstance = hinst; MSCTF_hinstance = hinst;
tlsIndex = TlsAlloc(); g_tlsIndex = TlsAlloc();
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
if (fImpLoad) break; if (fImpLoad) break;
TlsFree(tlsIndex); TlsFree(g_tlsIndex);
break; break;
} }
return TRUE; return TRUE;
@@ -588,14 +570,15 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID *ppvOut)
int i; int i;
*ppvOut = NULL; *ppvOut = NULL;
if (!IsEqualIID(iid, &IID_IUnknown) && !IsEqualIID(iid, &IID_IClassFactory)) if (iid != IID_IUnknown && iid != IID_IClassFactory)
return E_NOINTERFACE; return E_NOINTERFACE;
for (i = 0; ClassesTable[i].clsid != NULL; i++) for (i = 0; ClassesTable[i].clsid; i++)
if (IsEqualCLSID(ClassesTable[i].clsid, clsid)) { {
if (*ClassesTable[i].clsid == clsid)
return ClassFactory_Constructor(ClassesTable[i].ctor, ppvOut); 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; return CLASS_E_CLASSNOTAVAILABLE;
} }
@@ -621,7 +604,7 @@ HRESULT WINAPI DllUnregisterServer(void)
HRESULT WINAPI TF_CreateThreadMgr(ITfThreadMgr **pptim) HRESULT WINAPI TF_CreateThreadMgr(ITfThreadMgr **pptim)
{ {
TRACE("\n"); 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) HRESULT WINAPI TF_GetThreadMgr(ITfThreadMgr **pptim)
{ {
TRACE("\n"); TRACE("\n");
*pptim = TlsGetValue(tlsIndex); *pptim = (ITfThreadMgr *)TlsGetValue(g_tlsIndex);
if (*pptim) if (*pptim)
ITfThreadMgr_AddRef(*pptim); (*pptim)->AddRef();
return S_OK; return S_OK;
} }
@@ -643,7 +626,7 @@ HRESULT WINAPI TF_GetThreadMgr(ITfThreadMgr **pptim)
*/ */
HRESULT WINAPI SetInputScope(HWND hwnd, InputScope inputscope) HRESULT WINAPI SetInputScope(HWND hwnd, InputScope inputscope)
{ {
FIXME("STUB: %p %i\n",hwnd,inputscope); FIXME("STUB: %p %i\n", hwnd, inputscope);
return S_OK; return S_OK;
} }
@@ -655,11 +638,11 @@ HRESULT WINAPI SetInputScopes(HWND hwnd, const InputScope *pInputScopes,
UINT cPhrases, WCHAR *pszRegExp, WCHAR *pszSRGS) UINT cPhrases, WCHAR *pszRegExp, WCHAR *pszSRGS)
{ {
UINT i; 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++) 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++) 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; return S_OK;
} }
@@ -670,7 +653,7 @@ HRESULT WINAPI SetInputScopes(HWND hwnd, const InputScope *pInputScopes,
HRESULT WINAPI TF_CreateInputProcessorProfiles( HRESULT WINAPI TF_CreateInputProcessorProfiles(
ITfInputProcessorProfiles **ppipr) 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) HRESULT WINAPI TF_CreateLangBarMgr(ITfLangBarMgr **pppbm)
{ {
TRACE("\n"); TRACE("\n");
return LangBarMgr_Constructor(NULL,(IUnknown**)pppbm); return LangBarMgr_Constructor(NULL, (IUnknown**)pppbm);
} }
/***********************************************************************
* TF_CreateLangBarItemMgr (MSCTF.@)
*/
HRESULT WINAPI TF_CreateLangBarItemMgr(ITfLangBarItemMgr **pplbim) HRESULT WINAPI TF_CreateLangBarItemMgr(ITfLangBarItemMgr **pplbim)
{ {
FIXME("stub %p\n", pplbim); FIXME("stub %p\n", pplbim);
@@ -698,14 +684,3 @@ HRESULT WINAPI TF_CreateLangBarItemMgr(ITfLangBarItemMgr **pplbim)
return E_NOTIMPL; 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 #pragma once
#define _MSCTF_PRECOMP_H
#include <stdarg.h>
#include <wchar.h>
#define WIN32_NO_STATUS
#define _INC_WINDOWS
#define COM_NO_WINDOWS_H
#define COBJMACROS
#include <initguid.h>
#include <windef.h> #include <windef.h>
#include <winbase.h> #include <winbase.h>
#include <winreg.h> #include <oleauto.h>
#include <objbase.h>
#include <olectl.h> #include <olectl.h>
#include <cguid.h>
#include <msctf.h> #include <msctf.h>
#include <shlwapi.h> #include <msctf_undoc.h>
#include <tchar.h>
#include <strsafe.h>
#include <wine/list.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> * Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/ */
#include <initguid.h> #include "precomp.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 "range.h" #include "range.h"
#include "msctf_internal.h"
#include <wine/debug.h> #include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf); WINE_DEFAULT_DEBUG_CHANNEL(msctf);
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// CRange
CRange::CRange( CRange::CRange(
_In_ ITfContext *context, _In_ ITfContext *context,
_In_ ITextStoreACP *textstore,
_In_ DWORD lockType,
_In_ TfAnchor anchorStart, _In_ TfAnchor anchorStart,
_In_ TfAnchor anchorEnd _In_ TfAnchor anchorEnd
) )
: m_pContext(context) : m_cRefs(1)
, m_pTextStore(textstore) , m_context(context)
, m_dwLockType(lockType)
, m_anchorStart(anchorStart) , m_anchorStart(anchorStart)
, m_anchorEnd(anchorEnd) , m_anchorEnd(anchorEnd)
, m_dwCookie(MAXDWORD)
, m_cRefs(1)
{ {
if (context)
context->AddRef();
} }
CRange::~CRange() CRange::~CRange()
{ {
TRACE("destroying %p\n", this);
if (m_context)
m_context->Release();
} }
CRange *CRange::_Clone() CRange *CRange::_Clone()
{ {
CRange *pRange = new(cicNoThrow) CRange(m_pContext, m_pTextStore, m_dwLockType, CRange *pRange = new(cicNoThrow) CRange(m_context, m_anchorStart, m_anchorEnd);
m_anchorStart, m_anchorEnd);
if (!pRange) if (!pRange)
return NULL; return NULL;
pRange->m_dwCookie = m_dwCookie;
return pRange; return pRange;
} }
@@ -90,24 +74,19 @@ HRESULT CRange::TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELE
return S_OK; return S_OK;
} }
////////////////////////////////////////////////////////////////////////////
// ** IUnknown methods **
STDMETHODIMP CRange::QueryInterface(REFIID riid, void **ppvObj) STDMETHODIMP CRange::QueryInterface(REFIID riid, void **ppvObj)
{ {
if (IsEqualGUID(riid, IID_PRIV_CRANGE)) if (riid == IID_PRIV_CRANGE)
{ {
*ppvObj = this; *ppvObj = this;
return S_OK; // No AddRef return S_OK; // No AddRef
} }
if (IsEqualGUID(riid, IID_ITfRange) || IsEqualGUID(riid, IID_IUnknown)) if (riid == IID_IUnknown || riid == IID_ITfRange || riid == IID_ITfRangeACP)
*ppvObj = this;
else if (IsEqualGUID(riid, IID_ITfRangeACP))
*ppvObj = static_cast<ITfRangeACP *>(this); *ppvObj = static_cast<ITfRangeACP *>(this);
else if (IsEqualGUID(riid, IID_ITfRangeAnchor)) else if (riid == IID_ITfRangeAnchor)
*ppvObj = static_cast<ITfRangeAnchor *>(this); *ppvObj = static_cast<ITfRangeAnchor *>(this);
else if (IsEqualGUID(riid, IID_ITfSource)) else if (riid == IID_ITfSource)
*ppvObj = static_cast<ITfSource *>(this); *ppvObj = static_cast<ITfSource *>(this);
else else
*ppvObj = NULL; *ppvObj = NULL;
@@ -118,30 +97,25 @@ STDMETHODIMP CRange::QueryInterface(REFIID riid, void **ppvObj)
return S_OK; return S_OK;
} }
ERR("E_NOINTERFACE: %s\n", wine_dbgstr_guid(&riid)); WARN("unsupported interface: %s\n", debugstr_guid(&riid));
return E_NOINTERFACE; return E_NOINTERFACE;
} }
STDMETHODIMP_(ULONG) CRange::AddRef() STDMETHODIMP_(ULONG) CRange::AddRef()
{ {
TRACE("%p -> ()\n", this); TRACE("%p -> ()\n", this);
return InterlockedIncrement(&m_cRefs); return ::InterlockedIncrement(&m_cRefs);
} }
STDMETHODIMP_(ULONG) CRange::Release() STDMETHODIMP_(ULONG) CRange::Release()
{ {
TRACE("%p -> ()\n", this); TRACE("%p -> ()\n", this);
if (InterlockedDecrement(&m_cRefs) == 0) ULONG ret = InterlockedDecrement(&m_cRefs);
{ if (!ret)
delete this; delete this;
return 0; return ret;
}
return m_cRefs;
} }
////////////////////////////////////////////////////////////////////////////
// ** ITfRange methods **
STDMETHODIMP CRange::GetText( STDMETHODIMP CRange::GetText(
_In_ TfEditCookie ec, _In_ TfEditCookie ec,
_In_ DWORD dwFlags, _In_ DWORD dwFlags,
@@ -351,9 +325,6 @@ STDMETHODIMP CRange::GetContext(
return E_NOTIMPL; return E_NOTIMPL;
} }
////////////////////////////////////////////////////////////////////////////
// ** ITfRangeACP methods **
STDMETHODIMP CRange::GetExtent(_Out_ LONG *pacpAnchor, _Out_ LONG *pcch) STDMETHODIMP CRange::GetExtent(_Out_ LONG *pacpAnchor, _Out_ LONG *pcch)
{ {
FIXME("\n"); FIXME("\n");
@@ -366,9 +337,6 @@ STDMETHODIMP CRange::SetExtent(_In_ LONG acpAnchor, _In_ LONG cch)
return E_NOTIMPL; return E_NOTIMPL;
} }
////////////////////////////////////////////////////////////////////////////
// ** ITfRangeAnchor methods **
STDMETHODIMP CRange::GetExtent(_Out_ IAnchor **ppStart, _Out_ IAnchor **ppEnd) STDMETHODIMP CRange::GetExtent(_Out_ IAnchor **ppStart, _Out_ IAnchor **ppEnd)
{ {
FIXME("\n"); FIXME("\n");
@@ -381,9 +349,6 @@ STDMETHODIMP CRange::SetExtent(_In_ IAnchor *pAnchorStart, _In_ IAnchor *pAnchor
return E_NOTIMPL; return E_NOTIMPL;
} }
////////////////////////////////////////////////////////////////////////////
// ** ITfSource methods **
STDMETHODIMP CRange::AdviseSink( STDMETHODIMP CRange::AdviseSink(
_In_ REFIID riid, _In_ REFIID riid,
_In_ IUnknown *punk, _In_ IUnknown *punk,
@@ -404,11 +369,9 @@ STDMETHODIMP CRange::UnadviseSink(
EXTERN_C EXTERN_C
HRESULT HRESULT
Range_Constructor(ITfContext *context, ITextStoreACP *textstore, Range_Constructor(ITfContext *context, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut)
DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut)
{ {
CRange *This = new(cicNoThrow) CRange(context, textstore, lockType, CRange *This = new(cicNoThrow) CRange(context, (TfAnchor)anchorStart, (TfAnchor)anchorEnd);
(TfAnchor)anchorStart, (TfAnchor)anchorEnd);
if (!This) if (!This)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;

View File

@@ -7,20 +7,9 @@ class CRange
, public ITfRangeAnchor , public ITfRangeAnchor
, public ITfSource , 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: public:
CRange( CRange(
_In_ ITfContext *context, _In_ ITfContext *context,
_In_ ITextStoreACP *textstore,
_In_ DWORD lockType,
_In_ TfAnchor anchorStart, _In_ TfAnchor anchorStart,
_In_ TfAnchor anchorEnd); _In_ TfAnchor anchorEnd);
virtual ~CRange(); virtual ~CRange();
@@ -129,6 +118,13 @@ public:
STDMETHODIMP UnadviseSink(_In_ DWORD dwCookie) override; STDMETHODIMP UnadviseSink(_In_ DWORD dwCookie) override;
protected: protected:
LONG m_cRefs;
ITfContext *m_context;
DWORD m_dwLockType;
TfAnchor m_anchorStart;
TfAnchor m_anchorEnd;
DWORD m_dwCookie;
CRange *_Clone(); CRange *_Clone();
HRESULT _IsEqualX(TfEditCookie ec, BOOL bEnd, ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual); 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> * Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/ */
#include <initguid.h> #include "precomp.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 <wine/debug.h> #include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(msctf); WINE_DEFAULT_DEBUG_CHANNEL(msctf);
@@ -321,7 +308,7 @@ CThreadMgr::~CThreadMgr()
if (m_focusHook) if (m_focusHook)
UnhookWindowsHookEx(m_focusHook); UnhookWindowsHookEx(m_focusHook);
TlsSetValue(tlsIndex, NULL); TlsSetValue(g_tlsIndex, NULL);
TRACE("destroying %p\n", this); TRACE("destroying %p\n", this);
if (m_focus) if (m_focus)
@@ -340,8 +327,8 @@ CThreadMgr::~CThreadMgr()
{ {
PreservedKey* key = LIST_ENTRY(cursor, PreservedKey, entry); PreservedKey* key = LIST_ENTRY(cursor, PreservedKey, entry);
list_remove(cursor); list_remove(cursor);
HeapFree(GetProcessHeap(), 0, key->description); cicMemFree(key->description);
HeapFree(GetProcessHeap(), 0, key); cicMemFree(key);
} }
LIST_FOR_EACH_SAFE(cursor, cursor2, &m_CreatedDocumentMgrs) LIST_FOR_EACH_SAFE(cursor, cursor2, &m_CreatedDocumentMgrs)
@@ -349,14 +336,14 @@ CThreadMgr::~CThreadMgr()
DocumentMgrEntry *mgr = LIST_ENTRY(cursor, DocumentMgrEntry, entry); DocumentMgrEntry *mgr = LIST_ENTRY(cursor, DocumentMgrEntry, entry);
list_remove(cursor); list_remove(cursor);
FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n"); 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) LIST_FOR_EACH_SAFE(cursor, cursor2, &m_AssociatedFocusWindows)
{ {
AssociatedWindow *wnd = LIST_ENTRY(cursor, AssociatedWindow, entry); AssociatedWindow *wnd = LIST_ENTRY(cursor, AssociatedWindow, entry);
list_remove(cursor); list_remove(cursor);
HeapFree(GetProcessHeap(), 0, wnd); cicMemFree(wnd);
} }
m_CompartmentMgr->Release(); m_CompartmentMgr->Release();
@@ -444,7 +431,7 @@ STDMETHODIMP CThreadMgr::CreateDocumentMgr(_Out_ ITfDocumentMgr **ppdim)
if (!ppdim) if (!ppdim)
return E_INVALIDARG; return E_INVALIDARG;
DocumentMgrEntry *mgrentry = (DocumentMgrEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(DocumentMgrEntry)); DocumentMgrEntry *mgrentry = (DocumentMgrEntry *)cicMemAlloc(sizeof(DocumentMgrEntry));
if (!mgrentry) if (!mgrentry)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@@ -456,7 +443,7 @@ STDMETHODIMP CThreadMgr::CreateDocumentMgr(_Out_ ITfDocumentMgr **ppdim)
} }
else else
{ {
HeapFree(GetProcessHeap(), 0, mgrentry); cicMemFree(mgrentry);
} }
return hr; return hr;
@@ -483,7 +470,7 @@ STDMETHODIMP CThreadMgr::GetFocus(_Out_ ITfDocumentMgr **ppdimFocus)
TRACE("->%p\n", m_focus); TRACE("->%p\n", m_focus);
if (m_focus == NULL) if (!m_focus)
return S_FALSE; return S_FALSE;
m_focus->AddRef(); 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) LRESULT CALLBACK CThreadMgr::ThreadFocusHookProc(INT nCode, WPARAM wParam, LPARAM lParam)
{ {
CThreadMgr *This = (CThreadMgr *)TlsGetValue(tlsIndex); CThreadMgr *This = (CThreadMgr *)TlsGetValue(g_tlsIndex);
if (!This) if (!This)
{ {
ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n"); 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->hwnd = hwnd;
wnd->docmgr = pdimNew; wnd->docmgr = pdimNew;
list_add_head(&m_AssociatedFocusWindows, &wnd->entry); list_add_head(&m_AssociatedFocusWindows, &wnd->entry);
@@ -614,7 +601,7 @@ STDMETHODIMP CThreadMgr::IsThreadFocus(_Out_ BOOL *pfThreadFocus)
return E_INVALIDARG; return E_INVALIDARG;
HWND focus = ::GetFocus(); HWND focus = ::GetFocus();
*pfThreadFocus = (focus == NULL); *pfThreadFocus = !focus;
return S_OK; return S_OK;
} }
@@ -640,15 +627,15 @@ STDMETHODIMP CThreadMgr::GetGlobalCompartment(_Out_ ITfCompartmentMgr **ppCompMg
if (!ppCompMgr) if (!ppCompMgr)
return E_INVALIDARG; 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)) if (FAILED(hr))
return hr; return hr;
} }
globalCompartmentMgr->AddRef(); g_globalCompartmentMgr->AddRef();
*ppCompMgr = globalCompartmentMgr; *ppCompMgr = g_globalCompartmentMgr;
return S_OK; return S_OK;
} }
@@ -664,16 +651,16 @@ STDMETHODIMP CThreadMgr::ActivateEx(
if (flags) if (flags)
FIXME("Unimplemented flags %#x\n", flags); FIXME("Unimplemented flags %#x\n", flags);
if (!processId) if (!g_processId)
{ {
GUID guid; GUID guid;
CoCreateGuid(&guid); CoCreateGuid(&guid);
GetClientId(guid, &processId); GetClientId(guid, &g_processId);
} }
activate_textservices(this); activate_textservices(this);
++m_activationCount; ++m_activationCount;
*id = processId; *id = g_processId;
return S_OK; return S_OK;
} }
@@ -941,7 +928,7 @@ STDMETHODIMP CThreadMgr::PreserveKey(
return TF_E_ALREADY_EXISTS; return TF_E_ALREADY_EXISTS;
} }
PreservedKey *newkey = (PreservedKey *)HeapAlloc(GetProcessHeap(), 0, sizeof(PreservedKey)); PreservedKey *newkey = (PreservedKey *)cicMemAlloc(sizeof(PreservedKey));
if (!newkey) if (!newkey)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@@ -951,10 +938,10 @@ STDMETHODIMP CThreadMgr::PreserveKey(
newkey->description = NULL; newkey->description = NULL;
if (cchDesc) if (cchDesc)
{ {
newkey->description = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (cchDesc + 1) * sizeof(WCHAR)); newkey->description = (LPWSTR)cicMemAlloc((cchDesc + 1) * sizeof(WCHAR));
if (!newkey->description) if (!newkey->description)
{ {
HeapFree(GetProcessHeap(), 0, newkey); cicMemFree(newkey);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
CopyMemory(newkey->description, pchDesc, cchDesc * sizeof(WCHAR)); CopyMemory(newkey->description, pchDesc, cchDesc * sizeof(WCHAR));
@@ -988,8 +975,8 @@ STDMETHODIMP CThreadMgr::UnpreserveKey(
return CONNECT_E_NOCONNECTION; return CONNECT_E_NOCONNECTION;
list_remove(&key->entry); list_remove(&key->entry);
HeapFree(GetProcessHeap(), 0, key->description); cicMemFree(key->description);
HeapFree(GetProcessHeap(), 0, key); cicMemFree(key);
return S_OK; return S_OK;
} }
@@ -1228,7 +1215,7 @@ HRESULT CThreadMgr::CreateInstance(IUnknown *pUnkOuter, CThreadMgr **ppOut)
return CLASS_E_NOAGGREGATION; return CLASS_E_NOAGGREGATION;
/* Only 1 ThreadMgr is created per thread */ /* Only 1 ThreadMgr is created per thread */
CThreadMgr *This = (CThreadMgr *)TlsGetValue(tlsIndex); CThreadMgr *This = (CThreadMgr *)TlsGetValue(g_tlsIndex);
if (This) if (This)
{ {
This->AddRef(); This->AddRef();
@@ -1240,7 +1227,7 @@ HRESULT CThreadMgr::CreateInstance(IUnknown *pUnkOuter, CThreadMgr **ppOut)
if (!This) if (!This)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
TlsSetValue(tlsIndex, This); TlsSetValue(g_tlsIndex, This);
ITfCompartmentMgr *pCompMgr = NULL; ITfCompartmentMgr *pCompMgr = NULL;
CompartmentMgr_Constructor(static_cast<ITfThreadMgrEx *>(This), IID_IUnknown, (IUnknown **)&pCompMgr); CompartmentMgr_Constructor(static_cast<ITfThreadMgrEx *>(This), IID_IUnknown, (IUnknown **)&pCompMgr);
@@ -1260,7 +1247,7 @@ void CThreadMgr::OnDocumentMgrDestruction(ITfDocumentMgr *mgr)
if (mgrentry->docmgr == mgr) if (mgrentry->docmgr == mgr)
{ {
list_remove(cursor); list_remove(cursor);
HeapFree(GetProcessHeap(), 0, mgrentry); cicMemFree(mgrentry);
return; return;
} }
} }
@@ -1306,7 +1293,7 @@ STDMETHODIMP_(ULONG) CEnumTfDocumentMgr::AddRef()
STDMETHODIMP_(ULONG) CEnumTfDocumentMgr::Release() STDMETHODIMP_(ULONG) CEnumTfDocumentMgr::Release()
{ {
ULONG ret = InterlockedDecrement(&m_cRefs); ULONG ret = InterlockedDecrement(&m_cRefs);
if (ret == 0) if (!ret)
delete this; delete this;
return ret; return ret;
} }

View File

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