Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1069 lines
25 KiB

//***************************************************************************
//
// Copyright (c) 1998-1999 Microsoft Corporation
//
// SINK.CPP
//
// rogerbo 21-May-98 Created.
//
// Defines the implementation of ISWbemSink
//
//***************************************************************************
#include "precomp.h"
#include "objsink.h"
#include <olectl.h>
#define NUM_ON_OBJECT_READY_ARGS 2
#define NUM_ON_CONNECTION_READY_ARGS 2
#define NUM_ON_COMPLETED_ARGS 3
#define NUM_ON_PROGRESS_ARGS 4
#define NUM_ON_OBJECT_PUT_ARGS 2
#define NUM_ON_OBJECT_SECURITY_READY_ARGS 2
#define SINKS_MAX 2
//***************************************************************************
//
// CSWbemSink::CSWbemSink
//
// DESCRIPTION:
//
// Constructor.
//
//***************************************************************************
CSWbemSink::CSWbemSink()
{
_RD(static char *me = "CSwbemSink::CSWbemSink";)
m_pPrivateSink = NULL;
m_nSinks = 0;
m_nMaxSinks = SINKS_MAX;
m_cRef=0;
m_Dispatch.SetObj(this, IID_ISWbemSink, CLSID_SWbemSink, L"SWbemSink");
_RPrint(me, "===============================================", 0, "");
_RPrint(me, "", 0, "");
// Allocate list of CWbemObjectSink
m_rgpCWbemObjectSink = (WbemObjectListEntry *)malloc(m_nMaxSinks * sizeof(WbemObjectListEntry));
if (m_rgpCWbemObjectSink)
{
for(int count = 0; count < m_nMaxSinks; count++)
{
m_rgpCWbemObjectSink[count].pWbemObjectWrapper = NULL;
m_rgpCWbemObjectSink[count].pServices = NULL;
}
}
// Initialize all the connection points to NULL
for(int count = 0; count < NUM_CONNECTION_POINTS; count++)
m_rgpConnPt[count] = NULL;
// Create our connection point
if (m_rgpConnPt[0] = new CConnectionPoint(this, DIID_ISWbemSinkEvents))
m_rgpConnPt[0]->AddRef();
// Additional connection points could be instantiated here
InterlockedIncrement(&g_cObj);
}
//***************************************************************************
//
// CSWbemSink::~CSWbemSink
//
// DESCRIPTION:
//
// Destructor.
//
//***************************************************************************
CSWbemSink::~CSWbemSink(void)
{
_RD(static char *me = "CSWbemSink::~CSWbemSink";)
_RPrint(me, "", 0, "");
if (m_pPrivateSink)
{
// Make sure we don't hook back to ourselves any more
// as this CSWbemSink is about to expire
m_pPrivateSink->Detach ();
// Release our hold on the private sink
m_pPrivateSink->Release ();
m_pPrivateSink = NULL;
}
for(int count = 0; count < NUM_CONNECTION_POINTS; count++)
if(m_rgpConnPt[count] != NULL)
delete m_rgpConnPt[count];
free(m_rgpCWbemObjectSink);
InterlockedDecrement(&g_cObj);
_RPrint(me, "After decrement count is", (long)g_cObj, "");
}
//***************************************************************************
// HRESULT CSWbemSink::QueryInterface
// long CSWbemSink::AddRef
// long CSWbemSink::Release
//
// DESCRIPTION:
//
// Standard Com IUNKNOWN functions.
//
//***************************************************************************
STDMETHODIMP CSWbemSink::QueryInterface (
IN REFIID riid,
OUT LPVOID *ppv
)
{
*ppv=NULL;
if (IID_IUnknown==riid)
*ppv = reinterpret_cast<IUnknown *>(this);
else if (IID_ISWbemSink==riid)
*ppv = (ISWbemSink *)this;
else if (IID_IDispatch==riid)
*ppv = (IDispatch *) this;
else if (IID_IConnectionPointContainer==riid)
*ppv = (IConnectionPointContainer *)this;
else if (IID_IProvideClassInfo==riid)
*ppv = (IProvideClassInfo *)this;
else if (IID_IProvideClassInfo2==riid)
*ppv = (IProvideClassInfo2 *)this;
// else if (IID_ISWbemPrivateSink==riid)
// *ppv = (ISWbemPrivateSink *)(&m_privateSink); // Private I/F counting
else if (IID_ISWbemPrivateSinkLocator==riid)
*ppv = (ISWbemPrivateSinkLocator *)this;
else if (IID_IObjectSafety==riid)
*ppv = (IObjectSafety *)this;
else if (IID_ISupportErrorInfo==riid)
*ppv = (ISupportErrorInfo *)this;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CSWbemSink::AddRef(void)
{
InterlockedIncrement(&m_cRef);
return m_cRef;
}
STDMETHODIMP_(ULONG) CSWbemSink::Release(void)
{
_RD(static char *me = "CSWbemSink::Release";)
/*
* If the only refs that are left are those from
* CWbemPrivateSink then initiate a cancel on all
* remaining sinks. This is because there are no
* client refs to CSWbemSinks left, therefore queries
* in progress can be of no use. First make sure we
* do an Unadvise for all the connection points.
*/
LONG cRef = InterlockedDecrement(&m_cRef);
if (0!=cRef)
{
_ASSERT(cRef > 0);
return cRef;
}
else
{
// We are about to blow away this SWbemSink, so
// make sure we clean up any orphaned IWbemObjectSink's
// by unadvising and cancelling the underlying WMI calls
if(m_pPrivateSink)
m_pPrivateSink->Detach();
if (m_rgpConnPt[0])
{
m_rgpConnPt[0]->UnadviseAll();
}
Cancel();
}
delete this;
return 0;
}
//***************************************************************************
// HRESULT CSWbemSink::InterfaceSupportsErrorInfo
//
// DESCRIPTION:
//
// Standard Com ISupportErrorInfo functions.
//
//***************************************************************************
STDMETHODIMP CSWbemSink::InterfaceSupportsErrorInfo (IN REFIID riid)
{
return (IID_ISWbemSink == riid) ? S_OK : S_FALSE;
}
HRESULT STDMETHODCALLTYPE CSWbemSink::Cancel()
{
_RD(static char *me = "CSWbemSink::Cancel";)
ResetLastErrors ();
if (!m_nSinks)
return S_OK;
_RPrint(me, "!!!Cancel called", 0, "");
/*
* Take a copy of the sinks, this can change under our feet
* As the Cancel can cause us to be re-entered. No need to
* take a copy of m_nMaxSinks as this isn't used when cancels
* are occuring.
* Make sure we AddRef the sink so that it can't be blown away
* under our feet by a re-entrant call to OnCompleted
*/
HRESULT hr = WBEM_E_FAILED;
int nSinks = m_nSinks;
WbemObjectListEntry *rgpCWbemObjectSink =
(WbemObjectListEntry *)malloc(nSinks * sizeof(WbemObjectListEntry));
if (!rgpCWbemObjectSink)
hr = WBEM_E_OUT_OF_MEMORY;
else
{
int actual = 0;
for (int i = 0; i < m_nMaxSinks; i++)
{
if (m_rgpCWbemObjectSink[i].pWbemObjectWrapper)
{
m_rgpCWbemObjectSink[i].pWbemObjectWrapper->AddRef();
if (m_rgpCWbemObjectSink[i].pServices)
m_rgpCWbemObjectSink[i].pServices->AddRef();
rgpCWbemObjectSink[actual++] = m_rgpCWbemObjectSink[i];
}
}
/*
* Now do the actual cancel
*/
for (i = 0; i < nSinks; i++) {
if (rgpCWbemObjectSink[i].pWbemObjectWrapper) {
IWbemObjectSink *pSink = NULL;
if (SUCCEEDED(rgpCWbemObjectSink[i].pWbemObjectWrapper->QueryInterface
(IID_IWbemObjectSink, (PPVOID)&pSink)))
{
if (rgpCWbemObjectSink[i].pServices)
rgpCWbemObjectSink[i].pServices->CancelAsyncCall(pSink);
pSink->Release();
}
rgpCWbemObjectSink[i].pWbemObjectWrapper->Release();
if (rgpCWbemObjectSink[i].pServices)
rgpCWbemObjectSink[i].pServices->Release();
}
}
free(rgpCWbemObjectSink);
hr = S_OK;
}
return hr;
}
HRESULT CSWbemSink::EnumConnectionPoints(IEnumConnectionPoints** ppEnum)
{
HRESULT hr = E_FAIL;
if (!ppEnum)
hr = E_POINTER;
else
{
CEnumConnectionPoints* pEnum = new CEnumConnectionPoints(reinterpret_cast<IUnknown*>(this), (void**)m_rgpConnPt);
if (!pEnum)
hr = E_OUTOFMEMORY;
else if (FAILED(hr = pEnum->QueryInterface(IID_IEnumConnectionPoints, (void**)ppEnum)))
delete pEnum;
}
return hr;
}
HRESULT CSWbemSink::FindConnectionPoint(REFIID riid, IConnectionPoint** ppCP)
{
HRESULT hr = E_FAIL;
if(riid == DIID_ISWbemSinkEvents)
{
if (!ppCP)
hr = E_POINTER;
else if (m_rgpConnPt [0])
hr = m_rgpConnPt[0]->QueryInterface(IID_IConnectionPoint, (void**)ppCP);
}
else
hr = E_NOINTERFACE;
return hr;
}
HRESULT CSWbemSink::GetClassInfo(ITypeInfo** pTypeInfo)
{
HRESULT hr = E_FAIL;
if (!pTypeInfo)
hr = E_POINTER;
else
{
CComPtr<ITypeLib> pTypeLib;
if (SUCCEEDED(LoadRegTypeLib(LIBID_WbemScripting, 1, 0, LANG_NEUTRAL, &pTypeLib)))
hr = pTypeLib->GetTypeInfoOfGuid(CLSID_SWbemSink, pTypeInfo);
}
return hr;
}
HRESULT CSWbemSink::GetGUID(DWORD dwGuidKind, GUID* pGUID)
{
if(pGUID == NULL)
return E_INVALIDARG;
*pGUID = DIID_ISWbemSinkEvents;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CSWbemSink::AddObjectSink(
/* [in] */ IUnknown __RPC_FAR *pSink,
/* [in] */ IWbemServices __RPC_FAR *pServices)
{
if(m_nSinks == m_nMaxSinks)
{
// Expand the size of the sink list
void *newList = realloc(m_rgpCWbemObjectSink,(m_nMaxSinks + SINKS_MAX) * sizeof(WbemObjectListEntry));
if (!newList) //realloc failed
return E_OUTOFMEMORY;
m_rgpCWbemObjectSink = (WbemObjectListEntry *)newList;
// Initialize new bit
for(int count = m_nMaxSinks; count < (m_nMaxSinks + SINKS_MAX); count++)
{
m_rgpCWbemObjectSink[count].pWbemObjectWrapper = NULL;
m_rgpCWbemObjectSink[count].pServices = NULL;
}
m_nMaxSinks += SINKS_MAX;
}
for(int count = 0; count < m_nMaxSinks; count++)
if(m_rgpCWbemObjectSink[count].pWbemObjectWrapper == NULL)
{
m_rgpCWbemObjectSink[count].pWbemObjectWrapper = pSink;
m_rgpCWbemObjectSink[count].pServices = pServices;
break;
}
m_nSinks++;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CSWbemSink::RemoveObjectSink(/* [in] */ IUnknown __RPC_FAR *pSink)
{
for(int count = 0; count < m_nMaxSinks; count++)
if(pSink == m_rgpCWbemObjectSink[count].pWbemObjectWrapper)
{
m_rgpCWbemObjectSink[count].pWbemObjectWrapper = NULL;
m_nSinks--;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CSWbemSink::OnObjectReady(
/* [in] */ IDispatch __RPC_FAR *pObject,
/* [in] */ IDispatch __RPC_FAR *pContext)
{
if (m_rgpConnPt[0])
{
m_rgpConnPt[0]->OnObjectReady(pObject, pContext);
}
else
{
return E_FAIL;
}
return 0;
}
HRESULT STDMETHODCALLTYPE CSWbemSink::OnCompleted(
/* [in] */ HRESULT hResult,
/* [in] */ IDispatch __RPC_FAR *path,
/* [in] */ IDispatch __RPC_FAR *pErrorObject,
/* [in] */ IDispatch __RPC_FAR *pContext)
{
if (m_rgpConnPt[0])
{
m_rgpConnPt[0]->OnCompleted(hResult, pErrorObject, path, pContext);
}
else
{
return E_FAIL;
}
return 0;
}
HRESULT STDMETHODCALLTYPE CSWbemSink::OnProgress(
/* [in] */ long upperBound,
/* [in] */ long current,
/* [in] */ BSTR message,
/* [in] */ IDispatch __RPC_FAR *pContext)
{
if (m_rgpConnPt[0])
{
m_rgpConnPt[0]->OnProgress(upperBound, current, message, pContext);
}
else
{
return E_FAIL;
}
return 0;
}
HRESULT STDMETHODCALLTYPE CSWbemSink::GetPrivateSink(
/* [out] */ IUnknown **objWbemPrivateSink)
{
HRESULT hr = E_FAIL;
if (objWbemPrivateSink)
{
if(!m_pPrivateSink)
{
if (m_pPrivateSink = new CSWbemPrivateSink(this))
m_pPrivateSink->AddRef (); // Released in destructor
}
if (m_pPrivateSink)
hr = m_pPrivateSink->QueryInterface(IID_IUnknown, (PPVOID)objWbemPrivateSink);
}
else
hr = E_POINTER;
return hr;
}
// void** rpgCP is used so that this constructor can accept either CConnectionPoint**
// from CSWbemSink::EnumConnectionPoints or IConnectionPoint** from CEnumConnectionPoints::Clone
// This could also be done by overloading the constructor and duplicating some of this code
CEnumConnectionPoints::CEnumConnectionPoints(IUnknown* pUnkRef, void** rgpCP) : m_cRef(0)
{
m_iCur = 0;
m_pUnkRef = pUnkRef;
// m_rgpCP is a pointer to an array of IConnectionPoints or CConnectionPoints
for(int count = 0; count < NUM_CONNECTION_POINTS; count++)
((IUnknown*)rgpCP[count])->QueryInterface(IID_IConnectionPoint, (void**)&m_rgpCP[count]);
InterlockedIncrement(&g_cObj);
}
CEnumConnectionPoints::~CEnumConnectionPoints()
{
if(m_rgpCP != NULL)
for(int count = 0; count < NUM_CONNECTION_POINTS; count++)
m_rgpCP[count]->Release();
InterlockedDecrement(&g_cObj);
}
ULONG CEnumConnectionPoints::AddRef()
{
m_pUnkRef->AddRef();
return ++m_cRef;
}
ULONG CEnumConnectionPoints::Release()
{
m_pUnkRef->Release();
LONG cRef = InterlockedDecrement(&m_cRef);
if(cRef != 0)
{
_ASSERT(cRef > 0);
return cRef;
}
delete this;
return 0;
}
HRESULT CEnumConnectionPoints::QueryInterface(REFIID riid, void** ppv)
{
if(riid == IID_IUnknown || riid == IID_IEnumConnectionPoints)
*ppv = (IEnumConnectionPoints*)this;
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
HRESULT CEnumConnectionPoints::Next(ULONG cConnections, IConnectionPoint** rgpcn, ULONG* pcFetched)
{
if(rgpcn == NULL)
return E_POINTER;
if(pcFetched == NULL && cConnections != 1)
return E_INVALIDARG;
if(pcFetched != NULL)
*pcFetched = 0;
while(m_iCur < NUM_CONNECTION_POINTS && cConnections > 0)
{
*rgpcn = m_rgpCP[m_iCur++];
if(*rgpcn != NULL)
(*rgpcn)->AddRef();
if(pcFetched != NULL)
(*pcFetched)++;
cConnections--;
rgpcn++;
}
return S_OK;
}
HRESULT CEnumConnectionPoints::Skip(ULONG cConnections)
{
if(m_iCur + cConnections >= NUM_CONNECTION_POINTS)
return S_FALSE;
m_iCur += cConnections;
return S_OK;
}
HRESULT CEnumConnectionPoints::Reset()
{
m_iCur = 0;
return S_OK;
}
HRESULT CEnumConnectionPoints::Clone(IEnumConnectionPoints** ppEnum)
{
if(ppEnum == NULL)
return E_POINTER;
*ppEnum = NULL;
// Create the clone
CEnumConnectionPoints* pNew = new CEnumConnectionPoints(m_pUnkRef, (void**)m_rgpCP);
if(pNew == NULL)
return E_OUTOFMEMORY;
pNew->AddRef();
pNew->m_iCur = m_iCur;
*ppEnum = pNew;
return S_OK;
}
CConnectionPoint::CConnectionPoint(CSWbemSink* pObj, REFIID riid) :
m_cRef(0),
m_rgnCookies(NULL),
m_rgpUnknown(NULL)
{
m_iid = riid;
m_nMaxConnections = CCONNMAX;
m_rgnCookies = (unsigned *)malloc(m_nMaxConnections * sizeof(unsigned));
m_rgpUnknown = (IUnknown **)malloc(m_nMaxConnections * sizeof(IUnknown *));
// Don't need AddRef/Release since we are nested inside CSWbemSink
m_pObj = pObj;
for(int count = 0; count < m_nMaxConnections; count++)
{
if (m_rgpUnknown)
m_rgpUnknown[count] = NULL;
if (m_rgnCookies)
m_rgnCookies[count] = 0;
}
m_cConn = 0;
m_nCookieNext = 10; // Arbitrary starting cookie value
InterlockedIncrement(&g_cObj);
}
CConnectionPoint::~CConnectionPoint()
{
if (m_rgpUnknown)
{
for(int count = 0; count < m_nMaxConnections; count++)
if(m_rgpUnknown[count] != NULL)
{
m_rgpUnknown[count]->Release();
m_rgpUnknown[count] = NULL;
}
free(m_rgpUnknown);
}
if (m_rgnCookies)
free(m_rgnCookies);
InterlockedDecrement(&g_cObj);
}
HRESULT CConnectionPoint::QueryInterface(REFIID riid, void** ppv)
{
if(IID_IUnknown == riid || IID_IConnectionPoint == riid)
*ppv = (IConnectionPoint*)this;
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG CConnectionPoint::AddRef()
{
return ++m_cRef;
}
ULONG CConnectionPoint::Release()
{
LONG cRef = InterlockedDecrement(&m_cRef);
if(cRef != 0)
{
_ASSERT(cRef > 0);
return cRef;
}
delete this;
return 0;
}
HRESULT CConnectionPoint::GetConnectionInterface(IID *pIID)
{
if(pIID == NULL)
return E_POINTER;
*pIID = m_iid;
return S_OK;
}
HRESULT CConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer** ppCPC)
{
return m_pObj->QueryInterface(IID_IConnectionPointContainer, (void**)ppCPC);
}
HRESULT CConnectionPoint::Advise(IUnknown* pUnknownSink, DWORD* pdwCookie)
{
IUnknown* pSink;
*pdwCookie = 0;
_RD(static char *me = "CConnectionPoint::Advise";)
_RPrint(me, "Current connections (before adjustment): ", (long)m_cConn, "");
if(m_cConn == m_nMaxConnections)
{
//return CONNECT_E_ADVISELIMIT;
// Expand the size of the connection lists
void *tempMem = realloc(m_rgnCookies, (m_nMaxConnections + CCONNMAX) * sizeof(unsigned));
if (!tempMem) //realloc failed
return E_OUTOFMEMORY;
m_rgnCookies = (unsigned *)tempMem;
tempMem = realloc(m_rgpUnknown, (m_nMaxConnections + CCONNMAX) * sizeof(IUnknown *));
if (!tempMem)
return E_OUTOFMEMORY;
m_rgpUnknown = (IUnknown **)tempMem;
// Initialize new bit
for(int count = m_nMaxConnections; count < (m_nMaxConnections + CCONNMAX); count++)
{
m_rgpUnknown[count] = NULL;
m_rgnCookies[count] = 0;
}
m_nMaxConnections += CCONNMAX;
}
if(FAILED(pUnknownSink->QueryInterface(m_iid, (void**)&pSink)))
return CONNECT_E_CANNOTCONNECT;
for(int count = 0; count < m_nMaxConnections; count++)
if(m_rgpUnknown[count] == NULL)
{
m_rgpUnknown[count] = pSink;
m_rgnCookies[count] = ++m_nCookieNext;
*pdwCookie = m_nCookieNext;
break;
}
m_cConn++;
return NOERROR;
}
HRESULT CConnectionPoint::Unadvise(DWORD dwCookie)
{
_RD(static char *me = "CConnectionPoint::Unadvise";)
_RPrint(me, "Current connections (before adjustment): ", (long)m_cConn, "");
if(dwCookie == 0)
return E_INVALIDARG;
for(int count = 0; count < m_nMaxConnections; count++)
if(dwCookie == m_rgnCookies[count])
{
if(m_rgpUnknown[count] != NULL)
{
m_rgpUnknown[count]->Release();
m_rgpUnknown[count] = NULL;
m_rgnCookies[count] = 0;
}
m_cConn--;
return NOERROR;
}
return CONNECT_E_NOCONNECTION;
}
HRESULT CConnectionPoint::EnumConnections(IEnumConnections** ppEnum)
{
HRESULT hr = E_FAIL;
if (!ppEnum)
hr = E_POINTER;
else
{
*ppEnum = NULL;
CONNECTDATA* pCD = new CONNECTDATA[m_cConn];
if (!pCD)
hr = E_OUTOFMEMORY;
else
{
for(int count1 = 0, count2 = 0; count1 < m_nMaxConnections; count1++)
if(m_rgpUnknown[count1] != NULL)
{
pCD[count2].pUnk = (IUnknown*)m_rgpUnknown[count1];
pCD[count2].dwCookie = m_rgnCookies[count1];
count2++;
}
CEnumConnections* pEnum = new CEnumConnections(this, m_cConn, pCD);
delete [] pCD;
if (!pEnum)
hr = E_OUTOFMEMORY;
else
hr = pEnum->QueryInterface(IID_IEnumConnections, (void**)ppEnum);
}
}
return hr;
}
void CConnectionPoint::UnadviseAll() {
_RD(static char *me = "CConnectionPoint::UnadviseAll";)
_RPrint(me, "Current connections (before adjustment): ", (long)m_cConn, "");
for(int count = 0; count < m_nMaxConnections; count++) {
if(m_rgpUnknown[count] != NULL)
{
m_rgpUnknown[count]->Release();
m_rgpUnknown[count] = NULL;
m_rgnCookies[count] = 0;
m_cConn--;
}
}
_RPrint(me, "Current connections (after adjustment): ", (long)m_cConn, "");
}
void CConnectionPoint::OnObjectReady(
/* [in] */ IDispatch __RPC_FAR *pObject,
/* [in] */ IDispatch __RPC_FAR *pAsyncContext)
{
HRESULT hr = S_OK;
LPDISPATCH pdisp = NULL;
for(int i = 0; i < m_nMaxConnections; i++)
{
if(m_rgpUnknown[i])
{
if (SUCCEEDED(hr = m_rgpUnknown[i]->QueryInterface(IID_IDispatch, (PPVOID)&pdisp)))
{
DISPPARAMS dispparams;
VARIANTARG args[NUM_ON_OBJECT_READY_ARGS];
VARIANTARG *pArg = args;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = NUM_ON_OBJECT_READY_ARGS;
dispparams.rgvarg = args;
VariantInit(pArg);
pArg->vt = VT_DISPATCH;
pArg->pdispVal = pAsyncContext;
pArg++;
VariantInit(pArg);
pArg->vt = VT_DISPATCH;
pArg->pdispVal = pObject;
hr = pdisp->Invoke(WBEMS_DISPID_OBJECT_READY, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
pdisp->Release();
}
}
}
}
void CConnectionPoint::OnCompleted(
/* [in] */ HRESULT hResult,
/* [in] */ IDispatch __RPC_FAR *path,
/* [in] */ IDispatch __RPC_FAR *pErrorObject,
/* [in] */ IDispatch __RPC_FAR *pAsyncContext)
{
HRESULT hr = S_OK;
LPDISPATCH pdisp = NULL;
for(int i = 0; i < m_nMaxConnections; i++)
{
if(m_rgpUnknown[i])
{
if (SUCCEEDED(hr = m_rgpUnknown[i]->QueryInterface(IID_IDispatch, (PPVOID)&pdisp)))
{
VARIANTARG *pArg;
if (path)
{
DISPPARAMS putDispparams;
VARIANTARG putArgs[NUM_ON_OBJECT_PUT_ARGS];
memset(&putDispparams, 0, sizeof putDispparams);
putDispparams.cArgs = NUM_ON_OBJECT_PUT_ARGS;
putDispparams.rgvarg = pArg = putArgs;
VariantInit(pArg);
pArg->vt = VT_DISPATCH;
pArg->pdispVal = pAsyncContext;
pArg++;
VariantInit(pArg);
pArg->vt = VT_DISPATCH;
pArg->pdispVal = path;
hr = pdisp->Invoke(WBEMS_DISPID_OBJECT_PUT, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, &putDispparams, NULL, NULL, NULL);
}
DISPPARAMS dispparams;
VARIANTARG args[NUM_ON_COMPLETED_ARGS];
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = NUM_ON_COMPLETED_ARGS;
dispparams.rgvarg = pArg = args;
VariantInit(pArg);
pArg->vt = VT_DISPATCH;
pArg->pdispVal = pAsyncContext;
pArg++;
VariantInit(pArg);
pArg->vt = VT_DISPATCH;
pArg->pdispVal = pErrorObject;
pArg++;
VariantInit(pArg);
pArg->vt = VT_I4;
pArg->lVal = (long)hResult;
hr = pdisp->Invoke(WBEMS_DISPID_COMPLETED, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
pdisp->Release();
}
}
}
}
void CConnectionPoint::OnProgress(
/* [in] */ long upperBound,
/* [in] */ long current,
/* [in] */ BSTR message,
/* [in] */ IDispatch __RPC_FAR *pAsyncContext)
{
HRESULT hr = S_OK;
LPDISPATCH pdisp = NULL;
for(int i = 0; i < m_nMaxConnections; i++)
{
if(m_rgpUnknown[i])
{
if (SUCCEEDED(hr = m_rgpUnknown[i]->QueryInterface(IID_IDispatch, (PPVOID)&pdisp)))
{
DISPPARAMS dispparams;
VARIANTARG args[NUM_ON_PROGRESS_ARGS];
VARIANTARG *pArg = args;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = NUM_ON_PROGRESS_ARGS;
dispparams.rgvarg = args;
VariantInit(pArg);
pArg->vt = VT_DISPATCH;
pArg->pdispVal = (IDispatch FAR *)pAsyncContext;
pArg++;
VariantInit(pArg);
pArg->vt = VT_BSTR;
pArg->bstrVal = message;
pArg++;
VariantInit(pArg);
pArg->vt = VT_I4;
pArg->lVal = current;
pArg++;
VariantInit(pArg);
pArg->vt = VT_I4;
pArg->lVal = upperBound;
hr = pdisp->Invoke(WBEMS_DISPID_PROGRESS, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
pdisp->Release();
}
}
}
}
CEnumConnections::CEnumConnections(IUnknown* pUnknown, int cConn, CONNECTDATA* pConnData) : m_cRef(0)
{
m_pUnkRef = pUnknown;
m_iCur = 0;
m_cConn = cConn;
m_rgConnData = new CONNECTDATA[cConn];
if(m_rgConnData != NULL)
for(int count = 0; count < cConn; count++)
{
m_rgConnData[count] = pConnData[count];
m_rgConnData[count].pUnk->AddRef();
}
InterlockedIncrement(&g_cObj);
}
CEnumConnections::~CEnumConnections()
{
if(m_rgConnData != NULL)
{
for(unsigned count = 0; count < m_cConn; count++)
m_rgConnData[count].pUnk->Release();
delete [] m_rgConnData;
}
InterlockedDecrement(&g_cObj);
}
HRESULT CEnumConnections::Next(ULONG cConnections, CONNECTDATA* rgpcd, ULONG* pcFetched)
{
if(pcFetched == NULL && cConnections != 1)
return E_INVALIDARG;
if(pcFetched != NULL)
*pcFetched = 0;
if(rgpcd == NULL || m_iCur >= m_cConn)
return S_FALSE;
unsigned cReturn = 0;
while(m_iCur < m_cConn && cConnections > 0)
{
*rgpcd++ = m_rgConnData[m_iCur];
m_rgConnData[m_iCur++].pUnk->AddRef();
cReturn++;
cConnections--;
}
if(pcFetched != NULL)
*pcFetched = cReturn;
return S_OK;
}
HRESULT CEnumConnections::Skip(ULONG cConnections)
{
if(m_iCur + cConnections >= m_cConn)
return S_FALSE;
m_iCur += cConnections;
return S_OK;
}
HRESULT CEnumConnections::Reset()
{
m_iCur = 0;
return S_OK;
}
HRESULT CEnumConnections::Clone(IEnumConnections** ppEnum)
{
if(ppEnum == NULL)
return E_POINTER;
*ppEnum = NULL;
// Create the clone
CEnumConnections* pNew = new CEnumConnections(m_pUnkRef, m_cConn, m_rgConnData);
if(NULL == pNew)
return E_OUTOFMEMORY;
pNew->AddRef();
pNew->m_iCur = m_iCur;
*ppEnum = pNew;
return S_OK;
}
HRESULT CEnumConnections::QueryInterface(REFIID riid, void** ppv)
{
if(IID_IUnknown == riid || IID_IEnumConnections == riid)
*ppv = (IEnumConnections*)this;
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG CEnumConnections::AddRef()
{
return ++m_cRef;
}
ULONG CEnumConnections::Release()
{
LONG cRef = InterlockedDecrement(&m_cRef);
if(cRef != 0)
{
_ASSERT(cRef > 0);
return cRef;
}
delete this;
return 0;
}