Files
reactos/reactos/lib/ole32/oleobj.c
Gé van Geldorp 8d07772195 Sync to Wine-20050111:
Michael Stefaniuc <mstefani@redhat.de>
- Do not check for non NULL pointer before HeapFree'ing it. It's
  redundant.
Eric Pouech <pouech-eric@wanadoo.fr>
- Fixed some errors in function prototypes.
- ReadFile and WriteFile must be passed a parameter for the number of
  handled bytes when no overlapped operation is done.
- Removed excessive statement (break after return or goto, not useful
  break, not needed vars...)
Robert Shearman <rob@codeweavers.com>
- Remove unnecessary WNDPROC casts.
- Document how thread-safety is ensured for each member of the
  stub_manager and ifstub structs.
- Make stub_manager ref counted to ensure it doesn't get freed whilst
  it is still being used.
- ifstubs are now freed only when the controlling stub_manager is freed.
- Rename stub_manager_ref/unref to stub_manager_ext_addref/release
  respectively and make then take an unsigned long to prevent
  malicious callers from passing in a negative value and corrupting
  the ref count.
- Rename iid in wine_marshal_id to ipid and use IPIDs instead of IIDs in
  the stub manager.
- The channel buffer can be NULL if the proxy is disconnected, so check
  for this before releasing it.
- Make the ClassFactory proxy support aggregation.
- Document how thread-safety is ensured for each member of the
  stub_manager and ifstub structs.
- Make stub_manager ref counted to ensure it doesn't get freed whilst
  it is still being used.
- ifstubs are now freed only when the controlling stub_manager is freed.
- Rename stub_manager_ref/unref to stub_manager_ext_addref/release
  respectively and make then take an unsigned long to prevent
  malicious callers from passing in a negative value and corrupting
  the ref count.
- The current architecture cannot handle pipes changing address, so use
  a static array. Fixes memory corruption that sometimes occurs when
  using multiple pipes.
- Fix race on apartment creation.
- Display errors in decimal to make searching for the meaning in
  winerror.h easier.
- Move named pipe macros into rpc.c.
- Remove unneeded function.
- Implement COM local servers using table marshaling to avoid doing the
  marshaling in a child thread where COM has not been initialized.
- Remove unneeded includes and the unused COMPOBJ_hInstance32 variable.
- Make the wine_marshal_id structure more like the DCOM OBJREF
  structure, by replacing the process id field by apartment id (OXID),
  changing the users of the process id field to use the new field and
  renaming the objectid field to oid.
- Fix StdMarshalImpl_UnmarshalInterface to invalidate and release its
  stub when doing a same apartment marshal.
- Fixed incorrect unsigned test.
- Add tracing for proxy ref count functions.
- Release the channel on proxy destruction.
- Implement proxy manager.
- Add documentation to several functions.
- Coding style changes according to the style Mike and I have agreed
  upon for COM related files.
- Use OBJREF on the wire for generic marshaling functions.
- Add some function declarations to objbase.h.
- Add stubs for server ref counting.
- Implement HRESULT marshaling.
- Make struct oletls ref counted so that it is only detached from the
  apartment on the final CoUninitialize.
- Decrease the size of the crit sec on destroying an apartment - it is
  only needed for touching the apartment list.
- Small cleanups.
Mike Hearn <mh@codeweavers.com>
- Implement the COM stub manager, refactor the current stub code.
- Begin implementing interface stubs.
- Make apartment access thread-safe by introducing refcounting and
  wider usage of the apartment lock.
- Rework OLE TLS management to eliminate uninitialised apartments and
  parent chaining.
- Comment out an assert, as we don't yet implement IRemUnknown.
- Propagate apartments through the intermediate threads, make listener
  thread apartment scoped.
- Rename the STUBMGR thread to more accurately reflect its purpose.
- Add a DCOM todo list.
Mike McCormack <mike@codeweavers.com>
- Test and fix a few problems with OLE storage streams.
- Allow COM to start services containing COM servers.
- Tests and fixes for StgOpenStorage.
- Test and fix StgCreateDocFile grfModes.
Paul Vriens <Paul.Vriens@xs4all.nl>
- use Interlocked* functions in AddRef and Release.
- store the result of the Interlocked functions and use only this.
Francois Gouget <fgouget@free.fr>
- Assorted spelling fixes.
Alexandre Julliard <julliard@winehq.org>
- Janitorial: C booleans must not be compared against TRUE.
Bill Medland <billmedland@mercuryspeed.com>
- Corrected testing for multithreaded (based upon observations by Paul
  Vriens, Christian Costa and Robert Shearman).
