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.

1384 lines
40 KiB

  1. /*++
  2. Copyright (C) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. smalrtq.cpp
  5. Abstract:
  6. Implementation of the alert query class
  7. --*/
  8. #include "Stdafx.h"
  9. #include <pdhp.h> // for MIN_TIME_VALUE, MAX_TIME_VALUE
  10. #include <pdhmsg.h>
  11. #include <strsafe.h>
  12. #include "smlogs.h"
  13. #include "common.h"
  14. #include "smalrtq.h"
  15. USE_HANDLE_MACROS("SMLOGCFG(smalrtq.cpp)");
  16. #define ALRT_DEFAULT_COMMAND_FILE L""
  17. #define ALRT_DEFAULT_NETWORK_NAME L""
  18. #define ALRT_DEFAULT_USER_TEXT L""
  19. #define ALRT_DEFAULT_PERF_LOG_NAME L""
  20. //
  21. // Constructor
  22. CSmAlertQuery::CSmAlertQuery( CSmLogService* pLogService )
  23. : CSmLogQuery( pLogService ),
  24. m_dwCounterListLength ( 0 ),
  25. m_szNextCounter ( NULL ),
  26. mr_szCounterList ( NULL ),
  27. m_bCounterListInLocale (FALSE),
  28. mr_dwActionFlags ( ALRT_DEFAULT_ACTION )
  29. {
  30. memset (&mr_stiSampleInterval, 0, sizeof(mr_stiSampleInterval));
  31. return;
  32. }
  33. //
  34. // Destructor
  35. CSmAlertQuery::~CSmAlertQuery()
  36. {
  37. return;
  38. }
  39. //
  40. // Open function. either opens an existing log query entry
  41. // or creates a new one
  42. //
  43. DWORD
  44. CSmAlertQuery::Open ( const CString& rstrName, HKEY hKeyQuery, BOOL bReadOnly)
  45. {
  46. DWORD dwStatus = ERROR_SUCCESS;
  47. ASSERT ( SLQ_ALERT == GetLogType() );
  48. dwStatus = CSmLogQuery::Open ( rstrName, hKeyQuery, bReadOnly );
  49. return dwStatus;
  50. }
  51. //
  52. // Close Function
  53. // closes registry handles and frees allocated memory
  54. //
  55. DWORD
  56. CSmAlertQuery::Close ()
  57. {
  58. DWORD dwStatus;
  59. LOCALTRACE (L"Closing Query\n");
  60. if (mr_szCounterList != NULL) {
  61. delete [] mr_szCounterList;
  62. mr_szCounterList = NULL;
  63. }
  64. mr_strNetName.Empty();
  65. mr_strCmdFileName.Empty();
  66. mr_strCmdUserText.Empty();
  67. mr_strCmdUserTextIndirect.Empty();
  68. mr_strPerfLogName.Empty();
  69. dwStatus = CSmLogQuery::Close();
  70. return dwStatus;
  71. }
  72. //
  73. // UpdateRegistry function.
  74. // copies the current settings to the registry where they
  75. // are read by the log service
  76. //
  77. DWORD
  78. CSmAlertQuery::UpdateRegistry()
  79. {
  80. DWORD dwStatus = ERROR_SUCCESS;
  81. DWORD dwBufferSize = 0;
  82. LPWSTR szNewCounterList = NULL;
  83. if ( IsModifiable() ) {
  84. dwBufferSize = 0;
  85. //
  86. // Translate the counter list into English
  87. //
  88. dwStatus = TranslateMSZAlertCounterList(mr_szCounterList,
  89. NULL,
  90. &dwBufferSize,
  91. FALSE);
  92. if (dwStatus == ERROR_NOT_ENOUGH_MEMORY) {
  93. ASSERT ( 0 == dwBufferSize % sizeof(WCHAR) );
  94. szNewCounterList = new WCHAR[dwBufferSize / sizeof(WCHAR)];
  95. if (szNewCounterList != NULL) {
  96. dwStatus = TranslateMSZAlertCounterList(mr_szCounterList,
  97. szNewCounterList,
  98. &dwBufferSize,
  99. FALSE);
  100. }
  101. }
  102. if (dwStatus == ERROR_SUCCESS && szNewCounterList != NULL) {
  103. dwStatus = WriteRegistryStringValue (
  104. m_hKeyQuery,
  105. IDS_REG_COUNTER_LIST,
  106. REG_MULTI_SZ,
  107. szNewCounterList,
  108. &dwBufferSize);
  109. }
  110. else {
  111. dwBufferSize = m_dwCounterListLength * sizeof(WCHAR);
  112. dwStatus = WriteRegistryStringValue (
  113. m_hKeyQuery,
  114. IDS_REG_COUNTER_LIST,
  115. REG_MULTI_SZ,
  116. mr_szCounterList,
  117. &dwBufferSize);
  118. }
  119. // Schedule
  120. if ( ERROR_SUCCESS == dwStatus ) {
  121. dwStatus = WriteRegistrySlqTime (
  122. m_hKeyQuery,
  123. IDS_REG_SAMPLE_INTERVAL,
  124. &mr_stiSampleInterval);
  125. }
  126. if ( ERROR_SUCCESS == dwStatus ) {
  127. if ( !mr_strCmdFileName.IsEmpty() ) {
  128. dwBufferSize = mr_strCmdFileName.GetLength() + 1;
  129. dwBufferSize *= sizeof(WCHAR);
  130. } else {
  131. dwBufferSize = 0;
  132. }
  133. dwStatus = WriteRegistryStringValue (
  134. m_hKeyQuery,
  135. IDS_REG_COMMAND_FILE,
  136. REG_SZ,
  137. mr_strCmdFileName,
  138. &dwBufferSize);
  139. }
  140. if ( ERROR_SUCCESS == dwStatus ) {
  141. if ( !mr_strNetName.IsEmpty() ) {
  142. dwBufferSize = mr_strNetName.GetLength() + 1;
  143. dwBufferSize *= sizeof(WCHAR);
  144. } else {
  145. dwBufferSize = 0;
  146. }
  147. dwStatus = WriteRegistryStringValue (
  148. m_hKeyQuery,
  149. IDS_REG_NETWORK_NAME,
  150. REG_SZ,
  151. mr_strNetName,
  152. &dwBufferSize);
  153. }
  154. if ( ERROR_SUCCESS == dwStatus ) {
  155. if ( !mr_strCmdUserText.IsEmpty() ) {
  156. dwBufferSize = mr_strCmdUserText.GetLength() + 1;
  157. dwBufferSize *= sizeof(WCHAR);
  158. } else {
  159. dwBufferSize = 0;
  160. }
  161. dwStatus = WriteRegistryStringValue (
  162. m_hKeyQuery,
  163. IDS_REG_USER_TEXT,
  164. REG_SZ,
  165. mr_strCmdUserText,
  166. &dwBufferSize);
  167. }
  168. if ( ERROR_SUCCESS == dwStatus && !mr_strCmdUserTextIndirect.IsEmpty() ) {
  169. dwBufferSize = mr_strCmdUserTextIndirect.GetLength() + 1;
  170. dwBufferSize *= sizeof(WCHAR);
  171. dwStatus = WriteRegistryStringValue (
  172. m_hKeyQuery,
  173. IDS_REG_USER_TEXT,
  174. REG_SZ,
  175. mr_strCmdUserTextIndirect,
  176. &dwBufferSize);
  177. }
  178. if ( ERROR_SUCCESS == dwStatus ) {
  179. if ( !mr_strPerfLogName.IsEmpty() ) {
  180. dwBufferSize = mr_strPerfLogName.GetLength() + 1;
  181. dwBufferSize *= sizeof(WCHAR);
  182. } else {
  183. dwBufferSize = 0;
  184. }
  185. dwStatus = WriteRegistryStringValue (
  186. m_hKeyQuery,
  187. IDS_REG_PERF_LOG_NAME,
  188. REG_SZ,
  189. mr_strPerfLogName,
  190. &dwBufferSize);
  191. }
  192. if ( ERROR_SUCCESS == dwStatus ) {
  193. dwStatus = WriteRegistryDwordValue(
  194. m_hKeyQuery,
  195. IDS_REG_ACTION_FLAGS,
  196. &mr_dwActionFlags,
  197. REG_DWORD);
  198. }
  199. if ( ERROR_SUCCESS == dwStatus ) {
  200. dwStatus = CSmLogQuery::UpdateRegistry ();
  201. }
  202. } else {
  203. dwStatus = ERROR_ACCESS_DENIED;
  204. }
  205. return dwStatus;
  206. }
  207. DWORD
  208. CSmAlertQuery::TranslateCounterListToLocale()
  209. {
  210. DWORD dwBufferSize = 0;
  211. DWORD dwStatus = ERROR_SUCCESS;
  212. LPWSTR szNewCounterList = NULL;
  213. if (m_bCounterListInLocale) {
  214. return ERROR_SUCCESS;
  215. }
  216. CWaitCursor WaitCursor;
  217. //
  218. // Translate the counter list into Locale
  219. //
  220. dwBufferSize = 0;
  221. dwStatus = TranslateMSZAlertCounterList(
  222. mr_szCounterList,
  223. NULL,
  224. &dwBufferSize,
  225. TRUE);
  226. if (dwStatus == ERROR_NOT_ENOUGH_MEMORY) {
  227. ASSERT ( 0 == dwBufferSize % sizeof(WCHAR) );
  228. szNewCounterList = new WCHAR [dwBufferSize / sizeof(WCHAR)];
  229. if (szNewCounterList != NULL) {
  230. //
  231. // Translate the counter list into Locale
  232. //
  233. dwStatus = TranslateMSZAlertCounterList(
  234. mr_szCounterList,
  235. szNewCounterList,
  236. &dwBufferSize,
  237. TRUE);
  238. if (dwStatus == ERROR_SUCCESS) {
  239. m_dwCounterListLength = dwBufferSize / sizeof(WCHAR);
  240. //
  241. // Remove the old
  242. //
  243. delete [] mr_szCounterList;
  244. m_szNextCounter = NULL;
  245. mr_szCounterList = szNewCounterList;
  246. m_bCounterListInLocale = TRUE;
  247. }
  248. }
  249. }
  250. WaitCursor.Restore();
  251. return dwStatus;
  252. }
  253. //
  254. // SyncWithRegistry()
  255. // Reads the current values for this query from the registry
  256. // and reloads the internal values to match
  257. //
  258. DWORD
  259. CSmAlertQuery::SyncWithRegistry()
  260. {
  261. DWORD dwBufferSize = 0;
  262. DWORD dwStatus = ERROR_SUCCESS;
  263. SLQ_TIME_INFO stiDefault;
  264. LPWSTR pszTemp = NULL;
  265. LPWSTR szIndTemp = NULL;
  266. UINT uiBufferLen = 0;
  267. ASSERT (m_hKeyQuery != NULL);
  268. m_bCounterListInLocale = FALSE;
  269. //
  270. // Load the counter string list
  271. //
  272. dwStatus = ReadRegistryStringValue (
  273. m_hKeyQuery,
  274. IDS_REG_COUNTER_LIST,
  275. NULL,
  276. &mr_szCounterList,
  277. &dwBufferSize);
  278. if (dwStatus != ERROR_SUCCESS) {
  279. m_szNextCounter = NULL; //re-initialize
  280. m_dwCounterListLength = 0;
  281. } else {
  282. // convert buffersize to chars from bytes
  283. m_dwCounterListLength = dwBufferSize / sizeof(WCHAR);
  284. }
  285. // Schedule
  286. stiDefault.wDataType = SLQ_TT_DTYPE_UNITS;
  287. stiDefault.wTimeType = SLQ_TT_TTYPE_SAMPLE;
  288. stiDefault.dwAutoMode = SLQ_AUTO_MODE_AFTER;
  289. stiDefault.dwValue = 5; // default interval;
  290. stiDefault.dwUnitType = SLQ_TT_UTYPE_SECONDS;
  291. dwStatus = ReadRegistrySlqTime (
  292. m_hKeyQuery,
  293. IDS_REG_SAMPLE_INTERVAL,
  294. &stiDefault,
  295. &mr_stiSampleInterval);
  296. ASSERT (dwStatus == ERROR_SUCCESS);
  297. dwBufferSize = 0;
  298. dwStatus = ReadRegistryStringValue (
  299. m_hKeyQuery,
  300. IDS_REG_COMMAND_FILE,
  301. ALRT_DEFAULT_COMMAND_FILE,
  302. &pszTemp,
  303. &dwBufferSize);
  304. ASSERT (dwStatus == ERROR_SUCCESS);
  305. mr_strCmdFileName.Empty();
  306. if ( dwBufferSize > sizeof(WCHAR) ) {
  307. ASSERT ( NULL != pszTemp );
  308. ASSERT ( 0 != *pszTemp );
  309. mr_strCmdFileName = pszTemp;
  310. }
  311. delete [] pszTemp;
  312. pszTemp = NULL;
  313. dwBufferSize = 0;
  314. dwStatus = ReadRegistryStringValue (
  315. m_hKeyQuery,
  316. IDS_REG_NETWORK_NAME,
  317. ALRT_DEFAULT_NETWORK_NAME,
  318. &pszTemp,
  319. &dwBufferSize);
  320. ASSERT (dwStatus == ERROR_SUCCESS);
  321. mr_strNetName.Empty();
  322. if ( dwBufferSize > sizeof(WCHAR) ) {
  323. ASSERT ( NULL != pszTemp );
  324. ASSERT ( 0 != *pszTemp );
  325. mr_strNetName = pszTemp;
  326. }
  327. delete [] pszTemp ;
  328. pszTemp = NULL;
  329. dwBufferSize = 0;
  330. // User text field can be indirect
  331. if ( ERROR_SUCCESS == dwStatus ) {
  332. dwStatus = SmNoLocReadRegIndStrVal (
  333. m_hKeyQuery,
  334. IDS_REG_USER_TEXT,
  335. ALRT_DEFAULT_USER_TEXT,
  336. &szIndTemp,
  337. &uiBufferLen );
  338. }
  339. mr_strCmdUserText.Empty();
  340. if ( NULL != szIndTemp ) {
  341. if ( L'\0' != *szIndTemp ) {
  342. mr_strCmdUserText = szIndTemp;
  343. }
  344. }
  345. if ( NULL != szIndTemp ) {
  346. G_FREE ( szIndTemp );
  347. szIndTemp = NULL;
  348. }
  349. uiBufferLen = 0;
  350. dwStatus = ReadRegistryStringValue (
  351. m_hKeyQuery,
  352. IDS_REG_PERF_LOG_NAME,
  353. ALRT_DEFAULT_PERF_LOG_NAME,
  354. &pszTemp,
  355. &dwBufferSize);
  356. ASSERT (dwStatus == ERROR_SUCCESS);
  357. mr_strPerfLogName.Empty();
  358. if ( dwBufferSize > sizeof(WCHAR) ) {
  359. ASSERT ( NULL != pszTemp );
  360. ASSERT ( 0 != *pszTemp );
  361. mr_strPerfLogName = pszTemp;
  362. }
  363. delete [] pszTemp ;
  364. pszTemp = NULL;
  365. dwBufferSize = 0;
  366. dwStatus = ReadRegistryDwordValue (
  367. m_hKeyQuery,
  368. IDS_REG_ACTION_FLAGS,
  369. ALRT_DEFAULT_ACTION,
  370. &mr_dwActionFlags);
  371. ASSERT ( ERROR_SUCCESS == dwStatus );
  372. // Call parent class last to update shared values.
  373. dwStatus = CSmLogQuery::SyncWithRegistry();
  374. ASSERT (dwStatus == ERROR_SUCCESS);
  375. return dwStatus;
  376. }
  377. BOOL
  378. CSmAlertQuery::GetLogTime ( PSLQ_TIME_INFO pTimeInfo, DWORD dwFlags )
  379. {
  380. BOOL bStatus;
  381. ASSERT ( ( SLQ_TT_TTYPE_START == dwFlags )
  382. || ( SLQ_TT_TTYPE_STOP == dwFlags )
  383. || ( SLQ_TT_TTYPE_RESTART == dwFlags )
  384. || ( SLQ_TT_TTYPE_SAMPLE == dwFlags ) );
  385. bStatus = CSmLogQuery::GetLogTime( pTimeInfo, dwFlags );
  386. return bStatus;
  387. }
  388. BOOL
  389. CSmAlertQuery::SetLogTime ( PSLQ_TIME_INFO pTimeInfo, const DWORD dwFlags )
  390. {
  391. BOOL bStatus;
  392. ASSERT ( ( SLQ_TT_TTYPE_START == dwFlags )
  393. || ( SLQ_TT_TTYPE_STOP == dwFlags )
  394. || ( SLQ_TT_TTYPE_RESTART == dwFlags )
  395. || ( SLQ_TT_TTYPE_SAMPLE == dwFlags ) );
  396. bStatus = CSmLogQuery::SetLogTime( pTimeInfo, dwFlags );
  397. return bStatus;
  398. }
  399. BOOL
  400. CSmAlertQuery::GetDefaultLogTime(SLQ_TIME_INFO& rTimeInfo, DWORD dwFlags )
  401. {
  402. ASSERT ( ( SLQ_TT_TTYPE_START == dwFlags )
  403. || ( SLQ_TT_TTYPE_STOP == dwFlags ) );
  404. rTimeInfo.wTimeType = (WORD)dwFlags;
  405. rTimeInfo.wDataType = SLQ_TT_DTYPE_DATETIME;
  406. if ( SLQ_TT_TTYPE_START == dwFlags ) {
  407. SYSTEMTIME stLocalTime;
  408. FILETIME ftLocalTime;
  409. // Milliseconds set to 0 for Schedule times
  410. ftLocalTime.dwLowDateTime = ftLocalTime.dwHighDateTime = 0;
  411. GetLocalTime (&stLocalTime);
  412. stLocalTime.wMilliseconds = 0;
  413. SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
  414. rTimeInfo.dwAutoMode = SLQ_AUTO_MODE_AT;
  415. rTimeInfo.llDateTime = *(LONGLONG *)&ftLocalTime;
  416. } else {
  417. // Default stop values
  418. rTimeInfo.dwAutoMode = SLQ_AUTO_MODE_NONE;
  419. rTimeInfo.llDateTime = MAX_TIME_VALUE;
  420. }
  421. return TRUE;
  422. }
  423. BOOL
  424. CSmAlertQuery::GetActionInfo( PALERT_ACTION_INFO pInfo, LPDWORD pdwInfoBufSize)
  425. {
  426. DWORD dwSizeRequired = sizeof (ALERT_ACTION_INFO);
  427. BOOL bReturn = FALSE;
  428. LPWSTR szNextString;
  429. // compute required size
  430. if (pdwInfoBufSize == NULL) {
  431. return FALSE;
  432. }
  433. if ( !mr_strNetName.IsEmpty() ) {
  434. dwSizeRequired += ( mr_strNetName.GetLength() + 1 ) * sizeof(WCHAR);
  435. }
  436. if ( !mr_strCmdFileName.IsEmpty() ) {
  437. dwSizeRequired += ( mr_strCmdFileName.GetLength() + 1 ) * sizeof(WCHAR);
  438. }
  439. if ( !mr_strCmdUserText.IsEmpty() ) {
  440. dwSizeRequired += ( mr_strCmdUserText.GetLength() + 1 ) * sizeof(WCHAR);
  441. }
  442. if ( !mr_strPerfLogName.IsEmpty() ) {
  443. dwSizeRequired += ( mr_strPerfLogName.GetLength() + 1 ) * sizeof(WCHAR);
  444. }
  445. if (dwSizeRequired <= *pdwInfoBufSize) {
  446. // clear the caller's buffer before we start filling it
  447. if (pInfo != NULL) {
  448. memset (pInfo, 0, *pdwInfoBufSize);
  449. pInfo->dwSize = dwSizeRequired;
  450. pInfo->dwActionFlags = mr_dwActionFlags;
  451. szNextString = (LPWSTR)&pInfo[1];
  452. if ( !mr_strNetName.IsEmpty() ) {
  453. pInfo->szNetName = szNextString;
  454. StringCchCopy ( szNextString, dwSizeRequired, mr_strNetName );
  455. szNextString += lstrlen(szNextString) + 1;
  456. }
  457. if ( !mr_strCmdFileName.IsEmpty() ) {
  458. pInfo->szCmdFilePath = szNextString;
  459. StringCchCopy ( szNextString, dwSizeRequired, mr_strCmdFileName );
  460. szNextString += lstrlen(szNextString) + 1;
  461. }
  462. if ( !mr_strCmdUserText.IsEmpty() ) {
  463. pInfo->szUserText = szNextString;
  464. StringCchCopy ( szNextString, dwSizeRequired, mr_strCmdUserText );
  465. szNextString += lstrlen(szNextString) + 1;
  466. }
  467. if ( !mr_strPerfLogName.IsEmpty() ) {
  468. pInfo->szLogName = szNextString;
  469. StringCchCopy ( szNextString, dwSizeRequired, mr_strPerfLogName );
  470. szNextString += lstrlen(szNextString) + 1;
  471. }
  472. bReturn = TRUE;
  473. }
  474. }
  475. *pdwInfoBufSize = dwSizeRequired;
  476. return bReturn;
  477. }
  478. DWORD
  479. CSmAlertQuery::SetActionInfo( PALERT_ACTION_INFO pInfo )
  480. {
  481. DWORD dwStatus = ERROR_SUCCESS;
  482. if (pInfo != NULL) {
  483. // Update action values with those from the structure
  484. MFC_TRY
  485. mr_dwActionFlags = pInfo->dwActionFlags;
  486. mr_strNetName.Empty();
  487. if ( NULL != pInfo->szNetName ) {
  488. mr_strNetName = pInfo->szNetName;
  489. }
  490. mr_strCmdFileName.Empty();
  491. if ( NULL != pInfo->szCmdFilePath ) {
  492. mr_strCmdFileName = pInfo->szCmdFilePath;
  493. }
  494. mr_strCmdUserText.Empty();
  495. if ( NULL != pInfo->szUserText ) {
  496. mr_strCmdUserText = pInfo->szUserText;
  497. }
  498. mr_strPerfLogName.Empty();
  499. if ( NULL != pInfo->szLogName ) {
  500. mr_strPerfLogName = pInfo->szLogName;
  501. }
  502. MFC_CATCH_DWSTATUS
  503. } else {
  504. dwStatus = ERROR_INVALID_PARAMETER;
  505. }
  506. // Todo: Handle return status
  507. return dwStatus;
  508. }
  509. //
  510. // Get first counter in counter list
  511. //
  512. LPCWSTR
  513. CSmAlertQuery::GetFirstCounter()
  514. {
  515. LPWSTR szReturn;
  516. szReturn = mr_szCounterList;
  517. if (szReturn != NULL) {
  518. if (*szReturn == 0) {
  519. // then it's an empty string
  520. szReturn = NULL;
  521. m_szNextCounter = NULL;
  522. } else {
  523. m_szNextCounter = szReturn + lstrlen(szReturn) + 1;
  524. if (*m_szNextCounter == 0) {
  525. // end of list reached so set pointer to NULL
  526. m_szNextCounter = NULL;
  527. }
  528. }
  529. } else {
  530. // no buffer allocated yet
  531. m_szNextCounter = NULL;
  532. }
  533. return (LPCWSTR)szReturn;
  534. }
  535. //
  536. // Get next counter in counter list
  537. // NULL pointer means no more counters in list
  538. //
  539. LPCWSTR
  540. CSmAlertQuery::GetNextCounter()
  541. {
  542. LPWSTR szReturn;
  543. szReturn = m_szNextCounter;
  544. if (m_szNextCounter != NULL) {
  545. m_szNextCounter += lstrlen(szReturn) + 1;
  546. if (*m_szNextCounter == 0) {
  547. // end of list reached so set pointer to NULL
  548. m_szNextCounter = NULL;
  549. }
  550. } else {
  551. // already at the end of the list so nothing to do
  552. }
  553. return (LPCWSTR)szReturn;
  554. }
  555. //
  556. // clear out the counter list
  557. //
  558. VOID
  559. CSmAlertQuery::ResetCounterList()
  560. {
  561. if (mr_szCounterList != NULL) {
  562. delete [] mr_szCounterList;
  563. m_szNextCounter = NULL;
  564. mr_szCounterList = NULL;
  565. }
  566. m_dwCounterListLength = sizeof(WCHAR); // sizeof MSZ Null
  567. try {
  568. mr_szCounterList = new WCHAR [m_dwCounterListLength];
  569. mr_szCounterList[0] = 0;
  570. } catch ( ... ) {
  571. m_dwCounterListLength = 0;
  572. }
  573. }
  574. //
  575. // Add this counter string to the internal list
  576. //
  577. BOOL
  578. CSmAlertQuery::AddCounter(LPCWSTR szCounterPath)
  579. {
  580. HRESULT hr = S_OK;
  581. DWORD dwNewLen;
  582. LPWSTR szNewString;
  583. LPWSTR szNextString;
  584. ASSERT (szCounterPath != NULL);
  585. if (szCounterPath == NULL) {
  586. return FALSE;
  587. }
  588. dwNewLen = lstrlen(szCounterPath) + 1;
  589. if (m_dwCounterListLength <= 2) {
  590. dwNewLen += 1; // add room for the MSZ null
  591. // then this is the first string to go in the list
  592. try {
  593. szNewString = new WCHAR [dwNewLen];
  594. } catch ( ... ) {
  595. return FALSE; // leave now
  596. }
  597. szNextString = szNewString;
  598. } else {
  599. //
  600. // Double the list size on each allocation.
  601. //
  602. dwNewLen += m_dwCounterListLength;
  603. // this is the nth string to go in the list
  604. try {
  605. szNewString = new WCHAR [dwNewLen];
  606. } catch ( ... ) {
  607. return FALSE; // leave now
  608. }
  609. // Use memcpy because MSZ string.
  610. memcpy (szNewString, mr_szCounterList,
  611. (m_dwCounterListLength * sizeof(WCHAR)));
  612. szNextString = szNewString;
  613. szNextString += m_dwCounterListLength - 1;
  614. }
  615. hr = StringCchCopy ( szNextString, dwNewLen, szCounterPath );
  616. if ( SUCCEEDED ( hr) ) {
  617. szNextString = szNewString;
  618. szNextString += dwNewLen - 1;
  619. *szNextString = L'\0'; // MSZ Null
  620. if (mr_szCounterList != NULL) {
  621. delete [] mr_szCounterList;
  622. }
  623. mr_szCounterList = szNewString;
  624. m_szNextCounter = szNewString;
  625. m_dwCounterListLength = dwNewLen;
  626. } else {
  627. delete [] szNewString;
  628. return FALSE;
  629. }
  630. return TRUE;
  631. }
  632. DWORD
  633. CSmAlertQuery::GetLogType()
  634. {
  635. return ( SLQ_ALERT );
  636. }
  637. BOOL
  638. CSmAlertQuery::SetLogFileType ( const DWORD /* dwType */)
  639. {
  640. // No alert log file type
  641. return FALSE;
  642. }
  643. //
  644. // Get log file type and return as a string
  645. //
  646. //
  647. const CString&
  648. CSmAlertQuery::GetLogFileType ( )
  649. {
  650. return cstrEmpty;
  651. }
  652. void
  653. CSmAlertQuery::GetLogFileType ( DWORD& rdwFileType )
  654. {
  655. // Log file type should default in property bags.
  656. ASSERT ( FALSE );
  657. rdwFileType = ((DWORD)0xFFFFFFFF);
  658. return;
  659. }
  660. LPCWSTR
  661. CSmAlertQuery::GetCounterList( LPDWORD pcchListSize)
  662. {
  663. if (pcchListSize != NULL) *pcchListSize = m_dwCounterListLength;
  664. return mr_szCounterList;
  665. }
  666. BOOL CSmAlertQuery::SetCounterList( LPCWSTR mszCounterList, DWORD cchListSize)
  667. {
  668. BOOL bReturn = TRUE;
  669. if (mr_szCounterList != NULL) {
  670. delete [] mr_szCounterList;
  671. mr_szCounterList = NULL;
  672. m_dwCounterListLength = 0;
  673. }
  674. try {
  675. mr_szCounterList = new WCHAR [cchListSize];
  676. memcpy (mr_szCounterList, mszCounterList, (cchListSize * sizeof(WCHAR)));
  677. m_dwCounterListLength = cchListSize;
  678. } catch ( ... ) {
  679. bReturn = FALSE;
  680. }
  681. return bReturn;
  682. }
  683. const CString&
  684. CSmAlertQuery::GetLogFileName( BOOL )
  685. {
  686. // 2000.1 return empty string so that empty string is written to HTML file for alerts.
  687. return cstrEmpty;
  688. }
  689. HRESULT
  690. CSmAlertQuery::LoadCountersFromPropertyBag (
  691. IPropertyBag* pPropBag,
  692. IErrorLog* pIErrorLog )
  693. {
  694. HRESULT hr = S_OK;
  695. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  696. DWORD dwCount;
  697. DWORD dwIndex;
  698. CString strParamName;
  699. CString strNonLocParamName;
  700. LPWSTR szLocaleBuf = NULL;
  701. DWORD dwLocaleBufLen = 0;
  702. LPWSTR pszPath;
  703. PALERT_INFO_BLOCK paibInfo = NULL;
  704. LPWSTR szString = NULL;
  705. LPWSTR szCounterPath = NULL;
  706. m_bCounterListInLocale = FALSE;
  707. hr = DwordFromPropertyBag (
  708. pPropBag,
  709. pIErrorLog,
  710. IDS_HTML_SYSMON_COUNTERCOUNT,
  711. 0,
  712. dwCount);
  713. for ( dwIndex = 1; dwIndex <= dwCount; dwIndex++ ) {
  714. pdhStatus = ERROR_SUCCESS;
  715. hr = S_OK;
  716. pszPath = NULL;
  717. MFC_TRY
  718. DWORD dwBufLen = 0;
  719. DWORD dwCharCount = 0;
  720. DWORD dwByteCount = 0;
  721. DWORD dwOverUnder;
  722. DOUBLE dThreshold;
  723. strNonLocParamName.Format ( GetNonLocHtmlPropName ( IDS_HTML_SYSMON_COUNTERPATH ), dwIndex );
  724. strParamName.Format ( IDS_HTML_SYSMON_COUNTERPATH, dwIndex );
  725. hr = StringFromPropertyBag (
  726. pPropBag,
  727. pIErrorLog,
  728. strParamName,
  729. strNonLocParamName,
  730. L"",
  731. &szCounterPath,
  732. &dwBufLen );
  733. pszPath = szCounterPath;
  734. //
  735. // 1 for NULL character
  736. //
  737. if (dwBufLen > 1) {
  738. //
  739. // Initialize the locale path buffer
  740. //
  741. if (dwLocaleBufLen == 0) {
  742. dwLocaleBufLen = PDH_MAX_COUNTER_PATH + 1;
  743. szLocaleBuf = new WCHAR [dwLocaleBufLen];
  744. if (szLocaleBuf == NULL) {
  745. dwLocaleBufLen = 0;
  746. }
  747. }
  748. if (szLocaleBuf != NULL) {
  749. //
  750. // Translate counter name from English to Locale
  751. //
  752. dwBufLen = dwLocaleBufLen;
  753. pdhStatus = PdhTranslateLocaleCounter(
  754. szCounterPath,
  755. szLocaleBuf,
  756. &dwBufLen);
  757. if (pdhStatus == ERROR_SUCCESS) {
  758. m_bCounterListInLocale = TRUE;
  759. pszPath = szLocaleBuf;
  760. } else if ( PDH_MORE_DATA == pdhStatus ) {
  761. //
  762. // Todo: Build error message.
  763. //
  764. } // else build error message.
  765. }
  766. }
  767. if ( NULL != pszPath ) {
  768. strNonLocParamName.Format ( GetNonLocHtmlPropName ( IDS_HTML_ALERT_OVER_UNDER ), dwIndex );
  769. strParamName.Format ( IDS_HTML_ALERT_OVER_UNDER, dwIndex );
  770. hr = DwordFromPropertyBag (
  771. pPropBag,
  772. pIErrorLog,
  773. strParamName,
  774. strNonLocParamName,
  775. AIBF_UNDER,
  776. dwOverUnder);
  777. if ( SUCCEEDED ( hr ) ) {
  778. strNonLocParamName.Format ( GetNonLocHtmlPropName ( IDS_HTML_ALERT_THRESHOLD ), dwIndex );
  779. strParamName.Format ( IDS_HTML_ALERT_THRESHOLD, dwIndex );
  780. hr = DoubleFromPropertyBag (
  781. pPropBag,
  782. pIErrorLog,
  783. strParamName,
  784. strNonLocParamName,
  785. ((DOUBLE)0.0),
  786. dThreshold);
  787. }
  788. if ( SUCCEEDED ( hr ) ) {
  789. // 1 = size of "<"
  790. // SLQ_MAX_VALUE_LEN = size of threshold value
  791. // 1 = size of null terminator
  792. dwCharCount = lstrlen(pszPath) + 1 + SLQ_MAX_VALUE_LEN + 1;
  793. dwByteCount = sizeof (ALERT_INFO_BLOCK) + ( dwCharCount * sizeof(WCHAR) ) + MAX_ALIGN_BYTES;
  794. paibInfo = (PALERT_INFO_BLOCK) new CHAR[dwByteCount];
  795. ZeroMemory ( paibInfo, dwByteCount );
  796. szString = new WCHAR[dwCharCount];
  797. paibInfo->dwSize = dwByteCount;
  798. paibInfo->szCounterPath = pszPath;
  799. pszPath = NULL;
  800. paibInfo->dwFlags = dwOverUnder;
  801. paibInfo->dLimit = dThreshold;
  802. if ( MakeStringFromInfo( paibInfo, szString, &dwCharCount ) ) {
  803. AddCounter ( szString );
  804. }
  805. }
  806. }
  807. MFC_CATCH_MINIMUM
  808. if ( NULL != szString ) {
  809. delete [] szString;
  810. szString = NULL;
  811. }
  812. if ( NULL != szCounterPath ) {
  813. delete [] szCounterPath;
  814. szCounterPath = NULL;
  815. }
  816. if ( NULL != paibInfo ) {
  817. delete [] paibInfo;
  818. paibInfo = NULL;
  819. }
  820. }
  821. if ( NULL != szLocaleBuf ) {
  822. delete [] szLocaleBuf;
  823. }
  824. //
  825. // Todo: Display error message listing unloaded counters.
  826. //
  827. // Return good status regardless.
  828. return S_OK;
  829. }
  830. HRESULT
  831. CSmAlertQuery::LoadFromPropertyBag (
  832. IPropertyBag* pPropBag,
  833. IErrorLog* pIErrorLog )
  834. {
  835. HRESULT hr = S_OK;
  836. SLQ_TIME_INFO stiDefault;
  837. LPWSTR pszTemp = NULL;
  838. DWORD dwBufSize;
  839. //
  840. // Continue even if error, using defaults for missing values.
  841. //
  842. hr = LoadCountersFromPropertyBag ( pPropBag, pIErrorLog );
  843. stiDefault.wTimeType = SLQ_TT_TTYPE_SAMPLE;
  844. stiDefault.dwAutoMode = SLQ_AUTO_MODE_AFTER;
  845. stiDefault.wDataType = SLQ_TT_DTYPE_UNITS;
  846. stiDefault.dwUnitType = SLQ_TT_UTYPE_SECONDS;
  847. stiDefault.dwValue = 5;
  848. hr = SlqTimeFromPropertyBag (
  849. pPropBag,
  850. pIErrorLog,
  851. SLQ_TT_TTYPE_SAMPLE,
  852. &stiDefault,
  853. &mr_stiSampleInterval );
  854. mr_strCmdFileName.Empty();
  855. dwBufSize = 0;
  856. hr = StringFromPropertyBag (
  857. pPropBag,
  858. pIErrorLog,
  859. IDS_HTML_COMMAND_FILE,
  860. ALRT_DEFAULT_COMMAND_FILE,
  861. &pszTemp,
  862. &dwBufSize );
  863. if ( sizeof(WCHAR) < dwBufSize ) {
  864. ASSERT ( NULL != pszTemp );
  865. ASSERT ( 0 != * pszTemp );
  866. mr_strCmdFileName = pszTemp;
  867. }
  868. delete [] pszTemp;
  869. pszTemp = NULL;
  870. mr_strNetName.Empty();
  871. dwBufSize = 0;
  872. hr = StringFromPropertyBag (
  873. pPropBag,
  874. pIErrorLog,
  875. IDS_HTML_NETWORK_NAME,
  876. ALRT_DEFAULT_NETWORK_NAME,
  877. &pszTemp,
  878. &dwBufSize );
  879. if ( sizeof(WCHAR) < dwBufSize ) {
  880. ASSERT ( NULL != pszTemp );
  881. ASSERT ( 0 != * pszTemp );
  882. mr_strNetName = pszTemp;
  883. }
  884. delete [] pszTemp;
  885. pszTemp = NULL;
  886. mr_strCmdUserText.Empty();
  887. dwBufSize = 0;
  888. hr = StringFromPropertyBag (
  889. pPropBag,
  890. pIErrorLog,
  891. IDS_HTML_USER_TEXT,
  892. ALRT_DEFAULT_USER_TEXT,
  893. &pszTemp,
  894. &dwBufSize );
  895. if ( sizeof(WCHAR) < dwBufSize ) {
  896. ASSERT ( NULL != pszTemp );
  897. ASSERT ( 0 != * pszTemp );
  898. mr_strCmdUserText = pszTemp;
  899. }
  900. delete [] pszTemp;
  901. pszTemp = NULL;
  902. mr_strPerfLogName.Empty();
  903. dwBufSize = 0;
  904. hr = StringFromPropertyBag (
  905. pPropBag,
  906. pIErrorLog,
  907. IDS_HTML_PERF_LOG_NAME,
  908. ALRT_DEFAULT_PERF_LOG_NAME,
  909. &pszTemp,
  910. &dwBufSize );
  911. if ( sizeof(WCHAR) < dwBufSize ) {
  912. ASSERT ( NULL != pszTemp );
  913. ASSERT ( 0 != * pszTemp );
  914. mr_strPerfLogName = pszTemp;
  915. }
  916. delete [] pszTemp;
  917. pszTemp = NULL;
  918. hr = DwordFromPropertyBag (
  919. pPropBag,
  920. pIErrorLog,
  921. IDS_HTML_ACTION_FLAGS,
  922. ALRT_DEFAULT_ACTION,
  923. mr_dwActionFlags);
  924. hr = CSmLogQuery::LoadFromPropertyBag( pPropBag, pIErrorLog );
  925. return hr;
  926. }
  927. HRESULT
  928. CSmAlertQuery::SaveCountersToPropertyBag (
  929. IPropertyBag* pPropBag )
  930. {
  931. HRESULT hr = S_OK;
  932. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  933. LPCWSTR szString;
  934. CString strNonLocParamName;
  935. DWORD dwIndex = 0;
  936. LPWSTR szEnglishBuf = NULL;
  937. DWORD dwEnglishBufLen = 0;
  938. LPWSTR pszPath = NULL;
  939. PALERT_INFO_BLOCK paibInfo = NULL;
  940. LPWSTR pNewBuf = NULL;
  941. DWORD dwByteCount;
  942. DWORD dwBufLen;
  943. szString = GetFirstCounter();
  944. //
  945. // Todo: Error message for counters that fail.
  946. //
  947. while ( NULL != szString ) {
  948. pdhStatus = ERROR_SUCCESS;
  949. hr = S_OK;
  950. pszPath = NULL;
  951. MFC_TRY
  952. if ( NULL == paibInfo ) {
  953. //
  954. // Include space for possibly alignment padding
  955. //
  956. dwByteCount =
  957. sizeof (ALERT_INFO_BLOCK)
  958. + ( PDH_MAX_COUNTER_PATH + 1 ) * sizeof(WCHAR)
  959. + MAX_ALIGN_BYTES;
  960. paibInfo = (PALERT_INFO_BLOCK) new CHAR[dwByteCount];
  961. }
  962. if ( MakeInfoFromString( szString, paibInfo, &dwByteCount ) ) {
  963. pszPath = paibInfo->szCounterPath;
  964. if (m_bCounterListInLocale) {
  965. //
  966. // Translate counter name from Locale into English
  967. //
  968. if ( 0 == dwEnglishBufLen ) {
  969. dwEnglishBufLen = PDH_MAX_COUNTER_PATH + 1;
  970. szEnglishBuf = new WCHAR [dwEnglishBufLen];
  971. if ( NULL == szEnglishBuf ) {
  972. dwEnglishBufLen = 0;
  973. }
  974. }
  975. dwBufLen = dwEnglishBufLen;
  976. pdhStatus = PdhTranslate009Counter(
  977. paibInfo->szCounterPath,
  978. szEnglishBuf,
  979. &dwBufLen);
  980. if (pdhStatus == ERROR_SUCCESS) {
  981. pszPath = szEnglishBuf;
  982. } else if ( PDH_MORE_DATA == pdhStatus ) {
  983. //
  984. // Todo: Build error message.
  985. //
  986. } // else build error message.
  987. }
  988. if ( NULL != pszPath ) {
  989. strNonLocParamName.Format ( GetNonLocHtmlPropName ( IDS_HTML_SYSMON_COUNTERPATH ), ++dwIndex );
  990. hr = StringToPropertyBag ( pPropBag, strNonLocParamName, pszPath);
  991. strNonLocParamName.Format ( GetNonLocHtmlPropName ( IDS_HTML_ALERT_OVER_UNDER ), dwIndex );
  992. hr = DwordToPropertyBag ( pPropBag, strNonLocParamName, paibInfo->dwFlags );
  993. strNonLocParamName.Format ( GetNonLocHtmlPropName ( IDS_HTML_ALERT_THRESHOLD ), dwIndex );
  994. hr = DoubleToPropertyBag ( pPropBag, strNonLocParamName, paibInfo->dLimit );
  995. } else {
  996. hr = E_UNEXPECTED;
  997. }
  998. }
  999. MFC_CATCH_HR
  1000. szString = GetNextCounter();
  1001. }
  1002. hr = DwordToPropertyBag ( pPropBag, IDS_HTML_SYSMON_COUNTERCOUNT, dwIndex );
  1003. if ( NULL != paibInfo ) {
  1004. delete [] (char*)paibInfo;
  1005. paibInfo = NULL;
  1006. }
  1007. if (szEnglishBuf != NULL) {
  1008. delete [] szEnglishBuf;
  1009. }
  1010. //
  1011. // Todo: Display error message
  1012. // Todo: Caller handle error. Return count of saved counters.
  1013. //
  1014. return hr;
  1015. }
  1016. HRESULT
  1017. CSmAlertQuery::SaveToPropertyBag (
  1018. IPropertyBag* pPropBag,
  1019. BOOL fSaveAllProps )
  1020. {
  1021. HRESULT hr = NOERROR;
  1022. hr = SaveCountersToPropertyBag ( pPropBag );
  1023. hr = SlqTimeToPropertyBag ( pPropBag, SLQ_TT_TTYPE_SAMPLE, &mr_stiSampleInterval );
  1024. hr = StringToPropertyBag ( pPropBag, IDS_HTML_COMMAND_FILE, mr_strCmdFileName );
  1025. hr = StringToPropertyBag ( pPropBag, IDS_HTML_NETWORK_NAME, mr_strNetName );
  1026. hr = StringToPropertyBag ( pPropBag, IDS_HTML_USER_TEXT, mr_strCmdUserText );
  1027. hr = StringToPropertyBag ( pPropBag, IDS_HTML_PERF_LOG_NAME, mr_strPerfLogName );
  1028. hr = DwordToPropertyBag ( pPropBag, IDS_HTML_ACTION_FLAGS, mr_dwActionFlags );
  1029. hr = CSmLogQuery::SaveToPropertyBag( pPropBag, fSaveAllProps );
  1030. return hr;
  1031. }
  1032. DWORD
  1033. CSmAlertQuery::TranslateMSZAlertCounterList(
  1034. LPWSTR pszCounterList,
  1035. LPWSTR pBuffer,
  1036. LPDWORD pdwBufferSize,
  1037. BOOL bFlag
  1038. )
  1039. {
  1040. DWORD dwStatus = ERROR_SUCCESS;
  1041. HRESULT hr = S_OK;
  1042. LPWSTR pTmpBuf = NULL;
  1043. DWORD dwLen = 0;
  1044. LPWSTR pOriginPath = NULL;
  1045. LPWSTR pszCounterPathToAdd = NULL;
  1046. LPWSTR pNextStringPosition = NULL;
  1047. BOOL bEnoughBuffer = TRUE;
  1048. DWORD dwNewCounterListLen = 0;
  1049. DWORD dwCounterPathLen = 0;
  1050. LPWSTR pData = NULL;
  1051. LPWSTR pszBackupPath = NULL;
  1052. size_t cchBackupLen = PDH_MAX_COUNTER_PATH + 1;
  1053. if (pszCounterList == NULL || pdwBufferSize == NULL) {
  1054. dwStatus = ERROR_INVALID_PARAMETER;
  1055. return dwStatus;
  1056. }
  1057. if ( pBuffer == NULL || *pdwBufferSize == 0 ) {
  1058. bEnoughBuffer = FALSE;
  1059. } else {
  1060. pBuffer[0] = L'\0';
  1061. }
  1062. pOriginPath = pszCounterList;
  1063. while ( *pOriginPath ) {
  1064. pszCounterPathToAdd = NULL;
  1065. dwStatus = ERROR_SUCCESS;
  1066. MFC_TRY
  1067. //
  1068. // Locate the position where the data description begins
  1069. //
  1070. pData = pOriginPath;
  1071. while (*pData != L'\0' && *pData != L'<' && *pData != L'>') {
  1072. pData++;
  1073. }
  1074. //
  1075. // Backup the counter path
  1076. //
  1077. //
  1078. if (pszBackupPath == NULL) {
  1079. //
  1080. // Memory allocation error throws exception
  1081. //
  1082. pszBackupPath = new WCHAR [cchBackupLen] ;
  1083. pszBackupPath [0] = L'\0';
  1084. }
  1085. //
  1086. // StringCchCopyN adds null termination
  1087. //
  1088. hr = StringCchCopyN ( pszBackupPath, cchBackupLen, pOriginPath, (INT_PTR)(pData - pOriginPath) );
  1089. if ( SUCCEEDED ( hr ) && L'\0' != pszBackupPath [0] ) {
  1090. pszCounterPathToAdd = pszBackupPath;
  1091. //
  1092. // Initialize the buffer used for translating counter path.
  1093. // This is called only once.
  1094. //
  1095. dwLen = PDH_MAX_COUNTER_PATH + 1;
  1096. if (pTmpBuf == NULL) {
  1097. pTmpBuf = new WCHAR [ dwLen ] ;
  1098. }
  1099. if (bFlag) {
  1100. dwStatus = PdhTranslateLocaleCounter(
  1101. pszBackupPath,
  1102. pTmpBuf,
  1103. &dwLen);
  1104. } else {
  1105. dwStatus = PdhTranslate009Counter(
  1106. pszBackupPath,
  1107. pTmpBuf,
  1108. &dwLen);
  1109. }
  1110. if (dwStatus == ERROR_SUCCESS) {
  1111. pszCounterPathToAdd = pTmpBuf;
  1112. }
  1113. if ( NULL != pszCounterPathToAdd ) {
  1114. //
  1115. // Add the translated counter path to the new counter
  1116. // path list. The translated path is the original
  1117. // counter path if translation failed.
  1118. //
  1119. dwStatus = ERROR_SUCCESS;
  1120. dwCounterPathLen = lstrlen(pszCounterPathToAdd) + 1;
  1121. dwNewCounterListLen += dwCounterPathLen;
  1122. if ( bEnoughBuffer ) {
  1123. if ( (dwNewCounterListLen + lstrlen(pData) + 1) * sizeof(WCHAR) <= *pdwBufferSize) {
  1124. //
  1125. // Set up the copy position
  1126. //
  1127. pNextStringPosition = pBuffer + dwNewCounterListLen - dwCounterPathLen;
  1128. StringCchCopy ( pNextStringPosition, (dwCounterPathLen + lstrlen(pData) + 1), pszCounterPathToAdd );
  1129. StringCchCat (pNextStringPosition, (dwCounterPathLen + lstrlen(pData) + 1), pData);
  1130. }
  1131. else {
  1132. bEnoughBuffer = FALSE;
  1133. }
  1134. }
  1135. dwNewCounterListLen += lstrlen(pData);
  1136. pszCounterPathToAdd = NULL;
  1137. }
  1138. } else {
  1139. //
  1140. // Todo: On failure, add path to error list and continue with next counter.
  1141. //
  1142. }
  1143. MFC_CATCH_DWSTATUS
  1144. //
  1145. // Continue processing next counter path
  1146. //
  1147. pOriginPath += lstrlen(pOriginPath) + 1;
  1148. }
  1149. dwNewCounterListLen ++;
  1150. if ( bEnoughBuffer ) {
  1151. if ( ERROR_SUCCESS == dwStatus ) {
  1152. //
  1153. // Append the terminating 0
  1154. //
  1155. pBuffer[dwNewCounterListLen - 1] = L'\0';
  1156. }
  1157. //
  1158. // Todo: Display error for unadded counters.
  1159. //
  1160. } else {
  1161. if ( NULL != pBuffer ) {
  1162. pBuffer[0] = L'\0';
  1163. }
  1164. if ( ERROR_SUCCESS == dwStatus ) {
  1165. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  1166. }
  1167. }
  1168. *pdwBufferSize = dwNewCounterListLen * sizeof(WCHAR);
  1169. if (pszBackupPath != NULL) {
  1170. delete [] pszBackupPath;
  1171. }
  1172. if (pTmpBuf != NULL) {
  1173. delete [] pTmpBuf;
  1174. }
  1175. return dwStatus;
  1176. }