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.

789 lines
28 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 <pdh.h>
  11. #include <pdhmsg.h>
  12. #include <pdhp.h>
  13. #include "resource.h"
  14. #include "varg.c"
  15. DWORD GetLogFormat( LPTSTR str, LPDWORD pdwFormat );
  16. PDH_STATUS GetCountersFromFile( BOOL bExpand, HLOG hLog, HQUERY hQuery );
  17. PDH_STATUS QueryLog( HLOG hLog, HQUERY hQuery, FILE* f );
  18. PDH_STATUS AddCounters( BOOL bExpand, HLOG hLog, HQUERY hQuery );
  19. _inline BOOL IsTextFormat( DWORD dwFormat );
  20. #define PDH_LOG_TYPE_RETIRED_BIN_ 3
  21. #define CHECK_STATUS( hr ) if( ERROR_SUCCESS != hr ){ goto cleanup; }
  22. #define RELOG_ERROR_BADFILES 0xF0000001
  23. #define RELOG_ERROR_BADFORMAT 0xF0000002
  24. #define RELOG_ERROR_TIMERANGE 0xF0000003
  25. #define RELOG_ERROR_BADAPPEND 0xF0000004
  26. VARG_DECLARE_COMMANDS
  27. VARG_DEBUG( VARG_FLAG_OPTIONAL|VARG_FLAG_HIDDEN )
  28. VARG_HELP ( VARG_FLAG_OPTIONAL )
  29. VARG_BOOL ( IDS_PARAM_APPEND, VARG_FLAG_OPTIONAL, FALSE )
  30. VARG_MSZ ( IDS_PARAM_COUNTERS, VARG_FLAG_OPTIONAL, _T("") )
  31. VARG_STR ( IDS_PARAM_COUNTERFILE, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_FILENAME, _T("") )
  32. VARG_STR ( IDS_PARAM_FORMAT, VARG_FLAG_OPTIONAL|VARG_FLAG_LITERAL, _T("BIN") )
  33. VARG_MSZ ( IDS_PARAM_INPUT, VARG_FLAG_REQUIRED|VARG_FLAG_NOFLAG|VARG_FLAG_EXPANDFILES|VARG_FLAG_ARG_FILENAME, _T("") )
  34. VARG_INT ( IDS_PARAM_INTERVAL, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_DEFAULT, 0 )
  35. VARG_STR ( IDS_PARAM_OUTPUT, VARG_FLAG_OPTIONAL|VARG_FLAG_DEFAULTABLE|VARG_FLAG_RCDEFAULT, IDS_DEFAULT_OUTPUT )
  36. VARG_DATE ( IDS_PARAM_BEGIN, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_DATE )
  37. VARG_DATE ( IDS_PARAM_END, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_DATE )
  38. VARG_INI ( IDS_PARAM_SETTINGS, VARG_FLAG_OPTIONAL, NULL )
  39. VARG_BOOL ( IDS_PARAM_QUERY, VARG_FLAG_OPTIONAL, FALSE )
  40. VARG_BOOL ( IDS_PARAM_YES, VARG_FLAG_OPTIONAL, FALSE )
  41. VARG_DECLARE_NAMES
  42. eDebug,
  43. eHelp,
  44. eAppend,
  45. eCounters,
  46. eCounterFile,
  47. eFormat,
  48. eInput,
  49. eInterval,
  50. eOutput,
  51. eBegin,
  52. eEnd,
  53. eSettings,
  54. eQuery,
  55. eYes,
  56. VARG_DECLARE_FORMAT
  57. VARG_EXHELP( eFormat, IDS_EXAMPLE_FORMAT )
  58. VARG_EXHELP( eQuery, IDS_EXAMPLE_QUERY )
  59. VARG_EXHELP( eCounterFile, IDS_EXAMPLE_COUNTERFILE )
  60. VARG_EXHELP( eCounters, IDS_EXAMPLE_COUNTERS )
  61. VARG_DECLARE_END
  62. int __cdecl _tmain( int argc, LPTSTR* argv )
  63. {
  64. DWORD dwStatus = ERROR_SUCCESS;
  65. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  66. PDH_RELOG_INFO RelogInfo;
  67. DWORD dwOutputFormat;
  68. DWORD dwInputFormat;
  69. PDH_TIME_INFO InputTimeRange;
  70. LPTSTR strFile = NULL;
  71. ParseCmd( argc, argv );
  72. HLOG hLogIn = NULL;
  73. HQUERY hQuery = NULL;
  74. ZeroMemory( &RelogInfo, sizeof(PDH_RELOG_INFO) );
  75. DWORD dwNumEntries = 1;
  76. DWORD dwBufferSize = sizeof(PDH_TIME_INFO);
  77. int nBinary = 0;
  78. int nFiles = 0;
  79. if( Commands[eInput].strValue == NULL ){
  80. dwStatus = ERROR_OUTOFMEMORY;
  81. goto cleanup;
  82. }
  83. dwStatus = GetLogFormat( Commands[eFormat].strValue, &dwOutputFormat );
  84. CHECK_STATUS(dwStatus);
  85. strFile = Commands[eInput].strValue;
  86. PrintMessage( g_normal, IDS_MESSAGE_INPUT );
  87. PrintMessage( g_normal, IDS_MESSAGE_FILES );
  88. while( strFile != NULL && *strFile != _T('\0') ){
  89. pdhStatus = PdhGetLogFileType( strFile, &dwInputFormat );
  90. nFiles++;
  91. if( pdhStatus != ERROR_SUCCESS ){
  92. dwInputFormat = 0;
  93. }
  94. switch( dwInputFormat ){
  95. case PDH_LOG_TYPE_RETIRED_BIN_:
  96. PrintMessage( g_normal, IDS_MESSAGE_LOG_OLD_BIN, strFile );
  97. break;
  98. case PDH_LOG_TYPE_CSV:
  99. PrintMessage( g_normal, IDS_MESSAGE_LOG_CSV, strFile );
  100. break;
  101. case PDH_LOG_TYPE_TSV:
  102. PrintMessage( g_normal, IDS_MESSAGE_LOG_TSV, strFile );
  103. break;
  104. case PDH_LOG_TYPE_BINARY:
  105. nBinary++;
  106. PrintMessage( g_normal, IDS_MESSAGE_LOG_BINARY, strFile );
  107. break;
  108. case PDH_LOG_TYPE_PERFMON:
  109. PrintMessage( g_normal, IDS_MESSAGE_LOG_PERFMON, strFile );
  110. break;
  111. default:
  112. PrintMessage( g_normal, IDS_MESSAGE_LOG_UNKNOWN, strFile );
  113. }
  114. strFile += _tcslen(strFile)+1;
  115. }
  116. varg_printf( g_normal, _T("\n") );
  117. if( nFiles > 1 && nFiles > nBinary ){
  118. dwStatus = RELOG_ERROR_BADFILES;
  119. goto cleanup;
  120. }
  121. pdhStatus = PdhBindInputDataSource( &hLogIn, Commands[eInput].strValue );
  122. CHECK_STATUS( pdhStatus );
  123. pdhStatus = PdhOpenQueryH( hLogIn, NULL, &hQuery );
  124. CHECK_STATUS( pdhStatus );
  125. pdhStatus = PdhGetDataSourceTimeRangeH (
  126. hLogIn,
  127. &dwNumEntries,
  128. &InputTimeRange,
  129. &dwBufferSize
  130. );
  131. CHECK_STATUS( pdhStatus );
  132. SYSTEMTIME st;
  133. FileTimeToSystemTime( (FILETIME *)&InputTimeRange.StartTime, &st );
  134. PrintMessage( g_normal, IDS_MESSAGE_BEGIN );
  135. PrintDate( &st );
  136. FileTimeToSystemTime( (FILETIME *)&InputTimeRange.EndTime, &st );
  137. PrintMessage( g_normal, IDS_MESSAGE_END );
  138. PrintDate( &st );
  139. PrintMessage( g_normal, IDS_MESSAGE_SAMPLES, InputTimeRange.SampleCount );
  140. if( Commands[eQuery].bDefined ){
  141. FILE* f = NULL;
  142. if( Commands[eOutput].bDefined ){
  143. dwStatus = CheckFile( Commands[eOutput].strValue,
  144. Commands[eYes].bValue ?
  145. VARG_CF_OVERWRITE :
  146. (VARG_CF_PROMPT|VARG_CF_OVERWRITE)
  147. );
  148. CHECK_STATUS( dwStatus );
  149. f = _tfopen( Commands[eOutput].strValue, _T("w") );
  150. if( NULL == f ){
  151. dwStatus = GetLastError();
  152. }
  153. }
  154. pdhStatus = QueryLog( hLogIn, hQuery, f );
  155. if( NULL != f ){
  156. fclose(f);
  157. }
  158. }else if( (!Commands[eCounters].bDefined && !Commands[eCounterFile].bDefined) ){
  159. pdhStatus = QueryLog( hLogIn, hQuery, NULL );
  160. CHECK_STATUS( pdhStatus );
  161. }
  162. if( Commands[eCounters].bDefined ){
  163. pdhStatus = AddCounters( dwInputFormat, hLogIn, hQuery );
  164. CHECK_STATUS( pdhStatus );
  165. }
  166. if( Commands[eCounterFile].bDefined ){
  167. pdhStatus = GetCountersFromFile(
  168. (IsTextFormat( dwInputFormat ) || IsTextFormat(dwOutputFormat)),
  169. hLogIn,
  170. hQuery
  171. );
  172. CHECK_STATUS( pdhStatus );
  173. }
  174. if( Commands[eBegin].bDefined ){
  175. FILETIME ft;
  176. SystemTimeToFileTime( &Commands[eBegin].stValue, &ft );
  177. RelogInfo.TimeInfo.StartTime = *(LONGLONG *)&ft;
  178. if( RelogInfo.TimeInfo.StartTime >= InputTimeRange.EndTime ){
  179. dwStatus = RELOG_ERROR_TIMERANGE;
  180. }
  181. CHECK_STATUS(dwStatus);
  182. }
  183. if( Commands[eEnd].bDefined ){
  184. FILETIME ft;
  185. SystemTimeToFileTime( &Commands[eEnd].stValue, &ft );
  186. RelogInfo.TimeInfo.EndTime = *(LONGLONG *)&ft;
  187. if( RelogInfo.TimeInfo.EndTime <= InputTimeRange.StartTime ){
  188. dwStatus = RELOG_ERROR_TIMERANGE;
  189. }
  190. CHECK_STATUS(dwStatus);
  191. }
  192. if( Commands[eOutput].bDefined && !Commands[eQuery].bDefined ){
  193. TCHAR strFile[MAX_PATH];
  194. TCHAR drive[10];
  195. TCHAR path[MAXSTR];
  196. TCHAR file[MAXSTR];
  197. TCHAR ext[MAXSTR];
  198. RelogInfo.dwFileFormat = dwOutputFormat;
  199. _tsplitpath( Commands[eOutput].strValue, drive, path, file, ext );
  200. if( 0 == _tcslen( ext ) ){
  201. switch( RelogInfo.dwFileFormat ){
  202. case PDH_LOG_TYPE_TSV: _tcscpy( ext, _T("tsv") ); break;
  203. case PDH_LOG_TYPE_CSV: _tcscpy( ext, _T("csv") ); break;
  204. case PDH_LOG_TYPE_SQL: break;
  205. case PDH_LOG_TYPE_BINARY:
  206. _tcscpy( ext, _T("blg") ); break;
  207. }
  208. }
  209. _tmakepath( strFile, drive, path, file, ext );
  210. if( PDH_LOG_TYPE_SQL != dwOutputFormat ){
  211. if( Commands[eAppend].bDefined ){
  212. dwStatus = CheckFile( strFile, 0 );
  213. }else{
  214. dwStatus = CheckFile( strFile, Commands[eYes].bValue ? VARG_CF_OVERWRITE : (VARG_CF_PROMPT|VARG_CF_OVERWRITE) );
  215. }
  216. CHECK_STATUS(dwStatus);
  217. }
  218. RelogInfo.dwFlags = PDH_LOG_WRITE_ACCESS | PDH_LOG_CREATE_ALWAYS;
  219. if( Commands[eAppend].bValue ){
  220. if( IsTextFormat( dwOutputFormat) ){
  221. if( PDH_LOG_TYPE_SQL != dwOutputFormat ){
  222. dwStatus = RELOG_ERROR_BADAPPEND;
  223. goto cleanup;
  224. }
  225. }else{
  226. pdhStatus = PdhGetLogFileType( Commands[eOutput].strValue, &dwOutputFormat );
  227. if( ERROR_SUCCESS == pdhStatus && PDH_LOG_TYPE_BINARY == dwOutputFormat ){
  228. RelogInfo.dwFlags |= PDH_LOG_OPT_APPEND;
  229. }else{
  230. if( ERROR_SUCCESS == pdhStatus ){
  231. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  232. }
  233. goto cleanup;
  234. }
  235. }
  236. }
  237. RelogInfo.strLog = strFile;
  238. RelogInfo.TimeInfo.SampleCount = Commands[eInterval].nValue;
  239. pdhStatus = PdhRelog( hLogIn, &RelogInfo );
  240. CHECK_STATUS( pdhStatus );
  241. PrintMessage( g_normal, IDS_MESSAGE_OUTPUT );
  242. PrintMessage( g_normal, IDS_MESSAGE_FILE, RelogInfo.strLog );
  243. SYSTEMTIME st;
  244. FileTimeToSystemTime( (FILETIME *)&RelogInfo.TimeInfo.StartTime, &st );
  245. PrintMessage( g_normal, IDS_MESSAGE_BEGIN );
  246. PrintDate( &st );
  247. FileTimeToSystemTime( (FILETIME *)&RelogInfo.TimeInfo.EndTime, &st );
  248. PrintMessage( g_normal, IDS_MESSAGE_END );
  249. PrintDate( &st );
  250. PrintMessage( g_normal, IDS_MESSAGE_SAMPLES, RelogInfo.TimeInfo.SampleCount );
  251. }
  252. cleanup:
  253. if( hLogIn != NULL ){
  254. PdhCloseLog( hLogIn, PDH_FLAGS_CLOSE_QUERY );
  255. }
  256. switch( dwStatus ){
  257. case RELOG_ERROR_TIMERANGE:
  258. PrintMessage( g_debug, IDS_MESSAGE_BADRANGE );
  259. break;
  260. case RELOG_ERROR_BADFORMAT:
  261. PrintMessage( g_debug, IDS_MESSAGE_BADFORMAT, Commands[eFormat].strValue );
  262. break;
  263. case RELOG_ERROR_BADAPPEND:
  264. PrintMessage( g_debug, IDS_MESSAGE_BADFORMAT, Commands[eFormat].strValue );
  265. break;
  266. case RELOG_ERROR_BADFILES:
  267. PrintMessage( g_debug, IDS_MESSAGE_BADFILES );
  268. break;
  269. case ERROR_SUCCESS:
  270. if( ERROR_SUCCESS == pdhStatus ){
  271. PrintMessage( g_normal, IDS_MESSAGE_SUCCESS );
  272. }else{
  273. PrintErrorEx( pdhStatus, _T("PDH.DLL") );
  274. dwStatus = pdhStatus;
  275. }
  276. break;
  277. default:
  278. PrintError( dwStatus );
  279. }
  280. FreeCmd();
  281. return dwStatus;
  282. }
  283. _inline BOOL IsTextFormat( DWORD dwFormat )
  284. {
  285. switch( dwFormat ){
  286. case PDH_LOG_TYPE_CSV:
  287. case PDH_LOG_TYPE_TSV:
  288. case PDH_LOG_TYPE_SQL:
  289. return TRUE;
  290. default:
  291. return FALSE;
  292. }
  293. }
  294. DWORD
  295. GetLogFormat( LPTSTR str, LPDWORD pdwFormat )
  296. {
  297. DWORD dwFormat = PDH_LOG_TYPE_UNDEFINED;
  298. if( str != NULL ){
  299. if( !_tcsicmp( str, _T("TSV")) ){
  300. dwFormat = PDH_LOG_TYPE_TSV;
  301. }else if( !_tcsicmp( str, _T("CSV")) ){
  302. dwFormat = PDH_LOG_TYPE_CSV;
  303. }else if( !_tcsicmp( str, _T("SQL")) ){
  304. dwFormat = PDH_LOG_TYPE_SQL;
  305. }else if( !_tcsicmp( str, _T("BIN")) ){
  306. dwFormat = PDH_LOG_TYPE_BINARY;
  307. }else if( !_tcsicmp( str, _T("ETL")) ){
  308. dwFormat = PDH_LOG_TYPE_BINARY;
  309. }else if( !_tcsicmp( str, _T("BLG")) ){
  310. dwFormat = PDH_LOG_TYPE_BINARY;
  311. }
  312. }
  313. if( dwFormat == PDH_LOG_TYPE_UNDEFINED ){
  314. return RELOG_ERROR_BADFORMAT;
  315. }
  316. *pdwFormat = dwFormat;
  317. return ERROR_SUCCESS;
  318. }
  319. PDH_STATUS
  320. RelogGetMachines( HLOG hLog, LPTSTR* mszMachines )
  321. {
  322. PDH_STATUS pdhStatus;
  323. DWORD dwSize = 0;
  324. pdhStatus = PdhEnumMachinesH( hLog, NULL, &dwSize );
  325. if( ERROR_SUCCESS == pdhStatus ||
  326. PDH_MORE_DATA == pdhStatus ||
  327. PDH_INSUFFICIENT_BUFFER == pdhStatus ){
  328. *mszMachines = (LPTSTR)VARG_ALLOC( sizeof(TCHAR)*dwSize );
  329. if( *mszMachines != NULL ){
  330. pdhStatus = PdhEnumMachinesH( hLog, *mszMachines, &dwSize );
  331. }else{
  332. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  333. }
  334. }
  335. return pdhStatus;
  336. }
  337. PDH_STATUS
  338. RelogAddCounter( BOOL bExpand, HLOG hLog, HQUERY hQuery, LPTSTR strCounter, LPTSTR mszMachines )
  339. {
  340. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  341. HCOUNTER pCounter;
  342. if( hQuery == NULL || strCounter == NULL ){
  343. return ERROR_SUCCESS;
  344. }
  345. if( _tcslen( strCounter ) > 3 ){
  346. if( strCounter[1] == _T('\\') ){
  347. pdhStatus = PdhAddCounter(
  348. hQuery,
  349. strCounter,
  350. 0,
  351. &pCounter
  352. );
  353. }else{
  354. TCHAR buffer[MAXSTR];
  355. LPTSTR strMachine = mszMachines;
  356. if( strMachine != NULL ){
  357. while( *strMachine != _T('\0') ){
  358. _stprintf( buffer, _T("%s%s%s"),
  359. strMachine,
  360. (*strCounter == _T('\\')) ? _T("") : _T("\\"),
  361. strCounter );
  362. if( bExpand ){
  363. LPTSTR pBuffer = NULL;
  364. DWORD dwBufferSize = 0;
  365. do{
  366. pdhStatus = PdhExpandWildCardPathH(
  367. hLog,
  368. buffer,
  369. pBuffer,
  370. &dwBufferSize,
  371. 0
  372. );
  373. if( PDH_MORE_DATA == pdhStatus ){
  374. VARG_FREE( pBuffer );
  375. pBuffer = (LPTSTR)VARG_ALLOC( ++dwBufferSize * sizeof(TCHAR) );
  376. if( pBuffer == NULL ){
  377. break;
  378. }
  379. }
  380. }while(PDH_MORE_DATA == pdhStatus);
  381. if( ERROR_SUCCESS == pdhStatus && pBuffer != NULL ){
  382. LPTSTR szCounter = pBuffer;
  383. while( *szCounter != _T('\0') ){
  384. pdhStatus = PdhAddCounter(
  385. hQuery,
  386. szCounter,
  387. 0,
  388. &pCounter
  389. );
  390. szCounter += (_tcslen( szCounter) +1 );
  391. }
  392. }
  393. VARG_FREE( pBuffer );
  394. }else{
  395. pdhStatus = PdhAddCounter(
  396. hQuery,
  397. buffer,
  398. 0,
  399. &pCounter
  400. );
  401. }
  402. strMachine += (_tcslen( strMachine ) + 1);
  403. }
  404. }
  405. }
  406. }
  407. return ERROR_SUCCESS;
  408. }
  409. PDH_STATUS
  410. AddCounters( BOOL bExpand, HLOG hLog, HQUERY hQuery )
  411. {
  412. PDH_STATUS pdhStatus;
  413. LPTSTR strPath = Commands[eCounters].strValue;
  414. LPTSTR mszMachines = NULL;
  415. RelogGetMachines( hLog, &mszMachines );
  416. if( strPath != NULL ){
  417. while( *strPath != _T('\0') ){
  418. pdhStatus = RelogAddCounter( bExpand, hLog, hQuery, strPath, mszMachines );
  419. strPath += _tcslen( strPath )+1;
  420. }
  421. }
  422. VARG_FREE( mszMachines );
  423. return ERROR_SUCCESS;
  424. }
  425. PDH_STATUS
  426. GetCountersFromFile( BOOL bExpand, HLOG hLog, HQUERY hQuery )
  427. {
  428. TCHAR buffer[MAXSTR];
  429. PDH_STATUS pdhStatus;
  430. LPTSTR strCounter = NULL;
  431. LPTSTR mszMachines = NULL;
  432. FILE* f = _tfopen( Commands[eCounterFile].strValue, _T("r") );
  433. if( !f ){
  434. DWORD dwStatus = GetLastError();
  435. return PDH_LOG_FILE_OPEN_ERROR;
  436. }
  437. RelogGetMachines( hLog, &mszMachines );
  438. while( NULL != _fgetts( buffer, MAXSTR, f ) ){
  439. if( buffer[0] == _T(';') || // comments
  440. buffer[0] == _T('#') ){
  441. continue;
  442. }
  443. Chomp(buffer);
  444. strCounter = _tcstok( buffer, _T("\"\n") );
  445. if( strCounter != NULL ){
  446. pdhStatus = RelogAddCounter( bExpand, hLog, hQuery, buffer, mszMachines );
  447. }
  448. }
  449. fclose( f );
  450. VARG_FREE( mszMachines );
  451. return ERROR_SUCCESS;
  452. }
  453. _inline BOOL IsSameInstance( LPTSTR strLastInstance, LPTSTR strInstance )
  454. {
  455. if( strLastInstance == NULL || strInstance == NULL ){
  456. return FALSE;
  457. }
  458. return ( _tcscmp( strLastInstance, strInstance ) == 0 );
  459. }
  460. PDH_STATUS
  461. QueryLog( HLOG hLog, HQUERY hQuery, FILE* f )
  462. {
  463. PDH_STATUS pdhStatus;
  464. LPTSTR mszMachines = NULL;
  465. LPTSTR strMachine = NULL;
  466. LPTSTR strFullCounterPath = NULL;
  467. DWORD dwFullCounterPathSize = 0;
  468. DWORD dwMachines = 0;
  469. HCOUNTER pCounter;
  470. pdhStatus = PdhEnumMachinesH( hLog, mszMachines, &dwMachines );
  471. if( ERROR_SUCCESS == pdhStatus ||
  472. PDH_MORE_DATA == pdhStatus ||
  473. PDH_INSUFFICIENT_BUFFER == pdhStatus ){
  474. mszMachines = (LPTSTR)VARG_ALLOC( dwMachines * sizeof(TCHAR) );
  475. if( mszMachines == NULL ){
  476. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  477. goto cleanup;
  478. }
  479. pdhStatus = PdhEnumMachinesH( hLog, mszMachines, &dwMachines );
  480. if( ERROR_SUCCESS == pdhStatus ){
  481. strMachine = mszMachines;
  482. while( NULL != strMachine && strMachine[0] != _T('\0') ){
  483. LPTSTR mszObjects = NULL;
  484. LPTSTR strObject = NULL;
  485. DWORD dwObjects = 0;
  486. pdhStatus = PdhEnumObjectsH(
  487. hLog,
  488. strMachine,
  489. mszObjects,
  490. &dwObjects,
  491. PERF_DETAIL_WIZARD,
  492. FALSE
  493. );
  494. if( ERROR_SUCCESS == pdhStatus ||
  495. PDH_MORE_DATA == pdhStatus ||
  496. PDH_INSUFFICIENT_BUFFER == pdhStatus ){
  497. mszObjects = (LPTSTR)VARG_ALLOC( dwObjects * sizeof(TCHAR));
  498. if( mszObjects == NULL ){
  499. VARG_FREE( mszMachines );
  500. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  501. goto cleanup;
  502. }
  503. pdhStatus = PdhEnumObjectsH(
  504. hLog,
  505. strMachine,
  506. mszObjects,
  507. &dwObjects,
  508. PERF_DETAIL_WIZARD,
  509. FALSE
  510. );
  511. strObject = mszObjects;
  512. while( NULL != strObject && strObject[0] != _T('\0') ){
  513. LPTSTR mszCounters = NULL;
  514. LPTSTR strCounter = NULL;
  515. LPTSTR mszInstances = NULL;
  516. LPTSTR strInstance = NULL;
  517. DWORD dwCounters = 0;
  518. DWORD dwInstances = 0;
  519. pdhStatus = PdhEnumObjectItemsH(
  520. hLog,
  521. strMachine,
  522. strObject,
  523. mszCounters,
  524. &dwCounters,
  525. mszInstances,
  526. &dwInstances,
  527. PERF_DETAIL_WIZARD,
  528. 0
  529. );
  530. if( ERROR_SUCCESS == pdhStatus ||
  531. PDH_MORE_DATA == pdhStatus ||
  532. PDH_INSUFFICIENT_BUFFER == pdhStatus ){
  533. if( dwCounters > 0 ){
  534. mszCounters = (LPTSTR)VARG_ALLOC( dwCounters * sizeof(TCHAR) );
  535. }
  536. if( dwInstances > 0 ){
  537. mszInstances = (LPTSTR)VARG_ALLOC( dwInstances * sizeof(TCHAR) );
  538. }
  539. if( (mszCounters == NULL && dwCounters > 0 ) ||
  540. (mszInstances == NULL && dwInstances > 0) ){
  541. VARG_FREE( mszMachines );
  542. VARG_FREE( mszObjects );
  543. VARG_FREE( mszCounters );
  544. VARG_FREE( mszInstances );
  545. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  546. goto cleanup;
  547. }
  548. pdhStatus = PdhEnumObjectItemsH(
  549. hLog,
  550. strMachine,
  551. strObject,
  552. mszCounters,
  553. &dwCounters,
  554. mszInstances,
  555. &dwInstances,
  556. PERF_DETAIL_WIZARD,
  557. 0
  558. );
  559. if( ERROR_SUCCESS == pdhStatus ){
  560. strCounter = mszCounters;
  561. while( NULL != strCounter && strCounter[0] != _T('\0') ){
  562. PDH_COUNTER_PATH_ELEMENTS_W pdhElements;
  563. ZeroMemory( &pdhElements, sizeof( PDH_COUNTER_PATH_ELEMENTS ) );
  564. pdhElements.szMachineName = strMachine;
  565. pdhElements.szObjectName = strObject;
  566. pdhElements.szCounterName = strCounter;
  567. strInstance = mszInstances;
  568. if( NULL != strInstance && strInstance[0] != _T('\0') ){
  569. LPTSTR strLastInstance = NULL;
  570. ULONG nInstance = 0;
  571. while( strInstance[0] != _T('\0') ){
  572. DWORD dwSize = dwFullCounterPathSize;
  573. pdhElements.szInstanceName = strInstance;
  574. if( ! IsSameInstance( strLastInstance, strInstance ) ){
  575. pdhElements.dwInstanceIndex = -1;
  576. nInstance = 0;
  577. }else{
  578. pdhElements.dwInstanceIndex = ++nInstance;
  579. }
  580. pdhStatus = PdhMakeCounterPath( &pdhElements, strFullCounterPath, &dwSize, 0 );
  581. if( PDH_INSUFFICIENT_BUFFER == pdhStatus || PDH_MORE_DATA == pdhStatus ){
  582. VARG_FREE( strFullCounterPath );
  583. strFullCounterPath = (LPTSTR)VARG_ALLOC( dwSize * sizeof(TCHAR) );
  584. if( NULL != strFullCounterPath ){
  585. dwFullCounterPathSize = dwSize;
  586. pdhStatus = PdhMakeCounterPath( &pdhElements, strFullCounterPath, &dwSize, 0 );
  587. }
  588. }
  589. strLastInstance = strInstance;
  590. strInstance += _tcslen( strInstance ) + 1;
  591. if( Commands[eQuery].bValue ){
  592. if( NULL != f ){
  593. _ftprintf( f, _T("%s\n"), strFullCounterPath );
  594. }else{
  595. varg_printf( g_normal, _T("%1!s!\n"), strFullCounterPath );
  596. }
  597. }
  598. if( Commands[eCounters].bDefined == FALSE && Commands[eOutput].bDefined ){
  599. pdhStatus = PdhAddCounter(
  600. hQuery,
  601. strFullCounterPath,
  602. 0,
  603. &pCounter
  604. );
  605. }
  606. }
  607. }else{
  608. DWORD dwSize = dwFullCounterPathSize;
  609. pdhStatus = PdhMakeCounterPath( &pdhElements, strFullCounterPath, &dwSize, 0 );
  610. if( PDH_INSUFFICIENT_BUFFER == pdhStatus || PDH_MORE_DATA == pdhStatus ){
  611. VARG_FREE( strFullCounterPath );
  612. strFullCounterPath = (LPTSTR)VARG_ALLOC( dwSize * sizeof(TCHAR) );
  613. if( NULL != strFullCounterPath ){
  614. dwFullCounterPathSize = dwSize;
  615. pdhStatus = PdhMakeCounterPath( &pdhElements, strFullCounterPath, &dwSize, 0 );
  616. }
  617. }
  618. if( Commands[eQuery].bValue ){
  619. if( NULL != f ){
  620. _ftprintf( f, _T("%s\n"), strFullCounterPath );
  621. }else{
  622. varg_printf( g_normal, _T("%1!s!\n"), strFullCounterPath );
  623. }
  624. }
  625. if( Commands[eCounters].bDefined == FALSE && Commands[eOutput].bDefined ){
  626. pdhStatus = PdhAddCounter(
  627. hQuery,
  628. strFullCounterPath,
  629. 0,
  630. &pCounter
  631. );
  632. }
  633. }
  634. strCounter += _tcslen( strCounter ) + 1;
  635. }
  636. }
  637. VARG_FREE( mszCounters );
  638. VARG_FREE( mszInstances );
  639. }
  640. strObject += _tcslen( strObject ) + 1;
  641. }
  642. VARG_FREE( mszObjects );
  643. }
  644. strMachine += _tcslen( strMachine ) + 1;
  645. }
  646. }
  647. VARG_FREE( mszMachines );
  648. }
  649. cleanup:
  650. VARG_FREE( strFullCounterPath );
  651. if( NULL == f ){
  652. if( ERROR_SUCCESS == pdhStatus && Commands[eQuery].bValue){
  653. varg_printf( g_normal, _T("\n") );
  654. }
  655. }
  656. return pdhStatus;
  657. }