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.

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