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.

3297 lines
101 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. report.c
  5. Abstract:
  6. Manipulation routines for cpdata structures.
  7. Author:
  8. Melur Raghuraman (mraghu) 03-Oct-1997
  9. Environment:
  10. Revision History:
  11. --*/
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include "cpdata.h"
  15. #include "tracectr.h"
  16. #include <ntverp.h>
  17. #include "item.h"
  18. #define BREAK_LINE "+-----------------------------------------------------------------------------------------------------------------------------------+\n"
  19. extern PTRACE_CONTEXT_BLOCK TraceContext;
  20. extern ULONG TotalEventsLost;
  21. extern ULONG TotalEventCount;
  22. extern ULONG TimerResolution;
  23. extern ULONGLONG StartTime;
  24. extern ULONGLONG EndTime;
  25. extern __int64 ElapseTime;
  26. extern ULONG TotalBuffersRead;
  27. static FILE* procFile;
  28. static void PrintDiskTotals();
  29. static void PrintProcessCpuTime();
  30. static void PrintProcessData();
  31. static void PrintPerThreadPerDiskTable();
  32. static void WriteTransactionStatistics();
  33. static void WriteTransactionCPUTime();
  34. static void PrintProcessSubDataInclusive();
  35. static void PrintProcessSubDataExclusive();
  36. void TransInclusive(
  37. PLIST_ENTRY TrHead,
  38. ULONG level
  39. );
  40. static void ReportPageFaultInfo(PCPD_USER_CONTEXT_MM pUserContext);
  41. static void ReportHardFaultInfo(void);
  42. static void ReportHotFileInfo(ULONG NumEntry);
  43. static void ReportJobInfo(void);
  44. extern GUID PrintJobGuid;
  45. PWCHAR CpdiGuidToString(
  46. PWCHAR s,
  47. LPGUID piid
  48. );
  49. char* Month[] = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  50. char* Day[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
  51. ULONG ReportFlags = 0;
  52. void CollapseTree(
  53. PLIST_ENTRY OldTree,
  54. PLIST_ENTRY NewTree,
  55. BOOL flat
  56. )
  57. {
  58. PLIST_ENTRY OldNext;
  59. PTRANS_RECORD pTrans;
  60. PTRANS_RECORD pNewTrans;
  61. OldNext = OldTree->Flink;
  62. while (OldNext != OldTree)
  63. {
  64. pTrans = CONTAINING_RECORD(OldNext, TRANS_RECORD, Entry);
  65. OldNext = OldNext->Flink;
  66. pNewTrans = FindTransByList(NewTree, pTrans->pGuid, 0);
  67. if( NULL != pNewTrans ){
  68. pNewTrans->KCpu += pTrans->KCpu;
  69. pNewTrans->UCpu += pTrans->UCpu;
  70. pNewTrans->RefCount += pTrans->RefCount;
  71. pNewTrans->RefCount1 += pTrans->RefCount1;
  72. if (flat)
  73. {
  74. CollapseTree(&pTrans->SubTransListHead, NewTree, TRUE );
  75. }
  76. else
  77. {
  78. CollapseTree(& pTrans->SubTransListHead,
  79. & pNewTrans->SubTransListHead,
  80. FALSE);
  81. }
  82. }else{
  83. // fprintf(stderr, "(PDH.DLL) Memory Commit Failure.\n");
  84. }
  85. }
  86. }
  87. #define BARLEN 70
  88. char*
  89. TimeWindowBar(
  90. char* buffer,
  91. ULONGLONG min,
  92. ULONGLONG max
  93. )
  94. {
  95. double unit;
  96. ULONGLONG duration;
  97. int pre, bar, count;
  98. if(buffer == NULL){
  99. return NULL;
  100. }
  101. duration = ((CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000);
  102. unit = (double)BARLEN/(ULONG)duration;
  103. pre = (int)((ULONG)((min - CurrentSystem.StartTime)/10000000) * unit);
  104. bar = (int)((ULONG)((max - min)/10000000) * unit);
  105. strcpy( buffer, "" );
  106. count = 0;
  107. while(count++ < pre){ strcat(buffer, " "); }
  108. strcat( buffer, "|" );
  109. count = 0;
  110. while(count++ < bar){ strcat(buffer, "_"); }
  111. strcat(buffer, "|" );
  112. return buffer;
  113. }
  114. void
  115. WriteProc(
  116. LPWSTR ProcFileName,
  117. ULONG flags,
  118. PVOID pUserContext
  119. )
  120. {
  121. ULONGLONG duration;
  122. FILETIME StTm, EndTm, StlTm, EndlTm;
  123. LARGE_INTEGER LargeTmp;
  124. SYSTEMTIME tmf;
  125. PLIST_ENTRY Next, Head;
  126. PPROCESS_FILE_RECORD pFileRec;
  127. char buffer[MAXSTR];
  128. BOOL bResult;
  129. ReportFlags = flags;
  130. procFile = _wfopen(ProcFileName, L"w");
  131. if (procFile == NULL)
  132. return;
  133. LargeTmp.QuadPart = CurrentSystem.StartTime;
  134. StTm.dwHighDateTime = LargeTmp.HighPart;
  135. StTm.dwLowDateTime = LargeTmp.LowPart;
  136. FileTimeToLocalFileTime(&StTm, &StlTm);
  137. bResult = FileTimeToSystemTime (
  138. &StlTm,
  139. &tmf
  140. );
  141. if( ! bResult || tmf.wMonth > 12 ){
  142. ZeroMemory( &tmf, sizeof(SYSTEMTIME) );
  143. }
  144. fprintf(procFile,
  145. BREAK_LINE
  146. "| Windows Event Trace Session Report %83s\n"
  147. "| Version : %4d %82s\n"
  148. "| Type : %-20s %68s\n"
  149. BREAK_LINE
  150. "| %75s\n"
  151. "| Build : %-8d %79s\n"
  152. "| Processors: %-8d %79s\n"
  153. "| Start Time: %2d %3s %4d %2d:%02d:%02d.%03d %-80s |\n",
  154. "|",
  155. VER_PRODUCTBUILD, "|",
  156. ( ReportFlags & TRACE_LOG_REPORT_TOTALS ) ? "Total" : "Default", "|",
  157. "|",
  158. CurrentSystem.BuildNumber, "|",
  159. CurrentSystem.NumberOfProcessors, "|",
  160. tmf.wDay,
  161. Month[tmf.wMonth],
  162. tmf.wYear,
  163. tmf.wHour, tmf.wMinute, tmf.wSecond, tmf.wMilliseconds,
  164. "|______________________________________________________________________|"
  165. );
  166. LargeTmp.QuadPart = CurrentSystem.EndTime;
  167. EndTm.dwHighDateTime = LargeTmp.HighPart;
  168. EndTm.dwLowDateTime = LargeTmp.LowPart;
  169. FileTimeToLocalFileTime(&EndTm, &EndlTm);
  170. FileTimeToSystemTime (
  171. &EndlTm,
  172. &tmf
  173. );
  174. fprintf(procFile,
  175. "| End Time : %2d %3s %4d %2d:%02d:%02d.%03d %87s\n",
  176. tmf.wDay,
  177. Month[tmf.wMonth],
  178. tmf.wYear,
  179. tmf.wHour, tmf.wMinute, tmf.wSecond, tmf.wMilliseconds, "|");
  180. duration = (CurrentSystem.EndTime - CurrentSystem.StartTime) / 10000000;
  181. fprintf(procFile,
  182. "| Duration : %-15I64u sec %70s\n"
  183. "| %77s\n",
  184. duration,
  185. "|", "|"
  186. );
  187. Head = &CurrentSystem.ProcessFileListHead;
  188. Next = Head->Flink;
  189. while (Next != Head) {
  190. pFileRec = CONTAINING_RECORD( Next, PROCESS_FILE_RECORD, Entry );
  191. Next = Next->Flink;
  192. fprintf(procFile,
  193. "| Trace Name: %-43ws %60s\n"
  194. "| File Name : %-101ws %2s\n",
  195. pFileRec->TraceName ? pFileRec->TraceName : L"-", "|",
  196. pFileRec->FileName ? pFileRec->FileName : L"-", "|"
  197. );
  198. if (pFileRec->StartTime == 0)
  199. pFileRec->StartTime = CurrentSystem.StartTime;
  200. if (pFileRec->EndTime == 0)
  201. pFileRec->EndTime = CurrentSystem.EndTime;
  202. LargeTmp.QuadPart = pFileRec->StartTime;
  203. EndTm.dwHighDateTime = LargeTmp.HighPart;
  204. EndTm.dwLowDateTime = LargeTmp.LowPart;
  205. FileTimeToLocalFileTime(&EndTm, &EndlTm);
  206. FileTimeToSystemTime (
  207. &EndlTm,
  208. &tmf
  209. );
  210. fprintf(procFile,
  211. "| Start Time: %2d %3s %4d %2d:%02d:%02d.%03d %-80s |\n",
  212. tmf.wDay,
  213. Month[tmf.wMonth],
  214. tmf.wYear,
  215. tmf.wHour, tmf.wMinute, tmf.wSecond, tmf.wMilliseconds,
  216. TimeWindowBar(buffer, pFileRec->StartTime, pFileRec->EndTime)
  217. );
  218. LargeTmp.QuadPart = pFileRec->EndTime;
  219. EndTm.dwHighDateTime = LargeTmp.HighPart;
  220. EndTm.dwLowDateTime = LargeTmp.LowPart;
  221. FileTimeToLocalFileTime(&EndTm, &EndlTm);
  222. FileTimeToSystemTime (
  223. &EndlTm,
  224. &tmf
  225. );
  226. duration = (pFileRec->EndTime - pFileRec->StartTime) / 10000000;
  227. fprintf(procFile,
  228. "| End Time : %2d %3s %4d %2d:%02d:%02d.%03d %81s\n"
  229. "| Duration : %-15I64u sec %68s\n"
  230. "| %75s\n",
  231. tmf.wDay,
  232. Month[tmf.wMonth],
  233. tmf.wYear,
  234. tmf.wHour, tmf.wMinute, tmf.wSecond, tmf.wMilliseconds, "|",
  235. duration,
  236. "|","|"
  237. );
  238. }
  239. fprintf(procFile, BREAK_LINE "\n\n" );
  240. if (flags & (TRACE_LOG_REPORT_BASIC|TRACE_LOG_REPORT_TOTALS)){
  241. PMOF_INFO pMofInfo;
  242. WriteTransactionStatistics();
  243. WriteTransactionCPUTime();
  244. pMofInfo = GetMofInfoHead ((LPCGUID)&PrintJobGuid);
  245. if( pMofInfo != NULL ){
  246. if (pMofInfo->EventCount > 0) {
  247. ReportJobInfo();
  248. }
  249. }
  250. // PrintProcessData() must be run before others to set the process
  251. // time from the added thread times
  252. PrintProcessData();
  253. PrintProcessSubDataExclusive();
  254. PrintProcessSubDataInclusive();
  255. // PrintProcessCpuTime();
  256. PrintDiskTotals();
  257. PrintPerThreadPerDiskTable();
  258. }
  259. if (flags & TRACE_LOG_REPORT_MEMORY) {
  260. ReportPageFaultInfo((PCPD_USER_CONTEXT_MM) pUserContext);
  261. }
  262. if (flags & TRACE_LOG_REPORT_HARDFAULT ){
  263. // ReportHardFaultInfo();
  264. }
  265. if (flags & TRACE_LOG_REPORT_FILE)
  266. {
  267. // ReportHotFileInfo(PtrToUlong(pUserContext));
  268. }
  269. fclose(procFile);
  270. }
  271. static void
  272. PrintDiskTotals()
  273. {
  274. // Print the Disk Table.
  275. PTDISK_RECORD pDisk;
  276. PLIST_ENTRY Next, Head;
  277. ULONG rio, wio;
  278. Head = &CurrentSystem.GlobalDiskListHead;
  279. Next = Head->Flink;
  280. if( Next == Head ){
  281. return;
  282. }
  283. fprintf(procFile,
  284. BREAK_LINE
  285. "| Disk Totals %115s\n"
  286. BREAK_LINE
  287. "| Disk Name Reads Kb Writes Kb %62s\n"
  288. BREAK_LINE, "|", "|" );
  289. Head = &CurrentSystem.GlobalDiskListHead;
  290. Next = Head->Flink;
  291. while (Next != Head) {
  292. pDisk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
  293. rio = pDisk->ReadCount + pDisk->HPF;
  294. wio = pDisk->WriteCount;
  295. fprintf(procFile,
  296. "| %6d %6d %6d %6d %6d %61s\n",
  297. pDisk->DiskNumber,
  298. rio,
  299. (rio == 0) ? 0 : (pDisk->ReadSize + pDisk->HPFSize) / rio,
  300. wio,
  301. (wio == 0) ? 0 : pDisk->WriteSize / wio,
  302. "|"
  303. );
  304. Next = Next->Flink;
  305. }
  306. fprintf(procFile, BREAK_LINE "\n\n" );
  307. }
  308. void TotalTransChildren(
  309. PLIST_ENTRY Head,
  310. ULONG *Kernel,
  311. ULONG *User,
  312. LONG level )
  313. {
  314. PTRANS_RECORD pTrans;
  315. PLIST_ENTRY Next;
  316. Next = Head->Flink;
  317. while( Next != Head ){
  318. pTrans = CONTAINING_RECORD( Next, TRANS_RECORD, Entry );
  319. Next = Next->Flink;
  320. TotalTransChildren( &pTrans->SubTransListHead, Kernel, User, level+1 );
  321. *Kernel += pTrans->KCpu;
  322. *User += pTrans->UCpu;
  323. }
  324. }
  325. void PrintTransList( PLIST_ENTRY TrHead, LONG level )
  326. {
  327. PTRANS_RECORD pTrans;
  328. PMOF_INFO pMofInfo;
  329. ULONG Kernel;
  330. ULONG User;
  331. WCHAR str[1024];
  332. WCHAR buffer[MAXSTR];
  333. PLIST_ENTRY TrNext = TrHead->Flink;
  334. while( TrNext != TrHead ){
  335. int count = 0;
  336. pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
  337. TrNext = TrNext->Flink;
  338. Kernel = pTrans->KCpu;
  339. User = pTrans->UCpu;
  340. pMofInfo = GetMofInfoHead( pTrans->pGuid);
  341. if (pMofInfo == NULL) {
  342. return;
  343. }
  344. wcscpy(buffer,L"");
  345. while( (count++ < level) && (lstrlenW(buffer) < MAXSTR)){
  346. wcscat(buffer, L" ");
  347. }
  348. wcscat( buffer,
  349. ( pMofInfo->strDescription ?
  350. pMofInfo->strDescription :
  351. CpdiGuidToString( str, &pMofInfo->Guid ) ));
  352. TotalTransChildren( &pTrans->SubTransListHead, &Kernel, &User, 0 );
  353. fprintf( procFile,
  354. "| %-17S %6d %7d %7d %5s %5s %5s %5s %5s %5s %5s %5s %6s %6s\n",
  355. buffer,
  356. pTrans->RefCount,
  357. Kernel,
  358. User,
  359. "-",
  360. "-",
  361. "-",
  362. "-",
  363. "-",
  364. "-",
  365. "-",
  366. "-",
  367. "-", "|"
  368. );
  369. if( level <= MAX_TRANS_LEVEL ){
  370. PrintTransList( &pTrans->SubTransListHead, level+1 );
  371. }
  372. }
  373. }
  374. static void PrintProcessCpuTime()
  375. {
  376. PTHREAD_RECORD pThread;
  377. PPROCESS_RECORD pProcess;
  378. ULONGLONG lLifeTime;
  379. ULONG TotalUserTime = 0;
  380. ULONG TotalKernelTime = 0;
  381. ULONG TotalCPUTime = 0;
  382. PLIST_ENTRY Next, Head;
  383. PLIST_ENTRY ThNext, ThHead;
  384. BOOL titled;
  385. ULONG usedThreadCount;
  386. ULONG ThreadCount;
  387. ULONG ProcessUTime;
  388. ULONG ProcessKTime;
  389. ULONG ThreadKCPU;
  390. ULONG ThreadUCPU;
  391. Head = &CurrentSystem.ProcessListHead;
  392. Next = Head->Flink;
  393. if( Head == Next ){
  394. return;
  395. }
  396. // Walk through the Process List and Print the report.
  397. fprintf(procFile,
  398. BREAK_LINE
  399. "| Process/Thread CPU Time Statistics %93s\n"
  400. BREAK_LINE
  401. "| Image Name ID Trans Inclusive CPU(ms) Disk Total Tcp Total Duration |\n"
  402. "| Kernel User Reads Kb/Op Writes Kb/Op Send Kb/Op Recv Kb/Op |\n"
  403. BREAK_LINE, "|"
  404. );
  405. Head = &CurrentSystem.ProcessListHead;
  406. Next = Head->Flink;
  407. while (Next != Head) {
  408. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  409. lLifeTime = CalculateProcessLifeTime(pProcess);
  410. fprintf(procFile,
  411. "| %-15ws 0x%04X %6s %7d %7d %5d %5.2f %5d %5.2f %5d %8.2f %5d %8.2f %6I64u %6s\n",
  412. (pProcess->ImageName) ? pProcess->ImageName : L"Idle",
  413. pProcess->PID,
  414. "-",
  415. CalculateProcessKCPU(pProcess),
  416. CalculateProcessUCPU(pProcess),
  417. pProcess->ReadIO + pProcess->HPF,
  418. (pProcess->ReadIO + pProcess->HPF) ?
  419. (double)(pProcess->ReadIOSize + pProcess->HPFSize)/
  420. (double)(pProcess->ReadIO + pProcess->HPF) : 0,
  421. pProcess->WriteIO,
  422. pProcess->WriteIO ? (double)pProcess->WriteIOSize/(double)pProcess->WriteIO : 0,
  423. pProcess->SendCount,
  424. pProcess->SendCount ?
  425. (double)(pProcess->SendSize / 1024)/(double)pProcess->SendCount : 0,
  426. pProcess->RecvCount,
  427. pProcess->RecvCount ?
  428. (double)(pProcess->RecvSize / 1024) / (double)pProcess->RecvCount : 0,
  429. (lLifeTime / 10000000 ), "|"
  430. );
  431. ThHead = &pProcess->ThreadListHead;
  432. ThNext = ThHead->Flink;
  433. titled = FALSE;
  434. usedThreadCount = 0;
  435. ThreadCount = 0;
  436. ProcessUTime = 0;
  437. ProcessKTime = 0;
  438. while (ThNext != ThHead) {
  439. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  440. ThreadKCPU = (pThread->KCPUEnd - pThread->KCPUStart)
  441. * CurrentSystem.TimerResolution;
  442. ThreadUCPU = (pThread->UCPUEnd - pThread->UCPUStart)
  443. * CurrentSystem.TimerResolution;
  444. if( pThread->ReadIO
  445. || pThread->WriteIO
  446. || ThreadKCPU
  447. || ThreadUCPU
  448. || pThread->SendCount
  449. || pThread->RecvCount
  450. || pThread->HPF ){
  451. fprintf(procFile,
  452. "| 0x%04I64X %13s %5s %7d %7d %5d %5.2f %5d %5.2f %5d %8.2f %5d %8.2f %6I64u %6s\n",
  453. pThread->TID,
  454. " ",
  455. "-",
  456. ThreadKCPU,
  457. ThreadUCPU,
  458. pThread->ReadIO + pThread->HPF,
  459. pThread->ReadIO + pThread->HPF ?
  460. (double)(pThread->ReadIOSize + pThread->HPFSize)/
  461. (double)(pThread->ReadIO + pThread->HPF) : 0,
  462. pThread->WriteIO,
  463. pThread->WriteIO ? (double)pThread->WriteIOSize/
  464. (double)pThread->WriteIO : 0,
  465. pThread->SendCount,
  466. pThread->SendCount ?
  467. (double)(pThread->SendSize / 1024)/(double)pThread->SendCount : 0,
  468. pThread->RecvCount,
  469. pThread->RecvCount ?
  470. (double)(pThread->RecvSize / 1024)/(double)pThread->RecvCount : 0,
  471. ((pThread->TimeEnd - pThread->TimeStart) / 10000000), "|"
  472. );
  473. }
  474. PrintTransList( &pThread->TransListHead, 0 );
  475. TotalUserTime += ThreadUCPU;
  476. TotalKernelTime += ThreadKCPU;
  477. TotalCPUTime += ThreadKCPU + ThreadUCPU;
  478. ThNext = ThNext->Flink;
  479. }
  480. Next = Next->Flink;
  481. }
  482. fprintf(procFile, BREAK_LINE "\n\n" );
  483. }
  484. static void PrintProcessData()
  485. {
  486. PTHREAD_RECORD pThread;
  487. PPROCESS_RECORD pProcess;
  488. PTRANS_RECORD pTrans;
  489. PLIST_ENTRY Next, Head;
  490. PLIST_ENTRY ThNext, ThHead;
  491. PLIST_ENTRY TrNext, TrHead;
  492. ULONG usedThreadCount;
  493. ULONG ThreadCount;
  494. ULONG TotalusedThreadCount = 0;
  495. ULONG TotalThreadCount = 0;
  496. ULONG ThreadUTime;
  497. ULONG ThreadKTime;
  498. ULONG ThreadUTimeTrans;
  499. ULONG ThreadKTimeTrans;
  500. ULONG ThreadUTimeNoTrans;
  501. ULONG ThreadKTimeNoTrans;
  502. ULONG CountThreadNoTrans;
  503. ULONG TotalKCPUThreadNoTrans;
  504. ULONG TotalUCPUThreadNoTrans;
  505. double PercentThreadNoTrans;
  506. ULONG CountThreadTrans;
  507. ULONG TotalKCPUThreadTrans;
  508. ULONG TotalUCPUThreadTrans;
  509. double PercentThreadTrans;
  510. ULONG TransUTime;
  511. ULONG TransKTime;
  512. ULONG Processors;
  513. ULONG TotalKThread = 0;
  514. ULONG TotalUThread = 0;
  515. ULONG TotalKTrans = 0;
  516. ULONG TotalUTrans = 0;
  517. double PerTotal = 0.0;
  518. double IdlePercent = 0.0;
  519. double percent;
  520. double percentTrans;
  521. double lDuration;
  522. Head = &CurrentSystem.ProcessListHead;
  523. Next = Head->Flink;
  524. if( Head == Next ){
  525. return;
  526. }
  527. Processors = CurrentSystem.NumberOfProcessors ? CurrentSystem.NumberOfProcessors : 1;
  528. lDuration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime)))
  529. / 10000000.00;
  530. // Walk through the Process List and Print the report.
  531. fprintf(procFile,
  532. BREAK_LINE
  533. "| Image Statistics %111s\n"
  534. BREAK_LINE
  535. "| Image Name PID Threads Threads Process Transaction CPU%% %22s\n"
  536. "| Launched Used KCPU(ms) UCPU(ms) KCPU(ms) UCPU(ms) %28s\n"
  537. BREAK_LINE,
  538. "|",
  539. "|",
  540. "|"
  541. );
  542. Head = &CurrentSystem.ProcessListHead;
  543. Next = Head->Flink;
  544. while (Next != Head) {
  545. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  546. ThHead = &pProcess->ThreadListHead;
  547. ThNext = ThHead->Flink;
  548. usedThreadCount = 0;
  549. ThreadCount = 0;
  550. ThreadUTime = 0;
  551. ThreadKTime = 0;
  552. ThreadUTimeTrans = 0;
  553. ThreadKTimeTrans = 0;
  554. ThreadUTimeNoTrans = 0;
  555. ThreadKTimeNoTrans = 0;
  556. TransKTime = 0;
  557. TransUTime = 0;
  558. percent = 0;
  559. CountThreadNoTrans = 0;
  560. TotalKCPUThreadNoTrans = 0;
  561. TotalUCPUThreadNoTrans = 0;
  562. CountThreadTrans = 0;
  563. TotalKCPUThreadTrans = 0;
  564. TotalUCPUThreadTrans = 0;
  565. while (ThNext != ThHead) {
  566. LIST_ENTRY NewTransList;
  567. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  568. if( pThread->ReadIO
  569. || pThread->WriteIO
  570. || pThread->KCPUEnd > pThread->KCPUStart
  571. || pThread->UCPUEnd > pThread->UCPUStart
  572. || pThread->SendCount
  573. || pThread->RecvCount
  574. || pThread->HPF )
  575. {
  576. usedThreadCount++;
  577. TotalusedThreadCount++;
  578. }
  579. ThreadCount++;
  580. TotalThreadCount++;
  581. ThreadUTime += (pThread->UCPUEnd - pThread->UCPUStart)
  582. * CurrentSystem.TimerResolution;
  583. ThreadKTime += (pThread->KCPUEnd - pThread->KCPUStart)
  584. * CurrentSystem.TimerResolution;
  585. ThreadKTimeTrans += pThread->KCPU_Trans
  586. * CurrentSystem.TimerResolution;
  587. ThreadUTimeTrans += pThread->UCPU_Trans
  588. * CurrentSystem.TimerResolution;
  589. ThreadKTimeNoTrans += pThread->KCPU_NoTrans
  590. * CurrentSystem.TimerResolution;
  591. ThreadUTimeNoTrans += pThread->UCPU_NoTrans
  592. * CurrentSystem.TimerResolution;
  593. if (pThread->KCPU_Trans + pThread->UCPU_Trans == 0)
  594. {
  595. CountThreadNoTrans ++;
  596. TotalKCPUThreadNoTrans += pThread->KCPU_NoTrans
  597. * CurrentSystem.TimerResolution;
  598. TotalUCPUThreadNoTrans += pThread->UCPU_NoTrans
  599. * CurrentSystem.TimerResolution;
  600. }
  601. else
  602. {
  603. CountThreadTrans ++;
  604. TotalKCPUThreadTrans += ( pThread->KCPU_Trans
  605. + pThread->KCPU_NoTrans)
  606. * CurrentSystem.TimerResolution;
  607. TotalUCPUThreadTrans += ( pThread->UCPU_Trans
  608. + pThread->UCPU_NoTrans)
  609. * CurrentSystem.TimerResolution;
  610. }
  611. InitializeListHead(& NewTransList);
  612. CollapseTree(& pThread->TransListHead, & NewTransList, TRUE);
  613. TrHead = & NewTransList;
  614. TrNext = TrHead->Flink;
  615. while( TrNext != TrHead ){
  616. pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
  617. TransUTime += pTrans->UCpu;
  618. TransKTime += pTrans->KCpu;
  619. TrNext = TrNext->Flink;
  620. }
  621. DeleteTransList(& NewTransList, 0);
  622. ThNext = ThNext->Flink;
  623. }
  624. TotalKThread += ThreadKTime;
  625. TotalUThread += ThreadUTime;
  626. TotalKTrans += TransKTime;
  627. TotalUTrans += TransUTime;
  628. percent = (((ThreadKTime + ThreadUTime + 0.0)/lDuration)/1000.0) * 100.0;
  629. if (ThreadKTime + ThreadUTime == 0)
  630. {
  631. percentTrans = 0.0;
  632. PercentThreadTrans = 0.0;
  633. PercentThreadNoTrans = 0.0;
  634. }
  635. else
  636. {
  637. percentTrans = ( (ThreadKTimeTrans + ThreadUTimeTrans + 0.0)
  638. / (ThreadKTime + ThreadUTime + 0.0))
  639. * 100.00;
  640. PercentThreadTrans = ((TotalKCPUThreadTrans + TotalUCPUThreadTrans + 0.0)
  641. / (ThreadKTime + ThreadUTime + 0.0)) * 100.00;
  642. PercentThreadNoTrans = ((TotalKCPUThreadNoTrans + TotalUCPUThreadNoTrans + 0.0)
  643. / (ThreadKTime + ThreadUTime + 0.0)) * 100.00;
  644. }
  645. PerTotal += percent;
  646. fprintf(procFile,
  647. "| %-15ws 0x%08X %7d %7d %9d %9d %9d %9d %7.2f %22s\n",
  648. (pProcess->ImageName) ? pProcess->ImageName : L"Idle",
  649. pProcess->PID,
  650. ThreadCount,
  651. usedThreadCount,
  652. ThreadKTime,
  653. ThreadUTime,
  654. ThreadKTimeTrans,
  655. ThreadUTimeTrans,
  656. (percent / Processors),
  657. /*percentTrans,*/
  658. "|"
  659. );
  660. #if 0
  661. fprintf(procFile,
  662. "| %6d(%10d,%10d)%7.2f%% %6d(%10d,%10d)%7.2f%% |\n",
  663. CountThreadTrans,
  664. TotalKCPUThreadTrans,
  665. TotalUCPUThreadTrans,
  666. PercentThreadTrans,
  667. CountThreadNoTrans,
  668. TotalKCPUThreadNoTrans,
  669. TotalUCPUThreadNoTrans,
  670. PercentThreadNoTrans);
  671. #endif
  672. if(pProcess->PID == 0){
  673. IdlePercent += (percent / Processors );
  674. }
  675. Next = Next->Flink;
  676. }
  677. fprintf(procFile,
  678. BREAK_LINE
  679. "| %-15s %8s %7d %7d %9d %9d %9d %9d Total:%7.2f%% |\n",
  680. " ",
  681. " ",
  682. TotalThreadCount,
  683. TotalusedThreadCount,
  684. TotalKThread,
  685. TotalUThread,
  686. TotalKTrans,
  687. TotalUTrans,
  688. (PerTotal/Processors)
  689. );
  690. fprintf(procFile, BREAK_LINE "\n\n" );
  691. }
  692. void TransInclusive(
  693. PLIST_ENTRY TrHead,
  694. ULONG level
  695. )
  696. {
  697. ULONG Kernel, User;
  698. PLIST_ENTRY TrNext = TrHead->Flink;
  699. PMOF_INFO pMofInfo;
  700. PTRANS_RECORD pTrans;
  701. WCHAR buffer[MAXSTR];
  702. WCHAR str[MAXSTR];
  703. while( TrNext != TrHead ){
  704. ULONG count = 0;
  705. pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
  706. TrNext = TrNext->Flink;
  707. pMofInfo = GetMofInfoHead( pTrans->pGuid);
  708. if (pMofInfo == NULL) {
  709. return;
  710. }
  711. Kernel = pTrans->KCpu;
  712. User = pTrans->UCpu;
  713. TotalTransChildren( &pTrans->SubTransListHead, &Kernel, &User, 0 );
  714. wcscpy(buffer,L"");
  715. while( (count++ < level) && (lstrlenW(buffer) < MAXSTR)){
  716. wcscat(buffer, L" ");
  717. }
  718. wcscat( buffer,
  719. ( pMofInfo->strDescription ?
  720. pMofInfo->strDescription :
  721. CpdiGuidToString( str, &pMofInfo->Guid ) ));
  722. fprintf(procFile,
  723. "| %-30ws %5d %8d %8d %57s\n",
  724. buffer,
  725. pTrans->RefCount,
  726. Kernel,
  727. User,
  728. "|"
  729. );
  730. TransInclusive( &pTrans->SubTransListHead, level+1 );
  731. }
  732. }
  733. static void PrintProcessSubDataInclusive()
  734. {
  735. PPROCESS_RECORD pProcess;
  736. PTHREAD_RECORD pThread;
  737. PLIST_ENTRY Next, Head;
  738. PLIST_ENTRY TrNext;
  739. PLIST_ENTRY ThNext, ThHead;
  740. LIST_ENTRY NewHead;
  741. BOOL bTable = FALSE;
  742. Head = &CurrentSystem.ProcessListHead;
  743. Next = Head->Flink;
  744. while (Next != Head && !bTable ) {
  745. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  746. Next = Next->Flink;
  747. if( pProcess->PID == 0 ){
  748. continue;
  749. }
  750. // Total up all the threads into one list
  751. InitializeListHead( &NewHead );
  752. ThHead = &pProcess->ThreadListHead;
  753. ThNext = ThHead->Flink;
  754. while( ThNext != ThHead ){
  755. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  756. ThNext = ThNext->Flink;
  757. CollapseTree(&pThread->TransListHead, &NewHead, FALSE );
  758. }
  759. TrNext = NewHead.Flink;
  760. if( TrNext != &NewHead ){
  761. bTable = TRUE;
  762. }
  763. DeleteTransList( &NewHead, 0 );
  764. }
  765. if( !bTable ){
  766. return;
  767. }
  768. // Walk through the Process List and Print the report.
  769. fprintf(procFile,
  770. BREAK_LINE
  771. "| Inclusive Transactions Per Process %96s\n"
  772. BREAK_LINE
  773. "| Inclusive %39s\n"
  774. "| Name PID Count KCPU(ms) UCPU(ms) %51s\n"
  775. BREAK_LINE,
  776. "|",
  777. "|",
  778. "|"
  779. );
  780. Head = &CurrentSystem.ProcessListHead;
  781. Next = Head->Flink;
  782. while (Next != Head) {
  783. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  784. Next = Next->Flink;
  785. if( pProcess->PID == 0 ){
  786. continue;
  787. }
  788. // Total up all the threads into one list
  789. InitializeListHead( &NewHead );
  790. ThHead = &pProcess->ThreadListHead;
  791. ThNext = ThHead->Flink;
  792. while( ThNext != ThHead ){
  793. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  794. ThNext = ThNext->Flink;
  795. CollapseTree(&pThread->TransListHead, &NewHead, FALSE );
  796. }
  797. TrNext = NewHead.Flink;
  798. if( TrNext != &NewHead ){
  799. fprintf(procFile,
  800. "| %-30ws 0x%04X %90s\n",
  801. (pProcess->ImageName) ? pProcess->ImageName : L"Idle",
  802. pProcess->PID,
  803. "|"
  804. );
  805. TransInclusive( &NewHead, 0 );
  806. }
  807. DeleteTransList( &NewHead, 0 );
  808. }
  809. fprintf(procFile, BREAK_LINE "\n\n" );
  810. }
  811. static void PrintProcessSubDataExclusive()
  812. {
  813. PPROCESS_RECORD pProcess;
  814. PTRANS_RECORD pTrans;
  815. PTHREAD_RECORD pThread;
  816. PLIST_ENTRY ThNext, ThHead;
  817. PMOF_INFO pMofInfo;
  818. PLIST_ENTRY Next, Head;
  819. PLIST_ENTRY TrNext;
  820. LIST_ENTRY NewHead;
  821. double percent, percentCPU, totalPerCPU;
  822. double processPart;
  823. double transPart;
  824. double totalPercent;
  825. double trans, KCPU, UCPU;
  826. WCHAR str[1024];
  827. double duration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime))) / 10000000.00;
  828. BOOL bTable = FALSE;
  829. Head = &CurrentSystem.ProcessListHead;
  830. Next = Head->Flink;
  831. while (Next != Head && !bTable ) {
  832. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  833. Next = Next->Flink;
  834. if( pProcess->PID == 0 ){
  835. continue;
  836. }
  837. InitializeListHead( &NewHead );
  838. ThHead = &pProcess->ThreadListHead;
  839. ThNext = ThHead->Flink;
  840. while( ThNext != ThHead ){
  841. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  842. ThNext = ThNext->Flink;
  843. CollapseTree(&pThread->TransListHead, &NewHead, TRUE );
  844. }
  845. TrNext = NewHead.Flink;
  846. if( TrNext != &NewHead ){
  847. bTable = TRUE;
  848. }
  849. DeleteTransList( &NewHead, 0 );
  850. }
  851. if( !bTable ){
  852. return;
  853. }
  854. // Walk through the Process List and Print the report.
  855. if( ReportFlags & TRACE_LOG_REPORT_TOTALS ){
  856. fprintf(procFile,
  857. BREAK_LINE
  858. "| Exclusive Transactions Per Process %96s\n"
  859. BREAK_LINE
  860. "| Exclusive %54s\n"
  861. "| Name PID Trans Trans/sec KCPU(ms) UCPU(ms) Process CPU%% CPU%% %20s\n"
  862. BREAK_LINE,
  863. "|",
  864. "|",
  865. "|"
  866. );
  867. }else{
  868. fprintf(procFile,
  869. BREAK_LINE
  870. "| Exclusive Transactions Per Process %96s\n"
  871. BREAK_LINE
  872. "| Exclusive/Trans %54s\n"
  873. "| Name PID Trans Trans/sec KCPU(ms) UCPU(ms) Process CPU%% CPU%% %20s\n"
  874. BREAK_LINE,
  875. "|",
  876. "|",
  877. "|"
  878. );
  879. }
  880. Head = &CurrentSystem.ProcessListHead;
  881. Next = Head->Flink;
  882. while (Next != Head) {
  883. BOOL titled = FALSE;
  884. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  885. Next = Next->Flink;
  886. if( pProcess->PID == 0 ){
  887. continue;
  888. }
  889. InitializeListHead( &NewHead );
  890. ThHead = &pProcess->ThreadListHead;
  891. ThNext = ThHead->Flink;
  892. while( ThNext != ThHead ){
  893. pThread = CONTAINING_RECORD( ThNext, THREAD_RECORD, Entry );
  894. ThNext = ThNext->Flink;
  895. CollapseTree(&pThread->TransListHead, &NewHead, TRUE );
  896. }
  897. TrNext = NewHead.Flink;
  898. totalPercent = 0.0;
  899. totalPerCPU = 0.0;
  900. while( TrNext != &NewHead ){
  901. if(!titled){
  902. fprintf(procFile,
  903. "| %-15ws 0x%04X %105s\n",
  904. (pProcess->ImageName) ? pProcess->ImageName : L"Idle",
  905. pProcess->PID,
  906. "|"
  907. );
  908. titled = TRUE;
  909. }
  910. pTrans = CONTAINING_RECORD( TrNext, TRANS_RECORD, Entry );
  911. TrNext = TrNext->Flink;
  912. pMofInfo = GetMofInfoHead( pTrans->pGuid);
  913. if (pMofInfo == NULL) {
  914. return;
  915. }
  916. transPart = pTrans->UCpu + pTrans->KCpu;
  917. processPart = CalculateProcessKCPU(pProcess)
  918. + CalculateProcessUCPU(pProcess);
  919. percentCPU = ((((double)pTrans->KCpu + (double)pTrans->UCpu ) / 10.0 ) / duration) / ((double) CurrentSystem.NumberOfProcessors);
  920. totalPerCPU += percentCPU;
  921. if(processPart)
  922. percent = (transPart/processPart) * 100.0;
  923. else
  924. percent = 0;
  925. totalPercent += percent;
  926. if (!(ReportFlags & TRACE_LOG_REPORT_TOTALS) ){
  927. if (pTrans->RefCount == 0 && pTrans->RefCount1 == 0)
  928. KCPU = UCPU = 0.0;
  929. else if (pTrans->RefCount == 0) {
  930. KCPU = (double) pTrans->KCpu;
  931. UCPU = (double) pTrans->UCpu;
  932. }
  933. else {
  934. KCPU = (double) pTrans->KCpu / (double) pTrans->RefCount;
  935. UCPU = (double) pTrans->UCpu / (double) pTrans->RefCount;
  936. }
  937. }
  938. else{
  939. KCPU = (double)pTrans->KCpu;
  940. UCPU = (double)pTrans->UCpu;
  941. }
  942. trans = (double)pTrans->RefCount / duration;
  943. fprintf(procFile,
  944. "| %-30ws %5d %7.2f %8.0f %8.0f %7.2f %7.2f %19s\n",
  945. (pMofInfo->strDescription != NULL) ? pMofInfo->strDescription : CpdiGuidToString( str, &pMofInfo->Guid ),
  946. pTrans->RefCount,
  947. trans,
  948. KCPU,
  949. UCPU,
  950. percent,
  951. percentCPU,
  952. "|"
  953. );
  954. }
  955. if( titled ){
  956. fprintf( procFile,
  957. "| %84s ------- ------ %20s\n"
  958. "| %84s %7.2f%% %7.2f%% %19s\n",
  959. " ", "|",
  960. " ",
  961. totalPercent,
  962. totalPerCPU,
  963. "|"
  964. );
  965. }
  966. DeleteTransList( &NewHead, 0 );
  967. }
  968. fprintf(procFile, BREAK_LINE "\n\n" );
  969. }
  970. static void PrintPerThreadPerDiskTable( )
  971. {
  972. PPROCESS_RECORD pProcess;
  973. PTDISK_RECORD pDisk;
  974. PLIST_ENTRY Next, Head;
  975. PLIST_ENTRY GNext, GHead;
  976. PLIST_ENTRY DiNext, DiHead;
  977. ULONG rio, wio, DiskNumber;
  978. BOOL bTable = FALSE;
  979. // Walk through the Process List and Print the report.
  980. GHead = &CurrentSystem.GlobalDiskListHead;
  981. GNext = GHead->Flink;
  982. while (GNext != GHead && !bTable) {
  983. pDisk = CONTAINING_RECORD( GNext, TDISK_RECORD, Entry);
  984. DiskNumber = pDisk->DiskNumber;
  985. Head = &CurrentSystem.ProcessListHead;
  986. Next = Head->Flink;
  987. while (Next != Head) {
  988. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  989. DiHead = &pProcess->DiskListHead;
  990. DiNext = DiHead->Flink;
  991. while (DiNext != DiHead && !bTable) {
  992. pDisk = CONTAINING_RECORD( DiNext, TDISK_RECORD, Entry );
  993. if (DiskNumber != pDisk->DiskNumber) {
  994. DiNext = DiNext->Flink;
  995. continue;
  996. }else{
  997. bTable = TRUE;
  998. break;
  999. }
  1000. }
  1001. Next = Next->Flink;
  1002. }
  1003. GNext = GNext->Flink;
  1004. }
  1005. if( !bTable ){
  1006. return;
  1007. }
  1008. GHead = &CurrentSystem.GlobalDiskListHead;
  1009. GNext = GHead->Flink;
  1010. while (GNext != GHead) {
  1011. pDisk = CONTAINING_RECORD( GNext, TDISK_RECORD, Entry);
  1012. DiskNumber = pDisk->DiskNumber;
  1013. fprintf(procFile,
  1014. BREAK_LINE
  1015. "| Disk %3d %116s\n"
  1016. BREAK_LINE
  1017. "| Authority PID Image Name Read Kb Write Kb %50s\n"
  1018. "| Count Count %50s\n"
  1019. BREAK_LINE,
  1020. DiskNumber, "|", "|", "|"
  1021. );
  1022. Head = &CurrentSystem.ProcessListHead;
  1023. Next = Head->Flink;
  1024. while (Next != Head) {
  1025. pProcess = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  1026. DiHead = &pProcess->DiskListHead;
  1027. DiNext = DiHead->Flink;
  1028. while (DiNext != DiHead) {
  1029. pDisk = CONTAINING_RECORD( DiNext, TDISK_RECORD, Entry );
  1030. if (DiskNumber != pDisk->DiskNumber) {
  1031. DiNext = DiNext->Flink;
  1032. continue;
  1033. }
  1034. rio = pDisk->ReadCount + pDisk->HPF;
  1035. wio = pDisk->WriteCount;
  1036. fprintf(procFile,
  1037. "| %-22ws 0x%04X %-16ws",
  1038. (pProcess->UserName) ? pProcess->UserName : L"-",
  1039. pProcess->PID,
  1040. pProcess->ImageName ? pProcess->ImageName : L"-"
  1041. );
  1042. fprintf(procFile,
  1043. "%6d %6d %6d %6d %52s\n",
  1044. rio,
  1045. (rio == 0) ? 0 : (pDisk->ReadSize + pDisk->HPFSize) / rio,
  1046. wio,
  1047. (wio == 0) ? 0 : pDisk->WriteSize / wio, "|");
  1048. DiNext = DiNext->Flink;
  1049. }
  1050. Next = Next->Flink;
  1051. }
  1052. fprintf(procFile, BREAK_LINE "\n\n" );
  1053. GNext = GNext->Flink;
  1054. }
  1055. }
  1056. static void WriteTransactionStatistics()
  1057. {
  1058. PLIST_ENTRY Head, Next;
  1059. PLIST_ENTRY Dhead, DNext;
  1060. ULONG trans;
  1061. double KCPU, UCPU, PerCpu;
  1062. double RIO, WIO, Send, Recv;
  1063. PMOF_INFO pMofInfo;
  1064. PMOF_DATA pMofData;
  1065. double AvgRT;
  1066. double TransRate;
  1067. WCHAR str[1024];
  1068. double duration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime)))
  1069. / 10000000.00;
  1070. BOOL bTable = FALSE;
  1071. Head = &CurrentSystem.EventListHead;
  1072. Next = Head->Flink;
  1073. while (Head != Next && !bTable ) {
  1074. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1075. Dhead = &pMofInfo->DataListHead;
  1076. DNext = Dhead->Flink;
  1077. while(DNext!=Dhead){
  1078. pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
  1079. trans = pMofData->CompleteCount;
  1080. if (trans > 0) {
  1081. bTable = TRUE;
  1082. break;
  1083. }
  1084. DNext = DNext->Flink;
  1085. }
  1086. Next = Next->Flink;
  1087. }
  1088. if( !bTable ){
  1089. return;
  1090. }
  1091. if( ReportFlags & TRACE_LOG_REPORT_TOTALS ){
  1092. fprintf( procFile,
  1093. BREAK_LINE
  1094. "| Transaction Statistics %103s\n"
  1095. BREAK_LINE
  1096. "| Transaction Trans Response Transaction CPU %% Disk Total Tcp Total %20s\n"
  1097. "| Time(ms) Rate/sec Reads Writes Sends Recieves %16s\n"
  1098. BREAK_LINE,
  1099. "|",
  1100. "|",
  1101. "|"
  1102. );
  1103. }else{
  1104. fprintf( procFile,
  1105. BREAK_LINE
  1106. "| Transaction Statistics %103s\n"
  1107. BREAK_LINE
  1108. "| Transaction Trans Response Transaction CPU %% Disk/Trans Tcp/Trans %22s\n"
  1109. "| Time(ms) Rate/sec Reads Writes Sends Recieves %17s\n"
  1110. BREAK_LINE,
  1111. "|",
  1112. "|",
  1113. "|"
  1114. );
  1115. }
  1116. Head = &CurrentSystem.EventListHead;
  1117. Next = Head->Flink;
  1118. while (Head != Next) {
  1119. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1120. Dhead = &pMofInfo->DataListHead;
  1121. DNext = Dhead->Flink;
  1122. while(DNext!=Dhead){
  1123. pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
  1124. trans = pMofData->CompleteCount;
  1125. if (trans > 0) {
  1126. UCPU = pMofData->UserCPU;
  1127. KCPU = pMofData->KernelCPU;
  1128. PerCpu = (((UCPU + KCPU)/1000.0)/duration) * 100.0;
  1129. UCPU /= trans;
  1130. KCPU /= trans;
  1131. if(CurrentSystem.NumberOfProcessors)
  1132. PerCpu/=CurrentSystem.NumberOfProcessors;
  1133. if( ReportFlags & TRACE_LOG_REPORT_TOTALS ){
  1134. RIO = pMofData->ReadCount;
  1135. WIO = pMofData->WriteCount;
  1136. Send = pMofData->SendCount;
  1137. Recv = pMofData->RecvCount;
  1138. }else{
  1139. RIO = pMofData->ReadCount / trans;
  1140. WIO = pMofData->WriteCount / trans;
  1141. Send = pMofData->SendCount / trans;
  1142. Recv = pMofData->RecvCount / trans;
  1143. }
  1144. AvgRT = (double)pMofData->TotalResponseTime;
  1145. AvgRT /= trans;
  1146. TransRate = ( (float)trans / duration );
  1147. fprintf(procFile,
  1148. "| %-28ws %7d %7.0f ",
  1149. (pMofInfo->strDescription) ? pMofInfo->strDescription : CpdiGuidToString( str, &pMofInfo->Guid ),
  1150. pMofData->CompleteCount,
  1151. AvgRT
  1152. );
  1153. fprintf(procFile,
  1154. " %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %21s\n",
  1155. TransRate,
  1156. PerCpu,
  1157. RIO,
  1158. WIO,
  1159. Send,
  1160. Recv,
  1161. "|"
  1162. );
  1163. }
  1164. DNext = DNext->Flink;
  1165. }
  1166. Next = Next->Flink;
  1167. }
  1168. fprintf(procFile, BREAK_LINE "\n\n" );
  1169. }
  1170. static void WriteTransactionCPUTime()
  1171. {
  1172. PLIST_ENTRY Head, Next;
  1173. PLIST_ENTRY Dhead, DNext;
  1174. double KCPU, UCPU;
  1175. PMOF_INFO pMofInfo;
  1176. PMOF_DATA pMofData;
  1177. double trans;
  1178. double PerCpu;
  1179. WCHAR str[1024];
  1180. double duration = ((double)((LONGLONG)(CurrentSystem.EndTime - CurrentSystem.StartTime))) / 10000000.00;
  1181. BOOL bTable = FALSE;
  1182. Head = &CurrentSystem.EventListHead;
  1183. Next = Head->Flink;
  1184. while (Head != Next && !bTable ) {
  1185. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1186. Dhead = &pMofInfo->DataListHead;
  1187. DNext = Dhead->Flink;
  1188. while(DNext!=Dhead){
  1189. pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
  1190. trans = (double)pMofData->CompleteCount;
  1191. if (trans > 0) {
  1192. bTable = TRUE;
  1193. break;
  1194. }
  1195. DNext = DNext->Flink;
  1196. }
  1197. Next = Next->Flink;
  1198. }
  1199. if( !bTable ){
  1200. return;
  1201. }
  1202. if( !(ReportFlags & TRACE_LOG_REPORT_TOTALS) ){
  1203. fprintf( procFile,
  1204. BREAK_LINE
  1205. "| Transaction CPU Utilization |\n"
  1206. BREAK_LINE
  1207. "| Transaction Trans/sec Minimum Maximum Per Transaction Total CPU%% |\n"
  1208. "| KCPU(ms) UCPU(ms) KCPU(ms) UCPU(ms) KCPU(ms) UCPU(ms) KCPU(ms) UCPU(ms) |\n"
  1209. BREAK_LINE
  1210. );
  1211. }else{
  1212. fprintf( procFile,
  1213. BREAK_LINE
  1214. "| Transaction CPU Utilization |\n"
  1215. BREAK_LINE
  1216. "| Transaction Trans Minimum Maximum Per Transaction Total CPU%% |\n"
  1217. "| KCPU(ms) UCPU(ms) KCPU(ms) UCPU(ms) KCPU(ms) UCPU(ms) KCPU(ms) UCPU(ms) |\n"
  1218. BREAK_LINE
  1219. );
  1220. }
  1221. Head = &CurrentSystem.EventListHead;
  1222. Next = Head->Flink;
  1223. while (Head != Next) {
  1224. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1225. Dhead = &pMofInfo->DataListHead;
  1226. DNext = Dhead->Flink;
  1227. while(DNext!=Dhead){
  1228. pMofData = CONTAINING_RECORD(DNext, MOF_DATA, Entry);
  1229. trans = (double)pMofData->CompleteCount;
  1230. if (trans > 0) {
  1231. UCPU = pMofData->UserCPU;
  1232. UCPU /= trans;
  1233. KCPU = pMofData->KernelCPU;
  1234. KCPU /= trans;
  1235. PerCpu = (((pMofData->UserCPU + pMofData->KernelCPU + 0.0)/1000.0)/duration) * 100.0;
  1236. if( !(ReportFlags & TRACE_LOG_REPORT_TOTALS) ){
  1237. trans /= duration;
  1238. }
  1239. if(CurrentSystem.NumberOfProcessors)
  1240. PerCpu/=CurrentSystem.NumberOfProcessors;
  1241. fprintf(procFile,
  1242. "| %-28ws %7.2f %7d %7d %7d %7d %7.0f %7.0f %7d %7d %6.2f |\n",
  1243. (pMofInfo->strDescription) ? pMofInfo->strDescription : CpdiGuidToString( str, &pMofInfo->Guid ),
  1244. trans,
  1245. pMofData->MinKCpu,
  1246. pMofData->MinUCpu,
  1247. pMofData->MaxKCpu,
  1248. pMofData->MaxUCpu,
  1249. KCPU,
  1250. UCPU,
  1251. pMofData->KernelCPU,
  1252. pMofData->UserCPU,
  1253. PerCpu
  1254. );
  1255. }
  1256. DNext = DNext->Flink;
  1257. }
  1258. Next = Next->Flink;
  1259. }
  1260. fprintf(procFile, BREAK_LINE "\n\n" );
  1261. }
  1262. PWCHAR CpdiGuidToString(
  1263. PWCHAR s,
  1264. LPGUID piid
  1265. )
  1266. {
  1267. swprintf(s, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
  1268. piid->Data1, piid->Data2,
  1269. piid->Data3,
  1270. piid->Data4[0], piid->Data4[1],
  1271. piid->Data4[2], piid->Data4[3],
  1272. piid->Data4[4], piid->Data4[5],
  1273. piid->Data4[6], piid->Data4[7]);
  1274. return(s);
  1275. }
  1276. /*=============================================================================
  1277. */
  1278. #define MAX_RECORDS 65536
  1279. #define MAX_LOGS 1024 * 1024
  1280. typedef struct _PTR_RECORD
  1281. {
  1282. PVOID ptrRecord;
  1283. ULONG keySort;
  1284. } PTR_RECORD, * PPTR_RECORD;
  1285. static PPTR_RECORD PtrBuffer = NULL;
  1286. static ULONG PtrMax = MAX_LOGS;
  1287. static ULONG PtrTotal = 0;
  1288. static ULONG PtrIndex;
  1289. static PPROCESS_RECORD * ProcessList = NULL;
  1290. static WCHAR ** ModuleList = NULL;
  1291. static ULONG lCurrentMax = MAX_RECORDS;
  1292. static ULONG lTotal = 0;
  1293. void OutputTitle(
  1294. MM_REPORT_TYPE reportNow,
  1295. MM_REPORT_SORT_KEY sortNow,
  1296. PWCHAR strImgName
  1297. )
  1298. {
  1299. switch (reportNow)
  1300. {
  1301. case REPORT_SUMMARY_PROCESS:
  1302. fprintf(procFile, "Page Fault Summary for Processes, ");
  1303. break;
  1304. case REPORT_SUMMARY_MODULE:
  1305. fprintf(procFile, "Page Fault Summary for Loaded Modules, ");
  1306. break;
  1307. case REPORT_LIST_PROCESS:
  1308. fprintf(procFile, "Page Fault Rundown for ");
  1309. if (strImgName)
  1310. {
  1311. fprintf(procFile, "process '%ws', ", strImgName);
  1312. }
  1313. else
  1314. {
  1315. fprintf(procFile, "all processes, ");
  1316. }
  1317. break;
  1318. case REPORT_LIST_MODULE:
  1319. fprintf(procFile, "Page Fault rundown for ");
  1320. if (strImgName)
  1321. {
  1322. fprintf(procFile, "loaded module '%ws', ", strImgName);
  1323. }
  1324. else
  1325. {
  1326. fprintf(procFile, "all loaded modules, ");
  1327. }
  1328. break;
  1329. }
  1330. switch (sortNow)
  1331. {
  1332. case REPORT_SORT_ALL:
  1333. fprintf(procFile, "sorted by all page faults total.");
  1334. break;
  1335. case REPORT_SORT_HPF:
  1336. fprintf(procFile, "sorted by HardPageFault total.");
  1337. break;
  1338. case REPORT_SORT_TF:
  1339. fprintf(procFile, "sorted by TransitionFault total.");
  1340. break;
  1341. case REPORT_SORT_DZF:
  1342. fprintf(procFile, "sorted by DemandZeroFault total.");
  1343. break;
  1344. case REPORT_SORT_COW:
  1345. fprintf(procFile, "sorted by CopyOnWrite total.");
  1346. break;
  1347. }
  1348. fprintf(procFile, "\n");
  1349. }
  1350. void OutputModuleHeader()
  1351. {
  1352. fprintf(procFile, "=======================================================================================\n");
  1353. fprintf(procFile, " Module Name Base Module Fault Outside Image Fault Inside Image \n");
  1354. fprintf(procFile, " Address Size HPF TF DZF COW HPF TF DZF COW\n");
  1355. fprintf(procFile, "=======================================================================================\n");
  1356. }
  1357. void OutputModuleRecord(PMODULE_RECORD pModule)
  1358. {
  1359. fprintf(procFile, "%-12ws 0x%08x%8d %6d %6d %6d %6d %6d %6d %6d %6d\n",
  1360. pModule->strModuleName,
  1361. pModule->lBaseAddress,
  1362. pModule->lModuleSize,
  1363. pModule->lDataFaultHF,
  1364. pModule->lDataFaultTF,
  1365. pModule->lDataFaultDZF,
  1366. pModule->lDataFaultCOW,
  1367. pModule->lCodeFaultHF,
  1368. pModule->lCodeFaultTF,
  1369. pModule->lCodeFaultDZF,
  1370. pModule->lCodeFaultCOW);
  1371. }
  1372. void OutputTotal(
  1373. BOOLEAN fIsModule,
  1374. ULONG totalDataFaultHF,
  1375. ULONG totalDataFaultTF,
  1376. ULONG totalDataFaultDZF,
  1377. ULONG totalDataFaultCOW,
  1378. ULONG totalCodeFaultHF,
  1379. ULONG totalCodeFaultTF,
  1380. ULONG totalCodeFaultDZF,
  1381. ULONG totalCodeFaultCOW
  1382. )
  1383. {
  1384. if (fIsModule)
  1385. {
  1386. fprintf(procFile, "=======================================================================================\n");
  1387. fprintf(procFile, "Total %6d %6d %6d %6d %6d %6d %6d %6d\n",
  1388. totalDataFaultHF,
  1389. totalDataFaultTF,
  1390. totalDataFaultDZF,
  1391. totalDataFaultCOW,
  1392. totalCodeFaultHF,
  1393. totalCodeFaultTF,
  1394. totalCodeFaultDZF,
  1395. totalCodeFaultCOW);
  1396. fprintf(procFile, "=======================================================================================\n");
  1397. }
  1398. else
  1399. {
  1400. fprintf(procFile, "=============================================================================\n");
  1401. fprintf(procFile, "Total %6d %6d %6d %6d %6d %6d %6d %6d\n",
  1402. totalDataFaultHF,
  1403. totalDataFaultTF,
  1404. totalDataFaultDZF,
  1405. totalDataFaultCOW,
  1406. totalCodeFaultHF,
  1407. totalCodeFaultTF,
  1408. totalCodeFaultDZF,
  1409. totalCodeFaultCOW);
  1410. fprintf(procFile, "=============================================================================\n");
  1411. }
  1412. }
  1413. void OutputProcessHeader()
  1414. {
  1415. fprintf(procFile, "=============================================================================\n");
  1416. fprintf(procFile, " Process Image Name Fault Outside Image Fault Inside Image \n");
  1417. fprintf(procFile, " ID HPF TF DZF COW HPF TF DZF COW\n");
  1418. fprintf(procFile, "=============================================================================\n");
  1419. }
  1420. void OutputProcessRecord(PPROCESS_RECORD pProcess)
  1421. {
  1422. fprintf(procFile, "0x%06x %-12ws %6d %6d %6d %6d %6d %6d %6d %6d\n",
  1423. pProcess->PID,
  1424. pProcess->ImageName,
  1425. pProcess->lDataFaultHF,
  1426. pProcess->lDataFaultTF,
  1427. pProcess->lDataFaultDZF,
  1428. pProcess->lDataFaultCOW,
  1429. pProcess->lCodeFaultHF,
  1430. pProcess->lCodeFaultTF,
  1431. pProcess->lCodeFaultDZF,
  1432. pProcess->lCodeFaultCOW);
  1433. }
  1434. void OutputModuleProcessRecord(PPROCESS_RECORD pProcess, PMODULE_RECORD pModule)
  1435. {
  1436. fprintf(procFile, "0x%06x %-12ws %6d %6d %6d %6d %6d %6d %6d %6d\n",
  1437. pProcess->PID,
  1438. pProcess->ImageName,
  1439. pModule->lDataFaultHF,
  1440. pModule->lDataFaultTF,
  1441. pModule->lDataFaultDZF,
  1442. pModule->lDataFaultCOW,
  1443. pModule->lCodeFaultHF,
  1444. pModule->lCodeFaultTF,
  1445. pModule->lCodeFaultDZF,
  1446. pModule->lCodeFaultCOW);
  1447. }
  1448. BOOLEAN ModuleHasPageFault(PMODULE_RECORD pModule)
  1449. {
  1450. return (BOOLEAN) (pModule->lDataFaultHF
  1451. + pModule->lDataFaultTF
  1452. + pModule->lDataFaultDZF
  1453. + pModule->lDataFaultCOW
  1454. + pModule->lCodeFaultHF
  1455. + pModule->lCodeFaultTF
  1456. + pModule->lCodeFaultDZF
  1457. + pModule->lCodeFaultCOW
  1458. != 0);
  1459. }
  1460. BOOLEAN ProcessHasPageFault(PPROCESS_RECORD pProcess)
  1461. {
  1462. return (BOOLEAN) (pProcess->lDataFaultHF
  1463. + pProcess->lDataFaultTF
  1464. + pProcess->lDataFaultDZF
  1465. + pProcess->lDataFaultCOW
  1466. + pProcess->lCodeFaultHF
  1467. + pProcess->lCodeFaultTF
  1468. + pProcess->lCodeFaultDZF
  1469. + pProcess->lCodeFaultCOW
  1470. != 0);
  1471. }
  1472. ULONG GetModuleSortKey(PMODULE_RECORD pModule, MM_REPORT_SORT_KEY keySort)
  1473. {
  1474. ULONG keyValue = 0;
  1475. switch (keySort)
  1476. {
  1477. case REPORT_SORT_ALL:
  1478. keyValue = pModule->lDataFaultHF + pModule->lCodeFaultHF
  1479. + pModule->lDataFaultTF + pModule->lCodeFaultTF
  1480. + pModule->lDataFaultDZF + pModule->lCodeFaultDZF
  1481. + pModule->lDataFaultCOW + pModule->lCodeFaultCOW;
  1482. break;
  1483. case REPORT_SORT_HPF:
  1484. keyValue = pModule->lDataFaultHF + pModule->lCodeFaultHF;
  1485. break;
  1486. case REPORT_SORT_TF:
  1487. keyValue = pModule->lDataFaultTF + pModule->lCodeFaultTF;
  1488. break;
  1489. case REPORT_SORT_DZF:
  1490. keyValue = pModule->lDataFaultDZF + pModule->lCodeFaultDZF;
  1491. break;
  1492. case REPORT_SORT_COW:
  1493. keyValue = pModule->lDataFaultCOW + pModule->lCodeFaultCOW;
  1494. break;
  1495. }
  1496. return keyValue;
  1497. }
  1498. ULONG GetProcessSortKey(PPROCESS_RECORD pProcess, MM_REPORT_SORT_KEY keySort)
  1499. {
  1500. ULONG keyValue = 0;
  1501. switch (keySort)
  1502. {
  1503. case REPORT_SORT_ALL:
  1504. keyValue = pProcess->lDataFaultHF + pProcess->lCodeFaultHF
  1505. + pProcess->lDataFaultTF + pProcess->lCodeFaultTF
  1506. + pProcess->lDataFaultDZF + pProcess->lCodeFaultDZF
  1507. + pProcess->lDataFaultCOW + pProcess->lCodeFaultCOW;
  1508. break;
  1509. case REPORT_SORT_HPF:
  1510. keyValue = pProcess->lDataFaultHF + pProcess->lCodeFaultHF;
  1511. break;
  1512. case REPORT_SORT_TF:
  1513. keyValue = pProcess->lDataFaultTF + pProcess->lCodeFaultTF;
  1514. break;
  1515. case REPORT_SORT_DZF:
  1516. keyValue = pProcess->lDataFaultDZF + pProcess->lCodeFaultDZF;
  1517. break;
  1518. case REPORT_SORT_COW:
  1519. keyValue = pProcess->lDataFaultCOW + pProcess->lCodeFaultCOW;
  1520. break;
  1521. }
  1522. return keyValue;
  1523. }
  1524. ULONG GetModuleListIndex(PWCHAR strModuleName)
  1525. {
  1526. ULONG lIndex;
  1527. for (lIndex = 0; lIndex < lTotal; lIndex ++)
  1528. {
  1529. if (_wcsicmp(ModuleList[lIndex], strModuleName) == 0)
  1530. {
  1531. break;
  1532. }
  1533. }
  1534. return (lIndex);
  1535. }
  1536. ULONG GetProcessListIndex(PPROCESS_RECORD pProcess)
  1537. {
  1538. ULONG lIndex;
  1539. for (lIndex = 0; lIndex < lTotal; lIndex ++)
  1540. {
  1541. if (ProcessList[lIndex] == pProcess)
  1542. {
  1543. break;
  1544. }
  1545. }
  1546. return (lIndex);
  1547. }
  1548. int __cdecl CompareModuleRecord(const void * p1, const void * p2)
  1549. {
  1550. PPTR_RECORD pp1 = (PPTR_RECORD) p1;
  1551. PPTR_RECORD pp2 = (PPTR_RECORD) p2;
  1552. PMODULE_RECORD pModule1 = pp1->ptrRecord;
  1553. PMODULE_RECORD pModule2 = pp2->ptrRecord;
  1554. LONG diffFault = pp2->keySort - pp1->keySort;
  1555. if (diffFault == 0)
  1556. {
  1557. diffFault = wcscmp(pModule1->strModuleName, pModule2->strModuleName);
  1558. }
  1559. return diffFault;
  1560. }
  1561. int __cdecl CompareProcessRecord(const void * p1, const void * p2)
  1562. {
  1563. PPTR_RECORD pp1 = (PPTR_RECORD) p1;
  1564. PPTR_RECORD pp2 = (PPTR_RECORD) p2;
  1565. PPROCESS_RECORD pProcess1 = pp1->ptrRecord;
  1566. PPROCESS_RECORD pProcess2 = pp2->ptrRecord;
  1567. LONG diffFault = pp2->keySort - pp1->keySort;
  1568. if (diffFault == 0)
  1569. {
  1570. diffFault = _wcsicmp(pProcess1->ImageName, pProcess2->ImageName);
  1571. }
  1572. return diffFault;
  1573. }
  1574. int __cdecl CompareProcessModuleRecord(const void * p1, const void * p2)
  1575. {
  1576. PPTR_RECORD pp1 = (PPTR_RECORD) p1;
  1577. PPTR_RECORD pp2 = (PPTR_RECORD) p2;
  1578. PMODULE_RECORD pModule1 = pp1->ptrRecord;
  1579. PMODULE_RECORD pModule2 = pp2->ptrRecord;
  1580. LONG diffFault = GetProcessListIndex(pModule1->pProcess)
  1581. - GetProcessListIndex(pModule2->pProcess);
  1582. if (diffFault == 0)
  1583. {
  1584. diffFault = pp2->keySort - pp1->keySort;
  1585. if (diffFault == 0)
  1586. {
  1587. diffFault = wcscmp(pModule1->strModuleName,
  1588. pModule2->strModuleName);
  1589. }
  1590. }
  1591. return diffFault;
  1592. }
  1593. int __cdecl CompareModuleProcessRecord(const void * p1, const void * p2)
  1594. {
  1595. PPTR_RECORD pp1 = (PPTR_RECORD) p1;
  1596. PPTR_RECORD pp2 = (PPTR_RECORD) p2;
  1597. PMODULE_RECORD pModule1 = pp1->ptrRecord;
  1598. PMODULE_RECORD pModule2 = pp2->ptrRecord;
  1599. LONG diffFault = GetModuleListIndex(pModule1->strModuleName)
  1600. - GetModuleListIndex(pModule2->strModuleName);
  1601. if (diffFault == 0)
  1602. {
  1603. diffFault = pp2->keySort - pp1->keySort;
  1604. if (diffFault == 0)
  1605. {
  1606. if (pModule1->pProcess && pModule2->pProcess)
  1607. {
  1608. diffFault = (int) ( pModule1->pProcess->PID
  1609. - pModule2->pProcess->PID);
  1610. }
  1611. else if (pModule1->pProcess)
  1612. {
  1613. diffFault = -1;
  1614. }
  1615. else if (pModule2->pProcess)
  1616. {
  1617. diffFault = 1;
  1618. }
  1619. else
  1620. {
  1621. diffFault = 0;
  1622. }
  1623. }
  1624. }
  1625. return diffFault;
  1626. }
  1627. BOOLEAN GetModuleSummary(WCHAR * strModuleName, MM_REPORT_SORT_KEY sortNow)
  1628. {
  1629. PLIST_ENTRY pHead = & CurrentSystem.GlobalModuleListHead;
  1630. PLIST_ENTRY pNext = pHead->Flink;
  1631. PMODULE_RECORD pModule;
  1632. BOOLEAN fDone = FALSE;
  1633. while (!fDone)
  1634. {
  1635. for (PtrTotal = 0, fDone = TRUE;
  1636. pNext != pHead;
  1637. pNext = pNext->Flink)
  1638. {
  1639. if (PtrTotal == PtrMax)
  1640. {
  1641. fDone = FALSE;
  1642. break;
  1643. }
  1644. pModule = CONTAINING_RECORD(pNext, MODULE_RECORD, Entry);
  1645. if ( (!strModuleName || (pModule->strModuleName &&
  1646. !_wcsicmp(strModuleName, pModule->strModuleName)))
  1647. && (ModuleHasPageFault(pModule)))
  1648. {
  1649. PtrBuffer[PtrTotal].ptrRecord = (PVOID) pModule;
  1650. PtrBuffer[PtrTotal].keySort =
  1651. GetModuleSortKey(pModule, sortNow);
  1652. PtrTotal ++;
  1653. }
  1654. }
  1655. if (!fDone)
  1656. {
  1657. VirtualFree(PtrBuffer, 0, MEM_RELEASE);
  1658. PtrMax += MAX_LOGS;
  1659. PtrBuffer = (PPTR_RECORD) VirtualAlloc(
  1660. NULL,
  1661. sizeof(PTR_RECORD) * PtrMax,
  1662. MEM_COMMIT,
  1663. PAGE_READWRITE);
  1664. if (PtrBuffer == NULL)
  1665. {
  1666. // fprintf(stderr, "(PDH.DLL) Memory Commit Failure.\n");
  1667. goto Cleanup;
  1668. }
  1669. }
  1670. }
  1671. if (PtrTotal > 1)
  1672. {
  1673. qsort((void *) PtrBuffer,
  1674. (size_t) PtrTotal,
  1675. (size_t) sizeof(PTR_RECORD),
  1676. CompareModuleRecord);
  1677. }
  1678. Cleanup:
  1679. return fDone;
  1680. }
  1681. BOOLEAN GetProcessSummary(WCHAR * strImgName, MM_REPORT_SORT_KEY sortNow)
  1682. {
  1683. PLIST_ENTRY pHead = & CurrentSystem.ProcessListHead;
  1684. PLIST_ENTRY pNext = pHead->Flink;
  1685. PPROCESS_RECORD pProcess;
  1686. BOOLEAN fDone = FALSE;
  1687. while (!fDone)
  1688. {
  1689. for (fDone = TRUE, PtrTotal = 0;
  1690. pNext != pHead;
  1691. pNext = pNext->Flink)
  1692. {
  1693. if (PtrTotal == PtrMax)
  1694. {
  1695. fDone = FALSE;
  1696. break;
  1697. }
  1698. pProcess = CONTAINING_RECORD(pNext, PROCESS_RECORD, Entry);
  1699. if ( (!strImgName || (pProcess->ImageName &&
  1700. !_wcsicmp(strImgName, pProcess->ImageName)))
  1701. && (ProcessHasPageFault(pProcess)))
  1702. {
  1703. PtrBuffer[PtrTotal].ptrRecord = (PVOID) pProcess;
  1704. PtrBuffer[PtrTotal].keySort =
  1705. GetProcessSortKey(pProcess, sortNow);
  1706. PtrTotal ++;
  1707. }
  1708. }
  1709. if (!fDone)
  1710. {
  1711. VirtualFree(PtrBuffer, 0, MEM_RELEASE);
  1712. PtrMax += MAX_LOGS;
  1713. PtrBuffer = (PPTR_RECORD) VirtualAlloc(
  1714. NULL,
  1715. sizeof(PTR_RECORD) * PtrMax,
  1716. MEM_COMMIT,
  1717. PAGE_READWRITE);
  1718. if (PtrBuffer == NULL)
  1719. {
  1720. // fprintf(stderr, "(PDH.DLL) Memory Commit Failure.\n");
  1721. goto Cleanup;
  1722. }
  1723. }
  1724. }
  1725. if (PtrTotal > 1)
  1726. {
  1727. qsort((void *) PtrBuffer,
  1728. (size_t) PtrTotal,
  1729. (size_t) sizeof(PTR_RECORD),
  1730. CompareProcessRecord);
  1731. }
  1732. Cleanup:
  1733. return fDone;
  1734. }
  1735. BOOLEAN GoThroughAllProcessModule(
  1736. BOOLEAN fProcessList,
  1737. MM_REPORT_SORT_KEY sortNow
  1738. )
  1739. {
  1740. BOOLEAN fDone = FALSE;
  1741. PLIST_ENTRY pProcessHead = & CurrentSystem.ProcessListHead;
  1742. PLIST_ENTRY pProcessNext = pProcessHead->Flink;
  1743. PLIST_ENTRY pModuleHead;
  1744. PLIST_ENTRY pModuleNext;
  1745. PPROCESS_RECORD pProcess;
  1746. PMODULE_RECORD pModule;
  1747. while (!fDone)
  1748. {
  1749. for (PtrTotal = 0, fDone = TRUE;
  1750. fDone && pProcessNext != pProcessHead;
  1751. pProcessNext = pProcessNext->Flink)
  1752. {
  1753. pProcess = CONTAINING_RECORD(pProcessNext, PROCESS_RECORD, Entry);
  1754. if (fProcessList && GetProcessListIndex(pProcess) == lTotal)
  1755. {
  1756. continue;
  1757. }
  1758. pModuleHead = & pProcess->ModuleListHead;
  1759. for (pModuleNext = pModuleHead->Flink;
  1760. pModuleNext != pModuleHead;
  1761. pModuleNext = pModuleNext->Flink)
  1762. {
  1763. if (PtrTotal == PtrMax)
  1764. {
  1765. fDone = FALSE;
  1766. break;
  1767. }
  1768. pModule = CONTAINING_RECORD(pModuleNext,
  1769. MODULE_RECORD,
  1770. Entry);
  1771. if ( !fProcessList
  1772. && GetModuleListIndex(pModule->strModuleName) == lTotal)
  1773. {
  1774. continue;
  1775. }
  1776. if (ModuleHasPageFault(pModule))
  1777. {
  1778. PtrBuffer[PtrTotal].ptrRecord = (PVOID) pModule;
  1779. PtrBuffer[PtrTotal].keySort =
  1780. GetModuleSortKey(pModule, sortNow);
  1781. PtrTotal ++;
  1782. }
  1783. }
  1784. }
  1785. if (!fDone)
  1786. {
  1787. VirtualFree(PtrBuffer, 0, MEM_RELEASE);
  1788. PtrMax += MAX_LOGS;
  1789. PtrBuffer = (PPTR_RECORD) VirtualAlloc(
  1790. NULL,
  1791. sizeof(PTR_RECORD) * PtrMax,
  1792. MEM_COMMIT,
  1793. PAGE_READWRITE);
  1794. if (PtrBuffer == NULL)
  1795. {
  1796. // fprintf(stderr, "(PDH.DLL) Memory Commit Failure.\n");
  1797. goto Cleanup;
  1798. }
  1799. }
  1800. }
  1801. Cleanup:
  1802. return fDone;
  1803. }
  1804. BOOLEAN GetModuleList(WCHAR * strImgName, MM_REPORT_SORT_KEY sortNow)
  1805. {
  1806. PMODULE_RECORD pModule;
  1807. BOOLEAN fResult = GetModuleSummary(strImgName, sortNow);
  1808. ULONG lAllocSize = sizeof(ULONG) * lCurrentMax;
  1809. ULONG lIndex;
  1810. if (!fResult)
  1811. {
  1812. goto Cleanup;
  1813. }
  1814. // collect information from ModuleSummary and store in ModuleList array
  1815. //
  1816. ASSERT(!ModuleList);
  1817. ModuleList = (PWCHAR *) VirtualAlloc(
  1818. NULL, lAllocSize, MEM_COMMIT, PAGE_READWRITE);
  1819. if (ModuleList == NULL)
  1820. {
  1821. fResult = FALSE;
  1822. goto Cleanup;
  1823. }
  1824. for (fResult = FALSE; !fResult;)
  1825. {
  1826. for (fResult = TRUE, lTotal = 0, PtrIndex = 0;
  1827. PtrIndex < PtrTotal;
  1828. PtrIndex ++, lTotal ++)
  1829. {
  1830. if (lTotal == MAX_RECORDS)
  1831. {
  1832. fResult = FALSE;
  1833. break;
  1834. }
  1835. pModule = (PMODULE_RECORD) PtrBuffer[PtrIndex].ptrRecord;
  1836. ModuleList[lTotal] = (PWCHAR) VirtualAlloc(
  1837. NULL,
  1838. sizeof(WCHAR) * (lstrlenW(pModule->strModuleName) + 1),
  1839. MEM_COMMIT,
  1840. PAGE_READWRITE);
  1841. if (ModuleList[lTotal] == NULL) {
  1842. fResult = FALSE;
  1843. break;
  1844. }
  1845. wcscpy(ModuleList[lTotal], pModule->strModuleName);
  1846. }
  1847. if (!fResult)
  1848. {
  1849. for (lIndex = 0; lIndex < lTotal; lIndex ++)
  1850. {
  1851. VirtualFree(ModuleList[lIndex], 0, MEM_RELEASE);
  1852. }
  1853. VirtualFree(ModuleList, 0, MEM_RELEASE);
  1854. lCurrentMax += MAX_RECORDS;
  1855. lAllocSize = sizeof(ULONG) * lCurrentMax;
  1856. ModuleList =
  1857. VirtualAlloc(NULL, lAllocSize, MEM_COMMIT, PAGE_READWRITE);
  1858. if (ModuleList == NULL)
  1859. {
  1860. // fprintf(stderr, "(PDH.DLL) Memory Commit Failure.\n");
  1861. goto Cleanup;
  1862. }
  1863. }
  1864. }
  1865. // go through ModuleList of each PROCESS_RECORD based on the information
  1866. // from ModuleList array
  1867. //
  1868. fResult = GoThroughAllProcessModule(FALSE, sortNow);
  1869. if (fResult && PtrTotal > 1)
  1870. {
  1871. qsort((void *) PtrBuffer,
  1872. (size_t) PtrTotal,
  1873. (size_t) sizeof(PTR_RECORD),
  1874. CompareModuleProcessRecord);
  1875. }
  1876. Cleanup:
  1877. if (ModuleList)
  1878. {
  1879. for (lIndex = 0; lIndex < lTotal; lIndex ++)
  1880. {
  1881. VirtualFree(ModuleList[lIndex], 0, MEM_RELEASE);
  1882. }
  1883. VirtualFree(ModuleList, 0, MEM_RELEASE);
  1884. ModuleList = NULL;
  1885. }
  1886. return fResult;
  1887. }
  1888. BOOLEAN GetProcessList(WCHAR * strImgName, MM_REPORT_SORT_KEY sortNow)
  1889. {
  1890. PPROCESS_RECORD pProcess;
  1891. BOOLEAN fResult = GetProcessSummary(strImgName, sortNow);
  1892. ULONG lAllocSize = sizeof(PPROCESS_RECORD) * lCurrentMax;
  1893. if (!fResult)
  1894. {
  1895. goto Cleanup;
  1896. }
  1897. // collect information from ProcessSummary and store in ProcessList array
  1898. //
  1899. ASSERT(!ProcessList);
  1900. ProcessList = (PPROCESS_RECORD *) VirtualAlloc(
  1901. NULL, lAllocSize, MEM_COMMIT, PAGE_READWRITE);
  1902. if (ProcessList == NULL)
  1903. {
  1904. fResult = FALSE;
  1905. goto Cleanup;
  1906. }
  1907. for (fResult = FALSE; !fResult;)
  1908. {
  1909. for (fResult = TRUE, lTotal = 0, PtrIndex = 0;
  1910. PtrIndex < PtrTotal;
  1911. PtrIndex ++, lTotal ++)
  1912. {
  1913. if (lTotal == MAX_RECORDS)
  1914. {
  1915. fResult = FALSE;
  1916. break;
  1917. }
  1918. pProcess = (PPROCESS_RECORD) PtrBuffer[PtrIndex].ptrRecord;
  1919. ProcessList[lTotal] = pProcess;
  1920. }
  1921. if (!fResult)
  1922. {
  1923. VirtualFree(ProcessList, 0, MEM_RELEASE);
  1924. lCurrentMax += MAX_RECORDS;
  1925. lAllocSize = sizeof(ULONG) * lCurrentMax;
  1926. ProcessList =
  1927. VirtualAlloc(NULL, lAllocSize, MEM_COMMIT, PAGE_READWRITE);
  1928. if (ProcessList == NULL)
  1929. {
  1930. // fprintf(stderr, "(PDH.DLL) Memory Commit Failure.\n");
  1931. goto Cleanup;
  1932. }
  1933. }
  1934. }
  1935. // go through ModuleList of each PROCESS_RECORD based on the information
  1936. // from ProcessList
  1937. //
  1938. fResult = GoThroughAllProcessModule(TRUE, sortNow);
  1939. if (fResult && PtrTotal > 1)
  1940. {
  1941. qsort((void *) PtrBuffer,
  1942. (size_t) PtrTotal,
  1943. (size_t) sizeof(PTR_RECORD),
  1944. CompareProcessModuleRecord);
  1945. }
  1946. Cleanup:
  1947. if (ProcessList)
  1948. {
  1949. VirtualFree(ProcessList, 0, MEM_RELEASE);
  1950. ProcessList = NULL;
  1951. }
  1952. return fResult;
  1953. }
  1954. void ReportPageFaultInfo(PCPD_USER_CONTEXT_MM pUserContext)
  1955. {
  1956. PPROCESS_RECORD pProcessPrev = NULL;
  1957. WCHAR Module_Prev[256];
  1958. MM_REPORT_TYPE reportNow = REPORT_SUMMARY_PROCESS;
  1959. MM_REPORT_SORT_KEY sortNow = REPORT_SORT_ALL;
  1960. PWCHAR strImgName = NULL;
  1961. ULONG totalDataFaultHF = 0;
  1962. ULONG totalDataFaultTF = 0;
  1963. ULONG totalDataFaultDZF = 0;
  1964. ULONG totalDataFaultCOW = 0;
  1965. ULONG totalCodeFaultHF = 0;
  1966. ULONG totalCodeFaultTF = 0;
  1967. ULONG totalCodeFaultDZF = 0;
  1968. ULONG totalCodeFaultCOW = 0;
  1969. PPROCESS_RECORD pProcess;
  1970. PMODULE_RECORD pModule;
  1971. return;
  1972. ASSERT(!PtrBuffer);
  1973. PtrBuffer = (PPTR_RECORD) VirtualAlloc(
  1974. NULL,
  1975. sizeof(PTR_RECORD) * PtrMax,
  1976. MEM_COMMIT,
  1977. PAGE_READWRITE);
  1978. if (PtrBuffer == NULL)
  1979. {
  1980. goto Cleanup;
  1981. }
  1982. if (pUserContext)
  1983. {
  1984. reportNow = pUserContext->reportNow;
  1985. sortNow = pUserContext->sortNow;
  1986. strImgName = pUserContext->strImgName;
  1987. }
  1988. OutputTitle(reportNow, sortNow, strImgName);
  1989. switch (reportNow)
  1990. {
  1991. case REPORT_SUMMARY_MODULE:
  1992. if( FALSE == GetModuleSummary(NULL, sortNow) ){
  1993. break;
  1994. }
  1995. OutputModuleHeader();
  1996. totalDataFaultHF = totalDataFaultTF = totalDataFaultDZF
  1997. = totalDataFaultCOW = totalCodeFaultHF
  1998. = totalCodeFaultTF = totalCodeFaultDZF
  1999. = totalCodeFaultCOW = 0;
  2000. for (PtrIndex = 0; PtrIndex < PtrTotal; PtrIndex ++)
  2001. {
  2002. pModule = (PMODULE_RECORD) PtrBuffer[PtrIndex].ptrRecord;
  2003. OutputModuleRecord(pModule);
  2004. totalDataFaultHF += pModule->lDataFaultHF;
  2005. totalDataFaultTF += pModule->lDataFaultTF;
  2006. totalDataFaultDZF += pModule->lDataFaultDZF;
  2007. totalDataFaultCOW += pModule->lDataFaultCOW;
  2008. totalCodeFaultHF += pModule->lCodeFaultHF;
  2009. totalCodeFaultTF += pModule->lCodeFaultTF;
  2010. totalCodeFaultDZF += pModule->lCodeFaultDZF;
  2011. totalCodeFaultCOW += pModule->lCodeFaultCOW;
  2012. }
  2013. OutputTotal(TRUE,
  2014. totalDataFaultHF,
  2015. totalDataFaultTF,
  2016. totalDataFaultDZF,
  2017. totalDataFaultCOW,
  2018. totalCodeFaultHF,
  2019. totalCodeFaultTF,
  2020. totalCodeFaultDZF,
  2021. totalCodeFaultCOW);
  2022. break;
  2023. case REPORT_SUMMARY_PROCESS:
  2024. if( FALSE == GetProcessSummary(NULL, sortNow) ){
  2025. break;
  2026. }
  2027. OutputProcessHeader();
  2028. totalDataFaultHF = totalDataFaultTF = totalDataFaultDZF
  2029. = totalDataFaultCOW = totalCodeFaultHF
  2030. = totalCodeFaultTF = totalCodeFaultDZF
  2031. = totalCodeFaultCOW = 0;
  2032. for (PtrIndex = 0; PtrIndex < PtrTotal; PtrIndex ++)
  2033. {
  2034. pProcess = (PPROCESS_RECORD) PtrBuffer[PtrIndex].ptrRecord;
  2035. OutputProcessRecord(pProcess);
  2036. totalDataFaultHF += pProcess->lDataFaultHF;
  2037. totalDataFaultTF += pProcess->lDataFaultTF;
  2038. totalDataFaultDZF += pProcess->lDataFaultDZF;
  2039. totalDataFaultCOW += pProcess->lDataFaultCOW;
  2040. totalCodeFaultHF += pProcess->lCodeFaultHF;
  2041. totalCodeFaultTF += pProcess->lCodeFaultTF;
  2042. totalCodeFaultDZF += pProcess->lCodeFaultDZF;
  2043. totalCodeFaultCOW += pProcess->lCodeFaultCOW;
  2044. }
  2045. OutputTotal(FALSE,
  2046. totalDataFaultHF,
  2047. totalDataFaultTF,
  2048. totalDataFaultDZF,
  2049. totalDataFaultCOW,
  2050. totalCodeFaultHF,
  2051. totalCodeFaultTF,
  2052. totalCodeFaultDZF,
  2053. totalCodeFaultCOW);
  2054. break;
  2055. case REPORT_LIST_PROCESS:
  2056. if( FALSE == GetProcessList(strImgName, sortNow) ){
  2057. break;
  2058. }
  2059. if (PtrTotal > 0)
  2060. {
  2061. for (PtrIndex = 0; PtrIndex < PtrTotal; PtrIndex ++)
  2062. {
  2063. pModule = (PMODULE_RECORD) PtrBuffer[PtrIndex].ptrRecord;
  2064. pProcess = pModule->pProcess;
  2065. ASSERT(pProcess);
  2066. if (PtrIndex == 0 || pProcessPrev != pProcess)
  2067. {
  2068. if (PtrIndex != 0)
  2069. {
  2070. OutputTotal(TRUE,
  2071. totalDataFaultHF,
  2072. totalDataFaultTF,
  2073. totalDataFaultDZF,
  2074. totalDataFaultCOW,
  2075. totalCodeFaultHF,
  2076. totalCodeFaultTF,
  2077. totalCodeFaultDZF,
  2078. totalCodeFaultCOW);
  2079. }
  2080. totalDataFaultHF = totalDataFaultTF = totalDataFaultDZF
  2081. = totalDataFaultCOW = totalCodeFaultHF
  2082. = totalCodeFaultTF = totalCodeFaultDZF
  2083. = totalCodeFaultCOW = 0;
  2084. pProcessPrev = pModule->pProcess;
  2085. fprintf(procFile,
  2086. "\nProcess 0x%08x Image: %-20ws\n",
  2087. pProcess->PID, pProcess->ImageName);
  2088. OutputModuleHeader();
  2089. }
  2090. OutputModuleRecord(pModule);
  2091. totalDataFaultHF += pModule->lDataFaultHF;
  2092. totalDataFaultTF += pModule->lDataFaultTF;
  2093. totalDataFaultDZF += pModule->lDataFaultDZF;
  2094. totalDataFaultCOW += pModule->lDataFaultCOW;
  2095. totalCodeFaultHF += pModule->lCodeFaultHF;
  2096. totalCodeFaultTF += pModule->lCodeFaultTF;
  2097. totalCodeFaultDZF += pModule->lCodeFaultDZF;
  2098. totalCodeFaultCOW += pModule->lCodeFaultCOW;
  2099. }
  2100. OutputTotal(TRUE,
  2101. totalDataFaultHF,
  2102. totalDataFaultTF,
  2103. totalDataFaultDZF,
  2104. totalDataFaultCOW,
  2105. totalCodeFaultHF,
  2106. totalCodeFaultTF,
  2107. totalCodeFaultDZF,
  2108. totalCodeFaultCOW);
  2109. }
  2110. break;
  2111. case REPORT_LIST_MODULE:
  2112. if( FALSE == GetModuleList(strImgName, sortNow) ){
  2113. break;
  2114. }
  2115. if (PtrTotal > 0)
  2116. {
  2117. for (PtrIndex = 0; PtrIndex < PtrTotal; PtrIndex ++)
  2118. {
  2119. pModule = (PMODULE_RECORD) PtrBuffer[PtrIndex].ptrRecord;
  2120. if( pModule == NULL ){
  2121. break;
  2122. }
  2123. pProcess = pModule->pProcess;
  2124. ASSERT(pProcess);
  2125. if ( PtrIndex == 0
  2126. || _wcsicmp(Module_Prev, pModule->strModuleName))
  2127. {
  2128. if (PtrIndex != 0)
  2129. {
  2130. OutputTotal(FALSE,
  2131. totalDataFaultHF,
  2132. totalDataFaultTF,
  2133. totalDataFaultDZF,
  2134. totalDataFaultCOW,
  2135. totalCodeFaultHF,
  2136. totalCodeFaultTF,
  2137. totalCodeFaultDZF,
  2138. totalCodeFaultCOW);
  2139. }
  2140. totalDataFaultHF = totalDataFaultTF = totalDataFaultDZF
  2141. = totalDataFaultCOW = totalCodeFaultHF
  2142. = totalCodeFaultTF = totalCodeFaultDZF
  2143. = totalCodeFaultCOW = 0;
  2144. wcscpy(Module_Prev, pModule->strModuleName);
  2145. fprintf(procFile,
  2146. "\nModule Name: %-20ws, BaseAddress: 0x%08x, Size:%10d\n",
  2147. pModule->strModuleName,
  2148. pModule->lBaseAddress,
  2149. pModule->lModuleSize);
  2150. OutputProcessHeader();
  2151. }
  2152. OutputModuleProcessRecord(pProcess, pModule);
  2153. totalDataFaultHF += pModule->lDataFaultHF;
  2154. totalDataFaultTF += pModule->lDataFaultTF;
  2155. totalDataFaultDZF += pModule->lDataFaultDZF;
  2156. totalDataFaultCOW += pModule->lDataFaultCOW;
  2157. totalCodeFaultHF += pModule->lCodeFaultHF;
  2158. totalCodeFaultTF += pModule->lCodeFaultTF;
  2159. totalCodeFaultDZF += pModule->lCodeFaultDZF;
  2160. totalCodeFaultCOW += pModule->lCodeFaultCOW;
  2161. }
  2162. OutputTotal(FALSE,
  2163. totalDataFaultHF,
  2164. totalDataFaultTF,
  2165. totalDataFaultDZF,
  2166. totalDataFaultCOW,
  2167. totalCodeFaultHF,
  2168. totalCodeFaultTF,
  2169. totalCodeFaultDZF,
  2170. totalCodeFaultCOW);
  2171. }
  2172. break;
  2173. }
  2174. Cleanup:
  2175. if (PtrBuffer)
  2176. {
  2177. VirtualFree(PtrBuffer, 0, MEM_RELEASE);
  2178. }
  2179. ASSERT(!ProcessList && !ModuleList);
  2180. }
  2181. /*=============================================================================
  2182. */
  2183. extern PMODULE_RECORD SearchModuleByAddr(
  2184. PLIST_ENTRY pModuleListHead,
  2185. ULONG lAddress);
  2186. extern PMODULE_RECORD SearchSysModule(
  2187. PPROCESS_RECORD pProcess,
  2188. ULONG lAddress,
  2189. BOOLEAN fActive);
  2190. BOOLEAN
  2191. RundownHPFFileList(
  2192. BOOLEAN fRead,
  2193. PLIST_ENTRY pHPFFileListHead
  2194. )
  2195. {
  2196. PLIST_ENTRY pNext = pHPFFileListHead->Flink;
  2197. PHPF_FILE_RECORD pHPFFileRecord;
  2198. PFILE_OBJECT pFileObj;
  2199. PTDISK_RECORD pDiskRecord;
  2200. BOOLEAN fResult = (BOOLEAN)(pNext != pHPFFileListHead);
  2201. while (pNext != pHPFFileListHead)
  2202. {
  2203. pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
  2204. pNext = pNext->Flink;
  2205. pDiskRecord = FindGlobalDiskById(pHPFFileRecord->DiskNumber);
  2206. pFileObj = FindFileInTable(pHPFFileRecord->fDO);
  2207. if (pDiskRecord != NULL) {
  2208. fprintf(procFile, "\t\t%c%04d,%03d,%-8ws,0x%012I64x,%6d,0x%08p\n",
  2209. (fRead) ? ('R') : ('W'),
  2210. pHPFFileRecord->RecordID,
  2211. pHPFFileRecord->DiskNumber,
  2212. pDiskRecord->DiskName,
  2213. pHPFFileRecord->ByteOffset,
  2214. pHPFFileRecord->BytesCount,
  2215. pHPFFileRecord->fDO);
  2216. }
  2217. if (pFileObj && pFileObj->fileRec)
  2218. {
  2219. fprintf(procFile, "\t\t\t%ws\n", pFileObj->fileRec->FileName);
  2220. }
  2221. //else
  2222. //{
  2223. // fprintf(procFile,"\n");
  2224. //}
  2225. }
  2226. return fResult;
  2227. }
  2228. void ReportHardFaultInfo()
  2229. {
  2230. PLIST_ENTRY pProcessHead = & CurrentSystem.ProcessListHead;
  2231. PLIST_ENTRY pProcessNext = pProcessHead->Flink;
  2232. PPROCESS_RECORD pProcess;
  2233. PLIST_ENTRY pHPFHead;
  2234. PLIST_ENTRY pHPFNext;
  2235. PHPF_RECORD pHPF;
  2236. PMODULE_RECORD pModule;
  2237. PLIST_ENTRY pThreadHead;
  2238. PLIST_ENTRY pThreadNext;
  2239. PTHREAD_RECORD pThread;
  2240. BOOLEAN fRecord;
  2241. fprintf(procFile, "\nHardPageFault Rundown Report\n");
  2242. while (pProcessNext != pProcessHead)
  2243. {
  2244. pProcess = CONTAINING_RECORD(pProcessNext, PROCESS_RECORD, Entry);
  2245. pProcessNext = pProcessNext->Flink;
  2246. fprintf(procFile, "-------------------------------------------------------------------------------\n");
  2247. fprintf(procFile, "Process 0x%08x Image: %-20ws\n",
  2248. pProcess->PID, pProcess->ImageName);
  2249. pHPFHead = & pProcess->HPFListHead;
  2250. pHPFNext = pHPFHead->Flink;
  2251. while (pHPFNext != pHPFHead)
  2252. {
  2253. pHPF = CONTAINING_RECORD(pHPFNext, HPF_RECORD, Entry);
  2254. pHPFNext = pHPFNext->Flink;
  2255. fprintf(procFile, "\t%04d,0x%08x,",
  2256. pHPF->RecordID,
  2257. pHPF->lProgramCounter);
  2258. pModule = SearchModuleByAddr(
  2259. & pProcess->ModuleListHead,
  2260. pHPF->lProgramCounter);
  2261. if (pModule)
  2262. {
  2263. fprintf(procFile, "%-16ws,0x%08x,%010d\n",
  2264. pModule->strModuleName,
  2265. pModule->lBaseAddress,
  2266. pModule->lModuleSize);
  2267. }
  2268. else
  2269. {
  2270. fprintf(procFile, "None\n");
  2271. }
  2272. fprintf(procFile, "\t0x%08x,0x%08p,0x%010I64x,",
  2273. pHPF->lFaultAddress,
  2274. pHPF->fDO,
  2275. pHPF->lByteOffset);
  2276. pModule = SearchModuleByAddr(
  2277. & pProcess->ModuleListHead,
  2278. pHPF->lFaultAddress);
  2279. if (!pModule)
  2280. {
  2281. pModule = SearchSysModule(
  2282. pProcess, pHPF->lFaultAddress, FALSE);
  2283. }
  2284. if (pModule)
  2285. {
  2286. fprintf(procFile, "%-16ws,0x%08x,%010d\n",
  2287. pModule->strModuleName,
  2288. pModule->lBaseAddress,
  2289. pModule->lModuleSize);
  2290. }
  2291. else
  2292. {
  2293. fprintf(procFile, "None\n");
  2294. }
  2295. RundownHPFFileList(TRUE, & pHPF->HPFReadListHead);
  2296. fprintf(procFile, "\n");
  2297. }
  2298. pThreadHead = & CurrentSystem.GlobalThreadListHead;
  2299. pThreadNext = pThreadHead->Flink;
  2300. fprintf(procFile, "\tDisk I/O Wite Page Records:\n");
  2301. fRecord = FALSE;
  2302. while (pThreadNext != pThreadHead)
  2303. {
  2304. pThread = CONTAINING_RECORD(pThreadNext, THREAD_RECORD, Entry);
  2305. pThreadNext = pThreadNext->Flink;
  2306. if (pThread->pProcess == pProcess)
  2307. {
  2308. if (RundownHPFFileList(FALSE, & pThread->HPFWriteListHead))
  2309. {
  2310. fRecord = TRUE;
  2311. }
  2312. }
  2313. }
  2314. if (!fRecord)
  2315. {
  2316. fprintf(procFile, "\t\tNone\n");
  2317. }
  2318. pThreadHead = & CurrentSystem.GlobalThreadListHead;
  2319. pThreadNext = pThreadHead->Flink;
  2320. fprintf(procFile, "\tUnresolved Disk I/O Read Page Records:\n");
  2321. fRecord = FALSE;
  2322. while (pThreadNext != pThreadHead)
  2323. {
  2324. pThread = CONTAINING_RECORD(pThreadNext, THREAD_RECORD, Entry);
  2325. pThreadNext = pThreadNext->Flink;
  2326. if (pThread->pProcess == pProcess)
  2327. {
  2328. if (RundownHPFFileList(TRUE, & pThread->HPFReadListHead))
  2329. {
  2330. fRecord = TRUE;
  2331. }
  2332. }
  2333. }
  2334. if (!fRecord)
  2335. {
  2336. fprintf(procFile, "\t\tNone\n");
  2337. }
  2338. }
  2339. fprintf(procFile, "-------------------------------------------------------------------------------\n");
  2340. }
  2341. int __cdecl
  2342. CompareFileRecord(const void * p1, const void * p2)
  2343. {
  2344. PPTR_RECORD pp1 = (PPTR_RECORD) p1;
  2345. PPTR_RECORD pp2 = (PPTR_RECORD) p2;
  2346. PFILE_RECORD pFile1 = (PFILE_RECORD) pp1->ptrRecord;
  2347. PFILE_RECORD pFile2 = (PFILE_RECORD) pp2->ptrRecord;
  2348. LONG diffFault = pp2->keySort - pp1->keySort;
  2349. if (diffFault == 0)
  2350. {
  2351. diffFault = pFile1->DiskNumber - pFile2->DiskNumber;
  2352. if (diffFault == 0)
  2353. {
  2354. diffFault = wcscmp(pFile1->FileName, pFile2->FileName);
  2355. }
  2356. }
  2357. return diffFault;
  2358. }
  2359. void
  2360. ReportHotFileInfo(ULONG NumEntry)
  2361. {
  2362. PLIST_ENTRY pHead = & CurrentSystem.HotFileListHead;
  2363. PLIST_ENTRY pNext = pHead->Flink;
  2364. PFILE_RECORD pFile;
  2365. BOOLEAN fDone = FALSE;
  2366. ASSERT(!PtrBuffer);
  2367. PtrBuffer = (PPTR_RECORD) VirtualAlloc(
  2368. NULL,
  2369. sizeof(PTR_RECORD) * PtrMax,
  2370. MEM_COMMIT,
  2371. PAGE_READWRITE);
  2372. if( NULL == PtrBuffer ){
  2373. goto Cleanup;
  2374. }
  2375. while (!fDone)
  2376. {
  2377. for (PtrTotal = 0, fDone = TRUE;
  2378. pNext != pHead;
  2379. pNext = pNext->Flink)
  2380. {
  2381. if (PtrTotal == PtrMax)
  2382. {
  2383. fDone = FALSE;
  2384. break;
  2385. }
  2386. pFile = CONTAINING_RECORD(pNext, FILE_RECORD, Entry);
  2387. if (pFile->ReadCount + pFile->WriteCount > 0)
  2388. {
  2389. PtrBuffer[PtrTotal].ptrRecord = (PVOID) pFile;
  2390. PtrBuffer[PtrTotal].keySort =
  2391. pFile->ReadCount + pFile->WriteCount;
  2392. PtrTotal ++;
  2393. }
  2394. }
  2395. if (!fDone)
  2396. {
  2397. VirtualFree(PtrBuffer, 0, MEM_RELEASE);
  2398. PtrMax += MAX_LOGS;
  2399. PtrBuffer = (PPTR_RECORD) VirtualAlloc(
  2400. NULL,
  2401. sizeof(PTR_RECORD) * PtrMax,
  2402. MEM_COMMIT,
  2403. PAGE_READWRITE);
  2404. if (PtrBuffer == NULL)
  2405. {
  2406. // fprintf(stderr, "(PDH.DLL) Memory Commit Failure.\n");
  2407. goto Cleanup;
  2408. }
  2409. }
  2410. }
  2411. if (PtrTotal > 1)
  2412. {
  2413. qsort((void *) PtrBuffer,
  2414. (size_t) PtrTotal,
  2415. (size_t) sizeof(PTR_RECORD),
  2416. CompareFileRecord);
  2417. }
  2418. // output HotFile report title
  2419. //
  2420. fprintf(procFile,
  2421. "File Name Read Read Write Write\n");
  2422. fprintf(procFile,
  2423. " Process Information Count Size Count Size\n");
  2424. fprintf(procFile,
  2425. "================================================================================================================================\n");
  2426. PtrTotal = (PtrTotal > NumEntry) ? (NumEntry) : (PtrTotal);
  2427. for (PtrIndex = 0; PtrIndex < PtrTotal; PtrIndex ++)
  2428. {
  2429. PLIST_ENTRY pProtoHead;
  2430. PLIST_ENTRY pProtoNext;
  2431. PPROTO_PROCESS_RECORD pProto;
  2432. pFile = (PFILE_RECORD) PtrBuffer[PtrIndex].ptrRecord;
  2433. fprintf(procFile, "(%04d)%-90ws %5d %8d %5d %8d\n",
  2434. pFile->DiskNumber,
  2435. pFile->FileName,
  2436. pFile->ReadCount,
  2437. pFile->ReadSize,
  2438. pFile->WriteCount,
  2439. pFile->WriteSize);
  2440. pProtoHead = & pFile->ProtoProcessListHead;
  2441. pProtoNext = pProtoHead->Flink;
  2442. while (pProtoNext != pProtoHead)
  2443. {
  2444. pProto = CONTAINING_RECORD(pProtoNext, PROTO_PROCESS_RECORD, Entry);
  2445. pProtoNext = pProtoNext->Flink;
  2446. if (pProto->ReadCount + pProto->WriteCount > 0)
  2447. {
  2448. fprintf(procFile,
  2449. " 0x%08X %-74ws %5d %8d %5d %8d\n",
  2450. pProto->ProcessRecord->PID,
  2451. pProto->ProcessRecord->ImageName,
  2452. pProto->ReadCount,
  2453. pProto->ReadSize,
  2454. pProto->WriteCount,
  2455. pProto->WriteSize);
  2456. }
  2457. }
  2458. fprintf(procFile, "\n");
  2459. }
  2460. fprintf(procFile,
  2461. "================================================================================================================================\n");
  2462. Cleanup:
  2463. if (PtrBuffer)
  2464. {
  2465. VirtualFree(PtrBuffer, 0, MEM_RELEASE);
  2466. }
  2467. }
  2468. #define CHECKTOK( x ) if( NULL == x ) { continue; }
  2469. static void ReportJobInfo2(void)
  2470. {
  2471. JOB_RECORD Job, *pJob;
  2472. char* s;
  2473. char line[MAXSTR];
  2474. ULONG TotalCount = 0;
  2475. ULONGLONG TotalRT = 0;
  2476. ULONG TotalCPUTime = 0;
  2477. pJob = &Job;
  2478. if( NULL == CurrentSystem.TempFile ){
  2479. return;
  2480. }
  2481. rewind( CurrentSystem.TempFile );
  2482. while ( fgets(line, MAXSTR, CurrentSystem.TempFile) != NULL ) {
  2483. s = strtok( line, (","));
  2484. CHECKTOK( s );
  2485. pJob->JobId = atol(s);
  2486. if (pJob == NULL){
  2487. return;
  2488. }
  2489. }
  2490. fprintf(procFile, BREAK_LINE );
  2491. fprintf(procFile,
  2492. "| Spooler Transaction Instance (Job) Data |\n");
  2493. fprintf(procFile, BREAK_LINE );
  2494. fprintf(procFile,
  2495. "| Job Id Type JobSize Pages PPS Files GdiSize Color XRes YRes Qlty Copy TTOpt Threads |\n");
  2496. fprintf(procFile, BREAK_LINE );
  2497. RtlZeroMemory(pJob, sizeof(JOB_RECORD));
  2498. RtlZeroMemory(line, MAXSTR * sizeof(char));
  2499. rewind( CurrentSystem.TempFile );
  2500. while ( fgets(line, MAXSTR, CurrentSystem.TempFile) != NULL ) {
  2501. s = strtok( line, (","));
  2502. CHECKTOK( s );
  2503. pJob->JobId = atol(s);
  2504. if (pJob == NULL){
  2505. continue;
  2506. }
  2507. s = strtok( NULL, (","));
  2508. CHECKTOK( s );
  2509. pJob->KCPUTime = atol(s);
  2510. s = strtok( NULL, (","));
  2511. CHECKTOK( s );
  2512. pJob->UCPUTime = atol(s);
  2513. s = strtok( NULL, (","));
  2514. CHECKTOK( s );
  2515. pJob->ReadIO = atol(s);
  2516. s = strtok( NULL, (","));
  2517. CHECKTOK( s );
  2518. pJob->StartTime = _atoi64(s);
  2519. s = strtok( NULL, (","));
  2520. CHECKTOK( s );
  2521. pJob->EndTime = _atoi64(s);
  2522. s = strtok( NULL, (","));
  2523. CHECKTOK( s );
  2524. pJob->ResponseTime = _atoi64(s);
  2525. s = strtok( NULL, (","));
  2526. CHECKTOK( s );
  2527. pJob->PrintJobTime = _atoi64(s);
  2528. s = strtok( NULL, (","));
  2529. CHECKTOK( s );
  2530. pJob->WriteIO = atol(s);
  2531. s = strtok( NULL, (","));
  2532. CHECKTOK( s );
  2533. pJob->DataType = atol(s);
  2534. s = strtok( NULL, (","));
  2535. CHECKTOK( s );
  2536. pJob->JobSize = atol(s);
  2537. s = strtok( NULL, (","));
  2538. CHECKTOK( s );
  2539. pJob->Pages = atol(s);
  2540. s = strtok( NULL, (","));
  2541. CHECKTOK( s );
  2542. pJob->PagesPerSide = atol(s);
  2543. s = strtok( NULL, (","));
  2544. CHECKTOK( s );
  2545. pJob->FilesOpened = (SHORT) atol(s);
  2546. s = strtok( NULL, (","));
  2547. CHECKTOK( s );
  2548. pJob->GdiJobSize = (SHORT) atol(s);
  2549. s = strtok( NULL, (","));
  2550. CHECKTOK( s );
  2551. pJob->Color = (SHORT) atol(s);
  2552. s = strtok( NULL, (","));
  2553. CHECKTOK( s );
  2554. pJob->XRes = (SHORT) atol(s);
  2555. s = strtok( NULL, (","));
  2556. CHECKTOK( s );
  2557. pJob->YRes = (SHORT) atol(s);
  2558. s = strtok( NULL, (","));
  2559. CHECKTOK( s );
  2560. pJob->Quality = (SHORT) atol(s);
  2561. s = strtok( NULL, (","));
  2562. CHECKTOK( s );
  2563. pJob->Copies = (SHORT) atol(s);
  2564. s = strtok( NULL, (","));
  2565. CHECKTOK( s );
  2566. pJob->TTOption = (SHORT) atol(s);
  2567. s = strtok( NULL, (","));
  2568. CHECKTOK( s );
  2569. pJob->NumberOfThreads = atol(s);
  2570. fprintf(procFile,
  2571. "| %6d %8d %8d %4d %6d %6hd %8d %5hd %4hd %4hd %4hd %6hd %5hd %5d %27s\n",
  2572. pJob->JobId,
  2573. pJob->DataType,
  2574. pJob->JobSize,
  2575. pJob->Pages,
  2576. pJob->PagesPerSide,
  2577. pJob->FilesOpened,
  2578. pJob->GdiJobSize,
  2579. pJob->Color,
  2580. pJob->XRes,
  2581. pJob->YRes,
  2582. pJob->Quality,
  2583. pJob->Copies,
  2584. pJob->TTOption,
  2585. pJob->NumberOfThreads,
  2586. "|"
  2587. );
  2588. }
  2589. fprintf(procFile, BREAK_LINE "\n\n" );
  2590. }
  2591. static void ReportJobInfo(void)
  2592. {
  2593. JOB_RECORD Job, *pJob;
  2594. char* s;
  2595. char line[MAXSTR];
  2596. FILETIME StTm, StlTm;
  2597. LARGE_INTEGER LargeTmp;
  2598. SYSTEMTIME stStart, stEnd, stDequeue;
  2599. ULONG TotalCount = 0;
  2600. ULONGLONG TotalRT = 0;
  2601. ULONG TotalCPUTime = 0;
  2602. if( NULL == CurrentSystem.TempFile ){
  2603. return;
  2604. }
  2605. pJob = &Job;
  2606. rewind( CurrentSystem.TempFile );
  2607. while ( fgets(line, MAXSTR, CurrentSystem.TempFile) != NULL ) {
  2608. s = strtok( line, (","));
  2609. CHECKTOK( s );
  2610. pJob->JobId = atol(s);
  2611. if (pJob == NULL){
  2612. return;
  2613. }
  2614. }
  2615. fprintf(procFile, BREAK_LINE );
  2616. fprintf(procFile,
  2617. "| Transaction Instance (Job) Statistics |\n");
  2618. fprintf(procFile, BREAK_LINE );
  2619. fprintf(procFile,
  2620. "| Job Id StartTime DequeueTime EndTime RespTime CPUTime %60s \n", "|");
  2621. fprintf(procFile, BREAK_LINE );
  2622. RtlZeroMemory(pJob, sizeof(JOB_RECORD));
  2623. RtlZeroMemory(line, MAXSTR * sizeof(char));
  2624. rewind( CurrentSystem.TempFile );
  2625. while ( fgets(line, MAXSTR, CurrentSystem.TempFile) != NULL ) {
  2626. s = strtok( line, (","));
  2627. CHECKTOK( s );
  2628. pJob->JobId = atol(s);
  2629. if (pJob == NULL){
  2630. continue;
  2631. }
  2632. s = strtok( NULL, (","));
  2633. CHECKTOK( s );
  2634. pJob->KCPUTime = atol(s);
  2635. s = strtok( NULL, (","));
  2636. CHECKTOK( s );
  2637. pJob->UCPUTime = atol(s);
  2638. s = strtok( NULL, (","));
  2639. CHECKTOK( s );
  2640. pJob->ReadIO = atol(s);
  2641. s = strtok( NULL, (","));
  2642. CHECKTOK( s );
  2643. pJob->StartTime = _atoi64(s);
  2644. s = strtok( NULL, (","));
  2645. CHECKTOK( s );
  2646. pJob->EndTime = _atoi64(s);
  2647. s = strtok( NULL, (","));
  2648. CHECKTOK( s );
  2649. pJob->ResponseTime = _atoi64(s);
  2650. s = strtok( NULL, (","));
  2651. CHECKTOK( s );
  2652. pJob->PrintJobTime = _atoi64(s);
  2653. s = strtok( NULL, (","));
  2654. CHECKTOK( s );
  2655. pJob->WriteIO = atol(s);
  2656. s = strtok( NULL, (","));
  2657. CHECKTOK( s );
  2658. pJob->DataType = atol(s);
  2659. s = strtok( NULL, (","));
  2660. CHECKTOK( s );
  2661. pJob->JobSize = atol(s);
  2662. s = strtok( NULL, (","));
  2663. CHECKTOK( s );
  2664. pJob->Pages = atol(s);
  2665. s = strtok( NULL, (","));
  2666. CHECKTOK( s );
  2667. pJob->PagesPerSide = atol(s);
  2668. s = strtok( NULL, (","));
  2669. CHECKTOK( s );
  2670. pJob->FilesOpened = (SHORT) atol(s);
  2671. s = strtok( NULL, (","));
  2672. CHECKTOK( s );
  2673. pJob->GdiJobSize = (SHORT) atol(s);
  2674. s = strtok( NULL, (","));
  2675. CHECKTOK( s );
  2676. pJob->Color = (SHORT) atol(s);
  2677. s = strtok( NULL, (","));
  2678. CHECKTOK( s );
  2679. pJob->XRes = (SHORT) atol(s);
  2680. s = strtok( NULL, (","));
  2681. CHECKTOK( s );
  2682. pJob->YRes = (SHORT) atol(s);
  2683. s = strtok( NULL, (","));
  2684. CHECKTOK( s );
  2685. pJob->Quality = (SHORT) atol(s);
  2686. s = strtok( NULL, (","));
  2687. CHECKTOK( s );
  2688. pJob->Copies = (SHORT) atol(s);
  2689. s = strtok( NULL, (","));
  2690. CHECKTOK( s );
  2691. pJob->TTOption = (SHORT) atol(s);
  2692. s = strtok( NULL, (","));
  2693. CHECKTOK( s );
  2694. pJob->NumberOfThreads = atol(s);
  2695. LargeTmp.QuadPart = pJob->StartTime;
  2696. StTm.dwHighDateTime = LargeTmp.HighPart;
  2697. StTm.dwLowDateTime = LargeTmp.LowPart;
  2698. FileTimeToLocalFileTime(&StTm, &StlTm);
  2699. FileTimeToSystemTime (
  2700. &StlTm,
  2701. &stStart
  2702. );
  2703. LargeTmp.QuadPart = pJob->EndTime;
  2704. StTm.dwHighDateTime = LargeTmp.HighPart;
  2705. StTm.dwLowDateTime = LargeTmp.LowPart;
  2706. FileTimeToLocalFileTime(&StTm, &StlTm);
  2707. FileTimeToSystemTime (
  2708. &StlTm,
  2709. &stEnd
  2710. );
  2711. LargeTmp.QuadPart = pJob->PrintJobTime;
  2712. StTm.dwHighDateTime = LargeTmp.HighPart;
  2713. StTm.dwLowDateTime = LargeTmp.LowPart;
  2714. FileTimeToLocalFileTime(&StTm, &StlTm);
  2715. FileTimeToSystemTime (
  2716. &StlTm,
  2717. &stDequeue
  2718. );
  2719. fprintf(procFile,
  2720. "| %4d %2d:%02d:%02d.%03d %2d:%02d:%02d.%03d %2d:%02d:%02d.%03d %6I64u %5d %63s\n",
  2721. pJob->JobId,
  2722. stStart.wHour, stStart.wMinute, stStart.wSecond, stStart.wMilliseconds,
  2723. stDequeue.wHour, stDequeue.wMinute, stDequeue.wSecond, stDequeue.wMilliseconds,
  2724. stEnd.wHour, stEnd.wMinute, stEnd.wSecond, stEnd.wMilliseconds,
  2725. pJob->ResponseTime,
  2726. pJob->KCPUTime + pJob->UCPUTime,
  2727. "|"
  2728. );
  2729. TotalCount++;
  2730. TotalRT += pJob->ResponseTime;
  2731. TotalCPUTime += (pJob->KCPUTime + pJob->UCPUTime);
  2732. }
  2733. if (TotalCount > 0) {
  2734. TotalRT /= TotalCount;
  2735. TotalCPUTime /= TotalCount;
  2736. }
  2737. fprintf(procFile, BREAK_LINE );
  2738. fprintf(procFile,
  2739. "| %4d %6I64u %5d %63s\n",
  2740. TotalCount, TotalRT, TotalCPUTime, "|");
  2741. fprintf(procFile, BREAK_LINE "\n\n" );
  2742. ReportJobInfo2();
  2743. }
  2744. void
  2745. WriteSummary()
  2746. {
  2747. FILE* SummaryFile;
  2748. PLIST_ENTRY Head, Next;
  2749. PMOF_INFO pMofInfo;
  2750. ULONG i;
  2751. FILETIME StTm, StlTm;
  2752. LARGE_INTEGER LargeTmp;
  2753. SYSTEMTIME tmf, emf;
  2754. BOOL bResult;
  2755. if( NULL == TraceContext->SummaryFileName ){
  2756. return;
  2757. }
  2758. if( 0 == TotalEventCount ){
  2759. return;
  2760. }
  2761. SummaryFile = _wfopen( TraceContext->SummaryFileName, L"w" );
  2762. if (SummaryFile == NULL){
  2763. return;
  2764. }
  2765. fwprintf(SummaryFile,L"Files Processed:\n");
  2766. for (i=0; i<TraceContext->LogFileCount; i++) {
  2767. fwprintf(SummaryFile,L"\t%s\n",TraceContext->LogFileName[i]);
  2768. }
  2769. LargeTmp.QuadPart = StartTime;
  2770. StTm.dwHighDateTime = LargeTmp.HighPart;
  2771. StTm.dwLowDateTime = LargeTmp.LowPart;
  2772. FileTimeToLocalFileTime(&StTm, &StlTm);
  2773. bResult = FileTimeToSystemTime (
  2774. &StlTm,
  2775. &tmf
  2776. );
  2777. if ( !bResult || tmf.wMonth > 12) {
  2778. ZeroMemory( &tmf, sizeof(SYSTEMTIME) );
  2779. }
  2780. LargeTmp.QuadPart = EndTime;
  2781. StTm.dwHighDateTime = LargeTmp.HighPart;
  2782. StTm.dwLowDateTime = LargeTmp.LowPart;
  2783. FileTimeToLocalFileTime(&StTm, &StlTm);
  2784. bResult = FileTimeToSystemTime (
  2785. &StlTm,
  2786. &emf
  2787. );
  2788. if ( !bResult ) {
  2789. ZeroMemory( &emf, sizeof(SYSTEMTIME) );
  2790. }
  2791. ElapseTime = EndTime - StartTime;
  2792. fwprintf(SummaryFile,
  2793. L"Total Buffers Processed %d\n"
  2794. L"Total Events Processed %d\n"
  2795. L"Total Events Lost %d\n"
  2796. L"Start Time %2d %3S %4d %2d:%02d:%02d.%03d\n"
  2797. L"End Time %2d %3S %4d %2d:%02d:%02d.%03d\n"
  2798. L"Elapsed Time %I64d sec\n",
  2799. TotalBuffersRead,
  2800. TotalEventCount,
  2801. TotalEventsLost,
  2802. tmf.wDay, Month[tmf.wMonth], tmf.wYear, tmf.wHour, tmf.wMinute, tmf.wSecond, tmf.wMilliseconds,
  2803. emf.wDay, Month[emf.wMonth], emf.wYear,emf.wHour, emf.wMinute, emf.wSecond, emf.wMilliseconds,
  2804. (ElapseTime / 10000000) );
  2805. fwprintf(SummaryFile,
  2806. L"+-------------------------------------------------------------------------------------+\n"
  2807. L"|%10s %-20s %-10s %-38s|\n"
  2808. L"+-------------------------------------------------------------------------------------+\n",
  2809. L"Event Count",
  2810. L"Event Name",
  2811. L"Event Type",
  2812. L"Guid"
  2813. );
  2814. Head = &CurrentSystem.EventListHead;
  2815. Next = Head->Flink;
  2816. while (Head != Next) {
  2817. WCHAR wstr[MAXSTR];
  2818. PWCHAR str;
  2819. WCHAR s[64];
  2820. PLIST_ENTRY vHead, vNext;
  2821. PMOF_VERSION pMofVersion;
  2822. RtlZeroMemory(&wstr, MAXSTR);
  2823. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  2824. Next = Next->Flink;
  2825. if (pMofInfo->EventCount > 0) {
  2826. str = CpdiGuidToString(&s[0], (LPGUID)&pMofInfo->Guid);
  2827. if( pMofInfo->strDescription != NULL ){
  2828. wcscpy( wstr, pMofInfo->strDescription );
  2829. }
  2830. //
  2831. // Get event count by type from MOF_VERSION structure
  2832. //
  2833. vHead = &pMofInfo->VersionHeader;
  2834. vNext = vHead->Flink;
  2835. while (vHead != vNext) {
  2836. pMofVersion = CONTAINING_RECORD(vNext, MOF_VERSION, Entry);
  2837. vNext = vNext->Flink;
  2838. if (pMofVersion->EventCountByType != 0) {
  2839. fwprintf(SummaryFile,L"| %10d %-20s %-10s %38s|\n",
  2840. pMofVersion->EventCountByType,
  2841. wstr,
  2842. pMofVersion->strType ? pMofVersion->strType : GUID_TYPE_DEFAULT,
  2843. str);
  2844. }
  2845. }
  2846. }
  2847. }
  2848. fwprintf(SummaryFile,
  2849. L"+-------------------------------------------------------------------------------------+\n"
  2850. );
  2851. fclose( SummaryFile );
  2852. }