Huw Davies : ole32: Rewrite the OleAdviseHolder' s STATDATA enumerator to be a generic STATDATA enumerator.

Alexandre Julliard julliard at winehq.org
Fri Dec 17 11:30:45 CST 2010


Module: wine
Branch: master
Commit: 10aa9b219472e2662721146bc19cb74e08173d45
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=10aa9b219472e2662721146bc19cb74e08173d45

Author: Huw Davies <huw at codeweavers.com>
Date:   Thu Dec 16 12:20:51 2010 +0000

ole32: Rewrite the OleAdviseHolder's STATDATA enumerator to be a generic STATDATA enumerator.

---

 dlls/ole32/oleobj.c |  201 ++++++++++++++++++++++++++++++++-------------------
 1 files changed, 128 insertions(+), 73 deletions(-)

diff --git a/dlls/ole32/oleobj.c b/dlls/ole32/oleobj.c
index 4b2b5d7..6b4106a 100644
--- a/dlls/ole32/oleobj.c
+++ b/dlls/ole32/oleobj.c
@@ -38,6 +38,34 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
 #define INITIAL_SINKS 10
 
+static void release_statdata(STATDATA *data)
+{
+    if(data->formatetc.ptd)
+    {
+        CoTaskMemFree(data->formatetc.ptd);
+        data->formatetc.ptd = NULL;
+    }
+
+    if(data->pAdvSink)
+    {
+        IAdviseSink_Release(data->pAdvSink);
+        data->pAdvSink = NULL;
+    }
+}
+
+static HRESULT copy_statdata(STATDATA *dst, const STATDATA *src)
+{
+    *dst = *src;
+    if(src->formatetc.ptd)
+    {
+        dst->formatetc.ptd = CoTaskMemAlloc(src->formatetc.ptd->tdSize);
+        if(!dst->formatetc.ptd) return E_OUTOFMEMORY;
+        memcpy(dst->formatetc.ptd, src->formatetc.ptd, src->formatetc.ptd->tdSize);
+    }
+    if(dst->pAdvSink) IAdviseSink_AddRef(dst->pAdvSink);
+    return S_OK;
+}
+
 /**************************************************************************
  *  OleAdviseHolderImpl Implementation
  */
@@ -52,7 +80,7 @@ typedef struct OleAdviseHolderImpl
 
 } OleAdviseHolderImpl;
 
-static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum);
+static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD num, STATDATA *data, IEnumSTATDATA **ppenum);
 
 typedef struct
 {
@@ -60,16 +88,17 @@ typedef struct
     LONG ref;
 
     ULONG index;
-    OleAdviseHolderImpl *pOleAdviseHolder;
-} EnumOleSTATDATA;
+    DWORD num_of_elems;
+    STATDATA *statdata;
+    IUnknown *holder;
+} EnumSTATDATA;
 
-static inline EnumOleSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
+static inline EnumSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
 {
-    return CONTAINING_RECORD(iface, EnumOleSTATDATA, IEnumSTATDATA_iface);
+    return CONTAINING_RECORD(iface, EnumSTATDATA, IEnumSTATDATA_iface);
 }
 
