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.

5754 lines
176 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. callbacks.c
  5. Abstract:
  6. Setting up and handling the callbacks for the events from the
  7. trace file.
  8. Author:
  9. Melur Raghuraman (mraghu) 03-Oct-1997
  10. Environment:
  11. Revision History:
  12. Insung Park (insungp) 05-Jan-2001
  13. Updated DumpEvent() so that by default, it searches WBEM namespace
  14. for the event data layout information.
  15. Functions added/modified: GetArraySize, GetItemType,
  16. GetPropertiesFromWBEM, GetGuidsWbem, GetGuidsFile, and GetGuids.
  17. Insung Park (insungp) 16-Jan-2001
  18. Changes enabling tracerpt to handle an invalid type name array in the WBEM namespace.
  19. Bug fixes for memory corruption (GetPropertiesFromWBEM and GetGuidsWBEM).
  20. --*/
  21. #ifdef __cplusplus
  22. extern "C"{
  23. #endif
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include "cpdata.h"
  28. #include <wbemidl.h>
  29. #include "tracectr.h"
  30. #include "item.h"
  31. #include "guids.h"
  32. #define BUFFER_SIZE 64*1024
  33. #define MAX_BUFFER_SIZE 10*1024*1024
  34. #define MOFWSTR 16360
  35. #define MOFSTR 32720
  36. #define MAXTYPE 256
  37. #define UC(x) ( (UINT)((x) & 0xFF) )
  38. #define NTOHS(x) ( (UC(x) * 256) + UC((x) >> 8) )
  39. //
  40. // IRP Flags from ntos\inc\io.h for Io event processing.
  41. //
  42. #define IRP_NOCACHE 0x00000001
  43. #define IRP_PAGING_IO 0x00000002
  44. #define IRP_SYNCHRONOUS_API 0x00000004
  45. #define IRP_ASSOCIATED_IRP 0x00000008
  46. #define IRP_BUFFERED_IO 0x00000010
  47. #define IRP_DEALLOCATE_BUFFER 0x00000020
  48. #define IRP_SYNCHRONOUS_PAGING_IO 0x00000040
  49. #define IRP_CREATE_OPERATION 0x00000080
  50. #define IRP_READ_OPERATION 0x00000100
  51. #define IRP_WRITE_OPERATION 0x00000200
  52. #define IRP_CLOSE_OPERATION 0x00000400
  53. #define IRP_DEFER_IO_COMPLETION 0x00000800
  54. #define IRP_OB_QUERY_NAME 0x00001000
  55. #define IRP_HOLD_DEVICE_QUEUE 0x00002000
  56. int IdleEndCount = 0;
  57. ULONG PageFaultCount = 0;
  58. ULONG EventCount = 0;
  59. #define EVENT_TRACE_TYPE_SPL_SPOOLJOB EVENT_TRACE_TYPE_START
  60. #define EVENT_TRACE_TYPE_SPL_PRINTJOB EVENT_TRACE_TYPE_DEQUEUE
  61. #define EVENT_TRACE_TYPE_SPL_DELETEJOB EVENT_TRACE_TYPE_END
  62. #define EVENT_TRACE_TYPE_SPL_TRACKTHREAD EVENT_TRACE_TYPE_CHECKPOINT
  63. #define EVENT_TRACE_TYPE_SPL_ENDTRACKTHREAD 0x0A
  64. #define EVENT_TRACE_TYPE_SPL_JOBRENDERED 0x0B
  65. #define EVENT_TRACE_TYPE_SPL_PAUSE 0x0C
  66. #define EVENT_TRACE_TYPE_SPL_RESUME 0x0D
  67. extern PTRACE_CONTEXT_BLOCK TraceContext;
  68. extern ULONG TotalBuffersRead;
  69. ULONG HPFReadCount = 0;
  70. ULONG HPFWriteCount = 0;
  71. ULONG TotalEventsLost = 0;
  72. ULONG TotalEventCount = 0;
  73. ULONG TimerResolution = 10;
  74. ULONGLONG StartTime = 0;
  75. ULONGLONG EndTime = 0;
  76. BOOL fNoEndTime = FALSE;
  77. __int64 ElapseTime;
  78. PCHAR MofData = NULL;
  79. size_t MofLength = 0;
  80. BOOLEAN fIgnorePerfClock = FALSE;
  81. BOOLEAN fRealTimeCircular = FALSE;
  82. ULONG PointerSize = sizeof(PVOID) * 8;
  83. BOOL g_bUserMode = FALSE;
  84. static ULONG NumProc = 0;
  85. ULONGLONG BogusThreads[64];
  86. ULONG BogusCount=0;
  87. ULONG IdleThreadCount=0;
  88. BOOLEAN bCaptureBogusThreads=TRUE;
  89. IWbemServices *pWbemServices = NULL;
  90. void AnsiToUnicode(PCHAR str, PWCHAR wstr);
  91. ULONG
  92. ahextoi( WCHAR *s);
  93. PMOF_VERSION
  94. GetGuids( GUID Guid, SHORT nVersion, CHAR nLevel, SHORT nType, BOOL bKernelEvent );
  95. HRESULT
  96. WbemConnect( IWbemServices** pWbemServices );
  97. ULONG GetArraySize(
  98. IN IWbemQualifierSet *pQualSet
  99. );
  100. ITEM_TYPE
  101. GetItemType(
  102. IN CIMTYPE_ENUMERATION CimType,
  103. IN IWbemQualifierSet *pQualSet
  104. );
  105. PMOF_VERSION
  106. GetPropertiesFromWBEM(
  107. IWbemClassObject *pTraceSubClasses,
  108. GUID Guid,
  109. SHORT nVersion,
  110. CHAR nLevel,
  111. SHORT nType,
  112. BOOL bKernelEvent
  113. );
  114. PMOF_VERSION
  115. GetGuidsWBEM (
  116. GUID Guid,
  117. SHORT nVersion,
  118. CHAR nLevel,
  119. SHORT nType,
  120. BOOL bKernelEvent
  121. );
  122. PMOF_VERSION
  123. GetGuidsFile(
  124. GUID Guid,
  125. SHORT nVersion,
  126. CHAR nLevel,
  127. SHORT nType,
  128. BOOL bKernelEvent
  129. );
  130. VOID
  131. EventCallback(
  132. PEVENT_TRACE pEvent,
  133. PTHREAD_RECORD pThread
  134. );
  135. VOID
  136. AddMofInfo(
  137. PLIST_ENTRY List,
  138. LPWSTR strType,
  139. SHORT nType,
  140. UINT ArraySize
  141. );
  142. VOID
  143. UpdateThreadData(
  144. PJOB_RECORD pJob,
  145. PEVENT_TRACE_HEADER pHeader,
  146. PTHREAD_RECORD pThread
  147. );
  148. VOID
  149. PrintJobCallback(
  150. PEVENT_TRACE pEvent
  151. );
  152. void
  153. WINAPI
  154. DumpEvent(
  155. PEVENT_TRACE pEvent
  156. );
  157. void
  158. DumpMofVersionItem(
  159. PMOF_VERSION pMofVersion
  160. );
  161. extern PWCHAR CpdiGuidToString(PWCHAR s, LPGUID piid);
  162. ULONG Interpolate(ULONGLONG timeStart, ULONG deltaStart,
  163. ULONGLONG timeEnd, ULONG deltaEnd,
  164. ULONGLONG timeMiddle)
  165. {
  166. return deltaStart
  167. + (deltaEnd - deltaStart) * ((ULONG) (timeMiddle - timeStart))
  168. / ((ULONG) (timeEnd - timeStart));
  169. }
  170. BOOLEAN
  171. InTimeWindow(
  172. PEVENT_TRACE pEvent,
  173. PTHREAD_RECORD pThread
  174. )
  175. {
  176. PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER) & pEvent->Header;
  177. BOOLEAN fResult = (pThread) ? (TRUE) : (FALSE);
  178. if (fResult && fDSOnly)
  179. {
  180. if ( ((ULONGLONG) pHeader->TimeStamp.QuadPart < DSStartTime)
  181. || ((ULONGLONG) pHeader->TimeStamp.QuadPart > DSEndTime))
  182. {
  183. fResult = FALSE;
  184. }
  185. }
  186. return fResult;
  187. }
  188. VOID
  189. AdjustThreadTime(
  190. PEVENT_TRACE pEvent,
  191. PTHREAD_RECORD pThread
  192. )
  193. {
  194. PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER) & pEvent->Header;
  195. if (IsEqualGUID(&pHeader->Guid, &EventTraceGuid))
  196. {
  197. return;
  198. }
  199. else if (!pThread || pThread->DeadFlag)
  200. {
  201. return;
  202. }
  203. else if (fDSOnly)
  204. {
  205. if ( ((ULONGLONG) pHeader->TimeStamp.QuadPart >= DSStartTime)
  206. && ((ULONGLONG) pHeader->TimeStamp.QuadPart <= DSEndTime))
  207. {
  208. if (pThread->TimeStart < DSStartTime)
  209. {
  210. pThread->TimeStart = DSStartTime;
  211. pThread->KCPUStart = Interpolate(
  212. pThread->TimeEnd, pThread->KCPUStart,
  213. pHeader->TimeStamp.QuadPart, pHeader->KernelTime,
  214. DSStartTime);
  215. pThread->UCPUStart = Interpolate(
  216. pThread->TimeEnd, pThread->UCPUStart,
  217. pHeader->TimeStamp.QuadPart, pHeader->UserTime,
  218. DSStartTime);
  219. }
  220. pThread->KCPUEnd = pHeader->KernelTime;
  221. pThread->UCPUEnd = pHeader->UserTime;
  222. pThread->TimeEnd = (ULONGLONG)pHeader->TimeStamp.QuadPart;
  223. }
  224. else if ((ULONGLONG) pHeader->TimeStamp.QuadPart < DSStartTime)
  225. {
  226. pThread->TimeStart = pThread->TimeEnd
  227. = (ULONGLONG) pHeader->TimeStamp.QuadPart;
  228. pThread->KCPUStart = pThread->KCPUEnd = pHeader->KernelTime;
  229. pThread->UCPUStart = pThread->UCPUEnd = pHeader->UserTime;
  230. }
  231. else if ((ULONGLONG) pHeader->TimeStamp.QuadPart > DSEndTime)
  232. {
  233. if (pThread->TimeEnd < DSEndTime)
  234. {
  235. if (pThread->TimeEnd < DSStartTime)
  236. {
  237. pThread->KCPUStart = Interpolate(
  238. pThread->TimeEnd, pThread->KCPUStart,
  239. pHeader->TimeStamp.QuadPart, pHeader->KernelTime,
  240. DSStartTime);
  241. pThread->UCPUStart = Interpolate(
  242. pThread->TimeEnd, pThread->UCPUStart,
  243. pHeader->TimeStamp.QuadPart, pHeader->UserTime,
  244. DSStartTime);
  245. pThread->TimeStart = DSStartTime;
  246. }
  247. pThread->KCPUEnd = Interpolate(
  248. pThread->TimeEnd, pThread->KCPUEnd,
  249. pHeader->TimeStamp.QuadPart, pHeader->KernelTime,
  250. DSEndTime);
  251. pThread->UCPUEnd = Interpolate(
  252. pThread->TimeEnd, pThread->UCPUEnd,
  253. pHeader->TimeStamp.QuadPart, pHeader->UserTime,
  254. DSEndTime);
  255. pThread->TimeEnd = DSEndTime;
  256. }
  257. }
  258. }
  259. else
  260. {
  261. pThread->TimeEnd = pHeader->TimeStamp.QuadPart;
  262. if (pThread->KCPUEnd <= pHeader->KernelTime)
  263. pThread->KCPUEnd = pHeader->KernelTime;
  264. if (pThread->UCPUEnd <= pHeader->UserTime)
  265. pThread->UCPUEnd = pHeader->UserTime;
  266. }
  267. }
  268. //
  269. // This routine allocates a new MOF_VERSION entry for
  270. // the given type, version and Level.
  271. //
  272. PMOF_VERSION
  273. GetNewMofVersion( SHORT nType, SHORT nVersion, CHAR nLevel )
  274. {
  275. PMOF_VERSION pMofVersion = NULL;
  276. pMofVersion = (PMOF_VERSION)malloc(sizeof(MOF_VERSION));
  277. if( NULL == pMofVersion ){
  278. return NULL;
  279. }
  280. RtlZeroMemory(pMofVersion, sizeof(MOF_VERSION));
  281. InitializeListHead(&pMofVersion->ItemHeader);
  282. pMofVersion->TypeIndex = nType;
  283. pMofVersion->Level = nLevel;
  284. pMofVersion->Version = nVersion;
  285. return pMofVersion;
  286. }
  287. static void reduceA(char *Src)
  288. {
  289. char *Start = Src;
  290. if (!Src)
  291. return;
  292. while (*Src)
  293. {
  294. if ('\t' == *Src)
  295. *Src = ' ';
  296. else if (',' == *Src)
  297. *Src = ' ';
  298. else if ('\n' == *Src)
  299. *Src = ',';
  300. else if ('\r' == *Src)
  301. *Src = ' ';
  302. ++Src;
  303. }
  304. --Src;
  305. while ((Start < Src) && ((' ' == *Src) || (',' == *Src)))
  306. {
  307. *Src = 0x00;
  308. --Src;
  309. }
  310. }
  311. static void reduceW(WCHAR *Src)
  312. {
  313. WCHAR *Start = Src;
  314. if (!Src)
  315. return;
  316. while (*Src)
  317. {
  318. if (L'\t' == *Src)
  319. *Src = L' ';
  320. else if (L',' == *Src)
  321. *Src = L' ';
  322. else if (L'\n' == *Src)
  323. *Src = L',';
  324. else if (L'\r' == *Src)
  325. *Src = L' ';
  326. ++Src;
  327. }
  328. --Src;
  329. while ((Start < Src) && ((L' ' == *Src) || (L',' == *Src)))
  330. {
  331. *Src = 0x00;
  332. --Src;
  333. }
  334. }
  335. //
  336. // Given a GUID, return a MOF_INFO
  337. //
  338. PMOF_INFO
  339. GetMofInfoHead(
  340. LPCGUID pGuid
  341. )
  342. {
  343. PLIST_ENTRY Head, Next;
  344. PMOF_INFO pMofInfo;
  345. PLIST_ENTRY EventListHead;
  346. if (pGuid == NULL)
  347. return NULL;
  348. // Search the eventList for this Guid and find the head
  349. //
  350. //
  351. // Traverse the list and look for the Mof info head for this Guid.
  352. EventListHead = &CurrentSystem.EventListHead;
  353. Head = EventListHead;
  354. Next = Head->Flink;
  355. while (Head != Next) {
  356. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  357. if (IsEqualGUID(&pMofInfo->Guid, pGuid)) {
  358. return pMofInfo;
  359. }
  360. Next = Next->Flink;
  361. }
  362. //
  363. // If not found, add a new entry for this GUID
  364. //
  365. pMofInfo = (PMOF_INFO)malloc(sizeof(MOF_INFO));
  366. if (pMofInfo == NULL) {
  367. return NULL;
  368. }
  369. memset (pMofInfo, 0, sizeof(MOF_INFO));
  370. pMofInfo->Guid = *pGuid;
  371. InitializeListHead(&pMofInfo->VersionHeader);
  372. InitializeListHead(&pMofInfo->DataListHead);
  373. InsertTailList(EventListHead, &pMofInfo->Entry);
  374. return pMofInfo;
  375. }
  376. //
  377. // Locate the mof version information for the given guid
  378. //
  379. PMOF_VERSION
  380. GetMofVersion(
  381. PMOF_INFO pMofInfo,
  382. SHORT nType,
  383. SHORT nVersion,
  384. CHAR nLevel
  385. )
  386. {
  387. PLIST_ENTRY Head, Next;
  388. SHORT nMatchLevel = 0;
  389. SHORT nMatchCheck = 0;
  390. PMOF_VERSION pMofVersion = NULL;
  391. PMOF_VERSION pBestMatch = NULL;
  392. if (pMofInfo == NULL)
  393. return NULL;
  394. //
  395. // Traverse the list and look for the Mof info head for this Guid.
  396. Head = &pMofInfo->VersionHeader;
  397. Next = Head->Flink;
  398. while (Head != Next) {
  399. nMatchCheck = 0;
  400. pMofVersion = CONTAINING_RECORD(Next, MOF_VERSION, Entry);
  401. Next = Next->Flink;
  402. if( pMofVersion->TypeIndex == nType ){
  403. nMatchCheck++;
  404. }
  405. if( pMofVersion->Level == nLevel ){
  406. nMatchCheck++;
  407. }
  408. if( pMofVersion->Version == nVersion ){
  409. nMatchCheck++;
  410. }
  411. if( nMatchCheck == 3 ){ // Exact Match
  412. return pMofVersion;
  413. }
  414. if( nMatchCheck > nMatchLevel ){ // Close Match
  415. nMatchLevel = nMatchCheck;
  416. pBestMatch = pMofVersion;
  417. }
  418. if( pMofVersion->TypeIndex == EVENT_TYPE_DEFAULT && // Total Guess
  419. pBestMatch == NULL ){
  420. pBestMatch = pMofVersion;
  421. }
  422. }
  423. if (pBestMatch != NULL) {
  424. return pBestMatch;
  425. }
  426. //
  427. // If One does not exist, look it up in the file.
  428. //
  429. pMofVersion = GetGuids( pMofInfo->Guid, nVersion, nLevel, nType, 0 );
  430. // If still not found, create a unknown place holder
  431. if( NULL == pMofVersion ){
  432. pMofVersion = GetNewMofVersion( nType, nVersion, nLevel );
  433. if( pMofVersion != NULL ){
  434. InsertTailList( &pMofInfo->VersionHeader, &pMofVersion->Entry );
  435. if (nType == EVENT_TRACE_TYPE_INFO) {
  436. LPWSTR szHeader = L"Header";
  437. pMofVersion->strType = (PWCHAR)malloc((lstrlenW(szHeader)+1)*sizeof(WCHAR));
  438. if( pMofVersion->strType != NULL ){
  439. wcscpy( pMofVersion->strType, szHeader);
  440. }
  441. }
  442. }
  443. }
  444. return pMofVersion;
  445. }
  446. //
  447. // This routine adds a ITEM_DESC entry to all the MOF_VERSION
  448. // structures in the List
  449. //
  450. VOID
  451. AddMofInfo(
  452. PLIST_ENTRY List,
  453. LPWSTR strType,
  454. SHORT nType,
  455. UINT ArraySize
  456. )
  457. {
  458. PITEM_DESC pItem;
  459. PMOF_VERSION pMofVersion;
  460. PLIST_ENTRY Head = List;
  461. PLIST_ENTRY Next = Head->Flink;
  462. //
  463. // Traverse through the list of MOF_VERSIONS
  464. //
  465. while (Head != Next) {
  466. pMofVersion = CONTAINING_RECORD(Next, MOF_VERSION, Entry);
  467. Next = Next->Flink;
  468. if( NULL != pMofVersion ){
  469. //
  470. // ALLOCATE a new ITEM_DESC for the given type
  471. //
  472. pItem = (PITEM_DESC) malloc(sizeof(ITEM_DESC));
  473. if( NULL == pItem ){
  474. return;
  475. }
  476. ZeroMemory( pItem, sizeof(ITEM_DESC) );
  477. pItem->ItemType = (ITEM_TYPE)nType;
  478. pItem->ArraySize = ArraySize;
  479. // All standard datatypes with fixed sizes will be filled here.
  480. switch (nType) {
  481. case ItemChar :
  482. case ItemUChar : pItem->DataSize = sizeof (char); break;
  483. case ItemCharHidden : pItem->DataSize = sizeof (char); break;
  484. case ItemBool : pItem->DataSize = sizeof (BOOL); break;
  485. case ItemWChar : pItem->DataSize = sizeof (WCHAR); break;
  486. case ItemShort :
  487. case ItemPort :
  488. case ItemUShort : pItem->DataSize = sizeof (short); break;
  489. case ItemPtr : pItem->DataSize = PointerSize / 8; break; // BUG when two files (Win64 & Win32) are used.
  490. case ItemLong :
  491. case ItemIPAddr :
  492. case ItemCPUTime :
  493. case ItemULong :
  494. case ItemULongX : pItem->DataSize = sizeof (ULONG); break;
  495. case ItemGuid : pItem->DataSize = sizeof(GUID); break;
  496. case ItemLongLong :
  497. case ItemULongLong : pItem->DataSize = sizeof (__int64); break;
  498. case ItemChar4 : pItem->DataSize = sizeof(char) * 4; break;
  499. case ItemOptArgs :
  500. default : pItem->DataSize = 0;
  501. }
  502. pItem->strDescription = (PWCHAR) malloc( ( lstrlenW(strType)+1)*sizeof(WCHAR));
  503. if( NULL == pItem->strDescription ){
  504. free( pItem );
  505. return;
  506. }
  507. wcscpy(pItem->strDescription, strType);
  508. //
  509. // Insert the new entry into the ItemHeader list for
  510. // this Version, Type, Level combination
  511. //
  512. InsertTailList( &(pMofVersion->ItemHeader), &pItem->Entry);
  513. }
  514. }
  515. }
  516. VOID
  517. DeclareKernelEvents()
  518. {
  519. PMOF_VERSION pMofVersion;
  520. pMofVersion = GetGuids(FileIoGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  521. pMofVersion = GetGuids(DiskIoGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  522. pMofVersion = GetGuids(PageFaultGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  523. pMofVersion = GetGuids(ProcessGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  524. pMofVersion = GetGuids(ImageLoadGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  525. pMofVersion = GetGuids(ThreadGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  526. pMofVersion = GetGuids(TcpIpGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  527. pMofVersion = GetGuids(UdpIpGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  528. pMofVersion = GetGuids(EventTraceConfigGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  529. pMofVersion = GetGuids(RegistryGuid, EVENT_TYPE_DEFAULT, EVENT_VERSION_DEFAULT, EVENT_LEVEL_DEFAULT, TRUE);
  530. pMofVersion = GetGuids(EventTraceGuid, 0, 0, EVENT_TRACE_TYPE_INFO, TRUE);
  531. }
  532. VOID
  533. LogHeaderCallback(
  534. PEVENT_TRACE pEvent
  535. )
  536. {
  537. PEVENT_TRACE_HEADER pHeader;
  538. ULONG BuildNumber;
  539. PPROCESS_FILE_RECORD pFileRec;
  540. PTRACE_LOGFILE_HEADER pEvmInfo;
  541. if (pEvent == NULL)
  542. return;
  543. pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  544. if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_GUIDMAP) {
  545. return;
  546. }
  547. BuildNumber = ((PTRACE_LOGFILE_HEADER)pEvent->MofData)->ProviderVersion;
  548. BuildNumber &= (0xFAFFFFFF);
  549. CurrentSystem.BuildNumber = BuildNumber;
  550. pEvmInfo = (PTRACE_LOGFILE_HEADER) pEvent->MofData;
  551. CurrentSystem.TimerResolution = pEvmInfo->TimerResolution / 10000;
  552. CurrentSystem.NumberOfProcessors = pEvmInfo->NumberOfProcessors;
  553. //
  554. // If Multiple files are given, use the values from the first file.
  555. //
  556. if (NumProc == 0) {
  557. NumProc = pEvmInfo->NumberOfProcessors;
  558. RtlZeroMemory(&BogusThreads, 64*sizeof(ULONG));
  559. }
  560. //
  561. // With Multiple LogFiles always take the largest time window
  562. //
  563. if ((CurrentSystem.StartTime == (ULONGLONG) 0) ||
  564. ((ULONGLONG)pHeader->TimeStamp.QuadPart < CurrentSystem.StartTime))
  565. CurrentSystem.StartTime = pHeader->TimeStamp.QuadPart;
  566. if (DSStartTime == 0)
  567. DSStartTime = CurrentSystem.StartTime;
  568. if (fDSOnly && CurrentSystem.StartTime < DSStartTime)
  569. CurrentSystem.StartTime = DSStartTime;
  570. if ((CurrentSystem.EndTime == (ULONGLONG)0) ||
  571. (CurrentSystem.EndTime < (ULONGLONG)pEvmInfo->EndTime.QuadPart))
  572. CurrentSystem.EndTime = pEvmInfo->EndTime.QuadPart;
  573. if (CurrentSystem.EndTime == 0) {
  574. CurrentSystem.fNoEndTime = TRUE;
  575. }
  576. if (DSEndTime == 0)
  577. DSEndTime = CurrentSystem.EndTime;
  578. if (fDSOnly && CurrentSystem.EndTime > DSEndTime)
  579. CurrentSystem.EndTime = DSEndTime;
  580. pFileRec = (PPROCESS_FILE_RECORD)malloc(sizeof(PROCESS_FILE_RECORD));
  581. if( pFileRec != NULL ){
  582. // Temporary... WMI Should dereference ->LogFileName
  583. LPWSTR pName = (LPWSTR)pEvmInfo;
  584. pName = (LPWSTR)((PCHAR)pName + sizeof( TRACE_LOGFILE_HEADER ));
  585. pFileRec->TraceName = (LPWSTR)malloc( ( lstrlenW( pName )+1 )*sizeof(WCHAR) );
  586. if( pFileRec->TraceName != NULL ){
  587. wcscpy( pFileRec->TraceName, pName );
  588. }
  589. pName += lstrlenW( pName ) + 1;
  590. pFileRec->FileName = (LPWSTR)malloc( ( lstrlenW( pName )+1 )*sizeof(WCHAR) );
  591. if( pFileRec->FileName != NULL ){
  592. wcscpy( pFileRec->FileName, pName );
  593. }
  594. pFileRec->StartTime = pHeader->TimeStamp.QuadPart;
  595. pFileRec->EndTime = pEvmInfo->EndTime.QuadPart;
  596. InsertTailList( &CurrentSystem.ProcessFileListHead, &pFileRec->Entry );
  597. }
  598. }
  599. VOID
  600. IoWriteCallback(
  601. PEVENT_TRACE pEvent,
  602. PTHREAD_RECORD pThread
  603. )
  604. {
  605. PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  606. ULONG DiskNumber= 0;
  607. ULONG BytesWrite=0;
  608. PTDISK_RECORD Disk;
  609. PPROCESS_RECORD pProcess, pDiskProcess;
  610. PPROTO_PROCESS_RECORD pProto;
  611. PFILE_OBJECT fileObj;
  612. PFILE_RECORD pProcFile;
  613. PVOID fDO = NULL;
  614. ULONG IrpFlags = 0;
  615. LONGLONG ByteOffset = 0;
  616. ULONG pFlag = FALSE;
  617. BOOLEAN fValidWrite = (BOOLEAN) (!fDSOnly ||
  618. ( ((ULONGLONG) pHeader->TimeStamp.QuadPart >= DSStartTime)
  619. && ((ULONGLONG) pHeader->TimeStamp.QuadPart <= DSEndTime)));
  620. GetMofData(pEvent, L"DiskNumber", &DiskNumber, sizeof(ULONG));
  621. GetMofData(pEvent, L"IrpFlags", &IrpFlags, sizeof(ULONG));
  622. GetMofData(pEvent, L"TransferSize", &BytesWrite, sizeof(ULONG));
  623. GetMofData(pEvent, L"FileObject", &fDO, sizeof(ULONG));
  624. GetMofData(pEvent, L"ByteOffset", &ByteOffset, sizeof(LONGLONG));
  625. if (((IrpFlags & IRP_PAGING_IO) != 0) ||
  626. ((IrpFlags & IRP_SYNCHRONOUS_PAGING_IO) != 0)) {
  627. pFlag = TRUE;
  628. }
  629. if ((Disk = FindGlobalDiskById(DiskNumber)) == NULL) {
  630. if ( !AddDisk(DiskNumber, &Disk) ) {
  631. return;
  632. }
  633. }
  634. BytesWrite /= 1024; // Convert to Kbytes.
  635. if (fValidWrite)
  636. {
  637. Disk->WriteCount++;
  638. Disk->WriteSize += BytesWrite;
  639. }
  640. if (pThread == NULL) {
  641. //
  642. // Logger Thread Creation is MISSED by the collector.
  643. // Also, thread creation between process rundown code (UserMode) and
  644. // logger thread start (kernel mode) are missed.
  645. // So we must handle it here.
  646. //
  647. if (AddThread( pHeader->ThreadId, pEvent, &pThread )) {
  648. /*
  649. #if DBG
  650. DbgPrint("WARNING(%d): Thread %x added to charge IO Write event.\n",
  651. EventCount, pHeader->ThreadId);
  652. #endif
  653. */
  654. pThread->pProcess = FindProcessById(0, TRUE); // Charge it the system ???
  655. pThread->TimeStart = pHeader->TimeStamp.QuadPart;
  656. pThread->fOrphan = TRUE;
  657. //
  658. // Note: All ThreadStart record at the start of data collection
  659. // have the same TID in the header and in the Aux Fields.
  660. // Real ThreadStart events will have the Parent threadId in the
  661. // header and the new ThreadId in the Aux Field.
  662. //
  663. pThread->KCPUStart = pHeader->KernelTime;
  664. pThread->UCPUStart = pHeader->UserTime;
  665. AdjustThreadTime(pEvent, pThread);
  666. }
  667. else {
  668. /*
  669. #if DBG
  670. DbgPrint("FATBUG(%d): Cannot add thread %x for IO Write Event.\n",
  671. EventCount, pHeader->ThreadId);
  672. #endif
  673. */
  674. return;
  675. }
  676. }
  677. /*
  678. #if DBG
  679. else if (pThread->fOrphan)
  680. {
  681. DbgPrint("INFO(%d): IO Write Event Thread %x Is Still Orphan.\n",
  682. EventCount, pHeader->ThreadId);
  683. }
  684. else if (pThread->DeadFlag)
  685. {
  686. DbgPrint("INFO(%d): IO Write Event Thread %x Is Already Dead.\n",
  687. EventCount, pHeader->ThreadId);
  688. }
  689. #endif
  690. */
  691. if (fValidWrite)
  692. {
  693. if (pThread->pMofData != NULL) {
  694. ((PMOF_DATA)pThread->pMofData)->WriteCount++;
  695. }
  696. pThread->WriteIO++;
  697. pThread->WriteIOSize += BytesWrite;
  698. }
  699. // 2. Disk->Process
  700. //
  701. pDiskProcess = FindDiskProcessById(Disk, pThread->pProcess->PID);
  702. if (fValidWrite && pDiskProcess != NULL) {
  703. if (pFlag) {
  704. pDiskProcess->HPF++;
  705. pDiskProcess->HPFSize += BytesWrite;
  706. }
  707. else {
  708. pDiskProcess->WriteIO++;
  709. pDiskProcess->WriteIOSize += BytesWrite;
  710. }
  711. }
  712. // Add the I/O to the process that owns the causing thread.
  713. //
  714. pProcess = pThread->pProcess;
  715. if (fValidWrite && (pProcess != NULL ) ) {
  716. pProcess->WriteIO++;
  717. pProcess->WriteIOSize += BytesWrite;
  718. Disk = FindProcessDiskById(pProcess, DiskNumber);
  719. if (Disk != NULL) {
  720. Disk->WriteCount++;
  721. Disk->WriteSize += BytesWrite;
  722. }
  723. }
  724. //
  725. // Thread Local Disk.
  726. //
  727. Disk = FindLocalDiskById(&pThread->DiskListHead, DiskNumber);
  728. if (fValidWrite && Disk != NULL) {
  729. Disk->WriteCount++;
  730. Disk->WriteSize += BytesWrite;
  731. }
  732. //
  733. // Now add this I/O the file it came from
  734. //
  735. if (fValidWrite)
  736. {
  737. fileObj = FindFileInTable(fDO);
  738. if (fileObj == NULL) {
  739. return;
  740. }
  741. if (fileObj->fileRec != NULL) {
  742. fileObj->fileRec->WriteCount++;
  743. fileObj->fileRec->WriteSize += BytesWrite;
  744. pProcFile = FindFileInProcess(pProcess, fileObj->fileRec->FileName);
  745. if (pProcFile != NULL) {
  746. pProcFile->WriteCount++;
  747. pProcFile->WriteSize += BytesWrite;
  748. }
  749. pProto = FindProtoProcessRecord(fileObj->fileRec, pProcess);
  750. if (pProto != NULL) {
  751. pProto->WriteCount++;
  752. pProto->WriteSize += BytesWrite;
  753. }
  754. }
  755. else {
  756. // APC has not happened yet. So Make a copy of the pEvent.
  757. // and Insert it in EventListHead;
  758. AddEvent(fileObj, DiskNumber, BytesWrite, FALSE);
  759. }
  760. }
  761. if (pFlag || (IrpFlags & IRP_ASSOCIATED_IRP) != 0)
  762. {
  763. PHPF_FILE_RECORD pHPFFileRecord = NULL;
  764. HPFWriteCount ++;
  765. if ( fValidWrite
  766. && AddHPFFileRecord(& pHPFFileRecord, HPFWriteCount, IrpFlags,
  767. DiskNumber, ByteOffset, BytesWrite, fDO))
  768. {
  769. EnterTracelibCritSection();
  770. InsertHeadList(& pThread->HPFWriteListHead,
  771. & pHPFFileRecord->Entry);
  772. LeaveTracelibCritSection();
  773. }
  774. }
  775. }
  776. VOID
  777. PsStartCallback(
  778. PEVENT_TRACE pEvent
  779. )
  780. {
  781. PEVENT_TRACE_HEADER pHeader;
  782. ULONG ProcessId=0;
  783. ULONG ReadId = 0;
  784. PPROCESS_RECORD pProcess;
  785. char ImageName[16];
  786. ULONG returnLength = 16;
  787. CHAR UserName[64];
  788. CHAR Domain[64];
  789. CHAR FullName[256];
  790. ULONG RetLength;
  791. DWORD asize = 0;
  792. DWORD bsize = 0;
  793. ULONG Sid[64];
  794. PULONG pSid = &Sid[0];
  795. SID_NAME_USE Se;
  796. if (pEvent == NULL)
  797. return;
  798. pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  799. RetLength = GetMofData(pEvent, L"ProcessId", &ReadId, sizeof(ULONG));
  800. // if (RetLength == 0) {
  801. // return;
  802. // }
  803. ProcessId = ReadId;
  804. if ( AddProcess(ProcessId, &pProcess) ) {
  805. //
  806. // If the Data Collection Start Time and the Process Start Time
  807. // match, then the PsStart was created by the ProcessRunDown
  808. // Code. So Keep the CPU Times to compute the difference at the
  809. // end. Otherwise, zero the starting CPU Times.
  810. //
  811. pProcess->PID = ProcessId;
  812. RtlZeroMemory(&ImageName, 16 * sizeof(CHAR) );
  813. GetMofData(pEvent, L"ImageFileName", &ImageName, returnLength);
  814. asize = lstrlenA(ImageName);
  815. if (asize > 0) {
  816. pProcess->ImageName = (LPWSTR)malloc((asize + 1) * sizeof(WCHAR));
  817. if (pProcess->ImageName == NULL) {
  818. return;
  819. }
  820. //
  821. // Process hook has the image name as ASCII. So we need to
  822. // convert it to unicode here.
  823. //
  824. AnsiToUnicode(ImageName, pProcess->ImageName);
  825. }
  826. else {
  827. pProcess->ImageName = (LPWSTR)malloc(MAXSTR * sizeof(WCHAR));
  828. if (pProcess->ImageName == NULL) {
  829. return;
  830. }
  831. if (ProcessId == 0)
  832. {
  833. wcscpy(pProcess->ImageName, L"Idle");
  834. }
  835. else
  836. {
  837. wsprintfW(pProcess->ImageName,
  838. L"Unknown(0x%08X)",
  839. ProcessId);
  840. }
  841. }
  842. GetMofData(pEvent, L"UserSID", pSid, 64);
  843. asize = 64; bsize = 64;
  844. if (LookupAccountSidA(NULL,
  845. pSid,
  846. &UserName[0],
  847. &asize,
  848. &Domain[0],
  849. &bsize,
  850. &Se)) {
  851. char* pFullName = &FullName[0];
  852. strcpy(pFullName, "\\\\");
  853. strcat(pFullName, Domain);
  854. strcat(pFullName, "\\");
  855. strcat(pFullName, UserName);
  856. asize = lstrlenA(pFullName);
  857. if (asize > 0) {
  858. pProcess->UserName = (LPWSTR)malloc((asize + 1) * sizeof(WCHAR));
  859. if (pProcess->UserName != NULL) {
  860. AnsiToUnicode(pFullName, pProcess->UserName);
  861. }
  862. }
  863. }
  864. else
  865. {
  866. pProcess->UserName = (LPWSTR)malloc(7 * sizeof(WCHAR));
  867. if (pProcess->UserName != NULL) {
  868. wcscpy(pProcess->UserName, L"system");
  869. }
  870. }
  871. }
  872. }
  873. VOID
  874. PsEndCallback(
  875. PEVENT_TRACE pEvent
  876. )
  877. {
  878. PEVENT_TRACE_HEADER pHeader;
  879. ULONG ProcessId;
  880. ULONG ReadId = 0;
  881. PPROCESS_RECORD pProcess;
  882. char ImageName[16];
  883. ULONG returnLength = 16;
  884. CHAR UserName[64];
  885. CHAR Domain[64];
  886. CHAR FullName[256];
  887. DWORD asize = 0;
  888. DWORD bsize = 0;
  889. ULONG RetLength;
  890. ULONG Sid[64];
  891. PULONG pSid = &Sid[0];
  892. SID_NAME_USE Se;
  893. if (pEvent == NULL)
  894. return;
  895. pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  896. RetLength = GetMofData(pEvent, L"ProcessId", &ReadId, sizeof(ULONG));
  897. // if (RetLength == 0) {
  898. // return;
  899. // }
  900. ProcessId = ReadId;
  901. if ( (pProcess = FindProcessById(ProcessId, TRUE)) != NULL )
  902. {
  903. if (pProcess->DeadFlag)
  904. {
  905. /*
  906. #if DBG
  907. DbgPrint("FATBUG(%d): End Process %x Dead Already!\n",
  908. EventCount, ProcessId);
  909. #endif
  910. */
  911. return;
  912. }
  913. pProcess->DeadFlag = TRUE;
  914. RtlZeroMemory(&ImageName, 16 * sizeof(CHAR) );
  915. GetMofData(pEvent, L"ImageFileName", &ImageName, returnLength);
  916. asize = lstrlenA(ImageName);
  917. if (asize > 0)
  918. {
  919. if (pProcess->ImageName != NULL) {
  920. free(pProcess->ImageName);
  921. }
  922. pProcess->ImageName = (LPWSTR)malloc((asize + 1) * sizeof(WCHAR));
  923. if (pProcess->ImageName != NULL) {
  924. AnsiToUnicode(ImageName, pProcess->ImageName);
  925. }
  926. }
  927. GetMofData(pEvent, L"UserSID", pSid, 64);
  928. asize = 64; bsize = 64;
  929. if (LookupAccountSidA(NULL,
  930. pSid,
  931. &UserName[0],
  932. &asize,
  933. &Domain[0],
  934. &bsize,
  935. &Se)) {
  936. char* pFullName = &FullName[0];
  937. strcpy(pFullName, "\\\\");
  938. strcat(pFullName, Domain);
  939. strcat(pFullName, "\\");
  940. strcat(pFullName, UserName);
  941. asize = lstrlenA(pFullName);
  942. if (asize > 0)
  943. {
  944. if (pProcess->UserName != NULL)
  945. {
  946. free(pProcess->UserName);
  947. }
  948. pProcess->UserName = (LPWSTR)malloc((asize + 1) * sizeof(WCHAR));
  949. if (pProcess->UserName != NULL) {
  950. AnsiToUnicode(pFullName, pProcess->UserName);
  951. }
  952. }
  953. }
  954. else
  955. {
  956. if (pProcess->UserName != NULL)
  957. {
  958. free(pProcess->UserName);
  959. }
  960. pProcess->UserName = (LPWSTR)malloc(7 * sizeof(WCHAR));
  961. if (pProcess->UserName != NULL) {
  962. wcscpy(pProcess->UserName, L"system");
  963. }
  964. }
  965. }
  966. /*
  967. #if DBG
  968. else {
  969. DbgPrint("WARNING(%d): PsEnd for Unknown process %x Ignored!\n",
  970. EventCount, ProcessId);
  971. }
  972. #endif
  973. */
  974. }
  975. VOID
  976. ThStartCallback(
  977. PEVENT_TRACE pEvent
  978. )
  979. {
  980. PEVENT_TRACE_HEADER pHeader;
  981. ULONG ProcessorId = pEvent->ClientContext & 0x000000FF;
  982. ULONG ProcessId, ThreadId;
  983. PPROCESS_RECORD pProcess;
  984. PTHREAD_RECORD Thread;
  985. ULONG ReadId = 0;
  986. ULONG RetLength;
  987. if (pEvent == NULL)
  988. {
  989. return;
  990. }
  991. pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  992. RetLength = GetMofData(pEvent, L"TThreadId", &ReadId, sizeof(ULONG));
  993. // if (RetLength == 0) {
  994. // return;
  995. // }
  996. ThreadId = ReadId;
  997. RetLength = GetMofData(pEvent, L"ProcessId", &ReadId, sizeof(ULONG));
  998. // if (RetLength == 0) {
  999. // return;
  1000. // }
  1001. ProcessId = ReadId;
  1002. pProcess = FindProcessById(ProcessId, TRUE);
  1003. if (pProcess == NULL)
  1004. {
  1005. // This should not Happen. The PS hooks are supposed to guarantee
  1006. // that the process create happens before the thread creates
  1007. // for that process.
  1008. //
  1009. if (!AddProcess(ProcessId, &pProcess))
  1010. {
  1011. /*
  1012. #if DBG
  1013. DbgPrint("FATBUG(%d): Can not find Process Start Record Th %x PID %x\n",
  1014. EventCount, ThreadId, ProcessId);
  1015. #endif
  1016. */
  1017. return;
  1018. }
  1019. }
  1020. if (ThreadId == 0 && ProcessorId == 0)
  1021. {
  1022. pEvent->ClientContext += CurrentSystem.CurrentThread0 ++;
  1023. //ASSERT( CurrentSystem.CurrentThread0 <= CurrentSystem.NumberOfProcessors );
  1024. }
  1025. Thread = FindGlobalThreadById(ThreadId, pEvent);
  1026. if (ThreadId != 0 && Thread != NULL && !Thread->DeadFlag)
  1027. {
  1028. if (Thread->fOrphan)
  1029. {
  1030. Thread->fOrphan = FALSE;
  1031. /*
  1032. #if DBG
  1033. DbgPrint("INFO(%d): Attach orphan thread %x to process %x.\n",
  1034. EventCount, ThreadId, ProcessId);
  1035. #endif
  1036. */
  1037. }
  1038. else
  1039. {
  1040. EVENT_TRACE event;
  1041. /*
  1042. #if DBG
  1043. DbgPrint("WARNING(%d): Two active thread have the same TID %x.\n",
  1044. EventCount, ThreadId);
  1045. #endif
  1046. */
  1047. event.Header.TimeStamp.QuadPart = pHeader->TimeStamp.QuadPart;
  1048. event.Header.Class.Type = EVENT_TRACE_TYPE_END;
  1049. event.Header.ThreadId = ThreadId;
  1050. event.Header.UserTime = Thread->UCPUEnd;
  1051. event.Header.KernelTime = Thread->KCPUEnd;
  1052. //
  1053. // If a DCStart event with non-zero KCPU and UCPU is paired up with
  1054. // an end Event for the same ThreadId with less CPU Times, the delta
  1055. // can come out negative. We correct it here.
  1056. //
  1057. if (Thread->KCPUEnd < Thread->KCPUStart)
  1058. Thread->KCPUEnd = Thread->KCPUStart;
  1059. if (Thread->UCPUEnd < Thread->UCPUStart)
  1060. Thread->UCPUEnd = Thread->UCPUStart;
  1061. ThEndCallback(&event);
  1062. if (!AddThread(ThreadId, pEvent, &Thread))
  1063. {
  1064. /*
  1065. #if DBG
  1066. DbgPrint("FATBUG(%d): Cannot add global active thread TID %x.\n",
  1067. EventCount, ThreadId);
  1068. #endif
  1069. */
  1070. return;
  1071. }
  1072. }
  1073. }
  1074. else if (!AddThread(ThreadId, pEvent, &Thread)) {
  1075. /*
  1076. #if DBG
  1077. DbgPrint("FATBUG(%d): Cannot add global active thread TID %x.\n",
  1078. EventCount, ThreadId);
  1079. #endif
  1080. */
  1081. return;
  1082. }
  1083. Thread->pProcess = pProcess;
  1084. Thread->TimeStart = pHeader->TimeStamp.QuadPart;
  1085. // Note: All ThreadStart record at the start of data collection
  1086. // have the same TID in the header and in the Aux Fields.
  1087. // Real ThreadStart events will have the Parent threadId in the
  1088. // header and the new ThreadId in the Aux Field.
  1089. //
  1090. if ( (ThreadId == pHeader->ThreadId)
  1091. || (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_END))
  1092. {
  1093. Thread->KCPUStart = pHeader->KernelTime;
  1094. Thread->UCPUStart = pHeader->UserTime;
  1095. }
  1096. else
  1097. {
  1098. Thread->KCPUStart = 0;
  1099. Thread->UCPUStart = 0;
  1100. }
  1101. //
  1102. // For DCStart type, the TID in the pEvent and the new thread
  1103. // match. So we can adjust its ThreadTimes.
  1104. //
  1105. if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_START) {
  1106. AdjustThreadTime(pEvent, Thread);
  1107. }
  1108. else {
  1109. AdjustThreadTime(pEvent, NULL);
  1110. }
  1111. {
  1112. Thread->KCPU_Trans = 0;
  1113. Thread->KCPU_NoTrans = 0;
  1114. Thread->UCPU_Trans = 0;
  1115. Thread->UCPU_NoTrans = 0;
  1116. Thread->TransLevel = 0;
  1117. Thread->KCPU_PrevTrans = Thread->KCPUStart;
  1118. Thread->UCPU_PrevTrans = Thread->UCPUStart;
  1119. }
  1120. if (Thread->TID == 0 && CurrentSystem.BuildNumber <= 1877)
  1121. {
  1122. CurrentSystem.NumberOfProcessors++;
  1123. }
  1124. }
  1125. VOID
  1126. ShutdownThreads()
  1127. {
  1128. int i;
  1129. EVENT_TRACE event;
  1130. PLIST_ENTRY Head,Next;
  1131. PTHREAD_RECORD Thread;
  1132. RtlZeroMemory(&event, sizeof(EVENT_TRACE));
  1133. event.Header.TimeStamp.QuadPart = CurrentSystem.EndTime;
  1134. //
  1135. // Move the Thread list from the HashTable to GlobalList
  1136. //
  1137. for (i=0; i < THREAD_HASH_TABLESIZE; i++) {
  1138. Head = &CurrentSystem.ThreadHashList[i];
  1139. Next = Head->Flink;
  1140. while (Next != Head) {
  1141. Thread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
  1142. Next = Next->Flink;
  1143. if (!Thread->DeadFlag){
  1144. event.Header.Class.Type = EVENT_TRACE_TYPE_DC_END;
  1145. event.Header.ThreadId = Thread->TID;
  1146. event.Header.UserTime = Thread->UCPUEnd;
  1147. event.Header.KernelTime = Thread->KCPUEnd;
  1148. ThEndCallback( &event );
  1149. }
  1150. }
  1151. }
  1152. }
  1153. VOID
  1154. ShutdownProcesses()
  1155. {
  1156. PLIST_ENTRY pHead = &CurrentSystem.ProcessListHead;
  1157. PLIST_ENTRY pNext = pHead->Flink;
  1158. PPROCESS_RECORD pProcess;
  1159. while (pNext != pHead){
  1160. pProcess = CONTAINING_RECORD(pNext, PROCESS_RECORD, Entry);
  1161. pNext = pNext->Flink;
  1162. if (!pProcess->DeadFlag){
  1163. pProcess->DeadFlag = TRUE;
  1164. }
  1165. }
  1166. }
  1167. BOOL
  1168. StopThreadTrans(
  1169. PLIST_ENTRY Head,
  1170. PEVENT_TRACE pEvent,
  1171. PTHREAD_RECORD pThread
  1172. )
  1173. {
  1174. PTRANS_RECORD pTrans;
  1175. PLIST_ENTRY Next = Head->Flink;
  1176. while( Head != Next ){
  1177. pTrans = CONTAINING_RECORD(Next, TRANS_RECORD, Entry);
  1178. Next = Next->Flink;
  1179. if( !StopThreadTrans( &pTrans->SubTransListHead, pEvent, pThread ) ){
  1180. return FALSE;
  1181. }
  1182. if( !pTrans->bStarted ){
  1183. continue;
  1184. }
  1185. memcpy( &pEvent->Header.Guid, pTrans->pGuid, sizeof(GUID));
  1186. pEvent->Header.Class.Type = EVENT_TRACE_TYPE_END;
  1187. EventCallback( pEvent, pThread );
  1188. return FALSE; // stopping one will credit all running events
  1189. }
  1190. return TRUE;
  1191. }
  1192. VOID
  1193. ThEndCallback(
  1194. PEVENT_TRACE pEvent
  1195. )
  1196. {
  1197. PEVENT_TRACE_HEADER pHeader;
  1198. ULONG ThreadId;
  1199. PTHREAD_RECORD Thread;
  1200. if (pEvent == NULL)
  1201. {
  1202. return;
  1203. }
  1204. pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  1205. ThreadId = pHeader->ThreadId;
  1206. if (ThreadId == 0)
  1207. {
  1208. ULONG ProcessorId = pEvent->ClientContext & 0x000000FF;
  1209. if (ProcessorId == 0) {
  1210. pEvent->ClientContext += (CurrentSystem.NumberOfProcessors
  1211. - (CurrentSystem.CurrentThread0 --));
  1212. }
  1213. }
  1214. Thread = FindGlobalThreadById(ThreadId, pEvent);
  1215. if (Thread != NULL)
  1216. {
  1217. if (Thread->DeadFlag)
  1218. {
  1219. /*
  1220. #if DBG
  1221. DbgPrint("FATBUG(%d): Thread %x Dead Already\n",
  1222. EventCount, ThreadId);
  1223. #endif
  1224. */
  1225. return;
  1226. }
  1227. if (Thread->fOrphan)
  1228. {
  1229. ULONG ReadId = 0;
  1230. ULONG ProcessId = 0;
  1231. PPROCESS_RECORD pProcess = NULL;
  1232. GetMofData(pEvent, L"ProcessId", &ReadId, sizeof(ULONG));
  1233. ProcessId = ReadId;
  1234. pProcess = FindProcessById(ProcessId, TRUE);
  1235. if (pProcess != NULL)
  1236. {
  1237. Thread->fOrphan = FALSE;
  1238. Thread->pProcess = pProcess;
  1239. }
  1240. /*
  1241. #if DBG
  1242. DbgPrint("INFO(%d): ThEndCallback() attach orphan thread %X to process %X\n",
  1243. EventCount, ThreadId, ProcessId);
  1244. #endif
  1245. */
  1246. }
  1247. //
  1248. // Charge any unstopped transactions
  1249. //
  1250. if ( Thread != NULL
  1251. && pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_END)
  1252. {
  1253. StopThreadTrans(&Thread->TransListHead, pEvent, Thread );
  1254. }
  1255. Thread->DeadFlag = TRUE;
  1256. if (fDSOnly)
  1257. {
  1258. if ((ULONGLONG) pHeader->TimeStamp.QuadPart > DSEndTime)
  1259. {
  1260. Thread->TimeEnd = DSEndTime;
  1261. }
  1262. else
  1263. {
  1264. Thread->KCPUEnd = pHeader->KernelTime;
  1265. Thread->UCPUEnd = pHeader->UserTime;
  1266. Thread->TimeEnd = (ULONGLONG) pHeader->TimeStamp.QuadPart;
  1267. }
  1268. }
  1269. else
  1270. {
  1271. if (Thread->UCPUEnd < pHeader->UserTime)
  1272. Thread->UCPUEnd = pHeader->UserTime;
  1273. if (Thread->KCPUEnd < pHeader->KernelTime)
  1274. Thread->KCPUEnd = pHeader->KernelTime;
  1275. Thread->TimeEnd = pHeader->TimeStamp.QuadPart;
  1276. }
  1277. if (Thread->TransLevel <= 0)
  1278. {
  1279. Thread->KCPU_NoTrans += Thread->KCPUEnd - Thread->KCPU_PrevTrans;
  1280. Thread->UCPU_NoTrans += Thread->UCPUEnd - Thread->UCPU_PrevTrans;
  1281. }
  1282. else
  1283. {
  1284. Thread->KCPU_Trans += Thread->KCPUEnd - Thread->KCPU_PrevTrans;
  1285. Thread->UCPU_Trans += Thread->UCPUEnd - Thread->UCPU_PrevTrans;
  1286. /*
  1287. #if DBG
  1288. DbgPrint("WARNING(%d): Active Transactions in Dead Thread %x\n",
  1289. EventCount, ThreadId);
  1290. #endif
  1291. */
  1292. }
  1293. }
  1294. else
  1295. {
  1296. /*
  1297. #if DBG
  1298. DbgPrint("WARNING(%d): No Thread Start for ThreadId %x\n",
  1299. EventCount, ThreadId);
  1300. #endif
  1301. */
  1302. if (AddThread(ThreadId, pEvent, &Thread))
  1303. {
  1304. Thread->pProcess = FindProcessById(0, FALSE);
  1305. Thread->DeadFlag = TRUE;
  1306. Thread->fOrphan = TRUE;
  1307. Thread->TimeStart = Thread->TimeEnd = pHeader->TimeStamp.QuadPart;
  1308. Thread->KCPUStart = Thread->KCPUEnd = pHeader->KernelTime;
  1309. Thread->UCPUStart = Thread->UCPUEnd = pHeader->UserTime;
  1310. AdjustThreadTime(pEvent, Thread);
  1311. }
  1312. else
  1313. {
  1314. /*
  1315. #if DBG
  1316. DbgPrint("FATBUG(%d): Cannot add thread %x for ThreadEnd Event.\n",
  1317. EventCount, ThreadId);
  1318. #endif
  1319. */
  1320. }
  1321. }
  1322. }
  1323. VOID
  1324. IoReadCallback(
  1325. PEVENT_TRACE pEvent,
  1326. PTHREAD_RECORD pThread
  1327. )
  1328. {
  1329. PEVENT_TRACE_HEADER pHeader = (EVENT_TRACE_HEADER*)&pEvent->Header;
  1330. ULONG DiskNumber=0;
  1331. ULONG BytesRead=0;
  1332. ULONG IrpFlags=0;
  1333. PTDISK_RECORD Disk;
  1334. PPROCESS_RECORD pProcess;
  1335. PPROTO_PROCESS_RECORD pProto;
  1336. PFILE_OBJECT fileObj;
  1337. PFILE_RECORD pProcFile;
  1338. PVOID fDO;
  1339. BOOLEAN pFlag = FALSE;
  1340. PPROCESS_RECORD pDiskProcess;
  1341. LONGLONG ByteOffset;
  1342. BOOLEAN fValidRead = (BOOLEAN) (!fDSOnly ||
  1343. ( ((ULONGLONG) pHeader->TimeStamp.QuadPart >= DSStartTime)
  1344. && ((ULONGLONG) pHeader->TimeStamp.QuadPart <= DSEndTime)));
  1345. GetMofData(pEvent, L"DiskNumber", &DiskNumber, sizeof(ULONG));
  1346. GetMofData(pEvent, L"IrpFlags", &IrpFlags, sizeof(ULONG));
  1347. GetMofData(pEvent, L"TransferSize", &BytesRead, sizeof(ULONG));
  1348. GetMofData(pEvent, L"FileObject", &fDO, sizeof(ULONG));
  1349. GetMofData(pEvent, L"ByteOffset", &ByteOffset, sizeof(ULONGLONG));
  1350. BytesRead /= 1024; // Convert to Kbytes
  1351. if (((IrpFlags & IRP_PAGING_IO) != 0) ||
  1352. ((IrpFlags & IRP_SYNCHRONOUS_PAGING_IO) != 0)) {
  1353. pFlag = TRUE;
  1354. }
  1355. //
  1356. // TODO: From DiskNumber and Offset get the Logical Disk
  1357. // ie., DiskNumber = MapDisk(DiskIndex, Offset);
  1358. //
  1359. //
  1360. // Add the I/O to the DISK
  1361. //
  1362. if ((Disk = FindGlobalDiskById(DiskNumber)) == NULL) {
  1363. if (!AddDisk(DiskNumber, &Disk) ) {
  1364. return;
  1365. }
  1366. }
  1367. if (fValidRead)
  1368. {
  1369. if (pFlag) {
  1370. Disk->HPF++;
  1371. Disk->HPFSize += BytesRead;
  1372. }
  1373. else {
  1374. Disk->ReadCount++;
  1375. Disk->ReadSize += BytesRead;
  1376. }
  1377. }
  1378. //
  1379. // Add the I/O to the THREAD
  1380. //
  1381. if ( pThread == NULL) {
  1382. //
  1383. // NOTE: Logger Thread Creation is MISSED by the collector.
  1384. // Also, thread creation between process rundown code (UserMode) and
  1385. // logger thread start (kernel mode) are missed.
  1386. // So we must handle it here.
  1387. //
  1388. if (AddThread(pHeader->ThreadId, pEvent, &pThread )) {
  1389. /*
  1390. #if DBG
  1391. DbgPrint("WARNING(%d): Thread %x added to charge IO Read event\n",
  1392. EventCount, pHeader->ThreadId);
  1393. #endif
  1394. */
  1395. pThread->pProcess = FindProcessById(0, TRUE); // Charge it the system ???
  1396. pThread->TimeStart = pHeader->TimeStamp.QuadPart;
  1397. pThread->fOrphan = TRUE;
  1398. //
  1399. // Note: All ThreadStart record at the start of data collection
  1400. // have the same TID in the header and in the Aux Fields.
  1401. // Real ThreadStart events will have the Parent threadId in the
  1402. // header and the new ThreadId in the Aux Field.
  1403. //
  1404. pThread->KCPUStart = pHeader->KernelTime;
  1405. pThread->UCPUStart = pHeader->UserTime;
  1406. AdjustThreadTime(pEvent, pThread);
  1407. }
  1408. else {
  1409. /*
  1410. #if DBG
  1411. DbgPrint("FATBUG(%d): Cannot add thread %x for IO Read Event.\n",
  1412. EventCount, pHeader->ThreadId);
  1413. #endif
  1414. */
  1415. return;
  1416. }
  1417. }
  1418. /*
  1419. #if DBG
  1420. else if (pThread->fOrphan)
  1421. {
  1422. DbgPrint("INFO(%d): IO Read Event Thread %x Is Still Orphan.\n",
  1423. EventCount, pHeader->ThreadId);
  1424. }
  1425. else if (pThread->DeadFlag)
  1426. {
  1427. DbgPrint("INFO(%d): IO Read Event Thread %x Is Already Dead.\n",
  1428. EventCount, pHeader->ThreadId);
  1429. }
  1430. #endif
  1431. */
  1432. ASSERT(pThread != NULL);
  1433. if (fValidRead && pThread->pMofData != NULL) {
  1434. ((PMOF_DATA)pThread->pMofData)->ReadCount++;
  1435. }
  1436. if (fValidRead)
  1437. {
  1438. if (pFlag) {
  1439. pThread->HPF++;
  1440. pThread->HPFSize += BytesRead;
  1441. }
  1442. else {
  1443. pThread->ReadIO++;
  1444. pThread->ReadIOSize += BytesRead;
  1445. }
  1446. }
  1447. //
  1448. // 2. Disk->Process
  1449. //
  1450. pDiskProcess = FindDiskProcessById(Disk, pThread->pProcess->PID);
  1451. if (fValidRead && pDiskProcess != NULL) {
  1452. if (pFlag) {
  1453. pDiskProcess->HPF++;
  1454. pDiskProcess->HPFSize += BytesRead;
  1455. }
  1456. else {
  1457. pDiskProcess->ReadIO++;
  1458. pDiskProcess->ReadIOSize += BytesRead;
  1459. }
  1460. }
  1461. //
  1462. // Add the I/O to the PROCESS
  1463. //
  1464. pProcess = pThread->pProcess;
  1465. if (fValidRead && (pProcess != NULL )) {
  1466. pProcess->ReadIO++;
  1467. pProcess->ReadIOSize += BytesRead;
  1468. Disk = FindProcessDiskById(pProcess, DiskNumber);
  1469. if (Disk != NULL) {
  1470. if (pFlag) {
  1471. Disk->HPF++;
  1472. Disk->HPFSize += BytesRead;
  1473. }
  1474. else {
  1475. Disk->ReadCount++;
  1476. Disk->ReadSize += BytesRead;
  1477. }
  1478. }
  1479. }
  1480. //
  1481. // Add the I/O to the FILE
  1482. //
  1483. if (fValidRead)
  1484. {
  1485. fileObj = FindFileInTable(fDO);
  1486. if (fileObj == NULL) {
  1487. return;
  1488. }
  1489. if (fileObj->fileRec) {
  1490. fileObj->fileRec->ReadCount++;
  1491. fileObj->fileRec->ReadSize += BytesRead;
  1492. pProcFile = FindFileInProcess(pProcess, fileObj->fileRec->FileName);
  1493. if (pProcFile != NULL) {
  1494. #if 0
  1495. if (pFlag) {
  1496. pProcFile->HPF++;
  1497. pProcFile->HPFSize += BytesRead;
  1498. }
  1499. else {
  1500. #endif
  1501. pProcFile->ReadCount++;
  1502. pProcFile->ReadSize += BytesRead;
  1503. #if 0
  1504. }
  1505. #endif
  1506. }
  1507. pProto = FindProtoProcessRecord(fileObj->fileRec, pProcess);
  1508. if (pProto != NULL) {
  1509. #if 0
  1510. if (pFlag) {
  1511. pProto->HPF++;
  1512. pProto->HPFSize += BytesRead;
  1513. }
  1514. else {
  1515. #endif
  1516. pProto->ReadCount++;
  1517. pProto->ReadSize += BytesRead;
  1518. #if 0
  1519. }
  1520. #endif
  1521. }
  1522. }
  1523. else {
  1524. // APC has not happened yet. So Make a copy of the pEvent.
  1525. // and Insert it in EventListHead;
  1526. AddEvent(fileObj, DiskNumber, BytesRead, TRUE);
  1527. }
  1528. }
  1529. //
  1530. // Do the Drill Down Calls Now. To Save on memory we need to be
  1531. // selective about which ones to create.
  1532. //
  1533. // 2. Thread->Disk
  1534. Disk = FindLocalDiskById(&pThread->DiskListHead, DiskNumber);
  1535. if (fValidRead && Disk != NULL) {
  1536. if (pFlag) {
  1537. Disk->HPF++;
  1538. Disk->HPFSize += BytesRead;
  1539. }
  1540. else {
  1541. Disk->ReadCount++;
  1542. Disk->ReadSize += BytesRead;
  1543. }
  1544. }
  1545. if (pFlag || (IrpFlags & IRP_ASSOCIATED_IRP) != 0)
  1546. {
  1547. PHPF_FILE_RECORD pHPFFileRecord = NULL;
  1548. HPFReadCount ++;
  1549. if ( fValidRead
  1550. && AddHPFFileRecord(& pHPFFileRecord, HPFReadCount, IrpFlags,
  1551. DiskNumber, ByteOffset, BytesRead, fDO))
  1552. {
  1553. EnterTracelibCritSection();
  1554. InsertHeadList(& pThread->HPFReadListHead,
  1555. & pHPFFileRecord->Entry);
  1556. LeaveTracelibCritSection();
  1557. }
  1558. }
  1559. }
  1560. VOID
  1561. HotFileCallback(
  1562. PEVENT_TRACE pEvent
  1563. )
  1564. {
  1565. PEVENT_TRACE_HEADER pHeader;
  1566. WCHAR FileName[MAXSTR]; // Not Sure if this is sufficient...
  1567. PLIST_ENTRY Next, Head;
  1568. PFILE_RECORD fileRec, pProcFile = NULL;
  1569. PPROTO_FILE_RECORD protoFileRec;
  1570. PFILE_OBJECT fileObj;
  1571. PVOID fDO;
  1572. PTHREAD_RECORD pThread = NULL;
  1573. PPROCESS_RECORD pProcess = NULL;
  1574. PPROTO_PROCESS_RECORD pProto = NULL;
  1575. ULONG RetLength;
  1576. if (pEvent == NULL)
  1577. return;
  1578. pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  1579. RtlZeroMemory(&FileName, MAXSTR * sizeof(WCHAR));
  1580. GetMofData(pEvent, L"FileObject", &fDO, sizeof(ULONG));
  1581. RetLength = GetMofData(pEvent, L"FileName", &FileName, MAXSTR*sizeof(WCHAR));
  1582. if (RetLength == 0) {
  1583. return;
  1584. }
  1585. // Remember to Add the DISKNUMBER to the name
  1586. //
  1587. // When we get a FileName We need to find the FILE_RECORD
  1588. //
  1589. if ((fileRec = FindFileRecordByName(FileName)) == NULL) {
  1590. AddFile(FileName, &fileRec);
  1591. }
  1592. //
  1593. // Get the FileObject from the fileTable and update the information.
  1594. //
  1595. fileObj = FindFileInTable(fDO);
  1596. if (fileObj == NULL) {
  1597. return;
  1598. }
  1599. if (fileObj->fileRec != NULL) {
  1600. /*
  1601. #if DBG
  1602. DbgPrint("BUG: APC for known file %ws\n", FileName);
  1603. #endif
  1604. */
  1605. }
  1606. if ((pThread = FindGlobalThreadById(pHeader->ThreadId, pEvent)) != NULL) {
  1607. pProcess = pThread->pProcess;
  1608. if (pProcess != NULL) {
  1609. pProcFile = FindFileInProcess(pProcess, FileName);
  1610. pProto = FindProtoProcessRecord(fileRec, pProcess);
  1611. }
  1612. }
  1613. else {
  1614. return;
  1615. }
  1616. fileObj->fileRec = fileRec;
  1617. //
  1618. // Walk through the EventList and add it to this file record
  1619. //
  1620. Head = &fileObj->ProtoFileRecordListHead;
  1621. Next = Head->Flink;
  1622. while (Next != Head) {
  1623. protoFileRec = CONTAINING_RECORD( Next, PROTO_FILE_RECORD, Entry );
  1624. fileRec->DiskNumber = protoFileRec->DiskNumber;
  1625. if (protoFileRec->ReadFlag) {
  1626. fileRec->ReadCount++;
  1627. fileRec->ReadSize += protoFileRec->IoSize;
  1628. if (pProcFile != NULL) {
  1629. pProcFile->ReadCount++;
  1630. pProcFile->ReadSize += protoFileRec->IoSize;
  1631. }
  1632. if (pProto != NULL) {
  1633. pProto->ReadCount++;
  1634. pProto->ReadSize += protoFileRec->IoSize;
  1635. }
  1636. }
  1637. else {
  1638. fileRec->WriteCount++;
  1639. fileRec->WriteSize += protoFileRec->IoSize;
  1640. if (pProcFile != NULL) {
  1641. pProcFile->WriteCount++;
  1642. pProcFile->WriteSize += protoFileRec->IoSize;
  1643. }
  1644. if (pProto != NULL) {
  1645. pProto->WriteCount++;
  1646. pProto->WriteSize += protoFileRec->IoSize;
  1647. }
  1648. }
  1649. Next = Next->Flink;
  1650. RemoveEntryList( &protoFileRec->Entry);
  1651. }
  1652. //
  1653. // If DrillDown Records are appended, we need to handle those too
  1654. //
  1655. }
  1656. VOID
  1657. ModuleLoadCallback(PEVENT_TRACE pEvent)
  1658. {
  1659. PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER) & pEvent->Header;
  1660. ULONG lBaseAddress = 0;
  1661. ULONG lModuleSize = 0;
  1662. WCHAR strModulePath[256];
  1663. WCHAR * strModuleName;
  1664. ULONG rtnLength = sizeof(WCHAR) * 256;
  1665. PLIST_ENTRY pHead = &CurrentSystem.GlobalModuleListHead;
  1666. PLIST_ENTRY pNext = pHead->Flink;
  1667. PMODULE_RECORD pMatched = NULL;
  1668. PMODULE_RECORD pCurrent = NULL;
  1669. PTHREAD_RECORD pThread = NULL;
  1670. PPROCESS_RECORD pProcess = NULL;
  1671. RtlZeroMemory(strModulePath, 256 * sizeof(WCHAR) );
  1672. GetMofData(pEvent, L"ImageBase", & lBaseAddress, sizeof(ULONG));
  1673. GetMofData(pEvent, L"ImageSize", & lModuleSize, sizeof(ULONG));
  1674. GetMofData(pEvent, L"FileName", & strModulePath, rtnLength);
  1675. strModuleName = wcsrchr(strModulePath, L'\\');
  1676. if (!strModuleName){
  1677. strModuleName = strModulePath;
  1678. }else{
  1679. strModuleName ++;
  1680. }
  1681. // Check if loaded image is already in SYSTEM_RECORD::GlobalModuleListHead.
  1682. // Otherwise, insert new MODULE_RECORD.
  1683. //
  1684. while (!pMatched && pNext != pHead){
  1685. pMatched = CONTAINING_RECORD(pNext, MODULE_RECORD, Entry);
  1686. if (_wcsicmp(strModuleName, pMatched->strModuleName)){
  1687. pMatched = NULL;
  1688. pNext = pNext->Flink;
  1689. }
  1690. }
  1691. if (!pMatched){
  1692. if (AddModuleRecord(& pMatched, lBaseAddress, lModuleSize, strModuleName)){
  1693. EnterTracelibCritSection();
  1694. InsertHeadList(
  1695. & CurrentSystem.GlobalModuleListHead,
  1696. & pMatched->Entry);
  1697. LeaveTracelibCritSection();
  1698. pMatched->pProcess = NULL;
  1699. pMatched->pGlobalPtr = NULL;
  1700. }else{
  1701. return;
  1702. }
  1703. }
  1704. ASSERT(pMatched);
  1705. // Insert loaded image in PROCESS_RECORD::ModuleListHead
  1706. //
  1707. if (AddModuleRecord(& pCurrent, lBaseAddress, lModuleSize, strModuleName)){
  1708. pCurrent->pGlobalPtr = pMatched;
  1709. pThread = FindGlobalThreadById(pHeader->ThreadId, pEvent);
  1710. ASSERT(pThread);
  1711. if (!pThread){
  1712. free( pCurrent );
  1713. return;
  1714. }
  1715. pProcess = pThread->pProcess;
  1716. ASSERT(pProcess);
  1717. if (!pProcess){
  1718. free( pCurrent );
  1719. return;
  1720. }
  1721. EnterTracelibCritSection();
  1722. pCurrent->pProcess = pProcess;
  1723. InsertHeadList( & pProcess->ModuleListHead, & pCurrent->Entry);
  1724. LeaveTracelibCritSection();
  1725. }else{
  1726. return;
  1727. }
  1728. }
  1729. VOID
  1730. ProcessCallback(
  1731. PEVENT_TRACE pEvent
  1732. )
  1733. {
  1734. if (pEvent == NULL){
  1735. return;
  1736. }
  1737. if ((pEvent->Header.Class.Type == EVENT_TRACE_TYPE_START) ||
  1738. (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_START)) {
  1739. PsStartCallback(pEvent);
  1740. }
  1741. else if ((pEvent->Header.Class.Type == EVENT_TRACE_TYPE_END) ||
  1742. (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_END)) {
  1743. PsEndCallback(pEvent);
  1744. }
  1745. }
  1746. VOID
  1747. ThreadCallback(
  1748. PEVENT_TRACE pEvent
  1749. )
  1750. {
  1751. if (pEvent == NULL){
  1752. return;
  1753. }
  1754. if ((pEvent->Header.Class.Type == EVENT_TRACE_TYPE_START) ||
  1755. (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_START)) {
  1756. ThStartCallback(pEvent);
  1757. } else if ((pEvent->Header.Class.Type == EVENT_TRACE_TYPE_END) ||
  1758. (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_END)) {
  1759. ThEndCallback(pEvent);
  1760. }
  1761. }
  1762. PMODULE_RECORD
  1763. SearchModuleByAddr(
  1764. PLIST_ENTRY pModuleListHead,
  1765. ULONG lAddress
  1766. )
  1767. {
  1768. PLIST_ENTRY pNext = pModuleListHead->Flink;
  1769. PMODULE_RECORD pModule = NULL;
  1770. PMODULE_RECORD pCurrent;
  1771. while (pNext != pModuleListHead)
  1772. {
  1773. pCurrent = CONTAINING_RECORD(pNext, MODULE_RECORD, Entry);
  1774. pNext = pNext->Flink;
  1775. if ( (lAddress >= pCurrent->lBaseAddress)
  1776. && (lAddress < pCurrent->lBaseAddress + pCurrent->lModuleSize))
  1777. {
  1778. pModule = pCurrent;
  1779. break;
  1780. }
  1781. }
  1782. return pModule;
  1783. }
  1784. void
  1785. UpdatePageFaultCount(
  1786. PPROCESS_RECORD pProcess,
  1787. PMODULE_RECORD pModule,
  1788. ULONG lFaultAddr,
  1789. UCHAR FaultType)
  1790. {
  1791. BOOLEAN fFaultInImage = (BOOLEAN) ((lFaultAddr >= pModule->lBaseAddress)
  1792. && (lFaultAddr < pModule->lBaseAddress
  1793. + pModule->lModuleSize));
  1794. switch(FaultType)
  1795. {
  1796. case EVENT_TRACE_TYPE_MM_HPF :
  1797. if (fFaultInImage)
  1798. {
  1799. pProcess->lCodeFaultHF ++;
  1800. pModule->lCodeFaultHF ++;
  1801. if (pModule->pGlobalPtr)
  1802. {
  1803. pModule->pGlobalPtr->lCodeFaultHF ++;
  1804. }
  1805. }
  1806. else
  1807. {
  1808. pProcess->lDataFaultHF ++;
  1809. pModule->lDataFaultHF ++;
  1810. if (pModule->pGlobalPtr)
  1811. {
  1812. pModule->pGlobalPtr->lDataFaultHF ++;
  1813. }
  1814. }
  1815. break;
  1816. case EVENT_TRACE_TYPE_MM_TF :
  1817. if (fFaultInImage)
  1818. {
  1819. pProcess->lCodeFaultTF ++;
  1820. pModule->lCodeFaultTF ++;
  1821. if (pModule->pGlobalPtr)
  1822. {
  1823. pModule->pGlobalPtr->lCodeFaultTF ++;
  1824. }
  1825. }
  1826. else
  1827. {
  1828. pProcess->lDataFaultTF ++;
  1829. pModule->lDataFaultTF ++;
  1830. if (pModule->pGlobalPtr)
  1831. {
  1832. pModule->pGlobalPtr->lDataFaultTF ++;
  1833. }
  1834. }
  1835. break;
  1836. case EVENT_TRACE_TYPE_MM_DZF :
  1837. if (fFaultInImage)
  1838. {
  1839. pProcess->lCodeFaultDZF ++;
  1840. pModule->lCodeFaultDZF ++;
  1841. if (pModule->pGlobalPtr)
  1842. {
  1843. pModule->pGlobalPtr->lCodeFaultDZF ++;
  1844. }
  1845. }
  1846. else
  1847. {
  1848. pProcess->lDataFaultDZF ++;
  1849. pModule->lDataFaultDZF ++;
  1850. if (pModule->pGlobalPtr)
  1851. {
  1852. pModule->pGlobalPtr->lDataFaultDZF ++;
  1853. }
  1854. }
  1855. break;
  1856. case EVENT_TRACE_TYPE_MM_COW :
  1857. if (fFaultInImage)
  1858. {
  1859. pProcess->lCodeFaultCOW ++;
  1860. pModule->lCodeFaultCOW ++;
  1861. if (pModule->pGlobalPtr)
  1862. {
  1863. pModule->pGlobalPtr->lCodeFaultCOW ++;
  1864. }
  1865. }
  1866. else
  1867. {
  1868. pProcess->lDataFaultCOW ++;
  1869. pModule->lDataFaultCOW ++;
  1870. if (pModule->pGlobalPtr)
  1871. {
  1872. pModule->pGlobalPtr->lDataFaultCOW ++;
  1873. }
  1874. }
  1875. break;
  1876. default :
  1877. break;
  1878. }
  1879. }
  1880. PMODULE_RECORD
  1881. SearchSysModule(
  1882. PPROCESS_RECORD pProcess,
  1883. ULONG lPC,
  1884. BOOLEAN fActive
  1885. )
  1886. {
  1887. PMODULE_RECORD pModule = NULL;
  1888. PPROCESS_RECORD pSysProcess = FindProcessById(0, fActive);
  1889. PMODULE_RECORD pCurrent =
  1890. SearchModuleByAddr(& pSysProcess->ModuleListHead, lPC);
  1891. if (pCurrent)
  1892. {
  1893. if (AddModuleRecord(& pModule,
  1894. pCurrent->lBaseAddress,
  1895. pCurrent->lModuleSize,
  1896. pCurrent->strModuleName))
  1897. {
  1898. EnterTracelibCritSection();
  1899. InsertHeadList(
  1900. & pProcess->ModuleListHead,
  1901. & pModule->Entry);
  1902. LeaveTracelibCritSection();
  1903. pModule->pProcess = pProcess;
  1904. pModule->pGlobalPtr = pCurrent->pGlobalPtr;
  1905. }
  1906. }
  1907. return pModule;
  1908. }
  1909. VOID
  1910. PageFaultCallback(
  1911. PEVENT_TRACE pEvent,
  1912. PTHREAD_RECORD pThread
  1913. )
  1914. {
  1915. PEVENT_TRACE_HEADER pHeader;
  1916. PPROCESS_RECORD pProcess;
  1917. PMOF_DATA pMofData;
  1918. ULONG lFaultAddr = 0;
  1919. ULONG lPC = 0;
  1920. PVOID fDO = NULL;
  1921. LONG lByteCount = 0;
  1922. LONGLONG lByteOffset = 0;
  1923. WCHAR strHotFileName[1024];
  1924. ULONG rtnLength = sizeof(WCHAR) * 1024;
  1925. BOOLEAN fSpecialHPF = FALSE;
  1926. BOOLEAN fFound;
  1927. if (pEvent == NULL)
  1928. return;
  1929. if (!InTimeWindow(pEvent, pThread))
  1930. return;
  1931. GetMofData(pEvent, L"VirtualAddress", &lFaultAddr, sizeof(ULONG));
  1932. GetMofData(pEvent, L"ProgramCounter", &lPC, sizeof(ULONG));
  1933. pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  1934. if ( pHeader->Class.Type == EVENT_TRACE_TYPE_MM_HPF
  1935. && pEvent->MofLength > 2 * sizeof(ULONG))
  1936. {
  1937. fSpecialHPF = TRUE;
  1938. GetMofData(pEvent, L"FileObject", &fDO, sizeof(ULONG));
  1939. GetMofData(pEvent, L"ByteCount", &lByteCount, sizeof(LONG));
  1940. GetMofData(pEvent, L"ByteOffset", &lByteOffset, sizeof(LONGLONG));
  1941. GetMofData(pEvent, L"FileName", &strHotFileName, rtnLength);
  1942. }
  1943. if (pThread == NULL)
  1944. {
  1945. if (AddThread(pHeader->ThreadId, pEvent, &pThread ))
  1946. {
  1947. /*
  1948. #if DBG
  1949. DbgPrint("WARNING(%d): Thread %x added to charge PageFault event\n",
  1950. EventCount, pHeader->ThreadId);
  1951. #endif
  1952. */
  1953. pThread->pProcess = FindProcessById(0, TRUE);
  1954. pThread->TimeStart = pHeader->TimeStamp.QuadPart;
  1955. pThread->fOrphan = TRUE;
  1956. pThread->KCPUStart = pHeader->KernelTime;
  1957. pThread->UCPUStart = pHeader->UserTime;
  1958. AdjustThreadTime(pEvent, pThread);
  1959. }
  1960. else
  1961. {
  1962. /*
  1963. #if DBG
  1964. DbgPrint("FATBUG(%d): Cannot add thread %x for PageFault Event.\n",
  1965. EventCount, pHeader->ThreadId);
  1966. #endif
  1967. */
  1968. return;
  1969. }
  1970. }
  1971. /*
  1972. #if DBG
  1973. else if (pThread->fOrphan)
  1974. {
  1975. DbgPrint("INFO(%d): PageFault Event Thread %x Is Still Orphan.\n",
  1976. EventCount, pHeader->ThreadId);
  1977. }
  1978. else if (pThread->DeadFlag)
  1979. {
  1980. DbgPrint("INFO(%d): PageFault Event Thread %x Is Already Dead.\n",
  1981. EventCount, pHeader->ThreadId);
  1982. }
  1983. #endif
  1984. */
  1985. pMofData = (PMOF_DATA)pThread->pMofData;
  1986. if (pMofData && !fSpecialHPF)
  1987. {
  1988. switch(pHeader->Class.Type)
  1989. {
  1990. case EVENT_TRACE_TYPE_MM_TF : pMofData->MmTf++; break;
  1991. case EVENT_TRACE_TYPE_MM_DZF : pMofData->MmDzf++; break;
  1992. case EVENT_TRACE_TYPE_MM_COW : pMofData->MmCow++; break;
  1993. case EVENT_TRACE_TYPE_MM_GPF : pMofData->MmGpf++; break;
  1994. }
  1995. }
  1996. // Update loaded image MODULE_RECORD::lFaultCount
  1997. //
  1998. pProcess = pThread->pProcess;
  1999. if (pProcess != NULL)
  2000. {
  2001. PMODULE_RECORD pModule = SearchModuleByAddr(
  2002. & pProcess->ModuleListHead,
  2003. lPC);
  2004. fFound = FALSE;
  2005. if (fSpecialHPF)
  2006. {
  2007. PHPF_RECORD pHPFRecord = NULL;
  2008. PageFaultCount ++;
  2009. if (AddHPFRecord(& pHPFRecord, lFaultAddr,
  2010. fDO, lByteCount, lByteOffset))
  2011. {
  2012. PLIST_ENTRY pHead = & pThread->HPFReadListHead;
  2013. PLIST_ENTRY pNext = pHead->Flink;
  2014. PHPF_FILE_RECORD pHPFFileRecord;
  2015. PHPF_FILE_RECORD pHPFThreadRead;
  2016. LONG lTotalByte = 0;
  2017. BOOLEAN fAssociatedIrp = TRUE;
  2018. EnterTracelibCritSection();
  2019. pHPFRecord->RecordID = PageFaultCount;
  2020. InsertHeadList(& pProcess->HPFListHead, & pHPFRecord->Entry);
  2021. while (fAssociatedIrp && pNext != pHead)
  2022. {
  2023. pHPFThreadRead = CONTAINING_RECORD(pNext,
  2024. HPF_FILE_RECORD,
  2025. Entry);
  2026. pNext = pNext->Flink;
  2027. fAssociatedIrp = (BOOLEAN) ((pHPFThreadRead->IrpFlags
  2028. & IRP_ASSOCIATED_IRP) != 0);
  2029. if (!fAssociatedIrp && fDO != pHPFThreadRead->fDO)
  2030. {
  2031. fAssociatedIrp = TRUE;
  2032. continue;
  2033. }
  2034. if (AddHPFFileRecord(& pHPFFileRecord,
  2035. pHPFThreadRead->RecordID,
  2036. pHPFThreadRead->IrpFlags,
  2037. pHPFThreadRead->DiskNumber,
  2038. pHPFThreadRead->ByteOffset,
  2039. pHPFThreadRead->BytesCount,
  2040. pHPFThreadRead->fDO))
  2041. {
  2042. lTotalByte += pHPFThreadRead->BytesCount;
  2043. InsertHeadList(& pHPFRecord->HPFReadListHead,
  2044. & pHPFFileRecord->Entry);
  2045. }
  2046. RemoveEntryList(& pHPFThreadRead->Entry);
  2047. free(pHPFThreadRead);
  2048. }
  2049. LeaveTracelibCritSection();
  2050. }
  2051. goto Cleanup;
  2052. }
  2053. else if (pHeader->Class.Type == EVENT_TRACE_TYPE_MM_HPF)
  2054. {
  2055. PLIST_ENTRY pHead = & pProcess->HPFListHead;
  2056. PLIST_ENTRY pNext = pHead->Flink;
  2057. PHPF_RECORD pHPFRecord;
  2058. while (pNext != pHead)
  2059. {
  2060. pHPFRecord = CONTAINING_RECORD(pNext, HPF_RECORD, Entry);
  2061. pNext = pNext->Flink;
  2062. if (pHPFRecord->lFaultAddress == lFaultAddr)
  2063. {
  2064. pHPFRecord->lProgramCounter = lPC;
  2065. break;
  2066. }
  2067. }
  2068. }
  2069. if (pModule)
  2070. {
  2071. UpdatePageFaultCount(
  2072. pProcess, pModule, lFaultAddr, pHeader->Class.Type);
  2073. fFound = TRUE;
  2074. }
  2075. if (!fFound && pProcess->PID != 0)
  2076. {
  2077. PMODULE_RECORD pModule = SearchSysModule(pProcess, lPC, TRUE);
  2078. if (pModule)
  2079. {
  2080. UpdatePageFaultCount(
  2081. pProcess, pModule, lFaultAddr, pHeader->Class.Type);
  2082. fFound = TRUE;
  2083. }
  2084. }
  2085. if (!fFound)
  2086. {
  2087. PLIST_ENTRY pModuleHead = & pProcess->ModuleListHead;
  2088. PLIST_ENTRY pModuleNext = pModuleHead->Flink;
  2089. PMODULE_RECORD pModule;
  2090. while (pModuleNext != pModuleHead)
  2091. {
  2092. pModule = CONTAINING_RECORD(pModuleNext,
  2093. MODULE_RECORD,
  2094. Entry);
  2095. pModuleNext = pModuleNext->Flink;
  2096. if (!_wcsicmp(pModule->strModuleName, L"other"))
  2097. {
  2098. if ( pModule->lBaseAddress == 0
  2099. && pModule->lModuleSize == 0)
  2100. {
  2101. pModule->lBaseAddress = lPC;
  2102. pModule->lModuleSize = 1;
  2103. }
  2104. else if (pModule->lBaseAddress > lPC)
  2105. {
  2106. pModule->lModuleSize += pModule->lBaseAddress - lPC;
  2107. pModule->lBaseAddress = lPC;
  2108. }
  2109. else if ( pModule->lModuleSize
  2110. < lPC - pModule->lBaseAddress + 1)
  2111. {
  2112. pModule->lModuleSize =
  2113. lPC - pModule->lBaseAddress + 1;
  2114. }
  2115. UpdatePageFaultCount(
  2116. pProcess,
  2117. pModule,
  2118. lFaultAddr,
  2119. pHeader->Class.Type);
  2120. break;
  2121. }
  2122. }
  2123. }
  2124. }
  2125. else
  2126. {
  2127. /*
  2128. #if DBG
  2129. DbgPrint("ERROR - PageFaultCallback(0x%08I64x,0x%08I64x,0x%08x,0x%08x) cannot find process\n",
  2130. pHeader->ThreadId,
  2131. pThread->pProcess->PID,
  2132. lPC,
  2133. lFaultAddr);
  2134. #endif
  2135. */
  2136. }
  2137. Cleanup:
  2138. return;
  2139. }
  2140. VOID
  2141. DiskIoCallback(
  2142. PEVENT_TRACE pEvent,
  2143. PTHREAD_RECORD pThread
  2144. )
  2145. {
  2146. if (pEvent == NULL)
  2147. return;
  2148. if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_IO_READ) {
  2149. IoReadCallback(pEvent, pThread);
  2150. }
  2151. else {
  2152. IoWriteCallback(pEvent, pThread);
  2153. }
  2154. }
  2155. VOID
  2156. TcpIpCallback(
  2157. PEVENT_TRACE pEvent,
  2158. PTHREAD_RECORD pThread
  2159. )
  2160. {
  2161. PEVENT_TRACE_HEADER pHeader;
  2162. PPROCESS_RECORD pProcess;
  2163. ULONG size = 0;
  2164. if (pEvent == NULL)
  2165. return;
  2166. pHeader = (EVENT_TRACE_HEADER*)&pEvent->Header;
  2167. if (!InTimeWindow(pEvent, pThread))
  2168. return;
  2169. if (pThread == NULL)
  2170. {
  2171. if (AddThread(pHeader->ThreadId, pEvent, &pThread ))
  2172. {
  2173. /*
  2174. #if DBG
  2175. DbgPrint("WARNING(%d): Thread %x added to charge TCP/IP event\n",
  2176. EventCount, pHeader->ThreadId);
  2177. #endif
  2178. */
  2179. pThread->pProcess = FindProcessById(0, TRUE);
  2180. pThread->TimeStart = pHeader->TimeStamp.QuadPart;
  2181. pThread->fOrphan = TRUE;
  2182. pThread->KCPUStart = pHeader->KernelTime;
  2183. pThread->UCPUStart = pHeader->UserTime;
  2184. AdjustThreadTime(pEvent, pThread);
  2185. }
  2186. else
  2187. {
  2188. /*
  2189. #if DBG
  2190. DbgPrint("FATBUG(%d): Cannot add thread %x for TCP/IP Event.\n",
  2191. EventCount, pHeader->ThreadId);
  2192. #endif
  2193. */
  2194. return;
  2195. }
  2196. }
  2197. /*
  2198. #if DBG
  2199. else if (pThread->fOrphan)
  2200. {
  2201. DbgPrint("INFO(%d): TCP/IP Event Thread %x Is Still Orphan.\n",
  2202. EventCount, pHeader->ThreadId);
  2203. }
  2204. else if (pThread->DeadFlag)
  2205. {
  2206. DbgPrint("INFO(%d): TCP/IP Event Thread %x Is Already Dead.\n",
  2207. EventCount, pHeader->ThreadId);
  2208. }
  2209. #endif
  2210. */
  2211. if (GetMofData(pEvent, L"size", &size, sizeof(ULONG)) > 0) {
  2212. if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SEND ) {
  2213. pThread->SendCount++;
  2214. pThread->SendSize += size;
  2215. if (pThread->pMofData != NULL) {
  2216. ((PMOF_DATA)pThread->pMofData)->SendCount++;
  2217. }
  2218. if ( (pProcess = pThread->pProcess) != NULL ) {
  2219. pProcess->SendCount++;
  2220. pProcess->SendSize += size;
  2221. }
  2222. } else if( pEvent->Header.Class.Type == EVENT_TRACE_TYPE_RECEIVE ) {
  2223. pThread->RecvCount++;
  2224. pThread->RecvSize += size;
  2225. if (pThread->pMofData != NULL) {
  2226. ((PMOF_DATA)pThread->pMofData)->RecvCount++;
  2227. }
  2228. if ( (pProcess = pThread->pProcess) != NULL ) {
  2229. pProcess->RecvCount++;
  2230. pProcess->RecvSize += size;
  2231. }
  2232. }
  2233. }
  2234. }
  2235. PFILE_OBJECT
  2236. FindFileInTable (
  2237. IN PVOID fDO
  2238. )
  2239. {
  2240. PFILE_OBJECT thisFile, lastFile = NULL;
  2241. PFILE_OBJECT *fileTable;
  2242. UINT i;
  2243. fileTable = CurrentSystem.FileTable;
  2244. for (i = 0; i < MAX_FILE_TABLE_SIZE; i++) {
  2245. thisFile = fileTable[i];
  2246. fileTable[i] = lastFile;
  2247. lastFile = thisFile;
  2248. if ((thisFile != NULL) && (thisFile->fDO == fDO)) {
  2249. fileTable[0] = thisFile;
  2250. return thisFile;
  2251. }
  2252. }
  2253. if (lastFile == NULL) {
  2254. lastFile = (PFILE_OBJECT) malloc( sizeof(FILE_OBJECT));
  2255. if (lastFile == NULL) {
  2256. return NULL;
  2257. }
  2258. }
  2259. fileTable[0] = lastFile;
  2260. lastFile->fDO = fDO;
  2261. lastFile->fileRec = NULL;
  2262. InitializeListHead( &lastFile->ProtoFileRecordListHead );
  2263. return lastFile;
  2264. }
  2265. //
  2266. // TODO: Redo the EventList as FILE_RECORDS with Unknown Filenames
  2267. // The current implementation will create a proto record for
  2268. // evenry I/O and if the APC never arrives, it can choke the
  2269. // system!
  2270. //
  2271. VOID
  2272. AddEvent(
  2273. IN PFILE_OBJECT fileObject,
  2274. IN ULONG DiskNumber,
  2275. IN ULONG IoSize,
  2276. IN BOOLEAN ReadFlag
  2277. )
  2278. {
  2279. PPROTO_FILE_RECORD protoFileRec;
  2280. if (fileObject->fileRec != NULL) {
  2281. /*
  2282. #if DBG
  2283. DbgPrint("BUG: FileObject is NONNULL in AddEvent\n");
  2284. #endif
  2285. */
  2286. }
  2287. protoFileRec = (PPROTO_FILE_RECORD) malloc(sizeof(PROTO_FILE_RECORD));
  2288. if (protoFileRec == NULL) {
  2289. return;
  2290. }
  2291. protoFileRec->ReadFlag = ReadFlag;
  2292. protoFileRec->IoSize = IoSize;
  2293. protoFileRec->DiskNumber = DiskNumber;
  2294. InsertHeadList( &fileObject->ProtoFileRecordListHead, &protoFileRec->Entry);
  2295. // Currently NOT Keeping track of the DrillDown data for the File
  2296. // if APC has not happened yet. Some Events may be lost.
  2297. }
  2298. ULONG
  2299. GetMofData(
  2300. PEVENT_TRACE pEvent,
  2301. WCHAR *strName,
  2302. PVOID ReturnValue,
  2303. ULONG ReturnLength
  2304. )
  2305. {
  2306. PITEM_DESC pAuxInfo;
  2307. PUCHAR pData = (PUCHAR) pEvent->MofData;
  2308. ULONG RequiredLength = 0;
  2309. BOOLEAN AddNull = FALSE;
  2310. PLIST_ENTRY Head, Next;
  2311. PMOF_INFO pMofInfo;
  2312. PMOF_VERSION pMofVersion;
  2313. if (pEvent == NULL)
  2314. return 0;
  2315. if (strName == NULL)
  2316. return 0;
  2317. if (lstrlenW(strName) <= 0)
  2318. return 0;
  2319. pMofInfo = GetMofInfoHead(&pEvent->Header.Guid);
  2320. if (pMofInfo == NULL)
  2321. return 0;
  2322. pMofVersion = GetMofVersion(pMofInfo,
  2323. pEvent->Header.Class.Type,
  2324. pEvent->Header.Class.Version,
  2325. pEvent->Header.Class.Level
  2326. );
  2327. if (pMofVersion == NULL)
  2328. return 0;
  2329. Head = &pMofVersion->ItemHeader;
  2330. Next = Head->Flink;
  2331. while (Head != Next) {
  2332. pAuxInfo = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
  2333. if ( (ULONG) (pData-(PUCHAR)pEvent->MofData) >= pEvent->MofLength)
  2334. return 0;
  2335. switch (pAuxInfo->ItemType) {
  2336. case ItemShort:
  2337. case ItemUShort:
  2338. {
  2339. RequiredLength = 2;
  2340. }
  2341. break;
  2342. case ItemULong:
  2343. case ItemULongX:
  2344. {
  2345. RequiredLength = 4;
  2346. }
  2347. break;
  2348. case ItemLongLong:
  2349. case ItemULongLong:
  2350. {
  2351. RequiredLength = 8;
  2352. }
  2353. break;
  2354. case ItemPString :
  2355. pData += sizeof(USHORT);
  2356. case ItemString :
  2357. RequiredLength = lstrlenA((PCHAR)pData) + 1;
  2358. break;
  2359. case ItemWString :
  2360. //
  2361. // FileNames etc are not NULL Terminated and only the buffer
  2362. // is copied. To find its length, we can't use wcslen.
  2363. // The Length is computed from the assumption that this string
  2364. // is the last item for this event and the size of the event
  2365. // should help determine the size of this string.
  2366. RequiredLength = pEvent->MofLength -
  2367. (ULONG) (pData - (PUCHAR) pEvent->MofData);
  2368. AddNull = TRUE;
  2369. break;
  2370. case ItemSid :
  2371. {
  2372. PULONG pSid;
  2373. pSid = (PULONG) pData;
  2374. if (*pSid == 0) {
  2375. RequiredLength = 4;
  2376. }
  2377. else {
  2378. pData += 8; // skip the TOKEN_USER structure
  2379. RequiredLength = 8 + (4*pData[1]);
  2380. }
  2381. }
  2382. break;
  2383. case ItemPtr :
  2384. {
  2385. RequiredLength = PointerSize / 8;
  2386. if ( (RequiredLength != 4) && (RequiredLength != 8) ) {
  2387. RequiredLength = 4;
  2388. }
  2389. break;
  2390. }
  2391. default : RequiredLength = pAuxInfo->DataSize;
  2392. }
  2393. if (!wcscmp(pAuxInfo->strDescription, strName)) {
  2394. if (RequiredLength == 0) return 0;
  2395. //
  2396. // Make Sure there is enough room to copy
  2397. //
  2398. if (RequiredLength > ReturnLength) {
  2399. /*
  2400. #if DBG
  2401. DbgPrint("RequiredLength %d Space Available %d\n", RequiredLength, ReturnLength);
  2402. #endif
  2403. */
  2404. return RequiredLength;
  2405. }
  2406. memcpy(ReturnValue, pData, RequiredLength);
  2407. if (AddNull) {
  2408. WCHAR* ws;
  2409. ws = (WCHAR*) ReturnValue;
  2410. ws[RequiredLength/2] = 0;
  2411. }
  2412. return 0;
  2413. }
  2414. else {
  2415. }
  2416. pData += RequiredLength;
  2417. Next = Next->Flink;
  2418. }
  2419. return RequiredLength;
  2420. }
  2421. ULONG
  2422. GetDeltaWithTimeWindow(BOOLEAN fKCPU, PTHREAD_RECORD pThread,
  2423. ULONGLONG timeStart, ULONGLONG timeEnd,
  2424. ULONG DeltaStart, ULONG DeltaEnd)
  2425. {
  2426. ULONG lResult = 0;
  2427. ULONG lDeltaStart, lDeltaEnd;
  2428. UNREFERENCED_PARAMETER(pThread);
  2429. if (!fDSOnly)
  2430. {
  2431. lResult = (DeltaEnd > DeltaStart) ? (DeltaEnd - DeltaStart) : (0);
  2432. }
  2433. else if ((timeStart >= DSEndTime) || (timeEnd <= DSStartTime))
  2434. {
  2435. lResult = 0;
  2436. }
  2437. else if (fKCPU)
  2438. {
  2439. lDeltaStart = (timeStart < DSStartTime)
  2440. ? Interpolate(timeStart, DeltaStart,
  2441. timeEnd, DeltaEnd,
  2442. DSStartTime)
  2443. : DeltaStart;
  2444. lDeltaEnd = (timeEnd > DSEndTime)
  2445. ? Interpolate(timeStart, DeltaStart,
  2446. timeEnd, DeltaEnd,
  2447. DSEndTime)
  2448. : DeltaEnd;
  2449. lResult = (lDeltaEnd > lDeltaStart) ? (lDeltaEnd - lDeltaStart) : (0);
  2450. }
  2451. else
  2452. {
  2453. lDeltaStart = (timeStart < DSStartTime)
  2454. ? Interpolate(timeStart, DeltaStart,
  2455. timeEnd, DeltaEnd,
  2456. DSStartTime)
  2457. : DeltaStart;
  2458. lDeltaEnd = (timeEnd > DSEndTime)
  2459. ? Interpolate(timeStart, DeltaStart,
  2460. timeEnd, DeltaEnd,
  2461. DSEndTime)
  2462. : DeltaEnd;
  2463. lResult = (lDeltaEnd > lDeltaStart) ? (lDeltaEnd - lDeltaStart) : (0);
  2464. }
  2465. return lResult;
  2466. }
  2467. // Generic Event Callback. Get the Transaction Response Time.
  2468. //
  2469. VOID
  2470. EventCallback(
  2471. PEVENT_TRACE pEvent,
  2472. PTHREAD_RECORD pThread
  2473. )
  2474. {
  2475. PMOF_INFO pMofInfo;
  2476. PMOF_DATA pMofData;
  2477. PEVENT_TRACE_HEADER pHeader;
  2478. PPROCESS_RECORD pProcess;
  2479. PTRANS_RECORD pThreadTrans = NULL;
  2480. ULONGLONG delta;
  2481. if (pEvent == NULL)
  2482. return;
  2483. pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  2484. //
  2485. // Ignore Process/Thread Start/End transactions. Only go after
  2486. // User Defined Transactions.
  2487. //
  2488. pMofInfo = GetMofInfoHead(&pHeader->Guid);
  2489. if (pMofInfo == NULL){
  2490. return;
  2491. }
  2492. if ( pMofInfo->bKernelEvent ){
  2493. return;
  2494. }
  2495. if (IsEqualGUID( &pMofInfo->Guid, &EventTraceGuid ) ||
  2496. pEvent->Header.Class.Type == EVENT_TRACE_TYPE_GUIDMAP) {
  2497. return;
  2498. }
  2499. if (pThread == NULL) {
  2500. if (AddThread( pHeader->ThreadId, pEvent, &pThread )) {
  2501. /*
  2502. #if DBG
  2503. DbgPrint("WARNING(%d): Thread %x added to charge Event.\n",
  2504. EventCount, pHeader->ThreadId);
  2505. #endif
  2506. */
  2507. pThread->pProcess = FindProcessById(0, TRUE); // Charge it the system ???
  2508. pThread->TimeStart = pHeader->TimeStamp.QuadPart;
  2509. pThread->KCPUStart = pHeader->KernelTime;
  2510. pThread->UCPUStart = pHeader->UserTime;
  2511. pThread->fOrphan = TRUE;
  2512. AdjustThreadTime(pEvent, pThread);
  2513. }
  2514. else
  2515. {
  2516. /*
  2517. #if DBG
  2518. DbgPrint("FATBUG(%d): Cannot add thread %x for Event.\n",
  2519. EventCount, pHeader->ThreadId);
  2520. #endif
  2521. */
  2522. return;
  2523. }
  2524. }
  2525. /*
  2526. #if DBG
  2527. else if (pThread->fOrphan)
  2528. {
  2529. DbgPrint("INFO(%d): Generic Event Thread %x Is Still Orphan.\n",
  2530. EventCount, pHeader->ThreadId);
  2531. }
  2532. else if (pThread->DeadFlag)
  2533. {
  2534. DbgPrint("INFO(%d): Generic Event Thread %x Is Already Dead.\n",
  2535. EventCount, pHeader->ThreadId);
  2536. }
  2537. #endif
  2538. */
  2539. if (pMofInfo->strSortField == NULL){
  2540. pMofData = FindMofData(pMofInfo, NULL);
  2541. }
  2542. else if ( (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_START)
  2543. || (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_START)){
  2544. WCHAR strSortKey[MAXSTR];
  2545. RtlZeroMemory(strSortKey, MAXSTR * sizeof(WCHAR) );
  2546. GetMofData(pEvent, pMofInfo->strSortField, &strSortKey, MAXSTR);
  2547. pMofData = FindMofData(pMofInfo, strSortKey );
  2548. wcscpy(pThread->strSortKey, strSortKey );
  2549. }else{
  2550. pMofData = FindMofData( pMofInfo, pThread->strSortKey );
  2551. }
  2552. pProcess = pThread->pProcess;
  2553. if ( (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_START)
  2554. || (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_START)){
  2555. pThreadTrans = FindTransByList(& pThread->TransListHead,
  2556. & pMofInfo->Guid,
  2557. pThread->TransLevel);
  2558. }
  2559. else
  2560. {
  2561. LONG i = pThread->TransLevel - 1;
  2562. while (i >= 0)
  2563. {
  2564. if (IsEqualGUID(& pHeader->Guid,
  2565. pThread->TransStack[i]->pGuid))
  2566. {
  2567. pThreadTrans = pThread->TransStack[i];
  2568. break;
  2569. }
  2570. i --;
  2571. }
  2572. if (i < 0)
  2573. {
  2574. pThreadTrans = FindTransByList(& pThread->TransListHead,
  2575. &pMofInfo->Guid,
  2576. (pThread->TransLevel >= 0) ? (pThread->TransLevel) : (0));
  2577. if (pThread->TransLevel < 0)
  2578. {
  2579. pThread->TransLevel = 0;
  2580. pThread->TransStack[pThread->TransLevel] = pThreadTrans;
  2581. pThread->TransLevel ++;
  2582. }
  2583. }
  2584. }
  2585. if (pMofData == NULL) {
  2586. return;
  2587. }
  2588. if (pMofData->PrevClockTime == 0)
  2589. {
  2590. pMofData->PrevClockTime = pHeader->TimeStamp.QuadPart;
  2591. }
  2592. delta = (pHeader->TimeStamp.QuadPart - pMofData->PrevClockTime);
  2593. pMofData->TotalResponseTime += (delta * pMofData->InProgressCount) / 10000;
  2594. // Update the Clock
  2595. pMofData->PrevClockTime = pHeader->TimeStamp.QuadPart;
  2596. if ( (pHeader->Class.Type == EVENT_TRACE_TYPE_START)
  2597. || (pHeader->Class.Type == EVENT_TRACE_TYPE_DC_START))
  2598. {
  2599. if (pThread->TransLevel < 0)
  2600. {
  2601. pThread->TransLevel = 0;
  2602. }
  2603. if (pThread->TransLevel == 0)
  2604. {
  2605. LONG lDelta;
  2606. lDelta = pHeader->KernelTime - pThread->KCPU_PrevTrans;
  2607. if (lDelta > 0)
  2608. {
  2609. pThread->KCPU_NoTrans += lDelta;
  2610. pThread->KCPU_PrevTrans = pHeader->KernelTime;
  2611. }
  2612. lDelta = pHeader->UserTime - pThread->UCPU_PrevTrans;
  2613. if (lDelta > 0)
  2614. {
  2615. pThread->UCPU_NoTrans += lDelta;
  2616. pThread->UCPU_PrevTrans = pHeader->UserTime;
  2617. }
  2618. }
  2619. else
  2620. {
  2621. PTRANS_RECORD pTransPrev =
  2622. pThread->TransStack[pThread->TransLevel - 1];
  2623. PMOF_INFO pMofInfoPrev = GetMofInfoHead(pTransPrev->pGuid);
  2624. PMOF_DATA pMofDataPrev = NULL;
  2625. ULONG DeltaCPU;
  2626. if (pMofInfoPrev != NULL)
  2627. {
  2628. pMofDataPrev = FindMofData(pMofInfoPrev, NULL);
  2629. }
  2630. if (pMofDataPrev)
  2631. {
  2632. DeltaCPU = GetDeltaWithTimeWindow(
  2633. TRUE,
  2634. pThread,
  2635. pThread->Time_PrevEvent,
  2636. (ULONGLONG) pHeader->TimeStamp.QuadPart,
  2637. pThread->KCPU_PrevEvent,
  2638. pHeader->KernelTime);
  2639. DeltaCPU = DeltaCPU * CurrentSystem.TimerResolution;
  2640. pTransPrev->KCpu += DeltaCPU;
  2641. pMofDataPrev->KernelCPU += DeltaCPU;
  2642. if (pMofDataPrev->MaxKCpu < 0)
  2643. {
  2644. pMofDataPrev->MaxKCpu = DeltaCPU;
  2645. pMofDataPrev->MinKCpu = DeltaCPU;
  2646. }
  2647. if (DeltaCPU > (ULONG) pMofDataPrev->MaxKCpu)
  2648. {
  2649. pMofDataPrev->MaxKCpu = DeltaCPU;
  2650. }
  2651. if (DeltaCPU < (ULONG) pMofDataPrev->MinKCpu)
  2652. {
  2653. pMofDataPrev->MinKCpu = DeltaCPU;
  2654. }
  2655. DeltaCPU = GetDeltaWithTimeWindow(
  2656. FALSE,
  2657. pThread,
  2658. pThread->Time_PrevEvent,
  2659. (ULONGLONG) pHeader->TimeStamp.QuadPart,
  2660. pThread->UCPU_PrevEvent,
  2661. pHeader->UserTime);
  2662. DeltaCPU = DeltaCPU * CurrentSystem.TimerResolution;
  2663. pTransPrev->UCpu += DeltaCPU;
  2664. pMofDataPrev->UserCPU += DeltaCPU;
  2665. if (pMofDataPrev->MaxUCpu < 0)
  2666. {
  2667. pMofDataPrev->MaxUCpu = DeltaCPU;
  2668. pMofDataPrev->MinUCpu = DeltaCPU;
  2669. }
  2670. if (DeltaCPU > (ULONG) pMofDataPrev->MaxUCpu)
  2671. {
  2672. pMofDataPrev->MaxUCpu = DeltaCPU;
  2673. }
  2674. if (DeltaCPU < (ULONG) pMofDataPrev->MinUCpu)
  2675. {
  2676. pMofDataPrev->MinUCpu = DeltaCPU;
  2677. }
  2678. }
  2679. }
  2680. if( pThreadTrans != NULL ){
  2681. if( ! pThreadTrans->bStarted ){
  2682. pThreadTrans->bStarted = TRUE;
  2683. pMofData->InProgressCount ++;
  2684. if (pHeader->Class.Type == EVENT_TRACE_TYPE_START) {
  2685. pThread->RefCount ++;
  2686. pThreadTrans->RefCount ++;
  2687. }
  2688. else {
  2689. pThreadTrans->RefCount1 ++;
  2690. }
  2691. pThread->pMofData = pMofData;
  2692. pThread->TransStack[pThread->TransLevel] = pThreadTrans;
  2693. pThread->TransLevel ++;
  2694. }
  2695. }
  2696. pThread->Time_PrevEvent = (ULONGLONG) pHeader->TimeStamp.QuadPart;
  2697. pThread->KCPU_PrevEvent = pHeader->KernelTime;
  2698. pThread->UCPU_PrevEvent = pHeader->UserTime;
  2699. pThread->DeltaReadIO = pThread->ReadIO;
  2700. pThread->DeltaWriteIO = pThread->WriteIO;
  2701. pThread->DeltaSend = pThread->SendCount;
  2702. pThread->DeltaRecv = pThread->RecvCount;
  2703. }
  2704. else if ( (pHeader->Class.Type == EVENT_TRACE_TYPE_END)
  2705. || (pHeader->Class.Type == EVENT_TRACE_TYPE_DC_END))
  2706. {
  2707. ULONG DeltaCPU;
  2708. BOOLEAN fSwitch = TRUE;
  2709. if( pThreadTrans != NULL ){
  2710. if (pThreadTrans->bStarted){
  2711. PTRANS_RECORD pTransCurrent;
  2712. PMOF_INFO pMofInfoCurrent;
  2713. PMOF_DATA pMofDataCurrent;
  2714. BOOLEAN fCharged = FALSE;
  2715. if (pThread->TransLevel <= 0)
  2716. {
  2717. pThread->TransLevel = 0;
  2718. }
  2719. else {
  2720. do
  2721. {
  2722. pThread->TransLevel --;
  2723. pTransCurrent = pThread->TransStack[pThread->TransLevel];
  2724. if (pTransCurrent->bStarted)
  2725. {
  2726. pTransCurrent->bStarted = FALSE;
  2727. }
  2728. pMofInfoCurrent = GetMofInfoHead( pTransCurrent->pGuid );
  2729. pMofDataCurrent = NULL;
  2730. if (pMofInfoCurrent != NULL)
  2731. {
  2732. pMofDataCurrent = FindMofData(pMofInfoCurrent, NULL);
  2733. }
  2734. if (!pMofDataCurrent)
  2735. continue;
  2736. pMofDataCurrent->InProgressCount--;
  2737. if (pMofDataCurrent->InProgressCount < 0){
  2738. pMofDataCurrent->InProgressCount = 0;
  2739. }
  2740. pMofDataCurrent->CompleteCount++;
  2741. pMofDataCurrent->AverageResponseTime
  2742. = (pMofDataCurrent->CompleteCount > 0)
  2743. ? ( (LONG) pMofDataCurrent->TotalResponseTime
  2744. / pMofDataCurrent->CompleteCount)
  2745. : 0;
  2746. if (fCharged)
  2747. continue;
  2748. DeltaCPU = GetDeltaWithTimeWindow(
  2749. TRUE,
  2750. pThread,
  2751. pThread->Time_PrevEvent,
  2752. (ULONGLONG) pHeader->TimeStamp.QuadPart,
  2753. pThread->KCPU_PrevEvent,
  2754. pHeader->KernelTime);
  2755. DeltaCPU = DeltaCPU * CurrentSystem.TimerResolution;
  2756. pTransCurrent->KCpu += DeltaCPU;
  2757. pMofDataCurrent->KernelCPU += DeltaCPU;
  2758. if (pMofDataCurrent->MaxKCpu < 0)
  2759. {
  2760. pMofDataCurrent->MaxKCpu = DeltaCPU;
  2761. pMofDataCurrent->MinKCpu = DeltaCPU;
  2762. }
  2763. if (DeltaCPU > (ULONG) pMofDataCurrent->MaxKCpu)
  2764. {
  2765. pMofDataCurrent->MaxKCpu = DeltaCPU;
  2766. }
  2767. if (DeltaCPU < (ULONG) pMofDataCurrent->MinKCpu)
  2768. {
  2769. pMofDataCurrent->MinKCpu = DeltaCPU;
  2770. }
  2771. DeltaCPU = GetDeltaWithTimeWindow(
  2772. FALSE,
  2773. pThread,
  2774. pThread->Time_PrevEvent,
  2775. (ULONGLONG) pHeader->TimeStamp.QuadPart,
  2776. pThread->UCPU_PrevEvent,
  2777. pHeader->UserTime);
  2778. DeltaCPU = DeltaCPU * CurrentSystem.TimerResolution;
  2779. pTransCurrent->UCpu += DeltaCPU;
  2780. pMofDataCurrent->UserCPU += DeltaCPU;
  2781. if(pMofDataCurrent->MaxUCpu < 0)
  2782. {
  2783. pMofDataCurrent->MaxUCpu = DeltaCPU;
  2784. pMofDataCurrent->MinUCpu = DeltaCPU;
  2785. }
  2786. if (DeltaCPU > (ULONG) pMofDataCurrent->MaxUCpu)
  2787. {
  2788. pMofDataCurrent->MaxUCpu = DeltaCPU;
  2789. }
  2790. fCharged = TRUE;
  2791. }while ( pThread->TransLevel > 0 &&
  2792. !IsEqualGUID(& pHeader->Guid, pTransCurrent->pGuid));
  2793. }
  2794. pThread->Time_PrevEvent = (ULONGLONG) pHeader->TimeStamp.QuadPart;
  2795. pThread->KCPU_PrevEvent = pHeader->KernelTime;
  2796. pThread->UCPU_PrevEvent = pHeader->UserTime;
  2797. }
  2798. else
  2799. {
  2800. DeltaCPU = GetDeltaWithTimeWindow(
  2801. TRUE,
  2802. pThread,
  2803. (ULONGLONG) pHeader->TimeStamp.QuadPart,
  2804. (ULONGLONG) pHeader->TimeStamp.QuadPart,
  2805. pHeader->KernelTime,
  2806. pHeader->KernelTime);
  2807. DeltaCPU = DeltaCPU * CurrentSystem.TimerResolution;
  2808. pThreadTrans->KCpu += DeltaCPU;
  2809. pMofData->KernelCPU += DeltaCPU;
  2810. if (pMofData->MaxKCpu < 0)
  2811. {
  2812. pMofData->MaxKCpu = DeltaCPU;
  2813. pMofData->MinKCpu = DeltaCPU;
  2814. }
  2815. if (DeltaCPU > (ULONG) pMofData->MaxKCpu)
  2816. {
  2817. pMofData->MaxKCpu = DeltaCPU;
  2818. }
  2819. if (DeltaCPU < (ULONG) pMofData->MinKCpu)
  2820. {
  2821. pMofData->MinKCpu = DeltaCPU;
  2822. }
  2823. DeltaCPU = GetDeltaWithTimeWindow(
  2824. FALSE,
  2825. pThread,
  2826. (ULONGLONG) pHeader->TimeStamp.QuadPart,
  2827. (ULONGLONG) pHeader->TimeStamp.QuadPart,
  2828. pHeader->UserTime,
  2829. pHeader->UserTime);
  2830. DeltaCPU = DeltaCPU * CurrentSystem.TimerResolution;
  2831. pThreadTrans->UCpu += DeltaCPU;
  2832. pMofData->UserCPU += DeltaCPU;
  2833. if(pMofData->MaxUCpu < 0)
  2834. {
  2835. pMofData->MaxUCpu = DeltaCPU;
  2836. pMofData->MinUCpu = DeltaCPU;
  2837. }
  2838. if (DeltaCPU > (ULONG) pMofData->MaxUCpu)
  2839. {
  2840. pMofData->MaxUCpu = DeltaCPU;
  2841. }
  2842. if (DeltaCPU < (ULONG) pMofData->MinUCpu)
  2843. {
  2844. pMofData->MinUCpu = DeltaCPU;
  2845. }
  2846. fSwitch = FALSE;
  2847. }
  2848. }
  2849. pMofData->ReadCount += (pThread->ReadIO - pThread->DeltaReadIO);
  2850. pMofData->WriteCount += (pThread->WriteIO - pThread->DeltaWriteIO);
  2851. pMofData->SendCount += (pThread->SendCount - pThread->DeltaSend);
  2852. pMofData->RecvCount += (pThread->RecvCount - pThread->DeltaRecv);
  2853. pThread->pMofData = NULL;
  2854. if (fSwitch && pThread->TransLevel <= 0)
  2855. {
  2856. LONG lDelta;
  2857. if (pThread->TransLevel < 0)
  2858. {
  2859. pThread->TransLevel = 0;
  2860. }
  2861. lDelta = pHeader->KernelTime - pThread->KCPU_PrevTrans;
  2862. if (lDelta > 0)
  2863. {
  2864. pThread->KCPU_Trans += lDelta;
  2865. pThread->KCPU_PrevTrans = pHeader->KernelTime;
  2866. }
  2867. lDelta = pHeader->UserTime - pThread->UCPU_PrevTrans;
  2868. if (lDelta > 0)
  2869. {
  2870. pThread->UCPU_Trans += lDelta;
  2871. pThread->UCPU_PrevTrans = pHeader->UserTime;
  2872. }
  2873. }
  2874. }
  2875. }
  2876. ULONG
  2877. ThreadRunDown(
  2878. IN PSYSTEM_PROCESS_INFORMATION pProcessInfo
  2879. )
  2880. {
  2881. PSYSTEM_THREAD_INFORMATION pThreadInfo;
  2882. ULONG i;
  2883. EVENT_TRACE Event;
  2884. HANDLE EventInfo[2];
  2885. PEVENT_TRACE_HEADER pWnode;
  2886. ULONG TimerResolution = 1; // How do I get this??
  2887. RtlZeroMemory(&Event, sizeof(EVENT_TRACE));
  2888. pWnode = &Event.Header;
  2889. pWnode->Size = sizeof(EVENT_TRACE_HEADER) + 2 * sizeof(HANDLE);
  2890. pWnode->Class.Type = EVENT_TRACE_TYPE_DC_START;
  2891. Event.MofData = EventInfo;
  2892. Event.MofLength = 2 * sizeof(HANDLE);
  2893. GetSystemTimeAsFileTime((struct _FILETIME *)&pWnode->TimeStamp);
  2894. RtlCopyMemory(&pWnode->Guid, &ThreadGuid, sizeof(GUID));
  2895. pThreadInfo = (PSYSTEM_THREAD_INFORMATION) (pProcessInfo+1);
  2896. for (i=0; i < pProcessInfo->NumberOfThreads; i++) {
  2897. EventInfo[0] = pThreadInfo->ClientId.UniqueThread;
  2898. EventInfo[1] = pThreadInfo->ClientId.UniqueProcess;
  2899. pWnode->KernelTime = (ULONG) (pThreadInfo->KernelTime.QuadPart
  2900. / TimerResolution);
  2901. pWnode->UserTime = (ULONG) (pThreadInfo->UserTime.QuadPart
  2902. / TimerResolution);
  2903. ThreadCallback(&Event);
  2904. pThreadInfo += 1;
  2905. }
  2906. return ERROR_SUCCESS;
  2907. }
  2908. ULONG
  2909. ProcessRunDown(
  2910. )
  2911. {
  2912. PSYSTEM_PROCESS_INFORMATION pProcessInfo;
  2913. PSYSTEM_THREAD_INFORMATION pThreadInfo;
  2914. char* LargeBuffer1;
  2915. NTSTATUS status;
  2916. ULONG ReturnLength;
  2917. ULONG CurrentBufferSize;
  2918. ULONG TotalOffset = 0;
  2919. OBJECT_ATTRIBUTES objectAttributes;
  2920. EVENT_TRACE Event;
  2921. ULONG_PTR AuxInfo[64];
  2922. PEVENT_TRACE_HEADER pWnode;
  2923. RtlZeroMemory(&Event, sizeof(EVENT_TRACE));
  2924. pWnode = &Event.Header;
  2925. pWnode->Size = sizeof(EVENT_TRACE_HEADER) + 2 * sizeof(HANDLE);
  2926. pWnode->Class.Type = EVENT_TRACE_TYPE_DC_START;
  2927. Event.MofData = AuxInfo;
  2928. Event.MofLength = 2 * sizeof(HANDLE);
  2929. GetSystemTimeAsFileTime((struct _FILETIME *)&pWnode->TimeStamp);
  2930. RtlCopyMemory(&pWnode->Guid, &ProcessGuid, sizeof(GUID));
  2931. LargeBuffer1 = (LPSTR)VirtualAlloc (NULL,
  2932. MAX_BUFFER_SIZE,
  2933. MEM_RESERVE,
  2934. PAGE_READWRITE);
  2935. if (LargeBuffer1 == NULL) {
  2936. return ERROR_MORE_DATA;
  2937. }
  2938. if (VirtualAlloc (LargeBuffer1,
  2939. BUFFER_SIZE,
  2940. MEM_COMMIT,
  2941. PAGE_READWRITE) == NULL) {
  2942. return ERROR_MORE_DATA;
  2943. }
  2944. CurrentBufferSize = BUFFER_SIZE;
  2945. retry:
  2946. status = NtQuerySystemInformation(
  2947. SystemProcessInformation,
  2948. LargeBuffer1,
  2949. CurrentBufferSize,
  2950. &ReturnLength
  2951. );
  2952. if (status == STATUS_INFO_LENGTH_MISMATCH) {
  2953. //
  2954. // Increase buffer size.
  2955. //
  2956. CurrentBufferSize += 8192;
  2957. if (VirtualAlloc (LargeBuffer1,
  2958. CurrentBufferSize,
  2959. MEM_COMMIT,
  2960. PAGE_READWRITE) == NULL) {
  2961. return ERROR_MORE_DATA;
  2962. }
  2963. goto retry;
  2964. }
  2965. if (!NT_SUCCESS(status)) {
  2966. return(status);
  2967. }
  2968. TotalOffset = 0;
  2969. pProcessInfo = (SYSTEM_PROCESS_INFORMATION *) LargeBuffer1;
  2970. while (pProcessInfo != NULL) {
  2971. ULONG Size;
  2972. ULONG Length = 0;
  2973. ULONG SidLength = 0;
  2974. PUCHAR AuxPtr;
  2975. ANSI_STRING s;
  2976. HANDLE Token;
  2977. HANDLE pProcess;
  2978. PCLIENT_ID Cid;
  2979. ULONG TempInfo[128];
  2980. s.Buffer = NULL;
  2981. s.Length = 0;
  2982. Size = sizeof(EVENT_TRACE_HEADER) + 2 * sizeof(ULONG_PTR);
  2983. pThreadInfo = (PSYSTEM_THREAD_INFORMATION) (pProcessInfo+1);
  2984. if (pProcessInfo->NumberOfThreads > 0) {
  2985. Cid = (PCLIENT_ID) &pThreadInfo->ClientId;
  2986. }
  2987. else {
  2988. Cid = NULL;
  2989. }
  2990. if ( pProcessInfo->ImageName.Buffer &&
  2991. pProcessInfo->ImageName.Length > 0 ) {
  2992. RtlUnicodeStringToAnsiString(
  2993. &s,
  2994. (PUNICODE_STRING)&pProcessInfo->ImageName,
  2995. TRUE);
  2996. Length = s.Length + 1;
  2997. }
  2998. else {
  2999. Length = 1;
  3000. }
  3001. InitializeObjectAttributes(
  3002. &objectAttributes, 0, 0, NULL, NULL);
  3003. status = NtOpenProcess(
  3004. &pProcess,
  3005. PROCESS_QUERY_INFORMATION,
  3006. &objectAttributes,
  3007. Cid);
  3008. if (NT_SUCCESS(status)) {
  3009. status = NtOpenProcessToken(
  3010. pProcess,
  3011. TOKEN_READ,
  3012. &Token);
  3013. if (NT_SUCCESS(status)) {
  3014. status = NtQueryInformationToken(
  3015. Token,
  3016. TokenUser,
  3017. TempInfo,
  3018. 256,
  3019. &SidLength);
  3020. NtClose(Token);
  3021. }
  3022. NtClose(pProcess);
  3023. }
  3024. if ( (!NT_SUCCESS(status)) || SidLength <= 0) {
  3025. TempInfo[0] = 0;
  3026. SidLength = sizeof(ULONG);
  3027. }
  3028. Size += Length + SidLength;
  3029. AuxInfo[0] = (ULONG_PTR) pProcessInfo->UniqueProcessId;
  3030. AuxInfo[1] = (ULONG_PTR) pProcessInfo->InheritedFromUniqueProcessId;
  3031. AuxPtr = (PUCHAR) &AuxInfo[2];
  3032. RtlCopyMemory(AuxPtr, &TempInfo, SidLength);
  3033. AuxPtr += SidLength;
  3034. if ( Length > 1) {
  3035. RtlCopyMemory(AuxPtr, s.Buffer, Length);
  3036. AuxPtr += Length;
  3037. RtlFreeAnsiString(&s);
  3038. }
  3039. *AuxPtr = '\0';
  3040. AuxPtr++;
  3041. Event.MofLength = Size - sizeof(EVENT_TRACE_HEADER);
  3042. ProcessCallback(&Event);
  3043. ThreadRunDown(pProcessInfo);
  3044. if (pProcessInfo->NextEntryOffset == 0) {
  3045. break;
  3046. }
  3047. TotalOffset += pProcessInfo->NextEntryOffset;
  3048. pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
  3049. }
  3050. VirtualFree(LargeBuffer1, 0, MEM_RELEASE);
  3051. return status;
  3052. }
  3053. //
  3054. // This routine moves the temporary MOF_VERSION list
  3055. // into the VersionHeader list for this GUID (MofInfo)
  3056. //
  3057. void
  3058. FlushMofVersionList( PMOF_INFO pMofInfo, PLIST_ENTRY ListHead )
  3059. {
  3060. PMOF_VERSION pMofVersion;
  3061. PLIST_ENTRY Head = ListHead;
  3062. PLIST_ENTRY Next = Head->Flink;
  3063. while( Head != Next ){
  3064. pMofVersion = CONTAINING_RECORD(Next, MOF_VERSION, Entry);
  3065. Next = Next->Flink;
  3066. RemoveEntryList(&pMofVersion->Entry);
  3067. if (pMofInfo != NULL) {
  3068. InsertTailList( &pMofInfo->VersionHeader, &pMofVersion->Entry);
  3069. }
  3070. else {
  3071. free(pMofVersion);
  3072. //
  3073. // Really should not hit this case
  3074. //
  3075. /*
  3076. #if DBG
  3077. DbgPrint("TRACECTR: FlushMofVersionList. MofInfo ptr is NULL\n");
  3078. ASSERT (pMofInfo != NULL);
  3079. #endif
  3080. */
  3081. }
  3082. }
  3083. }
  3084. void
  3085. DumpMofVersionItem(
  3086. PMOF_VERSION pMofVersion
  3087. )
  3088. {
  3089. PLIST_ENTRY Head = &pMofVersion->ItemHeader;
  3090. PLIST_ENTRY Next = Head->Flink;
  3091. PITEM_DESC pItem;
  3092. DbgPrint("MOF_VERSION: Version %d Level %d Type %d strType %ws\n",
  3093. pMofVersion->Version,
  3094. pMofVersion->Level,
  3095. pMofVersion->TypeIndex,
  3096. pMofVersion->strType);
  3097. while( Head != Next ){
  3098. pItem = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
  3099. Next = Next->Flink;
  3100. DbgPrint("Name %ws Size %d ItemType %d\n", pItem->strDescription, pItem->DataSize, pItem->ItemType);
  3101. }
  3102. }
  3103. void
  3104. DumpMofList()
  3105. {
  3106. PMOF_INFO pMofInfo;
  3107. PLIST_ENTRY Head = &CurrentSystem.EventListHead;
  3108. PLIST_ENTRY Next = Head->Flink;
  3109. while( Head != Next ){
  3110. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  3111. Next = Next->Flink;
  3112. //
  3113. // Count the MOF Fields for this Guid and Type
  3114. //
  3115. DbgPrint("Name %ws KernelEvent %d\n", pMofInfo->strDescription,
  3116. pMofInfo->bKernelEvent);
  3117. }
  3118. }
  3119. PMOF_VERSION
  3120. GetGuids( GUID Guid, SHORT nVersion, CHAR nLevel, SHORT nType, BOOL bKernelEvent )
  3121. {
  3122. if ( TraceContext->Flags & TRACE_USE_WBEM ){
  3123. return GetGuidsWBEM( Guid, nVersion, nLevel, nType, bKernelEvent );
  3124. }else{
  3125. return GetGuidsFile( Guid, nVersion, nLevel, nType, bKernelEvent );
  3126. }
  3127. }
  3128. HRESULT
  3129. WbemConnect( IWbemServices** pWbemServices )
  3130. {
  3131. IWbemLocator *pLocator = NULL;
  3132. BSTR bszNamespace = SysAllocString( L"root\\wmi" );
  3133. HRESULT hr = CoInitialize(0);
  3134. hr = CoCreateInstance(
  3135. CLSID_WbemLocator,
  3136. 0,
  3137. CLSCTX_INPROC_SERVER,
  3138. IID_IWbemLocator,
  3139. (LPVOID *) &pLocator
  3140. );
  3141. CHECK_HR( hr );
  3142. hr = pLocator->ConnectServer(
  3143. bszNamespace,
  3144. NULL,
  3145. NULL,
  3146. NULL,
  3147. 0L,
  3148. NULL,
  3149. NULL,
  3150. pWbemServices
  3151. );
  3152. CHECK_HR( hr );
  3153. hr = CoSetProxyBlanket(
  3154. *pWbemServices,
  3155. RPC_C_AUTHN_WINNT,
  3156. RPC_C_AUTHZ_NONE,
  3157. NULL,
  3158. RPC_C_AUTHN_LEVEL_PKT,
  3159. RPC_C_IMP_LEVEL_IMPERSONATE,
  3160. NULL,
  3161. EOAC_NONE
  3162. );
  3163. cleanup:
  3164. SysFreeString( bszNamespace );
  3165. if( pLocator ){
  3166. pLocator->Release();
  3167. pLocator = NULL;
  3168. }
  3169. return hr;
  3170. }
  3171. ULONG GetArraySize(
  3172. IN IWbemQualifierSet *pQualSet
  3173. )
  3174. {
  3175. ULONG ArraySize = 1;
  3176. VARIANT pVal;
  3177. BSTR bszMaxLen;
  3178. HRESULT hRes;
  3179. if (pQualSet == NULL){
  3180. return ArraySize;
  3181. }
  3182. bszMaxLen = SysAllocString(L"MAX");
  3183. VariantInit(&pVal);
  3184. hRes = pQualSet->Get(bszMaxLen,
  3185. 0,
  3186. &pVal,
  3187. 0);
  3188. SysFreeString(bszMaxLen);
  3189. if (ERROR_SUCCESS == hRes && pVal.vt == VT_I4 ){
  3190. ArraySize = pVal.lVal;
  3191. }
  3192. VariantClear(&pVal);
  3193. return ArraySize;
  3194. }
  3195. ITEM_TYPE
  3196. GetItemType(
  3197. IN CIMTYPE_ENUMERATION CimType,
  3198. IN IWbemQualifierSet *pQualSet
  3199. )
  3200. {
  3201. ITEM_TYPE Type = ItemUnknown;;
  3202. VARIANT pVal;
  3203. HRESULT hRes;
  3204. BSTR bszQualName;
  3205. WCHAR strFormat[10];
  3206. WCHAR strTermination[30];
  3207. WCHAR strTemp[30];
  3208. BOOLEAN IsPointer = FALSE;
  3209. strFormat[0] = '\0';
  3210. strTermination[0] = '\0';
  3211. strTemp[0] = '\0';
  3212. if (pQualSet == NULL)
  3213. return ItemUnknown;
  3214. bszQualName = SysAllocString(L"format");
  3215. VariantInit(&pVal);
  3216. hRes = pQualSet->Get(bszQualName,
  3217. 0,
  3218. &pVal,
  3219. 0);
  3220. SysFreeString(bszQualName);
  3221. if (ERROR_SUCCESS == hRes && NULL != pVal.bstrVal)
  3222. wcscpy(strFormat, pVal.bstrVal);
  3223. bszQualName = SysAllocString(L"StringTermination");
  3224. VariantClear(&pVal);
  3225. hRes = pQualSet->Get(bszQualName,
  3226. 0,
  3227. &pVal,
  3228. 0);
  3229. SysFreeString(bszQualName);
  3230. if (ERROR_SUCCESS == hRes && NULL != pVal.bstrVal)
  3231. wcscpy(strTermination, pVal.bstrVal);
  3232. bszQualName = SysAllocString(L"pointer");
  3233. VariantClear(&pVal);
  3234. hRes = pQualSet->Get(bszQualName,
  3235. 0,
  3236. &pVal,
  3237. 0);
  3238. SysFreeString(bszQualName);
  3239. if (ERROR_SUCCESS == hRes)
  3240. IsPointer = TRUE;
  3241. // Major fix required to get rid of temp
  3242. bszQualName = SysAllocString(L"extension");
  3243. VariantClear(&pVal);
  3244. hRes = pQualSet->Get(bszQualName,
  3245. 0,
  3246. &pVal,
  3247. 0);
  3248. SysFreeString(bszQualName);
  3249. if (ERROR_SUCCESS == hRes && NULL != pVal.bstrVal)
  3250. wcscpy(strTemp, pVal.bstrVal);
  3251. VariantClear(&pVal);
  3252. CimType = (CIMTYPE_ENUMERATION)(CimType & (~CIM_FLAG_ARRAY));
  3253. switch (CimType) {
  3254. case CIM_EMPTY:
  3255. Type = ItemUnknown;
  3256. break;
  3257. case CIM_SINT8:
  3258. Type = ItemCharShort;
  3259. if (!_wcsicmp(strFormat, L"c")){
  3260. Type = ItemChar;
  3261. }
  3262. break;
  3263. case CIM_UINT8:
  3264. Type = ItemUChar;
  3265. if (!_wcsicmp(strTemp, L"NoPrint")) {
  3266. Type = ItemCharHidden;
  3267. }
  3268. break;
  3269. case CIM_SINT16:
  3270. Type = ItemShort;
  3271. break;
  3272. case CIM_UINT16:
  3273. Type = ItemUShort;
  3274. break;
  3275. case CIM_SINT32:
  3276. Type = ItemLong;
  3277. break;
  3278. case CIM_UINT32:
  3279. Type = ItemULong;
  3280. if (!_wcsicmp(strFormat, L"x")){
  3281. Type = ItemULongX;
  3282. }
  3283. break;
  3284. case CIM_SINT64:
  3285. Type = ItemLongLong;
  3286. break;
  3287. case CIM_UINT64:
  3288. Type = ItemULongLong;
  3289. break;
  3290. case CIM_BOOLEAN:
  3291. // ItemBool
  3292. Type = ItemBool;
  3293. break;
  3294. case CIM_STRING:
  3295. if (!_wcsicmp(strTermination, L"NullTerminated")) {
  3296. if (!_wcsicmp(strFormat, L"w"))
  3297. Type = ItemWString;
  3298. else
  3299. Type = ItemString;
  3300. }
  3301. else if (!_wcsicmp(strTermination, L"Counted")) {
  3302. if (!_wcsicmp(strFormat, L"w"))
  3303. Type = ItemPWString;
  3304. else
  3305. Type = ItemPString;
  3306. }
  3307. else if (!_wcsicmp(strTermination, L"ReverseCounted")) {
  3308. if (!_wcsicmp(strFormat, L"w"))
  3309. Type = ItemDSWString;
  3310. else
  3311. Type = ItemDSString;
  3312. }
  3313. else if (!_wcsicmp(strTermination, L"NotCounted")) {
  3314. Type = ItemNWString;
  3315. }else{
  3316. Type = ItemString;
  3317. }
  3318. break;
  3319. case CIM_CHAR16:
  3320. // ItemWChar
  3321. Type = ItemWChar;
  3322. break;
  3323. // Major fix required for executing methods from WBEM
  3324. case CIM_OBJECT :
  3325. if (!_wcsicmp(strTemp, L"Port"))
  3326. Type = ItemPort;
  3327. else if (!_wcsicmp(strTemp, L"RString"))
  3328. Type = ItemRString;
  3329. else if (!_wcsicmp(strTemp, L"RWString"))
  3330. Type = ItemRWString;
  3331. else if (!_wcsicmp(strTemp, L"IPAddr"))
  3332. Type = ItemIPAddr;
  3333. else if (!_wcsicmp(strTemp, L"Sid"))
  3334. Type = ItemSid;
  3335. else if (!_wcsicmp(strTemp, L"Guid"))
  3336. Type = ItemGuid;
  3337. else if (!_wcsicmp(strTemp, L"Variant"))
  3338. Type = ItemVariant;
  3339. else
  3340. Type = ItemUnknown;
  3341. break;
  3342. case CIM_REAL32:
  3343. case CIM_REAL64:
  3344. case CIM_DATETIME:
  3345. case CIM_REFERENCE:
  3346. case CIM_ILLEGAL:
  3347. default:
  3348. Type = ItemUnknown;
  3349. break;
  3350. }
  3351. if (IsPointer)
  3352. Type = ItemPtr;
  3353. return Type;
  3354. }
  3355. PMOF_VERSION
  3356. GetPropertiesFromWBEM(
  3357. // IWbemServices *pWbemServices,
  3358. IWbemClassObject *pTraceSubClasses,
  3359. GUID Guid,
  3360. SHORT nVersion,
  3361. CHAR nLevel,
  3362. SHORT nType,
  3363. BOOL bKernelEvent
  3364. )
  3365. {
  3366. IEnumWbemClassObject *pEnumTraceSubSubClasses = NULL;
  3367. IWbemClassObject *pTraceSubSubClasses = NULL;
  3368. IWbemQualifierSet *pQualSet = NULL;
  3369. PMOF_INFO pMofInfo = NULL;
  3370. PMOF_VERSION pMofLookup = NULL, pMofVersion = NULL;
  3371. BSTR bszClassName = NULL;
  3372. BSTR bszSubClassName = NULL;
  3373. BSTR bszWmiDataId = NULL;
  3374. BSTR bszEventType = NULL;
  3375. BSTR bszEventTypeName = NULL;
  3376. BSTR bszFriendlyName = NULL;
  3377. BSTR bszPropName = NULL;
  3378. TCHAR strClassName[MAXSTR];
  3379. TCHAR strType[MAXSTR];
  3380. LONG pVarType;
  3381. SHORT nEventType = EVENT_TYPE_DEFAULT;
  3382. LIST_ENTRY ListHead;
  3383. HRESULT hRes;
  3384. VARIANT pVal;
  3385. VARIANT pTypeVal;
  3386. VARIANT pTypeNameVal;
  3387. VARIANT pClassName;
  3388. ULONG lEventTypeWbem; // when types are in an array.
  3389. ULONG HUGEP *pTypeData;
  3390. BSTR HUGEP *pTypeNameData;
  3391. SAFEARRAY *PropArray = NULL;
  3392. SAFEARRAY *TypeArray = NULL;
  3393. SAFEARRAY *TypeNameArray = NULL;
  3394. long lLower, lUpper, lCount, IdIndex;
  3395. long lTypeLower, lTypeUpper;
  3396. long lTypeNameLower, lTypeNameUpper;
  3397. ULONG ArraySize;
  3398. ITEM_TYPE ItemType;
  3399. InitializeListHead(&ListHead);
  3400. VariantInit(&pVal);
  3401. VariantInit(&pTypeVal);
  3402. VariantInit(&pTypeNameVal);
  3403. VariantInit(&pClassName);
  3404. pMofInfo = GetMofInfoHead( &Guid );
  3405. if( NULL == pMofInfo ){
  3406. return NULL;
  3407. }
  3408. pMofInfo->bKernelEvent = bKernelEvent;
  3409. bszClassName = SysAllocString(L"__CLASS");
  3410. bszWmiDataId = SysAllocString(L"WmiDataId");
  3411. bszEventType = SysAllocString(L"EventType");
  3412. bszEventTypeName = SysAllocString(L"EventTypeName");
  3413. bszFriendlyName = SysAllocString(L"DisplayName");
  3414. hRes = pTraceSubClasses->Get(bszClassName, // property name
  3415. 0L,
  3416. &pVal, // output to this variant
  3417. NULL,
  3418. NULL);
  3419. if (ERROR_SUCCESS == hRes){
  3420. if (pQualSet) {
  3421. pQualSet->Release();
  3422. pQualSet = NULL;
  3423. }
  3424. // Get Qualifier Set to obtain the friendly name.
  3425. pTraceSubClasses->GetQualifierSet(&pQualSet);
  3426. hRes = pQualSet->Get(bszFriendlyName,
  3427. 0,
  3428. &pClassName,
  3429. 0);
  3430. if (ERROR_SUCCESS == hRes && pClassName.bstrVal != NULL) {
  3431. wcscpy(strClassName, pClassName.bstrVal);
  3432. pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(strClassName) + 1) * sizeof(TCHAR));
  3433. if (NULL != pMofInfo->strDescription) {
  3434. _tcscpy(pMofInfo->strDescription, strClassName);
  3435. }
  3436. }else{
  3437. strClassName[0] = L'\0';
  3438. }
  3439. // Put Event Header
  3440. pMofVersion = GetNewMofVersion(
  3441. EVENT_TYPE_DEFAULT,
  3442. EVENT_VERSION_DEFAULT,
  3443. EVENT_LEVEL_DEFAULT
  3444. );
  3445. if (pMofVersion != NULL) {
  3446. pMofLookup = pMofVersion;
  3447. InsertTailList(&ListHead, &pMofVersion->Entry);
  3448. }
  3449. else{
  3450. goto cleanup;
  3451. }
  3452. // Create an enumerator to find derived classes.
  3453. bszSubClassName = SysAllocString(pVal.bstrVal);
  3454. hRes = pWbemServices->CreateClassEnum (
  3455. bszSubClassName, // class name
  3456. WBEM_FLAG_SHALLOW | WBEM_FLAG_USE_AMENDED_QUALIFIERS, // shallow search
  3457. NULL,
  3458. &pEnumTraceSubSubClasses
  3459. );
  3460. SysFreeString ( bszSubClassName );
  3461. if (ERROR_SUCCESS == hRes) {
  3462. ULONG uReturnedSub = 1;
  3463. while(uReturnedSub == 1){
  3464. // For each event in the subclass
  3465. pTraceSubSubClasses = NULL;
  3466. hRes = pEnumTraceSubSubClasses->Next((-1), // timeout in infinite seconds
  3467. 1, // return just one instance
  3468. &pTraceSubSubClasses, // pointer to a Sub class
  3469. &uReturnedSub); // number obtained: one or zero
  3470. if (ERROR_SUCCESS == hRes && uReturnedSub == 1) {
  3471. if (pQualSet) {
  3472. pQualSet->Release();
  3473. pQualSet = NULL;
  3474. }
  3475. // Get Qualifier Set.
  3476. pTraceSubSubClasses->GetQualifierSet(&pQualSet);
  3477. // Get Type number among Qualifiers
  3478. VariantClear(&pTypeVal);
  3479. hRes = pQualSet->Get(bszEventType,
  3480. 0,
  3481. &pTypeVal,
  3482. 0);
  3483. if (ERROR_SUCCESS == hRes) {
  3484. TypeArray = NULL;
  3485. TypeNameArray = NULL;
  3486. if (pTypeVal.vt & VT_ARRAY) { // EventType is an array
  3487. TypeArray = pTypeVal.parray;
  3488. VariantClear(&pTypeNameVal);
  3489. hRes = pQualSet->Get(bszEventTypeName,
  3490. 0,
  3491. &pTypeNameVal,
  3492. 0);
  3493. if ((ERROR_SUCCESS == hRes) && (pTypeNameVal.vt & VT_ARRAY)) {
  3494. TypeNameArray = pTypeNameVal.parray;
  3495. }
  3496. if (TypeArray != NULL) {
  3497. hRes = SafeArrayGetLBound(TypeArray, 1, &lTypeLower);
  3498. if (ERROR_SUCCESS != hRes) {
  3499. break;
  3500. }
  3501. hRes = SafeArrayGetUBound(TypeArray, 1, &lTypeUpper);
  3502. if (ERROR_SUCCESS != hRes) {
  3503. break;
  3504. }
  3505. if (lTypeUpper < 0) {
  3506. break;
  3507. }
  3508. SafeArrayAccessData(TypeArray, (void HUGEP **)&pTypeData );
  3509. if (TypeNameArray != NULL) {
  3510. hRes = SafeArrayGetLBound(TypeNameArray, 1, &lTypeNameLower);
  3511. if (ERROR_SUCCESS != hRes) {
  3512. break;
  3513. }
  3514. hRes = SafeArrayGetUBound(TypeNameArray, 1, &lTypeNameUpper);
  3515. if (ERROR_SUCCESS != hRes) {
  3516. break;
  3517. }
  3518. if (lTypeNameUpper < 0)
  3519. break;
  3520. SafeArrayAccessData(TypeNameArray, (void HUGEP **)&pTypeNameData );
  3521. }
  3522. for (lCount = lTypeLower; lCount <= lTypeUpper; lCount++) {
  3523. lEventTypeWbem = pTypeData[lCount];
  3524. nEventType = (SHORT)lEventTypeWbem;
  3525. pMofVersion = GetNewMofVersion(nEventType, nVersion, nLevel);
  3526. if (pMofVersion != NULL) {
  3527. InsertTailList(&ListHead, &pMofVersion->Entry);
  3528. if (nType == nEventType) {
  3529. // Type matched
  3530. pMofLookup = pMofVersion;
  3531. }
  3532. if (TypeNameArray != NULL) {
  3533. if ((lCount >= lTypeNameLower) && (lCount <= lTypeNameUpper)) {
  3534. pMofVersion->strType = (LPTSTR)malloc((_tcslen(pTypeNameData[lCount]) + 1) * sizeof(TCHAR));
  3535. if (pMofVersion->strType != NULL){
  3536. wcscpy(pMofVersion->strType, (LPWSTR)(pTypeNameData[lCount]));
  3537. }
  3538. }
  3539. }
  3540. }
  3541. }
  3542. SafeArrayUnaccessData(TypeArray);
  3543. SafeArrayDestroy(TypeArray);
  3544. VariantInit(&pTypeVal);
  3545. if (TypeNameArray != NULL) {
  3546. SafeArrayUnaccessData(TypeNameArray);
  3547. SafeArrayDestroy(TypeNameArray);
  3548. VariantInit(&pTypeNameVal);
  3549. }
  3550. }
  3551. else {
  3552. //
  3553. // If the Types or TypeName is not found, then bail
  3554. //
  3555. break;
  3556. }
  3557. }
  3558. else { // EventType is scalar
  3559. hRes = VariantChangeType(&pTypeVal, &pTypeVal, 0, VT_I2);
  3560. if (ERROR_SUCCESS == hRes)
  3561. nEventType = (SHORT)V_I2(&pTypeVal);
  3562. else
  3563. nEventType = (SHORT)V_I4(&pTypeVal);
  3564. VariantClear(&pTypeNameVal);
  3565. hRes = pQualSet->Get(bszEventTypeName,
  3566. 0,
  3567. &pTypeNameVal,
  3568. 0);
  3569. if (ERROR_SUCCESS == hRes) {
  3570. wcscpy(strType, pTypeNameVal.bstrVal);
  3571. }
  3572. else{
  3573. strType[0] = '\0';
  3574. }
  3575. pMofVersion = GetNewMofVersion(nEventType, nVersion, nLevel);
  3576. if (pMofVersion != NULL) {
  3577. InsertTailList(&ListHead, &pMofVersion->Entry);
  3578. if (nType == nEventType) {
  3579. // Type matched
  3580. pMofLookup = pMofVersion;
  3581. }
  3582. pMofVersion->strType = (LPTSTR)malloc((_tcslen(strType) + 1) * sizeof(TCHAR));
  3583. if (pMofVersion->strType != NULL){
  3584. _tcscpy(pMofVersion->strType, strType);
  3585. }
  3586. }
  3587. }
  3588. // Get event layout
  3589. VariantClear(&pVal);
  3590. IdIndex = 1;
  3591. V_VT(&pVal) = VT_I4;
  3592. V_I4(&pVal) = IdIndex;
  3593. // For each property
  3594. PropArray = NULL;
  3595. while (pTraceSubSubClasses->GetNames(bszWmiDataId, // only properties with WmiDataId qualifier
  3596. WBEM_FLAG_ONLY_IF_IDENTICAL,
  3597. &pVal, // WmiDataId number starting from 1
  3598. &PropArray) == WBEM_NO_ERROR) {
  3599. hRes = SafeArrayGetLBound(PropArray, 1, &lLower);
  3600. if (ERROR_SUCCESS != hRes) {
  3601. break;
  3602. }
  3603. hRes = SafeArrayGetUBound(PropArray, 1, &lUpper);
  3604. if (ERROR_SUCCESS != hRes) {
  3605. break;
  3606. }
  3607. if (lUpper < 0)
  3608. break;
  3609. // This loop will iterate just once.
  3610. for (lCount = lLower; lCount <= lUpper; lCount++) {
  3611. hRes = SafeArrayGetElement(PropArray, &lCount, &bszPropName);
  3612. if (ERROR_SUCCESS != hRes) {
  3613. break;
  3614. }
  3615. hRes = pTraceSubSubClasses->Get(bszPropName, // Property name
  3616. 0L,
  3617. NULL,
  3618. &pVarType, // CIMTYPE of the property
  3619. NULL);
  3620. if (ERROR_SUCCESS != hRes) {
  3621. break;
  3622. }
  3623. // Get the Qualifier set for the property
  3624. if (pQualSet) {
  3625. pQualSet->Release();
  3626. pQualSet = NULL;
  3627. }
  3628. hRes = pTraceSubSubClasses->GetPropertyQualifierSet(bszPropName,
  3629. &pQualSet);
  3630. if (ERROR_SUCCESS != hRes) {
  3631. break;
  3632. }
  3633. ItemType = GetItemType((CIMTYPE_ENUMERATION)pVarType, pQualSet);
  3634. if( pVarType & CIM_FLAG_ARRAY ){
  3635. ArraySize = GetArraySize(pQualSet);
  3636. }else{
  3637. ArraySize = 1;
  3638. }
  3639. AddMofInfo(&ListHead,
  3640. bszPropName,
  3641. ItemType,
  3642. ArraySize);
  3643. }
  3644. SafeArrayDestroy(PropArray);
  3645. PropArray = NULL;
  3646. V_I4(&pVal) = ++IdIndex;
  3647. } // end enumerating through WmiDataId
  3648. FlushMofVersionList(pMofInfo, &ListHead);
  3649. } // if getting event type was successful
  3650. } // if enumeration returned a subclass successfully
  3651. } // end enumerating subclasses
  3652. } // if enumeration was created successfully
  3653. } // if getting class name was successful
  3654. cleanup:
  3655. VariantClear(&pVal);
  3656. VariantClear(&pTypeVal);
  3657. VariantClear(&pClassName);
  3658. SysFreeString(bszClassName);
  3659. SysFreeString(bszWmiDataId);
  3660. SysFreeString(bszEventType);
  3661. SysFreeString(bszEventTypeName);
  3662. SysFreeString(bszFriendlyName);
  3663. // Should not free bszPropName becuase it is already freed by SafeArrayDestroy
  3664. FlushMofVersionList(pMofInfo, &ListHead);
  3665. return pMofLookup;
  3666. }
  3667. PMOF_VERSION
  3668. GetGuidsWBEM ( GUID Guid, SHORT nVersion, CHAR nLevel, SHORT nType, BOOL bKernelEvent )
  3669. {
  3670. IEnumWbemClassObject *pEnumTraceSubClasses = NULL, *pEnumTraceSubSubClasses = NULL;
  3671. IWbemClassObject *pTraceSubClasses = NULL, *pTraceSubSubClasses = NULL;
  3672. IWbemQualifierSet *pQualSet = NULL;
  3673. BSTR bszInstance = NULL;
  3674. BSTR bszPropertyName = NULL;
  3675. BSTR bszSubClassName = NULL;
  3676. BSTR bszGuid = NULL;
  3677. BSTR bszVersion = NULL;
  3678. TCHAR strGuid[MAXSTR], strTargetGuid[MAXSTR];
  3679. HRESULT hRes;
  3680. VARIANT pVal;
  3681. VARIANT pGuidVal;
  3682. VARIANT pVersionVal;
  3683. UINT nCounter=0;
  3684. BOOLEAN MatchFound;
  3685. SHORT nEventVersion = EVENT_VERSION_DEFAULT;
  3686. PMOF_VERSION pMofLookup = NULL;
  3687. VariantInit(&pVal);
  3688. VariantInit(&pGuidVal);
  3689. VariantInit(&pVersionVal);
  3690. if (NULL == pWbemServices) {
  3691. hRes = WbemConnect( &pWbemServices );
  3692. CHECK_HR( hRes );
  3693. }
  3694. // Convert traget GUID to string for later comparison
  3695. CpdiGuidToString(strTargetGuid, &Guid);
  3696. bszInstance = SysAllocString(L"EventTrace");
  3697. bszPropertyName = SysAllocString(L"__CLASS");
  3698. bszGuid = SysAllocString(L"Guid");
  3699. bszVersion = SysAllocString(L"EventVersion");
  3700. pEnumTraceSubClasses = NULL;
  3701. // Get an enumerator for all classes under "EventTace".
  3702. hRes = pWbemServices->CreateClassEnum (
  3703. bszInstance,
  3704. WBEM_FLAG_SHALLOW | WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  3705. NULL,
  3706. &pEnumTraceSubClasses );
  3707. SysFreeString (bszInstance);
  3708. if (ERROR_SUCCESS == hRes) {
  3709. ULONG uReturned = 1;
  3710. MatchFound = FALSE;
  3711. while (uReturned == 1) {
  3712. pTraceSubClasses = NULL;
  3713. // Get the next ClassObject.
  3714. hRes = pEnumTraceSubClasses->Next((-1), // timeout in infinite seconds
  3715. 1, // return just one instance
  3716. &pTraceSubClasses, // pointer to Event Trace Sub Class
  3717. &uReturned); // number obtained: one or zero
  3718. if (ERROR_SUCCESS == hRes && (uReturned == 1)) {
  3719. // Get the class name
  3720. hRes = pTraceSubClasses->Get(bszPropertyName, // property name
  3721. 0L,
  3722. &pVal, // output to this variant
  3723. NULL,
  3724. NULL);
  3725. if (ERROR_SUCCESS == hRes){
  3726. bszSubClassName = SysAllocString(pVal.bstrVal);
  3727. // Create an enumerator to find derived classes.
  3728. hRes = pWbemServices->CreateClassEnum (
  3729. bszSubClassName,
  3730. WBEM_FLAG_SHALLOW | WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  3731. NULL,
  3732. &pEnumTraceSubSubClasses
  3733. );
  3734. SysFreeString ( bszSubClassName );
  3735. VariantClear(&pVal);
  3736. if (ERROR_SUCCESS == hRes) {
  3737. ULONG uReturnedSub = 1;
  3738. MatchFound = FALSE;
  3739. while(uReturnedSub == 1){
  3740. pTraceSubSubClasses = NULL;
  3741. // enumerate through the resultset.
  3742. hRes = pEnumTraceSubSubClasses->Next((-1), // timeout in infinite seconds
  3743. 1, // return just one instance
  3744. &pTraceSubSubClasses, // pointer to a Sub class
  3745. &uReturnedSub); // number obtained: one or zero
  3746. if (ERROR_SUCCESS == hRes && uReturnedSub == 1) {
  3747. // Get the subclass name
  3748. hRes = pTraceSubSubClasses->Get(bszPropertyName, // Class name
  3749. 0L,
  3750. &pVal, // output to this variant
  3751. NULL,
  3752. NULL);
  3753. VariantClear(&pVal);
  3754. if (ERROR_SUCCESS == hRes){
  3755. // Get Qualifier Set.
  3756. if (pQualSet) {
  3757. pQualSet->Release();
  3758. pQualSet = NULL;
  3759. }
  3760. pTraceSubSubClasses->GetQualifierSet (&pQualSet );
  3761. // Get GUID among Qualifiers
  3762. hRes = pQualSet->Get(bszGuid,
  3763. 0,
  3764. &pGuidVal,
  3765. 0);
  3766. if (ERROR_SUCCESS == hRes) {
  3767. _tcscpy(strGuid, (LPTSTR)V_BSTR(&pGuidVal));
  3768. VariantClear ( &pGuidVal );
  3769. if (!_tcsstr(strGuid, _T("{")))
  3770. _stprintf(strGuid , _T("{%s}"), strGuid);
  3771. if (!_tcsicmp(strTargetGuid, strGuid)) {
  3772. hRes = pQualSet->Get(bszVersion,
  3773. 0,
  3774. &pVersionVal,
  3775. 0);
  3776. if (ERROR_SUCCESS == hRes) {
  3777. hRes = VariantChangeType(&pVersionVal, &pVersionVal, 0, VT_I2);
  3778. if (ERROR_SUCCESS == hRes)
  3779. nEventVersion = (SHORT)V_I2(&pVersionVal);
  3780. else
  3781. nEventVersion = (SHORT)V_I4(&pVersionVal);
  3782. VariantClear(&pVersionVal);
  3783. if (nVersion == nEventVersion) {
  3784. //_tprintf(_T("Match Found: \t%s\t, version %d\n"), strGuid, nVersion);
  3785. // Match is found.
  3786. // Now put all events in this subtree into the list
  3787. MatchFound = TRUE;
  3788. pMofLookup = GetPropertiesFromWBEM( pTraceSubSubClasses,
  3789. Guid,
  3790. nVersion,
  3791. nLevel,
  3792. nType,
  3793. bKernelEvent
  3794. );
  3795. break;
  3796. }
  3797. }
  3798. else {
  3799. // if there is no version number for this event
  3800. MatchFound = TRUE;
  3801. //_tprintf(_T("Close Match Found: \t%s\t, version %d\n"), strGuid, nEventVersion);
  3802. pMofLookup = GetPropertiesFromWBEM( pTraceSubSubClasses,
  3803. Guid,
  3804. EVENT_VERSION_DEFAULT,
  3805. nLevel,
  3806. nType,
  3807. bKernelEvent
  3808. );
  3809. break;
  3810. }
  3811. }
  3812. }
  3813. }
  3814. }
  3815. } // end while enumerating sub classes
  3816. if (MatchFound) {
  3817. break;
  3818. }
  3819. if (pEnumTraceSubSubClasses) {
  3820. pEnumTraceSubSubClasses->Release();
  3821. pEnumTraceSubSubClasses = NULL;
  3822. }
  3823. } // if creating enumeration was successful
  3824. } // if getting class name was successful
  3825. }
  3826. nCounter++;
  3827. // if match is found, break out of the top level search
  3828. if (MatchFound)
  3829. break;
  3830. } // end while enumerating top classes
  3831. if( pEnumTraceSubClasses ){
  3832. pEnumTraceSubClasses->Release();
  3833. pEnumTraceSubClasses = NULL;
  3834. }
  3835. } // if creating enumeration for top level is successful
  3836. cleanup:
  3837. VariantClear(&pGuidVal);
  3838. VariantClear(&pVersionVal);
  3839. SysFreeString(bszGuid);
  3840. SysFreeString(bszPropertyName);
  3841. SysFreeString(bszVersion);
  3842. if (pEnumTraceSubClasses){
  3843. pEnumTraceSubClasses->Release();
  3844. pEnumTraceSubClasses = NULL;
  3845. }
  3846. if (pEnumTraceSubSubClasses){
  3847. pEnumTraceSubSubClasses->Release();
  3848. pEnumTraceSubSubClasses = NULL;
  3849. }
  3850. if (pQualSet) {
  3851. pQualSet->Release();
  3852. pQualSet = NULL;
  3853. }
  3854. return pMofLookup;
  3855. }
  3856. PMOF_VERSION
  3857. GetGuidsFile( GUID Guid, SHORT nVersion, CHAR nLevel, SHORT nType, BOOL bKernelEvent )
  3858. {
  3859. FILE *f = NULL;
  3860. WCHAR line[MAXSTR];
  3861. WCHAR buffer[MAXSTR];
  3862. PMOF_INFO pMofInfo = NULL;
  3863. PMOF_VERSION pMofLookup = NULL;
  3864. PMOF_VERSION pMofVersion = NULL;
  3865. UINT i;
  3866. LPWSTR s;
  3867. UINT typeCount = 0;
  3868. BOOL bInInfo = FALSE;
  3869. BOOL bInGuid = FALSE;
  3870. SHORT nTypeIndex;
  3871. CHAR nLevelIndex = -1;
  3872. SHORT nVersionIndex = -1;
  3873. SHORT nMatchLevel = 0;
  3874. GUID guid;
  3875. LIST_ENTRY ListHead;
  3876. InitializeListHead( &ListHead );
  3877. //
  3878. // If MofFileName is given, use it. Otherwise, look for
  3879. // the default file mofdata.guid
  3880. //
  3881. if (TraceContext->MofFileName != NULL) {
  3882. f = _wfopen( TraceContext->MofFileName, L"r" );
  3883. if( !f ){
  3884. return NULL;
  3885. }
  3886. }else{
  3887. return NULL;
  3888. }
  3889. while ( fgetws(line, MAXSTR, f) != NULL ) {
  3890. UINT Index;
  3891. if(line[0] == '/'){
  3892. continue;
  3893. }
  3894. if(line[0] == '{' && bInGuid ){
  3895. bInInfo = TRUE;
  3896. }
  3897. else if ( line[0] == '}' && bInGuid ){
  3898. bInInfo = FALSE;
  3899. FlushMofVersionList( pMofInfo, &ListHead );
  3900. }
  3901. else if( bInInfo && bInGuid ){
  3902. ITEM_TYPE type;
  3903. LPWSTR strValue;
  3904. Index = 1;
  3905. strValue = wcstok(line, L"\n\t\r,");
  3906. s = wcstok( NULL, L" \n\t\r,[");
  3907. if(s != NULL && strValue != NULL ){
  3908. PWCHAR t;
  3909. while (*strValue == ' ') { // skip leading blanks
  3910. strValue++;
  3911. }
  3912. t = wcstok(NULL, L"]" );
  3913. if (t != NULL) {
  3914. Index = _wtoi(t);
  3915. }
  3916. if(! _wcsicmp(s,STR_ItemChar)) type = ItemChar;
  3917. else if(! _wcsicmp(s,STR_ItemCharHidden)) type = ItemCharHidden;
  3918. else if(! _wcsicmp(s,STR_ItemUChar)) type = ItemUChar;
  3919. else if(! _wcsicmp(s,STR_ItemCharShort))type = ItemCharShort;
  3920. else if(! _wcsicmp(s,STR_ItemCharSign)) type = ItemCharSign;
  3921. else if(! _wcsicmp(s,STR_ItemShort)) type = ItemShort;
  3922. else if(! _wcsicmp(s,STR_ItemUShort)) type = ItemUShort;
  3923. else if(! _wcsicmp(s,STR_ItemLong)) type = ItemLong;
  3924. else if(! _wcsicmp(s,STR_ItemULong)) type = ItemULong;
  3925. else if(! _wcsicmp(s,STR_ItemULongX)) type = ItemULongX;
  3926. else if(! _wcsicmp(s,STR_ItemLongLong)) type = ItemLongLong;
  3927. else if(! _wcsicmp(s,STR_ItemULongLong)) type = ItemULongLong;
  3928. else if(! _wcsicmp(s,STR_ItemString)) type = ItemString;
  3929. else if(! _wcsicmp(s,STR_ItemWString)) type = ItemWString;
  3930. else if(! _wcsicmp(s,STR_ItemRString)) type = ItemRString;
  3931. else if(! _wcsicmp(s,STR_ItemRWString)) type = ItemRWString;
  3932. else if(! _wcsicmp(s,STR_ItemPString)) type = ItemPString;
  3933. else if(! _wcsicmp(s,STR_ItemMLString)) type = ItemMLString;
  3934. else if(! _wcsicmp(s,STR_ItemNWString)) type = ItemNWString;
  3935. else if(! _wcsicmp(s,STR_ItemPWString)) type = ItemPWString;
  3936. else if(! _wcsicmp(s,STR_ItemDSString)) type = ItemDSString;
  3937. else if(! _wcsicmp(s,STR_ItemDSWString)) type = ItemDSWString;
  3938. else if(! _wcsicmp(s,STR_ItemSid)) type = ItemSid;
  3939. else if(! _wcsicmp(s,STR_ItemChar4)) type = ItemChar4;
  3940. else if(! _wcsicmp(s,STR_ItemIPAddr)) type = ItemIPAddr;
  3941. else if(! _wcsicmp(s,STR_ItemPort)) type = ItemPort;
  3942. else if(! _wcsicmp(s,STR_ItemPtr)) type = ItemPtr;
  3943. else if(! _wcsicmp(s,STR_ItemGuid)) type = ItemGuid;
  3944. else if(! _wcsicmp(s,STR_ItemOptArgs)) type = ItemOptArgs;
  3945. else if(! _wcsicmp(s,STR_ItemCPUTime)) type = ItemCPUTime;
  3946. else if(! _wcsicmp(s,STR_ItemVariant)) type = ItemVariant;
  3947. else if(! _wcsicmp(s,STR_ItemBool)) type = ItemBool;
  3948. else type = ItemUnknown;
  3949. AddMofInfo( &ListHead, strValue, (SHORT)type, Index );
  3950. }
  3951. }
  3952. else if( line[0] == '#' && bInGuid ){
  3953. LPWSTR strType;
  3954. LPWSTR strValue;
  3955. s = wcstok( line, L" \t");
  3956. if( NULL == s ){
  3957. continue;
  3958. }
  3959. if( line[1] == 'l' || line[1] == 'L' ){ // level
  3960. strValue = wcstok( NULL, L" \t\n\r" );
  3961. if( strValue != NULL ){
  3962. nLevelIndex = (CHAR)_wtoi( strValue );
  3963. }
  3964. }else if( line[1] == 'v' || line[1] == 'V' ){ // version
  3965. strValue = wcstok( NULL, L" \t\n\r" );
  3966. if( strValue != NULL ){
  3967. nVersionIndex = (SHORT)_wtoi( strValue );
  3968. }
  3969. typeCount = 0;
  3970. }else if( line[1] == 't' || line[1] == 'T' ){ // type
  3971. SHORT nMatchCheck = 0;
  3972. strType = wcstok( NULL, L" \t\n\r" );
  3973. strValue = wcstok( NULL, L"\"\n,\r" );
  3974. if( strType && strValue ){
  3975. nTypeIndex = (SHORT)_wtoi( strValue );
  3976. }else{
  3977. continue;
  3978. }
  3979. typeCount++;
  3980. if(typeCount >= MAXTYPE){
  3981. //fwprintf(stderr, L"Warning: Too many types defined\n");
  3982. }
  3983. pMofVersion = GetNewMofVersion( nTypeIndex, nVersionIndex, nLevelIndex );
  3984. if( NULL != pMofVersion ){
  3985. InsertTailList( (&ListHead), &pMofVersion->Entry);
  3986. pMofVersion->strType = (LPWSTR)malloc( ( lstrlenW(strType)+1) * sizeof(WCHAR) );
  3987. if( NULL != pMofVersion->strType ){
  3988. wcscpy( pMofVersion->strType, strType );
  3989. }
  3990. if( nTypeIndex == nType ){
  3991. nMatchCheck = 1;
  3992. if( nLevelIndex == nLevel ){
  3993. nMatchCheck++;
  3994. }
  3995. if( nVersionIndex == nVersion ){
  3996. nMatchCheck++;
  3997. }
  3998. }
  3999. if( nMatchCheck > nMatchLevel ){
  4000. nMatchLevel = nMatchCheck;
  4001. pMofLookup = pMofVersion;
  4002. }
  4003. }
  4004. }
  4005. }
  4006. else if ( (line[0] >= '0' && line[0] <= '9')
  4007. || (line[0] >= 'a' && line[0] <= 'f')
  4008. || (line[0] >= 'A' && line[0] <= 'F')) {
  4009. LPWSTR strName = NULL;
  4010. bInGuid = FALSE;
  4011. typeCount = 0;
  4012. wcsncpy(buffer, line, 8);
  4013. buffer[8] = 0;
  4014. guid.Data1 = ahextoi(&buffer[0]);
  4015. wcsncpy(buffer, &line[9], 4);
  4016. buffer[4] = 0;
  4017. guid.Data2 = (USHORT) ahextoi(&buffer[0]);
  4018. wcsncpy(buffer, &line[14], 4);
  4019. buffer[4] = 0;
  4020. guid.Data3 = (USHORT) ahextoi(buffer);
  4021. for (i=0; i<2; i++) {
  4022. wcsncpy(buffer, &line[19 + (i*2)], 2);
  4023. buffer[2] = 0;
  4024. guid.Data4[i] = (UCHAR) ahextoi(buffer);
  4025. }
  4026. for (i=2; i<8; i++) {
  4027. wcsncpy(buffer, &line[20 + (i*2)], 2);
  4028. buffer[2] = 0;
  4029. guid.Data4[i] = (UCHAR) ahextoi(buffer);
  4030. }
  4031. if( ! IsEqualGUID( &Guid, &guid ) ){
  4032. continue;
  4033. }
  4034. s = &line[36];
  4035. strName = wcstok( s, L" \n\t\r" );
  4036. if( NULL == strName ){ // Must have a name for the Guid.
  4037. continue;
  4038. }
  4039. bInGuid = TRUE;
  4040. FlushMofVersionList(pMofInfo, &ListHead );
  4041. pMofInfo = GetMofInfoHead( &Guid);
  4042. if (pMofInfo == NULL) {
  4043. return NULL;
  4044. }
  4045. pMofInfo->bKernelEvent = bKernelEvent;
  4046. pMofInfo->strDescription = (LPWSTR)malloc(( lstrlenW(strName)+1) * sizeof(WCHAR));
  4047. if( NULL != pMofInfo->strDescription ){
  4048. wcscpy(pMofInfo->strDescription, strName);
  4049. }
  4050. pMofVersion = GetNewMofVersion(
  4051. EVENT_TYPE_DEFAULT,
  4052. EVENT_VERSION_DEFAULT,
  4053. EVENT_LEVEL_DEFAULT
  4054. );
  4055. if (pMofVersion == NULL) {
  4056. return NULL;
  4057. }
  4058. pMofLookup = pMofVersion;
  4059. InsertTailList( (&ListHead), &pMofVersion->Entry);
  4060. }
  4061. }
  4062. FlushMofVersionList(pMofInfo, &ListHead );
  4063. fclose(f);
  4064. return pMofLookup;
  4065. }
  4066. VOID
  4067. UpdateThreadData(
  4068. PJOB_RECORD pJob,
  4069. PEVENT_TRACE_HEADER pHeader,
  4070. PTHREAD_RECORD pThread
  4071. )
  4072. {
  4073. unsigned long i = 0;
  4074. BOOLEAN bFound = FALSE;
  4075. if ( (pJob == NULL) || (pHeader == NULL) || (pThread == NULL) ) {
  4076. return;
  4077. }
  4078. for (i = 0; i < pJob->NumberOfThreads; i++) {
  4079. if (pJob->ThreadData[i].ThreadId == pHeader->ThreadId) {
  4080. bFound = TRUE;
  4081. break;
  4082. }
  4083. }
  4084. if ((i < MAX_THREADS) && !bFound) {
  4085. pJob->ThreadData[i].ThreadId = pHeader->ThreadId;
  4086. pJob->NumberOfThreads++;
  4087. bFound = TRUE;
  4088. }
  4089. if (bFound) {
  4090. //
  4091. // TODO: There is potential for double counting if the same thread
  4092. // came back and did more work for this job after having done work for an other
  4093. // job in between.
  4094. //
  4095. if (pJob->ThreadData[i].PrevKCPUTime > 0)
  4096. pJob->ThreadData[i].KCPUTime += pHeader->KernelTime * CurrentSystem.TimerResolution - pJob->ThreadData[i].PrevKCPUTime;
  4097. if (pJob->ThreadData[i].PrevUCPUTime > 0)
  4098. pJob->ThreadData[i].UCPUTime += pHeader->UserTime * CurrentSystem.TimerResolution - pJob->ThreadData[i].PrevUCPUTime;
  4099. if (pJob->ThreadData[i].PrevReadIO > 0)
  4100. pJob->ThreadData[i].ReadIO += pThread->ReadIO - pJob->ThreadData[i].PrevReadIO;
  4101. if (pJob->ThreadData[i].PrevWriteIO > 0)
  4102. pJob->ThreadData[i].WriteIO += pThread->WriteIO - pJob->ThreadData[i].PrevWriteIO;
  4103. pJob->ThreadData[i].PrevKCPUTime = pHeader->KernelTime * CurrentSystem.TimerResolution;
  4104. pJob->ThreadData[i].PrevUCPUTime = pHeader->UserTime * CurrentSystem.TimerResolution;
  4105. pJob->ThreadData[i].PrevReadIO = pThread->ReadIO;
  4106. pJob->ThreadData[i].PrevWriteIO = pThread->WriteIO;
  4107. }
  4108. }
  4109. VOID
  4110. PrintJobCallback(
  4111. PEVENT_TRACE pEvent
  4112. )
  4113. {
  4114. PTHREAD_RECORD pThread;
  4115. PEVENT_TRACE_HEADER pHeader;
  4116. PMOF_INFO pMofInfo;
  4117. ULONG JobId = 0;
  4118. PJOB_RECORD pJob;
  4119. if (pEvent == NULL)
  4120. return;
  4121. pHeader = (PEVENT_TRACE_HEADER)&pEvent->Header;
  4122. //
  4123. // Ignore Process/Thread Start/End transactions. Only go after
  4124. // User Defined Transactions.
  4125. //
  4126. pMofInfo = GetMofInfoHead( &pEvent->Header.Guid );
  4127. if (pMofInfo == NULL){
  4128. return;
  4129. }
  4130. if (!IsEqualGUID(&pEvent->Header.Guid, &ThreadGuid))
  4131. GetMofData(pEvent, L"JobId", &JobId, sizeof(ULONG));
  4132. pThread = FindGlobalThreadById(pHeader->ThreadId, pEvent);
  4133. if (JobId == 0) {
  4134. if (pThread == NULL) return;
  4135. JobId = pThread->JobId; // if Current Job Id is 0, use the cached one.
  4136. }
  4137. else {
  4138. if (pThread != NULL) {
  4139. if (JobId != pThread->JobId) {
  4140. pJob = FindJobRecord(pThread->JobId);
  4141. UpdateThreadData(pJob, pHeader, pThread);
  4142. }
  4143. pThread->JobId = JobId;
  4144. }
  4145. }
  4146. if (JobId == 0) return; // To filter all th termination without print jobs.
  4147. pJob = FindJobRecord(JobId);
  4148. if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_SPOOLJOB) {
  4149. if (pJob) {
  4150. // A job id is being reused before it was deleted from the last
  4151. // use. We must have missed a delete event, so just through the old
  4152. // job away.
  4153. EnterTracelibCritSection();
  4154. RemoveEntryList( &pJob->Entry );
  4155. LeaveTracelibCritSection();
  4156. free (pJob);
  4157. }
  4158. pJob = AddJobRecord(JobId);
  4159. if (pJob != NULL) {
  4160. pJob->StartTime = pEvent->Header.TimeStamp.QuadPart;
  4161. }
  4162. }
  4163. if (pJob == NULL) // if a Start event is lost for this job, this could happen.
  4164. return;
  4165. UpdateThreadData(pJob, pHeader, pThread);
  4166. // If you see any of these things then stop tracking resources on the
  4167. // thread.
  4168. if ((pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_ENDTRACKTHREAD) ||
  4169. (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_DELETEJOB) ||
  4170. (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_PAUSE) ||
  4171. (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_RESUME)) {
  4172. if (pThread != NULL)
  4173. pThread->JobId = 0;
  4174. }
  4175. if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_PAUSE) {
  4176. pJob->PauseStartTime = pEvent->Header.TimeStamp.QuadPart;
  4177. }
  4178. else if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_RESUME) {
  4179. pJob->PauseTime += (pEvent->Header.TimeStamp.QuadPart - pJob->PauseStartTime) / 10000;
  4180. pJob->PauseStartTime = 0;
  4181. }
  4182. else if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_PRINTJOB) {
  4183. pJob->PrintJobTime = pEvent->Header.TimeStamp.QuadPart;
  4184. }
  4185. else if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_DELETEJOB) {
  4186. unsigned long i;
  4187. pJob->EndTime = pEvent->Header.TimeStamp.QuadPart;
  4188. pJob->ResponseTime += (pEvent->Header.TimeStamp.QuadPart - pJob->StartTime) / 10000; // in msec
  4189. GetMofData(pEvent, L"JobSize", &pJob->JobSize, sizeof(ULONG));
  4190. GetMofData(pEvent, L"DataType", &pJob->DataType, sizeof(ULONG));
  4191. GetMofData(pEvent, L"Pages", &pJob->Pages, sizeof(ULONG));
  4192. GetMofData(pEvent, L"PagesPerSide", &pJob->PagesPerSide, sizeof(ULONG));
  4193. GetMofData(pEvent, L"FilesOpened", &pJob->FilesOpened, sizeof(SHORT));
  4194. pJob->KCPUTime = 0;
  4195. pJob->UCPUTime = 0;
  4196. pJob->ReadIO = 0;
  4197. pJob->WriteIO = 0;
  4198. for (i=0; i < pJob->NumberOfThreads; i++) {
  4199. pJob->KCPUTime += pJob->ThreadData[i].KCPUTime;
  4200. pJob->UCPUTime += pJob->ThreadData[i].UCPUTime;
  4201. pJob->ReadIO += pJob->ThreadData[i].ReadIO;
  4202. pJob->WriteIO += pJob->ThreadData[i].WriteIO;
  4203. }
  4204. DeleteJobRecord(pJob, (TraceContext->Flags & TRACE_SPOOLER));
  4205. }
  4206. else if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_SPL_JOBRENDERED) {
  4207. GetMofData(pEvent, L"GdiJobSize", &pJob->GdiJobSize, sizeof(ULONG));
  4208. GetMofData(pEvent, L"ICMMethod", &pJob->ICMMethod, sizeof(ULONG));
  4209. GetMofData(pEvent, L"Color", &pJob->Color, sizeof(SHORT));
  4210. GetMofData(pEvent, L"XRes", &pJob->XRes, sizeof(SHORT));
  4211. GetMofData(pEvent, L"YRes", &pJob->YRes, sizeof(SHORT));
  4212. GetMofData(pEvent, L"Quality", &pJob->Quality, sizeof(SHORT));
  4213. GetMofData(pEvent, L"Copies", &pJob->Copies, sizeof(SHORT));
  4214. GetMofData(pEvent, L"TTOption", &pJob->TTOption, sizeof(SHORT));
  4215. }
  4216. }
  4217. VOID
  4218. GeneralEventCallback(
  4219. PEVENT_TRACE pEvent
  4220. )
  4221. {
  4222. PTHREAD_RECORD pThread;
  4223. if ((pEvent == NULL) || (TraceContext == NULL))
  4224. return;
  4225. // If the ThreadId is -1 or the FieldTypeFlags in the event
  4226. // shows there is no CPU Time, ignore the event. This can happen
  4227. // when PERFINFO headers are found in kernel data.
  4228. //
  4229. if ( (pEvent->Header.ThreadId == -1) ||
  4230. (pEvent->Header.FieldTypeFlags & EVENT_TRACE_USE_NOCPUTIME) ) {
  4231. if (TraceContext->Flags & (TRACE_DUMP|TRACE_SUMMARY)) {
  4232. DumpEvent(pEvent);
  4233. }
  4234. return;
  4235. }
  4236. //
  4237. // Notes: This code is here to fix up the Event Record for the
  4238. // Idle Threads. Since Idle threads are not guaranteed to have
  4239. // Cid initialized, we could end up with bogus thread Ids.
  4240. //
  4241. // Assumption: In DC_START records, the first process record must
  4242. // be the idle process followed by idle threads.
  4243. //
  4244. if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_START) {
  4245. if (bCaptureBogusThreads) {
  4246. //
  4247. // Here we will convert the next N threads into idle threads
  4248. // N = Number of Processors.
  4249. if (IsEqualGUID(&pEvent->Header.Guid, &ThreadGuid)) {
  4250. if (pEvent->Header.ThreadId != 0) {
  4251. PULONG Ptr;
  4252. BogusThreads[BogusCount++] = pEvent->Header.ThreadId;
  4253. pEvent->Header.ThreadId = 0;
  4254. //
  4255. // Assumption: The first two ULONGs are the
  4256. // ThreadId and ProcessId in this record. If that changes
  4257. // this will corrupt memory!
  4258. //
  4259. Ptr = (PULONG)pEvent->MofData;
  4260. *Ptr = 0;
  4261. Ptr++;
  4262. *Ptr = 0;
  4263. }
  4264. }
  4265. //
  4266. // Once all the idle threads are seen, no need to capture anymore
  4267. //
  4268. if (IdleThreadCount++ == NumProc) bCaptureBogusThreads = FALSE;
  4269. }
  4270. } else {
  4271. //
  4272. // This is the TimeConsuming Part. We need to do this only if
  4273. // we found bogus threads earlier.
  4274. //
  4275. if (BogusCount > 0) {
  4276. ULONG i;
  4277. for (i=0; i < BogusCount; i++) {
  4278. if (pEvent->Header.ThreadId == BogusThreads[i]) {
  4279. pEvent->Header.ThreadId = 0;
  4280. //
  4281. // If DC_END records also fix up the Mof for Thread End
  4282. //
  4283. if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_DC_END) {
  4284. PULONG Ptr;
  4285. Ptr = (PULONG)pEvent->MofData;
  4286. *Ptr = 0;
  4287. Ptr++;
  4288. *Ptr = 0;
  4289. }
  4290. }
  4291. }
  4292. }
  4293. }
  4294. //
  4295. // After the above code we should not see any threadId's over 64K
  4296. //
  4297. /*
  4298. #if DBG
  4299. if (pEvent->Header.ThreadId > 65536)
  4300. DbgPrint("%d: Bad ThreadId %x Found\n", EventCount+1,
  4301. pEvent->Header.ThreadId);
  4302. #endif
  4303. */
  4304. //
  4305. // Dump the event in csv file, if required.
  4306. //
  4307. if (TraceContext->Flags & (TRACE_DUMP|TRACE_SUMMARY)) {
  4308. DumpEvent(pEvent);
  4309. }
  4310. else {
  4311. PMOF_INFO pMofInfo;
  4312. PMOF_VERSION pMofVersion = NULL;
  4313. pMofInfo = GetMofInfoHead( &pEvent->Header.Guid );
  4314. if (pMofInfo == NULL){
  4315. return;
  4316. }
  4317. pMofInfo->EventCount++;
  4318. pMofVersion = GetMofVersion(pMofInfo,
  4319. pEvent->Header.Class.Type,
  4320. pEvent->Header.Class.Version,
  4321. pEvent->Header.Class.Level
  4322. );
  4323. }
  4324. if ( (TraceContext->Flags & TRACE_REDUCE) == 0 ) {
  4325. return;
  4326. }
  4327. //
  4328. // TODO: This may prevent DiskIO write events and TCP receive events to
  4329. // get ignored
  4330. //
  4331. if (pEvent->Header.ThreadId == 0) {
  4332. if ( (pEvent->Header.Class.Type != EVENT_TRACE_TYPE_START)
  4333. && (pEvent->Header.Class.Type != EVENT_TRACE_TYPE_DC_START)
  4334. && (pEvent->Header.Class.Type != EVENT_TRACE_TYPE_END)
  4335. && (pEvent->Header.Class.Type != EVENT_TRACE_TYPE_DC_END)
  4336. )
  4337. {
  4338. EventCount++;
  4339. return;
  4340. }
  4341. }
  4342. pThread = FindGlobalThreadById(pEvent->Header.ThreadId, pEvent);
  4343. if ( CurrentSystem.fNoEndTime
  4344. && CurrentSystem.EndTime < (ULONGLONG) pEvent->Header.TimeStamp.QuadPart)
  4345. {
  4346. CurrentSystem.EndTime = pEvent->Header.TimeStamp.QuadPart;
  4347. if (fDSOnly && CurrentSystem.EndTime > DSEndTime)
  4348. CurrentSystem.EndTime = DSEndTime;
  4349. }
  4350. EventCount ++;
  4351. if (IsEqualGUID(&pEvent->Header.Guid, &EventTraceGuid))
  4352. {
  4353. AdjustThreadTime(pEvent, pThread);
  4354. LogHeaderCallback(pEvent);
  4355. }
  4356. else if (IsEqualGUID(&pEvent->Header.Guid, &ProcessGuid))
  4357. {
  4358. AdjustThreadTime(pEvent, pThread);
  4359. ProcessCallback(pEvent);
  4360. }
  4361. else if (IsEqualGUID(&pEvent->Header.Guid, &ThreadGuid))
  4362. {
  4363. if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_START)
  4364. {
  4365. AdjustThreadTime(pEvent, pThread);
  4366. }
  4367. ThreadCallback(pEvent);
  4368. }
  4369. else if (pEvent->Header.ThreadId != 0)
  4370. {
  4371. AdjustThreadTime(pEvent, pThread);
  4372. if (IsEqualGUID(&pEvent->Header.Guid, &DiskIoGuid))
  4373. {
  4374. DiskIoCallback(pEvent, pThread);
  4375. }
  4376. else if (IsEqualGUID(&pEvent->Header.Guid, &FileIoGuid))
  4377. {
  4378. HotFileCallback(pEvent);
  4379. }
  4380. else if (IsEqualGUID(&pEvent->Header.Guid, &ImageLoadGuid))
  4381. {
  4382. ModuleLoadCallback(pEvent);
  4383. }
  4384. else if (IsEqualGUID(&pEvent->Header.Guid, &TcpIpGuid))
  4385. {
  4386. TcpIpCallback(pEvent, pThread);
  4387. }
  4388. else if (IsEqualGUID(&pEvent->Header.Guid, &UdpIpGuid))
  4389. {
  4390. TcpIpCallback(pEvent, pThread);
  4391. }
  4392. else if (IsEqualGUID(&pEvent->Header.Guid, &PageFaultGuid))
  4393. {
  4394. PageFaultCallback(pEvent, pThread);
  4395. }
  4396. else if (IsEqualGUID(&pEvent->Header.Guid, &EventTraceConfigGuid)) {
  4397. // Ignore for now.
  4398. // We need to pick this up for a Hardwareconfig report.
  4399. //
  4400. }
  4401. else
  4402. {
  4403. //
  4404. // This is a hack specific to Print Servers.
  4405. // Need to come up with a general solution. MKR.
  4406. //
  4407. if (IsEqualGUID(&pEvent->Header.Guid, &PrintJobGuid) ||
  4408. IsEqualGUID(&pEvent->Header.Guid, &RenderedJobGuid)) {
  4409. PrintJobCallback(pEvent);
  4410. }
  4411. EventCallback(pEvent, pThread);
  4412. }
  4413. }
  4414. }
  4415. ULONG ahextoi( WCHAR *s)
  4416. {
  4417. int len;
  4418. ULONG num, base, hex;
  4419. len = lstrlenW(s);
  4420. hex = 0; base = 1; num = 0;
  4421. while (--len >= 0) {
  4422. if ( (s[len] == 'x' || s[len] == 'X') &&
  4423. (s[len-1] == '0') )
  4424. break;
  4425. if (s[len] >= '0' && s[len] <= '9')
  4426. num = s[len] - '0';
  4427. else if (s[len] >= 'a' && s[len] <= 'f')
  4428. num = (s[len] - 'a') + 10;
  4429. else if (s[len] >= 'A' && s[len] <= 'F')
  4430. num = (s[len] - 'A') + 10;
  4431. else
  4432. continue;
  4433. hex += num * base;
  4434. base = base * 16;
  4435. }
  4436. return hex;
  4437. }
  4438. void AnsiToUnicode(PCHAR str, PWCHAR wstr)
  4439. {
  4440. int len, i;
  4441. PUCHAR AnsiChar;
  4442. if (str == NULL || wstr == NULL)
  4443. return;
  4444. len = strlen(str);
  4445. for (i=0; i<len; i++)
  4446. {
  4447. AnsiChar = (PUCHAR) &str[i];
  4448. wstr[i] = (WCHAR) RtlAnsiCharToUnicodeChar(&AnsiChar);
  4449. }
  4450. wstr[len] = 0;
  4451. }
  4452. void
  4453. WINAPI
  4454. DumpEvent(
  4455. PEVENT_TRACE pEvent
  4456. )
  4457. {
  4458. PEVENT_TRACE_HEADER pHeader;
  4459. ULONG i;
  4460. PITEM_DESC pItem;
  4461. char str[MOFSTR];
  4462. WCHAR wstr[MOFWSTR];
  4463. PCHAR ptr;
  4464. ULONG ulongword;
  4465. LONG longword;
  4466. USHORT ushortword;
  4467. SHORT shortword;
  4468. PMOF_INFO pMofInfo;
  4469. PMOF_VERSION pMofVersion;
  4470. PLIST_ENTRY Head, Next;
  4471. char iChar;
  4472. WCHAR iwChar;
  4473. ULONG MofDataUsed;
  4474. FILE* DumpFile = NULL;
  4475. TotalEventCount++;
  4476. if (pEvent == NULL) {
  4477. return;
  4478. }
  4479. pHeader = (PEVENT_TRACE_HEADER) &pEvent->Header;
  4480. if( IsEqualGUID(&pEvent->Header.Guid, &EventTraceGuid) &&
  4481. pEvent->Header.Class.Type == EVENT_TRACE_TYPE_INFO ) {
  4482. PTRACE_LOGFILE_HEADER head = (PTRACE_LOGFILE_HEADER)pEvent->MofData;
  4483. if( NULL != head ){
  4484. g_bUserMode = (head->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE);
  4485. if(head->TimerResolution > 0){
  4486. TimerResolution = head->TimerResolution / 10000;
  4487. }
  4488. StartTime = head->StartTime.QuadPart;
  4489. EndTime = head->EndTime.QuadPart;
  4490. fNoEndTime = (EndTime == 0);
  4491. PointerSize = head->PointerSize;
  4492. if (PointerSize < 16){ // minimum is 16 bits
  4493. PointerSize = 32; // defaults = 32 bits
  4494. }
  4495. }
  4496. }
  4497. if (fNoEndTime && EndTime < (ULONGLONG) pHeader->TimeStamp.QuadPart) {
  4498. EndTime = pHeader->TimeStamp.QuadPart;
  4499. }
  4500. if (MofData == NULL) {
  4501. MofLength = pEvent->MofLength + sizeof(UNICODE_NULL);
  4502. MofData = (LPSTR)malloc(MofLength);
  4503. }
  4504. else if ((pEvent->MofLength + sizeof(UNICODE_NULL)) > MofLength) {
  4505. MofLength = pEvent->MofLength + sizeof(UNICODE_NULL);
  4506. MofData = (LPSTR)realloc(MofData, MofLength);
  4507. }
  4508. if (MofData == NULL) {
  4509. return;
  4510. }
  4511. if ((pEvent->MofData == NULL) && (0 != pEvent->MofLength)) {
  4512. return;
  4513. }
  4514. if (pEvent->MofData != NULL) {
  4515. memcpy(MofData, pEvent->MofData, pEvent->MofLength);
  4516. }
  4517. MofData[pEvent->MofLength] = 0;
  4518. MofData[pEvent->MofLength+1] = 0;
  4519. ptr = MofData;
  4520. MofDataUsed = 0;
  4521. pMofInfo = GetMofInfoHead( &pEvent->Header.Guid );
  4522. if (pMofInfo == NULL) {
  4523. return;
  4524. }
  4525. pMofInfo->EventCount++;
  4526. pMofVersion = GetMofVersion(pMofInfo,
  4527. pEvent->Header.Class.Type,
  4528. pEvent->Header.Class.Version,
  4529. pEvent->Header.Class.Level
  4530. );
  4531. if( NULL == pMofVersion ){
  4532. return;
  4533. }
  4534. pMofVersion->EventCountByType++;
  4535. if( !(TraceContext->Flags & TRACE_DUMP) ){
  4536. return;
  4537. }
  4538. DumpFile = TraceContext->hDumpFile;
  4539. if( pMofInfo->strDescription != NULL ){
  4540. fwprintf( DumpFile, L"%12s, ", pMofInfo->strDescription );
  4541. }else{
  4542. fwprintf( DumpFile, L"%12s, ", CpdiGuidToString( wstr, &pMofInfo->Guid ) );
  4543. }
  4544. if(pMofVersion->strType != NULL && wcslen(pMofVersion->strType) ){
  4545. fwprintf( DumpFile, L"%10s, ", pMofVersion->strType );
  4546. }else{
  4547. fwprintf( DumpFile, L"%10d, ", pEvent->Header.Class.Type );
  4548. }
  4549. if( TraceContext->Flags & TRACE_EXTENDED_FMT ){
  4550. fwprintf( DumpFile, L"%8d,%8d,%8d, ",
  4551. pEvent->Header.Class.Type,
  4552. pEvent->Header.Class.Level,
  4553. pEvent->Header.Class.Version
  4554. );
  4555. }
  4556. // Thread ID
  4557. fwprintf( DumpFile, L"0x%04X, ", pHeader->ThreadId );
  4558. // System Time
  4559. fwprintf( DumpFile, L"%20I64u, ", pHeader->TimeStamp.QuadPart);
  4560. if( g_bUserMode == FALSE ){
  4561. // Kernel Time
  4562. fwprintf(DumpFile, L"%10lu, ", pHeader->KernelTime * TimerResolution);
  4563. // User Time
  4564. fwprintf(DumpFile, L"%10lu, ", pHeader->UserTime * TimerResolution);
  4565. }else{
  4566. // processor Time
  4567. fwprintf(DumpFile, L"%I64u, ", pHeader->ProcessorTime);
  4568. }
  4569. Head = &pMofVersion->ItemHeader;
  4570. Next = Head->Flink;
  4571. if ((Head == Next) && (pEvent->MofLength > 0)) {
  4572. fwprintf(DumpFile, L"DataSize=%d, ", pEvent->MofLength);
  4573. }
  4574. while (Head != Next) {
  4575. pItem = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
  4576. Next = Next->Flink;
  4577. MofDataUsed = (ULONG) (ptr - MofData);
  4578. if (MofDataUsed >= pEvent->MofLength){
  4579. break;
  4580. }
  4581. switch (pItem->ItemType)
  4582. {
  4583. case ItemChar:
  4584. case ItemUChar:
  4585. for (i=0;i<pItem->ArraySize;i++){
  4586. iChar = *((PCHAR) ptr);
  4587. fwprintf(DumpFile, L"%c", iChar);
  4588. ptr += sizeof(CHAR);
  4589. }
  4590. fwprintf(DumpFile, L", " );
  4591. break;
  4592. case ItemCharHidden:
  4593. ptr += sizeof(CHAR) * pItem->ArraySize;
  4594. break;
  4595. case ItemWChar:
  4596. for(i=0;i<pItem->ArraySize;i++){
  4597. iwChar = *((PWCHAR) ptr);
  4598. fwprintf(DumpFile, L"%wc", iwChar);
  4599. ptr += sizeof(WCHAR);
  4600. }
  4601. fwprintf(DumpFile, L", ");
  4602. break;
  4603. case ItemCharSign:
  4604. {
  4605. char sign[5];
  4606. memcpy(&sign, ptr, sizeof(CHAR) * 2);
  4607. sign[2] = '\0';
  4608. strcpy(str, sign);
  4609. MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
  4610. fwprintf(DumpFile, L"\"%ws\", ", wstr);
  4611. ptr += sizeof(CHAR) * 2;
  4612. break;
  4613. }
  4614. case ItemCharShort:
  4615. iChar = *((PCHAR) ptr);
  4616. fwprintf(DumpFile, L"%d, ", iChar);
  4617. ptr += sizeof(CHAR);
  4618. break;
  4619. case ItemShort:
  4620. shortword = * ((PSHORT) ptr);
  4621. fwprintf(DumpFile, L"%6d, ", shortword);
  4622. ptr += sizeof (SHORT);
  4623. break;
  4624. case ItemUShort:
  4625. ushortword = *((PUSHORT) ptr);
  4626. fwprintf(DumpFile, L"%6u, ", ushortword);
  4627. ptr += sizeof (USHORT);
  4628. break;
  4629. case ItemLong:
  4630. longword = *((PLONG) ptr);
  4631. fwprintf(DumpFile, L"%8d, ", longword);
  4632. ptr += sizeof (LONG);
  4633. break;
  4634. case ItemULong:
  4635. ulongword = *((PULONG) ptr);
  4636. fwprintf(DumpFile, L"%8lu, ", ulongword);
  4637. ptr += sizeof (ULONG);
  4638. break;
  4639. case ItemULongX:
  4640. ulongword = *((PULONG) ptr);
  4641. fwprintf(DumpFile, L"0x%08X, ", ulongword);
  4642. ptr += sizeof (ULONG);
  4643. break;
  4644. case ItemPtr :
  4645. {
  4646. unsigned __int64 pointer;
  4647. if (PointerSize == 64) {
  4648. pointer = *((unsigned __int64 *) ptr);
  4649. fwprintf(DumpFile, L"0x%X, ", pointer);
  4650. }
  4651. else { // assumes 32 bit otherwise
  4652. ulongword = *((PULONG) ptr);
  4653. fwprintf(DumpFile, L"0x%08X, ", ulongword);
  4654. }
  4655. ptr += PointerSize / 8;
  4656. //
  4657. // If target source is Win64, then use Ptr, else use ulongword
  4658. //
  4659. break;
  4660. }
  4661. case ItemIPAddr:
  4662. {
  4663. ulongword = *((PULONG) ptr);
  4664. // Convert it to readable form
  4665. //
  4666. fwprintf(DumpFile, L"%03d.%03d.%03d.%03d, ",
  4667. (ulongword >> 0) & 0xff,
  4668. (ulongword >> 8) & 0xff,
  4669. (ulongword >> 16) & 0xff,
  4670. (ulongword >> 24) & 0xff);
  4671. ptr += sizeof (ULONG);
  4672. break;
  4673. }
  4674. case ItemPort:
  4675. {
  4676. fwprintf(DumpFile, L"%u, ", NTOHS((USHORT) *ptr));
  4677. ptr += sizeof (USHORT);
  4678. break;
  4679. }
  4680. case ItemLongLong:
  4681. {
  4682. LONGLONG n64;
  4683. n64 = *((LONGLONG*) ptr);
  4684. ptr += sizeof(LONGLONG);
  4685. fwprintf(DumpFile, L"%16I64d, ", n64);
  4686. break;
  4687. }
  4688. case ItemULongLong:
  4689. {
  4690. ULONGLONG n64;
  4691. n64 = *((ULONGLONG*) ptr);
  4692. ptr += sizeof(ULONGLONG);
  4693. fwprintf(DumpFile, L"%16I64u, ", n64);
  4694. break;
  4695. }
  4696. case ItemString:
  4697. case ItemRString:
  4698. {
  4699. USHORT pLen = (USHORT)strlen((CHAR*) ptr);
  4700. if (pLen > 0)
  4701. {
  4702. strcpy(str, ptr);
  4703. if (pItem->ItemType == ItemRString)
  4704. {
  4705. reduceA(str);
  4706. }
  4707. for (i=pLen-1; i>0; i--) {
  4708. if (str[i] == 0xFF)
  4709. str[i] = 0;
  4710. else break;
  4711. }
  4712. MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
  4713. fwprintf(DumpFile, L"\"%ws\", ", wstr);
  4714. }
  4715. ptr += (pLen + 1);
  4716. break;
  4717. }
  4718. case ItemRWString:
  4719. case ItemWString:
  4720. {
  4721. size_t pLen = 0;
  4722. size_t i;
  4723. if (*(WCHAR *) ptr)
  4724. {
  4725. if (pItem->ItemType == ItemRWString)
  4726. {
  4727. reduceW((WCHAR *) ptr);
  4728. }
  4729. pLen = ((lstrlenW((WCHAR*)ptr) + 1) * sizeof(WCHAR));
  4730. memcpy(wstr, ptr, pLen);
  4731. for (i = (pLen/2)-1; i > 0; i--)
  4732. {
  4733. if (((USHORT) wstr[i] == (USHORT) 0xFFFF))
  4734. {
  4735. wstr[i] = (USHORT) 0;
  4736. }
  4737. else break;
  4738. }
  4739. wstr[pLen / 2] = wstr[(pLen / 2) + 1]= '\0';
  4740. fwprintf(DumpFile, L"\"%ws\", ", wstr);
  4741. }
  4742. ptr += pLen;
  4743. break;
  4744. }
  4745. case ItemDSString: // Counted String
  4746. {
  4747. USHORT pLen = (USHORT)(256 * ((USHORT) * ptr) + ((USHORT) * (ptr + 1)));
  4748. ptr += sizeof(USHORT);
  4749. if (pLen > (pEvent->MofLength - MofDataUsed - 1)) {
  4750. pLen = (USHORT) (pEvent->MofLength - MofDataUsed - 1);
  4751. }
  4752. if (pLen > 0)
  4753. {
  4754. strcpy(str, ptr);
  4755. MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
  4756. fwprintf(DumpFile, L"\"%ws\", ", wstr);
  4757. }
  4758. ptr += (pLen + 1);
  4759. break;
  4760. }
  4761. case ItemPString: // Counted String
  4762. {
  4763. USHORT pLen = * ((USHORT *) ptr);
  4764. ptr += sizeof(USHORT);
  4765. if (pLen > (pEvent->MofLength - MofDataUsed)) {
  4766. pLen = (USHORT) (pEvent->MofLength - MofDataUsed);
  4767. }
  4768. if (pLen > MOFSTR * sizeof(CHAR)) {
  4769. pLen = MOFSTR * sizeof(CHAR);
  4770. }
  4771. if (pLen > 0) {
  4772. memcpy(str, ptr, pLen);
  4773. str[pLen] = '\0';
  4774. MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
  4775. fwprintf(DumpFile, L"\"%ws\", ", wstr);
  4776. }
  4777. ptr += pLen;
  4778. break;
  4779. }
  4780. case ItemDSWString: // DS Counted Wide Strings
  4781. case ItemPWString: // Counted Wide Strings
  4782. {
  4783. USHORT pLen = (USHORT)(( pItem->ItemType == ItemDSWString)
  4784. ? (256 * ((USHORT) * ptr) + ((USHORT) * (ptr + 1)))
  4785. : (* ((USHORT *) ptr)));
  4786. ptr += sizeof(USHORT);
  4787. if (pLen > (pEvent->MofLength - MofDataUsed)) {
  4788. pLen = (USHORT) (pEvent->MofLength - MofDataUsed);
  4789. }
  4790. if (pLen > MOFWSTR * sizeof(WCHAR)) {
  4791. pLen = MOFWSTR * sizeof(WCHAR);
  4792. }
  4793. if (pLen > 0) {
  4794. memcpy(wstr, ptr, pLen);
  4795. wstr[pLen / sizeof(WCHAR)] = L'\0';
  4796. fwprintf(DumpFile, L"\"%ws\", ", wstr);
  4797. }
  4798. ptr += pLen;
  4799. break;
  4800. }
  4801. case ItemNWString: // Non Null Terminated String
  4802. {
  4803. USHORT Size;
  4804. Size = (USHORT)(pEvent->MofLength - (ULONG)(ptr - MofData));
  4805. if( Size > MOFSTR )
  4806. {
  4807. Size = MOFSTR;
  4808. }
  4809. if (Size > 0)
  4810. {
  4811. memcpy(wstr, ptr, Size);
  4812. wstr[Size / 2] = '\0';
  4813. fwprintf(DumpFile, L"\"%ws\", ", wstr);
  4814. }
  4815. ptr += Size;
  4816. break;
  4817. }
  4818. case ItemMLString: // Multi Line String
  4819. {
  4820. USHORT pLen;
  4821. char * src, * dest;
  4822. BOOL inQ = FALSE;
  4823. BOOL skip = FALSE;
  4824. UINT lineCount = 0;
  4825. ptr += sizeof(UCHAR) * 2;
  4826. pLen = (USHORT)strlen(ptr);
  4827. if (pLen > 0)
  4828. {
  4829. src = ptr;
  4830. dest = str;
  4831. while (* src != '\0'){
  4832. if (* src == '\n'){
  4833. if (!lineCount){
  4834. * dest++ = ' ';
  4835. }
  4836. lineCount++;
  4837. }else if (* src == '\"'){
  4838. if (inQ){
  4839. char strCount[32];
  4840. char * cpy;
  4841. sprintf(strCount, "{%dx}", lineCount);
  4842. cpy = & strCount[0];
  4843. while (* cpy != '\0'){
  4844. * dest ++ = * cpy ++;
  4845. }
  4846. }
  4847. inQ = !inQ;
  4848. }else if (!skip){
  4849. *dest++ = *src;
  4850. }
  4851. skip = (lineCount > 1 && inQ);
  4852. src++;
  4853. }
  4854. *dest = '\0';
  4855. MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
  4856. fwprintf(DumpFile, L"\"%ws\", ", wstr);
  4857. }
  4858. ptr += (pLen);
  4859. break;
  4860. }
  4861. case ItemSid:
  4862. {
  4863. WCHAR UserName[64];
  4864. WCHAR Domain[64];
  4865. WCHAR FullName[256];
  4866. ULONG asize = 0;
  4867. ULONG bsize = 0;
  4868. ULONG Sid[64];
  4869. PULONG pSid = & Sid[0];
  4870. SID_NAME_USE Se;
  4871. ULONG nSidLength;
  4872. pSid = (PULONG) ptr;
  4873. if (*pSid == 0){
  4874. ptr += 4;
  4875. fwprintf(DumpFile, L"%4d, ", *pSid);
  4876. }
  4877. else
  4878. {
  4879. ptr += 8; // skip the TOKEN_USER structure
  4880. nSidLength = 8 + (4*ptr[1]);
  4881. asize = 64;
  4882. bsize = 64;
  4883. if (LookupAccountSidW(
  4884. NULL,
  4885. (PSID) ptr,
  4886. (LPWSTR) & UserName[0],
  4887. & asize,
  4888. (LPWSTR) & Domain[0],
  4889. & bsize,
  4890. & Se))
  4891. {
  4892. LPWSTR pFullName = &FullName[0];
  4893. swprintf( pFullName, L"\\\\%s\\%s", Domain, UserName);
  4894. asize = (ULONG) lstrlenW(pFullName);
  4895. if (asize > 0){
  4896. fwprintf(DumpFile, L"\"%s\", ", pFullName);
  4897. }
  4898. }
  4899. else
  4900. {
  4901. fwprintf(DumpFile, L"\"System\", " );
  4902. }
  4903. SetLastError( ERROR_SUCCESS );
  4904. ptr += nSidLength;
  4905. }
  4906. break;
  4907. }
  4908. case ItemChar4:
  4909. fwprintf(DumpFile,
  4910. L"%c%c%c%c, ",
  4911. *ptr, ptr[1], ptr[2], ptr[3]);
  4912. ptr += 4 * sizeof(CHAR);
  4913. break;
  4914. case ItemGuid:
  4915. {
  4916. WCHAR s[64];
  4917. fwprintf(DumpFile, L"%s, ", CpdiGuidToString(&s[0], (LPGUID)ptr));
  4918. ptr += sizeof(GUID);
  4919. break;
  4920. }
  4921. case ItemCPUTime:
  4922. {
  4923. ulongword = * ((PULONG) ptr);
  4924. fwprintf(DumpFile, L"%8lu, ", ulongword * TimerResolution);
  4925. ptr += sizeof (ULONG);
  4926. break;
  4927. }
  4928. case ItemOptArgs:
  4929. {
  4930. DWORD dwOptArgs = * ((PLONG) ptr);
  4931. DWORD dwMofLen = pEvent->MofLength + sizeof(UNICODE_NULL);
  4932. DWORD dwMofUsed = MofDataUsed + sizeof(DWORD);
  4933. DWORD dwType;
  4934. DWORD i;
  4935. LPWSTR wszString;
  4936. LPSTR aszString;
  4937. LONG lValue32;
  4938. LONGLONG lValue64;
  4939. ptr += sizeof(LONG);
  4940. for (i = 0; i < 8; i ++) {
  4941. if (dwMofUsed > dwMofLen) {
  4942. break;
  4943. }
  4944. dwType = (dwOptArgs >> (i * 4)) & 0x0000000F;
  4945. switch (dwType) {
  4946. case 0: // LONG
  4947. dwMofUsed += sizeof(LONG);
  4948. if (dwMofUsed <= dwMofLen) {
  4949. lValue32 = * ((LONG *) ptr);
  4950. ptr += sizeof(LONG);
  4951. fwprintf(DumpFile, L"%d,", lValue32);
  4952. }
  4953. break;
  4954. case 1: // WSTR
  4955. wszString = (LPWSTR) ptr;
  4956. dwMofUsed += sizeof(WCHAR) * (lstrlenW(wszString) + 1);
  4957. if (dwMofUsed <= dwMofLen) {
  4958. fwprintf(DumpFile, L"\"%ws\",", wszString);
  4959. ptr += sizeof(WCHAR) * (lstrlenW(wszString) + 1);
  4960. }
  4961. break;
  4962. case 2: // STR
  4963. aszString = (LPSTR) ptr;
  4964. dwMofUsed += sizeof(CHAR) * (lstrlenA(aszString) + 1);
  4965. if (dwMofUsed <= dwMofLen) {
  4966. fwprintf(DumpFile, L"\"%s\",", aszString);
  4967. ptr += sizeof(CHAR) * (lstrlenA(aszString) + 1);
  4968. }
  4969. break;
  4970. case 3: // LONG64
  4971. dwMofUsed += sizeof(LONGLONG);
  4972. if (dwMofUsed <= dwMofLen) {
  4973. lValue64 = * ((LONGLONG *) ptr);
  4974. ptr += sizeof(LONGLONG);
  4975. fwprintf(DumpFile, L"%I64d,", lValue64);
  4976. }
  4977. break;
  4978. }
  4979. }
  4980. break;
  4981. }
  4982. case ItemVariant:
  4983. {
  4984. //
  4985. // Variable Size. First ULONG gives the sizee and the rest is blob
  4986. //
  4987. ulongword = *((PULONG) ptr);
  4988. ptr += sizeof(ULONG);
  4989. fwprintf(DumpFile, L"DataSize=%d, ", ulongword);
  4990. // No need to dump the contents of the Blob itself.
  4991. ptr += ulongword;
  4992. break;
  4993. }
  4994. case ItemBool:
  4995. {
  4996. BOOL Flag = (BOOL)*ptr;
  4997. fwprintf(DumpFile, L"%5s, " , (Flag) ? L"TRUE" : L"FALSE" );
  4998. ptr += sizeof(BOOL);
  4999. break;
  5000. }
  5001. default:
  5002. ptr += sizeof (int);
  5003. }
  5004. }
  5005. //Instance ID, Parent Instance ID
  5006. fwprintf(DumpFile, L"%d, %d\n", pEvent->InstanceId, pEvent->ParentInstanceId );
  5007. }
  5008. #ifdef __cplusplus
  5009. }
  5010. #endif