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

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