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)

Reply via email to