📄 autoobj.cpp
字号:
return AddSink(pv, pdwCookie);
}
//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::AddSink
//=--------------------------------------------------------------------------=
// in some cases, we'll already have done the QI, and won't need to do the
// work that is done in the Advise routine above. thus, these people can
// just call this instead. [this stems really from IQuickActivate]
//
// Parameters:
// void * - [in] the sink to add. it's already been addref'd
// DWORD * - [out] cookie
//
// Output:
// HRESULT
//
// Notes:
//
HRESULT CAutomationObjectWEvents::CConnectionPoint::AddSink
(
void *pv,
DWORD *pdwCookie
)
{
IUnknown **rgUnkNew;
// we optimize the case where there is only one sink to not allocate
// any storage. turns out very rarely is there more than one.
//
switch (m_cSinks) {
case 0:
ASSERT(!m_rgSinks, L"this should be null when there are no sinks");
m_rgSinks = (IUnknown **)pv;
break;
case 1:
// go ahead and do the initial allocation. we'll get 8 at a time
//
rgUnkNew = (IUnknown **)HeapAlloc(g_hHeap, 0, 8 * sizeof(IUnknown *));
RETURN_ON_NULLALLOC(rgUnkNew);
rgUnkNew[0] = (IUnknown *)m_rgSinks;
rgUnkNew[1] = (IUnknown *)pv;
m_rgSinks = rgUnkNew;
break;
default:
// if we're out of sinks, then we have to increase the size
// of the array
//
if (!(m_cSinks & 0x7)) {
rgUnkNew = (IUnknown **)HeapReAlloc(g_hHeap, 0, m_rgSinks, (m_cSinks + 8) * sizeof(IUnknown *));
RETURN_ON_NULLALLOC(rgUnkNew);
m_rgSinks = rgUnkNew;
} else
rgUnkNew = m_rgSinks;
rgUnkNew[m_cSinks] = (IUnknown *)pv;
break;
}
*pdwCookie = (DWORD)pv;
m_cSinks++;
return S_OK;
}
//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::Unadvise
//=--------------------------------------------------------------------------=
// they don't want to be told any more.
//
// Parameters:
// DWORD - [in] the cookie we gave 'em.
//
// Output:
// HRESULT
//
// Notes:
//
STDMETHODIMP CAutomationObjectWEvents::CConnectionPoint::Unadvise
(
DWORD dwCookie
)
{
IUnknown *pUnk;
int x;
if (!dwCookie)
return S_OK;
// see how many sinks we've currently got, and deal with things based
// on that.
//
switch (m_cSinks) {
case 1:
// it's the only sink. make sure the ptrs are the same, and
// then free things up
//
if ((DWORD)m_rgSinks != dwCookie)
return CONNECT_E_NOCONNECTION;
m_rgSinks = NULL;
break;
case 2:
// there are two sinks. go back down to one sink scenario
//
if ((DWORD)m_rgSinks[0] != dwCookie && (DWORD)m_rgSinks[1] != dwCookie)
return CONNECT_E_NOCONNECTION;
pUnk = ((DWORD)m_rgSinks[0] == dwCookie)
? m_rgSinks[1]
: ((DWORD)m_rgSinks[1] == dwCookie) ? m_rgSinks[0] : NULL;
if (!pUnk) return CONNECT_E_NOCONNECTION;
HeapFree(g_hHeap, 0, m_rgSinks);
m_rgSinks = (IUnknown **)pUnk;
break;
default:
// there are more than two sinks. just clean up the hole we've
// got in our array now.
//
for (x = 0; x < m_cSinks; x++) {
if ((DWORD)m_rgSinks[x] == dwCookie)
break;
}
if (x == m_cSinks) return CONNECT_E_NOCONNECTION;
if (x < m_cSinks - 1)
memcpy(&(m_rgSinks[x]), &(m_rgSinks[x + 1]), (m_cSinks -1 - x) * sizeof(IUnknown *));
else
m_rgSinks[x] = NULL;
break;
}
// we're happy
//
m_cSinks--;
((IUnknown *)dwCookie)->Release();
return S_OK;
}
//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::EnumConnections
//=--------------------------------------------------------------------------=
// enumerates all current connections
//
// Paramters:
// IEnumConnections ** - [out] new enumerator object
//
// Output:
// HRESULT
//
// NOtes:
//
STDMETHODIMP CAutomationObjectWEvents::CConnectionPoint::EnumConnections
(
IEnumConnections **ppEnumOut
)
{
CONNECTDATA *rgConnectData = NULL;
int i;
if (m_cSinks) {
// allocate some memory big enough to hold all of the sinks.
//
rgConnectData = (CONNECTDATA *)HeapAlloc(g_hHeap, 0, m_cSinks * sizeof(CONNECTDATA));
RETURN_ON_NULLALLOC(rgConnectData);
// fill in the array
//
if (m_cSinks == 1) {
rgConnectData[0].pUnk = (IUnknown *)m_rgSinks;
rgConnectData[0].dwCookie = (DWORD)m_rgSinks;
} else {
// loop through all available sinks.
//
for (i = 0; i < m_cSinks; i++) {
rgConnectData[i].pUnk = m_rgSinks[i];
rgConnectData[i].dwCookie = (DWORD)m_rgSinks[i];
}
}
}
// create yon enumerator object.
//
*ppEnumOut = (IEnumConnections *)(IEnumGeneric *)new CStandardEnum(IID_IEnumConnections,
m_cSinks, sizeof(CONNECTDATA), rgConnectData, CopyAndAddRefObject);
if (!*ppEnumOut) {
HeapFree(g_hHeap, 0, rgConnectData);
return E_OUTOFMEMORY;
}
return S_OK;
}
//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::~CConnectionPoint
//=--------------------------------------------------------------------------=
// cleans up
//
// Notes:
//
CAutomationObjectWEvents::CConnectionPoint::~CConnectionPoint ()
{
int x;
// clean up some memory stuff
//
if (!m_cSinks)
return;
else if (m_cSinks == 1)
((IUnknown *)m_rgSinks)->Release();
else {
for (x = 0; x < m_cSinks; x++)
QUICK_RELEASE(m_rgSinks[x]);
HeapFree(g_hHeap, 0, m_rgSinks);
}
}
//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPiont::DoInvoke
//=--------------------------------------------------------------------------=
// fires an event to all listening on our event interface.
//
// Parameters:
// DISPID - [in] event to fire.
// DISPPARAMS - [in]
//
// Notes:
//
void CAutomationObjectWEvents::CConnectionPoint::DoInvoke
(
DISPID dispid,
DISPPARAMS *pdispparams
)
{
int iConnection;
// if we don't have any sinks, then there's nothing to do. we intentionally
// ignore errors here.
//
if (m_cSinks == 0)
return;
else if (m_cSinks == 1)
((IDispatch *)m_rgSinks)->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
else
for (iConnection = 0; iConnection < m_cSinks; iConnection++)
((IDispatch *)m_rgSinks[iConnection])->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
}
//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::DoOnChanged
//=--------------------------------------------------------------------------=
// fires the OnChanged event for IPropertyNotifySink listeners.
//
// Parameters:
// DISPID - [in] dude that changed.
//
// Output:
// none
//
// Notes:
//
void CAutomationObjectWEvents::CConnectionPoint::DoOnChanged
(
DISPID dispid
)
{
int iConnection;
// if we don't have any sinks, then there's nothing to do.
//
if (m_cSinks == 0)
return;
else if (m_cSinks == 1)
((IPropertyNotifySink *)m_rgSinks)->OnChanged(dispid);
else
for (iConnection = 0; iConnection < m_cSinks; iConnection++)
((IPropertyNotifySink *)m_rgSinks[iConnection])->OnChanged(dispid);
}
//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::DoOnRequestEdit
//=--------------------------------------------------------------------------=
// fires the OnRequestEdit for IPropertyNotifySinkListeners
//
// Parameters:
// DISPID - [in] dispid user wants to change.
//
// Output:
// BOOL - false means you cant
//
// Notes:
//
BOOL CAutomationObjectWEvents::CConnectionPoint::DoOnRequestEdit
(
DISPID dispid
)
{
HRESULT hr;
int iConnection;
// if we don't have any sinks, then there's nothing to do.
//
if (m_cSinks == 0)
hr = S_OK;
else if (m_cSinks == 1)
hr =((IPropertyNotifySink *)m_rgSinks)->OnRequestEdit(dispid);
else {
for (iConnection = 0; iConnection < m_cSinks; iConnection++) {
hr = ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnRequestEdit(dispid);
if (hr != S_OK) break;
}
}
return (hr == S_OK) ? TRUE : FALSE;
}
//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::FireEvent
//=--------------------------------------------------------------------------=
// fires an event. handles arbitrary number of arguments.
//
// Parameters:
// EVENTINFO * - [in] struct that describes the event.
// ... - arguments to the event
//
// Output:
// none
//
// Notes:
// - use stdarg's va_* macros.
//
void __cdecl CAutomationObjectWEvents::FireEvent
(
EVENTINFO *pEventInfo,
...
)
{
va_list valist;
DISPPARAMS dispparams;
VARIANT rgvParameters[MAX_ARGS];
VARIANT *pv;
VARTYPE vt;
int iParameter;
int cbSize;
ASSERT(pEventInfo->cParameters <= MAX_ARGS, L"Don't support more than MAX_ARGS params. sorry.");
va_start(valist, pEventInfo);
// copy the Parameters into the rgvParameters array. make sure we reverse
// them for automation
//
pv = &(rgvParameters[pEventInfo->cParameters - 1]);
for (iParameter = 0; iParameter < pEventInfo->cParameters; iParameter++) {
vt = pEventInfo->rgTypes[iParameter];
// if it's a by value variant, then just copy the whole
// dang thing
//
if (vt == VT_VARIANT)
*pv = va_arg(valist, VARIANT);
else {
// copy the vt and the data value.
//
pv->vt = vt;
if (vt & VT_BYREF)
cbSize = sizeof(void *);
else
cbSize = g_rgcbDataTypeSize[vt];
// small optimization -- we can copy 2/4 bytes over quite
// quickly.
//
if (cbSize == sizeof(short))
V_I2(pv) = va_arg(valist, short);
else if (cbSize == 4)
V_I4(pv) = va_arg(valist, long);
else {
// copy over 8 bytes
//
ASSERT(cbSize == 8, L"don't recognize the type!!");
V_CY(pv) = va_arg(valist, CURRENCY);
}
}
pv--;
}
// fire the event
//
dispparams.rgvarg = rgvParameters;
dispparams.cArgs = pEventInfo->cParameters;
dispparams.rgdispidNamedArgs = NULL;
dispparams.cNamedArgs = 0;
m_cpEvents.DoInvoke(pEventInfo->dispid, &dispparams);
va_end(valist);
}
//=--------------------------------------------------------------------------=
// CopyAndAddRefObject
//=--------------------------------------------------------------------------=
// copies an object pointer, and then addref's the object.
//
// Parameters:
// void * - [in] dest.
// const void * - [in] src
// DWORD - [in] size, ignored, since it's always 4
//
// Notes:
//
void WINAPI CopyAndAddRefObject
(
void *pDest,
const void *pSource,
DWORD dwSize
)
{
ASSERT(pDest && pSource, L"Bogus Pointer(s) passed into CopyAndAddRefObject!!!!");
*((IUnknown **)pDest) = *((IUnknown **)pSource);
ADDREF_OBJECT(*((IUnknown **)pDest));
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -