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.

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