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.

811 lines
22 KiB

  1. /*++
  2. Copyright (C) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. smctrqry.cpp
  5. Abstract:
  6. Implementation of the counter log query class.
  7. --*/
  8. #include "Stdafx.h"
  9. #include <pdhp.h> // for MIN_TIME_VALUE, MAX_TIME_VALUE
  10. #include <pdhmsg.h>
  11. #include "smctrqry.h"
  12. USE_HANDLE_MACROS("SMLOGCFG(smctrqry.cpp)");
  13. //
  14. // Constructor
  15. CSmCounterLogQuery::CSmCounterLogQuery( CSmLogService* pLogService )
  16. : CSmLogQuery( pLogService ),
  17. m_dwCounterListLength ( 0 ),
  18. m_szNextCounter ( NULL ),
  19. mr_szCounterList ( NULL )
  20. {
  21. // initialize member variables
  22. memset (&mr_stiSampleInterval, 0, sizeof(mr_stiSampleInterval));
  23. return;
  24. }
  25. //
  26. // Destructor
  27. CSmCounterLogQuery::~CSmCounterLogQuery()
  28. {
  29. return;
  30. }
  31. //
  32. // Open function. either opens an existing log query entry
  33. // or creates a new one
  34. //
  35. DWORD
  36. CSmCounterLogQuery::Open ( const CString& rstrName, HKEY hKeyQuery, BOOL bReadOnly)
  37. {
  38. DWORD dwStatus = ERROR_SUCCESS;
  39. ASSERT ( SLQ_COUNTER_LOG == GetLogType() );
  40. dwStatus = CSmLogQuery::Open ( rstrName, hKeyQuery, bReadOnly );
  41. return dwStatus;
  42. }
  43. //
  44. // Close Function
  45. // closes registry handles and frees allocated memory
  46. //
  47. DWORD
  48. CSmCounterLogQuery::Close ()
  49. {
  50. DWORD dwStatus;
  51. LOCALTRACE (L"Closing Query\n");
  52. if (mr_szCounterList != NULL) {
  53. delete (mr_szCounterList);
  54. mr_szCounterList = NULL;
  55. }
  56. dwStatus = CSmLogQuery::Close();
  57. return dwStatus;
  58. }
  59. //
  60. // UpdateRegistry function.
  61. // copies the current settings to the registry where they
  62. // are read by the log service
  63. //
  64. DWORD
  65. CSmCounterLogQuery::UpdateRegistry()
  66. {
  67. DWORD dwStatus = ERROR_SUCCESS;
  68. DWORD dwBufferSize;
  69. LPTSTR szNewCounterList = NULL;
  70. if ( IsModifiable() ) {
  71. dwBufferSize = 0;
  72. //
  73. // Translate the counter list into English
  74. //
  75. dwStatus = TranslateMSZCounterList(mr_szCounterList,
  76. NULL,
  77. &dwBufferSize,
  78. FALSE);
  79. if (dwStatus == ERROR_NOT_ENOUGH_MEMORY) {
  80. szNewCounterList = (LPTSTR) new char [dwBufferSize];
  81. if (szNewCounterList != NULL) {
  82. dwStatus = TranslateMSZCounterList(mr_szCounterList,
  83. szNewCounterList,
  84. &dwBufferSize,
  85. FALSE);
  86. }
  87. }
  88. if (dwStatus == ERROR_SUCCESS && szNewCounterList != NULL) {
  89. dwStatus = WriteRegistryStringValue (
  90. m_hKeyQuery,
  91. IDS_REG_COUNTER_LIST,
  92. REG_MULTI_SZ,
  93. szNewCounterList,
  94. &dwBufferSize);
  95. }
  96. else {
  97. dwBufferSize = m_dwCounterListLength * sizeof(TCHAR);
  98. dwStatus = WriteRegistryStringValue (
  99. m_hKeyQuery,
  100. IDS_REG_COUNTER_LIST,
  101. REG_MULTI_SZ,
  102. mr_szCounterList,
  103. &dwBufferSize);
  104. }
  105. // Schedule
  106. if ( ERROR_SUCCESS == dwStatus ) {
  107. dwStatus = WriteRegistrySlqTime (
  108. m_hKeyQuery,
  109. IDS_REG_SAMPLE_INTERVAL,
  110. &mr_stiSampleInterval);
  111. }
  112. if ( ERROR_SUCCESS == dwStatus ) {
  113. dwStatus = CSmLogQuery::UpdateRegistry ();
  114. }
  115. } else {
  116. dwStatus = ERROR_ACCESS_DENIED;
  117. }
  118. return dwStatus;
  119. }
  120. //
  121. // SyncWithRegistry()
  122. // reads the current values for this query from the registry
  123. // and reloads the internal values to match
  124. //
  125. //
  126. DWORD
  127. CSmCounterLogQuery::SyncWithRegistry()
  128. {
  129. DWORD dwBufferSize = 0;
  130. DWORD dwStatus = ERROR_SUCCESS;
  131. SLQ_TIME_INFO stiDefault;
  132. LPTSTR szNewCounterList;
  133. ASSERT (m_hKeyQuery != NULL);
  134. // load counter string list
  135. // Get Counter List
  136. dwStatus = ReadRegistryStringValue (
  137. m_hKeyQuery,
  138. IDS_REG_COUNTER_LIST,
  139. NULL,
  140. &mr_szCounterList,
  141. &dwBufferSize);
  142. if (dwStatus != ERROR_SUCCESS) {
  143. m_szNextCounter = NULL; //re-initialize
  144. m_dwCounterListLength = 0;
  145. } else {
  146. m_dwCounterListLength = dwBufferSize / sizeof(TCHAR);
  147. //
  148. // Translate the counter list into Locale
  149. //
  150. dwBufferSize = 0;
  151. dwStatus = TranslateMSZCounterList(
  152. mr_szCounterList,
  153. NULL,
  154. &dwBufferSize,
  155. TRUE);
  156. if (dwStatus == ERROR_NOT_ENOUGH_MEMORY) {
  157. szNewCounterList = (LPTSTR) new char [dwBufferSize];
  158. if (szNewCounterList != NULL) {
  159. //
  160. // Translate the counter list into Locale
  161. //
  162. dwStatus = TranslateMSZCounterList(
  163. mr_szCounterList,
  164. szNewCounterList,
  165. &dwBufferSize,
  166. TRUE);
  167. if (dwStatus == ERROR_SUCCESS) {
  168. m_dwCounterListLength = dwBufferSize / sizeof(TCHAR);
  169. //
  170. // Remove the old
  171. //
  172. delete (mr_szCounterList);
  173. m_szNextCounter = NULL;
  174. mr_szCounterList = szNewCounterList;
  175. }
  176. }
  177. }
  178. }
  179. // Schedule
  180. stiDefault.wTimeType = SLQ_TT_TTYPE_SAMPLE;
  181. stiDefault.dwAutoMode = SLQ_AUTO_MODE_AFTER;
  182. stiDefault.wDataType = SLQ_TT_DTYPE_UNITS;
  183. stiDefault.dwUnitType = SLQ_TT_UTYPE_SECONDS;
  184. stiDefault.dwValue = 15;
  185. dwStatus = ReadRegistrySlqTime (
  186. m_hKeyQuery,
  187. IDS_REG_SAMPLE_INTERVAL,
  188. &stiDefault,
  189. &mr_stiSampleInterval);
  190. ASSERT (dwStatus == ERROR_SUCCESS);
  191. // Call parent class last to update shared values.
  192. dwStatus = CSmLogQuery::SyncWithRegistry();
  193. ASSERT (dwStatus == ERROR_SUCCESS);
  194. return dwStatus;
  195. }
  196. //
  197. // Get first counter in counter list
  198. //
  199. LPCWSTR
  200. CSmCounterLogQuery::GetFirstCounter()
  201. {
  202. LPTSTR szReturn;
  203. szReturn = mr_szCounterList;
  204. if (szReturn != NULL) {
  205. if (*szReturn == 0) {
  206. // then it's an empty string
  207. szReturn = NULL;
  208. m_szNextCounter = NULL;
  209. } else {
  210. m_szNextCounter = szReturn + lstrlen(szReturn) + 1;
  211. if (*m_szNextCounter == 0) {
  212. // end of list reached so set pointer to NULL
  213. m_szNextCounter = NULL;
  214. }
  215. }
  216. } else {
  217. // no buffer allocated yet
  218. m_szNextCounter = NULL;
  219. }
  220. return (LPCWSTR)szReturn;
  221. }
  222. //
  223. // Get next counter in counter list
  224. // NULL pointer means no more counters in list
  225. //
  226. LPCWSTR
  227. CSmCounterLogQuery::GetNextCounter()
  228. {
  229. LPTSTR szReturn;
  230. szReturn = m_szNextCounter;
  231. if (m_szNextCounter != NULL) {
  232. m_szNextCounter += lstrlen(szReturn) + 1;
  233. if (*m_szNextCounter == 0) {
  234. // end of list reached so set pointer to NULL
  235. m_szNextCounter = NULL;
  236. }
  237. } else {
  238. // already at the end of the list so nothing to do
  239. }
  240. return (LPCWSTR)szReturn;
  241. }
  242. //
  243. // clear out the counter list
  244. //
  245. VOID
  246. CSmCounterLogQuery::ResetCounterList()
  247. {
  248. if (mr_szCounterList != NULL) {
  249. delete (mr_szCounterList);
  250. m_szNextCounter = NULL;
  251. mr_szCounterList = NULL;
  252. }
  253. m_dwCounterListLength = sizeof(WCHAR); // sizeof MSZ Null
  254. try {
  255. mr_szCounterList = new WCHAR [m_dwCounterListLength];
  256. mr_szCounterList[0] = 0;
  257. } catch ( ... ) {
  258. m_dwCounterListLength = 0;
  259. }
  260. }
  261. //
  262. // Add this counter string to the internal list
  263. //
  264. BOOL
  265. CSmCounterLogQuery::AddCounter(LPCWSTR szCounterPath)
  266. {
  267. DWORD dwNewSize;
  268. LPTSTR szNewString;
  269. LPTSTR szNextString;
  270. ASSERT (szCounterPath != NULL);
  271. if (szCounterPath == NULL) {
  272. return FALSE;
  273. }
  274. dwNewSize = lstrlen(szCounterPath) + 1;
  275. if (m_dwCounterListLength <= 2) {
  276. dwNewSize += 1; // add room for the MSZ null
  277. // then this is the first string to go in the list
  278. try {
  279. szNewString = new TCHAR [dwNewSize];
  280. } catch ( ... ) {
  281. return FALSE; // leave now
  282. }
  283. szNextString = szNewString;
  284. } else {
  285. dwNewSize += m_dwCounterListLength;
  286. // this is the nth string to go in the list
  287. try {
  288. szNewString = new TCHAR [dwNewSize];
  289. } catch ( ... ) {
  290. return FALSE; // leave now
  291. }
  292. memcpy (szNewString, mr_szCounterList,
  293. (m_dwCounterListLength * sizeof(TCHAR)));
  294. szNextString = szNewString;
  295. szNextString += m_dwCounterListLength - 1;
  296. }
  297. lstrcpyW (szNextString, szCounterPath);
  298. szNextString = szNewString;
  299. szNextString += dwNewSize - 1;
  300. *szNextString = 0; // MSZ Null
  301. if (mr_szCounterList != NULL) {
  302. delete (mr_szCounterList);
  303. }
  304. mr_szCounterList = szNewString;
  305. m_szNextCounter = szNewString;
  306. m_dwCounterListLength = dwNewSize;
  307. return TRUE;
  308. }
  309. BOOL
  310. CSmCounterLogQuery::GetLogTime(PSLQ_TIME_INFO pTimeInfo, DWORD dwFlags)
  311. {
  312. BOOL bStatus;
  313. ASSERT ( ( SLQ_TT_TTYPE_START == dwFlags )
  314. || ( SLQ_TT_TTYPE_STOP == dwFlags )
  315. || ( SLQ_TT_TTYPE_RESTART == dwFlags )
  316. || ( SLQ_TT_TTYPE_SAMPLE == dwFlags ) );
  317. bStatus = CSmLogQuery::GetLogTime( pTimeInfo, dwFlags );
  318. return bStatus;
  319. }
  320. BOOL
  321. CSmCounterLogQuery::SetLogTime(PSLQ_TIME_INFO pTimeInfo, const DWORD dwFlags)
  322. {
  323. BOOL bStatus;
  324. ASSERT ( ( SLQ_TT_TTYPE_START == dwFlags )
  325. || ( SLQ_TT_TTYPE_STOP == dwFlags )
  326. || ( SLQ_TT_TTYPE_RESTART == dwFlags )
  327. || ( SLQ_TT_TTYPE_SAMPLE == dwFlags ) );
  328. bStatus = CSmLogQuery::SetLogTime( pTimeInfo, dwFlags );
  329. return bStatus;
  330. }
  331. BOOL
  332. CSmCounterLogQuery::GetDefaultLogTime(SLQ_TIME_INFO& rTimeInfo, DWORD dwFlags)
  333. {
  334. ASSERT ( ( SLQ_TT_TTYPE_START == dwFlags )
  335. || ( SLQ_TT_TTYPE_STOP == dwFlags ) );
  336. rTimeInfo.wTimeType = (WORD)dwFlags;
  337. rTimeInfo.wDataType = SLQ_TT_DTYPE_DATETIME;
  338. if ( SLQ_TT_TTYPE_START == dwFlags ) {
  339. SYSTEMTIME stLocalTime;
  340. FILETIME ftLocalTime;
  341. // Milliseconds set to 0 for Schedule times
  342. GetLocalTime (&stLocalTime);
  343. stLocalTime.wMilliseconds = 0;
  344. SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
  345. rTimeInfo.dwAutoMode = SLQ_AUTO_MODE_AT;
  346. rTimeInfo.llDateTime = *(LONGLONG *)&ftLocalTime;
  347. } else {
  348. // Default stop values
  349. rTimeInfo.dwAutoMode = SLQ_AUTO_MODE_NONE;
  350. rTimeInfo.llDateTime = MAX_TIME_VALUE;
  351. }
  352. return TRUE;
  353. }
  354. DWORD
  355. CSmCounterLogQuery::GetLogType()
  356. {
  357. return ( SLQ_COUNTER_LOG );
  358. }
  359. HRESULT
  360. CSmCounterLogQuery::LoadCountersFromPropertyBag (
  361. IPropertyBag* pPropBag,
  362. IErrorLog* pIErrorLog )
  363. {
  364. HRESULT hr = S_OK;
  365. PDH_STATUS pdhStatus;
  366. CString strParamName;
  367. DWORD dwCount = 0;
  368. DWORD dwIndex;
  369. LPTSTR szLocaleBuf = NULL;
  370. DWORD dwLocaleBufSize = 0;
  371. hr = DwordFromPropertyBag (
  372. pPropBag,
  373. pIErrorLog,
  374. IDS_HTML_SYSMON_COUNTERCOUNT,
  375. 0,
  376. dwCount);
  377. for ( dwIndex = 1; dwIndex <= dwCount; dwIndex++ ) {
  378. LPTSTR szCounterPath = NULL;
  379. LPTSTR pszPath = NULL;
  380. DWORD dwBufSize = 0;
  381. LPTSTR pNewBuf;
  382. strParamName.Format ( IDS_HTML_SYSMON_COUNTERPATH, dwIndex );
  383. hr = StringFromPropertyBag (
  384. pPropBag,
  385. pIErrorLog,
  386. strParamName,
  387. L"",
  388. &szCounterPath,
  389. &dwBufSize );
  390. pszPath = szCounterPath;
  391. if (dwBufSize > sizeof(TCHAR)) {
  392. //
  393. // Initialize the locale path buffer
  394. //
  395. if (dwLocaleBufSize == 0) {
  396. dwLocaleBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
  397. szLocaleBuf = (LPTSTR) G_ALLOC(dwLocaleBufSize);
  398. if (szLocaleBuf == NULL) {
  399. dwLocaleBufSize = 0;
  400. }
  401. }
  402. if (szLocaleBuf != NULL) {
  403. //
  404. // Translate counter name from English to Localization
  405. //
  406. dwBufSize = dwLocaleBufSize;
  407. pdhStatus = PdhTranslateLocaleCounter(
  408. szCounterPath,
  409. szLocaleBuf,
  410. &dwBufSize);
  411. if (pdhStatus == PDH_MORE_DATA) {
  412. pNewBuf = (LPTSTR)G_REALLOC(szLocaleBuf, dwBufSize);
  413. if (pNewBuf != NULL) {
  414. szLocaleBuf = pNewBuf;
  415. dwLocaleBufSize = dwBufSize;
  416. pdhStatus = PdhTranslateLocaleCounter(
  417. szCounterPath,
  418. szLocaleBuf,
  419. &dwBufSize);
  420. }
  421. }
  422. if (pdhStatus == ERROR_SUCCESS) {
  423. pszPath = szLocaleBuf;
  424. }
  425. }
  426. AddCounter ( pszPath );
  427. }
  428. delete (szCounterPath);
  429. }
  430. if (szLocaleBuf != NULL) {
  431. G_FREE(szLocaleBuf);
  432. }
  433. return hr;
  434. }
  435. HRESULT
  436. CSmCounterLogQuery::LoadFromPropertyBag (
  437. IPropertyBag* pPropBag,
  438. IErrorLog* pIErrorLog )
  439. {
  440. HRESULT hr = S_OK;
  441. SLQ_TIME_INFO stiDefault;
  442. // Continue even if error, using defaults for missing values.
  443. hr = LoadCountersFromPropertyBag( pPropBag, pIErrorLog );
  444. stiDefault.wTimeType = SLQ_TT_TTYPE_SAMPLE;
  445. stiDefault.dwAutoMode = SLQ_AUTO_MODE_AFTER;
  446. stiDefault.wDataType = SLQ_TT_DTYPE_UNITS;
  447. stiDefault.dwUnitType = SLQ_TT_UTYPE_SECONDS;
  448. stiDefault.dwValue = 15;
  449. hr = SlqTimeFromPropertyBag (
  450. pPropBag,
  451. pIErrorLog,
  452. SLQ_TT_TTYPE_SAMPLE,
  453. &stiDefault,
  454. &mr_stiSampleInterval );
  455. hr = CSmLogQuery::LoadFromPropertyBag( pPropBag, pIErrorLog );
  456. return hr;
  457. }
  458. HRESULT
  459. CSmCounterLogQuery::SaveCountersToPropertyBag (
  460. IPropertyBag* pPropBag )
  461. {
  462. HRESULT hr = NOERROR;
  463. CString strParamName;
  464. LPCTSTR pszCounterPath;
  465. LPTSTR szEnglishBuf = NULL;
  466. DWORD dwEnglishBufSize = 0;
  467. LPCTSTR pszPath = NULL;
  468. PDH_STATUS pdhStatus;
  469. DWORD dwIndex = 0;
  470. pszCounterPath = GetFirstCounter();
  471. MFC_TRY
  472. // Passing sz ( TCHAR[n] ) causes memory alloc, which might throw an exception
  473. while ( NULL != pszCounterPath ) {
  474. LPTSTR pNewBuf;
  475. DWORD dwBufSize;
  476. pszPath = pszCounterPath;
  477. //
  478. // Initialize the locale path buffer
  479. //
  480. if (dwEnglishBufSize == 0) {
  481. dwEnglishBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
  482. szEnglishBuf = (LPTSTR) G_ALLOC(dwEnglishBufSize);
  483. if (szEnglishBuf == NULL) {
  484. dwEnglishBufSize = 0;
  485. }
  486. }
  487. if (szEnglishBuf != NULL) {
  488. //
  489. // Translate counter name from Localization into English
  490. //
  491. dwBufSize = dwEnglishBufSize;
  492. pdhStatus = PdhTranslate009Counter(
  493. (LPTSTR)pszCounterPath,
  494. szEnglishBuf,
  495. &dwBufSize);
  496. if (pdhStatus == PDH_MORE_DATA) {
  497. pNewBuf = (LPTSTR)G_REALLOC(szEnglishBuf, dwBufSize);
  498. if (pNewBuf != NULL) {
  499. szEnglishBuf = pNewBuf;
  500. dwEnglishBufSize = dwBufSize;
  501. pdhStatus = PdhTranslate009Counter(
  502. (LPTSTR)pszCounterPath,
  503. szEnglishBuf,
  504. &dwBufSize);
  505. }
  506. }
  507. if (pdhStatus == ERROR_SUCCESS) {
  508. pszPath = szEnglishBuf;
  509. }
  510. }
  511. // Counter path count starts with 1.
  512. strParamName.Format ( IDS_HTML_SYSMON_COUNTERPATH, ++dwIndex );
  513. hr = StringToPropertyBag ( pPropBag, strParamName, pszPath );
  514. pszCounterPath = GetNextCounter();
  515. }
  516. hr = DwordToPropertyBag ( pPropBag, IDS_HTML_SYSMON_COUNTERCOUNT, dwIndex );
  517. MFC_CATCH_HR
  518. if (szEnglishBuf != NULL) {
  519. G_FREE(szEnglishBuf);
  520. }
  521. return hr;
  522. }
  523. HRESULT
  524. CSmCounterLogQuery::SaveToPropertyBag (
  525. IPropertyBag* pPropBag,
  526. BOOL fSaveAllProps )
  527. {
  528. HRESULT hr = NOERROR;
  529. hr = CSmLogQuery::SaveToPropertyBag( pPropBag, fSaveAllProps );
  530. hr = SaveCountersToPropertyBag ( pPropBag );
  531. hr = SlqTimeToPropertyBag ( pPropBag, SLQ_TT_TTYPE_SAMPLE, &mr_stiSampleInterval );
  532. return hr;
  533. }
  534. HRESULT
  535. CSmCounterLogQuery::TranslateMSZCounterList(
  536. LPTSTR pszCounterList,
  537. LPTSTR pBuffer,
  538. LPDWORD pdwBufferSize,
  539. BOOL bFlag
  540. )
  541. {
  542. LPTSTR pTmpBuf = NULL;
  543. DWORD dwTmpBufSize = 0;
  544. DWORD dwSize = 0;
  545. LPTSTR pNewBuf = NULL;
  546. LPTSTR pszCounterPath = NULL;
  547. LPTSTR pszCounterPathToAdd = NULL;
  548. LPTSTR pNextStringPosition = NULL;
  549. BOOL bNotEnoughBuffer = FALSE;
  550. DWORD dwNewCounterListLen = 0;
  551. DWORD dwCounterPathLen = 0;
  552. PDH_STATUS Status = ERROR_SUCCESS;
  553. if (pszCounterList == NULL || pdwBufferSize == NULL) {
  554. Status = ERROR_INVALID_PARAMETER;
  555. goto ErrorOut;
  556. }
  557. if (pBuffer == NULL || *pdwBufferSize == 0) {
  558. bNotEnoughBuffer = TRUE;
  559. }
  560. //
  561. // Probe parameters
  562. //
  563. __try {
  564. if (* pdwBufferSize != 0 && pBuffer != NULL) {
  565. *pBuffer = 0;
  566. * (LPTSTR) ( ((LPBYTE) pBuffer)
  567. + ((* pdwBufferSize) - sizeof(*pBuffer)) ) = 0;
  568. }
  569. pszCounterPath = pszCounterList;
  570. while (*pszCounterPath) {
  571. pszCounterPathToAdd = pszCounterPath;
  572. //
  573. // Initialize the buffer used for translating counter path
  574. // called only once
  575. //
  576. if (pTmpBuf == NULL) {
  577. dwTmpBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
  578. pTmpBuf = (LPTSTR) G_ALLOC(dwTmpBufSize);
  579. if (pTmpBuf == NULL) {
  580. Status = ERROR_OUTOFMEMORY;
  581. goto ErrorOut;
  582. }
  583. }
  584. if (pTmpBuf != NULL) {
  585. dwSize = dwTmpBufSize;
  586. if (bFlag) {
  587. Status = PdhTranslateLocaleCounter(
  588. pszCounterPath,
  589. pTmpBuf,
  590. &dwSize);
  591. }
  592. else {
  593. Status = PdhTranslate009Counter(
  594. pszCounterPath,
  595. pTmpBuf,
  596. &dwSize);
  597. }
  598. if (Status == PDH_MORE_DATA) {
  599. pNewBuf = (LPTSTR) G_REALLOC(pTmpBuf, dwSize);
  600. if (pNewBuf == NULL) {
  601. Status = ERROR_OUTOFMEMORY;
  602. goto ErrorOut;
  603. }
  604. pTmpBuf = pNewBuf;
  605. dwTmpBufSize = dwSize;
  606. //
  607. // Try second time
  608. //
  609. if (bFlag) {
  610. Status = PdhTranslateLocaleCounter(
  611. pszCounterPath,
  612. pTmpBuf,
  613. &dwSize);
  614. }
  615. else {
  616. Status = PdhTranslate009Counter(
  617. pszCounterPath,
  618. pTmpBuf,
  619. &dwSize);
  620. }
  621. }
  622. if (Status == ERROR_SUCCESS) {
  623. pszCounterPathToAdd = pTmpBuf;
  624. }
  625. }
  626. //
  627. // Add the translated counter path(it is the original
  628. // counter path if translation failed) to the new counter
  629. // path list
  630. //
  631. dwCounterPathLen = lstrlen(pszCounterPathToAdd) + 1;
  632. dwNewCounterListLen += dwCounterPathLen;
  633. if (! bNotEnoughBuffer) {
  634. if ( (dwNewCounterListLen + 1) * sizeof(TCHAR) <= *pdwBufferSize) {
  635. //
  636. // Set up the copy position
  637. //
  638. pNextStringPosition = pBuffer + dwNewCounterListLen - dwCounterPathLen;
  639. lstrcpy(pNextStringPosition, pszCounterPathToAdd);
  640. }
  641. else {
  642. bNotEnoughBuffer = TRUE;
  643. }
  644. }
  645. //
  646. // Continue processing next counter path
  647. //
  648. pszCounterPath += lstrlen(pszCounterPath) + 1;
  649. }
  650. dwNewCounterListLen ++;
  651. if (! bNotEnoughBuffer) {
  652. //
  653. // Append the terminating 0
  654. //
  655. pBuffer[dwNewCounterListLen-1] = 0;
  656. }
  657. else {
  658. Status = ERROR_NOT_ENOUGH_MEMORY;
  659. }
  660. *pdwBufferSize = dwNewCounterListLen * sizeof(TCHAR);
  661. } __except (EXCEPTION_EXECUTE_HANDLER) {
  662. Status = ERROR_INVALID_PARAMETER;
  663. }
  664. ErrorOut:
  665. if (pTmpBuf != NULL) {
  666. G_FREE(pTmpBuf);
  667. }
  668. return Status;
  669. }