📄 connpt.c
字号:
/*
* Implementation of a generic ConnectionPoint object.
*
* Copyright 2000 Huw D M Davies for CodeWeavers
*
* 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
*
* NOTES:
* See one exported function here is CreateConnectionPoint, see
* comments just above that function for information.
*/
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#define COBJMACROS
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "ole2.h"
#include "olectl.h"
#include "connpt.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
#define MAXSINKS 10
/************************************************************************
* Implementation of IConnectionPoint
*/
typedef struct ConnectionPointImpl {
const IConnectionPointVtbl *lpvtbl;
/* IUnknown of our main object*/
IUnknown *Obj;
/* Reference count */
LONG ref;
/* IID of sink interface */
IID iid;
/* Array of sink IUnknowns */
IUnknown **sinks;
DWORD maxSinks;
DWORD nSinks;
} ConnectionPointImpl;
static const IConnectionPointVtbl ConnectionPointImpl_VTable;
/************************************************************************
* Implementation of IEnumConnections
*/
typedef struct EnumConnectionsImpl {
const IEnumConnectionsVtbl *lpvtbl;
LONG ref;
/* IUnknown of ConnectionPoint, used for ref counting */
IUnknown *pUnk;
/* Connection Data */
CONNECTDATA *pCD;
DWORD nConns;
/* Next connection to enumerate from */
DWORD nCur;
} EnumConnectionsImpl;
static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
DWORD nSinks,
CONNECTDATA *pCD);
/************************************************************************
* ConnectionPointImpl_Construct
*/
static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
REFIID riid)
{
ConnectionPointImpl *Obj;
Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
Obj->lpvtbl = &ConnectionPointImpl_VTable;
Obj->Obj = pUnk;
Obj->ref = 1;
Obj->iid = *riid;
Obj->maxSinks = MAXSINKS;
Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(IUnknown*) * MAXSINKS);
Obj->nSinks = 0;
return Obj;
}
/************************************************************************
* ConnectionPointImpl_Destroy
*/
static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
{
DWORD i;
for(i = 0; i < Obj->maxSinks; i++) {
if(Obj->sinks[i]) {
IUnknown_Release(Obj->sinks[i]);
Obj->sinks[i] = NULL;
}
}
HeapFree(GetProcessHeap(), 0, Obj->sinks);
HeapFree(GetProcessHeap(), 0, Obj);
return;
}
static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
/************************************************************************
* ConnectionPointImpl_QueryInterface (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
IConnectionPoint* iface,
REFIID riid,
void** ppvObject)
{
ConnectionPointImpl *This = (ConnectionPointImpl *)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 (IsEqualIID(&IID_IUnknown, riid))
*ppvObject = (IConnectionPoint*)This;
else if (IsEqualIID(&IID_IConnectionPoint, riid))
*ppvObject = (IConnectionPoint*)This;
/*
* Check that we obtained an interface.
*/
if ((*ppvObject)==0)
{
FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
return E_NOINTERFACE;
}
/*
* Query Interface always increases the reference count by one when it is
* successful
*/
ConnectionPointImpl_AddRef((IConnectionPoint*)This);
return S_OK;
}
/************************************************************************
* ConnectionPointImpl_AddRef (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
{
ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
return refCount;
}
/************************************************************************
* ConnectionPointImpl_Release (IUnknown)
*
* See Windows documentation for more details on IUnknown methods.
*/
static ULONG WINAPI ConnectionPointImpl_Release(
IConnectionPoint* iface)
{
ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
ULONG refCount = InterlockedDecrement(&This->ref);
TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
/*
* If the reference count goes down to 0, perform suicide.
*/
if (!refCount) ConnectionPointImpl_Destroy(This);
return refCount;
}
/************************************************************************
* ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
*
*/
static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
IConnectionPoint *iface,
IID *piid)
{
ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
*piid = This->iid;
return S_OK;
}
/************************************************************************
* ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
*
*/
static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
IConnectionPoint *iface,
IConnectionPointContainer **ppCPC)
{
ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
TRACE("(%p)->(%p)\n", This, ppCPC);
return IUnknown_QueryInterface(This->Obj,
&IID_IConnectionPointContainer,
(LPVOID)ppCPC);
}
/************************************************************************
* ConnectionPointImpl_Advise (IConnectionPoint)
*
*/
static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
IUnknown *lpUnk,
DWORD *pdwCookie)
{
DWORD i;
ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
IUnknown *lpSink;
TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
*pdwCookie = 0;
if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
return CONNECT_E_CANNOTCONNECT;
for(i = 0; i < This->maxSinks; i++) {
if(This->sinks[i] == NULL)
break;
}
if(i == This->maxSinks) {
This->maxSinks += MAXSINKS;
This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
This->maxSinks * sizeof(IUnknown *));
}
This->sinks[i] = lpSink;
This->nSinks++;
*pdwCookie = i + 1;
return S_OK;
}
/************************************************************************
* ConnectionPointImpl_Unadvise (IConnectionPoint)
*
*/
static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
DWORD dwCookie)
{
ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
TRACE("(%p)->(%d)\n", This, dwCookie);
if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
IUnknown_Release(This->sinks[dwCookie-1]);
This->sinks[dwCookie-1] = NULL;
This->nSinks--;
return S_OK;
}
/************************************************************************
* ConnectionPointImpl_EnumConnections (IConnectionPoint)
*
*/
static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
IConnectionPoint *iface,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -