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.

810 lines
19 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. cntrtree.cpp
  5. Abstract:
  6. Implements internal counter management.
  7. --*/
  8. #include "polyline.h"
  9. #include <strsafe.h>
  10. #include <assert.h>
  11. #include <pdhmsg.h>
  12. #include "smonmsg.h"
  13. #include "appmema.h"
  14. #include "grphitem.h"
  15. #include "cntrtree.h"
  16. CCounterTree::CCounterTree()
  17. : m_nItems (0)
  18. {
  19. }
  20. HRESULT
  21. CCounterTree::AddCounterItem(
  22. LPWSTR pszPath,
  23. PCGraphItem pItem,
  24. BOOL bMonitorDuplicateInstances
  25. )
  26. {
  27. HRESULT hr;
  28. PPDH_COUNTER_PATH_ELEMENTS pPathInfo = NULL;
  29. ULONG ulBufSize;
  30. PDH_STATUS stat;
  31. CMachineNode *pMachine;
  32. CObjectNode *pObject;
  33. CCounterNode *pCounter;
  34. CInstanceNode *pInstance;
  35. if ( NULL != pszPath && NULL != pItem ) {
  36. // Record whether machine is explicit or defaults to local
  37. pItem->m_fLocalMachine = !(pszPath[0] == L'\\' && pszPath[1] == L'\\');
  38. pPathInfo = NULL;
  39. do {
  40. if (pPathInfo) {
  41. delete [] ((char*)pPathInfo);
  42. pPathInfo = NULL;
  43. }
  44. else {
  45. ulBufSize = sizeof(PDH_COUNTER_PATH_ELEMENTS) + sizeof(WCHAR) * PDH_MAX_COUNTER_PATH;
  46. }
  47. pPathInfo = (PPDH_COUNTER_PATH_ELEMENTS) new char [ ulBufSize ];
  48. if (pPathInfo == NULL) {
  49. return E_OUTOFMEMORY;
  50. }
  51. stat = PdhParseCounterPath( pszPath, pPathInfo, & ulBufSize, 0);
  52. } while (stat == PDH_INSUFFICIENT_BUFFER || stat == PDH_MORE_DATA);
  53. //
  54. // We use do {} while (0) here to act like a switch statement
  55. //
  56. do {
  57. if (stat != ERROR_SUCCESS) {
  58. hr = E_FAIL;
  59. break;
  60. }
  61. // Find or create each level of hierarchy
  62. hr = GetMachine( pPathInfo->szMachineName, &pMachine);
  63. if (FAILED(hr) || NULL == pMachine ) {
  64. break;
  65. }
  66. hr = pMachine->GetCounterObject(pPathInfo->szObjectName, &pObject);
  67. if (FAILED(hr) || NULL == pObject ) {
  68. break;
  69. }
  70. hr = pObject->GetCounter(pPathInfo->szCounterName, &pCounter);
  71. if (FAILED(hr) || NULL == pCounter ) {
  72. break;
  73. }
  74. hr = pObject->GetInstance(
  75. pPathInfo->szParentInstance,
  76. pPathInfo->szInstanceName,
  77. pPathInfo->dwInstanceIndex,
  78. bMonitorDuplicateInstances,
  79. &pInstance);
  80. if (FAILED(hr) || NULL == pInstance ) {
  81. break;
  82. }
  83. hr = pInstance->AddItem(pCounter, pItem);
  84. if (SUCCEEDED(hr)) {
  85. m_nItems++;
  86. UpdateAppPerfDwordData (DD_ITEM_COUNT, m_nItems);
  87. }
  88. } while (0);
  89. } else {
  90. hr = E_INVALIDARG;
  91. }
  92. if (pPathInfo) {
  93. delete [] ((char*)pPathInfo);
  94. }
  95. return hr;
  96. }
  97. HRESULT
  98. CCounterTree::GetMachine (
  99. IN LPWSTR pszName,
  100. OUT PCMachineNode *ppMachineRet
  101. )
  102. {
  103. PCMachineNode pMachine = NULL;
  104. PCMachineNode pMachineNew = NULL;
  105. HRESULT hr = NOERROR;
  106. if ( NULL == ppMachineRet || NULL == pszName ) {
  107. hr = E_POINTER;
  108. } else {
  109. *ppMachineRet = NULL;
  110. if (m_listMachines.FindByName(pszName, FIELD_OFFSET(CMachineNode, m_szName), (PCNamedNode*)&pMachine)) {
  111. *ppMachineRet = pMachine;
  112. hr = NOERROR;
  113. } else {
  114. pMachineNew = new(lstrlen(pszName) * sizeof(WCHAR)) CMachineNode;
  115. if (!pMachineNew) {
  116. hr = E_OUTOFMEMORY;
  117. } else {
  118. pMachineNew->m_pCounterTree = this;
  119. StringCchCopy(pMachineNew->m_szName, lstrlen(pszName) + 1, pszName);
  120. m_listMachines.Add(pMachineNew, pMachine);
  121. *ppMachineRet = pMachineNew;
  122. hr = NOERROR;
  123. }
  124. }
  125. }
  126. return hr;
  127. }
  128. void
  129. CCounterTree::RemoveMachine (
  130. IN PCMachineNode pMachine
  131. )
  132. {
  133. // Remove machine from list and delete it
  134. m_listMachines.Remove(pMachine);
  135. delete pMachine ;
  136. }
  137. PCGraphItem
  138. CCounterTree::FirstCounter (
  139. void
  140. )
  141. {
  142. if (!FirstMachine())
  143. return NULL;
  144. else
  145. return FirstMachine()->FirstObject()->FirstInstance()->FirstItem();
  146. }
  147. HRESULT
  148. CCounterTree::IndexFromCounter (
  149. IN const CGraphItem* pItem,
  150. OUT INT* pIndex )
  151. {
  152. HRESULT hr = E_POINTER;
  153. CGraphItem* pLocalItem;
  154. INT iLocalIndex = 0;
  155. if ( NULL != pItem && NULL != pIndex ) {
  156. *pIndex = 0;
  157. hr = E_INVALIDARG;
  158. pLocalItem = FirstCounter();
  159. while ( NULL != pLocalItem ) {
  160. iLocalIndex++;
  161. if ( pLocalItem != pItem ) {
  162. pLocalItem = pLocalItem->Next();
  163. } else {
  164. *pIndex = iLocalIndex;
  165. hr = S_OK;
  166. break;
  167. }
  168. }
  169. }
  170. return hr;
  171. }
  172. HRESULT
  173. CMachineNode::GetCounterObject (
  174. IN LPWSTR pszName,
  175. OUT PCObjectNode *ppObjectRet
  176. )
  177. {
  178. PCObjectNode pObject;
  179. PCObjectNode pObjectNew;
  180. if (m_listObjects.FindByName(pszName, FIELD_OFFSET(CObjectNode, m_szName), (PCNamedNode*)&pObject)) {
  181. *ppObjectRet = pObject;
  182. return NOERROR;
  183. }
  184. pObjectNew = new(lstrlen(pszName) * sizeof(WCHAR)) CObjectNode;
  185. if (!pObjectNew)
  186. return E_OUTOFMEMORY;
  187. pObjectNew->m_pMachine = this;
  188. StringCchCopy(pObjectNew->m_szName, lstrlen(pszName) + 1, pszName);
  189. m_listObjects.Add(pObjectNew, pObject);
  190. *ppObjectRet = pObjectNew;
  191. return NOERROR;
  192. }
  193. void
  194. CMachineNode::RemoveObject (
  195. IN PCObjectNode pObject
  196. )
  197. {
  198. // Remove object from list and delete it
  199. m_listObjects.Remove(pObject);
  200. delete pObject;
  201. // If this was the last one, remove ourself
  202. if (m_listObjects.IsEmpty())
  203. m_pCounterTree->RemoveMachine(this);
  204. }
  205. void
  206. CMachineNode::DeleteNode (
  207. BOOL bPropagateUp
  208. )
  209. {
  210. PCObjectNode pObject;
  211. PCObjectNode pNextObject;
  212. // Delete all object nodes
  213. pObject = FirstObject();
  214. while ( NULL != pObject ) {
  215. pNextObject = pObject->Next();
  216. pObject->DeleteNode(FALSE);
  217. m_listObjects.Remove(pObject);
  218. delete pObject;
  219. pObject = pNextObject;
  220. }
  221. assert(m_listObjects.IsEmpty());
  222. // Notify parent if requested
  223. if (bPropagateUp) {
  224. m_pCounterTree->RemoveMachine(this);
  225. }
  226. }
  227. HRESULT
  228. CObjectNode::GetCounter (
  229. IN LPWSTR pszName,
  230. OUT PCCounterNode *ppCounterRet
  231. )
  232. {
  233. PCCounterNode pCounter;
  234. PCCounterNode pCounterNew;
  235. if (m_listCounters.FindByName(pszName, FIELD_OFFSET(CCounterNode, m_szName), (PCNamedNode*)&pCounter)) {
  236. *ppCounterRet = pCounter;
  237. return NOERROR;
  238. }
  239. pCounterNew = new(lstrlen(pszName) * sizeof(WCHAR)) CCounterNode;
  240. if (!pCounterNew)
  241. return E_OUTOFMEMORY;
  242. pCounterNew->m_pObject = this;
  243. StringCchCopy(pCounterNew->m_szName, lstrlen(pszName) + 1, pszName);
  244. m_listCounters.Add(pCounterNew, pCounter);
  245. *ppCounterRet = pCounterNew;
  246. return NOERROR;
  247. }
  248. //
  249. // The minimum of length of instance name is
  250. // 12. 10 characters for index number(4G)
  251. // 1 for '#' and 1 for terminating 0.
  252. //
  253. #define MIN_INSTANCE_NAME_LEN 12
  254. HRESULT
  255. CObjectNode::GetInstance (
  256. IN LPWSTR pszParent,
  257. IN LPWSTR pszInstance,
  258. IN DWORD dwIndex,
  259. IN BOOL bMonitorDuplicateInstances,
  260. OUT PCInstanceNode *ppInstanceRet
  261. )
  262. {
  263. HRESULT hr = NOERROR;
  264. PCInstanceNode pInstance;
  265. PCInstanceNode pInstanceNew;
  266. LPWSTR szInstName = NULL;
  267. LONG lSize = MIN_INSTANCE_NAME_LEN;
  268. LONG lInstanceLen = 0;
  269. LONG lParentLen = 0;
  270. //
  271. // Calculate the length of the buffer to
  272. // hold the instance and parent names.
  273. //
  274. if (pszInstance) {
  275. lSize += lstrlen(pszInstance);
  276. }
  277. if (pszParent) {
  278. lParentLen = lstrlen(pszParent);
  279. }
  280. lSize += lParentLen + 1;
  281. szInstName = new WCHAR [lSize];
  282. if (szInstName == NULL) {
  283. return E_OUTOFMEMORY;
  284. }
  285. //
  286. // Initialize the string
  287. //
  288. szInstName[0] = L'\0';
  289. if (pszInstance) {
  290. //
  291. // If the parent name exists, copy it
  292. //
  293. if (pszParent) {
  294. StringCchCopy(szInstName, lSize, pszParent);
  295. szInstName[lParentLen] = L'/';
  296. szInstName[lParentLen+1] = L'\0';
  297. }
  298. //
  299. // Copy the instance name.
  300. //
  301. StringCchCat(szInstName, lSize, pszInstance);
  302. //
  303. // Append instance index
  304. //
  305. // "#n" is only appended to the stored name if the index is > 0.
  306. //
  307. if ( dwIndex > 0 && bMonitorDuplicateInstances ) {
  308. StringCchPrintf(&szInstName[lstrlen(szInstName)],
  309. lSize - lstrlen(szInstName),
  310. L"#%d",
  311. dwIndex);
  312. }
  313. }
  314. //
  315. // We use do {} while (0) to act like a switch statement
  316. //
  317. do {
  318. if (m_listInstances.FindByName(szInstName,
  319. FIELD_OFFSET(CInstanceNode, m_szName),
  320. (PCNamedNode*)&pInstance)) {
  321. *ppInstanceRet = pInstance;
  322. break;
  323. }
  324. //
  325. // Create a new one if can not find it
  326. //
  327. lInstanceLen = lstrlen(szInstName);
  328. pInstanceNew = new(lInstanceLen * sizeof(WCHAR)) CInstanceNode;
  329. if (!pInstanceNew) {
  330. hr = E_OUTOFMEMORY;
  331. break;
  332. }
  333. pInstanceNew->m_pObject = this;
  334. pInstanceNew->m_nParentLen = lParentLen;
  335. StringCchCopy(pInstanceNew->m_szName, lInstanceLen + 1, szInstName);
  336. m_listInstances.Add(pInstanceNew, pInstance);
  337. *ppInstanceRet = pInstanceNew;
  338. } while (0);
  339. if (szInstName) {
  340. delete [] szInstName;
  341. }
  342. return hr;
  343. }
  344. void
  345. CObjectNode::RemoveInstance (
  346. IN PCInstanceNode pInstance
  347. )
  348. {
  349. // Remove instance from list and delete it
  350. m_listInstances.Remove(pInstance);
  351. if (pInstance->m_pCachedParentName) {
  352. delete [] pInstance->m_pCachedParentName;
  353. }
  354. if (pInstance->m_pCachedInstName) {
  355. delete [] pInstance->m_pCachedInstName;
  356. }
  357. delete pInstance ;
  358. // if that was the last instance, remove ourself
  359. if (m_listInstances.IsEmpty())
  360. m_pMachine->RemoveObject(this);
  361. }
  362. void
  363. CObjectNode::RemoveCounter (
  364. IN PCCounterNode pCounter
  365. )
  366. {
  367. // Remove counter from list and delete it
  368. m_listCounters.Remove(pCounter);
  369. delete pCounter;
  370. // Don't propagate removal up to object.
  371. // It will go away when the last instance is removed.
  372. }
  373. void
  374. CObjectNode::DeleteNode (
  375. BOOL bPropagateUp
  376. )
  377. {
  378. PCInstanceNode pInstance;
  379. PCInstanceNode pNextInstance;
  380. // Delete all instance nodes
  381. pInstance = FirstInstance();
  382. while ( NULL != pInstance ) {
  383. pNextInstance = pInstance->Next();
  384. pInstance->DeleteNode(FALSE);
  385. m_listInstances.Remove(pInstance);
  386. delete pInstance;
  387. pInstance = pNextInstance;
  388. }
  389. // No need to delete counters nodes as they get
  390. // deleted as their last paired instance does
  391. // Notify parent if requested
  392. if (bPropagateUp)
  393. m_pMachine->RemoveObject(this);
  394. }
  395. HRESULT
  396. CInstanceNode::AddItem (
  397. IN PCCounterNode pCounter,
  398. IN PCGraphItem pItemNew
  399. )
  400. {
  401. PCGraphItem pItemPrev = NULL;
  402. PCGraphItem pItem = m_pItems;
  403. INT iStat = 1;
  404. // Check for existing item for specified counter, stopping at insertion point
  405. while ( pItem != NULL && (iStat = lstrcmp(pCounter->Name(), pItem->m_pCounter->Name())) > 0) {
  406. pItemPrev = pItem;
  407. pItem = pItem->m_pNextItem;
  408. }
  409. // if item exists, return duplicate error status
  410. if (iStat == 0) {
  411. return SMON_STATUS_DUPL_COUNTER_PATH;
  412. }
  413. // else insert the new item
  414. else {
  415. if (pItemPrev != NULL) {
  416. pItemNew->m_pNextItem = pItemPrev->m_pNextItem;
  417. pItemPrev->m_pNextItem = pItemNew;
  418. }
  419. else if (m_pItems != NULL) {
  420. pItemNew->m_pNextItem = m_pItems;
  421. m_pItems = pItemNew;
  422. }
  423. else {
  424. m_pItems = pItemNew;
  425. }
  426. }
  427. // Set back links
  428. pItemNew->m_pInstance = this;
  429. pItemNew->m_pCounter = pCounter;
  430. pCounter->AddItem(pItem);
  431. return NOERROR;
  432. }
  433. void
  434. CInstanceNode::RemoveItem (
  435. IN PCGraphItem pitem
  436. )
  437. {
  438. PCGraphItem pitemPrev = NULL;
  439. PCGraphItem pitemTemp = m_pItems;
  440. // Locate item in list
  441. while (pitemTemp != NULL && pitemTemp != pitem) {
  442. pitemPrev = pitemTemp;
  443. pitemTemp = pitemTemp->m_pNextItem;
  444. }
  445. if (pitemTemp == NULL)
  446. return;
  447. // Remove from list
  448. if (pitemPrev)
  449. pitemPrev->m_pNextItem = pitem->m_pNextItem;
  450. else
  451. m_pItems = pitem->m_pNextItem;
  452. // Remove item from Counter set
  453. pitem->Counter()->RemoveItem(pitem);
  454. // Decrement the total item count
  455. pitem->Tree()->m_nItems--;
  456. UpdateAppPerfDwordData (DD_ITEM_COUNT, pitem->Tree()->m_nItems);
  457. // Release the item
  458. pitem->Release();
  459. // if last item under this instance, remove the instance
  460. if (m_pItems == NULL)
  461. m_pObject->RemoveInstance(this);
  462. }
  463. void
  464. CInstanceNode::DeleteNode (
  465. BOOL bPropagateUp
  466. )
  467. {
  468. PCGraphItem pItem;
  469. pItem = m_pItems;
  470. while ( NULL != pItem ) {
  471. m_pItems = pItem->m_pNextItem;
  472. pItem->Delete(FALSE);
  473. pItem->Counter()->RemoveItem(pItem);
  474. pItem->Release();
  475. pItem = m_pItems;
  476. }
  477. if (bPropagateUp)
  478. m_pObject->RemoveInstance(this);
  479. }
  480. LPWSTR
  481. CInstanceNode::GetParentName()
  482. {
  483. if (m_pCachedParentName == NULL) {
  484. m_pCachedParentName = new WCHAR [m_nParentLen + 1];
  485. if (m_pCachedParentName == NULL) {
  486. return L"";
  487. }
  488. if (m_nParentLen) {
  489. StringCchCopy(m_pCachedParentName, m_nParentLen + 1, m_szName);
  490. }
  491. else {
  492. m_pCachedParentName[0] = 0;
  493. }
  494. }
  495. return m_pCachedParentName;
  496. }
  497. LPWSTR
  498. CInstanceNode::GetInstanceName()
  499. {
  500. LPWSTR pszInst = m_nParentLen ? (m_szName + m_nParentLen + 1) : m_szName;
  501. if (m_pCachedInstName == NULL) {
  502. m_pCachedInstName = new WCHAR [lstrlen(pszInst) + 1];
  503. if (m_pCachedInstName == NULL) {
  504. return L"";
  505. }
  506. StringCchCopy(m_pCachedInstName, lstrlen(pszInst) + 1, pszInst);
  507. }
  508. return m_pCachedInstName;
  509. }
  510. void
  511. CCounterNode::DeleteNode (
  512. BOOL bPropagateUp
  513. )
  514. {
  515. PCInstanceNode pInstance, pInstNext;
  516. PCGraphItem pItem, pItemNext;
  517. if (!bPropagateUp)
  518. return;
  519. // We have to delete the counters item via the instances
  520. // because they maintain the linked list of items
  521. pInstance = m_pObject->FirstInstance();
  522. while (pInstance) {
  523. pInstNext = pInstance->Next();
  524. pItem = pInstance->FirstItem();
  525. while (pItem) {
  526. if (pItem->Counter() == this) {
  527. // Delete all UI associated with the item
  528. pItem->Delete(FALSE);
  529. pItemNext = pItem->m_pNextItem;
  530. // Note that Instance->RemoveItem() will
  531. // also remove counters that have no more items
  532. pItem->Instance()->RemoveItem(pItem);
  533. pItem = pItemNext;
  534. }
  535. else {
  536. pItem = pItem->m_pNextItem;
  537. }
  538. }
  539. pInstance = pInstNext;
  540. }
  541. }
  542. /*******************************
  543. CCounterNode::~CCounterNode (
  544. IN PCGraphItem pItem
  545. )
  546. {
  547. PCGraphItem pItemPrev = NULL;
  548. PCGraphItem pItemFind = m_pItems;
  549. // Find item in list
  550. while (pItemFind != NULL && pItemFind != pItem) {
  551. pItemPrev = pItem;
  552. pItem = pItem->m_pNextItem;
  553. }
  554. if (pItemFind != pItem)
  555. return E_FAIL;
  556. // Unlink from counter item list
  557. if (pItemPrev)
  558. pItemPrev->m_pNextItem = pItem->m_pNextItem;
  559. else
  560. m_pItems = pItem->m_pNextItem;
  561. // Unlink from instance
  562. pItem->m_pInstance->RemoveCounter(pItem);
  563. // if no more items, remove self from parnet object
  564. if (m_pItems == NULL) {
  565. m_pObject->RemoveCounter(this);
  566. return NOERROR;
  567. }
  568. *******************************/
  569. /*
  570. void*
  571. CMachineNode::operator new( size_t stBlock, LPWSTR pszName )
  572. { return malloc(stBlock + lstrlen(pszName) * sizeof(WCHAR)); }
  573. void
  574. CMachineNode::operator delete ( void * pObject, LPWSTR )
  575. { free(pObject); }
  576. void*
  577. CObjectNode::operator new( size_t stBlock, LPWSTR pszName )
  578. { return malloc(stBlock + lstrlen(pszName) * sizeof(WCHAR)); }
  579. void
  580. CObjectNode::operator delete ( void * pObject, LPWSTR )
  581. { free(pObject); }
  582. void*
  583. CInstanceNode::operator new( size_t stBlock, LPWSTR pszName )
  584. { return malloc(stBlock + lstrlen(pszName) * sizeof(WCHAR)); }
  585. void
  586. CInstanceNode::operator delete ( void * pObject, LPWSTR )
  587. { free(pObject); }
  588. void*
  589. CCounterNode::operator new( size_t stBlock, LPWSTR pszName )
  590. { return malloc(stBlock + lstrlen(pszName) * sizeof(WCHAR)); }
  591. void
  592. CCounterNode::operator delete ( void * pObject, LPWSTR )
  593. { free(pObject); }CMachineNode::operator new( size_t stBlock, INT iLength )
  594. */
  595. void *
  596. CMachineNode::operator new( size_t stBlock, UINT iLength )
  597. {
  598. return malloc(stBlock + iLength);
  599. }
  600. void
  601. CMachineNode::operator delete ( void * pObject, UINT )
  602. {
  603. free(pObject);
  604. }
  605. void*
  606. CObjectNode::operator new( size_t stBlock, UINT iLength )
  607. {
  608. return malloc(stBlock + iLength);
  609. }
  610. void
  611. CObjectNode::operator delete ( void * pObject, UINT )
  612. {
  613. free(pObject);
  614. }
  615. void*
  616. CInstanceNode::operator new( size_t stBlock, UINT iLength )
  617. {
  618. return malloc(stBlock + iLength);
  619. }
  620. void
  621. CInstanceNode::operator delete ( void * pObject, UINT )
  622. {
  623. free(pObject);
  624. }
  625. void*
  626. CCounterNode::operator new( size_t stBlock, UINT iLength )
  627. {
  628. return malloc(stBlock + iLength);
  629. }
  630. void
  631. CCounterNode::operator delete ( void * pObject, UINT )
  632. {
  633. free(pObject);
  634. }
  635. #if _MSC_VER >= 1300
  636. void
  637. CMachineNode::operator delete ( void * pObject )
  638. { free(pObject); }
  639. void
  640. CObjectNode::operator delete ( void * pObject )
  641. { free(pObject); }
  642. void
  643. CInstanceNode::operator delete ( void * pObject )
  644. {
  645. free(pObject);
  646. }
  647. void
  648. CCounterNode::operator delete ( void * pObject )
  649. { free(pObject); }
  650. #endif