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.

715 lines
14 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. counters.cpp
  5. Abstract:
  6. Implementation of the ICounters interface
  7. --*/
  8. #include "polyline.h"
  9. #include "counters.h"
  10. #include "grphitem.h"
  11. #include "unkhlpr.h"
  12. #include "unihelpr.h"
  13. //Standard IUnknown implementation for contained interface
  14. IMPLEMENT_CONTAINED_CONSTRUCTOR(CPolyline, CImpICounters)
  15. IMPLEMENT_CONTAINED_DESTRUCTOR(CImpICounters)
  16. IMPLEMENT_CONTAINED_ADDREF(CImpICounters)
  17. IMPLEMENT_CONTAINED_RELEASE(CImpICounters)
  18. STDMETHODIMP
  19. CImpICounters::QueryInterface (
  20. IN REFIID riid,
  21. OUT PPVOID ppv
  22. )
  23. {
  24. HRESULT hr = S_OK;
  25. if (ppv == NULL) {
  26. return E_POINTER;
  27. }
  28. try {
  29. *ppv = NULL;
  30. if (IID_IUnknown == riid || IID_ICounters == riid) {
  31. *ppv = (LPVOID)this;
  32. AddRef();
  33. } else {
  34. hr = E_NOINTERFACE;
  35. }
  36. } catch (...) {
  37. hr = E_POINTER;
  38. }
  39. return hr;
  40. }
  41. STDMETHODIMP
  42. CImpICounters::GetTypeInfoCount (
  43. OUT UINT *pctInfo
  44. )
  45. {
  46. HRESULT hr = S_OK;
  47. if (pctInfo == NULL) {
  48. return E_POINTER;
  49. }
  50. try {
  51. *pctInfo = 1;
  52. } catch (...) {
  53. hr = E_POINTER;
  54. }
  55. return hr;
  56. }
  57. STDMETHODIMP
  58. CImpICounters::GetTypeInfo (
  59. IN UINT itInfo,
  60. IN LCID /* lcid */,
  61. OUT ITypeInfo **ppITypeInfo )
  62. {
  63. HRESULT hr = S_OK;
  64. if (ppITypeInfo == NULL) {
  65. return E_POINTER;
  66. }
  67. try {
  68. *ppITypeInfo = NULL;
  69. if (0 == itInfo) {
  70. //
  71. // We ignore the LCID
  72. //
  73. hr = m_pObj->m_pITypeLib->GetTypeInfoOfGuid(IID_ICounters, ppITypeInfo);
  74. } else {
  75. hr = TYPE_E_ELEMENTNOTFOUND;
  76. }
  77. } catch (...) {
  78. hr = E_POINTER;
  79. }
  80. return hr;
  81. }
  82. STDMETHODIMP
  83. CImpICounters::GetIDsOfNames (
  84. IN REFIID riid,
  85. IN OLECHAR **rgszNames,
  86. IN UINT cNames,
  87. IN LCID /* lcid */,
  88. OUT DISPID *rgDispID
  89. )
  90. {
  91. HRESULT hr = DISP_E_UNKNOWNINTERFACE;
  92. ITypeInfo *pTI = NULL;
  93. if (rgDispID == NULL || rgszNames == NULL) {
  94. return E_POINTER;
  95. }
  96. if (IID_NULL == riid) {
  97. try {
  98. *rgDispID = NULL;
  99. hr = m_pObj->m_pITypeLib->GetTypeInfoOfGuid(IID_ICounters, &pTI);
  100. if (SUCCEEDED(hr)) {
  101. hr = DispGetIDsOfNames(pTI, rgszNames, cNames, rgDispID);
  102. }
  103. } catch (...) {
  104. hr = E_POINTER;
  105. }
  106. }
  107. if (pTI) {
  108. pTI->Release();
  109. }
  110. return hr;
  111. }
  112. /*
  113. * CImpIDispatch::Invoke
  114. *
  115. * Purpose:
  116. * Calls a method in the dispatch interface or manipulates a
  117. * property.
  118. *
  119. * Parameters:
  120. * dispID DISPID of the method or property of interest.
  121. * riid REFIID reserved, must be IID_NULL.
  122. * lcid LCID of the locale.
  123. * wFlags USHORT describing the context of the invocation.
  124. * pDispParams DISPPARAMS * to the array of arguments.
  125. * pVarResult VARIANT * in which to store the result. Is
  126. * NULL if the caller is not interested.
  127. * pExcepInfo EXCEPINFO * to exception information.
  128. * puArgErr UINT * in which to store the index of an
  129. * invalid parameter if DISP_E_TYPEMISMATCH
  130. * is returned.
  131. *
  132. * Return Value:
  133. * HRESULT NOERROR or a general error code.
  134. */
  135. STDMETHODIMP
  136. CImpICounters::Invoke (
  137. IN DISPID dispID,
  138. IN REFIID riid,
  139. IN LCID /* lcid */,
  140. IN USHORT wFlags,
  141. IN DISPPARAMS *pDispParams,
  142. OUT VARIANT *pVarResult,
  143. OUT EXCEPINFO *pExcepInfo,
  144. OUT UINT *puArgErr
  145. )
  146. {
  147. HRESULT hr = DISP_E_UNKNOWNINTERFACE;
  148. ITypeInfo *pTI = NULL;
  149. if ( IID_NULL == riid ) {
  150. try {
  151. hr = m_pObj->m_pITypeLib->GetTypeInfoOfGuid(IID_ICounters, &pTI);
  152. if (SUCCEEDED(hr)) {
  153. hr = pTI->Invoke(this,
  154. dispID,
  155. wFlags,
  156. pDispParams,
  157. pVarResult,
  158. pExcepInfo,
  159. puArgErr);
  160. }
  161. } catch (...) {
  162. hr = E_POINTER;
  163. }
  164. }
  165. if (pTI) {
  166. pTI->Release();
  167. }
  168. return hr;
  169. }
  170. STDMETHODIMP
  171. CImpICounters::get_Count (
  172. OUT LONG *pLong
  173. )
  174. {
  175. HRESULT hr = S_OK;
  176. if (pLong == NULL) {
  177. return E_POINTER;
  178. }
  179. try {
  180. *pLong = m_pObj->m_Graph.CounterTree.NumCounters();
  181. } catch (...) {
  182. hr = E_POINTER;
  183. }
  184. return hr;
  185. }
  186. STDMETHODIMP
  187. CImpICounters::get__NewEnum (
  188. IUnknown **ppIunk
  189. )
  190. {
  191. HRESULT hr = S_OK;
  192. CImpIEnumCounter *pEnum = NULL;
  193. if (ppIunk == NULL) {
  194. return E_POINTER;
  195. }
  196. try {
  197. *ppIunk = NULL;
  198. pEnum = new CImpIEnumCounter;
  199. if ( NULL != pEnum ) {
  200. hr = pEnum->Init(
  201. m_pObj->m_Graph.CounterTree.FirstCounter(),
  202. m_pObj->m_Graph.CounterTree.NumCounters() );
  203. if ( SUCCEEDED ( hr ) ) {
  204. *ppIunk = pEnum;
  205. pEnum->AddRef();
  206. }
  207. }
  208. else {
  209. hr = E_OUTOFMEMORY;
  210. }
  211. } catch (...) {
  212. hr = E_POINTER;
  213. }
  214. if (FAILED(hr) && pEnum != NULL) {
  215. delete pEnum;
  216. }
  217. return hr;
  218. }
  219. STDMETHODIMP
  220. CImpICounters::get_Item (
  221. IN VARIANT varIndex,
  222. OUT DICounterItem **ppI
  223. )
  224. {
  225. HRESULT hr = S_OK;
  226. VARIANT varLoc;
  227. INT iIndex = 0;
  228. INT i;
  229. CGraphItem *pGItem = NULL;
  230. if (ppI == NULL) {
  231. return E_POINTER;
  232. }
  233. //
  234. // Try coercing index to I4
  235. //
  236. VariantInit(&varLoc);
  237. try {
  238. *ppI = NULL;
  239. //
  240. // We use do{}while(0) here to act like a switch statement
  241. //
  242. do {
  243. hr = VariantChangeType(&varLoc, &varIndex, 0, VT_I4);
  244. if ( !SUCCEEDED (hr) ) {
  245. break;
  246. }
  247. //
  248. // Verify index is in range
  249. //
  250. iIndex = V_I4(&varLoc);
  251. if (iIndex < 1 || iIndex > m_pObj->m_Graph.CounterTree.NumCounters()) {
  252. hr = DISP_E_BADINDEX;
  253. break;
  254. }
  255. //
  256. // Traverse counter linked list to indexed item
  257. //
  258. pGItem = m_pObj->m_Graph.CounterTree.FirstCounter();
  259. i = 1;
  260. while (i++ < iIndex && pGItem != NULL) {
  261. pGItem = pGItem->Next();
  262. }
  263. //
  264. // Something wrong with linked list!!
  265. //
  266. if ( NULL == pGItem ) {
  267. hr = E_FAIL;
  268. break;
  269. }
  270. //
  271. // Return counter's dispatch interface
  272. //
  273. hr = pGItem->QueryInterface(DIID_DICounterItem, (PVOID*)ppI);
  274. } while (0);
  275. } catch (...) {
  276. hr = E_POINTER;
  277. }
  278. return hr;
  279. }
  280. STDMETHODIMP
  281. CImpICounters::Add (
  282. IN BSTR bstrPath,
  283. OUT DICounterItem **ppI
  284. )
  285. {
  286. HRESULT hr = S_OK;
  287. PCGraphItem pGItem = NULL;
  288. if (ppI == NULL) {
  289. return E_POINTER;
  290. }
  291. try {
  292. *ppI = NULL;
  293. //
  294. // If non-null counter
  295. //
  296. if (bstrPath != NULL && bstrPath[0] != 0) {
  297. hr = m_pObj->m_pCtrl->AddCounter(bstrPath, &pGItem);
  298. if ( SUCCEEDED (hr) && NULL != pGItem) {
  299. hr = pGItem->QueryInterface(DIID_DICounterItem, (PVOID*)ppI);
  300. }
  301. }
  302. else {
  303. hr = E_INVALIDARG;
  304. }
  305. } catch (...) {
  306. hr = E_POINTER;
  307. }
  308. if (pGItem) {
  309. pGItem->Release();
  310. }
  311. return hr;
  312. }
  313. STDMETHODIMP
  314. CImpICounters::Remove (
  315. IN VARIANT varIndex
  316. )
  317. {
  318. DICounterItem *pDI = NULL;
  319. PCGraphItem pGItem;
  320. HRESULT hr;
  321. // Get interface to indexed item
  322. hr = get_Item(varIndex, &pDI);
  323. if ( SUCCEEDED ( hr ) ) {
  324. // Exchange Dispatch interface for direct one
  325. hr = pDI->QueryInterface(IID_ICounterItem, (PVOID*)&pGItem);
  326. pDI->Release();
  327. if ( SUCCEEDED ( hr ) ) {
  328. assert ( NULL != pGItem );
  329. // Delete the item from the control
  330. pGItem->Delete(TRUE);
  331. // Release the temp interface
  332. pGItem->Release();
  333. }
  334. }
  335. return hr;
  336. }
  337. CImpIEnumCounter::CImpIEnumCounter (
  338. VOID
  339. )
  340. {
  341. m_cItems = 0;
  342. m_uCurrent = 0;
  343. m_cRef = 0;
  344. m_paGraphItem = NULL;
  345. }
  346. HRESULT
  347. CImpIEnumCounter::Init (
  348. PCGraphItem pGraphItem,
  349. INT cItems
  350. )
  351. {
  352. HRESULT hr = S_OK;
  353. INT i;
  354. if ( cItems > 0 ) {
  355. m_cItems = cItems;
  356. m_paGraphItem = (PCGraphItem*)malloc(sizeof(PCGraphItem) * cItems);
  357. if ( NULL != m_paGraphItem ) {
  358. ZeroMemory(m_paGraphItem, sizeof(PCGraphItem) * cItems);
  359. for (i = 0; i < cItems; i++) {
  360. m_paGraphItem[i] = pGraphItem;
  361. pGraphItem = pGraphItem->Next();
  362. }
  363. } else {
  364. hr = E_OUTOFMEMORY;
  365. }
  366. } // No error if cItems <= 0
  367. return hr;
  368. }
  369. STDMETHODIMP
  370. CImpIEnumCounter::QueryInterface (
  371. IN REFIID riid,
  372. OUT PVOID *ppv
  373. )
  374. {
  375. HRESULT hr = S_OK;
  376. if (ppv == NULL) {
  377. return E_POINTER;
  378. }
  379. try {
  380. *ppv = NULL;
  381. if ((riid == IID_IUnknown) || (riid == IID_IEnumVARIANT)) {
  382. *ppv = this;
  383. AddRef();
  384. } else {
  385. hr = E_NOINTERFACE;
  386. }
  387. } catch (...) {
  388. hr = E_POINTER;
  389. }
  390. return hr;
  391. }
  392. STDMETHODIMP_(ULONG)
  393. CImpIEnumCounter::AddRef (
  394. VOID
  395. )
  396. {
  397. return ++m_cRef;
  398. }
  399. STDMETHODIMP_(ULONG)
  400. CImpIEnumCounter::Release(
  401. VOID
  402. )
  403. {
  404. if (--m_cRef == 0) {
  405. if (m_paGraphItem != NULL)
  406. free(m_paGraphItem);
  407. delete this;
  408. return 0;
  409. }
  410. return m_cRef;
  411. }
  412. STDMETHODIMP
  413. CImpIEnumCounter::Next(
  414. IN ULONG cItems,
  415. OUT VARIANT *varItem,
  416. OUT ULONG *pcReturned
  417. )
  418. {
  419. HRESULT hr = S_OK;
  420. ULONG i;
  421. ULONG cRet;
  422. if (varItem == NULL) {
  423. return E_POINTER;
  424. }
  425. try {
  426. //
  427. // Clear the return variants
  428. //
  429. for (i = 0; i < cItems; i++) {
  430. VariantInit(&varItem[i]);
  431. }
  432. //
  433. // Try to fill the caller's array
  434. //
  435. for (cRet = 0; cRet < cItems; cRet++) {
  436. //
  437. // No more, return success with false
  438. //
  439. if (m_uCurrent == m_cItems) {
  440. hr = S_FALSE;
  441. break;
  442. }
  443. //
  444. // Get a dispatch interface for the item
  445. //
  446. hr = m_paGraphItem[m_uCurrent]->QueryInterface(DIID_DICounterItem,
  447. (PVOID*)&V_DISPATCH(&varItem[cRet]));
  448. if (FAILED(hr)) {
  449. break;
  450. }
  451. V_VT(&varItem[cRet]) = VT_DISPATCH;
  452. m_uCurrent++;
  453. }
  454. //
  455. // If failed, clear out the variants
  456. //
  457. if (FAILED(hr)) {
  458. for (i = 0; i < cItems; i++) {
  459. if (V_VT(&varItem[i]) == VT_DISPATCH) {
  460. V_DISPATCH(&varItem[i])->Release();
  461. }
  462. VariantClear(&varItem[i]);
  463. }
  464. cRet = 0;
  465. }
  466. // If desired, return number of items fetched
  467. if (pcReturned) {
  468. *pcReturned = cRet;
  469. }
  470. } catch (...) {
  471. hr = E_POINTER;
  472. }
  473. return hr;
  474. }
  475. /***
  476. *HRESULT CEnumPoint::Skip(unsigned long)
  477. *Purpose:
  478. * Attempt to skip over the next 'celt' elements in the enumeration
  479. * sequence.
  480. *
  481. *Entry:
  482. * celt = the count of elements to skip
  483. *
  484. *Exit:
  485. * return value = HRESULT
  486. * S_OK
  487. * S_FALSE - the end of the sequence was reached
  488. *
  489. ***********************************************************************/
  490. STDMETHODIMP
  491. CImpIEnumCounter::Skip(
  492. IN ULONG cItems
  493. )
  494. {
  495. m_uCurrent += cItems;
  496. if (m_uCurrent > m_cItems) {
  497. m_uCurrent = m_cItems;
  498. return S_FALSE;
  499. }
  500. return S_OK;
  501. }
  502. /***
  503. *HRESULT CEnumPoint::Reset(void)
  504. *Purpose:
  505. * Reset the enumeration sequence back to the beginning.
  506. *
  507. *Entry:
  508. * None
  509. *
  510. *Exit:
  511. * return value = SHRESULT CODE
  512. * S_OK
  513. *
  514. ***********************************************************************/
  515. STDMETHODIMP
  516. CImpIEnumCounter::Reset(
  517. VOID
  518. )
  519. {
  520. m_uCurrent = 0;
  521. return S_OK;
  522. }
  523. /***
  524. *HRESULT CEnumPoint::Clone(IEnumVARIANT**)
  525. *Purpose:
  526. * Retrun a CPoint enumerator with exactly the same state as the
  527. * current one.
  528. *
  529. *Entry:
  530. * None
  531. *
  532. *Exit:
  533. * return value = HRESULT
  534. * S_OK
  535. * E_OUTOFMEMORY
  536. *
  537. ***********************************************************************/
  538. STDMETHODIMP
  539. CImpIEnumCounter::Clone (
  540. OUT IEnumVARIANT **ppEnum
  541. )
  542. {
  543. HRESULT hr = S_OK;
  544. ULONG i;
  545. CImpIEnumCounter *pNewEnum = NULL;
  546. if (ppEnum == NULL) {
  547. return E_POINTER;
  548. }
  549. try {
  550. *ppEnum = NULL;
  551. //
  552. // Create new enumerator
  553. //
  554. pNewEnum = new CImpIEnumCounter;
  555. if ( NULL != pNewEnum ) {
  556. // Init, copy item list and current position
  557. pNewEnum->m_cItems = m_cItems;
  558. pNewEnum->m_uCurrent = m_uCurrent;
  559. pNewEnum->m_paGraphItem = (PCGraphItem*)malloc(sizeof(PCGraphItem) * m_cItems);
  560. if ( NULL != pNewEnum->m_paGraphItem ) {
  561. for (i = 0; i < m_cItems; i++) {
  562. pNewEnum->m_paGraphItem[i] = m_paGraphItem[i];
  563. }
  564. *ppEnum = pNewEnum;
  565. }
  566. else {
  567. hr = E_OUTOFMEMORY;
  568. }
  569. } else {
  570. hr = E_OUTOFMEMORY;
  571. }
  572. } catch (...) {
  573. hr = E_POINTER;
  574. }
  575. if (FAILED(hr) && pNewEnum != NULL) {
  576. if (pNewEnum->m_paGraphItem != NULL) {
  577. free(pNewEnum->m_paGraphItem);
  578. }
  579. delete pNewEnum;
  580. }
  581. return hr;
  582. }