⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oleobj.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *	OLE2 COM objects
 *
 *	Copyright 1998 Eric Kohl
 *      Copyright 1999 Francis Beaudet
 *
 * 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
 */


#include <stdarg.h>
#include <string.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winerror.h"
#include "wine/debug.h"
#include "ole2.h"

WINE_DEFAULT_DEBUG_CHANNEL(ole);

#define INITIAL_SINKS 10

/**************************************************************************
 *  OleAdviseHolderImpl Implementation
 */
typedef struct OleAdviseHolderImpl
{
  const IOleAdviseHolderVtbl *lpVtbl;

  LONG ref;

  DWORD         maxSinks;
  IAdviseSink** arrayOfSinks;

} OleAdviseHolderImpl;

static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum);

typedef struct
{
    const IEnumSTATDATAVtbl *lpvtbl;
    LONG ref;

    ULONG index;
    OleAdviseHolderImpl *pOleAdviseHolder;
} EnumOleSTATDATA;

static HRESULT WINAPI EnumOleSTATDATA_QueryInterface(
    IEnumSTATDATA *iface, REFIID riid, void **ppv)
{
    TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
    if (IsEqualIID(riid, &IID_IUnknown) ||
        IsEqualIID(riid, &IID_IEnumSTATDATA))
    {
        IUnknown_AddRef(iface);
        *ppv = iface;
        return S_OK;
    }
    return E_NOINTERFACE;
}

static ULONG WINAPI EnumOleSTATDATA_AddRef(
    IEnumSTATDATA *iface)
{
    EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
    TRACE("()\n");
    return InterlockedIncrement(&This->ref);
}

static ULONG WINAPI EnumOleSTATDATA_Release(
    IEnumSTATDATA *iface)
{
    EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
    LONG refs = InterlockedDecrement(&This->ref);
    TRACE("()\n");
    if (!refs)
    {
        IOleAdviseHolder_Release((IOleAdviseHolder *)This->pOleAdviseHolder);
        HeapFree(GetProcessHeap(), 0, This);
    }
    return refs;
}

static HRESULT WINAPI EnumOleSTATDATA_Next(
    IEnumSTATDATA *iface, ULONG celt, LPSTATDATA rgelt,
    ULONG *pceltFetched)
{
    EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
    HRESULT hr = S_OK;

    TRACE("(%d, %p, %p)\n", celt, rgelt, pceltFetched);

    if (pceltFetched)
        *pceltFetched = 0;

    for (; celt; celt--, rgelt++)
    {
        while ((This->index < This->pOleAdviseHolder->maxSinks) && 
               !This->pOleAdviseHolder->arrayOfSinks[This->index])
        {
            This->index++;
        }
        if (This->index >= This->pOleAdviseHolder->maxSinks)
        {
            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;

        if (pceltFetched)
            (*pceltFetched)++;
        This->index++;
    }
    return hr;
}

static HRESULT WINAPI EnumOleSTATDATA_Skip(
    IEnumSTATDATA *iface, ULONG celt)
{
    EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;

    TRACE("(%d)\n", celt);

    for (; celt; celt--)
    {
        while ((This->index < This->pOleAdviseHolder->maxSinks) && 
               !This->pOleAdviseHolder->arrayOfSinks[This->index])
        {
            This->index++;
        }
        if (This->index >= This->pOleAdviseHolder->maxSinks)
            return S_FALSE;
        This->index++;
    }
    return S_OK;
}

static HRESULT WINAPI EnumOleSTATDATA_Reset(
    IEnumSTATDATA *iface)
{
    EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;

    TRACE("()\n");

    This->index = 0;
    return S_OK;
}

static HRESULT WINAPI EnumOleSTATDATA_Clone(
    IEnumSTATDATA *iface,
    IEnumSTATDATA **ppenum)
{
    EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
    return EnumOleSTATDATA_Construct(This->pOleAdviseHolder, This->index, ppenum);
}

static const IEnumSTATDATAVtbl EnumOleSTATDATA_VTable =
{
    EnumOleSTATDATA_QueryInterface,
    EnumOleSTATDATA_AddRef,
    EnumOleSTATDATA_Release,
    EnumOleSTATDATA_Next,
    EnumOleSTATDATA_Skip,
    EnumOleSTATDATA_Reset,
    EnumOleSTATDATA_Clone
};

static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum)
{
    EnumOleSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
    if (!This)
        return E_OUTOFMEMORY;
    This->lpvtbl = &EnumOleSTATDATA_VTable;
    This->ref = 1;
    This->index = index;
    This->pOleAdviseHolder = pOleAdviseHolder;
    IOleAdviseHolder_AddRef((IOleAdviseHolder *)pOleAdviseHolder);
    *ppenum = (IEnumSTATDATA *)&This->lpvtbl;
    return S_OK;    
}

/**************************************************************************
 *  OleAdviseHolderImpl_Destructor
 */
static void OleAdviseHolderImpl_Destructor(
  OleAdviseHolderImpl* ptrToDestroy)
{
  DWORD index;
  TRACE("%p\n", ptrToDestroy);

  for (index = 0; index < ptrToDestroy->maxSinks; index++)
  {
    if (ptrToDestroy->arrayOfSinks[index]!=0)
    {
      IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
      ptrToDestroy->arrayOfSinks[index] = NULL;
    }
  }

  HeapFree(GetProcessHeap(),
	   0,
	   ptrToDestroy->arrayOfSinks);


  HeapFree(GetProcessHeap(),
	   0,
	   ptrToDestroy);
}

/**************************************************************************
 *  OleAdviseHolderImpl_QueryInterface
 */
