Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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