- Added TRACE for investigating OXID errors.

svn path=/trunk/; revision=12952
2005-01-12 10:23:25 +00:00

756 lines
20 KiB
C

/*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
{
IOleAdviseHolderVtbl *lpVtbl;
DWORD ref;
DWORD maxSinks;
IAdviseSink** arrayOfSinks;
} OleAdviseHolderImpl;
static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(void);
static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);
static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);
static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);
static ULONG WINAPI OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER);
static HRESULT WINAPI OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*);
static HRESULT WINAPI OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD);
static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **);
static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *);
static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER);
static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER);
/**************************************************************************
* OleAdviseHolderImpl_VTable
*/
static struct IOleAdviseHolderVtbl oahvt =
{
OleAdviseHolderImpl_QueryInterface,
OleAdviseHolderImpl_AddRef,
OleAdviseHolderImpl_Release,
OleAdviseHolderImpl_Advise,
OleAdviseHolderImpl_Unadvise,
OleAdviseHolderImpl_EnumAdvise,
OleAdviseHolderImpl_SendOnRename,
OleAdviseHolderImpl_SendOnSave,
OleAdviseHolderImpl_SendOnClose
};
/**************************************************************************
* OleAdviseHolderImpl_Constructor
*/
static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()
{
OleAdviseHolderImpl* lpoah;
DWORD index;
lpoah= (OleAdviseHolderImpl*)HeapAlloc(GetProcessHeap(),
0,
sizeof(OleAdviseHolderImpl));
lpoah->lpVtbl = &oahvt;
lpoah->ref = 1;
lpoah->maxSinks = INITIAL_SINKS;
lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
0,
lpoah->maxSinks * sizeof(IAdviseSink*));
for (index = 0; index < lpoah->maxSinks; index++)
lpoah->arrayOfSinks[index]=0;
TRACE("returning %p\n", lpoah);
return (LPOLEADVISEHOLDER)lpoah;
}
/**************************************************************************
* 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=%ld)\n", This, ref - 1);
return ref;
}
/******************************************************************************
* OleAdviseHolderImpl_Release
*/
static ULONG WINAPI OleAdviseHolderImpl_Release(
LPOLEADVISEHOLDER iface)
{
OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
ULONG ref;
TRACE("(%p)->(ref=%ld)\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)->(%lu)\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;
FIXME("(%p)->(%p)\n", This, ppenumAdvise);
*ppenumAdvise = NULL;
return S_OK;
}
/******************************************************************************
* OleAdviseHolderImpl_SendOnRename
*/
static HRESULT WINAPI
OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
{
OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
FIXME("(%p)->(%p)\n", This, pmk);
return S_OK;
}
/******************************************************************************
* OleAdviseHolderImpl_SendOnSave
*/
static HRESULT WINAPI
OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
{
OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
FIXME("(%p)\n", This);
return S_OK;
}
/******************************************************************************
* OleAdviseHolderImpl_SendOnClose
*/
static HRESULT WINAPI
OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
{
OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
FIXME("(%p)\n", This);
return S_OK;
}
/**************************************************************************
* DataAdviseHolder Implementation
*/
typedef struct DataAdviseConnection {
IAdviseSink *sink;
FORMATETC fmat;
DWORD advf;
} DataAdviseConnection;
typedef struct DataAdviseHolder
{
IDataAdviseHolderVtbl *lpVtbl;
DWORD ref;
DWORD maxCons;
DataAdviseConnection* Connections;
} DataAdviseHolder;
/**************************************************************************
* DataAdviseHolder method prototypes
*/
static IDataAdviseHolder* DataAdviseHolder_Constructor(void);
static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
static HRESULT WINAPI DataAdviseHolder_QueryInterface(
IDataAdviseHolder* iface,
REFIID riid,
void** ppvObject);
static ULONG WINAPI DataAdviseHolder_AddRef(
IDataAdviseHolder* iface);
static ULONG WINAPI DataAdviseHolder_Release(
IDataAdviseHolder* iface);
static HRESULT WINAPI DataAdviseHolder_Advise(
IDataAdviseHolder* iface,
IDataObject* pDataObject,
FORMATETC* pFetc,
DWORD advf,
IAdviseSink* pAdvise,
DWORD* pdwConnection);
static HRESULT WINAPI DataAdviseHolder_Unadvise(
IDataAdviseHolder* iface,
DWORD dwConnection);
static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
IDataAdviseHolder* iface,
IEnumSTATDATA** ppenumAdvise);
static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
IDataAdviseHolder* iface,
IDataObject* pDataObject,
DWORD dwReserved,
DWORD advf);
/**************************************************************************
* DataAdviseHolderImpl_VTable
*/
static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
{
DataAdviseHolder_QueryInterface,
DataAdviseHolder_AddRef,
DataAdviseHolder_Release,
DataAdviseHolder_Advise,
DataAdviseHolder_Unadvise,
DataAdviseHolder_EnumAdvise,
DataAdviseHolder_SendOnDataChange
};
/******************************************************************************
* DataAdviseHolder_Constructor
*/
static IDataAdviseHolder* DataAdviseHolder_Constructor()
{
DataAdviseHolder* newHolder;
newHolder = (DataAdviseHolder*)HeapAlloc(GetProcessHeap(),
0,
sizeof(DataAdviseHolder));
newHolder->lpVtbl = &DataAdviseHolderImpl_VTable;
newHolder->ref = 1;
newHolder->maxCons = INITIAL_SINKS;
newHolder->Connections = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
newHolder->maxCons *
sizeof(DataAdviseConnection));
TRACE("returning %p\n", newHolder);
return (IDataAdviseHolder*)newHolder;
}
/******************************************************************************
* DataAdviseHolder_Destructor
*/
static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
{
DWORD index;
TRACE("%p\n", ptrToDestroy);
for (index = 0; index < ptrToDestroy->maxCons; index++)
{
if (ptrToDestroy->Connections[index].sink != NULL)
{
IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
ptrToDestroy->Connections[index].sink = NULL;
}
}
HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
HeapFree(GetProcessHeap(), 0, ptrToDestroy);
}
/************************************************************************
* DataAdviseHolder_QueryInterface (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static HRESULT WINAPI DataAdviseHolder_QueryInterface(
IDataAdviseHolder* iface,
REFIID riid,
void** ppvObject)
{
DataAdviseHolder *This = (DataAdviseHolder *)iface;
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
/*
* Perform a sanity check on the parameters.
*/
if ( (This==0) || (ppvObject==0) )
return E_INVALIDARG;
/*
* Initialize the return parameter.
*/
*ppvObject = 0;
/*
* Compare the riid with the interface IDs implemented by this object.
*/
if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
(memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0) )
{
*ppvObject = iface;
}
/*
* Check that we obtained an interface.
*/
if ((*ppvObject)==0)
{
return E_NOINTERFACE;
}
/*
* Query Interface always increases the reference count by one when it is
* successful.
*/
IUnknown_AddRef((IUnknown*)*ppvObject);
return S_OK;
}
/************************************************************************
* DataAdviseHolder_AddRef (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static ULONG WINAPI DataAdviseHolder_AddRef(
IDataAdviseHolder* iface)
{
DataAdviseHolder *This = (DataAdviseHolder *)iface;
TRACE("(%p) (ref=%ld)\n", This, This->ref);
return InterlockedIncrement(&This->ref);
}
/************************************************************************
* DataAdviseHolder_Release (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static ULONG WINAPI DataAdviseHolder_Release(
IDataAdviseHolder* iface)
{
DataAdviseHolder *This = (DataAdviseHolder *)iface;
ULONG ref;
TRACE("(%p) (ref=%ld)\n", This, This->ref);
/*
* Decrease the reference count on this object.
*/
ref = InterlockedDecrement(&This->ref);
/*
* If the reference count goes down to 0, perform suicide.
*/
if (ref==0) DataAdviseHolder_Destructor(This);
return ref;
}
/************************************************************************
* DataAdviseHolder_Advise
*
*/
static HRESULT WINAPI DataAdviseHolder_Advise(
IDataAdviseHolder* iface,
IDataObject* pDataObject,
FORMATETC* pFetc,
DWORD advf,
IAdviseSink* pAdvise,
DWORD* pdwConnection)
{
DWORD index;
DataAdviseHolder *This = (DataAdviseHolder *)iface;
TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
pAdvise, pdwConnection);
/*
* Sanity check
*/
if (pdwConnection==NULL)
return E_POINTER;
*pdwConnection = 0;
/*
* Find a free spot in the array.
*/
for (index = 0; index < This->maxCons; index++)
{
if (This->Connections[index].sink == NULL)
break;
}
/*
* If the array is full, we need to grow it.
*/
if (index == This->maxCons)
{
This->maxCons+=INITIAL_SINKS;
This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
This->Connections,
This->maxCons*sizeof(DataAdviseConnection));
}
/*
* Store the new sink
*/
This->Connections[index].sink = pAdvise;
memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
This->Connections[index].advf = advf;
if (This->Connections[index].sink != NULL) {
IAdviseSink_AddRef(This->Connections[index].sink);
if(advf & ADVF_PRIMEFIRST) {
DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
}
}
/*
* 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;
}
/******************************************************************************
* DataAdviseHolder_Unadvise
*/
static HRESULT WINAPI DataAdviseHolder_Unadvise(
IDataAdviseHolder* iface,
DWORD dwConnection)
{
DataAdviseHolder *This = (DataAdviseHolder *)iface;
TRACE("(%p)->(%lu)\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->maxCons)
return OLE_E_NOCONNECTION;
if (This->Connections[dwConnection].sink == NULL)
return OLE_E_NOCONNECTION;
/*
* Release the sink and mark the spot in the list as free.
*/
IAdviseSink_Release(This->Connections[dwConnection].sink);
memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
return S_OK;
}
static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
IDataAdviseHolder* iface,
IEnumSTATDATA** ppenumAdvise)
{
DataAdviseHolder *This = (DataAdviseHolder *)iface;
FIXME("(%p)->(%p)\n", This, ppenumAdvise);
return E_NOTIMPL;
}
/******************************************************************************
* DataAdviseHolder_SendOnDataChange
*/
static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
IDataAdviseHolder* iface,
IDataObject* pDataObject,
DWORD dwReserved,
DWORD advf)
{
DataAdviseHolder *This = (DataAdviseHolder *)iface;
DWORD index;
STGMEDIUM stg;
HRESULT res;
TRACE("(%p)->(%p,%08lx,%08lx)\n", This, pDataObject, dwReserved, advf);
for(index = 0; index < This->maxCons; index++) {
if(This->Connections[index].sink != NULL) {
if(!(This->Connections[index].advf & ADVF_NODATA)) {
TRACE("Calling IDataObject_GetData\n");
res = IDataObject_GetData(pDataObject,
&(This->Connections[index].fmat),
&stg);
TRACE("returns %08lx\n", res);
}
TRACE("Calling IAdviseSink_OnDataChange\n");
IAdviseSink_OnDataChange(This->Connections[index].sink,
&(This->Connections[index].fmat),
&stg);
TRACE("Done IAdviseSink_OnDataChange\n");
if(This->Connections[index].advf & ADVF_ONLYONCE) {
TRACE("Removing connection\n");
DataAdviseHolder_Unadvise(iface, index+1);
}
}
}
return S_OK;
}
/***********************************************************************
* API functions
*/
/***********************************************************************
* CreateOleAdviseHolder [OLE32.@]
*/
HRESULT WINAPI CreateOleAdviseHolder(
LPOLEADVISEHOLDER *ppOAHolder)
{
TRACE("(%p)\n", ppOAHolder);
/*
* Sanity check,
*/
if (ppOAHolder==NULL)
return E_POINTER;
*ppOAHolder = OleAdviseHolderImpl_Constructor ();
if (*ppOAHolder != NULL)
return S_OK;
return E_OUTOFMEMORY;
}
/******************************************************************************
* CreateDataAdviseHolder [OLE32.@]
*/
HRESULT WINAPI CreateDataAdviseHolder(
LPDATAADVISEHOLDER* ppDAHolder)
{
TRACE("(%p)\n", ppDAHolder);
/*
* Sanity check,
*/
if (ppDAHolder==NULL)
return E_POINTER;
*ppDAHolder = DataAdviseHolder_Constructor();
if (*ppDAHolder != NULL)
return S_OK;
return E_OUTOFMEMORY;
}