static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
  LPOLEADVISEHOLDER iface,
  REFIID            riid,
  LPVOID*           ppvObj)
{
  OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
  TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
  /*
   * Sanity check
   */
  if (ppvObj==NULL)
    return E_POINTER;

  *ppvObj = NULL;

  if (IsEqualIID(riid, &IID_IUnknown))
  {
    /* IUnknown */
    *ppvObj = This;
  }
  else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
  {
    /* IOleAdviseHolder */
    *ppvObj = (IOleAdviseHolder*) This;
  }

  if(*ppvObj == NULL)
    return E_NOINTERFACE;

  /*
   * A successful QI always increments the reference count.
   */
  IUnknown_AddRef((IUnknown*)*ppvObj);

  return S_OK;
}

/******************************************************************************
 * OleAdviseHolderImpl_AddRef
 */
static ULONG WINAPI OleAdviseHolderImpl_AddRef(
  LPOLEADVISEHOLDER iface)
{
  OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
  ULONG ref = InterlockedIncrement(&This->ref);

  TRACE("(%p)->(ref=%d)\n", This, ref - 1);

  return ref;
}

/******************************************************************************
 * OleAdviseHolderImpl_Release
 */
static ULONG WINAPI OleAdviseHolderImpl_Release(
  LPOLEADVISEHOLDER iface)
{
  OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
  ULONG ref;
  TRACE("(%p)->(ref=%d)\n", This, This->ref);
  ref = InterlockedDecrement(&This->ref);

  if (ref == 0) OleAdviseHolderImpl_Destructor(This);

  return ref;
}

/******************************************************************************
 * OleAdviseHolderImpl_Advise
 */
static HRESULT WINAPI OleAdviseHolderImpl_Advise(
  LPOLEADVISEHOLDER iface,
  IAdviseSink*      pAdvise,
  DWORD*            pdwConnection)
{
  DWORD index;

  OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;

  TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);

  /*
   * Sanity check
   */
  if (pdwConnection==NULL)
    return E_POINTER;

  *pdwConnection = 0;

  /*
   * Find a free spot in the array.
   */
  for (index = 0; index < This->maxSinks; index++)
  {
    if (This->arrayOfSinks[index]==NULL)
      break;
  }

  /*
   * If the array is full, we need to grow it.
   */
  if (index == This->maxSinks)
  {
    DWORD i;

    This->maxSinks+=INITIAL_SINKS;

    This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
				     0,
				     This->arrayOfSinks,
				     This->maxSinks*sizeof(IAdviseSink*));

    for (i=index;i < This->maxSinks; i++)
      This->arrayOfSinks[i]=0;
  }

  /*
   * Store the new sink
   */
  This->arrayOfSinks[index] = pAdvise;

  if (This->arrayOfSinks[index]!=NULL)
    IAdviseSink_AddRef(This->arrayOfSinks[index]);

  /*
   * Return the index as the cookie.
   * Since 0 is not a valid cookie, we will increment by
   * 1 the index in the table.
   */
  *pdwConnection = index+1;

  return S_OK;
}

/******************************************************************************
 * OleAdviseHolderImpl_Unadvise
 */
static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
  LPOLEADVISEHOLDER iface,
  DWORD             dwConnection)
{
  OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;

  TRACE("(%p)->(%u)\n", This, dwConnection);

  /*
   * So we don't return 0 as a cookie, the index was
   * incremented by 1 in OleAdviseHolderImpl_Advise
   * we have to compensate.
   */
  dwConnection--;

  /*
   * Check for invalid cookies.
   */
  if (dwConnection >= This->maxSinks)
    return OLE_E_NOCONNECTION;

  if (This->arrayOfSinks[dwConnection] == NULL)
    return OLE_E_NOCONNECTION;

  /*
   * Release the sink and mark the spot in the list as free.
   */
  IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
  This->arrayOfSinks[dwConnection] = NULL;

  return S_OK;
}

/******************************************************************************
 * OleAdviseHolderImpl_EnumAdvise
 */
static HRESULT WINAPI
OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
{
    OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;

    TRACE("(%p)->(%p)\n", This, ppenumAdvise);

    *ppenumAdvise = NULL;

    return EnumOleSTATDATA_Construct(This, 0, ppenumAdvise);
}

/******************************************************************************
 * OleAdviseHolderImpl_SendOnRename
 */
static HRESULT WINAPI
OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
{
    IEnumSTATDATA *pEnum;
    HRESULT hr;

    TRACE("(%p)->(%p)\n", iface, pmk);

    hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
    if (SUCCEEDED(hr))
    {
        STATDATA statdata;
        while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
        {
            IAdviseSink_OnRename(statdata.pAdvSink, pmk);

            IAdviseSink_Release(statdata.pAdvSink);
        }
        IEnumSTATDATA_Release(pEnum);
    }

    return hr;
}

/******************************************************************************
 * OleAdviseHolderImpl_SendOnSave
 */
static HRESULT WINAPI
OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
{
    IEnumSTATDATA *pEnum;
    HRESULT hr;

    TRACE("(%p)->()\n", iface);

    hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
    if (SUCCEEDED(hr))
    {
        STATDATA statdata;
        while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
        {
            IAdviseSink_OnSave(statdata.pAdvSink);

            IAdviseSink_Release(statdata.pAdvSink);
        }
        IEnumSTATDATA_Release(pEnum);
    }

    return hr;
}

/******************************************************************************
 * OleAdviseHolderImpl_SendOnClose
 */
static HRESULT WINAPI
OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
{
    IEnumSTATDATA *pEnum;
    HRESULT hr;

    TRACE("(%p)->()\n", iface);

    hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
    if (SUCCEEDED(hr))
    {
        STATDATA statdata;
        while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
        {
            IAdviseSink_OnClose(statdata.pAdvSink);

            IAdviseSink_Release(statdata.pAdvSink);
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -