Source code of Windows XP (NT5)
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.

1036 lines
24 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1998-1999 Microsoft Corporation
  4. //
  5. // SINK.CPP
  6. //
  7. // rogerbo 21-May-98 Created.
  8. //
  9. // Defines the implementation of ISWbemSink
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. #include "objsink.h"
  14. #include <olectl.h>
  15. #define NUM_ON_OBJECT_READY_ARGS 2
  16. #define NUM_ON_CONNECTION_READY_ARGS 2
  17. #define NUM_ON_COMPLETED_ARGS 3
  18. #define NUM_ON_PROGRESS_ARGS 4
  19. #define NUM_ON_OBJECT_PUT_ARGS 2
  20. #define NUM_ON_OBJECT_SECURITY_READY_ARGS 2
  21. #define SINKS_MAX 2
  22. //***************************************************************************
  23. //
  24. // CSWbemSink::CSWbemSink
  25. //
  26. // DESCRIPTION:
  27. //
  28. // Constructor.
  29. //
  30. //***************************************************************************
  31. CSWbemSink::CSWbemSink()
  32. {
  33. _RD(static char *me = "CSwbemSink::CSWbemSink";)
  34. m_pPrivateSink = NULL;
  35. m_nSinks = 0;
  36. m_nMaxSinks = SINKS_MAX;
  37. m_cRef=0;
  38. m_Dispatch.SetObj(this, IID_ISWbemSink, CLSID_SWbemSink, L"SWbemSink");
  39. _RPrint(me, "===============================================", 0, "");
  40. _RPrint(me, "", 0, "");
  41. // Allocate list of CWbemObjectSink
  42. m_rgpCWbemObjectSink = (WbemObjectListEntry *)malloc(m_nMaxSinks * sizeof(WbemObjectListEntry));
  43. if (m_rgpCWbemObjectSink)
  44. {
  45. for(int count = 0; count < m_nMaxSinks; count++)
  46. {
  47. m_rgpCWbemObjectSink[count].pWbemObjectWrapper = NULL;
  48. m_rgpCWbemObjectSink[count].pServices = NULL;
  49. }
  50. }
  51. // Initialize all the connection points to NULL
  52. for(int count = 0; count < NUM_CONNECTION_POINTS; count++)
  53. m_rgpConnPt[count] = NULL;
  54. // Create our connection point
  55. if (m_rgpConnPt[0] = new CConnectionPoint(this, DIID_ISWbemSinkEvents))
  56. m_rgpConnPt[0]->AddRef();
  57. // Additional connection points could be instantiated here
  58. InterlockedIncrement(&g_cObj);
  59. }
  60. //***************************************************************************
  61. //
  62. // CSWbemSink::~CSWbemSink
  63. //
  64. // DESCRIPTION:
  65. //
  66. // Destructor.
  67. //
  68. //***************************************************************************
  69. CSWbemSink::~CSWbemSink(void)
  70. {
  71. _RD(static char *me = "CSWbemSink::~CSWbemSink";)
  72. _RPrint(me, "", 0, "");
  73. if (m_pPrivateSink)
  74. {
  75. // Make sure we don't hook back to ourselves any more
  76. // as this CSWbemSink is about to expire
  77. m_pPrivateSink->Detach ();
  78. // Release our hold on the private sink
  79. m_pPrivateSink->Release ();
  80. m_pPrivateSink = NULL;
  81. }
  82. for(int count = 0; count < NUM_CONNECTION_POINTS; count++)
  83. if(m_rgpConnPt[count] != NULL)
  84. delete m_rgpConnPt[count];
  85. free(m_rgpCWbemObjectSink);
  86. InterlockedDecrement(&g_cObj);
  87. _RPrint(me, "After decrement count is", (long)g_cObj, "");
  88. }
  89. //***************************************************************************
  90. // HRESULT CSWbemSink::QueryInterface
  91. // long CSWbemSink::AddRef
  92. // long CSWbemSink::Release
  93. //
  94. // DESCRIPTION:
  95. //
  96. // Standard Com IUNKNOWN functions.
  97. //
  98. //***************************************************************************
  99. STDMETHODIMP CSWbemSink::QueryInterface (
  100. IN REFIID riid,
  101. OUT LPVOID *ppv
  102. )
  103. {
  104. *ppv=NULL;
  105. if (IID_IUnknown==riid)
  106. *ppv = reinterpret_cast<IUnknown *>(this);
  107. else if (IID_ISWbemSink==riid)
  108. *ppv = (ISWbemSink *)this;
  109. else if (IID_IDispatch==riid)
  110. *ppv = (IDispatch *) this;
  111. else if (IID_IConnectionPointContainer==riid)
  112. *ppv = (IConnectionPointContainer *)this;
  113. else if (IID_IProvideClassInfo==riid)
  114. *ppv = (IProvideClassInfo *)this;
  115. else if (IID_IProvideClassInfo2==riid)
  116. *ppv = (IProvideClassInfo2 *)this;
  117. // else if (IID_ISWbemPrivateSink==riid)
  118. // *ppv = (ISWbemPrivateSink *)(&m_privateSink); // Private I/F counting
  119. else if (IID_ISWbemPrivateSinkLocator==riid)
  120. *ppv = (ISWbemPrivateSinkLocator *)this;
  121. else if (IID_IObjectSafety==riid)
  122. *ppv = (IObjectSafety *)this;
  123. else if (IID_ISupportErrorInfo==riid)
  124. *ppv = (ISupportErrorInfo *)this;
  125. if (NULL!=*ppv)
  126. {
  127. ((LPUNKNOWN)*ppv)->AddRef();
  128. return NOERROR;
  129. }
  130. return ResultFromScode(E_NOINTERFACE);
  131. }
  132. STDMETHODIMP_(ULONG) CSWbemSink::AddRef(void)
  133. {
  134. InterlockedIncrement(&m_cRef);
  135. return m_cRef;
  136. }
  137. STDMETHODIMP_(ULONG) CSWbemSink::Release(void)
  138. {
  139. _RD(static char *me = "CSWbemSink::Release";)
  140. /*
  141. * If the only refs that are left are those from
  142. * CWbemPrivateSink then initiate a cancel on all
  143. * remaining sinks. This is because there are no
  144. * client refs to CSWbemSinks left, therefore queries
  145. * in progress can be of no use. First make sure we
  146. * do an Unadvise for all the connection points.
  147. */
  148. InterlockedDecrement(&m_cRef);
  149. if (0L!=m_cRef)
  150. {
  151. return m_cRef;
  152. }
  153. else
  154. {
  155. // We are about to blow away this SWbemSink, so
  156. // make sure we clean up any orphaned IWbemObjectSink's
  157. // by unadvising and cancelling the underlying WMI calls
  158. if(m_pPrivateSink)
  159. m_pPrivateSink->Detach();
  160. if (m_rgpConnPt[0])
  161. {
  162. m_rgpConnPt[0]->UnadviseAll();
  163. }
  164. Cancel();
  165. }
  166. delete this;
  167. return 0;
  168. }
  169. //***************************************************************************
  170. // HRESULT CSWbemSink::InterfaceSupportsErrorInfo
  171. //
  172. // DESCRIPTION:
  173. //
  174. // Standard Com ISupportErrorInfo functions.
  175. //
  176. //***************************************************************************
  177. STDMETHODIMP CSWbemSink::InterfaceSupportsErrorInfo (IN REFIID riid)
  178. {
  179. return (IID_ISWbemSink == riid) ? S_OK : S_FALSE;
  180. }
  181. HRESULT STDMETHODCALLTYPE CSWbemSink::Cancel()
  182. {
  183. _RD(static char *me = "CSWbemSink::Cancel";)
  184. ResetLastErrors ();
  185. if (!m_nSinks)
  186. return S_OK;
  187. _RPrint(me, "!!!Cancel called", 0, "");
  188. /*
  189. * Take a copy of the sinks, this can change under our feet
  190. * As the Cancel can cause us to be re-entered. No need to
  191. * take a copy of m_nMaxSinks as this isn't used when cancels
  192. * are occuring.
  193. * Make sure we AddRef the sink so that it can't be blown away
  194. * under our feet by a re-entrant call to OnCompleted
  195. */
  196. HRESULT hr = WBEM_E_FAILED;
  197. int nSinks = m_nSinks;
  198. WbemObjectListEntry *rgpCWbemObjectSink =
  199. (WbemObjectListEntry *)malloc(nSinks * sizeof(WbemObjectListEntry));
  200. if (!rgpCWbemObjectSink)
  201. hr = WBEM_E_OUT_OF_MEMORY;
  202. else
  203. {
  204. int actual = 0;
  205. for (int i = 0; i < m_nMaxSinks; i++)
  206. {
  207. if (m_rgpCWbemObjectSink[i].pWbemObjectWrapper)
  208. {
  209. m_rgpCWbemObjectSink[i].pWbemObjectWrapper->AddRef();
  210. if (m_rgpCWbemObjectSink[i].pServices)
  211. m_rgpCWbemObjectSink[i].pServices->AddRef();
  212. rgpCWbemObjectSink[actual++] = m_rgpCWbemObjectSink[i];
  213. }
  214. }
  215. /*
  216. * Now do the actual cancel
  217. */
  218. for (i = 0; i < nSinks; i++) {
  219. if (rgpCWbemObjectSink[i].pWbemObjectWrapper) {
  220. IWbemObjectSink *pSink = NULL;
  221. if (SUCCEEDED(rgpCWbemObjectSink[i].pWbemObjectWrapper->QueryInterface
  222. (IID_IWbemObjectSink, (PPVOID)&pSink)))
  223. {
  224. if (rgpCWbemObjectSink[i].pServices)
  225. rgpCWbemObjectSink[i].pServices->CancelAsyncCall(pSink);
  226. pSink->Release();
  227. }
  228. rgpCWbemObjectSink[i].pWbemObjectWrapper->Release();
  229. if (rgpCWbemObjectSink[i].pServices)
  230. rgpCWbemObjectSink[i].pServices->Release();
  231. }
  232. }
  233. free(rgpCWbemObjectSink);
  234. hr = S_OK;
  235. }
  236. return hr;
  237. }
  238. HRESULT CSWbemSink::EnumConnectionPoints(IEnumConnectionPoints** ppEnum)
  239. {
  240. HRESULT hr = E_FAIL;
  241. if (!ppEnum)
  242. hr = E_POINTER;
  243. else
  244. {
  245. CEnumConnectionPoints* pEnum = new CEnumConnectionPoints(reinterpret_cast<IUnknown*>(this), (void**)m_rgpConnPt);
  246. if (!pEnum)
  247. hr = E_OUTOFMEMORY;
  248. else if (FAILED(hr = pEnum->QueryInterface(IID_IEnumConnectionPoints, (void**)ppEnum)))
  249. delete pEnum;
  250. }
  251. return hr;
  252. }
  253. HRESULT CSWbemSink::FindConnectionPoint(REFIID riid, IConnectionPoint** ppCP)
  254. {
  255. HRESULT hr = E_FAIL;
  256. if(riid == DIID_ISWbemSinkEvents)
  257. {
  258. if (!ppCP)
  259. hr = E_POINTER;
  260. else if (m_rgpConnPt [0])
  261. hr = m_rgpConnPt[0]->QueryInterface(IID_IConnectionPoint, (void**)ppCP);
  262. }
  263. else
  264. hr = E_NOINTERFACE;
  265. return hr;
  266. }
  267. HRESULT CSWbemSink::GetClassInfo(ITypeInfo** pTypeInfo)
  268. {
  269. HRESULT hr = E_FAIL;
  270. if (!pTypeInfo)
  271. hr = E_POINTER;
  272. else
  273. {
  274. CComPtr<ITypeLib> pTypeLib;
  275. if (SUCCEEDED(LoadRegTypeLib(LIBID_WbemScripting, 1, 0, LANG_NEUTRAL, &pTypeLib)))
  276. hr = pTypeLib->GetTypeInfoOfGuid(CLSID_SWbemSink, pTypeInfo);
  277. }
  278. return hr;
  279. }
  280. HRESULT CSWbemSink::GetGUID(DWORD dwGuidKind, GUID* pGUID)
  281. {
  282. if(pGUID == NULL)
  283. return E_INVALIDARG;
  284. *pGUID = DIID_ISWbemSinkEvents;
  285. return S_OK;
  286. }
  287. HRESULT STDMETHODCALLTYPE CSWbemSink::AddObjectSink(
  288. /* [in] */ IUnknown __RPC_FAR *pSink,
  289. /* [in] */ IWbemServices __RPC_FAR *pServices)
  290. {
  291. if(m_nSinks == m_nMaxSinks)
  292. {
  293. // Expand the size of the sink list
  294. m_rgpCWbemObjectSink = (WbemObjectListEntry *)realloc(m_rgpCWbemObjectSink,
  295. (m_nMaxSinks + SINKS_MAX) * sizeof(WbemObjectListEntry));
  296. // Initialize new bit
  297. for(int count = m_nMaxSinks; count < (m_nMaxSinks + SINKS_MAX); count++)
  298. {
  299. m_rgpCWbemObjectSink[count].pWbemObjectWrapper = NULL;
  300. m_rgpCWbemObjectSink[count].pServices = NULL;
  301. }
  302. m_nMaxSinks += SINKS_MAX;
  303. }
  304. for(int count = 0; count < m_nMaxSinks; count++)
  305. if(m_rgpCWbemObjectSink[count].pWbemObjectWrapper == NULL)
  306. {
  307. m_rgpCWbemObjectSink[count].pWbemObjectWrapper = pSink;
  308. m_rgpCWbemObjectSink[count].pServices = pServices;
  309. break;
  310. }
  311. m_nSinks++;
  312. return S_OK;
  313. }
  314. HRESULT STDMETHODCALLTYPE CSWbemSink::RemoveObjectSink(/* [in] */ IUnknown __RPC_FAR *pSink)
  315. {
  316. for(int count = 0; count < m_nMaxSinks; count++)
  317. if(pSink == m_rgpCWbemObjectSink[count].pWbemObjectWrapper)
  318. {
  319. m_rgpCWbemObjectSink[count].pWbemObjectWrapper = NULL;
  320. m_nSinks--;
  321. }
  322. return S_OK;
  323. }
  324. HRESULT STDMETHODCALLTYPE CSWbemSink::OnObjectReady(
  325. /* [in] */ IDispatch __RPC_FAR *pObject,
  326. /* [in] */ IDispatch __RPC_FAR *pContext)
  327. {
  328. if (m_rgpConnPt[0])
  329. {
  330. m_rgpConnPt[0]->OnObjectReady(pObject, pContext);
  331. }
  332. else
  333. {
  334. return E_FAIL;
  335. }
  336. return 0;
  337. }
  338. HRESULT STDMETHODCALLTYPE CSWbemSink::OnCompleted(
  339. /* [in] */ HRESULT hResult,
  340. /* [in] */ IDispatch __RPC_FAR *path,
  341. /* [in] */ IDispatch __RPC_FAR *pErrorObject,
  342. /* [in] */ IDispatch __RPC_FAR *pContext)
  343. {
  344. if (m_rgpConnPt[0])
  345. {
  346. m_rgpConnPt[0]->OnCompleted(hResult, pErrorObject, path, pContext);
  347. }
  348. else
  349. {
  350. return E_FAIL;
  351. }
  352. return 0;
  353. }
  354. HRESULT STDMETHODCALLTYPE CSWbemSink::OnProgress(
  355. /* [in] */ long upperBound,
  356. /* [in] */ long current,
  357. /* [in] */ BSTR message,
  358. /* [in] */ IDispatch __RPC_FAR *pContext)
  359. {
  360. if (m_rgpConnPt[0])
  361. {
  362. m_rgpConnPt[0]->OnProgress(upperBound, current, message, pContext);
  363. }
  364. else
  365. {
  366. return E_FAIL;
  367. }
  368. return 0;
  369. }
  370. HRESULT STDMETHODCALLTYPE CSWbemSink::GetPrivateSink(
  371. /* [out] */ IUnknown **objWbemPrivateSink)
  372. {
  373. HRESULT hr = E_FAIL;
  374. if (objWbemPrivateSink)
  375. {
  376. if(!m_pPrivateSink)
  377. {
  378. if (m_pPrivateSink = new CSWbemPrivateSink(this))
  379. m_pPrivateSink->AddRef (); // Released in destructor
  380. }
  381. if (m_pPrivateSink)
  382. hr = m_pPrivateSink->QueryInterface(IID_IUnknown, (PPVOID)objWbemPrivateSink);
  383. }
  384. else
  385. hr = E_POINTER;
  386. return hr;
  387. }
  388. // void** rpgCP is used so that this constructor can accept either CConnectionPoint**
  389. // from CSWbemSink::EnumConnectionPoints or IConnectionPoint** from CEnumConnectionPoints::Clone
  390. // This could also be done by overloading the constructor and duplicating some of this code
  391. CEnumConnectionPoints::CEnumConnectionPoints(IUnknown* pUnkRef, void** rgpCP) : m_cRef(0)
  392. {
  393. m_iCur = 0;
  394. m_pUnkRef = pUnkRef;
  395. // m_rgpCP is a pointer to an array of IConnectionPoints or CConnectionPoints
  396. for(int count = 0; count < NUM_CONNECTION_POINTS; count++)
  397. ((IUnknown*)rgpCP[count])->QueryInterface(IID_IConnectionPoint, (void**)&m_rgpCP[count]);
  398. InterlockedIncrement(&g_cObj);
  399. }
  400. CEnumConnectionPoints::~CEnumConnectionPoints()
  401. {
  402. if(m_rgpCP != NULL)
  403. for(int count = 0; count < NUM_CONNECTION_POINTS; count++)
  404. m_rgpCP[count]->Release();
  405. InterlockedDecrement(&g_cObj);
  406. }
  407. ULONG CEnumConnectionPoints::AddRef()
  408. {
  409. m_pUnkRef->AddRef();
  410. return ++m_cRef;
  411. }
  412. ULONG CEnumConnectionPoints::Release()
  413. {
  414. m_pUnkRef->Release();
  415. if(--m_cRef != 0)
  416. return m_cRef;
  417. delete this;
  418. return 0;
  419. }
  420. HRESULT CEnumConnectionPoints::QueryInterface(REFIID riid, void** ppv)
  421. {
  422. if(riid == IID_IUnknown || riid == IID_IEnumConnectionPoints)
  423. *ppv = (IEnumConnectionPoints*)this;
  424. else
  425. {
  426. *ppv = NULL;
  427. return E_NOINTERFACE;
  428. }
  429. AddRef();
  430. return S_OK;
  431. }
  432. HRESULT CEnumConnectionPoints::Next(ULONG cConnections, IConnectionPoint** rgpcn, ULONG* pcFetched)
  433. {
  434. if(rgpcn == NULL)
  435. return E_POINTER;
  436. if(pcFetched == NULL && cConnections != 1)
  437. return E_INVALIDARG;
  438. if(pcFetched != NULL)
  439. *pcFetched = 0;
  440. while(m_iCur < NUM_CONNECTION_POINTS && cConnections > 0)
  441. {
  442. *rgpcn = m_rgpCP[m_iCur++];
  443. if(*rgpcn != NULL)
  444. (*rgpcn)->AddRef();
  445. if(pcFetched != NULL)
  446. (*pcFetched)++;
  447. cConnections--;
  448. rgpcn++;
  449. }
  450. return S_OK;
  451. }
  452. HRESULT CEnumConnectionPoints::Skip(ULONG cConnections)
  453. {
  454. if(m_iCur + cConnections >= NUM_CONNECTION_POINTS)
  455. return S_FALSE;
  456. m_iCur += cConnections;
  457. return S_OK;
  458. }
  459. HRESULT CEnumConnectionPoints::Reset()
  460. {
  461. m_iCur = 0;
  462. return S_OK;
  463. }
  464. HRESULT CEnumConnectionPoints::Clone(IEnumConnectionPoints** ppEnum)
  465. {
  466. if(ppEnum == NULL)
  467. return E_POINTER;
  468. *ppEnum = NULL;
  469. // Create the clone
  470. CEnumConnectionPoints* pNew = new CEnumConnectionPoints(m_pUnkRef, (void**)m_rgpCP);
  471. if(pNew == NULL)
  472. return E_OUTOFMEMORY;
  473. pNew->AddRef();
  474. pNew->m_iCur = m_iCur;
  475. *ppEnum = pNew;
  476. return S_OK;
  477. }
  478. CConnectionPoint::CConnectionPoint(CSWbemSink* pObj, REFIID riid) :
  479. m_cRef(0),
  480. m_rgnCookies(NULL),
  481. m_rgpUnknown(NULL)
  482. {
  483. m_iid = riid;
  484. m_nMaxConnections = CCONNMAX;
  485. m_rgnCookies = (unsigned *)malloc(m_nMaxConnections * sizeof(unsigned));
  486. m_rgpUnknown = (IUnknown **)malloc(m_nMaxConnections * sizeof(IUnknown *));
  487. // Don't need AddRef/Release since we are nested inside CSWbemSink
  488. m_pObj = pObj;
  489. for(int count = 0; count < m_nMaxConnections; count++)
  490. {
  491. if (m_rgpUnknown)
  492. m_rgpUnknown[count] = NULL;
  493. if (m_rgnCookies)
  494. m_rgnCookies[count] = 0;
  495. }
  496. m_cConn = 0;
  497. m_nCookieNext = 10; // Arbitrary starting cookie value
  498. InterlockedIncrement(&g_cObj);
  499. }
  500. CConnectionPoint::~CConnectionPoint()
  501. {
  502. if (m_rgpUnknown)
  503. {
  504. for(int count = 0; count < m_nMaxConnections; count++)
  505. if(m_rgpUnknown[count] != NULL)
  506. {
  507. m_rgpUnknown[count]->Release();
  508. m_rgpUnknown[count] = NULL;
  509. }
  510. free(m_rgpUnknown);
  511. }
  512. if (m_rgnCookies)
  513. free(m_rgnCookies);
  514. InterlockedDecrement(&g_cObj);
  515. }
  516. HRESULT CConnectionPoint::QueryInterface(REFIID riid, void** ppv)
  517. {
  518. if(IID_IUnknown == riid || IID_IConnectionPoint == riid)
  519. *ppv = (IConnectionPoint*)this;
  520. else
  521. {
  522. *ppv = NULL;
  523. return E_NOINTERFACE;
  524. }
  525. AddRef();
  526. return S_OK;
  527. }
  528. ULONG CConnectionPoint::AddRef()
  529. {
  530. return ++m_cRef;
  531. }
  532. ULONG CConnectionPoint::Release()
  533. {
  534. if(--m_cRef != 0)
  535. return m_cRef;
  536. delete this;
  537. return 0;
  538. }
  539. HRESULT CConnectionPoint::GetConnectionInterface(IID *pIID)
  540. {
  541. if(pIID == NULL)
  542. return E_POINTER;
  543. *pIID = m_iid;
  544. return S_OK;
  545. }
  546. HRESULT CConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer** ppCPC)
  547. {
  548. return m_pObj->QueryInterface(IID_IConnectionPointContainer, (void**)ppCPC);
  549. }
  550. HRESULT CConnectionPoint::Advise(IUnknown* pUnknownSink, DWORD* pdwCookie)
  551. {
  552. IUnknown* pSink;
  553. *pdwCookie = 0;
  554. _RD(static char *me = "CConnectionPoint::Advise";)
  555. _RPrint(me, "Current connections (before adjustment): ", (long)m_cConn, "");
  556. if(m_cConn == m_nMaxConnections)
  557. {
  558. //return CONNECT_E_ADVISELIMIT;
  559. // Expand the size of the connection lists
  560. m_rgnCookies = (unsigned *)realloc(m_rgnCookies, (m_nMaxConnections + CCONNMAX) * sizeof(unsigned));
  561. m_rgpUnknown = (IUnknown **)realloc(m_rgpUnknown, (m_nMaxConnections + CCONNMAX) * sizeof(IUnknown *));
  562. // Initialize new bit
  563. for(int count = m_nMaxConnections; count < (m_nMaxConnections + CCONNMAX); count++)
  564. {
  565. m_rgpUnknown[count] = NULL;
  566. m_rgnCookies[count] = 0;
  567. }
  568. m_nMaxConnections += CCONNMAX;
  569. }
  570. if(FAILED(pUnknownSink->QueryInterface(m_iid, (void**)&pSink)))
  571. return CONNECT_E_CANNOTCONNECT;
  572. for(int count = 0; count < m_nMaxConnections; count++)
  573. if(m_rgpUnknown[count] == NULL)
  574. {
  575. m_rgpUnknown[count] = pSink;
  576. m_rgnCookies[count] = ++m_nCookieNext;
  577. *pdwCookie = m_nCookieNext;
  578. break;
  579. }
  580. m_cConn++;
  581. return NOERROR;
  582. }
  583. HRESULT CConnectionPoint::Unadvise(DWORD dwCookie)
  584. {
  585. _RD(static char *me = "CConnectionPoint::Unadvise";)
  586. _RPrint(me, "Current connections (before adjustment): ", (long)m_cConn, "");
  587. if(dwCookie == 0)
  588. return E_INVALIDARG;
  589. for(int count = 0; count < m_nMaxConnections; count++)
  590. if(dwCookie == m_rgnCookies[count])
  591. {
  592. if(m_rgpUnknown[count] != NULL)
  593. {
  594. m_rgpUnknown[count]->Release();
  595. m_rgpUnknown[count] = NULL;
  596. m_rgnCookies[count] = 0;
  597. }
  598. m_cConn--;
  599. return NOERROR;
  600. }
  601. return CONNECT_E_NOCONNECTION;
  602. }
  603. HRESULT CConnectionPoint::EnumConnections(IEnumConnections** ppEnum)
  604. {
  605. HRESULT hr = E_FAIL;
  606. if (!ppEnum)
  607. hr = E_POINTER;
  608. else
  609. {
  610. *ppEnum = NULL;
  611. CONNECTDATA* pCD = new CONNECTDATA[m_cConn];
  612. if (!pCD)
  613. hr = E_OUTOFMEMORY;
  614. else
  615. {
  616. for(int count1 = 0, count2 = 0; count1 < m_nMaxConnections; count1++)
  617. if(m_rgpUnknown[count1] != NULL)
  618. {
  619. pCD[count2].pUnk = (IUnknown*)m_rgpUnknown[count1];
  620. pCD[count2].dwCookie = m_rgnCookies[count1];
  621. count2++;
  622. }
  623. CEnumConnections* pEnum = new CEnumConnections(this, m_cConn, pCD);
  624. delete [] pCD;
  625. if (!pEnum)
  626. hr = E_OUTOFMEMORY;
  627. else
  628. hr = pEnum->QueryInterface(IID_IEnumConnections, (void**)ppEnum);
  629. }
  630. }
  631. return hr;
  632. }
  633. void CConnectionPoint::UnadviseAll() {
  634. _RD(static char *me = "CConnectionPoint::UnadviseAll";)
  635. _RPrint(me, "Current connections (before adjustment): ", (long)m_cConn, "");
  636. for(int count = 0; count < m_nMaxConnections; count++) {
  637. if(m_rgpUnknown[count] != NULL)
  638. {
  639. m_rgpUnknown[count]->Release();
  640. m_rgpUnknown[count] = NULL;
  641. m_rgnCookies[count] = 0;
  642. m_cConn--;
  643. }
  644. }
  645. _RPrint(me, "Current connections (after adjustment): ", (long)m_cConn, "");
  646. }
  647. void CConnectionPoint::OnObjectReady(
  648. /* [in] */ IDispatch __RPC_FAR *pObject,
  649. /* [in] */ IDispatch __RPC_FAR *pAsyncContext)
  650. {
  651. HRESULT hr = S_OK;
  652. LPDISPATCH pdisp = NULL;
  653. for(int i = 0; i < m_nMaxConnections; i++)
  654. {
  655. if(m_rgpUnknown[i])
  656. {
  657. if (SUCCEEDED(hr = m_rgpUnknown[i]->QueryInterface(IID_IDispatch, (PPVOID)&pdisp)))
  658. {
  659. DISPPARAMS dispparams;
  660. VARIANTARG args[NUM_ON_OBJECT_READY_ARGS];
  661. VARIANTARG *pArg = args;
  662. memset(&dispparams, 0, sizeof dispparams);
  663. dispparams.cArgs = NUM_ON_OBJECT_READY_ARGS;
  664. dispparams.rgvarg = args;
  665. VariantInit(pArg);
  666. pArg->vt = VT_DISPATCH;
  667. pArg->pdispVal = pAsyncContext;
  668. pArg++;
  669. VariantInit(pArg);
  670. pArg->vt = VT_DISPATCH;
  671. pArg->pdispVal = pObject;
  672. hr = pdisp->Invoke(WBEMS_DISPID_OBJECT_READY, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  673. DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
  674. pdisp->Release();
  675. }
  676. }
  677. }
  678. }
  679. void CConnectionPoint::OnCompleted(
  680. /* [in] */ HRESULT hResult,
  681. /* [in] */ IDispatch __RPC_FAR *path,
  682. /* [in] */ IDispatch __RPC_FAR *pErrorObject,
  683. /* [in] */ IDispatch __RPC_FAR *pAsyncContext)
  684. {
  685. HRESULT hr = S_OK;
  686. LPDISPATCH pdisp = NULL;
  687. for(int i = 0; i < m_nMaxConnections; i++)
  688. {
  689. if(m_rgpUnknown[i])
  690. {
  691. if (SUCCEEDED(hr = m_rgpUnknown[i]->QueryInterface(IID_IDispatch, (PPVOID)&pdisp)))
  692. {
  693. VARIANTARG *pArg;
  694. if (path)
  695. {
  696. DISPPARAMS putDispparams;
  697. VARIANTARG putArgs[NUM_ON_OBJECT_PUT_ARGS];
  698. memset(&putDispparams, 0, sizeof putDispparams);
  699. putDispparams.cArgs = NUM_ON_OBJECT_PUT_ARGS;
  700. putDispparams.rgvarg = pArg = putArgs;
  701. VariantInit(pArg);
  702. pArg->vt = VT_DISPATCH;
  703. pArg->pdispVal = pAsyncContext;
  704. pArg++;
  705. VariantInit(pArg);
  706. pArg->vt = VT_DISPATCH;
  707. pArg->pdispVal = path;
  708. hr = pdisp->Invoke(WBEMS_DISPID_OBJECT_PUT, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  709. DISPATCH_METHOD, &putDispparams, NULL, NULL, NULL);
  710. }
  711. DISPPARAMS dispparams;
  712. VARIANTARG args[NUM_ON_COMPLETED_ARGS];
  713. memset(&dispparams, 0, sizeof dispparams);
  714. dispparams.cArgs = NUM_ON_COMPLETED_ARGS;
  715. dispparams.rgvarg = pArg = args;
  716. VariantInit(pArg);
  717. pArg->vt = VT_DISPATCH;
  718. pArg->pdispVal = pAsyncContext;
  719. pArg++;
  720. VariantInit(pArg);
  721. pArg->vt = VT_DISPATCH;
  722. pArg->pdispVal = pErrorObject;
  723. pArg++;
  724. VariantInit(pArg);
  725. pArg->vt = VT_I4;
  726. pArg->lVal = (long)hResult;
  727. hr = pdisp->Invoke(WBEMS_DISPID_COMPLETED, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  728. DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
  729. pdisp->Release();
  730. }
  731. }
  732. }
  733. }
  734. void CConnectionPoint::OnProgress(
  735. /* [in] */ long upperBound,
  736. /* [in] */ long current,
  737. /* [in] */ BSTR message,
  738. /* [in] */ IDispatch __RPC_FAR *pAsyncContext)
  739. {
  740. HRESULT hr = S_OK;
  741. LPDISPATCH pdisp = NULL;
  742. for(int i = 0; i < m_nMaxConnections; i++)
  743. {
  744. if(m_rgpUnknown[i])
  745. {
  746. if (SUCCEEDED(hr = m_rgpUnknown[i]->QueryInterface(IID_IDispatch, (PPVOID)&pdisp)))
  747. {
  748. DISPPARAMS dispparams;
  749. VARIANTARG args[NUM_ON_PROGRESS_ARGS];
  750. VARIANTARG *pArg = args;
  751. memset(&dispparams, 0, sizeof dispparams);
  752. dispparams.cArgs = NUM_ON_PROGRESS_ARGS;
  753. dispparams.rgvarg = args;
  754. VariantInit(pArg);
  755. pArg->vt = VT_DISPATCH;
  756. pArg->pdispVal = (IDispatch FAR *)pAsyncContext;
  757. pArg++;
  758. VariantInit(pArg);
  759. pArg->vt = VT_BSTR;
  760. pArg->bstrVal = message;
  761. pArg++;
  762. VariantInit(pArg);
  763. pArg->vt = VT_I4;
  764. pArg->lVal = current;
  765. pArg++;
  766. VariantInit(pArg);
  767. pArg->vt = VT_I4;
  768. pArg->lVal = upperBound;
  769. hr = pdisp->Invoke(WBEMS_DISPID_PROGRESS, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  770. DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
  771. pdisp->Release();
  772. }
  773. }
  774. }
  775. }
  776. CEnumConnections::CEnumConnections(IUnknown* pUnknown, int cConn, CONNECTDATA* pConnData) : m_cRef(0)
  777. {
  778. m_pUnkRef = pUnknown;
  779. m_iCur = 0;
  780. m_cConn = cConn;
  781. m_rgConnData = new CONNECTDATA[cConn];
  782. if(m_rgConnData != NULL)
  783. for(int count = 0; count < cConn; count++)
  784. {
  785. m_rgConnData[count] = pConnData[count];
  786. m_rgConnData[count].pUnk->AddRef();
  787. }
  788. InterlockedIncrement(&g_cObj);
  789. }
  790. CEnumConnections::~CEnumConnections()
  791. {
  792. if(m_rgConnData != NULL)
  793. {
  794. for(unsigned count = 0; count < m_cConn; count++)
  795. m_rgConnData[count].pUnk->Release();
  796. delete [] m_rgConnData;
  797. }
  798. InterlockedDecrement(&g_cObj);
  799. }
  800. HRESULT CEnumConnections::Next(ULONG cConnections, CONNECTDATA* rgpcd, ULONG* pcFetched)
  801. {
  802. if(pcFetched == NULL && cConnections != 1)
  803. return E_INVALIDARG;
  804. if(pcFetched != NULL)
  805. *pcFetched = 0;
  806. if(rgpcd == NULL || m_iCur >= m_cConn)
  807. return S_FALSE;
  808. unsigned cReturn = 0;
  809. while(m_iCur < m_cConn && cConnections > 0)
  810. {
  811. *rgpcd++ = m_rgConnData[m_iCur];
  812. m_rgConnData[m_iCur++].pUnk->AddRef();
  813. cReturn++;
  814. cConnections--;
  815. }
  816. if(pcFetched != NULL)
  817. *pcFetched = cReturn;
  818. return S_OK;
  819. }
  820. HRESULT CEnumConnections::Skip(ULONG cConnections)
  821. {
  822. if(m_iCur + cConnections >= m_cConn)
  823. return S_FALSE;
  824. m_iCur += cConnections;
  825. return S_OK;
  826. }
  827. HRESULT CEnumConnections::Reset()
  828. {
  829. m_iCur = 0;
  830. return S_OK;
  831. }
  832. HRESULT CEnumConnections::Clone(IEnumConnections** ppEnum)
  833. {
  834. if(ppEnum == NULL)
  835. return E_POINTER;
  836. *ppEnum = NULL;
  837. // Create the clone
  838. CEnumConnections* pNew = new CEnumConnections(m_pUnkRef, m_cConn, m_rgConnData);
  839. if(NULL == pNew)
  840. return E_OUTOFMEMORY;
  841. pNew->AddRef();
  842. pNew->m_iCur = m_iCur;
  843. *ppEnum = pNew;
  844. return S_OK;
  845. }
  846. HRESULT CEnumConnections::QueryInterface(REFIID riid, void** ppv)
  847. {
  848. if(IID_IUnknown == riid || IID_IEnumConnections == riid)
  849. *ppv = (IEnumConnections*)this;
  850. else
  851. {
  852. *ppv = NULL;
  853. return E_NOINTERFACE;
  854. }
  855. AddRef();
  856. return S_OK;
  857. }
  858. ULONG CEnumConnections::AddRef()
  859. {
  860. return ++m_cRef;
  861. }
  862. ULONG CEnumConnections::Release()
  863. {
  864. if(--m_cRef != 0)
  865. return m_cRef;
  866. delete this;
  867. return 0;
  868. }