-static HRESULT WINAPI EnumOleSTATDATA_QueryInterface(
-    IEnumSTATDATA *iface, REFIID riid, void **ppv)
+static HRESULT WINAPI EnumSTATDATA_QueryInterface(IEnumSTATDATA *iface, REFIID riid, void **ppv)
 {
     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
     if (IsEqualIID(riid, &IID_IUnknown) ||
@@ -82,91 +111,77 @@ static HRESULT WINAPI EnumOleSTATDATA_QueryInterface(
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI EnumOleSTATDATA_AddRef(
-    IEnumSTATDATA *iface)
+static ULONG WINAPI EnumSTATDATA_AddRef(IEnumSTATDATA *iface)
 {
-    EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
+    EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
     TRACE("()\n");
     return InterlockedIncrement(&This->ref);
 }
 
-static ULONG WINAPI EnumOleSTATDATA_Release(
-    IEnumSTATDATA *iface)
+static ULONG WINAPI EnumSTATDATA_Release(IEnumSTATDATA *iface)
 {
-    EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
+    EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
     LONG refs = InterlockedDecrement(&This->ref);
     TRACE("()\n");
     if (!refs)
     {
-        IOleAdviseHolder_Release((IOleAdviseHolder *)This->pOleAdviseHolder);
+        DWORD i;
+        for(i = 0; i < This->num_of_elems; i++)
+            release_statdata(This->statdata + i);
+        HeapFree(GetProcessHeap(), 0, This->statdata);
+        IUnknown_Release(This->holder);
         HeapFree(GetProcessHeap(), 0, This);
     }
     return refs;
 }
 
-static HRESULT WINAPI EnumOleSTATDATA_Next(
-    IEnumSTATDATA *iface, ULONG celt, LPSTATDATA rgelt,
-    ULONG *pceltFetched)
+static HRESULT WINAPI EnumSTATDATA_Next(IEnumSTATDATA *iface, ULONG num, LPSTATDATA data,
+                                        ULONG *fetched)
 {
-    EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
+    EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
+    DWORD count = 0;
     HRESULT hr = S_OK;
 
-    TRACE("(%d, %p, %p)\n", celt, rgelt, pceltFetched);
+    TRACE("(%d, %p, %p)\n", num, data, fetched);
 
-    if (pceltFetched)
-        *pceltFetched = 0;
-
-    for (; celt; celt--, rgelt++)
+    while(num--)
     {
-        while ((This->index < This->pOleAdviseHolder->maxSinks) && 
-               !This->pOleAdviseHolder->arrayOfSinks[This->index])
-        {
-            This->index++;
-        }
-        if (This->index >= This->pOleAdviseHolder->maxSinks)
+        if (This->index >= This->num_of_elems)
         {
             hr = S_FALSE;
             break;
         }
 
-        memset(&rgelt->formatetc, 0, sizeof(rgelt->formatetc));
-        rgelt->advf = 0;
-        rgelt->pAdvSink = This->pOleAdviseHolder->arrayOfSinks[This->index];
-        IAdviseSink_AddRef(rgelt->pAdvSink);
-        rgelt->dwConnection = This->index;
+        copy_statdata(data + count, This->statdata + This->index);
 
-        if (pceltFetched)
-            (*pceltFetched)++;
+        count++;
         This->index++;
     }
+
+    if (fetched) *fetched = count;
+
     return hr;
 }
 
-static HRESULT WINAPI EnumOleSTATDATA_Skip(
-    IEnumSTATDATA *iface, ULONG celt)
+static HRESULT WINAPI EnumSTATDATA_Skip(IEnumSTATDATA *iface, ULONG num)
 {
-    EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
+    EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
 
-    TRACE("(%d)\n", celt);
+    TRACE("(%d)\n", num);
 
-    for (; celt; celt--)
+    if(This->index + num >= This->num_of_elems)
     {
-        while ((This->index < This->pOleAdviseHolder->maxSinks) && 
-               !This->pOleAdviseHolder->arrayOfSinks[This->index])
-        {
-            This->index++;
-        }
-        if (This->index >= This->pOleAdviseHolder->maxSinks)
-            return S_FALSE;
-        This->index++;
+        This->index = This->num_of_elems;
+        return S_FALSE;
     }
+
+    This->index += num;
     return S_OK;
 }
 
-static HRESULT WINAPI EnumOleSTATDATA_Reset(
-    IEnumSTATDATA *iface)
+static HRESULT WINAPI EnumSTATDATA_Reset(IEnumSTATDATA *iface)
 {
-    EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
+    EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
 
     TRACE("()\n");
 
@@ -174,35 +189,49 @@ static HRESULT WINAPI EnumOleSTATDATA_Reset(
     return S_OK;
 }
 
-static HRESULT WINAPI EnumOleSTATDATA_Clone(
-    IEnumSTATDATA *iface,
-    IEnumSTATDATA **ppenum)
+static HRESULT WINAPI EnumSTATDATA_Clone(IEnumSTATDATA *iface, IEnumSTATDATA **ppenum)
 {
-    EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
-    return EnumOleSTATDATA_Construct(This->pOleAdviseHolder, This->index, ppenum);
+    EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
+
+    return EnumSTATDATA_Construct(This->holder, This->index, This->num_of_elems, This->statdata, ppenum);
 }
 
-static const IEnumSTATDATAVtbl EnumOleSTATDATA_VTable =
+static const IEnumSTATDATAVtbl EnumSTATDATA_VTable =
 {
-    EnumOleSTATDATA_QueryInterface,
-    EnumOleSTATDATA_AddRef,
-    EnumOleSTATDATA_Release,
-    EnumOleSTATDATA_Next,
-    EnumOleSTATDATA_Skip,
-    EnumOleSTATDATA_Reset,
-    EnumOleSTATDATA_Clone
+    EnumSTATDATA_QueryInterface,
+    EnumSTATDATA_AddRef,
+    EnumSTATDATA_Release,
+    EnumSTATDATA_Next,
+    EnumSTATDATA_Skip,
+    EnumSTATDATA_Reset,
+    EnumSTATDATA_Clone
 };
 
-static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum)
+static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD num, STATDATA *data,
+                                      IEnumSTATDATA **ppenum)
 {
-    EnumOleSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
-    if (!This)
-        return E_OUTOFMEMORY;
-    This->IEnumSTATDATA_iface.lpVtbl = &EnumOleSTATDATA_VTable;
+    EnumSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+    DWORD i;
+
+    if (!This) return E_OUTOFMEMORY;
+
+    This->IEnumSTATDATA_iface.lpVtbl = &EnumSTATDATA_VTable;
     This->ref = 1;
     This->index = index;
-    This->pOleAdviseHolder = pOleAdviseHolder;
-    IOleAdviseHolder_AddRef((IOleAdviseHolder *)pOleAdviseHolder);
+
+    This->statdata = HeapAlloc(GetProcessHeap(), 0, num * sizeof(*This->statdata));
+    if(!This->statdata)
+    {
+        HeapFree(GetProcessHeap(), 0, This);
+        return E_OUTOFMEMORY;
+    }
+
+    for(i = 0; i < num; i++)
+        copy_statdata(This->statdata + i, data + i);
+
+    This->num_of_elems = num;
+    This->holder = holder;
+    IUnknown_AddRef(holder);
     *ppenum = &This->IEnumSTATDATA_iface;
     return S_OK;
 }
@@ -415,12 +444,38 @@ static HRESULT WINAPI
 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
 {
     OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
+    IUnknown *unk;
+    DWORD i, count;
+    STATDATA *data;
+    static const FORMATETC empty_fmtetc = {0, NULL, 0, -1, 0};
+    HRESULT hr;
 
     TRACE("(%p)->(%p)\n", This, ppenumAdvise);
 
     *ppenumAdvise = NULL;
 
-    return EnumOleSTATDATA_Construct(This, 0, ppenumAdvise);
+    /* Build an array of STATDATA structures */
+    data = HeapAlloc(GetProcessHeap(), 0, This->maxSinks * sizeof(*data));
+    if(!data) return E_OUTOFMEMORY;
+
+    for(i = 0, count = 0; i < This->maxSinks; i++)
+    {
+        if(This->arrayOfSinks[i])
+        {
+            data[count].formatetc = empty_fmtetc;
+            data[count].advf = 0;
+            data[count].pAdvSink = This->arrayOfSinks[i]; /* The constructor will take a ref. */
+            data[count].dwConnection = i;
+            count++;
+        }
+    }
+
+    IOleAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
+    hr = EnumSTATDATA_Construct(unk, 0, count, data, ppenumAdvise);
+    IUnknown_Release(unk);
+    HeapFree(GetProcessHeap(), 0, data);
+
+    return hr;
 }
 
 /******************************************************************************




More information about the wine-cvs mailing list