|
|
//***************************************************************************
//
// File:
//
// Module: MS SNMP Provider
//
// Purpose:
//
// Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
/*
* SMIREVT.CPP * * Implemenation of a connection point object for the SMIR notify mechanism. * The methods/objects in this file are accessed by the SMIR API; the API * provides a user friendly interface to ISMIRNotify. */ #include <precomp.h>
#include "csmir.h"
#include "smir.h"
#include "handles.h"
#include "classfac.h"
#include <textdef.h>
#include "evtcons.h"
#ifdef ICECAP_PROFILE
#include <icapexp.h>
#endif
// scope guard
#include <autoptr.h>
extern CRITICAL_SECTION g_CriticalSection ;
/**********************************************************************************
* CSmirConnectionPoint * * Connectpoint implementation that supports the interface ISMIRNotify. * * CSmirConnObject::CSmirConnObject * CSmirConnObject::~CSmirConnObject ***********************************************************************************/ /*
* CSmirConnectionPoint::CSmirConnectionPoint * CSmirConnectionPoint::~CSmirConnectionPoint * * Parameters (Constructor): * pObj PCSmirConnObject of the object we're in. We can * query this for the IConnectionPointContainer * interface we might need. * riid REFIID of the interface we're supporting ***********************************************************************************/
CSmirConnectionPoint::CSmirConnectionPoint(PCSmirConnObject pObj, REFIID riid, CSmir *pSmir) { m_cRef=0; m_iid=riid; /*
* Our lifetime is controlled by the connectable object itself, * although other external clients will call AddRef and Release. * Since we're nested in the connectable object's lifetime, * there's no need to call AddRef on pObj. */ m_pObj=pObj; m_dwCookieNext=100; //Arbitrary starting cookie value
}
CSmirConnectionPoint::~CSmirConnectionPoint(void) { DWORD lKey = 0; LPUNKNOWN pItem = NULL; POSITION rNextPosition; for(rNextPosition=m_Connections.GetStartPosition();NULL!=rNextPosition;) { m_Connections.GetNextAssoc(rNextPosition, lKey, pItem ); pItem->Release(); } m_Connections.RemoveAll();
return; }
/*
* CSmirConnectionPoint::QueryInterface * CSmirConnectionPoint::AddRef * CSmirConnectionPoint::Release * * Purpose: * Non-delegating IUnknown members for CSmirConnectionPoint. */
STDMETHODIMP CSmirConnectionPoint::QueryInterface(REFIID riid , LPVOID *ppv) { *ppv=NULL;
if ((IID_IUnknown == riid) || (IID_IConnectionPoint == riid)|| (IID_ISMIR_Notify == riid)) *ppv=(LPVOID)this;
if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; }
return ResultFromScode(E_NOINTERFACE); }
STDMETHODIMP_(ULONG) CSmirConnectionPoint::AddRef(void) { return InterlockedIncrement(&m_cRef); }
STDMETHODIMP_(ULONG) CSmirConnectionPoint::Release(void) { long ret; if (0!=(ret=InterlockedDecrement(&m_cRef))) return ret;
delete this; return 0; }
/*
* CSmirConnectionPoint::GetConnectionInterface * * Purpose: * Returns the IID of the outgoing interface supported through * this connection point. * * Parameters: * pIID IID * in which to store the IID. */
STDMETHODIMP CSmirConnectionPoint::GetConnectionInterface(IID *pIID) { if (NULL==pIID) return ResultFromScode(E_POINTER);
*pIID=m_iid; return NOERROR; }
/*
* CSmirConnectionPoint::GetConnectionPointContainer * * Purpose: * Returns a pointer to the IConnectionPointContainer that * is manageing this connection point. * * Parameters: * ppCPC IConnectionPointContainer ** in which to return * the pointer after calling AddRef. */
STDMETHODIMP CSmirConnectionPoint::GetConnectionPointContainer (IConnectionPointContainer **ppCPC) { return m_pObj->QueryInterface(IID_IConnectionPointContainer , (void **)ppCPC); }
/*
* CSmirConnectionPoint::Advise * * Purpose: * Provides this connection point with a notification sink to * call whenever the appropriate outgoing function/event occurs. * * Parameters: * pUnkSink LPUNKNOWN to the sink to notify. The connection * point must QueryInterface on this pointer to obtain * the proper interface to call. The connection * point must also insure that any pointer held has * a reference count (QueryInterface will do it). * pdwCookie DWORD * in which to store the connection key for * later calls to Unadvise. */
STDMETHODIMP CSmirConnectionPoint::Advise(LPUNKNOWN pUnkSink , DWORD *pdwCookie) { *pdwCookie=0; if (NULL == pUnkSink) return E_POINTER;
/*
* Verify that the sink has the interface it's supposed * to. We don't have to know what it is because we have * m_iid to describe it. If this works, then we * have a pointer with an AddRef that we can save. */ IUnknown *pSink = NULL ; if (FAILED(pUnkSink->QueryInterface(m_iid, (PPVOID)&pSink))) { return CONNECT_E_CANNOTCONNECT; } //We got the sink, now store it.
*pdwCookie = InterlockedIncrement(&m_dwCookieNext);
m_Connections.SetAt(*pdwCookie,pSink); /*Add ref the smir to make sure that this stays in memory for the lifetime of the
*sink. The release is in unadvise. */ return S_OK; }
/*
* CSmirConnectionPoint::Unadvise * * Purpose: * Terminates the connection to the notification sink identified * with dwCookie (that was returned from Advise). The connection * point has to Release any held pointers for that sink. * * Parameters: * dwCookie DWORD connection key from Advise. */
STDMETHODIMP CSmirConnectionPoint::Unadvise(DWORD dwCookie) { //the only invalid cookie is 0
if (0==dwCookie) { //MyTraceEvent.Generate(__FILE__,__LINE__, "CSmirConnectionPoint::Unadvise E_INVALIDARG");
return E_UNEXPECTED; } LPUNKNOWN pSink = NULL; //stop anyone else unadvising with the same cookie
criticalSection.Lock () ; if(TRUE == m_Connections.Lookup(dwCookie,pSink)) { m_Connections.RemoveKey(dwCookie); //having removed the key the look up will fail so we can release the critical section
criticalSection.Unlock () ; pSink->Release(); /*release the smir. This could cause the smir to unload from memory! Do not do
*anything after this because we are (ultimatly) owned by the smir object */
return S_OK; } criticalSection.Unlock () ; return CONNECT_E_NOCONNECTION; } /*
* CSmirConnectionPoint::EnumConnections * * Purpose: * Creates and returns an enumerator object with the * IEnumConnections interface that will enumerate the IUnknown * pointers of each connected sink. * * Parameters: * ppEnum LPENUMCONNECTIONS in which to store the * IEnumConnections pointer. */
STDMETHODIMP CSmirConnectionPoint::EnumConnections(LPENUMCONNECTIONS *ppEnum) { LPCONNECTDATA pCD = NULL; PCEnumConnections pEnum = NULL;
//NULL the IN parameter
*ppEnum=NULL;
//check that we have some connections
if (0 == m_Connections.GetCount()) return ResultFromScode(OLE_E_NOCONNECTION);
/*
* Create the array of CONNECTDATA structures to give to the * enumerator. */ pCD=new CONNECTDATA[(UINT)m_Connections.GetCount()];
if (NULL==pCD) return ResultFromScode(E_OUTOFMEMORY);
wmilib::auto_buffer<CONNECTDATA> pCD_Guard ( pCD ) ;
DWORD lKey = 0; LPUNKNOWN pItem = NULL; POSITION rNextPosition; UINT j=0; for(rNextPosition=m_Connections.GetStartPosition();NULL!=rNextPosition;j++) { m_Connections.GetNextAssoc(rNextPosition, lKey, pItem ); pCD[j].pUnk=pItem; pCD[j].dwCookie=lKey; } /*
* If creation works, it makes a copy pCD, so we can * always delete it regardless of the outcome. */ pEnum=new CEnumConnections(this, m_Connections.GetCount(), pCD);
if (NULL==pEnum) return ResultFromScode(E_OUTOFMEMORY);
//This does an AddRef for us.
return pEnum->QueryInterface(IID_IEnumConnections, (PPVOID)ppEnum); }
//Connection Enumerator follows
/*
* CEnumConnections::CEnumConnections * CEnumConnections::~CEnumConnections * * Parameters (Constructor): * pUnkRef LPUNKNOWN to use for reference counting. * cConn ULONG number of connections in prgpConn * prgConnData LPCONNECTDATA to the array to enumerate. */
CEnumConnections::CEnumConnections(LPUNKNOWN pUnkRef, ULONG cConn , LPCONNECTDATA prgConnData) : m_rgConnData ( NULL ) { UINT i;
m_cRef=0; m_pUnkRef=pUnkRef;
m_iCur=0; m_cConn=cConn;
/*
* Copy the passed array. We need to do this because a clone * has to have its own copy as well. */ m_rgConnData=new CONNECTDATA[(UINT)cConn];
if (NULL!=m_rgConnData) { for (i=0; i < cConn; i++) { m_rgConnData[i]=prgConnData[i]; m_rgConnData[i].pUnk=prgConnData[i].pUnk; m_rgConnData[i].pUnk->AddRef(); } }
return; }
CEnumConnections::~CEnumConnections(void) { if (NULL!=m_rgConnData) { UINT i;
for (i=0; i < m_cConn; i++) m_rgConnData[i].pUnk->Release();
delete [] m_rgConnData; }
return; } /*
* CEnumConnections::QueryInterface * CEnumConnections::AddRef * CEnumConnections::Release * * Purpose: * IUnknown members for CEnumConnections object. */
STDMETHODIMP CEnumConnections::QueryInterface(REFIID riid , LPVOID *ppv) { *ppv=NULL;
if (IID_IUnknown==riid || IID_IEnumConnections==riid) *ppv=(LPVOID)this;
if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; }
return ResultFromScode(E_NOINTERFACE); }
STDMETHODIMP_(ULONG) CEnumConnections::AddRef(void) { InterlockedIncrement(&m_cRef); m_pUnkRef->AddRef(); return m_cRef; }
STDMETHODIMP_(ULONG) CEnumConnections::Release(void) { m_pUnkRef->Release();
long ret; if (0L!=(ret=InterlockedDecrement(&m_cRef))) return ret;
delete this; return 0; }
/*
* CEnumConnections::Next * * Purpose: * Returns the next element in the enumeration. * * Parameters: * cConn ULONG number of connections to return. * pConnData LPCONNECTDATA in which to store the returned * structures. * pulEnum ULONG * in which to return how many we * enumerated. * * Return Value: * HRESULT NOERROR if successful, S_FALSE otherwise, */
STDMETHODIMP CEnumConnections::Next(ULONG cConn , LPCONNECTDATA pConnData, ULONG *pulEnum) { ULONG cReturn=0L;
if (NULL==m_rgConnData) return ResultFromScode(S_FALSE);
if (NULL==pulEnum) { if (1L!=cConn) return ResultFromScode(E_POINTER); } else *pulEnum=0L;
if (NULL==pConnData || m_iCur >= m_cConn) return ResultFromScode(S_FALSE);
while (m_iCur < m_cConn && cConn > 0) { *pConnData++=m_rgConnData[m_iCur]; m_rgConnData[m_iCur++].pUnk->AddRef(); cReturn++; cConn--; }
if (NULL!=pulEnum) *pulEnum=cReturn;
return NOERROR; }
STDMETHODIMP CEnumConnections::Skip(ULONG cSkip) { if (((m_iCur+cSkip) >= m_cConn) || NULL==m_rgConnData) return ResultFromScode(S_FALSE);
m_iCur+=cSkip; return NOERROR; }
STDMETHODIMP CEnumConnections::Reset(void) { m_iCur=0; return NOERROR; }
STDMETHODIMP CEnumConnections::Clone(LPENUMCONNECTIONS *ppEnum) { PCEnumConnections pNew;
*ppEnum=NULL;
//Create the clone
pNew=new CEnumConnections(m_pUnkRef, m_cConn, m_rgConnData);
if (NULL==pNew) return ResultFromScode(E_OUTOFMEMORY);
pNew->AddRef(); pNew->m_iCur=m_iCur;
*ppEnum=pNew; return NOERROR; }
/**********************************************************************************
* CSmirConnObject * * Connectable Object implementation that supports the * interface ISMIRNotify. * * CSmirConnObject::CSmirConnObject * CSmirConnObject::~CSmirConnObject ***********************************************************************************/
CSmirConnObject::CSmirConnObject(CSmir *pSmir) : m_rgpConnPt ( NULL ) { // CSMIRClassFactory::objectsInProgress++;
m_cRef=0; //create SMIR_NUMBER_OF_CONNECTION_POINTS connection points
m_rgpConnPt = new CSmirConnectionPoint*[SMIR_NUMBER_OF_CONNECTION_POINTS]; for(int iLoop=0;iLoop<SMIR_NUMBER_OF_CONNECTION_POINTS;iLoop++) m_rgpConnPt[iLoop] = NULL;
try { Init(pSmir); } catch(...) { if (m_rgpConnPt) { //free the connection points
for(int iLoop=0;iLoop<SMIR_NUMBER_OF_CONNECTION_POINTS;iLoop++) { if (NULL!=m_rgpConnPt[iLoop]) { //release all of the connected objects
//while(m_rgpConnPt[iLoop]->Release());
m_rgpConnPt[iLoop]->Release(); } } //and delete the connection point
delete[] m_rgpConnPt; m_rgpConnPt = NULL; }
throw; } }
CSmirConnObject::~CSmirConnObject(void) { if (m_rgpConnPt) { //free the connection points
for(int iLoop=0;iLoop<SMIR_NUMBER_OF_CONNECTION_POINTS;iLoop++) { if (NULL!=m_rgpConnPt[iLoop]) { //release all of the connected objects
//while(m_rgpConnPt[iLoop]->Release());
m_rgpConnPt[iLoop]->Release(); } } //and delete the connection point
delete[] m_rgpConnPt; }
// CSMIRClassFactory::objectsInProgress--;
}
/*
* CSmirConnObject::Init * * Purpose: * Instantiates the interface implementations for this object. * * Parameters: * None * * Return Value: * BOOL TRUE if initialization succeeds, FALSE otherwise. */
BOOL CSmirConnObject::Init(CSmir *pSmir) { //Create our connection points
//the smir change CP
m_rgpConnPt[SMIR_NOTIFY_CONNECTION_POINT]= new CSmirNotifyCP(this, IID_ISMIR_Notify, pSmir); if (NULL==m_rgpConnPt[SMIR_NOTIFY_CONNECTION_POINT]) return FALSE;
m_rgpConnPt[SMIR_NOTIFY_CONNECTION_POINT]->AddRef();
return TRUE; } /*
* CSmirConnObject::QueryInterface * * Purpose: * Manages the interfaces for this object which supports the * IUnknown, ISampleOne, and ISampleTwo interfaces. * * Parameters: * riid REFIID of the interface to return. * ppv PPVOID in which to store the pointer. * * Return Value: * HRESULT NOERROR on success, E_NOINTERFACE if the * interface is not supported. */
STDMETHODIMP CSmirConnObject::QueryInterface(REFIID riid, PPVOID ppv) { if (ppv) *ppv = NULL; else return E_INVALIDARG;
if((IID_IConnectionPointContainer == riid)||(IID_ISMIR_Notify == riid)) *ppv = this; else return E_NOINTERFACE;
return S_OK; }
/*
* CSmirConnObject::AddRef * CSmirConnObject::Release * * Reference counting members. When Release sees a zero count * the object destroys itself. */
DWORD CSmirConnObject::AddRef(void) { return InterlockedIncrement(&m_cRef); }
DWORD CSmirConnObject::Release(void) { long ret; if (0!=(ret=InterlockedDecrement(&m_cRef))) { return ret; }
delete this; return 0; }
/*
* CSmirConnObject::EnumConnectionPoints * * Purpose: * Creates and returns an enumerator object with the * IEnumConnectionPoints interface that will enumerate the * individual connection points supported in this object. * * Parameters: * ppEnum LPENUMCONNECTIONPOINTS in which to store the * IEnumConnectionPoints pointer. * * Return Value: * HRESULT NOERROR on success, E_OUTOFMEMORY on failure or * other error code. */
STDMETHODIMP CSmirConnObject :: EnumConnectionPoints (LPENUMCONNECTIONPOINTS *ppEnum) { IConnectionPoint **rgCP = NULL ; CEnumConnectionPoints * pEnum = NULL ;
*ppEnum=NULL;
rgCP=(IConnectionPoint **)m_rgpConnPt;
//Create the enumerator: we have two connection points
pEnum=new CEnumConnectionPoints(this, SMIR_NUMBER_OF_CONNECTION_POINTS, rgCP);
if (NULL==pEnum) return ResultFromScode(E_OUTOFMEMORY);
pEnum->AddRef(); *ppEnum=pEnum; return NOERROR; }
/*
* CSmirConnObject::FindConnectionPoint * * Purpose: * Returns a pointer to the IConnectionPoint for a given * outgoing IID. * * Parameters: * riid REFIID of the outgoing interface for which * a connection point is desired. * ppCP IConnectionPoint ** in which to return * the pointer after calling AddRef. * * Return Value: * HRESULT NOERROR if the connection point is found, * E_NOINTERFACE if it's not supported. */
STDMETHODIMP CSmirConnObject::FindConnectionPoint(REFIID riid , IConnectionPoint **ppCP) { *ppCP=NULL; HRESULT result; if (IID_ISMIR_Notify==riid) { result = m_rgpConnPt[SMIR_NOTIFY_CONNECTION_POINT] ->QueryInterface(IID_IConnectionPoint, (PPVOID)ppCP); if (NULL != ppCP) return result; }
return ResultFromScode(E_NOINTERFACE); }
//Connection Point Enumerator follows
/*
* CEnumConnectionPoints::CEnumConnectionPoints * CEnumConnectionPoints::~CEnumConnectionPoints * * Parameters (Constructor): * pUnkRef LPUNKNOWN to use for reference counting. * cPoints ULONG number of connection points in prgpCP * rgpCP IConnectionPoint** to the array to enumerate. */
CEnumConnectionPoints::CEnumConnectionPoints(LPUNKNOWN pUnkRef , ULONG cPoints, IConnectionPoint **rgpCP) : m_rgpCP ( NULL ) { UINT i;
m_cRef=0; m_pUnkRef=pUnkRef;
m_iCur=0; m_cPoints=cPoints; m_rgpCP=new IConnectionPoint *[(UINT)cPoints];
if (NULL!=m_rgpCP) { for (i=0; i < cPoints; i++) { m_rgpCP[i]=rgpCP[i]; m_rgpCP[i]->AddRef(); } }
return; }
CEnumConnectionPoints::~CEnumConnectionPoints(void) { if (NULL!=m_rgpCP) { UINT i;
for (i=0; i < m_cPoints; i++) m_rgpCP[i]->Release();
delete [] m_rgpCP; }
return; }
/*
* CEnumConnectionPoints::QueryInterface * CEnumConnectionPoints::AddRef * CEnumConnectionPoints::Release * * Purpose: * IUnknown members for CEnumConnectionPoints object. */
STDMETHODIMP CEnumConnectionPoints::QueryInterface(REFIID riid , LPVOID *ppv) { *ppv=NULL;
if (IID_IUnknown==riid || IID_IEnumConnectionPoints==riid) *ppv=(LPVOID)this;
if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; }
return ResultFromScode(E_NOINTERFACE); }
STDMETHODIMP_(ULONG) CEnumConnectionPoints::AddRef(void) { InterlockedIncrement(&m_cRef); m_pUnkRef->AddRef(); return m_cRef; }
STDMETHODIMP_(ULONG) CEnumConnectionPoints::Release(void) { m_pUnkRef->Release();
long ret; if (0L!=(ret=InterlockedDecrement(&m_cRef))) return ret;
delete this; return 0; }
/*
* CEnumConnectionPoints::Next * * Purpose: * Returns the next element in the enumeration. * * Parameters: * cPoints ULONG number of connection points to return. * ppCP IConnectionPoint** in which to store the returned * pointers. * pulEnum ULONG * in which to return how many we * enumerated. * * Return Value: * HRESULT NOERROR if successful, S_FALSE otherwise, */
STDMETHODIMP CEnumConnectionPoints::Next(ULONG cPoints , IConnectionPoint **ppCP, ULONG *pulEnum) { ULONG cReturn=0L;
if (NULL==m_rgpCP) return ResultFromScode(S_FALSE);
if (NULL==ppCP) return ResultFromScode(E_POINTER);
if (NULL==pulEnum) { if (1L!=cPoints) return ResultFromScode(E_POINTER); } else *pulEnum=0L;
if (NULL==*ppCP || m_iCur >= m_cPoints) return ResultFromScode(S_FALSE);
while (m_iCur < m_cPoints && cPoints > 0) { *ppCP=m_rgpCP[m_iCur++];
if (NULL!=*ppCP) (*ppCP)->AddRef();
ppCP++; cReturn++; cPoints--; }
if (NULL!=pulEnum) *pulEnum=cReturn;
return NOERROR; }
STDMETHODIMP CEnumConnectionPoints::Skip(ULONG cSkip) { if (((m_iCur+cSkip) >= m_cPoints) || NULL==m_rgpCP) return ResultFromScode(S_FALSE);
m_iCur+=cSkip; return NOERROR; }
STDMETHODIMP CEnumConnectionPoints::Reset(void) { m_iCur=0; return NOERROR; }
STDMETHODIMP CEnumConnectionPoints::Clone (LPENUMCONNECTIONPOINTS *ppEnum) { PCEnumConnectionPoints pNew = NULL ;
*ppEnum=NULL;
//Create the clone
pNew=new CEnumConnectionPoints(m_pUnkRef, m_cPoints, m_rgpCP);
if (NULL==pNew) return ResultFromScode(E_OUTOFMEMORY);
pNew->AddRef(); pNew->m_iCur=m_iCur;
*ppEnum=pNew; return NOERROR; } /*
* CSmirEnumClassCP/CSmirNotifyCP:: * * Purpose: * Provides the notify connection point advise, unadvise constructor and destructor. * * Parameters: * pUnkSink LPUNKNOWN to the sink to notify. The connection * point must QueryInterface on this pointer to obtain * the proper interface to call. The connection * point must also insure that any pointer held has * a reference count (QueryInterface will do it). * pdwCookie DWORD * in which to store the connection key for * later calls to Unadvise. */
CSmirNotifyCP :: CSmirNotifyCP(PCSmirConnObject pCO, REFIID riid, CSmir *pSmir): CSmirConnectionPoint(pCO,riid,pSmir), m_evtConsumer (NULL) { // CSMIRClassFactory::objectsInProgress++;
m_bRegistered = FALSE; m_evtConsumer = new CSmirWbemEventConsumer(pSmir); void* tmp = NULL; if (FAILED(m_evtConsumer->QueryInterface(IID_ISMIR_WbemEventConsumer, &tmp))) { delete m_evtConsumer; m_evtConsumer = NULL; } }
CSmirNotifyCP :: ~CSmirNotifyCP() { if (NULL != m_evtConsumer) { m_evtConsumer->Release(); } // CSMIRClassFactory::objectsInProgress--;
}
/*
* CSmirConnObject::TriggerEvent * * Purpose: * Functions to make each connection point generate calls * to any connected sinks. Since these functions are specific * to IDuckEvents, they only deal with the connection point * for that one interface * * Parameters: * iEvent UINT of the event to trigger, either * EVENT_QUACK, EVENT_FLAP, or EVENT_PADDLE. * * Return Value: * BOOL TRUE events are triggered, FALSE if there * are no connected sinks. */
BOOL CSmirNotifyCP::TriggerEvent() { IEnumConnections *pEnum = NULL ; CONNECTDATA cd ;
if (FAILED(EnumConnections(&pEnum))) return FALSE;
while (NOERROR == pEnum->Next(1, &cd, NULL)) { //a promise fulfilled - Andrew Sinclair just in case anyone thinks otherwise!
ISMIRNotify *pJudith;
if (SUCCEEDED(cd.pUnk->QueryInterface(IID_ISMIR_Notify, (PPVOID)&pJudith))) { pJudith->ChangeNotify(); pJudith->Release(); }
cd.pUnk->Release(); }
pEnum->Release();
return TRUE; }
STDMETHODIMP CSmirNotifyCP::Advise(CSmir* pSmir, LPUNKNOWN pUnkSink , DWORD *pdwCookie) { if (NULL == m_evtConsumer) { return WBEM_E_FAILED; }
//if this is the first person to connect
if(m_Connections.IsEmpty()) { //register for WBEM Events for Smir Namespace changes
if (SUCCEEDED(m_evtConsumer->Register(pSmir))) { m_bRegistered = TRUE; } }
return CSmirConnectionPoint::Advise(pUnkSink, pdwCookie); }
STDMETHODIMP CSmirNotifyCP::Unadvise(CSmir* pSmir, DWORD dwCookie) { EnterCriticalSection ( & g_CriticalSection ) ;
HRESULT hr = CSmirConnectionPoint::Unadvise(dwCookie); IWbemServices *t_pServ = NULL;
if(S_OK== hr) { //if this is the last connection unregister for WBEM Events
if(m_Connections.IsEmpty()) { if (NULL == m_evtConsumer) { return WBEM_E_FAILED; } else if (m_bRegistered) { hr = m_evtConsumer->GetUnRegisterParams(&t_pServ); } } }
LeaveCriticalSection ( & g_CriticalSection ) ;
if (SUCCEEDED(hr) && (t_pServ != NULL)) { hr = m_evtConsumer->UnRegister(pSmir, t_pServ); t_pServ->Release(); t_pServ = NULL;
//guarantees only one query at a time with the event consumer (sink)....
EnterCriticalSection ( & g_CriticalSection ) ; m_bRegistered = FALSE; LeaveCriticalSection ( & g_CriticalSection ) ; }
return hr; }
|