https://git.reactos.org/?p=reactos.git;a=commitdiff;h=954598037fc4ddd76078e5159329a7594434d2c9
commit 954598037fc4ddd76078e5159329a7594434d2c9 Author: Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com> AuthorDate: Wed Dec 20 22:01:39 2023 +0900 Commit: GitHub <nore...@github.com> CommitDate: Wed Dec 20 22:01:39 2023 +0900 [MSCTFIME][SDK] Implement CCompartmentEventSink (#6205) - Modify <cicero/cicbase.h> and <cicero/cicarray.h>. - Add CCompartmentEventSink class. CORE-19360 --- dll/ime/msctfime/msctfime.cpp | 152 ++++++++++++++++++++++++++++++++++ dll/ime/msctfime/msctfime.h | 1 + sdk/include/reactos/cicero/cicarray.h | 20 +++-- sdk/include/reactos/cicero/cicbase.h | 14 ++++ 4 files changed, 178 insertions(+), 9 deletions(-) diff --git a/dll/ime/msctfime/msctfime.cpp b/dll/ime/msctfime/msctfime.cpp index 044a6bc8cb2..5a3e8c94830 100644 --- a/dll/ime/msctfime/msctfime.cpp +++ b/dll/ime/msctfime/msctfime.cpp @@ -164,6 +164,10 @@ void TFUninitLib_Thread(PLIBTHREAD pLibThread) } } +/*********************************************************************** + * Compartment + */ + HRESULT GetCompartment( IUnknown *pUnknown, @@ -304,6 +308,154 @@ ClearCompartment( return hr; } +typedef struct CESMAP +{ + ITfCompartment *m_pComp; + DWORD m_dwCookie; +} CESMAP, *PCESMAP; + +typedef INT (CALLBACK *FN_EVENTSINK)(LPVOID, REFGUID); + +class CCompartmentEventSink : public ITfCompartmentEventSink +{ + CicArray m_array; + LONG m_cRefs; + FN_EVENTSINK m_fnEventSink; + LPVOID m_pUserData; + +public: + CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData); + virtual ~CCompartmentEventSink(); + + HRESULT _Advise(IUnknown *pUnknown, REFGUID rguid, ITfCompartment *pComp); + HRESULT _Unadvise(); + + // IUnknown interface + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + // ITfCompartmentEventSink interface + STDMETHODIMP OnChange(REFGUID rguid) override; +}; + +CCompartmentEventSink::CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData) + : m_array(8) + , m_cRefs(1) + , m_fnEventSink(fnEventSink) + , m_pUserData(pUserData) +{ +} + +CCompartmentEventSink::~CCompartmentEventSink() +{ +} + +STDMETHODIMP CCompartmentEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfCompartmentEventSink)) + { + *ppvObj = this; + AddRef(); + return S_OK; + } + + *ppvObj = NULL; + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) CCompartmentEventSink::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +STDMETHODIMP_(ULONG) CCompartmentEventSink::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +STDMETHODIMP CCompartmentEventSink::OnChange(REFGUID rguid) +{ + return m_fnEventSink(m_pUserData, rguid); +} + +HRESULT +CCompartmentEventSink::_Advise(IUnknown *pUnknown, REFGUID rguid, ITfCompartment *pComp) +{ + CESMAP *pCesMap = (CESMAP *)m_array.Append(1); + if (!pCesMap) + return E_OUTOFMEMORY; + + ITfSource *pSource = NULL; + + HRESULT hr = GetCompartment(pUnknown, rguid, &pCesMap->m_pComp, !!pComp); + if (FAILED(hr)) + { + hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource); + if (FAILED(hr)) + { + hr = pSource->AdviseSink(IID_ITfCompartmentEventSink, this, &pCesMap->m_dwCookie); + if (FAILED(hr)) + { + if (pCesMap->m_pComp) + { + pCesMap->m_pComp->Release(); + pCesMap->m_pComp = NULL; + } + m_array.Remove(m_array.m_cItems - 1, 1); + } + else + { + hr = S_OK; + } + } + } + + if (pSource) + pSource->Release(); + + return hr; +} + +HRESULT CCompartmentEventSink::_Unadvise() +{ + CESMAP *pCesMap = (CESMAP *)m_array.m_pb; + if (!m_array.m_cItems) + return S_OK; + + INT cItems = m_array.m_cItems; + do + { + ITfSource *pSource = NULL; + HRESULT hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource); + if (SUCCEEDED(hr)) + pSource->UnadviseSink(pCesMap->m_dwCookie); + + if (pCesMap->m_pComp) + { + pCesMap->m_pComp->Release(); + pCesMap->m_pComp = NULL; + } + + if (pSource) + pSource->Release(); + + ++pCesMap; + --cItems; + } while (cItems); + + return S_OK; +} + +/*********************************************************************** + * CicInputContext + */ + /* FIXME */ class CicInputContext : public ITfContextOwnerCompositionSink { diff --git a/dll/ime/msctfime/msctfime.h b/dll/ime/msctfime/msctfime.h index 892bd76ef26..daa9f74c66f 100644 --- a/dll/ime/msctfime/msctfime.h +++ b/dll/ime/msctfime/msctfime.h @@ -23,6 +23,7 @@ #include <strsafe.h> #include <cicero/cicbase.h> +#include <cicero/cicarray.h> #include <cicero/osinfo.h> #include <cicero/CModulePath.h> #include <cicero/imclock.h> diff --git a/sdk/include/reactos/cicero/cicarray.h b/sdk/include/reactos/cicero/cicarray.h index 8767ac727f9..9ce7cfa6b76 100644 --- a/sdk/include/reactos/cicero/cicarray.h +++ b/sdk/include/reactos/cicero/cicarray.h @@ -11,18 +11,17 @@ class CicArray { - LPVOID lpVtbl; +public: LPBYTE m_pb; INT m_cItems; INT m_cbItem; INT m_cCapacity; -public: CicArray(INT cbItem); - virtual CicArray(); + virtual ~CicArray(); - void Insert(INT iItem, INT cGrow); - void Append(INT cGrow); + BOOL Insert(INT iItem, INT cGrow); + LPVOID Append(INT cGrow); void Remove(INT iItem, INT cRemove); }; @@ -40,12 +39,14 @@ inline CicArray::~CicArray() cicMemFree(m_pb); } -inline void CicArray::Append(INT cGrow) +inline LPVOID CicArray::Append(INT cGrow) { - Insert(m_cItems, cGrow); + if (!Insert(m_cItems, cGrow)) + return NULL; + return &m_pb[(m_cItems - cGrow) * m_cbItem]; } -inline void CicArray::Insert(INT iItem, INT cGrow) +inline BOOL CicArray::Insert(INT iItem, INT cGrow) { INT cNewCapacity = m_cItems + cGrow; if (m_cCapacity < cNewCapacity) @@ -60,7 +61,7 @@ inline void CicArray::Insert(INT iItem, INT cGrow) pbNew = (BYTE *)cicMemAlloc(cNewCapacity * m_cbItem); if (!pbNew) - return; + return FALSE; m_pb = pbNew; m_cCapacity = cNewCapacity; @@ -74,6 +75,7 @@ inline void CicArray::Insert(INT iItem, INT cGrow) } m_cItems += cGrow; + return TRUE; } inline void CicArray::Remove(INT iItem, INT cRemove) diff --git a/sdk/include/reactos/cicero/cicbase.h b/sdk/include/reactos/cicero/cicbase.h index 9048dcb865a..3e4184ac7fc 100644 --- a/sdk/include/reactos/cicero/cicbase.h +++ b/sdk/include/reactos/cicero/cicbase.h @@ -5,11 +5,25 @@ * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com> */ +#pragma once + +static inline LPVOID cicMemAlloc(SIZE_T size) +{ + return LocalAlloc(0, size); +} + static inline LPVOID cicMemAllocClear(SIZE_T size) { return LocalAlloc(LMEM_ZEROINIT, size); } +static inline LPVOID cicMemReAlloc(LPVOID ptr, SIZE_T newSize) +{ + if (!ptr) + return LocalAlloc(LMEM_ZEROINIT, newSize); + return LocalReAlloc(ptr, newSize, LMEM_ZEROINIT); +} + static inline void cicMemFree(LPVOID ptr) { if (ptr)