https://git.reactos.org/?p=reactos.git;a=commitdiff;h=954598037fc4ddd76078e…
commit 954598037fc4ddd76078e5159329a7594434d2c9
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Wed Dec 20 22:01:39 2023 +0900
Commit: GitHub <noreply(a)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.mz(a)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)