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.

940 lines
33 KiB

  1. /*****************************************************************************\
  2. Author: Corey Morgan (coreym)
  3. Copyright (c) Microsoft Corporation. All rights reserved.
  4. \*****************************************************************************/
  5. #include <windows.h>
  6. #include <tchar.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <wtypes.h>
  10. #include <objbase.h>
  11. #include <pdh.h>
  12. #include <pdhmsg.h>
  13. #include <pdhp.h>
  14. #include "resource.h"
  15. #include "varg.c"
  16. DWORD GetLogFormat( LPTSTR str, LPDWORD pdwFormat );
  17. PDH_STATUS GetCountersFromFile( BOOL bExpand, HLOG hLog, HQUERY hQuery );
  18. PDH_STATUS QueryLog( HLOG hLog, HQUERY hQuery, FILE* f );
  19. PDH_STATUS AddCounters( BOOL bExpand, HLOG hLog, HQUERY hQuery );
  20. _inline BOOL IsTextFormat( DWORD dwFormat );
  21. DWORD GetTempName( LPTSTR strFile, size_t cchSize );
  22. void ReportStatus( int Status, double Progress );
  23. #define PDH_LOG_TYPE_RETIRED_BIN_ 3
  24. #define CHECK_STATUS( hr ) if( ERROR_SUCCESS != hr ){ goto cleanup; }
  25. #define RELOG_ERROR_BADFILES 0xF0000001
  26. #define RELOG_ERROR_BADFORMAT 0xF0000002
  27. #define RELOG_ERROR_TIMERANGE 0xF0000003
  28. #define RELOG_ERROR_BADAPPEND 0xF0000004
  29. VARG_DECLARE_COMMANDS
  30. VARG_DEBUG( VARG_FLAG_OPTIONAL|VARG_FLAG_HIDDEN )
  31. VARG_HELP ( VARG_FLAG_OPTIONAL )
  32. VARG_BOOL ( IDS_PARAM_APPEND, VARG_FLAG_OPTIONAL, FALSE )
  33. VARG_MSZ ( IDS_PARAM_COUNTERS, VARG_FLAG_OPTIONAL, _T("") )
  34. VARG_STR ( IDS_PARAM_COUNTERFILE, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_FILENAME, _T("") )
  35. VARG_STR ( IDS_PARAM_FORMAT, VARG_FLAG_OPTIONAL|VARG_FLAG_LITERAL, _T("BIN") )
  36. VARG_MSZ ( IDS_PARAM_INPUT, VARG_FLAG_REQUIRED|VARG_FLAG_NOFLAG|VARG_FLAG_EXPANDFILES|VARG_FLAG_ARG_FILENAME, _T("") )
  37. VARG_INT ( IDS_PARAM_INTERVAL, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_DEFAULT, 0 )
  38. VARG_STR ( IDS_PARAM_OUTPUT, VARG_FLAG_OPTIONAL|VARG_FLAG_DEFAULTABLE|VARG_FLAG_RCDEFAULT, IDS_DEFAULT_OUTPUT )
  39. VARG_DATE ( IDS_PARAM_BEGIN, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_DATE )
  40. VARG_DATE ( IDS_PARAM_END, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_DATE )
  41. VARG_INI ( IDS_PARAM_SETTINGS, VARG_FLAG_OPTIONAL, NULL )
  42. VARG_BOOL ( IDS_PARAM_QUERY, VARG_FLAG_OPTIONAL, FALSE )
  43. VARG_BOOL ( IDS_PARAM_YES, VARG_FLAG_OPTIONAL, FALSE )
  44. VARG_BOOL ( IDS_PARAM_FA, VARG_FLAG_OPTIONAL|VARG_FLAG_HIDDEN, FALSE )
  45. VARG_DECLARE_NAMES
  46. eDebug,
  47. eHelp,
  48. eAppend,
  49. eCounters,
  50. eCounterFile,
  51. eFormat,
  52. eInput,
  53. eInterval,
  54. eOutput,
  55. eBegin,
  56. eEnd,
  57. eSettings,
  58. eQuery,
  59. eYes,
  60. eForceAppend,
  61. VARG_DECLARE_FORMAT
  62. VARG_EXHELP( eFormat, IDS_EXAMPLE_FORMAT )
  63. VARG_EXHELP( eQuery, IDS_EXAMPLE_QUERY )
  64. VARG_EXHELP( eCounterFile, IDS_EXAMPLE_COUNTERFILE )
  65. VARG_EXHELP( eCounters, IDS_EXAMPLE_COUNTERS )
  66. VARG_DECLARE_END
  67. int __cdecl _tmain( int argc, LPTSTR* argv )
  68. {
  69. DWORD dwStatus = ERROR_SUCCESS;
  70. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  71. PDH_RELOG_INFO RelogInfo;
  72. DWORD dwOutputFormat;
  73. DWORD dwInputFormat;
  74. PDH_TIME_INFO InputTimeRange;
  75. LPTSTR strFile = NULL;
  76. TCHAR strTempFile[MAXSTR] = _T("");
  77. ParseCmd( argc, argv );
  78. HLOG hLogIn = NULL;
  79. HQUERY hQuery = NULL;
  80. ZeroMemory( &RelogInfo, sizeof(PDH_RELOG_INFO) );
  81. DWORD dwNumEntries = 1;
  82. DWORD dwBufferSize = sizeof(PDH_TIME_INFO);
  83. int nBinary = 0;
  84. int nFiles = 0;
  85. BOOL bFakeAppend = FALSE;
  86. if( Commands[eInput].strValue == NULL ){
  87. dwStatus = ERROR_OUTOFMEMORY;
  88. goto cleanup;
  89. }
  90. if( Commands[eAppend].bValue && !(Commands[eForceAppend].bValue ) ){
  91. // We are going to do a merge instead
  92. bFakeAppend = TRUE;
  93. dwStatus = varg_cmdStringAddMsz( eInput, Commands[eOutput].strValue );
  94. CHECK_STATUS( dwStatus );
  95. dwStatus = GetTempName( strTempFile, MAXSTR );
  96. CHECK_STATUS( dwStatus );
  97. }
  98. dwStatus = GetLogFormat( Commands[eFormat].strValue, &dwOutputFormat );
  99. CHECK_STATUS(dwStatus);
  100. strFile = Commands[eInput].strValue;
  101. PrintMessage( g_normal, IDS_MESSAGE_INPUT );
  102. PrintMessage( g_normal, IDS_MESSAGE_FILES );
  103. while( strFile != NULL && *strFile != _T('\0') ){
  104. pdhStatus = PdhGetLogFileType( strFile, &dwInputFormat );
  105. nFiles++;
  106. if( pdhStatus != ERROR_SUCCESS ){
  107. dwInputFormat = 0;
  108. }
  109. switch( dwInputFormat ){
  110. case PDH_LOG_TYPE_RETIRED_BIN_:
  111. PrintMessage( g_normal, IDS_MESSAGE_LOG_OLD_BIN, strFile );
  112. break;
  113. case PDH_LOG_TYPE_CSV:
  114. PrintMessage( g_normal, IDS_MESSAGE_LOG_CSV, strFile );
  115. break;
  116. case PDH_LOG_TYPE_TSV:
  117. PrintMessage( g_normal, IDS_MESSAGE_LOG_TSV, strFile );
  118. break;
  119. case PDH_LOG_TYPE_BINARY:
  120. nBinary++;
  121. PrintMessage( g_normal, IDS_MESSAGE_LOG_BINARY, strFile );
  122. break;
  123. case PDH_LOG_TYPE_PERFMON:
  124. PrintMessage( g_normal, IDS_MESSAGE_LOG_PERFMON, strFile );
  125. break;
  126. default:
  127. PrintMessage( g_normal, IDS_MESSAGE_LOG_UNKNOWN, strFile );
  128. }
  129. strFile += _tcslen(strFile)+1;
  130. }
  131. varg_printf( g_normal, _T("\n") );
  132. if( nFiles > 1 && nFiles > nBinary ){
  133. dwStatus = RELOG_ERROR_BADFILES;
  134. goto cleanup;
  135. }
  136. pdhStatus = PdhBindInputDataSource( &hLogIn, Commands[eInput].strValue );
  137. CHECK_STATUS( pdhStatus );
  138. pdhStatus = PdhOpenQueryH( hLogIn, NULL, &hQuery );
  139. CHECK_STATUS( pdhStatus );
  140. pdhStatus = PdhGetDataSourceTimeRangeH (
  141. hLogIn,
  142. &dwNumEntries,
  143. &InputTimeRange,
  144. &dwBufferSize
  145. );
  146. CHECK_STATUS( pdhStatus );
  147. SYSTEMTIME st;
  148. FileTimeToSystemTime( (FILETIME *)&InputTimeRange.StartTime, &st );
  149. PrintMessage( g_normal, IDS_MESSAGE_BEGIN );
  150. PrintDate( &st );
  151. FileTimeToSystemTime( (FILETIME *)&InputTimeRange.EndTime, &st );
  152. PrintMessage( g_normal, IDS_MESSAGE_END );
  153. PrintDate( &st );
  154. PrintMessage( g_normal, IDS_MESSAGE_SAMPLES, InputTimeRange.SampleCount );
  155. if( Commands[eQuery].bDefined ){
  156. FILE* f = NULL;
  157. if( Commands[eOutput].bDefined ){
  158. dwStatus = CheckFile( Commands[eOutput].strValue,
  159. Commands[eYes].bValue ?
  160. VARG_CF_OVERWRITE :
  161. (VARG_CF_PROMPT|VARG_CF_OVERWRITE)
  162. );
  163. CHECK_STATUS( dwStatus );
  164. f = _tfopen( Commands[eOutput].strValue, _T("w") );
  165. if( NULL == f ){
  166. dwStatus = GetLastError();
  167. }
  168. }
  169. pdhStatus = QueryLog( hLogIn, hQuery, f );
  170. if( NULL != f ){
  171. fclose(f);
  172. }
  173. }else if( (!Commands[eCounters].bDefined && !Commands[eCounterFile].bDefined) ){
  174. pdhStatus = QueryLog( hLogIn, hQuery, NULL );
  175. CHECK_STATUS( pdhStatus );
  176. }
  177. if( Commands[eCounters].bDefined ){
  178. pdhStatus = AddCounters( IsTextFormat( dwOutputFormat ), hLogIn, hQuery );
  179. CHECK_STATUS( pdhStatus );
  180. }
  181. if( Commands[eCounterFile].bDefined ){
  182. pdhStatus = GetCountersFromFile(
  183. (IsTextFormat( dwInputFormat ) || IsTextFormat(dwOutputFormat)),
  184. hLogIn,
  185. hQuery
  186. );
  187. CHECK_STATUS( pdhStatus );
  188. }
  189. if( Commands[eBegin].bDefined ){
  190. FILETIME ft;
  191. SystemTimeToFileTime( &Commands[eBegin].stValue, &ft );
  192. RelogInfo.TimeInfo.StartTime = *(LONGLONG *)&ft;
  193. if( RelogInfo.TimeInfo.StartTime >= InputTimeRange.EndTime ){
  194. dwStatus = RELOG_ERROR_TIMERANGE;
  195. }
  196. CHECK_STATUS(dwStatus);
  197. }
  198. if( Commands[eEnd].bDefined ){
  199. FILETIME ft;
  200. SystemTimeToFileTime( &Commands[eEnd].stValue, &ft );
  201. RelogInfo.TimeInfo.EndTime = *(LONGLONG *)&ft;
  202. if( RelogInfo.TimeInfo.EndTime <= InputTimeRange.StartTime ){
  203. dwStatus = RELOG_ERROR_TIMERANGE;
  204. }
  205. CHECK_STATUS(dwStatus);
  206. }
  207. if( Commands[eOutput].bDefined && !Commands[eQuery].bDefined ){
  208. TCHAR strFileBuffer[MAX_PATH];
  209. TCHAR drive[_MAX_DRIVE];
  210. TCHAR path[_MAX_DIR];
  211. TCHAR file[_MAX_FNAME];
  212. TCHAR ext[_MAX_EXT];
  213. RelogInfo.dwFileFormat = dwOutputFormat;
  214. _tsplitpath( Commands[eOutput].strValue, drive, path, file, ext );
  215. if( 0 == _tcslen( ext ) ){
  216. switch( RelogInfo.dwFileFormat ){
  217. case PDH_LOG_TYPE_TSV: StringCchCopy( ext, _MAX_EXT, _T("tsv") ); break;
  218. case PDH_LOG_TYPE_CSV: StringCchCopy( ext, _MAX_EXT, _T("csv") ); break;
  219. case PDH_LOG_TYPE_SQL: break;
  220. case PDH_LOG_TYPE_BINARY:
  221. StringCchCopy( ext, _MAX_EXT, _T("blg") ); break;
  222. }
  223. }
  224. _tmakepath( strFileBuffer, drive, path, file, ext );
  225. if( PDH_LOG_TYPE_SQL != dwOutputFormat ){
  226. if( Commands[eAppend].bDefined ){
  227. dwStatus = CheckFile( strFileBuffer, 0 );
  228. }else{
  229. dwStatus = CheckFile( strFileBuffer, Commands[eYes].bValue ? VARG_CF_OVERWRITE : (VARG_CF_PROMPT|VARG_CF_OVERWRITE) );
  230. }
  231. CHECK_STATUS(dwStatus);
  232. }
  233. RelogInfo.dwFlags = PDH_LOG_WRITE_ACCESS | PDH_LOG_CREATE_ALWAYS;
  234. if( Commands[eAppend].bValue && Commands[eForceAppend].bValue ){
  235. if( IsTextFormat( dwOutputFormat) ){
  236. if( PDH_LOG_TYPE_SQL != dwOutputFormat ){
  237. dwStatus = RELOG_ERROR_BADAPPEND;
  238. goto cleanup;
  239. }
  240. }else{
  241. pdhStatus = PdhGetLogFileType( Commands[eOutput].strValue, &dwOutputFormat );
  242. if( ERROR_SUCCESS == pdhStatus && PDH_LOG_TYPE_BINARY == dwOutputFormat ){
  243. RelogInfo.dwFlags |= PDH_LOG_OPT_APPEND;
  244. }else{
  245. if( ERROR_SUCCESS == pdhStatus ){
  246. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  247. }
  248. goto cleanup;
  249. }
  250. }
  251. }
  252. if( bFakeAppend ){
  253. RelogInfo.strLog = strTempFile;
  254. }else{
  255. RelogInfo.strLog = strFileBuffer;
  256. }
  257. RelogInfo.StatusFunction = ReportStatus;
  258. RelogInfo.TimeInfo.SampleCount = Commands[eInterval].nValue;
  259. ReportStatus( 0, 0.0 );
  260. pdhStatus = PdhRelog( hLogIn, &RelogInfo );
  261. CHECK_STATUS( pdhStatus );
  262. ReportStatus( 0, 1.0 );
  263. varg_printf( g_normal, _T("\n\n") );
  264. if( bFakeAppend ){
  265. BOOL bResult;
  266. bResult = CopyFile( strTempFile, Commands[eOutput].strValue, FALSE );
  267. DeleteFile( strTempFile );
  268. if( !bResult ){
  269. dwStatus = GetLastError();
  270. }
  271. CHECK_STATUS( dwStatus );
  272. RelogInfo.strLog = strFileBuffer;
  273. }
  274. PrintMessage( g_normal, IDS_MESSAGE_OUTPUT );
  275. PrintMessage( g_normal, IDS_MESSAGE_FILE, RelogInfo.strLog );
  276. FileTimeToSystemTime( (FILETIME *)&RelogInfo.TimeInfo.StartTime, &st );
  277. PrintMessage( g_normal, IDS_MESSAGE_BEGIN );
  278. PrintDate( &st );
  279. FileTimeToSystemTime( (FILETIME *)&RelogInfo.TimeInfo.EndTime, &st );
  280. PrintMessage( g_normal, IDS_MESSAGE_END );
  281. PrintDate( &st );
  282. PrintMessage( g_normal, IDS_MESSAGE_SAMPLES, RelogInfo.TimeInfo.SampleCount );
  283. }
  284. cleanup:
  285. if( hLogIn != NULL ){
  286. PdhCloseLog( hLogIn, PDH_FLAGS_CLOSE_QUERY );
  287. }
  288. switch( dwStatus ){
  289. case RELOG_ERROR_TIMERANGE:
  290. PrintMessage( g_debug, IDS_MESSAGE_BADRANGE );
  291. break;
  292. case RELOG_ERROR_BADFORMAT:
  293. PrintMessage( g_debug, IDS_MESSAGE_BADFORMAT, Commands[eFormat].strValue );
  294. break;
  295. case RELOG_ERROR_BADAPPEND:
  296. PrintMessage( g_debug, IDS_MESSAGE_BADFORMAT, Commands[eFormat].strValue );
  297. break;
  298. case RELOG_ERROR_BADFILES:
  299. PrintMessage( g_debug, IDS_MESSAGE_BADFILES );
  300. break;
  301. case ERROR_SUCCESS:
  302. if( ERROR_SUCCESS == pdhStatus ){
  303. PrintMessage( g_normal, IDS_MESSAGE_SUCCESS );
  304. }else{
  305. switch( pdhStatus ){
  306. case PDH_SQL_ALLOC_FAILED:
  307. case PDH_SQL_ALLOCCON_FAILED:
  308. case PDH_SQL_EXEC_DIRECT_FAILED:
  309. case PDH_SQL_FETCH_FAILED:
  310. case PDH_SQL_ROWCOUNT_FAILED:
  311. case PDH_SQL_MORE_RESULTS_FAILED:
  312. case PDH_SQL_CONNECT_FAILED:
  313. case PDH_SQL_BIND_FAILED:
  314. PrintMessage( g_debug, IDS_MESSAGE_SQLERROR );
  315. break;
  316. default:
  317. PrintErrorEx( pdhStatus, _T("PDH.DLL") );
  318. }
  319. dwStatus = pdhStatus;
  320. }
  321. break;
  322. default:
  323. PrintError( dwStatus );
  324. }
  325. FreeCmd();
  326. return dwStatus;
  327. }
  328. void ReportStatus( int Status, double Progress )
  329. {
  330. HRESULT hr;
  331. TCHAR buffer[16];
  332. hr = StringCchPrintf( buffer, 16, _T("%1.2f%%"), Progress*100 );
  333. _tprintf( _T("\r") );
  334. varg_printf( g_normal, _T("%1!s!"), buffer );
  335. }
  336. DWORD
  337. GetTempName( LPTSTR strFile, size_t cchSize )
  338. {
  339. DWORD dwStatus;
  340. GUID guid;
  341. const size_t cchGuidSize = 128;
  342. TCHAR strGUID[cchGuidSize];
  343. DWORD nChar = 0;
  344. dwStatus = UuidCreate( &guid );
  345. if( dwStatus == RPC_S_OK || dwStatus == RPC_S_UUID_LOCAL_ONLY ){
  346. nChar = StringFromGUID2( guid, strGUID, cchGuidSize );
  347. dwStatus = ERROR_SUCCESS;
  348. }
  349. if( 0 == nChar ){
  350. StringCchCopy( strGUID, cchGuidSize, _T("{d41c99ea-c303-4d06-b779-f9e8e20acb8f}") );
  351. }
  352. nChar = GetTempPath( cchSize, strFile );
  353. if( 0 == nChar ){
  354. dwStatus = GetLastError();
  355. }
  356. if( ERROR_SUCCESS == dwStatus ){
  357. StringCchCat( strFile, cchSize, strGUID );
  358. }
  359. return dwStatus;
  360. }
  361. _inline BOOL IsTextFormat( DWORD dwFormat )
  362. {
  363. switch( dwFormat ){
  364. case PDH_LOG_TYPE_CSV:
  365. case PDH_LOG_TYPE_TSV:
  366. case PDH_LOG_TYPE_SQL:
  367. return TRUE;
  368. default:
  369. return FALSE;
  370. }
  371. }
  372. DWORD
  373. GetLogFormat( LPTSTR str, LPDWORD pdwFormat )
  374. {
  375. DWORD dwFormat = PDH_LOG_TYPE_UNDEFINED;
  376. if( str != NULL ){
  377. if( !_tcsicmp( str, _T("TSV")) ){
  378. dwFormat = PDH_LOG_TYPE_TSV;
  379. }else if( !_tcsicmp( str, _T("CSV")) ){
  380. dwFormat = PDH_LOG_TYPE_CSV;
  381. }else if( !_tcsicmp( str, _T("SQL")) ){
  382. dwFormat = PDH_LOG_TYPE_SQL;
  383. }else if( !_tcsicmp( str, _T("BIN")) ){
  384. dwFormat = PDH_LOG_TYPE_BINARY;
  385. }else if( !_tcsicmp( str, _T("ETL")) ){
  386. dwFormat = PDH_LOG_TYPE_BINARY;
  387. }else if( !_tcsicmp( str, _T("BLG")) ){
  388. dwFormat = PDH_LOG_TYPE_BINARY;
  389. }
  390. }
  391. if( dwFormat == PDH_LOG_TYPE_UNDEFINED ){
  392. return RELOG_ERROR_BADFORMAT;
  393. }
  394. *pdwFormat = dwFormat;
  395. return ERROR_SUCCESS;
  396. }
  397. PDH_STATUS
  398. RelogGetMachines( HLOG hLog, LPTSTR* mszMachines )
  399. {
  400. PDH_STATUS pdhStatus;
  401. DWORD dwSize = 0;
  402. pdhStatus = PdhEnumMachinesH( hLog, NULL, &dwSize );
  403. if( ERROR_SUCCESS == pdhStatus ||
  404. PDH_MORE_DATA == pdhStatus ||
  405. PDH_INSUFFICIENT_BUFFER == pdhStatus ){
  406. *mszMachines = (LPTSTR)VARG_ALLOC( sizeof(TCHAR)*dwSize );
  407. if( *mszMachines != NULL ){
  408. pdhStatus = PdhEnumMachinesH( hLog, *mszMachines, &dwSize );
  409. }else{
  410. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  411. }
  412. }
  413. return pdhStatus;
  414. }
  415. PDH_STATUS
  416. RelogAddCounter( BOOL bExpand, HLOG hLog, HQUERY hQuery, LPTSTR strCounter, LPTSTR mszMachines )
  417. {
  418. PDH_STATUS pdhStatus;
  419. HCOUNTER pCounter;
  420. LPTSTR szMachineList;
  421. PPDH_COUNTER_PATH_ELEMENTS pPathElements = NULL;
  422. DWORD dwPathElementsBufferSize = 0;
  423. LPTSTR szPathBuffer = NULL;
  424. DWORD dwPathBufferSize = 0;
  425. LPTSTR szExpandedPathBuffer = NULL;
  426. DWORD dwExpandedPathBufferSize = 0;
  427. BOOL bMachineDeclared = FALSE;
  428. if( hQuery == NULL || strCounter == NULL ){
  429. return ERROR_SUCCESS;
  430. }
  431. //
  432. // Parse original path
  433. //
  434. if( _tcslen( strCounter ) > 3 ){
  435. if( strCounter[1] == _T('\\') ){
  436. bMachineDeclared = TRUE;
  437. }
  438. }
  439. do{
  440. pdhStatus = PdhParseCounterPath( strCounter, pPathElements, &dwPathElementsBufferSize, 0 );
  441. if( PDH_MORE_DATA == pdhStatus ){
  442. VARG_FREE( pPathElements );
  443. pPathElements = (PPDH_COUNTER_PATH_ELEMENTS)VARG_ALLOC( ++dwPathElementsBufferSize );
  444. if( NULL == pPathElements ){
  445. break;
  446. }
  447. }
  448. }while( PDH_MORE_DATA == pdhStatus );
  449. if( NULL == pPathElements ){
  450. return ERROR_OUTOFMEMORY;
  451. }
  452. //
  453. // If the original path contains a machine name
  454. // only add that machine. Otherwise counter for
  455. // all machines in the mszMachines list
  456. //
  457. if( bMachineDeclared ){
  458. szMachineList = pPathElements->szMachineName;
  459. }else{
  460. szMachineList = mszMachines;
  461. }
  462. while( NULL != szMachineList ){
  463. pPathElements->szMachineName = szMachineList;
  464. do{
  465. pdhStatus = PdhMakeCounterPath( pPathElements, szPathBuffer, &dwPathBufferSize, 0 );
  466. if( PDH_MORE_DATA == pdhStatus ){
  467. VARG_FREE( szPathBuffer );
  468. szPathBuffer = (LPTSTR)VARG_ALLOC( ++dwPathBufferSize * sizeof(TCHAR) );
  469. if( NULL == szPathBuffer ){
  470. break;
  471. }
  472. }
  473. }while( PDH_MORE_DATA == pdhStatus );
  474. //
  475. // If writing to a text file wild cards must be expanded
  476. //
  477. if( bExpand ){
  478. do{
  479. pdhStatus = PdhExpandWildCardPathH(
  480. hLog,
  481. szPathBuffer,
  482. szExpandedPathBuffer,
  483. &dwExpandedPathBufferSize,
  484. 0
  485. );
  486. if( PDH_MORE_DATA == pdhStatus ){
  487. VARG_FREE( szExpandedPathBuffer );
  488. szExpandedPathBuffer = (LPTSTR)VARG_ALLOC( ++dwExpandedPathBufferSize * sizeof(TCHAR) );
  489. if( szExpandedPathBuffer == NULL ){
  490. break;
  491. }
  492. }
  493. }while(PDH_MORE_DATA == pdhStatus);
  494. if( ERROR_SUCCESS == pdhStatus && szExpandedPathBuffer != NULL ){
  495. LPTSTR szCounter = szExpandedPathBuffer;
  496. while( *szCounter != _T('\0') ){
  497. pdhStatus = PdhAddCounter(
  498. hQuery,
  499. szCounter,
  500. 0,
  501. &pCounter
  502. );
  503. szCounter += (_tcslen( szCounter) +1 );
  504. }
  505. }
  506. }else{
  507. pdhStatus = PdhAddCounter(
  508. hQuery,
  509. szPathBuffer,
  510. 0,
  511. &pCounter
  512. );
  513. }
  514. if( bMachineDeclared ){
  515. szMachineList = NULL;
  516. }else{
  517. szMachineList += (_tcslen( szMachineList ) + 1);
  518. if( _T('\0') == *szMachineList ){
  519. szMachineList = NULL;
  520. }
  521. }
  522. }
  523. VARG_FREE( szPathBuffer );
  524. VARG_FREE( pPathElements );
  525. VARG_FREE( szExpandedPathBuffer );
  526. return ERROR_SUCCESS;
  527. }
  528. PDH_STATUS
  529. AddCounters( BOOL bExpand, HLOG hLog, HQUERY hQuery )
  530. {
  531. PDH_STATUS pdhStatus;
  532. LPTSTR strPath = Commands[eCounters].strValue;
  533. LPTSTR mszMachines = NULL;
  534. RelogGetMachines( hLog, &mszMachines );
  535. if( strPath != NULL ){
  536. while( *strPath != _T('\0') ){
  537. pdhStatus = RelogAddCounter( bExpand, hLog, hQuery, strPath, mszMachines );
  538. strPath += _tcslen( strPath )+1;
  539. }
  540. }
  541. VARG_FREE( mszMachines );
  542. return ERROR_SUCCESS;
  543. }
  544. PDH_STATUS
  545. GetCountersFromFile( BOOL bExpand, HLOG hLog, HQUERY hQuery )
  546. {
  547. TCHAR buffer[MAXSTR];
  548. PDH_STATUS pdhStatus;
  549. LPTSTR strCounter = NULL;
  550. LPTSTR mszMachines = NULL;
  551. FILE* f = _tfopen( Commands[eCounterFile].strValue, _T("r") );
  552. if( !f ){
  553. DWORD dwStatus = GetLastError();
  554. return PDH_FILE_NOT_FOUND;
  555. }
  556. RelogGetMachines( hLog, &mszMachines );
  557. while( NULL != _fgetts( buffer, MAXSTR, f ) ){
  558. if( buffer[0] == _T(';') || // comments
  559. buffer[0] == _T('#') ){
  560. continue;
  561. }
  562. Chomp(buffer);
  563. strCounter = _tcstok( buffer, _T("\"\n") );
  564. if( strCounter != NULL ){
  565. pdhStatus = RelogAddCounter( bExpand, hLog, hQuery, buffer, mszMachines );
  566. }
  567. }
  568. fclose( f );
  569. VARG_FREE( mszMachines );
  570. return ERROR_SUCCESS;
  571. }
  572. _inline BOOL IsSameInstance( LPTSTR strLastInstance, LPTSTR strInstance )
  573. {
  574. if( strLastInstance == NULL || strInstance == NULL ){
  575. return FALSE;
  576. }
  577. return ( _tcscmp( strLastInstance, strInstance ) == 0 );
  578. }
  579. PDH_STATUS
  580. QueryLog( HLOG hLog, HQUERY hQuery, FILE* f )
  581. {
  582. PDH_STATUS pdhStatus;
  583. LPTSTR mszMachines = NULL;
  584. LPTSTR strMachine = NULL;
  585. LPTSTR strFullCounterPath = NULL;
  586. DWORD dwFullCounterPathSize = 0;
  587. DWORD dwMachines = 0;
  588. HCOUNTER pCounter;
  589. pdhStatus = PdhEnumMachinesH( hLog, mszMachines, &dwMachines );
  590. if( ERROR_SUCCESS == pdhStatus ||
  591. PDH_MORE_DATA == pdhStatus ||
  592. PDH_INSUFFICIENT_BUFFER == pdhStatus ){
  593. mszMachines = (LPTSTR)VARG_ALLOC( dwMachines * sizeof(TCHAR) );
  594. if( mszMachines == NULL ){
  595. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  596. goto cleanup;
  597. }
  598. pdhStatus = PdhEnumMachinesH( hLog, mszMachines, &dwMachines );
  599. if( ERROR_SUCCESS == pdhStatus ){
  600. strMachine = mszMachines;
  601. while( NULL != strMachine && strMachine[0] != _T('\0') ){
  602. LPTSTR mszObjects = NULL;
  603. LPTSTR strObject = NULL;
  604. DWORD dwObjects = 0;
  605. pdhStatus = PdhEnumObjectsH(
  606. hLog,
  607. strMachine,
  608. mszObjects,
  609. &dwObjects,
  610. PERF_DETAIL_WIZARD,
  611. FALSE
  612. );
  613. if( ERROR_SUCCESS == pdhStatus ||
  614. PDH_MORE_DATA == pdhStatus ||
  615. PDH_INSUFFICIENT_BUFFER == pdhStatus ){
  616. mszObjects = (LPTSTR)VARG_ALLOC( dwObjects * sizeof(TCHAR));
  617. if( mszObjects == NULL ){
  618. VARG_FREE( mszMachines );
  619. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  620. goto cleanup;
  621. }
  622. pdhStatus = PdhEnumObjectsH(
  623. hLog,
  624. strMachine,
  625. mszObjects,
  626. &dwObjects,
  627. PERF_DETAIL_WIZARD,
  628. FALSE
  629. );
  630. strObject = mszObjects;
  631. while( NULL != strObject && strObject[0] != _T('\0') ){
  632. LPTSTR mszCounters = NULL;
  633. LPTSTR strCounter = NULL;
  634. LPTSTR mszInstances = NULL;
  635. LPTSTR strInstance = NULL;
  636. DWORD dwCounters = 0;
  637. DWORD dwInstances = 0;
  638. pdhStatus = PdhEnumObjectItemsH(
  639. hLog,
  640. strMachine,
  641. strObject,
  642. mszCounters,
  643. &dwCounters,
  644. mszInstances,
  645. &dwInstances,
  646. PERF_DETAIL_WIZARD,
  647. 0
  648. );
  649. if( ERROR_SUCCESS == pdhStatus ||
  650. PDH_MORE_DATA == pdhStatus ||
  651. PDH_INSUFFICIENT_BUFFER == pdhStatus ){
  652. if( dwCounters > 0 ){
  653. mszCounters = (LPTSTR)VARG_ALLOC( dwCounters * sizeof(TCHAR) );
  654. }
  655. if( dwInstances > 0 ){
  656. mszInstances = (LPTSTR)VARG_ALLOC( dwInstances * sizeof(TCHAR) );
  657. }
  658. if( (mszCounters == NULL && dwCounters > 0 ) ||
  659. (mszInstances == NULL && dwInstances > 0) ){
  660. VARG_FREE( mszMachines );
  661. VARG_FREE( mszObjects );
  662. VARG_FREE( mszCounters );
  663. VARG_FREE( mszInstances );
  664. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  665. goto cleanup;
  666. }
  667. pdhStatus = PdhEnumObjectItemsH(
  668. hLog,
  669. strMachine,
  670. strObject,
  671. mszCounters,
  672. &dwCounters,
  673. mszInstances,
  674. &dwInstances,
  675. PERF_DETAIL_WIZARD,
  676. 0
  677. );
  678. if( ERROR_SUCCESS == pdhStatus ){
  679. strCounter = mszCounters;
  680. while( NULL != strCounter && strCounter[0] != _T('\0') ){
  681. PDH_COUNTER_PATH_ELEMENTS_W pdhElements;
  682. ZeroMemory( &pdhElements, sizeof( PDH_COUNTER_PATH_ELEMENTS ) );
  683. pdhElements.szMachineName = strMachine;
  684. pdhElements.szObjectName = strObject;
  685. pdhElements.szCounterName = strCounter;
  686. strInstance = mszInstances;
  687. if( NULL != strInstance && strInstance[0] != _T('\0') ){
  688. LPTSTR strLastInstance = NULL;
  689. ULONG nInstance = 0;
  690. while( strInstance[0] != _T('\0') ){
  691. DWORD dwSize = dwFullCounterPathSize;
  692. pdhElements.szInstanceName = strInstance;
  693. if( ! IsSameInstance( strLastInstance, strInstance ) ){
  694. pdhElements.dwInstanceIndex = -1;
  695. nInstance = 0;
  696. }else{
  697. pdhElements.dwInstanceIndex = ++nInstance;
  698. }
  699. pdhStatus = PdhMakeCounterPath( &pdhElements, strFullCounterPath, &dwSize, 0 );
  700. if( PDH_INSUFFICIENT_BUFFER == pdhStatus || PDH_MORE_DATA == pdhStatus ){
  701. VARG_FREE( strFullCounterPath );
  702. strFullCounterPath = (LPTSTR)VARG_ALLOC( dwSize * sizeof(TCHAR) );
  703. if( NULL != strFullCounterPath ){
  704. dwFullCounterPathSize = dwSize;
  705. pdhStatus = PdhMakeCounterPath( &pdhElements, strFullCounterPath, &dwSize, 0 );
  706. }
  707. }
  708. strLastInstance = strInstance;
  709. strInstance += _tcslen( strInstance ) + 1;
  710. if( Commands[eQuery].bValue ){
  711. if( NULL != f ){
  712. _ftprintf( f, _T("%s\n"), strFullCounterPath );
  713. }else{
  714. varg_printf( g_normal, _T("%1!s!\n"), strFullCounterPath );
  715. }
  716. }
  717. if( Commands[eCounters].bDefined == FALSE && Commands[eOutput].bDefined ){
  718. pdhStatus = PdhAddCounter(
  719. hQuery,
  720. strFullCounterPath,
  721. 0,
  722. &pCounter
  723. );
  724. }
  725. }
  726. }else{
  727. DWORD dwSize = dwFullCounterPathSize;
  728. pdhStatus = PdhMakeCounterPath( &pdhElements, strFullCounterPath, &dwSize, 0 );
  729. if( PDH_INSUFFICIENT_BUFFER == pdhStatus || PDH_MORE_DATA == pdhStatus ){
  730. VARG_FREE( strFullCounterPath );
  731. strFullCounterPath = (LPTSTR)VARG_ALLOC( dwSize * sizeof(TCHAR) );
  732. if( NULL != strFullCounterPath ){
  733. dwFullCounterPathSize = dwSize;
  734. pdhStatus = PdhMakeCounterPath( &pdhElements, strFullCounterPath, &dwSize, 0 );
  735. }
  736. }
  737. if( Commands[eQuery].bValue ){
  738. if( NULL != f ){
  739. _ftprintf( f, _T("%s\n"), strFullCounterPath );
  740. }else{
  741. varg_printf( g_normal, _T("%1!s!\n"), strFullCounterPath );
  742. }
  743. }
  744. if( Commands[eCounters].bDefined == FALSE && Commands[eOutput].bDefined ){
  745. pdhStatus = PdhAddCounter(
  746. hQuery,
  747. strFullCounterPath,
  748. 0,
  749. &pCounter
  750. );
  751. }
  752. }
  753. strCounter += _tcslen( strCounter ) + 1;
  754. }
  755. }
  756. VARG_FREE( mszCounters );
  757. VARG_FREE( mszInstances );
  758. }
  759. strObject += _tcslen( strObject ) + 1;
  760. }
  761. VARG_FREE( mszObjects );
  762. }
  763. strMachine += _tcslen( strMachine ) + 1;
  764. }
  765. }
  766. VARG_FREE( mszMachines );
  767. }
  768. cleanup:
  769. VARG_FREE( strFullCounterPath );
  770. if( NULL == f ){
  771. if( ERROR_SUCCESS == pdhStatus && Commands[eQuery].bValue){
  772. varg_printf( g_normal, _T("\n") );
  773. }
  774. }
  775. return pdhStatus;
  776. }