Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1488 lines
46 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. api.c
  5. Abstract:
  6. Manipulation routines for cpdata structures.
  7. Author:
  8. Melur Raghuraman (mraghu) 03-Oct-1997
  9. Environment:
  10. Revision History:
  11. --*/
  12. #include <stdio.h>
  13. #include "cpdata.h"
  14. #include "tracectr.h"
  15. extern PTRACE_CONTEXT_BLOCK TraceContext;
  16. extern PWCHAR CpdiGuidToString(PWCHAR s, LPGUID piid);
  17. HRESULT
  18. CPDAPI
  19. GetTempName( LPTSTR strFile, DWORD dwSize )
  20. {
  21. HRESULT hr;
  22. GUID guid;
  23. UNICODE_STRING strGUID;
  24. WCHAR buffer[MAXSTR];
  25. hr = UuidCreate( &guid );
  26. if( !( hr == RPC_S_OK || hr == RPC_S_UUID_LOCAL_ONLY ) ){
  27. return hr;
  28. }
  29. hr = RtlStringFromGUID( &guid, &strGUID );
  30. if( ERROR_SUCCESS != hr ){
  31. return hr;
  32. }
  33. _stprintf( buffer, _T("%%temp%%\\%s"), strGUID.Buffer );
  34. if( ! ExpandEnvironmentStrings( buffer, strFile, dwSize ) ){
  35. hr = GetLastError();
  36. }
  37. RtlFreeUnicodeString( &strGUID );
  38. return hr;
  39. }
  40. ULONG
  41. GetTraceTransactionInfo(
  42. OUT PVOID TraceInformation,
  43. IN ULONG TraceInformationLength,
  44. OUT PULONG Length,
  45. IN ULONG InstanceCount,
  46. IN LPCWSTR *InstanceNames,
  47. IN ULONG TraceInformationClass,
  48. IN BOOLEAN bDrillDown
  49. );
  50. ULONG
  51. DrillDownDisk(
  52. IN PTDISK_RECORD DiskRecord,
  53. IN ULONG TraceInformationClass,
  54. OUT PVOID DiskInformation,
  55. IN ULONG DiskInformationLength,
  56. OUT PULONG Length
  57. );
  58. ULONG
  59. GetTraceProcessInfo (
  60. OUT PVOID ProcessInformation,
  61. IN ULONG ProcessInformationLength,
  62. OUT PULONG Length,
  63. IN ULONG InstanceCount,
  64. IN LPCWSTR *InstanceNames,
  65. IN ULONG TraceInformationClass,
  66. IN BOOLEAN bDrillDown
  67. );
  68. // Same for File information.
  69. //
  70. ULONG
  71. GetTraceFileInfo (
  72. OUT PVOID FileInformation,
  73. IN ULONG FileInformationLength,
  74. OUT PULONG Length,
  75. IN ULONG InstanceCount,
  76. IN LPCWSTR *InstanceNames,
  77. IN ULONG TraceInformationClass,
  78. IN BOOLEAN bDrillDown
  79. );
  80. ULONG
  81. GetTraceDiskInfo (
  82. OUT PVOID DiskInformation,
  83. IN ULONG DiskInformationLength,
  84. OUT PULONG Length,
  85. IN ULONG InstanceCount,
  86. IN LPCWSTR *InstanceNames,
  87. IN ULONG TraceInformationClass,
  88. IN BOOLEAN bDrillDown
  89. );
  90. ULONG
  91. GetTraceModuleInfo(
  92. OUT PVOID ModuleInformation,
  93. IN ULONG ModuleInformationLength,
  94. OUT PULONG Length,
  95. OUT PVOID * ppModuleLast,
  96. IN PPROCESS_RECORD pProcess,
  97. IN PLIST_ENTRY pModuleListHead,
  98. IN ULONG lOffset
  99. );
  100. ULONG
  101. GetTraceProcessFaultInfo(
  102. OUT PVOID ProcessFaultInformation,
  103. IN ULONG ProcessFaultInformationLength,
  104. OUT PULONG Length
  105. );
  106. ULONG
  107. GetTraceProcessModuleInfo (
  108. OUT PVOID ModuleInformation,
  109. IN ULONG ModuleInformationLength,
  110. OUT PULONG Length,
  111. IN ULONG InstanceCount,
  112. IN LPCWSTR * InstanceNames
  113. );
  114. static void
  115. CopyProcessInfo (
  116. OUT PTRACE_PROCESS_INFOW ProcessInfo,
  117. IN PPROCESS_RECORD Process
  118. );
  119. static void
  120. CopyDiskInfo (
  121. OUT PTRACE_DISK_INFOW DiskInfo,
  122. IN PTDISK_RECORD DiskRecord
  123. );
  124. static void
  125. CopyFileInfo (
  126. OUT PTRACE_FILE_INFOW FileInfo,
  127. IN PFILE_RECORD FileRecord
  128. );
  129. BOOLEAN
  130. MatchInstance(
  131. IN LPCWSTR CurrentInstance,
  132. IN ULONG InstanceCount,
  133. IN LPCWSTR *InstanceNames
  134. );
  135. BOOLEAN
  136. MatchDisk(
  137. IN ULONG CurrentInstance,
  138. IN ULONG InstanceCount,
  139. IN LPCSTR *InstanceNames
  140. );
  141. ULONG
  142. CPDAPI
  143. TraceSetTimer(
  144. IN ULONG FlushTimer
  145. )
  146. {
  147. if (TraceContext != NULL) {
  148. TraceContext->LoggerInfo->FlushTimer = FlushTimer;
  149. }
  150. return ERROR_SUCCESS;
  151. }
  152. ULONG
  153. CPDAPI
  154. TraceQueryAllInstances(
  155. IN TRACEINFOCLASS TraceInformationClass,
  156. OUT PVOID TraceInformation,
  157. IN ULONG TraceInformationLength,
  158. OUT PULONG Length
  159. )
  160. {
  161. ULONG status = ERROR_INVALID_PARAMETER;
  162. PTRACE_MODULE_INFO pModuleLast = NULL;
  163. if (TraceInformation != NULL && TraceInformationLength > 0) {
  164. switch (TraceInformationClass) {
  165. case TraceProcessInformation:
  166. status = GetTraceProcessInfo(TraceInformation,
  167. TraceInformationLength,
  168. Length,
  169. 0, NULL, 0, FALSE);
  170. break;
  171. case TraceFileInformation:
  172. status = GetTraceFileInfo(TraceInformation,
  173. TraceInformationLength,
  174. Length, 0, NULL, 0, FALSE);
  175. break;
  176. case TraceDiskInformation:
  177. status = GetTraceDiskInfo(TraceInformation,
  178. TraceInformationLength,
  179. Length, 0, NULL, 0, FALSE);
  180. break;
  181. case TraceTransactionInformation:
  182. status = GetTraceTransactionInfo(TraceInformation,
  183. TraceInformationLength,
  184. Length, 0, NULL, 0, FALSE);
  185. break;
  186. case TraceProcessPageFaultInformation:
  187. status = GetTraceProcessFaultInfo(TraceInformation,
  188. TraceInformationLength,
  189. Length);
  190. break;
  191. case TraceModuleInformation:
  192. status = GetTraceModuleInfo(TraceInformation,
  193. TraceInformationLength,
  194. Length,
  195. (PVOID *) & pModuleLast,
  196. NULL,
  197. & CurrentSystem.GlobalModuleListHead,
  198. 0);
  199. if (pModuleLast != NULL) {
  200. pModuleLast->NextEntryOffset = 0;
  201. }
  202. break;
  203. }
  204. }
  205. return status;
  206. }
  207. ULONG
  208. CPDAPI
  209. TraceQueryInstanceW (
  210. IN TRACEINFOCLASS TraceInformationClass,
  211. IN ULONG InstanceCount,
  212. IN LPCWSTR *InstanceNames,
  213. OUT PVOID TraceInformation,
  214. IN ULONG TraceInformationLength,
  215. OUT PULONG Length
  216. )
  217. {
  218. if (TraceInformation == NULL || TraceInformationLength == 0)
  219. return ERROR_INVALID_PARAMETER;
  220. switch(TraceInformationClass) {
  221. case TraceProcessInformation:
  222. return GetTraceProcessInfo(TraceInformation,
  223. TraceInformationLength,
  224. Length,
  225. InstanceCount,
  226. InstanceNames,
  227. 0, FALSE);
  228. break;
  229. case TraceFileInformation:
  230. return GetTraceFileInfo(TraceInformation,
  231. TraceInformationLength,
  232. Length,
  233. InstanceCount,
  234. InstanceNames,
  235. 0, FALSE);
  236. break;
  237. case TraceDiskInformation:
  238. return GetTraceDiskInfo(TraceInformation,
  239. TraceInformationLength,
  240. Length,
  241. InstanceCount,
  242. InstanceNames,
  243. 0, FALSE);
  244. break;
  245. case TraceModuleInformation:
  246. return GetTraceProcessModuleInfo(TraceInformation,
  247. TraceInformationLength,
  248. Length,
  249. InstanceCount,
  250. InstanceNames);
  251. break;
  252. }
  253. return 0;
  254. }
  255. ULONG
  256. DrillDownProcess(
  257. IN PPROCESS_RECORD ProcessRecord,
  258. IN ULONG TraceInformationClass,
  259. OUT PVOID DiskInformation,
  260. IN ULONG DiskInformationLength,
  261. OUT PULONG Length
  262. )
  263. {
  264. PLIST_ENTRY Next, Head;
  265. PTDISK_RECORD DiskRecord = NULL;
  266. PFILE_RECORD pFile = NULL;
  267. ULONG TotalSize = 0;
  268. ULONG NextEntryOffset = 0;
  269. PTRACE_DISK_INFOW DiskInfo = NULL;
  270. PTRACE_FILE_INFOW FileInfo = NULL;
  271. ULONG status = 0;
  272. ULONG EntrySize = 0;
  273. ULONG len = 0;
  274. PVOID s;
  275. char * t;
  276. if (ProcessRecord == NULL)
  277. return ERROR_INVALID_PARAMETER;
  278. switch (TraceInformationClass)
  279. {
  280. case TraceDiskInformation:
  281. Head = & ProcessRecord->DiskListHead;
  282. EntrySize = sizeof(TRACE_DISK_INFOW);
  283. break;
  284. case TraceFileInformation:
  285. Head = & ProcessRecord->FileListHead;
  286. EntrySize = sizeof(TRACE_FILE_INFOW);
  287. break;
  288. default:
  289. return ERROR_INVALID_PARAMETER;
  290. }
  291. Next = Head->Flink;
  292. while (Next != Head)
  293. {
  294. // Return the data in the Appropriate structure
  295. //
  296. switch (TraceInformationClass)
  297. {
  298. case TraceDiskInformation:
  299. DiskRecord = CONTAINING_RECORD(Next, TDISK_RECORD, Entry);
  300. DiskInfo = (PTRACE_DISK_INFOW)
  301. ((PUCHAR) DiskInformation + TotalSize);
  302. len = sizeof(TRACE_DISK_INFOW)
  303. + (lstrlenW(DiskRecord->DiskName) + 1) * sizeof(WCHAR);
  304. NextEntryOffset = len;
  305. TotalSize += len;
  306. if (TotalSize > DiskInformationLength)
  307. {
  308. status = ERROR_MORE_DATA;
  309. *Length = 0;
  310. return status;
  311. }
  312. CopyDiskInfo(DiskInfo, DiskRecord);
  313. t = s = (char *) DiskInfo + sizeof(TRACE_DISK_INFOW);
  314. wcscpy((PWCHAR) s, DiskRecord->DiskName);
  315. DiskInfo->DiskName = (PWCHAR) s;
  316. if (TraceContext->Flags & TRACE_ZERO_ON_QUERY)
  317. { // pseudo sort
  318. DiskRecord->ReadCount = 0;
  319. DiskRecord->WriteCount = 0;
  320. DiskRecord->ReadSize = 0;
  321. DiskRecord->WriteSize = 0;
  322. }
  323. DiskInfo->NextEntryOffset = NextEntryOffset;
  324. break;
  325. case TraceFileInformation:
  326. {
  327. ULONG NameLen;
  328. pFile = CONTAINING_RECORD(Next, FILE_RECORD, Entry);
  329. Next = Next->Flink;
  330. if (pFile->ReadCount == 0 && pFile->WriteCount == 0)
  331. continue;
  332. FileInfo = (PTRACE_FILE_INFOW)
  333. ((PUCHAR) DiskInformation + TotalSize);
  334. NameLen = (lstrlenW(pFile->FileName) + 1) * sizeof(WCHAR);
  335. NextEntryOffset = sizeof(TRACE_FILE_INFOW) + NameLen;
  336. TotalSize += sizeof(TRACE_FILE_INFOW) + NameLen;
  337. if (TotalSize > DiskInformationLength)
  338. {
  339. LeaveTracelibCritSection();
  340. * Length = 0;
  341. return ERROR_MORE_DATA;
  342. }
  343. CopyFileInfo(FileInfo, pFile);
  344. if (TraceContext->Flags & TRACE_ZERO_ON_QUERY)
  345. {
  346. pFile->ReadCount =
  347. pFile->WriteCount =
  348. pFile->ReadSize =
  349. pFile->WriteSize = 0;
  350. }
  351. FileInfo->NextEntryOffset = NextEntryOffset;
  352. break;
  353. }
  354. }
  355. Next = Next->Flink;
  356. }
  357. if (DiskInfo != NULL)
  358. DiskInfo->NextEntryOffset = 0;
  359. if (FileInfo != NULL)
  360. FileInfo->NextEntryOffset = 0;
  361. * Length = TotalSize;
  362. return status;
  363. }
  364. ULONG
  365. GetTraceTransactionInfo(
  366. OUT PVOID TraceInformation,
  367. IN ULONG TraceInformationLength,
  368. OUT PULONG Length,
  369. IN ULONG InstanceCount,
  370. IN LPCWSTR *InstanceNames,
  371. IN ULONG TraceInformationClass,
  372. IN BOOLEAN bDrillDown
  373. )
  374. {
  375. PLIST_ENTRY Next, Head;
  376. PMOF_INFO pMofInfo;
  377. PLIST_ENTRY DNext, DHead;
  378. PMOF_DATA pMofData;
  379. ULONG TotalSize = 0;
  380. ULONG NextEntryOffset = 0;
  381. PTRACE_TRANSACTION_INFO TransInfo = NULL;
  382. ULONGLONG TotalResponse;
  383. ULONG status=0;
  384. ULONG nameLen;
  385. ULONG count;
  386. WCHAR strDescription[1024];
  387. UNREFERENCED_PARAMETER(InstanceCount);
  388. UNREFERENCED_PARAMETER(InstanceNames);
  389. UNREFERENCED_PARAMETER(TraceInformationClass);
  390. UNREFERENCED_PARAMETER(bDrillDown);
  391. EnterTracelibCritSection();
  392. Head = &CurrentSystem.EventListHead;
  393. Next = Head->Flink;
  394. while (Next != Head) {
  395. pMofInfo = CONTAINING_RECORD( Next, MOF_INFO, Entry );
  396. Next = Next->Flink;
  397. if (pMofInfo->strDescription != NULL)
  398. wcscpy(strDescription, pMofInfo->strDescription);
  399. else
  400. CpdiGuidToString(strDescription, & pMofInfo->Guid);
  401. nameLen = (lstrlenW(strDescription) + 1) * sizeof(WCHAR);
  402. TransInfo = (PTRACE_TRANSACTION_INFO)
  403. ( (PUCHAR)TraceInformation + TotalSize);
  404. RtlZeroMemory(TransInfo, (nameLen + sizeof(TRACE_TRANSACTION_INFO)));
  405. NextEntryOffset = sizeof(TRACE_TRANSACTION_INFO) + nameLen;
  406. TotalSize += NextEntryOffset;
  407. if (TotalSize > TraceInformationLength) {
  408. status = ERROR_MORE_DATA;
  409. LeaveTracelibCritSection();
  410. goto failed;
  411. }
  412. TransInfo->NextEntryOffset = NextEntryOffset;
  413. DHead = &pMofInfo->DataListHead;
  414. DNext = DHead->Flink;
  415. count = 0;
  416. TotalResponse = 0;
  417. while( DNext != DHead ){
  418. pMofData = CONTAINING_RECORD( DNext, MOF_DATA, Entry );
  419. count += pMofData->CompleteCount;
  420. TotalResponse += pMofData->TotalResponseTime;
  421. if (TraceContext->Flags & TRACE_ZERO_ON_QUERY) {
  422. pMofData->CompleteCount = 0;
  423. pMofData->TotalResponseTime = 0;
  424. }
  425. // Fix Min and Max in Callbacks.
  426. //
  427. DNext = DNext->Flink;
  428. }
  429. if (count > 0) {
  430. TransInfo->AverageResponseTime = (ULONG)TotalResponse / count;
  431. }
  432. TransInfo->TransactionCount = count;
  433. TransInfo->Name =
  434. (PWCHAR) ((PUCHAR) TransInfo + sizeof(TRACE_TRANSACTION_INFO));
  435. wcscpy(TransInfo->Name, strDescription);
  436. }
  437. LeaveTracelibCritSection();
  438. failed:
  439. if (TransInfo != NULL)
  440. TransInfo->NextEntryOffset = 0;
  441. *Length = TotalSize;
  442. return 0;
  443. }
  444. BOOLEAN
  445. MatchProcess(
  446. IN PPROCESS_RECORD Process,
  447. IN ULONG InstanceCount,
  448. IN LPCWSTR *InstanceNames
  449. )
  450. {
  451. BOOLEAN status = FALSE;
  452. if (Process->UserName && Process->ImageName) {
  453. PCHAR t = NULL;
  454. PWCHAR s;
  455. ULONG len = lstrlenW(Process->UserName) + lstrlenW(Process->ImageName) + 4;
  456. t = malloc(len);
  457. if (t == NULL) {
  458. return FALSE;
  459. }
  460. s = malloc(len * sizeof(WCHAR));
  461. if (s == NULL) {
  462. free (t);
  463. return FALSE;
  464. }
  465. if (Process->UserName)
  466. {
  467. wcscpy(s, Process->UserName);
  468. wcscat(s, L" (");
  469. wcscat(s, Process->ImageName);
  470. wcscat(s, L")");
  471. }
  472. else
  473. {
  474. wcscpy(s, L"Unknown (");
  475. wcscat(s, Process->ImageName);
  476. wcscat(s, L")");
  477. }
  478. status = MatchInstance(s, InstanceCount, InstanceNames);
  479. if (!status)
  480. {
  481. sprintf(t, "%ws", Process->ImageName);
  482. wcscpy(s, Process->ImageName);
  483. status = MatchInstance(s, InstanceCount, InstanceNames);
  484. }
  485. free(t);
  486. free(s);
  487. }
  488. return status;
  489. }
  490. // APIs to get the real time data.
  491. //
  492. ULONG
  493. GetTraceProcessInfo(
  494. OUT PVOID SystemInformation,
  495. IN ULONG SystemInformationLength,
  496. OUT PULONG Length,
  497. IN ULONG InstanceCount,
  498. IN LPCWSTR *InstanceNames,
  499. IN ULONG TraceInformationClass,
  500. IN BOOLEAN bDrillDown
  501. )
  502. {
  503. PLIST_ENTRY Next, Head;
  504. PPROCESS_RECORD Process;
  505. ULONG TotalSize = 0;
  506. ULONG NextEntryOffset = 0;
  507. PTRACE_PROCESS_INFOW ProcessInfo = (PTRACE_PROCESS_INFOW)SystemInformation;
  508. PTRACE_PROCESS_INFOW LastProcessInfo = NULL;
  509. ULONG status=0;
  510. ULONG UserNameLen = 0;
  511. ULONG ImageNameLen = 0;
  512. EnterTracelibCritSection();
  513. Head = &CurrentSystem.ProcessListHead;
  514. Next = Head->Flink;
  515. while (Next != Head) {
  516. Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  517. Next = Next->Flink;
  518. if ((Process->ReadIO+Process->WriteIO) == 0)
  519. continue;
  520. if ((InstanceCount > 0) &&
  521. (!MatchProcess(Process, InstanceCount, InstanceNames))) {
  522. continue;
  523. }
  524. if (bDrillDown) {
  525. status = DrillDownProcess(Process,
  526. TraceInformationClass,
  527. SystemInformation,
  528. SystemInformationLength,
  529. Length
  530. );
  531. LeaveTracelibCritSection();
  532. return status;
  533. }
  534. else {
  535. UserNameLen = (Process->UserName) ? (lstrlenW(Process->UserName) + 1)
  536. : 0;
  537. UserNameLen = (UserNameLen+1) * sizeof(WCHAR);
  538. ImageNameLen = (Process->ImageName) ?
  539. (lstrlenW(Process->ImageName) + 1)
  540. : 0;
  541. ImageNameLen = (ImageNameLen + 1) * sizeof(WCHAR);
  542. NextEntryOffset = sizeof(TRACE_PROCESS_INFOW) +
  543. UserNameLen + ImageNameLen;
  544. TotalSize += NextEntryOffset;
  545. if (TotalSize > SystemInformationLength) {
  546. status = ERROR_MORE_DATA;
  547. continue;
  548. //LeaveTracelibCritSection();
  549. //goto failed;
  550. }
  551. CopyProcessInfo(ProcessInfo, Process);
  552. ProcessInfo->NextEntryOffset = NextEntryOffset;
  553. LastProcessInfo = ProcessInfo;
  554. ProcessInfo = (PTRACE_PROCESS_INFOW)
  555. ( (PUCHAR)SystemInformation + TotalSize);
  556. if (TraceContext->Flags & TRACE_ZERO_ON_QUERY) { // don't like this!
  557. Process->ReadIO = Process->ReadIOSize
  558. = Process->WriteIO = Process->WriteIOSize
  559. = Process->SendCount = Process->SendSize
  560. = Process->RecvCount = Process->RecvSize
  561. = Process->HPF = Process->SPF
  562. = Process->PrivateWSet = Process->GlobalWSet = 0;
  563. }
  564. }
  565. }
  566. LeaveTracelibCritSection();
  567. if( NULL != LastProcessInfo ){
  568. LastProcessInfo->NextEntryOffset = 0;
  569. }
  570. *Length = TotalSize;
  571. return status;
  572. }
  573. BOOLEAN
  574. MatchInstance(
  575. IN LPCWSTR CurrentInstance,
  576. IN ULONG InstanceCount,
  577. IN LPCWSTR *InstanceNames
  578. )
  579. {
  580. ULONG i;
  581. if (InstanceCount <= 0) // wild card match.
  582. return TRUE;
  583. for (i=0; i < InstanceCount; i++) {
  584. if (CurrentInstance == NULL ||
  585. InstanceNames[i] == NULL)
  586. continue;
  587. if (!_wcsicmp(CurrentInstance, InstanceNames[i])) {
  588. return TRUE;
  589. }
  590. }
  591. return FALSE;
  592. }
  593. BOOLEAN
  594. MatchDisk(
  595. IN ULONG CurrentInstance,
  596. IN ULONG InstanceCount,
  597. IN LPCSTR *InstanceNames
  598. )
  599. {
  600. ULONG i;
  601. ULONG DiskNumber;
  602. if (InstanceCount <= 0) // wild card match.
  603. return TRUE;
  604. for (i=0; i < InstanceCount; i++) {
  605. DiskNumber = atoi(InstanceNames[i]);
  606. if (DiskNumber == CurrentInstance) {
  607. return TRUE;
  608. }
  609. }
  610. return FALSE;
  611. }
  612. static void
  613. CopyProcessInfo(
  614. OUT PTRACE_PROCESS_INFOW ProcessInfo,
  615. IN PPROCESS_RECORD Process
  616. )
  617. {
  618. PWCHAR s;
  619. ULONG NameLength = 0;
  620. ProcessInfo->PID = Process->PID;
  621. ProcessInfo->ReadCount = Process->ReadIO;
  622. ProcessInfo->WriteCount = Process->WriteIO;
  623. ProcessInfo->HPF = Process->HPF;
  624. ProcessInfo->SPF = Process->SPF;
  625. ProcessInfo->PrivateWSet = Process->PrivateWSet;
  626. ProcessInfo->GlobalWSet = Process->GlobalWSet;
  627. ProcessInfo->ReadSize = (Process->ReadIO > 0) ?
  628. Process->ReadIOSize / Process->ReadIO :
  629. 0;
  630. ProcessInfo->WriteSize = (Process->WriteIO > 0) ?
  631. Process->WriteIOSize / Process->WriteIO :
  632. 0;
  633. ProcessInfo->SendCount = Process->SendCount;
  634. ProcessInfo->RecvCount = Process->RecvCount;
  635. ProcessInfo->SendSize = Process->SendCount > 0
  636. ? Process->SendSize / Process->SendCount
  637. : 0;
  638. ProcessInfo->RecvSize = Process->RecvCount > 0
  639. ? Process->RecvSize / Process->RecvCount
  640. : 0;
  641. ProcessInfo->UserCPU = CalculateProcessKCPU(Process);
  642. ProcessInfo->KernelCPU = CalculateProcessUCPU(Process);
  643. ProcessInfo->TransCount = 0;
  644. ProcessInfo->ResponseTime = Process->ResponseTime;
  645. ProcessInfo->TxnStartTime = Process->TxnStartTime;
  646. ProcessInfo->TxnEndTime = Process->TxnEndTime;
  647. ProcessInfo->LifeTime = CalculateProcessLifeTime(Process);
  648. if (Process->UserName) {
  649. s = (PWCHAR) ((char *) ProcessInfo + sizeof(TRACE_PROCESS_INFOW));
  650. wcscpy(s, Process->UserName);
  651. ((PTRACE_PROCESS_INFOW) ProcessInfo)->UserName = s;
  652. NameLength = (lstrlenW(Process->UserName) + 1) * sizeof(WCHAR);
  653. }
  654. else
  655. {
  656. ProcessInfo->UserName = NULL;
  657. }
  658. if (Process->ImageName) {
  659. WCHAR strBuf[MAXSTR];
  660. if (Process->UserName)
  661. {
  662. wcscpy(strBuf, Process->UserName);
  663. wcscat(strBuf, L"(");
  664. }
  665. else
  666. {
  667. wcscpy(strBuf, L"Unknown (");
  668. }
  669. wcscat(strBuf, Process->ImageName);
  670. wcscat(strBuf, L")");
  671. s = (PWCHAR) ((char *) ProcessInfo + sizeof(TRACE_PROCESS_INFOW));
  672. wcscpy(s, strBuf);
  673. ((PTRACE_PROCESS_INFOW) ProcessInfo)->ImageName = s;
  674. }
  675. else {
  676. ProcessInfo->ImageName = NULL;
  677. }
  678. }
  679. ULONG
  680. GetTraceFileInfo(
  681. OUT PVOID FileInformation,
  682. IN ULONG FileInformationLength,
  683. OUT PULONG Length,
  684. IN ULONG InstanceCount,
  685. IN LPCWSTR *InstanceNames,
  686. IN ULONG TraceInformationClass,
  687. IN BOOLEAN bDrillDown
  688. )
  689. {
  690. PLIST_ENTRY Next, Head;
  691. PFILE_RECORD FileRecord;
  692. PPROTO_PROCESS_RECORD ProtoProcess;
  693. PPROCESS_RECORD Process;
  694. ULONG TotalSize = 0;
  695. ULONG NextEntryOffset = 0;
  696. PTRACE_FILE_INFOW FileInfo = NULL;
  697. ULONG status=ERROR_SUCCESS;
  698. ULONG Len;
  699. PTRACE_PROCESS_INFOW ProcessInfo = NULL;
  700. ULONG UserNameLen = 0;
  701. ULONG ImageNameLen = 0;
  702. PWCHAR s;
  703. EnterTracelibCritSection();
  704. Head = &CurrentSystem.HotFileListHead;
  705. Next = Head->Flink;
  706. while (Next != Head) {
  707. FileRecord = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
  708. Next = Next->Flink;
  709. if ((InstanceCount > 0) &&
  710. (!MatchInstance(FileRecord->FileName, InstanceCount, InstanceNames))) {
  711. continue;
  712. }
  713. // Check to see if Instance Drilldown has been requested.
  714. //
  715. if (bDrillDown) {
  716. switch (TraceInformationClass) {
  717. case TraceProcessInformation:
  718. {
  719. Head = &FileRecord->ProtoProcessListHead;
  720. Next = Head->Flink;
  721. while (Next != Head) {
  722. ProtoProcess = CONTAINING_RECORD( Next,
  723. PROTO_PROCESS_RECORD,
  724. Entry );
  725. Next = Next->Flink;
  726. Process = ProtoProcess->ProcessRecord;
  727. if ((ProtoProcess->ReadCount +
  728. ProtoProcess->WriteCount) == 0) continue;
  729. UserNameLen = (Process->UserName) ?
  730. (lstrlenW(Process->UserName) + 1)
  731. : 0;
  732. ImageNameLen = (Process->ImageName) ?
  733. (lstrlenW(Process->ImageName) + 1)
  734. : 0;
  735. UserNameLen = (UserNameLen+1) * sizeof(WCHAR);
  736. ImageNameLen = (ImageNameLen+1) * sizeof(WCHAR);
  737. ProcessInfo = (PTRACE_PROCESS_INFOW)
  738. ( (PUCHAR)FileInformation + TotalSize);
  739. ProcessInfo->PID = Process->PID;
  740. ProcessInfo->ReadCount = ProtoProcess->ReadCount;
  741. ProcessInfo->WriteCount = ProtoProcess->WriteCount;
  742. ProcessInfo->HPF = ProtoProcess->HPF;
  743. ProcessInfo->ReadSize = (ProtoProcess->ReadCount > 0)
  744. ? (ProtoProcess->ReadSize /
  745. ProtoProcess->ReadCount) :
  746. 0;
  747. ProcessInfo->WriteSize = (ProtoProcess->WriteCount
  748. > 0) ?
  749. ProtoProcess->WriteSize
  750. / ProtoProcess->WriteCount :
  751. 0;
  752. if (TraceContext->Flags & TRACE_ZERO_ON_QUERY) {
  753. ProtoProcess->ReadCount = 0;
  754. ProtoProcess->WriteCount = 0;
  755. ProtoProcess->ReadSize = 0;
  756. ProtoProcess->WriteSize = 0;
  757. }
  758. if (Process->ImageName) {
  759. WCHAR strBuf[MAXSTR];
  760. if (Process->UserName) {
  761. wcscpy(strBuf, Process->UserName);
  762. wcscat(strBuf, L" (");
  763. }
  764. else
  765. wcscpy(strBuf, L"Unknown (");
  766. wcscat(strBuf, Process->ImageName);
  767. wcscat(strBuf, L")");
  768. s = (PWCHAR) ((char *)ProcessInfo +
  769. sizeof(TRACE_PROCESS_INFOW));
  770. wcscpy(s, strBuf);
  771. ((PTRACE_PROCESS_INFOW) ProcessInfo)->ImageName = s;
  772. }
  773. else {
  774. ProcessInfo->ImageName = 0;
  775. }
  776. NextEntryOffset = sizeof(TRACE_PROCESS_INFOW) +
  777. UserNameLen+ImageNameLen;
  778. ProcessInfo->NextEntryOffset = NextEntryOffset;
  779. TotalSize += sizeof(TRACE_PROCESS_INFOW) +
  780. UserNameLen +
  781. ImageNameLen;
  782. if (TotalSize > FileInformationLength) {
  783. status = ERROR_MORE_DATA;
  784. LeaveTracelibCritSection();
  785. goto failed;
  786. }
  787. }
  788. break;
  789. }
  790. case TraceFileInformation:
  791. LeaveTracelibCritSection();
  792. return ERROR_NO_DATA;
  793. break;
  794. case TraceDiskInformation:
  795. LeaveTracelibCritSection();
  796. return ERROR_NO_DATA;
  797. break;
  798. }
  799. LeaveTracelibCritSection();
  800. if (ProcessInfo != NULL)
  801. ProcessInfo->NextEntryOffset = 0;
  802. *Length = TotalSize;
  803. return status;
  804. }
  805. // Do not return files with no activity.
  806. //
  807. if (FileRecord->ReadCount == 0 && FileRecord->WriteCount == 0) {
  808. continue;
  809. }
  810. FileInfo = (PTRACE_FILE_INFOW)
  811. ( (PUCHAR)FileInformation + TotalSize);
  812. Len = (lstrlenW(FileRecord->FileName) +1) * sizeof(WCHAR);
  813. NextEntryOffset = sizeof(TRACE_FILE_INFOW) + Len;
  814. TotalSize += sizeof(TRACE_FILE_INFOW) + Len;
  815. if (TotalSize > FileInformationLength) {
  816. status = ERROR_MORE_DATA;
  817. LeaveTracelibCritSection();
  818. goto failed;
  819. }
  820. CopyFileInfo(FileInfo, FileRecord);
  821. if (TraceContext->Flags & TRACE_ZERO_ON_QUERY) { // pseudo sort
  822. FileRecord->ReadCount =
  823. FileRecord->WriteCount =
  824. FileRecord->ReadSize =
  825. FileRecord->WriteSize = 0;
  826. }
  827. FileInfo->NextEntryOffset = NextEntryOffset;
  828. // Go to the next File
  829. }
  830. LeaveTracelibCritSection();
  831. if (FileInfo != NULL)
  832. FileInfo->NextEntryOffset = 0;
  833. *Length = TotalSize;
  834. failed:
  835. return status;
  836. }
  837. static void
  838. CopyFileInfo(
  839. OUT PTRACE_FILE_INFOW FileInfo,
  840. IN PFILE_RECORD FileRecord
  841. )
  842. {
  843. PVOID s;
  844. char* t;
  845. FileInfo->DiskNumber = FileRecord->DiskNumber;
  846. FileInfo->ReadCount = FileRecord->ReadCount;
  847. FileInfo->WriteCount = FileRecord->WriteCount;
  848. FileInfo->ReadSize = (FileInfo->ReadCount > 0) ?
  849. FileRecord->ReadSize / FileRecord->ReadCount :
  850. 0;
  851. FileInfo->WriteSize = (FileRecord->WriteCount > 0) ?
  852. FileRecord->WriteSize / FileRecord->WriteCount :
  853. 0;
  854. t = s = (char*)FileInfo + sizeof(TRACE_FILE_INFOW);
  855. wcscpy((PWCHAR)s, FileRecord->FileName);
  856. FileInfo->FileName = (PWCHAR)s;
  857. }
  858. ULONG
  859. DrillDownDisk(
  860. IN PTDISK_RECORD DiskRecord,
  861. IN ULONG TraceInformationClass,
  862. OUT PVOID DiskInformation,
  863. IN ULONG DiskInformationLength,
  864. OUT PULONG Length
  865. )
  866. {
  867. PLIST_ENTRY Next, Head;
  868. PPROCESS_RECORD Process = NULL;
  869. PFILE_RECORD pFile = NULL;
  870. ULONG TotalSize = 0;
  871. ULONG NextEntryOffset = 0;
  872. PTRACE_DISK_INFOW DiskInfo = NULL;
  873. PTRACE_PROCESS_INFOW ProcessInfo = NULL;
  874. PTRACE_FILE_INFOW FileInfo = NULL;
  875. ULONG EntrySize = 0;
  876. if (DiskRecord == NULL)
  877. return ERROR_INVALID_PARAMETER;
  878. switch (TraceInformationClass) {
  879. case TraceProcessInformation:
  880. Head = &DiskRecord->ProcessListHead;
  881. EntrySize = sizeof(TRACE_PROCESS_INFOW);
  882. break;
  883. /* case TraceThreadInformation:
  884. Head = &DiskRecord->ThreadListHead;
  885. EntrySize = sizeof(TRACE_THREAD_INFO);
  886. break;
  887. */
  888. case TraceFileInformation:
  889. Head = & CurrentSystem.HotFileListHead;
  890. EntrySize = sizeof(TRACE_FILE_INFOW);
  891. break;
  892. default:
  893. return ERROR_INVALID_PARAMETER;
  894. }
  895. Next = Head->Flink;
  896. while (Next != Head) {
  897. // Return the data in the Appropriate structure
  898. //
  899. switch (TraceInformationClass) {
  900. case TraceProcessInformation:
  901. {
  902. ULONG UserNameLen, ImageNameLen;
  903. Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry);
  904. Next = Next->Flink;
  905. ProcessInfo = (PTRACE_PROCESS_INFOW)
  906. ((PUCHAR) DiskInformation + TotalSize);
  907. UserNameLen = (Process->UserName) ?
  908. (lstrlenW(Process->UserName) + 1) : 0;
  909. UserNameLen = (UserNameLen+1) * sizeof(WCHAR);
  910. ImageNameLen = (Process->ImageName) ?
  911. (lstrlenW(Process->ImageName) + 1) : 0;
  912. ImageNameLen = (ImageNameLen + 1) * sizeof(WCHAR);
  913. NextEntryOffset = sizeof(TRACE_PROCESS_INFOW) +
  914. UserNameLen + ImageNameLen;
  915. TotalSize += NextEntryOffset;
  916. if (TotalSize > DiskInformationLength) {
  917. LeaveTracelibCritSection();
  918. *Length = 0;
  919. return ERROR_MORE_DATA;
  920. }
  921. CopyProcessInfo(ProcessInfo, Process);
  922. if (TraceContext->Flags & TRACE_ZERO_ON_QUERY) {
  923. Process->ReadIO = 0;
  924. Process->WriteIO = 0;
  925. Process->HPF = Process->SPF = 0;
  926. Process->ReadIOSize = Process->WriteIOSize = 0;
  927. Process->PrivateWSet = Process->GlobalWSet = 0;
  928. }
  929. ProcessInfo->NextEntryOffset = NextEntryOffset;
  930. break;
  931. }
  932. //case TraceThreadInformation:
  933. // break;
  934. case TraceFileInformation:
  935. {
  936. ULONG NameLen;
  937. pFile = CONTAINING_RECORD(Next, FILE_RECORD, Entry);
  938. Next = Next->Flink;
  939. if (pFile->DiskNumber != DiskRecord->DiskNumber)
  940. continue;
  941. if (pFile->ReadCount == 0 && pFile->WriteCount == 0)
  942. continue;
  943. FileInfo = (PTRACE_FILE_INFOW)
  944. ((PUCHAR) DiskInformation + TotalSize);
  945. NameLen = (lstrlenW(pFile->FileName) + 1) * sizeof(WCHAR);
  946. NextEntryOffset = sizeof(TRACE_FILE_INFOW) + NameLen;
  947. TotalSize += sizeof(TRACE_FILE_INFOW) + NameLen;
  948. if (TotalSize > DiskInformationLength)
  949. {
  950. LeaveTracelibCritSection();
  951. * Length = 0;
  952. return ERROR_MORE_DATA;
  953. }
  954. CopyFileInfo(FileInfo, pFile);
  955. if (TraceContext->Flags & TRACE_ZERO_ON_QUERY)
  956. {
  957. pFile->ReadCount =
  958. pFile->WriteCount =
  959. pFile->ReadSize =
  960. pFile->WriteSize = 0;
  961. }
  962. FileInfo->NextEntryOffset = NextEntryOffset;
  963. break;
  964. }
  965. default:
  966. return ERROR_INVALID_PARAMETER;
  967. }
  968. }
  969. if (ProcessInfo != NULL)
  970. ProcessInfo->NextEntryOffset = 0;
  971. if (FileInfo != NULL)
  972. FileInfo->NextEntryOffset = 0;
  973. if (DiskInfo != NULL)
  974. DiskInfo->NextEntryOffset = 0;
  975. *Length = TotalSize;
  976. return ERROR_SUCCESS;
  977. }
  978. ULONG
  979. GetTraceDiskInfo(
  980. OUT PVOID DiskInformation,
  981. IN ULONG DiskInformationLength,
  982. OUT PULONG Length,
  983. IN ULONG InstanceCount,
  984. IN LPCWSTR *InstanceNames,
  985. IN ULONG TraceInformationClass,
  986. IN BOOLEAN bDrillDown
  987. )
  988. {
  989. PLIST_ENTRY Next, Head;
  990. PTDISK_RECORD DiskRecord;
  991. ULONG TotalSize = 0;
  992. ULONG NextEntryOffset = 0;
  993. PTRACE_DISK_INFOW DiskInfo = NULL;
  994. ULONG status=0;
  995. ULONG len;
  996. PWCHAR s;
  997. EnterTracelibCritSection();
  998. Head = &CurrentSystem.GlobalDiskListHead;
  999. Next = Head->Flink;
  1000. while (Next != Head) {
  1001. DiskRecord = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
  1002. Next = Next->Flink;
  1003. if ( (InstanceCount > 0)
  1004. && (!MatchInstance(DiskRecord->DiskName,
  1005. InstanceCount,
  1006. InstanceNames)))
  1007. {
  1008. continue;
  1009. }
  1010. if ((DiskRecord->ReadCount+DiskRecord->WriteCount) == 0)
  1011. continue;
  1012. if (bDrillDown) {
  1013. status = DrillDownDisk(DiskRecord,
  1014. TraceInformationClass,
  1015. DiskInformation,
  1016. DiskInformationLength,
  1017. Length);
  1018. LeaveTracelibCritSection();
  1019. return status;
  1020. }
  1021. // If it's not a drilldown request, then it must be for
  1022. // the Disk record.
  1023. //
  1024. DiskInfo = (PTRACE_DISK_INFOW)
  1025. ( (PUCHAR)DiskInformation + TotalSize);
  1026. len = sizeof(TRACE_DISK_INFOW) + (lstrlenW(DiskRecord->DiskName)+1) * sizeof(WCHAR);
  1027. NextEntryOffset = len; // sizeof(TRACE_DISK_INFOW);
  1028. TotalSize += len; // sizeof(TRACE_DISK_INFOW);
  1029. if (TotalSize > DiskInformationLength) {
  1030. status = ERROR_MORE_DATA;
  1031. LeaveTracelibCritSection();
  1032. goto failed;
  1033. }
  1034. CopyDiskInfo(DiskInfo, DiskRecord);
  1035. s = (PWCHAR) ((char*) DiskInfo + sizeof(TRACE_DISK_INFOW));
  1036. wcscpy(s, DiskRecord->DiskName);
  1037. DiskInfo->DiskName = (PWCHAR)s;
  1038. if (TraceContext->Flags & TRACE_ZERO_ON_QUERY) { // pseudo sort
  1039. DiskRecord->ReadCount = 0;
  1040. DiskRecord->WriteCount = 0;
  1041. DiskRecord->ReadSize = 0;
  1042. DiskRecord->WriteSize = 0;
  1043. }
  1044. DiskInfo->NextEntryOffset = NextEntryOffset;
  1045. }
  1046. LeaveTracelibCritSection();
  1047. if (DiskInfo != NULL)
  1048. DiskInfo->NextEntryOffset = 0;
  1049. *Length = TotalSize;
  1050. failed:
  1051. return status;
  1052. }
  1053. static void
  1054. CopyDiskInfo(
  1055. OUT PTRACE_DISK_INFOW DiskInfo,
  1056. IN PTDISK_RECORD DiskRecord
  1057. )
  1058. {
  1059. DiskInfo->DiskNumber = DiskRecord->DiskNumber;
  1060. DiskInfo->ReadCount = DiskRecord->ReadCount;
  1061. DiskInfo->WriteCount = DiskRecord->WriteCount;
  1062. DiskInfo->ReadSize = (DiskInfo->ReadCount > 0) ?
  1063. DiskRecord->ReadSize / DiskRecord->ReadCount :
  1064. 0;
  1065. DiskInfo->WriteSize = (DiskRecord->WriteCount > 0) ?
  1066. DiskRecord->WriteSize / DiskRecord->WriteCount :
  1067. 0;
  1068. }
  1069. ULONG
  1070. GetTraceModuleInfo(
  1071. OUT PVOID ModuleInformation,
  1072. IN ULONG ModuleInformationLength,
  1073. OUT PULONG Length,
  1074. OUT PVOID * ppModuleLast,
  1075. IN PPROCESS_RECORD pProcess,
  1076. IN PLIST_ENTRY pModuleListHead,
  1077. IN ULONG lOffset
  1078. )
  1079. {
  1080. ULONG status = 0;
  1081. PLIST_ENTRY pNext = pModuleListHead->Flink;
  1082. ULONG lTotalSize = lOffset;
  1083. ULONG lCurrentSize;
  1084. ULONG lModuleNameLength;
  1085. ULONG lImageNameLength;
  1086. PMODULE_RECORD pModule;
  1087. PTRACE_MODULE_INFO pModuleInfo;
  1088. ULONG ProcessID = pProcess ? pProcess->PID : 0;
  1089. LPWSTR strImageName = pProcess ? pProcess->ImageName : NULL;
  1090. EnterTracelibCritSection();
  1091. while (pNext != pModuleListHead)
  1092. {
  1093. pModule = CONTAINING_RECORD(pNext, MODULE_RECORD, Entry);
  1094. pNext = pNext->Flink;
  1095. lModuleNameLength = lstrlenW(pModule->strModuleName) + 1;
  1096. lImageNameLength = (strImageName) ? (lstrlenW(strImageName) + 1) : (1);
  1097. lCurrentSize = sizeof(TRACE_MODULE_INFO)
  1098. + sizeof(WCHAR) * lModuleNameLength
  1099. + sizeof(WCHAR) * lImageNameLength;
  1100. pModuleInfo = (PTRACE_MODULE_INFO)
  1101. ((PUCHAR) ModuleInformation + lTotalSize);
  1102. pModuleInfo->PID = ProcessID;
  1103. pModuleInfo->lBaseAddress = pModule->lBaseAddress;
  1104. pModuleInfo->lModuleSize = pModule->lModuleSize;
  1105. pModuleInfo->lDataFaultHF = pModule->lDataFaultHF;
  1106. pModuleInfo->lDataFaultTF = pModule->lDataFaultTF;
  1107. pModuleInfo->lDataFaultDZF = pModule->lDataFaultDZF;
  1108. pModuleInfo->lDataFaultCOW = pModule->lDataFaultCOW;
  1109. pModuleInfo->lCodeFaultHF = pModule->lCodeFaultHF;
  1110. pModuleInfo->lCodeFaultTF = pModule->lCodeFaultTF;
  1111. pModuleInfo->lCodeFaultDZF = pModule->lCodeFaultDZF;
  1112. pModuleInfo->lCodeFaultCOW = pModule->lCodeFaultCOW;
  1113. pModuleInfo->NextEntryOffset = lCurrentSize;
  1114. pModuleInfo->strImageName = (PWCHAR) ((PUCHAR) pModuleInfo
  1115. + sizeof(TRACE_MODULE_INFO));
  1116. if (strImageName)
  1117. {
  1118. wcscpy(pModuleInfo->strImageName, strImageName);
  1119. }
  1120. pModuleInfo->strModuleName = (WCHAR *) ((PUCHAR) pModuleInfo
  1121. + sizeof(TRACE_MODULE_INFO)
  1122. + sizeof(WCHAR) * lImageNameLength);
  1123. wcscpy(pModuleInfo->strModuleName, pModule->strModuleName);
  1124. if (pNext == pModuleListHead)
  1125. {
  1126. * ppModuleLast = pModuleInfo;
  1127. }
  1128. lTotalSize += lCurrentSize;
  1129. if (lTotalSize > ModuleInformationLength)
  1130. {
  1131. status = ERROR_MORE_DATA;
  1132. }
  1133. }
  1134. * Length = lTotalSize;
  1135. LeaveTracelibCritSection();
  1136. return status;
  1137. }
  1138. ULONG
  1139. GetTraceProcessModuleInfo (
  1140. OUT PVOID ModuleInformation,
  1141. IN ULONG ModuleInformationLength,
  1142. OUT PULONG Length,
  1143. IN ULONG InstanceCount,
  1144. IN LPCWSTR* InstanceNames
  1145. )
  1146. {
  1147. ULONG status = 0;
  1148. ULONG lOffset = 0;
  1149. PPROCESS_RECORD pProcess;
  1150. PLIST_ENTRY pHead = & CurrentSystem.ProcessListHead;
  1151. PLIST_ENTRY pNext = pHead->Flink;
  1152. PVOID pModuleLast = NULL;
  1153. while (status == 0 && pNext != pHead)
  1154. {
  1155. pProcess = CONTAINING_RECORD(pNext, PROCESS_RECORD, Entry);
  1156. pNext = pNext->Flink;
  1157. if ( InstanceCount > 0
  1158. && !MatchProcess(pProcess, InstanceCount, InstanceNames))
  1159. {
  1160. continue;
  1161. }
  1162. status = GetTraceModuleInfo(
  1163. ModuleInformation,
  1164. ModuleInformationLength,
  1165. Length,
  1166. & pModuleLast,
  1167. pProcess,
  1168. & pProcess->ModuleListHead,
  1169. lOffset);
  1170. if (status == 0)
  1171. {
  1172. lOffset = * Length;
  1173. }
  1174. }
  1175. * Length = lOffset;
  1176. if (pModuleLast)
  1177. {
  1178. ((PTRACE_MODULE_INFO) pModuleLast)->NextEntryOffset = 0;
  1179. }
  1180. return status;
  1181. }
  1182. ULONG
  1183. GetTraceProcessFaultInfo(
  1184. OUT PVOID ProcessFaultInformation,
  1185. IN ULONG ProcessFaultInformationLength,
  1186. OUT PULONG Length
  1187. )
  1188. {
  1189. ULONG status = 0;
  1190. PLIST_ENTRY pHead = & CurrentSystem.ProcessListHead;
  1191. PLIST_ENTRY pNext = pHead->Flink;
  1192. ULONG TotalSize = 0;
  1193. ULONG CurrentSize;
  1194. ULONG lenImgName;
  1195. PPROCESS_RECORD pProcess;
  1196. PTRACE_PROCESS_FAULT_INFO pProcessInfo;
  1197. UNREFERENCED_PARAMETER(Length);
  1198. EnterTracelibCritSection();
  1199. while (status == 0 && pNext != pHead)
  1200. {
  1201. pProcess = CONTAINING_RECORD(pNext, PROCESS_RECORD, Entry);
  1202. pNext = pNext->Flink;
  1203. lenImgName = (pProcess->ImageName)
  1204. ? (lstrlenW(pProcess->ImageName) + 1)
  1205. : (1);
  1206. CurrentSize = sizeof(TRACE_PROCESS_FAULT_INFO)
  1207. + sizeof(WCHAR) * lenImgName;
  1208. pProcessInfo = (PTRACE_PROCESS_FAULT_INFO)
  1209. ((PUCHAR) ProcessFaultInformation + TotalSize);
  1210. pProcessInfo->PID = pProcess->PID;
  1211. pProcessInfo->lDataFaultHF = pProcess->lDataFaultHF;
  1212. pProcessInfo->lDataFaultTF = pProcess->lDataFaultTF;
  1213. pProcessInfo->lDataFaultDZF = pProcess->lDataFaultDZF;
  1214. pProcessInfo->lDataFaultCOW = pProcess->lDataFaultCOW;
  1215. pProcessInfo->lCodeFaultHF = pProcess->lCodeFaultHF;
  1216. pProcessInfo->lCodeFaultTF = pProcess->lCodeFaultTF;
  1217. pProcessInfo->lCodeFaultDZF = pProcess->lCodeFaultDZF;
  1218. pProcessInfo->lCodeFaultCOW = pProcess->lCodeFaultCOW;
  1219. pProcessInfo->NextEntryOffset = CurrentSize;
  1220. pProcessInfo->ImageName =
  1221. (PWCHAR)((PUCHAR) pProcessInfo + sizeof(TRACE_PROCESS_FAULT_INFO));
  1222. if (pProcess->ImageName)
  1223. {
  1224. wcscpy(pProcessInfo->ImageName, pProcess->ImageName);
  1225. }
  1226. TotalSize += CurrentSize;
  1227. if (TotalSize > ProcessFaultInformationLength)
  1228. {
  1229. status = ERROR_MORE_DATA;
  1230. }
  1231. }
  1232. LeaveTracelibCritSection();
  1233. return status;
  1234. }
  1235. ULONG
  1236. CPDAPI
  1237. TraceDrillDownW(
  1238. IN TRACEINFOCLASS RootInformationClass,
  1239. IN LPCWSTR InstanceName,
  1240. IN TRACEINFOCLASS TraceInformationClass,
  1241. OUT PVOID TraceInformation,
  1242. IN ULONG TraceInformationLength,
  1243. OUT PULONG Length
  1244. )
  1245. {
  1246. // Error Checking
  1247. //
  1248. if ( (InstanceName == NULL || TraceInformation == NULL) ||
  1249. (TraceInformationLength == 0))
  1250. return ERROR_INVALID_PARAMETER;
  1251. switch(RootInformationClass) {
  1252. case TraceProcessInformation:
  1253. {
  1254. ULONG Status;
  1255. Status = GetTraceProcessInfo(TraceInformation,
  1256. TraceInformationLength,
  1257. Length,
  1258. 1,
  1259. (LPCWSTR *) & InstanceName,
  1260. TraceInformationClass,
  1261. TRUE);
  1262. return Status;
  1263. }
  1264. case TraceFileInformation:
  1265. return GetTraceFileInfo(TraceInformation,
  1266. TraceInformationLength,
  1267. Length,
  1268. 1,
  1269. (LPCWSTR *) & InstanceName,
  1270. TraceInformationClass,
  1271. TRUE);
  1272. case TraceDiskInformation:
  1273. return GetTraceDiskInfo(TraceInformation,
  1274. TraceInformationLength,
  1275. Length,
  1276. 1,
  1277. (LPCWSTR *) & InstanceName,
  1278. TraceInformationClass,
  1279. TRUE);
  1280. }
  1281. return (ERROR_SUCCESS);
  1282. }