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.

2554 lines
66 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. process.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 <stdlib.h>
  14. #include "cpdata.h"
  15. #include "tracectr.h"
  16. #include "item.h"
  17. extern PTRACE_CONTEXT_BLOCK TraceContext;
  18. extern PWCHAR CpdiGuidToString(PWCHAR s, ULONG len, LPGUID piid);
  19. extern LIST_ENTRY g_ValueMapTable;
  20. VOID
  21. Aggregate(
  22. IN PTHREAD_RECORD pThread
  23. );
  24. ULONG
  25. CPDAPI
  26. GetTempName( LPTSTR strFile, size_t cchSize )
  27. {
  28. HRESULT hr;
  29. DWORD dwStatus;
  30. GUID guid;
  31. WCHAR strGUID[128];
  32. DWORD nChar = 0;
  33. dwStatus = UuidCreate( &guid );
  34. if( dwStatus == RPC_S_OK || dwStatus == RPC_S_UUID_LOCAL_ONLY ){
  35. nChar = StringFromGUID2( (const GUID*)&guid, strGUID, 128 );
  36. dwStatus = ERROR_SUCCESS;
  37. }
  38. if( 0 == nChar ){
  39. hr = StringCchPrintf( strGUID, 128, L"{d41c99ea-c303-4d06-b779-f9e8e20acb8f}.%08d", rand() );
  40. }
  41. nChar = GetTempPath( cchSize, strFile );
  42. if( 0 == nChar ){
  43. dwStatus = GetLastError();
  44. }
  45. if( ERROR_SUCCESS == dwStatus ){
  46. hr = StringCchCat( strFile, cchSize, strGUID );
  47. }
  48. return dwStatus;
  49. }
  50. __inline
  51. USHORT
  52. UrlHashKey(
  53. PUCHAR UrlStr,
  54. ULONG StrSize
  55. )
  56. {
  57. USHORT i, l, key = 0;
  58. i = (USHORT)(StrSize - 1);
  59. // Use only the last 25 chars
  60. l = (StrSize > 25) ? (USHORT)(StrSize - 25) : 0;
  61. // UrlStr cannot be NULL when this function is called.
  62. for ( ; i >= l; i--) {
  63. key = 37 * key + (USHORT)(*(UrlStr + i));
  64. if (i == 0) {
  65. break;
  66. }
  67. }
  68. key = key % (URL_HASH_TABLESIZE);
  69. return key;
  70. }
  71. VOID
  72. InitDiskRecord(
  73. PTDISK_RECORD pDisk,
  74. ULONG DiskNumber
  75. )
  76. {
  77. PWCHAR name;
  78. if (pDisk == NULL){
  79. return;
  80. }
  81. memset(pDisk, 0, sizeof(TDISK_RECORD));
  82. InitializeListHead(&pDisk->ProcessListHead);
  83. InitializeListHead(&pDisk->FileListHead);
  84. pDisk->DiskNumber = DiskNumber;
  85. name = (PWCHAR)malloc(16 * sizeof(WCHAR));
  86. if (name != NULL) {
  87. StringCbPrintfW(name, 16 * sizeof(WCHAR), L"Disk%d", DiskNumber);
  88. }
  89. pDisk->DiskName = name;
  90. }
  91. VOID
  92. InitFileRecord(
  93. PFILE_RECORD pFile
  94. )
  95. {
  96. if (pFile == NULL){
  97. return;
  98. }
  99. memset(pFile, 0, sizeof(FILE_RECORD));
  100. InitializeListHead(&pFile->ProtoProcessListHead);
  101. }
  102. VOID
  103. InitThreadRecord(
  104. PTHREAD_RECORD pThread
  105. )
  106. {
  107. if (pThread == NULL)
  108. return;
  109. memset(pThread, 0, sizeof(THREAD_RECORD));
  110. InitializeListHead( &pThread->DiskListHead );
  111. InitializeListHead( &pThread->TransListHead );
  112. InitializeListHead( &pThread->HPFReadListHead );
  113. InitializeListHead( &pThread->HPFWriteListHead );
  114. }
  115. PTRANS_RECORD
  116. CreateTransRecord()
  117. {
  118. PLIST_ENTRY Head, Next;
  119. PTRANS_RECORD pTrans = NULL;
  120. EnterTracelibCritSection();
  121. Head = &CurrentSystem.FreeTransListHead;
  122. Next = Head->Flink;
  123. if (Next != Head) {
  124. pTrans = CONTAINING_RECORD ( Next, TRANS_RECORD, Entry );
  125. RemoveEntryList( &pTrans->Entry );
  126. }
  127. LeaveTracelibCritSection();
  128. if (pTrans == NULL) {
  129. pTrans = malloc(sizeof(TRANS_RECORD));
  130. if (pTrans == NULL) {
  131. SetLastError(ERROR_OUTOFMEMORY);
  132. return NULL;
  133. }
  134. }
  135. memset(pTrans, 0, sizeof(TRANS_RECORD));
  136. InitializeListHead(&pTrans->SubTransListHead);
  137. return pTrans;
  138. }
  139. VOID
  140. InitMofData(
  141. PMOF_DATA pMofData
  142. )
  143. {
  144. if (pMofData == NULL)
  145. return;
  146. memset(pMofData, 0, sizeof(MOF_DATA));
  147. pMofData->MaxKCpu = -1;
  148. pMofData->MinKCpu = -1;
  149. pMofData->MaxUCpu = -1;
  150. pMofData->MinUCpu = -1;
  151. }
  152. VOID
  153. InitProcessRecord(
  154. PPROCESS_RECORD pProcess
  155. )
  156. {
  157. if (pProcess == NULL)
  158. return;
  159. memset(pProcess, 0, sizeof(PROCESS_RECORD));
  160. InitializeListHead( &pProcess->ThreadListHead );
  161. InitializeListHead( &pProcess->DiskListHead );
  162. InitializeListHead( &pProcess->FileListHead );
  163. InitializeListHead( &pProcess->ModuleListHead );
  164. InitializeListHead( &pProcess->HPFListHead );
  165. }
  166. BOOLEAN AddModuleRecord(PMODULE_RECORD * ppModule,
  167. ULONG lBaseAddress,
  168. ULONG lModuleSize,
  169. WCHAR * strModuleName)
  170. {
  171. PMODULE_RECORD pModule;
  172. if ( (ppModule == NULL) || (strModuleName == NULL) ) {
  173. return FALSE;
  174. }
  175. pModule = (PMODULE_RECORD)malloc(sizeof(MODULE_RECORD));
  176. if(NULL != pModule){
  177. memset(pModule, 0, sizeof(MODULE_RECORD));
  178. pModule->strModuleName =
  179. malloc(sizeof(WCHAR) * (lstrlenW(strModuleName) + 1));
  180. if (pModule->strModuleName == NULL)
  181. {
  182. free(pModule);
  183. pModule = NULL;
  184. }
  185. else
  186. {
  187. StringCchCopyW(pModule->strModuleName, (lstrlenW(strModuleName) + 1), strModuleName);
  188. pModule->lBaseAddress = lBaseAddress;
  189. pModule->lModuleSize = lModuleSize;
  190. }
  191. }
  192. * ppModule = pModule;
  193. return (BOOLEAN) (* ppModule != NULL);
  194. }
  195. BOOLEAN AddHPFFileRecord(
  196. PHPF_FILE_RECORD * ppHPFFileRecord,
  197. ULONG RecordID,
  198. ULONG IrpFlags,
  199. ULONG DiskNumber,
  200. ULONGLONG ByteOffset,
  201. ULONG BytesCount,
  202. PVOID fDO
  203. )
  204. {
  205. PHPF_FILE_RECORD pHPFFileRecord = malloc(sizeof(HPF_FILE_RECORD));
  206. if (pHPFFileRecord)
  207. {
  208. pHPFFileRecord->RecordID = RecordID;
  209. pHPFFileRecord->IrpFlags = IrpFlags;
  210. pHPFFileRecord->DiskNumber = DiskNumber;
  211. pHPFFileRecord->ByteOffset = ByteOffset;
  212. pHPFFileRecord->BytesCount = BytesCount;
  213. pHPFFileRecord->fDO = fDO;
  214. }
  215. * ppHPFFileRecord = pHPFFileRecord;
  216. return (BOOLEAN) (* ppHPFFileRecord != NULL);
  217. }
  218. BOOLEAN AddHPFRecord(
  219. PHPF_RECORD * ppHPFRecord,
  220. ULONG lFaultAddress,
  221. PVOID fDO,
  222. LONG ByteCount,
  223. LONGLONG ByteOffset
  224. )
  225. {
  226. PHPF_RECORD pHPFRecord = malloc(sizeof(HPF_RECORD));
  227. if (pHPFRecord)
  228. {
  229. pHPFRecord->fDO = fDO;
  230. pHPFRecord->lFaultAddress = lFaultAddress;
  231. pHPFRecord->lByteCount = ByteCount;
  232. pHPFRecord->lByteOffset = ByteOffset;
  233. InitializeListHead(& pHPFRecord->HPFReadListHead);
  234. }
  235. * ppHPFRecord = pHPFRecord;
  236. return (BOOLEAN) (* ppHPFRecord != NULL);
  237. }
  238. void DeleteHPFRecord(
  239. PHPF_RECORD pHPFRecord
  240. )
  241. {
  242. PLIST_ENTRY pHead;
  243. PLIST_ENTRY pNext;
  244. PHPF_FILE_RECORD pHPFFileRecord;
  245. if (!pHPFRecord)
  246. return;
  247. RemoveEntryList(& pHPFRecord->Entry);
  248. pHead = & pHPFRecord->HPFReadListHead;
  249. pNext = pHead->Flink;
  250. while (pNext != pHead)
  251. {
  252. pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
  253. pNext = pNext->Flink;
  254. RemoveEntryList(& pHPFFileRecord->Entry);
  255. free(pHPFFileRecord);
  256. }
  257. free(pHPFRecord);
  258. return;
  259. }
  260. VOID
  261. InitWorkloadRecord(
  262. PWORKLOAD_RECORD pWorkload
  263. )
  264. {
  265. if (pWorkload == NULL)
  266. return;
  267. memset(pWorkload, 0, sizeof(WORKLOAD_RECORD));
  268. InitializeListHead( &pWorkload->DiskListHead );
  269. }
  270. VOID
  271. DeleteWorkloadRecord(
  272. PWORKLOAD_RECORD pWorkload
  273. )
  274. {
  275. if (pWorkload == NULL)
  276. return;
  277. }
  278. PPROTO_PROCESS_RECORD
  279. AddProtoProcess(
  280. PFILE_RECORD pFile,
  281. PPROCESS_RECORD pProcess
  282. )
  283. {
  284. PPROTO_PROCESS_RECORD pProto;
  285. if (pFile == NULL || pProcess == NULL)
  286. return NULL;
  287. pProto = malloc(sizeof(PROTO_PROCESS_RECORD));
  288. if (pProto == NULL) {
  289. return NULL;
  290. }
  291. memset(pProto, 0, sizeof(PROTO_PROCESS_RECORD));
  292. pProto->ProcessRecord = pProcess;
  293. InsertHeadList( &pFile->ProtoProcessListHead, &pProto->Entry );
  294. return pProto;
  295. }
  296. PPROTO_PROCESS_RECORD
  297. FindProtoProcessRecord(
  298. PFILE_RECORD pFile,
  299. PPROCESS_RECORD pProcess
  300. )
  301. {
  302. PLIST_ENTRY Next, Head;
  303. PPROTO_PROCESS_RECORD pProto;
  304. if (pFile == NULL || pProcess == NULL)
  305. return NULL;
  306. Head = &pFile->ProtoProcessListHead;
  307. Next = Head->Flink;
  308. while (Next != Head) {
  309. pProto = CONTAINING_RECORD(Next, PROTO_PROCESS_RECORD, Entry);
  310. if (pProcess == pProto->ProcessRecord)
  311. return pProto;
  312. Next = Next->Flink;
  313. }
  314. return (AddProtoProcess(pFile, pProcess));
  315. }
  316. BOOLEAN
  317. AddProcess(
  318. ULONG ProcessId,
  319. PPROCESS_RECORD *ReturnedProcess
  320. )
  321. {
  322. PPROCESS_RECORD Process;
  323. PMODULE_RECORD pModule = NULL;
  324. Process = malloc(sizeof(PROCESS_RECORD));
  325. if (Process == NULL) {
  326. return FALSE;
  327. }
  328. InitProcessRecord( Process );
  329. Process->PID = ProcessId;
  330. if (!AddModuleRecord(& pModule, 0, 0, L"other")) {
  331. free(Process);
  332. return FALSE;
  333. }
  334. pModule->pProcess = Process;
  335. EnterTracelibCritSection();
  336. InsertHeadList( &CurrentSystem.ProcessListHead, &Process->Entry );
  337. InsertHeadList(& Process->ModuleListHead, & pModule->Entry);
  338. LeaveTracelibCritSection();
  339. *ReturnedProcess = Process;
  340. return TRUE;
  341. }
  342. BOOLEAN
  343. DeleteProcess(
  344. PPROCESS_RECORD Process
  345. )
  346. {
  347. PLIST_ENTRY Next, Head;
  348. PTHREAD_RECORD Thread;
  349. PTDISK_RECORD Disk;
  350. PFILE_RECORD pFile;
  351. PMODULE_RECORD pModule;
  352. PHPF_RECORD pHPFRecord;
  353. if (Process == NULL)
  354. return FALSE;
  355. EnterTracelibCritSection();
  356. RemoveEntryList( &Process->Entry );
  357. LeaveTracelibCritSection();
  358. Head = &Process->ThreadListHead;
  359. Next = Head->Flink;
  360. while (Next != Head) {
  361. Thread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
  362. Next = Next->Flink;
  363. DeleteThread( Thread );
  364. }
  365. Head = &Process->DiskListHead;
  366. Next = Head->Flink;
  367. while (Next != Head) {
  368. Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
  369. Next = Next->Flink;
  370. DeleteDisk( Disk );
  371. }
  372. Head = &Process->HPFListHead;
  373. Next = Head->Flink;
  374. while (Next != Head) {
  375. pHPFRecord = CONTAINING_RECORD(Next, HPF_RECORD, Entry);
  376. Next = Next->Flink;
  377. DeleteHPFRecord(pHPFRecord);
  378. }
  379. Head = &Process->FileListHead;
  380. Next = Head->Flink;
  381. while (Next != Head) {
  382. pFile = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
  383. Next = Next->Flink;
  384. RemoveEntryList( &pFile->Entry );
  385. if (pFile->FileName != NULL)
  386. free(pFile->FileName);
  387. free(pFile);
  388. }
  389. Head = &Process->ModuleListHead;
  390. Next = Head->Flink;
  391. while (Next != Head)
  392. {
  393. pModule = CONTAINING_RECORD(Next, MODULE_RECORD, Entry);
  394. Next = Next->Flink;
  395. RemoveEntryList(& pModule->Entry);
  396. if(pModule->strModuleName)
  397. {
  398. free(pModule->strModuleName);
  399. }
  400. free(pModule);
  401. }
  402. if (Process->ImageName != NULL)
  403. free(Process->ImageName);
  404. if (Process->UserName != NULL)
  405. free(Process->UserName);
  406. free( Process );
  407. return TRUE;
  408. }
  409. BOOLEAN
  410. AddThread(
  411. ULONG ThreadId,
  412. PEVENT_TRACE pEvent,
  413. PTHREAD_RECORD * ResultThread
  414. )
  415. {
  416. PTHREAD_RECORD Thread = NULL;
  417. PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER) & pEvent->Header;
  418. int i;
  419. Thread = malloc(sizeof(THREAD_RECORD));
  420. if (Thread == NULL) {
  421. return FALSE;
  422. }
  423. InitThreadRecord(Thread);
  424. Thread->TimeStart = Thread->TimeEnd
  425. = (ULONGLONG) pHeader->TimeStamp.QuadPart;
  426. Thread->TID = ThreadId;
  427. Thread->ProcessorID = pEvent->ClientContext & 0x000000FF;
  428. i = (int)Thread->TID;
  429. i = i % THREAD_HASH_TABLESIZE;
  430. InsertHeadList(&CurrentSystem.ThreadHashList[i], &Thread->Entry);
  431. *ResultThread = Thread;
  432. return TRUE;
  433. }
  434. BOOLEAN
  435. DeleteThread(
  436. PTHREAD_RECORD Thread
  437. )
  438. {
  439. PLIST_ENTRY pHead;
  440. PLIST_ENTRY pNext;
  441. PHPF_FILE_RECORD pHPFFileRecord;
  442. if (Thread == NULL) {
  443. return FALSE;
  444. }
  445. RemoveEntryList( &Thread->Entry );
  446. DeleteTransList( &Thread->TransListHead, 0 );
  447. pHead = & Thread->HPFReadListHead;
  448. pNext = pHead->Flink;
  449. while (pNext != pHead)
  450. {
  451. pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
  452. pNext = pNext->Flink;
  453. RemoveEntryList(& pHPFFileRecord->Entry);
  454. free(pHPFFileRecord);
  455. }
  456. pHead = & Thread->HPFWriteListHead;
  457. pNext = pHead->Flink;
  458. while (pNext != pHead)
  459. {
  460. pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
  461. pNext = pNext->Flink;
  462. RemoveEntryList(& pHPFFileRecord->Entry);
  463. free(pHPFFileRecord);
  464. }
  465. free( Thread );
  466. return TRUE;
  467. }
  468. PTRANS_RECORD
  469. FindTransByList(
  470. PLIST_ENTRY Head,
  471. LPGUID pGuid,
  472. ULONG level
  473. )
  474. {
  475. PLIST_ENTRY Next;
  476. PTRANS_RECORD pTrans = NULL;
  477. // Recursively look for the list that does
  478. // not contain a running guid
  479. //
  480. if (level <= MAX_TRANS_LEVEL && Head != NULL)
  481. {
  482. Next = Head->Flink;
  483. while (Next != Head)
  484. {
  485. pTrans = CONTAINING_RECORD(Next, TRANS_RECORD, Entry);
  486. if (pTrans->bStarted)
  487. {
  488. if ( (level == 0 || level == 1)
  489. && IsEqualGUID(pTrans->pGuid, pGuid))
  490. {
  491. return pTrans;
  492. }
  493. else if (level > 0)
  494. {
  495. return FindTransByList(& pTrans->SubTransListHead,
  496. pGuid,
  497. level - 1);
  498. }
  499. }
  500. Next = Next->Flink;
  501. }
  502. }
  503. // Found the correct list; now find
  504. // the matching transaction
  505. //
  506. if (level == 0 && Head != NULL)
  507. {
  508. Next = Head->Flink;
  509. while (Next != Head)
  510. {
  511. pTrans = CONTAINING_RECORD(Next, TRANS_RECORD, Entry);
  512. if (IsEqualGUID( pTrans->pGuid, pGuid))
  513. {
  514. return pTrans;
  515. }
  516. Next = Next->Flink;
  517. }
  518. //
  519. // If not Found, go ahead and add it.
  520. //
  521. pTrans = CreateTransRecord();
  522. if (pTrans != NULL) {
  523. pTrans->pGuid = pGuid;
  524. InsertHeadList( Head, &pTrans->Entry );
  525. }
  526. }
  527. return pTrans;
  528. }
  529. PMOF_DATA
  530. FindMofData(
  531. PMOF_INFO pMofInfo,
  532. PWCHAR strSortKey
  533. )
  534. {
  535. PLIST_ENTRY Next;
  536. PLIST_ENTRY Head;
  537. PMOF_DATA pMofData = NULL;
  538. if (pMofInfo == NULL) {
  539. return NULL;
  540. }
  541. Head = &pMofInfo->DataListHead;
  542. if (Head != NULL)
  543. {
  544. Next = Head->Flink;
  545. while (Next != Head)
  546. {
  547. pMofData = CONTAINING_RECORD(Next, MOF_DATA, Entry);
  548. if (strSortKey == NULL && pMofData->strSortKey == NULL)
  549. {
  550. return pMofData;
  551. }
  552. else if ( strSortKey != NULL
  553. && pMofData->strSortKey != NULL
  554. && !wcscmp(pMofData->strSortKey, strSortKey))
  555. {
  556. return pMofData;
  557. }
  558. Next = Next->Flink;
  559. }
  560. // If not Found, go ahead and add it.
  561. //
  562. pMofData = (PMOF_DATA)malloc(sizeof(MOF_DATA));
  563. if (pMofData == NULL)
  564. {
  565. return NULL;
  566. }
  567. InitMofData(pMofData);
  568. if (strSortKey != NULL)
  569. {
  570. pMofData->strSortKey =
  571. (PWCHAR) malloc((lstrlenW(strSortKey) + 1) * sizeof(WCHAR));
  572. if (pMofData->strSortKey != NULL) {
  573. StringCchCopyW(pMofData->strSortKey, (lstrlenW(strSortKey) + 1), strSortKey);
  574. }
  575. }
  576. InsertHeadList(Head, &pMofData->Entry);
  577. }
  578. return pMofData;
  579. }
  580. BOOLEAN
  581. DeleteTrans(
  582. PTRANS_RECORD Trans
  583. )
  584. {
  585. if (Trans == NULL)
  586. return FALSE;
  587. EnterTracelibCritSection();
  588. RemoveEntryList( &Trans->Entry );
  589. InsertHeadList( &CurrentSystem.FreeTransListHead, &Trans->Entry );
  590. LeaveTracelibCritSection();
  591. return TRUE;
  592. }
  593. BOOLEAN
  594. DeleteTransList(
  595. PLIST_ENTRY Head,
  596. ULONG level
  597. )
  598. {
  599. PLIST_ENTRY Next;
  600. PTRANS_RECORD pTrans;
  601. if( Head == NULL || level > MAX_TRANS_LEVEL )
  602. return FALSE;
  603. Next = Head->Flink;
  604. while(Next != Head){
  605. pTrans = CONTAINING_RECORD( Next, TRANS_RECORD, Entry );
  606. Next = Next->Flink;
  607. DeleteTransList( &pTrans->SubTransListHead, level+1);
  608. DeleteTrans( pTrans );
  609. }
  610. return TRUE;
  611. }
  612. PPROCESS_RECORD
  613. FindProcessById(
  614. ULONG Id,
  615. BOOLEAN CheckAlive
  616. )
  617. {
  618. PLIST_ENTRY Next, Head;
  619. PPROCESS_RECORD Process=NULL;
  620. EnterTracelibCritSection();
  621. Head = &CurrentSystem.ProcessListHead;
  622. Next = Head->Flink;
  623. while (Next != Head) {
  624. Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  625. if (Process->PID == Id) {
  626. LeaveTracelibCritSection();
  627. if ((Process->DeadFlag) && (CheckAlive))
  628. return NULL;
  629. else
  630. return Process;
  631. }
  632. Next = Next->Flink;
  633. }
  634. LeaveTracelibCritSection();
  635. return NULL;
  636. }
  637. PTHREAD_RECORD
  638. FindGlobalThreadById(
  639. ULONG ThreadId,
  640. PEVENT_TRACE pEvent
  641. )
  642. {
  643. PLIST_ENTRY Next,
  644. Head;
  645. PTHREAD_RECORD Thread;
  646. PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER) & pEvent->Header;
  647. ULONG i = ThreadId;
  648. ULONG Depth = 0;
  649. i = i % THREAD_HASH_TABLESIZE;
  650. Head = &CurrentSystem.ThreadHashList[i];
  651. Next = Head->Flink;
  652. while (Next != Head)
  653. {
  654. Thread = CONTAINING_RECORD(Next, THREAD_RECORD, Entry);
  655. Next = Next->Flink;
  656. Depth++;
  657. if (Thread->TID == ThreadId)
  658. {
  659. if (ThreadId == 0)
  660. {
  661. ULONG ProcessorId = pEvent->ClientContext & 0x000000FF;
  662. if (ProcessorId != Thread->ProcessorID)
  663. {
  664. continue;
  665. }
  666. }
  667. if (!Thread->DeadFlag)
  668. {
  669. if (Depth > 40) {
  670. RemoveEntryList( &Thread->Entry );
  671. InsertHeadList( Head, &Thread->Entry );
  672. }
  673. return Thread;
  674. }
  675. else if ( Thread->TimeEnd
  676. == (ULONGLONG) pHeader->TimeStamp.QuadPart)
  677. {
  678. if (Depth > 40) {
  679. RemoveEntryList( &Thread->Entry );
  680. InsertHeadList( Head, &Thread->Entry );
  681. }
  682. return Thread;
  683. }
  684. else
  685. {
  686. // The alive thead must be at the head of the list
  687. // otherwise bail
  688. //
  689. return NULL;
  690. }
  691. }
  692. }
  693. return NULL;
  694. }
  695. PWORKLOAD_RECORD
  696. FindWorkloadById(
  697. ULONG Id
  698. )
  699. {
  700. PLIST_ENTRY Next, Head;
  701. PWORKLOAD_RECORD Workload = NULL;
  702. Head = &CurrentSystem.WorkloadListHead;
  703. Next = Head->Flink;
  704. while (Next != Head) {
  705. Workload = CONTAINING_RECORD( Next, WORKLOAD_RECORD, Entry );
  706. if (Workload->ClassNumber == Id) {
  707. return Workload;
  708. }
  709. Next = Next->Flink;
  710. }
  711. return NULL;
  712. }
  713. BOOLEAN
  714. AddDisk(
  715. ULONG DiskNumber,
  716. PTDISK_RECORD *ReturnedDisk
  717. )
  718. {
  719. PTDISK_RECORD Disk;
  720. Disk = malloc(sizeof(TDISK_RECORD));
  721. if (Disk == NULL) {
  722. return FALSE;
  723. }
  724. InitDiskRecord(Disk, DiskNumber);
  725. Disk->DiskNumber = DiskNumber;
  726. InsertHeadList( &CurrentSystem.GlobalDiskListHead, &Disk->Entry );
  727. *ReturnedDisk = Disk;
  728. return TRUE;
  729. }
  730. BOOLEAN
  731. DeleteDisk(
  732. PTDISK_RECORD Disk
  733. )
  734. {
  735. PLIST_ENTRY Head, Next;
  736. PPROCESS_RECORD Process;
  737. PFILE_RECORD File;
  738. if (Disk == NULL)
  739. return FALSE;
  740. RemoveEntryList( &Disk->Entry );
  741. if (Disk->DiskName != NULL)
  742. free(Disk->DiskName);
  743. Head = &Disk->ProcessListHead;
  744. Next = Head->Flink;
  745. while (Next != Head) {
  746. Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  747. Next = Next->Flink;
  748. DeleteProcess( Process );
  749. }
  750. Head = &Disk->FileListHead;
  751. Next = Head->Flink;
  752. while (Next != Head) {
  753. File = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
  754. Next = Next->Flink;
  755. DeleteFileRecord( File );
  756. }
  757. free( Disk );
  758. return TRUE;
  759. }
  760. PTDISK_RECORD
  761. FindLocalDiskById(
  762. PLIST_ENTRY Head,
  763. ULONG Id
  764. )
  765. {
  766. PLIST_ENTRY Next;
  767. PTDISK_RECORD Disk = NULL;
  768. if (Head == NULL)
  769. return NULL;
  770. Next = Head->Flink;
  771. while (Next != Head) {
  772. Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
  773. if (Disk->DiskNumber == Id) {
  774. return Disk;
  775. }
  776. Next = Next->Flink;
  777. }
  778. // If not Found, go ahead and add it.
  779. //
  780. Disk = malloc(sizeof(TDISK_RECORD));
  781. if (Disk == NULL) {
  782. return FALSE;
  783. }
  784. InitDiskRecord(Disk, Id);
  785. Disk->DiskNumber = Id;
  786. InsertHeadList( Head, &Disk->Entry );
  787. return Disk;
  788. }
  789. PTDISK_RECORD
  790. FindProcessDiskById(
  791. PPROCESS_RECORD pProcess,
  792. ULONG Id
  793. )
  794. {
  795. PLIST_ENTRY Next, Head;
  796. PTDISK_RECORD Disk = NULL;
  797. if (pProcess == NULL)
  798. return NULL;
  799. Head = &pProcess->DiskListHead;
  800. Next = Head->Flink;
  801. while (Next != Head) {
  802. Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
  803. if (Disk->DiskNumber == Id) {
  804. return Disk;
  805. }
  806. Next = Next->Flink;
  807. }
  808. // If not Found, go ahead and add it.
  809. //
  810. Disk = malloc(sizeof(TDISK_RECORD));
  811. if (Disk == NULL) {
  812. return NULL;
  813. }
  814. InitDiskRecord(Disk, Id);
  815. Disk->DiskNumber = Id;
  816. InsertHeadList( &pProcess->DiskListHead, &Disk->Entry );
  817. return Disk;
  818. }
  819. PPROCESS_RECORD
  820. FindDiskProcessById(
  821. PTDISK_RECORD pDisk,
  822. ULONG Id
  823. )
  824. {
  825. PLIST_ENTRY Next, Head;
  826. PPROCESS_RECORD Process = NULL;
  827. PPROCESS_RECORD gProcess = NULL;
  828. if (pDisk == NULL)
  829. return NULL;
  830. Head = &pDisk->ProcessListHead;
  831. Next = Head->Flink;
  832. while (Next != Head) {
  833. Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  834. if (Process->PID == Id) {
  835. return Process;
  836. }
  837. Next = Next->Flink;
  838. }
  839. // If not Found, go ahead and add it.
  840. //
  841. Process = malloc(sizeof(PROCESS_RECORD));
  842. if (Process == NULL) {
  843. return FALSE;
  844. }
  845. InitProcessRecord(Process);
  846. Process->PID = Id;
  847. // Find the global Process Record and copy the UserName and Image.
  848. //
  849. gProcess = FindProcessById(Id, FALSE);
  850. if (gProcess != NULL) {
  851. if ( IsNotEmpty( gProcess->UserName ) ) {
  852. Process->UserName = (LPWSTR)malloc( (wcslen(gProcess->UserName) + 1) * sizeof(WCHAR) );
  853. if (NULL != Process->UserName) {
  854. StringCchCopyW(Process->UserName, (wcslen(gProcess->UserName) + 1), gProcess->UserName);
  855. }
  856. }
  857. if ( IsNotEmpty( gProcess->ImageName ) ) {
  858. Process->ImageName = (LPWSTR)malloc( (wcslen(gProcess->ImageName) + 1) * sizeof(WCHAR) );
  859. if (NULL != Process->ImageName) {
  860. StringCchCopyW(Process->ImageName, (wcslen(gProcess->ImageName) + 1), gProcess->ImageName);
  861. }
  862. }
  863. }
  864. InsertHeadList( &pDisk->ProcessListHead, &Process->Entry );
  865. return Process;
  866. }
  867. PTDISK_RECORD
  868. FindGlobalDiskById(
  869. ULONG Id
  870. )
  871. {
  872. PLIST_ENTRY Next, Head;
  873. PTDISK_RECORD Disk = NULL;
  874. Head = &CurrentSystem.GlobalDiskListHead;
  875. Next = Head->Flink;
  876. while (Next != Head) {
  877. Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
  878. if (Disk->DiskNumber == Id) {
  879. return Disk;
  880. }
  881. Next = Next->Flink;
  882. }
  883. return NULL;
  884. }
  885. VOID
  886. DeleteMofVersion(
  887. PMOF_VERSION pMofVersion,
  888. FILE* file
  889. )
  890. {
  891. PLIST_ENTRY Next, Head;
  892. PITEM_DESC pMofItem;
  893. //
  894. // Traverse through the MOF_VERSION list and
  895. // delete each one
  896. //
  897. if (pMofVersion == NULL)
  898. return;
  899. if( NULL != file ){
  900. fwprintf( file, L" %s (Type:%d Level:%d Version:%d)\n",
  901. pMofVersion->strType ? pMofVersion->strType : L"Default",
  902. pMofVersion->TypeIndex,
  903. pMofVersion->Level,
  904. pMofVersion->Version
  905. );
  906. }
  907. Head = &pMofVersion->ItemHeader;
  908. Next = Head->Flink;
  909. while (Head != Next) {
  910. pMofItem = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
  911. Next = Next->Flink;
  912. RemoveEntryList( &pMofItem->Entry );
  913. if (pMofItem->strDescription != NULL){
  914. if( NULL != file ){
  915. fwprintf( file, L" %s\n",
  916. pMofItem->strDescription
  917. );
  918. }
  919. free (pMofItem->strDescription);
  920. }
  921. free (pMofItem);
  922. }
  923. }
  924. VOID
  925. DeleteMofInfo(
  926. PMOF_INFO pMofInfo,
  927. FILE* f
  928. )
  929. {
  930. PLIST_ENTRY Next, Head;
  931. PMOF_VERSION pMofVersion;
  932. //
  933. // Traverse through the MOF_VERSION list and
  934. // delete each one
  935. //
  936. if (pMofInfo == NULL){
  937. return;
  938. }
  939. if( NULL != f ){
  940. WCHAR buffer[MAXSTR];
  941. fwprintf( f, L"%s\n",
  942. pMofInfo->strDescription ? pMofInfo->strDescription : CpdiGuidToString( buffer, MAXSTR, &pMofInfo->Guid ) );
  943. }
  944. Head = &pMofInfo->VersionHeader;
  945. Next = Head->Flink;
  946. while (Head != Next) {
  947. pMofVersion = CONTAINING_RECORD(Next, MOF_VERSION, Entry);
  948. Next = Next->Flink;
  949. RemoveEntryList( &pMofVersion->Entry );
  950. DeleteMofVersion( pMofVersion, f );
  951. }
  952. //
  953. // Delete any strings allocated for this structure
  954. //
  955. if (pMofInfo->strDescription){
  956. free(pMofInfo->strDescription);
  957. }
  958. //
  959. // Finally delete the object
  960. //
  961. free(pMofInfo);
  962. }
  963. VOID
  964. Cleanup()
  965. {
  966. PTDISK_RECORD Disk;
  967. PTHREAD_RECORD Thread;
  968. PPROCESS_RECORD Process;
  969. PFILE_RECORD FileRec;
  970. PWORKLOAD_RECORD pWorkload;
  971. PMODULE_RECORD pModule;
  972. PTRANS_RECORD pTrans;
  973. PMOF_INFO pMofInfo;
  974. PPRINT_JOB_RECORD pJob;
  975. PHTTP_REQUEST_RECORD pReq;
  976. PURL_RECORD pUrl;
  977. PCLIENT_RECORD pClient;
  978. PSITE_RECORD pSite;
  979. PLOGICAL_DRIVE_RECORD pLogDrive;
  980. PVALUEMAP pValueMap;
  981. PLIST_ENTRY Next, Head;
  982. PLIST_ENTRY EventListHead;
  983. FILE* f = NULL;
  984. ULONG i;
  985. // Clean up the Global Disk List for now.
  986. //
  987. EventListHead = &CurrentSystem.EventListHead;
  988. Head = EventListHead;
  989. Next = Head->Flink;
  990. if( (TraceContext->Flags & TRACE_INTERPRET) && NULL != TraceContext->CompFileName ){
  991. f = _wfopen( TraceContext->CompFileName, L"w" );
  992. }
  993. while (Head != Next) {
  994. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  995. Next = Next->Flink;
  996. RemoveEntryList( &pMofInfo->Entry );
  997. DeleteMofInfo(pMofInfo, f);
  998. }
  999. if( NULL != f ){
  1000. fclose( f );
  1001. f = NULL;
  1002. }
  1003. Head = &CurrentSystem.GlobalDiskListHead;
  1004. Next = Head->Flink;
  1005. while (Next != Head) {
  1006. Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
  1007. Next = Next->Flink;
  1008. DeleteDisk( Disk );
  1009. }
  1010. // Clean up the Global Thread List for now.
  1011. //
  1012. Head = &CurrentSystem.GlobalThreadListHead;
  1013. Next = Head->Flink;
  1014. while (Next != Head) {
  1015. Thread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
  1016. Next = Next->Flink;
  1017. DeleteThread( Thread );
  1018. }
  1019. Head = &CurrentSystem.ProcessListHead;
  1020. Next = Head->Flink;
  1021. while (Next != Head) {
  1022. Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
  1023. Next = Next->Flink;
  1024. DeleteProcess( Process );
  1025. }
  1026. Head = &CurrentSystem.GlobalModuleListHead;
  1027. Next = Head->Flink;
  1028. while (Next != Head)
  1029. {
  1030. pModule = CONTAINING_RECORD(Next, MODULE_RECORD, Entry);
  1031. Next = Next->Flink;
  1032. RemoveEntryList(& pModule->Entry);
  1033. if(pModule->strModuleName)
  1034. {
  1035. free(pModule->strModuleName);
  1036. }
  1037. free(pModule);
  1038. }
  1039. Head = &CurrentSystem.HotFileListHead;
  1040. Next = Head->Flink;
  1041. while (Next != Head) {
  1042. FileRec = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
  1043. Next = Next->Flink;
  1044. DeleteFileRecord( FileRec );
  1045. }
  1046. // Cleanup workload structures
  1047. //
  1048. Head = &CurrentSystem.WorkloadListHead;
  1049. Next = Head->Flink;
  1050. while (Next != Head) {
  1051. pWorkload = CONTAINING_RECORD( Next, WORKLOAD_RECORD, Entry );
  1052. Next = Next->Flink;
  1053. DeleteWorkloadRecord( pWorkload );
  1054. }
  1055. //
  1056. // Cleanup the Print Job List structures
  1057. //
  1058. Head = &CurrentSystem.PrintJobListHead;
  1059. Next = Head->Flink;
  1060. while (Next != Head) {
  1061. pJob = CONTAINING_RECORD( Next, PRINT_JOB_RECORD, Entry );
  1062. Next = Next->Flink;
  1063. RemoveEntryList(&pJob->Entry);
  1064. free(pJob);
  1065. }
  1066. //
  1067. // Cleanup the Http Request List structures
  1068. //
  1069. Head = &CurrentSystem.HttpReqListHead;
  1070. Next = Head->Flink;
  1071. while (Next != Head) {
  1072. pReq = CONTAINING_RECORD( Next, HTTP_REQUEST_RECORD, Entry );
  1073. Next = Next->Flink;
  1074. RemoveEntryList(&pReq->Entry);
  1075. if (pReq->URL != NULL) {
  1076. free(pReq->URL);
  1077. }
  1078. free(pReq);
  1079. }
  1080. //
  1081. // Cleanup the Pending Http Request List structures
  1082. //
  1083. Head = &CurrentSystem.PendingHttpReqListHead;
  1084. Next = Head->Flink;
  1085. while (Next != Head) {
  1086. pReq = CONTAINING_RECORD( Next, HTTP_REQUEST_RECORD, Entry );
  1087. Next = Next->Flink;
  1088. RemoveEntryList(&pReq->Entry);
  1089. if (pReq->URL != NULL) {
  1090. free(pReq->URL);
  1091. }
  1092. free(pReq);
  1093. }
  1094. //
  1095. // Cleanup the URL List structures
  1096. //
  1097. for (i = 0; i < URL_HASH_TABLESIZE; i++) {
  1098. Head = &CurrentSystem.URLHashList[i];
  1099. Next = Head->Flink;
  1100. while (Next != Head) {
  1101. pUrl = CONTAINING_RECORD( Next, URL_RECORD, Entry );
  1102. Next = Next->Flink;
  1103. RemoveEntryList(&pUrl->Entry);
  1104. free(pUrl);
  1105. }
  1106. }
  1107. //
  1108. // Cleanup the Client List structures
  1109. //
  1110. Head = &CurrentSystem.ClientListHead;
  1111. Next = Head->Flink;
  1112. while (Next != Head) {
  1113. pClient = CONTAINING_RECORD( Next, CLIENT_RECORD, Entry );
  1114. Next = Next->Flink;
  1115. RemoveEntryList(&pClient->Entry);
  1116. free(pClient);
  1117. }
  1118. //
  1119. // Cleanup the Site List structures
  1120. //
  1121. Head = &CurrentSystem.SiteListHead;
  1122. Next = Head->Flink;
  1123. while (Next != Head) {
  1124. pSite = CONTAINING_RECORD( Next, SITE_RECORD, Entry );
  1125. Next = Next->Flink;
  1126. RemoveEntryList(&pSite->Entry);
  1127. free(pSite);
  1128. }
  1129. //
  1130. // Cleanup the Logical Drive structures
  1131. //
  1132. Head = &CurrentSystem.LogicalDriveHead;
  1133. Next = Head->Flink;
  1134. while (Next != Head) {
  1135. pLogDrive = CONTAINING_RECORD( Next, LOGICAL_DRIVE_RECORD, Entry );
  1136. Next = Next->Flink;
  1137. RemoveEntryList(&pLogDrive->Entry);
  1138. if (NULL != pLogDrive->DriveLetterString) {
  1139. free(pLogDrive->DriveLetterString);
  1140. }
  1141. free(pLogDrive);
  1142. }
  1143. //
  1144. // Clean up recyled memory structures
  1145. //
  1146. Head = &CurrentSystem.FreePrintJobListHead;
  1147. Next = Head->Flink;
  1148. while (Next != Head) {
  1149. pJob = CONTAINING_RECORD( Next, PRINT_JOB_RECORD, Entry );
  1150. Next = Next->Flink;
  1151. RemoveEntryList(&pJob->Entry);
  1152. free(pJob);
  1153. }
  1154. Head = &CurrentSystem.FreeTransListHead;
  1155. Next = Head->Flink;
  1156. while (Next != Head) {
  1157. pTrans = CONTAINING_RECORD( Next, TRANS_RECORD, Entry );
  1158. Next = Next->Flink;
  1159. RemoveEntryList(&pTrans->Entry);
  1160. free(pTrans);
  1161. }
  1162. Head = &CurrentSystem.FreeHttpReqListHead;
  1163. Next = Head->Flink;
  1164. while (Next != Head) {
  1165. pReq = CONTAINING_RECORD( Next, HTTP_REQUEST_RECORD, Entry );
  1166. Next = Next->Flink;
  1167. RemoveEntryList(&pReq->Entry);
  1168. free(pReq);
  1169. }
  1170. Head = &CurrentSystem.FreeURLListHead;
  1171. Next = Head->Flink;
  1172. while (Next != Head) {
  1173. pUrl = CONTAINING_RECORD( Next, URL_RECORD, Entry );
  1174. Next = Next->Flink;
  1175. RemoveEntryList(&pUrl->Entry);
  1176. free(pUrl);
  1177. }
  1178. Head = &g_ValueMapTable;
  1179. Next = Head->Flink;
  1180. while (Next != Head) {
  1181. pValueMap = CONTAINING_RECORD( Next, VALUEMAP, Entry );
  1182. Next = Next->Flink;
  1183. RemoveEntryList(&pValueMap->Entry);
  1184. if( NULL != pValueMap->saValueMap ){
  1185. SafeArrayDestroy( pValueMap->saValueMap );
  1186. }
  1187. if( NULL != pValueMap->saValues ){
  1188. SafeArrayDestroy( pValueMap->saValues );
  1189. }
  1190. free( pValueMap );
  1191. }
  1192. }
  1193. PLOGICAL_DRIVE_RECORD
  1194. FindLogicalDrive(
  1195. ULONGLONG AccessedOffset,
  1196. ULONG DiskNumber
  1197. )
  1198. {
  1199. PLOGICAL_DRIVE_RECORD pLogDrive = NULL;
  1200. PLIST_ENTRY Next, Head;
  1201. EnterTracelibCritSection();
  1202. // Find drive letter when logical drive info is available.
  1203. Head = &CurrentSystem.LogicalDriveHead;
  1204. Next = Head->Flink;
  1205. if (Next != Head) {
  1206. while (Next != Head) {
  1207. pLogDrive = CONTAINING_RECORD( Next, LOGICAL_DRIVE_RECORD, Entry );
  1208. if (DiskNumber == pLogDrive->DiskNumber &&
  1209. AccessedOffset < pLogDrive->StartOffset &&
  1210. Next->Blink != Head) {
  1211. pLogDrive = CONTAINING_RECORD( Next->Blink, LOGICAL_DRIVE_RECORD, Entry );
  1212. break;
  1213. }
  1214. Next = Next->Flink;
  1215. }
  1216. }
  1217. LeaveTracelibCritSection();
  1218. if (NULL != pLogDrive && DiskNumber == pLogDrive->DiskNumber) {
  1219. return pLogDrive;
  1220. }
  1221. else {
  1222. return NULL;
  1223. }
  1224. }
  1225. BOOLEAN
  1226. AddFile(
  1227. WCHAR* fileName,
  1228. PFILE_RECORD *ReturnedFile,
  1229. PLOGICAL_DRIVE_RECORD pLogDrive
  1230. )
  1231. {
  1232. PFILE_RECORD fileRec;
  1233. PLIST_ENTRY Next, Head;
  1234. if (fileName == NULL)
  1235. return FALSE;
  1236. fileRec = malloc(sizeof(FILE_RECORD));
  1237. if (fileRec == NULL) {
  1238. return FALSE;
  1239. }
  1240. InitFileRecord( fileRec );
  1241. fileRec->FileName = malloc( (lstrlenW(fileName)+ 1) * sizeof(WCHAR));
  1242. if (fileRec->FileName != NULL) {
  1243. StringCchCopyW(fileRec->FileName, (lstrlenW(fileName)+ 1), fileName);
  1244. }
  1245. if (NULL != pLogDrive) {
  1246. fileRec->DiskNumber = pLogDrive->DiskNumber;
  1247. if (NULL != pLogDrive->DriveLetterString) {
  1248. fileRec->Drive = malloc( (lstrlenW(pLogDrive->DriveLetterString)+ 1) * sizeof(WCHAR));
  1249. if (fileRec->Drive != NULL) {
  1250. StringCchCopyW(fileRec->Drive, lstrlenW(pLogDrive->DriveLetterString)+ 1, pLogDrive->DriveLetterString);
  1251. }
  1252. }
  1253. }
  1254. EnterTracelibCritSection();
  1255. InsertHeadList( &CurrentSystem.HotFileListHead, &fileRec->Entry );
  1256. LeaveTracelibCritSection();
  1257. *ReturnedFile = fileRec;
  1258. return TRUE;
  1259. }
  1260. BOOLEAN
  1261. DeleteFileRecord(
  1262. PFILE_RECORD fileRec
  1263. )
  1264. {
  1265. PLIST_ENTRY Next, Head;
  1266. PPROTO_PROCESS_RECORD pProto;
  1267. if (fileRec == NULL)
  1268. return FALSE;
  1269. EnterTracelibCritSection();
  1270. RemoveEntryList( &fileRec->Entry );
  1271. LeaveTracelibCritSection();
  1272. if (fileRec->FileName != NULL)
  1273. free(fileRec->FileName);
  1274. if (fileRec->Drive != NULL)
  1275. free(fileRec->Drive);
  1276. Head = &fileRec->ProtoProcessListHead;
  1277. Next = Head->Flink;
  1278. while (Head != Next) {
  1279. pProto = CONTAINING_RECORD( Next, PROTO_PROCESS_RECORD, Entry);
  1280. Next = Next->Flink;
  1281. RemoveEntryList( &pProto->Entry );
  1282. free(pProto);
  1283. }
  1284. free( fileRec );
  1285. return TRUE;
  1286. }
  1287. PFILE_RECORD
  1288. FindFileRecordByName(
  1289. WCHAR* fileName,
  1290. PLOGICAL_DRIVE_RECORD pLogDrive
  1291. )
  1292. {
  1293. PLIST_ENTRY Next, Head;
  1294. PFILE_RECORD fileRec = NULL;
  1295. if (fileName == NULL)
  1296. return NULL;
  1297. EnterTracelibCritSection();
  1298. Head = &CurrentSystem.HotFileListHead;
  1299. Next = Head->Flink;
  1300. while (Next != Head) {
  1301. fileRec = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
  1302. if (!wcscmp(fileName, fileRec->FileName)) {
  1303. if (NULL != pLogDrive && pLogDrive->DiskNumber == fileRec->DiskNumber) {
  1304. if (NULL != pLogDrive->DriveLetterString &&
  1305. NULL != fileRec->Drive &&
  1306. !wcscmp(pLogDrive->DriveLetterString, fileRec->Drive)) {
  1307. LeaveTracelibCritSection();
  1308. return fileRec;
  1309. }
  1310. else if (NULL == pLogDrive->DriveLetterString &&
  1311. NULL == fileRec->Drive) {
  1312. LeaveTracelibCritSection();
  1313. return fileRec;
  1314. }
  1315. }
  1316. else if (NULL == pLogDrive) {
  1317. LeaveTracelibCritSection();
  1318. return fileRec;
  1319. }
  1320. }
  1321. Next = Next->Flink;
  1322. }
  1323. LeaveTracelibCritSection();
  1324. return NULL;
  1325. }
  1326. PFILE_RECORD
  1327. FindFileInProcess(
  1328. PPROCESS_RECORD pProcess,
  1329. WCHAR* fileName
  1330. )
  1331. {
  1332. PLIST_ENTRY Next, Head;
  1333. PFILE_RECORD fileRec = NULL;
  1334. if (pProcess == NULL || fileName == NULL)
  1335. return NULL;
  1336. EnterTracelibCritSection();
  1337. Head = &pProcess->FileListHead;
  1338. Next = Head->Flink;
  1339. while (Next != Head) {
  1340. fileRec = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
  1341. if (!wcscmp(fileName, fileRec->FileName)) {
  1342. //ReleaseMutex(CurrentSystem.HotFileListMutex);
  1343. LeaveTracelibCritSection();
  1344. return fileRec;
  1345. }
  1346. Next = Next->Flink;
  1347. }
  1348. LeaveTracelibCritSection();
  1349. return NULL;
  1350. }
  1351. VOID
  1352. AddLogicalDrive(
  1353. ULONGLONG StartOffset,
  1354. ULONGLONG PartitionSize,
  1355. ULONG DiskNumber,
  1356. ULONG Size,
  1357. ULONG DriveType,
  1358. PWCHAR DriveLetterString
  1359. )
  1360. {
  1361. PLOGICAL_DRIVE_RECORD pLogDrive = NULL, pTempLogDrive = NULL;
  1362. PLIST_ENTRY Next, Head;
  1363. pLogDrive = malloc(sizeof(LOGICAL_DRIVE_RECORD));
  1364. if (pLogDrive == NULL) {
  1365. SetLastError(ERROR_OUTOFMEMORY);
  1366. return;
  1367. }
  1368. RtlZeroMemory(pLogDrive, sizeof(LOGICAL_DRIVE_RECORD));
  1369. pLogDrive->StartOffset = StartOffset;
  1370. pLogDrive->PartitionSize = PartitionSize;
  1371. pLogDrive->DiskNumber = DiskNumber;
  1372. pLogDrive->Size = Size;
  1373. pLogDrive->DriveType = DriveType;
  1374. if (DriveLetterString != NULL) {
  1375. pLogDrive->DriveLetterString = malloc( (lstrlenW(DriveLetterString)+ 1) * sizeof(WCHAR));
  1376. if (pLogDrive->DriveLetterString != NULL) {
  1377. StringCchCopyW(pLogDrive->DriveLetterString, lstrlenW(DriveLetterString)+ 1, DriveLetterString);
  1378. }
  1379. }
  1380. EnterTracelibCritSection();
  1381. // When inserting logical drives, do it in StartOffset order.
  1382. Head = &CurrentSystem.LogicalDriveHead;
  1383. Next = Head->Flink;
  1384. while (Next != Head) {
  1385. pTempLogDrive = CONTAINING_RECORD( Next, LOGICAL_DRIVE_RECORD, Entry );
  1386. if (pLogDrive->StartOffset < pTempLogDrive->StartOffset) {
  1387. break;
  1388. }
  1389. Next = Next->Flink;
  1390. }
  1391. InsertTailList( Next, &pLogDrive->Entry );
  1392. LeaveTracelibCritSection();
  1393. }
  1394. VOID
  1395. AssignClass(
  1396. PPROCESS_RECORD pProcess,
  1397. PTHREAD_RECORD pThread
  1398. )
  1399. {
  1400. UNREFERENCED_PARAMETER(pProcess);
  1401. pThread->ClassNumber = 1; // For the Time being make it single class.
  1402. }
  1403. VOID
  1404. Classify()
  1405. {
  1406. // Assign Class to each Thread or Process.
  1407. //
  1408. PLIST_ENTRY Head, Next;
  1409. PTHREAD_RECORD pThread;
  1410. Head = &CurrentSystem.GlobalThreadListHead;
  1411. Next = Head->Flink;
  1412. while (Next != Head) {
  1413. pThread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
  1414. AssignClass(NULL, pThread);
  1415. Aggregate(pThread);
  1416. Next = Next->Flink;
  1417. }
  1418. }
  1419. // Given the number of classes this routine
  1420. // creates and initializes the workload object
  1421. //
  1422. VOID
  1423. InitClass()
  1424. {
  1425. PWORKLOAD_RECORD pWorkload;
  1426. ULONG nclass;
  1427. ULONG i;
  1428. // Create the Class records here.
  1429. //
  1430. nclass = 1;
  1431. CurrentSystem.NumberOfWorkloads = 1;
  1432. for (i = 1; i <= nclass; i++) {
  1433. pWorkload = malloc(sizeof(WORKLOAD_RECORD));
  1434. if (pWorkload == NULL) {
  1435. return;
  1436. }
  1437. InitWorkloadRecord( pWorkload );
  1438. pWorkload->ClassNumber = i;
  1439. InsertHeadList( &CurrentSystem.WorkloadListHead, &pWorkload->Entry );
  1440. }
  1441. }
  1442. PTDISK_RECORD
  1443. FindDiskInList(
  1444. IN PLIST_ENTRY Head,
  1445. IN ULONG Id
  1446. )
  1447. {
  1448. PLIST_ENTRY Next;
  1449. PTDISK_RECORD pDisk = NULL;
  1450. if (Head != NULL) {
  1451. Next = Head->Flink;
  1452. while (Next != Head) {
  1453. pDisk = CONTAINING_RECORD ( Next, TDISK_RECORD, Entry );
  1454. if (pDisk->DiskNumber == Id) {
  1455. return pDisk;
  1456. }
  1457. Next = Next->Flink;
  1458. }
  1459. pDisk = malloc(sizeof(TDISK_RECORD));
  1460. if (pDisk == NULL) {
  1461. return NULL;
  1462. }
  1463. InitDiskRecord( pDisk, Id );
  1464. InsertHeadList( Head, &pDisk->Entry );
  1465. }
  1466. return pDisk;
  1467. }
  1468. VOID
  1469. Aggregate(
  1470. IN PTHREAD_RECORD pThread
  1471. )
  1472. {
  1473. PWORKLOAD_RECORD pWorkload;
  1474. PTDISK_RECORD pDisk, pClassDisk;
  1475. PLIST_ENTRY Next, Head;
  1476. // Aggregate the metrics over each class.
  1477. //
  1478. if ((pWorkload = FindWorkloadById(pThread->ClassNumber)) != NULL) {
  1479. pWorkload->UserCPU += (pThread->UCPUEnd - pThread->UCPUStart)
  1480. * CurrentSystem.TimerResolution;
  1481. pWorkload->KernelCPU += (pThread->KCPUEnd - pThread->KCPUStart)
  1482. * CurrentSystem.TimerResolution;
  1483. //
  1484. // Walk through the Thread Disk records and aggregate them
  1485. // to the class
  1486. Head = &pThread->DiskListHead;
  1487. Next = Head->Flink;
  1488. while (Next != Head) {
  1489. pDisk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
  1490. Next = Next->Flink;
  1491. pClassDisk = FindDiskInList(&pWorkload->DiskListHead,
  1492. pDisk->DiskNumber) ;
  1493. if (pClassDisk != NULL) {
  1494. pClassDisk->ReadCount += pDisk->ReadCount;
  1495. pClassDisk->WriteCount += pDisk->WriteCount;
  1496. pClassDisk->ReadSize += (pDisk->ReadCount * pDisk->ReadSize);
  1497. pClassDisk->WriteSize += (pDisk->WriteCount * pDisk->WriteSize);
  1498. pWorkload->ReadCount += pDisk->ReadCount;
  1499. }
  1500. }
  1501. }
  1502. }
  1503. ULONGLONG
  1504. CalculateProcessLifeTime(
  1505. PPROCESS_RECORD pProcess
  1506. )
  1507. {
  1508. BOOLEAN fFirst = TRUE;
  1509. ULONGLONG TimeStart = 0;
  1510. ULONGLONG TimeEnd = 0;
  1511. PLIST_ENTRY pHead = &pProcess->ThreadListHead;
  1512. PLIST_ENTRY pNext = pHead->Flink;
  1513. PTHREAD_RECORD pThread;
  1514. while (pNext != pHead)
  1515. {
  1516. pThread = CONTAINING_RECORD(pNext, THREAD_RECORD, Entry);
  1517. pNext = pNext->Flink;
  1518. if (fFirst)
  1519. {
  1520. TimeStart = pThread->TimeStart;
  1521. TimeEnd = pThread->TimeEnd;
  1522. fFirst = FALSE;
  1523. }
  1524. else if (pThread->TimeStart < TimeStart)
  1525. {
  1526. TimeStart = pThread->TimeStart;
  1527. }
  1528. else if (pThread->TimeEnd > TimeEnd)
  1529. {
  1530. TimeEnd = pThread->TimeEnd;
  1531. }
  1532. }
  1533. return (TimeEnd - TimeStart);
  1534. }
  1535. ULONG
  1536. CalculateProcessKCPU(
  1537. PPROCESS_RECORD pProcess
  1538. )
  1539. {
  1540. ULONG KCPUTotal = 0;
  1541. ULONG KCPUMissing = 0;
  1542. PLIST_ENTRY pHead = &pProcess->ThreadListHead;
  1543. PLIST_ENTRY pNext = pHead->Flink;
  1544. PTHREAD_RECORD pThread;
  1545. while (pNext != pHead)
  1546. {
  1547. pThread = CONTAINING_RECORD(pNext, THREAD_RECORD, Entry);
  1548. pNext = pNext->Flink;
  1549. if (pThread->KCPUEnd > pThread->KCPUStart)
  1550. {
  1551. if ((pProcess->PID != 0) ||
  1552. ((pProcess->PID == 0) && (pThread->TID == 0)) ){
  1553. KCPUTotal += pThread->KCPUEnd - pThread->KCPUStart;
  1554. }
  1555. else {
  1556. KCPUMissing += pThread->KCPUEnd - pThread->KCPUStart;
  1557. }
  1558. }
  1559. }
  1560. return (ULONG) (KCPUTotal * CurrentSystem.TimerResolution);
  1561. }
  1562. ULONG
  1563. CalculateProcessUCPU(
  1564. PPROCESS_RECORD pProcess
  1565. )
  1566. {
  1567. ULONG UCPUTotal = 0;
  1568. ULONG UCPUMissing = 0;
  1569. PLIST_ENTRY pHead = &pProcess->ThreadListHead;
  1570. PLIST_ENTRY pNext = pHead->Flink;
  1571. PTHREAD_RECORD pThread;
  1572. while (pNext != pHead)
  1573. {
  1574. pThread = CONTAINING_RECORD(pNext, THREAD_RECORD, Entry);
  1575. pNext = pNext->Flink;
  1576. if (pThread->UCPUEnd > pThread->UCPUStart)
  1577. {
  1578. if ((pProcess->PID != 0) ||
  1579. ((pProcess->PID == 0) && (pThread->TID == 0)) ) {
  1580. UCPUTotal += pThread->UCPUEnd - pThread->UCPUStart;
  1581. }
  1582. else {
  1583. UCPUMissing += pThread->UCPUEnd - pThread->UCPUStart;
  1584. }
  1585. }
  1586. }
  1587. return (ULONG) (UCPUTotal * CurrentSystem.TimerResolution);
  1588. }
  1589. PPRINT_JOB_RECORD
  1590. FindPrintJobRecord(
  1591. ULONG JobId
  1592. )
  1593. {
  1594. PLIST_ENTRY Head, Next;
  1595. PPRINT_JOB_RECORD pJob;
  1596. EnterTracelibCritSection();
  1597. Head = &CurrentSystem.PrintJobListHead;
  1598. Next = Head->Flink;
  1599. while (Next != Head) {
  1600. pJob = CONTAINING_RECORD ( Next, PRINT_JOB_RECORD, Entry );
  1601. if (pJob->JobId == JobId) {
  1602. LeaveTracelibCritSection();
  1603. return pJob;
  1604. }
  1605. Next = Next->Flink;
  1606. }
  1607. LeaveTracelibCritSection();
  1608. return NULL;
  1609. }
  1610. PHTTP_REQUEST_RECORD
  1611. FindHttpReqRecord(
  1612. ULONGLONG RequestId
  1613. )
  1614. {
  1615. PLIST_ENTRY Head, Next;
  1616. PHTTP_REQUEST_RECORD pReq;
  1617. ULONG Depth = 0;
  1618. EnterTracelibCritSection();
  1619. Head = &CurrentSystem.HttpReqListHead;
  1620. Next = Head->Flink;
  1621. while (Next != Head) {
  1622. pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
  1623. if (pReq->RequestId == RequestId) {
  1624. if (Depth > 40) {
  1625. RemoveEntryList( &pReq->Entry );
  1626. InsertHeadList( Head, &pReq->Entry );
  1627. }
  1628. LeaveTracelibCritSection();
  1629. return pReq;
  1630. }
  1631. Next = Next->Flink;
  1632. Depth++;
  1633. }
  1634. LeaveTracelibCritSection();
  1635. return NULL;
  1636. }
  1637. PHTTP_REQUEST_RECORD
  1638. FindHttpReqRecordByConId(
  1639. ULONGLONG ConId,
  1640. PHTTP_REQUEST_RECORD pPrevReq
  1641. )
  1642. {
  1643. PLIST_ENTRY Head, Next;
  1644. PHTTP_REQUEST_RECORD pReq;
  1645. ULONG Depth = 0;
  1646. EnterTracelibCritSection();
  1647. Head = &CurrentSystem.HttpReqListHead;
  1648. Next = Head->Flink;
  1649. while (Next != Head) {
  1650. pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
  1651. if (pReq->ConId == ConId) {
  1652. if (pPrevReq == NULL || pPrevReq != pReq) {
  1653. if (Depth > 40) {
  1654. RemoveEntryList( &pReq->Entry );
  1655. InsertHeadList( Head, &pReq->Entry );
  1656. }
  1657. LeaveTracelibCritSection();
  1658. return pReq;
  1659. }
  1660. }
  1661. Next = Next->Flink;
  1662. Depth++;
  1663. }
  1664. Depth = 0;
  1665. Head = &CurrentSystem.PendingHttpReqListHead;
  1666. Next = Head->Flink;
  1667. while (Next != Head) {
  1668. pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
  1669. if (pReq->ConId == ConId) {
  1670. if (pPrevReq == NULL || pPrevReq != pReq) {
  1671. if (Depth > 40) {
  1672. RemoveEntryList( &pReq->Entry );
  1673. InsertHeadList( Head, &pReq->Entry );
  1674. }
  1675. LeaveTracelibCritSection();
  1676. return pReq;
  1677. }
  1678. }
  1679. Next = Next->Flink;
  1680. Depth++;
  1681. }
  1682. LeaveTracelibCritSection();
  1683. return NULL;
  1684. }
  1685. PHTTP_REQUEST_RECORD
  1686. FindPendingHttpReqRecord(
  1687. ULONGLONG RequestId
  1688. )
  1689. {
  1690. PLIST_ENTRY Head, Next;
  1691. PHTTP_REQUEST_RECORD pReq;
  1692. ULONG Depth = 0;
  1693. EnterTracelibCritSection();
  1694. Head = &CurrentSystem.PendingHttpReqListHead;
  1695. Next = Head->Flink;
  1696. while (Next != Head) {
  1697. pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
  1698. if (pReq->RequestId == RequestId) {
  1699. if (Depth > 40) {
  1700. RemoveEntryList( &pReq->Entry );
  1701. InsertHeadList( Head, &pReq->Entry );
  1702. }
  1703. LeaveTracelibCritSection();
  1704. return pReq;
  1705. }
  1706. Next = Next->Flink;
  1707. Depth++;
  1708. }
  1709. LeaveTracelibCritSection();
  1710. return NULL;
  1711. }
  1712. PURL_RECORD
  1713. FindUrlRecord(
  1714. PUCHAR Url
  1715. )
  1716. {
  1717. PLIST_ENTRY Head, Next;
  1718. PURL_RECORD pUrl;
  1719. ULONG Depth = 0;
  1720. ULONG UrlStrSize;
  1721. PUCHAR UrlChar;
  1722. BOOL bMatch;
  1723. UCHAR TempEndChar;
  1724. USHORT HashKey;
  1725. if (Url == NULL) {
  1726. return NULL;
  1727. }
  1728. UrlStrSize = 0;
  1729. UrlChar = Url;
  1730. while (*UrlChar != '\0' && *UrlChar != '?') {
  1731. UrlStrSize++;
  1732. UrlChar++;
  1733. }
  1734. // No URL will end with '/'
  1735. if (*(UrlChar - 1) == '/') {
  1736. UrlStrSize--;
  1737. }
  1738. TempEndChar = *(Url + UrlStrSize);
  1739. *(Url + UrlStrSize) = '\0';
  1740. HashKey = UrlHashKey(Url, UrlStrSize);
  1741. EnterTracelibCritSection();
  1742. Head = &CurrentSystem.URLHashList[HashKey];
  1743. Next = Head->Flink;
  1744. while (Next != Head) {
  1745. pUrl = CONTAINING_RECORD ( Next, URL_RECORD, Entry );
  1746. // pUrl->URL cannot be NULL. If it is, it shouldn't even be created.
  1747. if ( _stricmp( Url, pUrl->URL ) == 0 ) {
  1748. if (Depth > 20) {
  1749. RemoveEntryList( &pUrl->Entry );
  1750. InsertHeadList( Head, &pUrl->Entry );
  1751. }
  1752. LeaveTracelibCritSection();
  1753. return pUrl;
  1754. }
  1755. Next = Next->Flink;
  1756. Depth++;
  1757. }
  1758. LeaveTracelibCritSection();
  1759. *(Url + UrlStrSize) = TempEndChar;
  1760. return NULL;
  1761. }
  1762. PCLIENT_RECORD
  1763. FindClientRecord(
  1764. USHORT IpAddrType,
  1765. ULONG IpAddrV4,
  1766. USHORT *IpAddrV6
  1767. )
  1768. {
  1769. PLIST_ENTRY Head, Next;
  1770. PCLIENT_RECORD pClient;
  1771. if (IpAddrV6 == NULL) {
  1772. return NULL;
  1773. }
  1774. EnterTracelibCritSection();
  1775. Head = &CurrentSystem.ClientListHead;
  1776. Next = Head->Flink;
  1777. while (Next != Head) {
  1778. pClient = CONTAINING_RECORD ( Next, CLIENT_RECORD, Entry );
  1779. if (pClient->IpAddrType == IpAddrType &&
  1780. pClient->IpAddrV4 == IpAddrV4 &&
  1781. RtlCompareMemory(IpAddrV6, pClient->IpAddrV6, sizeof(USHORT) * 8) == sizeof(USHORT) * 8) {
  1782. LeaveTracelibCritSection();
  1783. return pClient;
  1784. }
  1785. Next = Next->Flink;
  1786. }
  1787. LeaveTracelibCritSection();
  1788. return NULL;
  1789. }
  1790. PSITE_RECORD
  1791. FindSiteRecord(
  1792. ULONG SiteId
  1793. )
  1794. {
  1795. PLIST_ENTRY Head, Next;
  1796. PSITE_RECORD pSite;
  1797. EnterTracelibCritSection();
  1798. Head = &CurrentSystem.SiteListHead;
  1799. Next = Head->Flink;
  1800. while (Next != Head) {
  1801. pSite = CONTAINING_RECORD ( Next, SITE_RECORD, Entry );
  1802. if (pSite->SiteId == SiteId) {
  1803. LeaveTracelibCritSection();
  1804. return pSite;
  1805. }
  1806. Next = Next->Flink;
  1807. }
  1808. LeaveTracelibCritSection();
  1809. return NULL;
  1810. }
  1811. //
  1812. // A New Job with a JobId has been found. This routine will create a
  1813. // new job record to track it through various threads in the system
  1814. //
  1815. PPRINT_JOB_RECORD
  1816. AddPrintJobRecord(
  1817. ULONG JobId
  1818. )
  1819. {
  1820. PLIST_ENTRY Head, Next;
  1821. PPRINT_JOB_RECORD pJob = NULL;
  1822. EnterTracelibCritSection();
  1823. Head = &CurrentSystem.FreePrintJobListHead;
  1824. Next = Head->Flink;
  1825. if (Next != Head) {
  1826. pJob = CONTAINING_RECORD ( Next, PRINT_JOB_RECORD, Entry );
  1827. RemoveEntryList( &pJob->Entry );
  1828. }
  1829. LeaveTracelibCritSection();
  1830. if (pJob == NULL) {
  1831. pJob = malloc(sizeof(PRINT_JOB_RECORD));
  1832. if (pJob == NULL) {
  1833. SetLastError( ERROR_OUTOFMEMORY);
  1834. return NULL;
  1835. }
  1836. }
  1837. RtlZeroMemory(pJob, sizeof(PRINT_JOB_RECORD));
  1838. pJob->JobId = JobId;
  1839. EnterTracelibCritSection();
  1840. InsertHeadList( &CurrentSystem.PrintJobListHead, &pJob->Entry );
  1841. LeaveTracelibCritSection();
  1842. return pJob;
  1843. }
  1844. PHTTP_REQUEST_RECORD
  1845. AddHttpReqRecord(
  1846. ULONGLONG RequestId,
  1847. USHORT IpAddrType,
  1848. ULONG IpAddrV4,
  1849. USHORT *IpAddrV6
  1850. )
  1851. {
  1852. PLIST_ENTRY Head, Next;
  1853. PHTTP_REQUEST_RECORD pReq = NULL;
  1854. EnterTracelibCritSection();
  1855. Head = &CurrentSystem.FreeHttpReqListHead;
  1856. Next = Head->Flink;
  1857. if (Next != Head) {
  1858. pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
  1859. RemoveEntryList( &pReq->Entry );
  1860. }
  1861. LeaveTracelibCritSection();
  1862. if (pReq == NULL) {
  1863. pReq = malloc(sizeof(HTTP_REQUEST_RECORD));
  1864. if (pReq == NULL) {
  1865. SetLastError(ERROR_OUTOFMEMORY);
  1866. return NULL;
  1867. }
  1868. }
  1869. RtlZeroMemory(pReq, sizeof(HTTP_REQUEST_RECORD));
  1870. pReq->RequestId = RequestId;
  1871. pReq->IpAddrType = IpAddrType;
  1872. pReq->IpAddrV4 = IpAddrV4;
  1873. if (IpAddrV6 != NULL && IpAddrType == TDI_ADDRESS_TYPE_IP6) {
  1874. RtlCopyMemory(&pReq->IpAddrV6, IpAddrV6, sizeof(USHORT) * 8);
  1875. }
  1876. EnterTracelibCritSection();
  1877. InsertHeadList( &CurrentSystem.HttpReqListHead, &pReq->Entry );
  1878. LeaveTracelibCritSection();
  1879. return pReq;
  1880. }
  1881. PURL_RECORD
  1882. AddUrlRecord(
  1883. PUCHAR Url
  1884. )
  1885. {
  1886. PLIST_ENTRY Head, Next;
  1887. PUCHAR UrlStr = NULL, UrlChar;
  1888. PURL_RECORD pUrl = NULL;
  1889. ULONG UrlStrSize;
  1890. USHORT HashKey;
  1891. if (Url == NULL) {
  1892. return NULL;
  1893. }
  1894. EnterTracelibCritSection();
  1895. Head = &CurrentSystem.FreeURLListHead;
  1896. Next = Head->Flink;
  1897. if (Next != Head) {
  1898. pUrl = CONTAINING_RECORD ( Next, URL_RECORD, Entry );
  1899. RemoveEntryList( &pUrl->Entry );
  1900. }
  1901. LeaveTracelibCritSection();
  1902. if (pUrl == NULL) {
  1903. pUrl = malloc(sizeof(URL_RECORD));
  1904. if (pUrl == NULL) {
  1905. SetLastError(ERROR_OUTOFMEMORY);
  1906. return NULL;
  1907. }
  1908. }
  1909. UrlStrSize = 0;
  1910. UrlChar = Url;
  1911. while (*UrlChar != '\0' && *UrlChar != '?') {
  1912. UrlStrSize++;
  1913. UrlChar++;
  1914. }
  1915. // No URL will end with '/'
  1916. if (*(UrlChar - 1) == '/') {
  1917. *(UrlChar - 1) = '\0';
  1918. UrlStrSize--;
  1919. }
  1920. RtlZeroMemory(pUrl, sizeof(URL_RECORD));
  1921. pUrl->URL = (PUCHAR)malloc(UrlStrSize + 1);
  1922. if (pUrl->URL == NULL) {
  1923. EnterTracelibCritSection();
  1924. InsertHeadList( &CurrentSystem.FreeURLListHead, &pUrl->Entry );
  1925. LeaveTracelibCritSection();
  1926. return NULL;
  1927. }
  1928. strncpy(pUrl->URL, Url, UrlStrSize);
  1929. *(pUrl->URL + UrlStrSize) = '\0';
  1930. HashKey = UrlHashKey(pUrl->URL, UrlStrSize);
  1931. EnterTracelibCritSection();
  1932. InsertHeadList( &CurrentSystem.URLHashList[HashKey], &pUrl->Entry );
  1933. LeaveTracelibCritSection();
  1934. return pUrl;
  1935. }
  1936. PURL_RECORD
  1937. FindOrAddUrlRecord(
  1938. PUCHAR Url
  1939. )
  1940. {
  1941. PURL_RECORD pUrl = NULL;
  1942. pUrl = FindUrlRecord(Url);
  1943. if (pUrl == NULL) {
  1944. pUrl = AddUrlRecord(Url);
  1945. }
  1946. return pUrl;
  1947. }
  1948. PCLIENT_RECORD
  1949. AddClientRecord(
  1950. USHORT IpAddrType,
  1951. ULONG IpAddrV4,
  1952. USHORT *IpAddrV6
  1953. )
  1954. {
  1955. PCLIENT_RECORD pClient = NULL;
  1956. pClient = malloc(sizeof(CLIENT_RECORD));
  1957. if (pClient == NULL) {
  1958. SetLastError(ERROR_OUTOFMEMORY);
  1959. return NULL;
  1960. }
  1961. RtlZeroMemory(pClient, sizeof(CLIENT_RECORD));
  1962. pClient->IpAddrType = IpAddrType;
  1963. pClient->IpAddrV4 = IpAddrV4;
  1964. if (IpAddrV6 != NULL && IpAddrType == TDI_ADDRESS_TYPE_IP6) {
  1965. RtlCopyMemory(pClient->IpAddrV6, IpAddrV6, sizeof(USHORT) * 8);
  1966. }
  1967. EnterTracelibCritSection();
  1968. InsertHeadList( &CurrentSystem.ClientListHead, &pClient->Entry );
  1969. LeaveTracelibCritSection();
  1970. return pClient;
  1971. }
  1972. PCLIENT_RECORD
  1973. FindOrAddClientRecord(
  1974. USHORT IpAddrType,
  1975. ULONG IpAddrV4,
  1976. USHORT *IpAddrV6
  1977. )
  1978. {
  1979. PCLIENT_RECORD pClient = NULL;
  1980. pClient = FindClientRecord(IpAddrType, IpAddrV4, IpAddrV6);
  1981. if (pClient == NULL) {
  1982. pClient = AddClientRecord(IpAddrType, IpAddrV4, IpAddrV6);
  1983. }
  1984. return pClient;
  1985. }
  1986. PSITE_RECORD
  1987. AddSiteRecord(
  1988. ULONG SiteId
  1989. )
  1990. {
  1991. PSITE_RECORD pSite = NULL;
  1992. pSite = malloc(sizeof(SITE_RECORD));
  1993. if (pSite == NULL) {
  1994. SetLastError(ERROR_OUTOFMEMORY);
  1995. return NULL;
  1996. }
  1997. RtlZeroMemory(pSite, sizeof(SITE_RECORD));
  1998. pSite->SiteId = SiteId;
  1999. EnterTracelibCritSection();
  2000. InsertHeadList( &CurrentSystem.SiteListHead, &pSite->Entry );
  2001. LeaveTracelibCritSection();
  2002. return pSite;
  2003. }
  2004. PSITE_RECORD
  2005. FindOrAddSiteRecord(
  2006. ULONG SiteId
  2007. )
  2008. {
  2009. PSITE_RECORD pSite = NULL;
  2010. pSite = FindSiteRecord(SiteId);
  2011. if (pSite == NULL) {
  2012. pSite = AddSiteRecord(SiteId);
  2013. }
  2014. return pSite;
  2015. }
  2016. PURL_RECORD
  2017. GetHeadUrlRecord(
  2018. ULONG index
  2019. )
  2020. {
  2021. PLIST_ENTRY Head, Next;
  2022. PURL_RECORD pUrl = NULL;
  2023. EnterTracelibCritSection();
  2024. Head = &CurrentSystem.URLHashList[index];
  2025. Next = Head->Flink;
  2026. if (Next != Head) {
  2027. pUrl = CONTAINING_RECORD ( Next, URL_RECORD, Entry );
  2028. RemoveEntryList( &pUrl->Entry );
  2029. }
  2030. LeaveTracelibCritSection();
  2031. return pUrl;
  2032. }
  2033. PCLIENT_RECORD
  2034. GetHeadClientRecord()
  2035. {
  2036. PLIST_ENTRY Head, Next;
  2037. PCLIENT_RECORD pClient = NULL;
  2038. EnterTracelibCritSection();
  2039. Head = &CurrentSystem.ClientListHead;
  2040. Next = Head->Flink;
  2041. if (Next != Head) {
  2042. pClient = CONTAINING_RECORD ( Next, CLIENT_RECORD, Entry );
  2043. RemoveEntryList( &pClient->Entry );
  2044. }
  2045. LeaveTracelibCritSection();
  2046. return pClient;
  2047. }
  2048. PSITE_RECORD
  2049. GetHeadSiteRecord()
  2050. {
  2051. PLIST_ENTRY Head, Next;
  2052. PSITE_RECORD pSite = NULL;
  2053. EnterTracelibCritSection();
  2054. Head = &CurrentSystem.SiteListHead;
  2055. Next = Head->Flink;
  2056. if (Next != Head) {
  2057. pSite = CONTAINING_RECORD ( Next, SITE_RECORD, Entry );
  2058. RemoveEntryList( &pSite->Entry );
  2059. }
  2060. LeaveTracelibCritSection();
  2061. return pSite;
  2062. }
  2063. //
  2064. // Deletes a Job record with the JobId. Before deleting the contents
  2065. // of the job record is dumped to a temp file for later reporting.
  2066. //
  2067. ULONG
  2068. DeletePrintJobRecord(
  2069. PPRINT_JOB_RECORD pJob,
  2070. ULONG bSave
  2071. )
  2072. {
  2073. if (pJob == NULL)
  2074. return ERROR_INVALID_PARAMETER;
  2075. //
  2076. // Print the Contents of pJob to file.
  2077. //
  2078. // If the -spooler option isn't given to the reducer this fprintf causes the
  2079. // program to crash. Maybe TRACE_SPOOLER should alway be set.
  2080. if (CurrentSystem.TempPrintFile != NULL && bSave) {
  2081. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->JobId);
  2082. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->KCPUTime);
  2083. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->UCPUTime);
  2084. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->ReadIO);
  2085. fprintf(CurrentSystem.TempPrintFile, "%I64u, ", pJob->StartTime);
  2086. fprintf(CurrentSystem.TempPrintFile, "%I64u, ", pJob->EndTime);
  2087. fprintf(CurrentSystem.TempPrintFile, "%I64u, ", (pJob->ResponseTime - pJob->PauseTime));
  2088. fprintf(CurrentSystem.TempPrintFile, "%I64u, ", pJob->PrintJobTime);
  2089. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->WriteIO);
  2090. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->DataType);
  2091. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->JobSize);
  2092. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->Pages);
  2093. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->PagesPerSide);
  2094. fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->FilesOpened);
  2095. fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->GdiJobSize);
  2096. fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->Color);
  2097. fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->XRes);
  2098. fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->YRes);
  2099. fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->Quality);
  2100. fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->Copies);
  2101. fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->TTOption);
  2102. fprintf(CurrentSystem.TempPrintFile, "%d\n", pJob->NumberOfThreads);
  2103. }
  2104. EnterTracelibCritSection();
  2105. RemoveEntryList( &pJob->Entry );
  2106. InsertHeadList( &CurrentSystem.FreePrintJobListHead, &pJob->Entry );
  2107. LeaveTracelibCritSection();
  2108. return ERROR_SUCCESS;
  2109. }
  2110. ULONG
  2111. DeleteHttpReqRecord(
  2112. PHTTP_REQUEST_RECORD pReq,
  2113. ULONG bSave
  2114. )
  2115. {
  2116. if (pReq == NULL)
  2117. return ERROR_INVALID_PARAMETER;
  2118. //
  2119. // Print the Contents of pReq to file.
  2120. //
  2121. if (CurrentSystem.TempIisFile != NULL && bSave) {
  2122. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->RequestId);
  2123. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->SiteId);
  2124. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->KCPUTime);
  2125. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->UCPUTime);
  2126. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->ReadIO);
  2127. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->WriteIO);
  2128. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULStartTime);
  2129. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULEndTime);
  2130. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULResponseTime);
  2131. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULParseTime);
  2132. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULDeliverTime);
  2133. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULReceiveTime);
  2134. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->ULReceiveType);
  2135. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->ULEndType);
  2136. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->W3StartTime);
  2137. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->W3EndTime);
  2138. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->W3FilterResponseTime);
  2139. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->W3ProcessType);
  2140. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->W3EndType);
  2141. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->FileReqTime);
  2142. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->CGIStartTime);
  2143. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->CGIEndTime);
  2144. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ISAPIStartTime);
  2145. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ISAPIEndTime);
  2146. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ASPStartTime);
  2147. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ASPEndTime);
  2148. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->SSLResponseTime);
  2149. fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->StrmFltrResponseTime);
  2150. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->HttpStatus);
  2151. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IsapiExt);
  2152. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrType);
  2153. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->IpAddrV4);
  2154. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[0]);
  2155. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[1]);
  2156. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[2]);
  2157. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[3]);
  2158. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[4]);
  2159. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[5]);
  2160. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[6]);
  2161. fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[7]);
  2162. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->NumberOfThreads);
  2163. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->BytesSent);
  2164. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->ULCPUTime);
  2165. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->W3CPUTime);
  2166. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->W3FltrCPUTime);
  2167. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->ISAPICPUTime);
  2168. fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->ASPCPUTime);
  2169. fprintf(CurrentSystem.TempIisFile, "%d,", pReq->CGICPUTime);
  2170. if (pReq->URL != NULL) {
  2171. fprintf(CurrentSystem.TempIisFile, "%s\n", pReq->URL);
  2172. free(pReq->URL);
  2173. }
  2174. else {
  2175. fprintf(CurrentSystem.TempIisFile, "Unknown\n");
  2176. }
  2177. }
  2178. EnterTracelibCritSection();
  2179. RemoveEntryList( &pReq->Entry );
  2180. InsertHeadList( &CurrentSystem.FreeHttpReqListHead, &pReq->Entry );
  2181. LeaveTracelibCritSection();
  2182. return ERROR_SUCCESS;
  2183. }
  2184. ULONG
  2185. DeleteUrlRecord(
  2186. PURL_RECORD pUrl
  2187. )
  2188. {
  2189. if (pUrl == NULL)
  2190. return ERROR_INVALID_PARAMETER;
  2191. if (pUrl->URL != NULL) {
  2192. free(pUrl->URL);
  2193. }
  2194. EnterTracelibCritSection();
  2195. RemoveEntryList( &pUrl->Entry );
  2196. InsertHeadList( &CurrentSystem.FreeURLListHead, &pUrl->Entry );
  2197. LeaveTracelibCritSection();
  2198. return ERROR_SUCCESS;
  2199. }
  2200. ULONG
  2201. DeleteClientRecord(
  2202. PCLIENT_RECORD pClient
  2203. )
  2204. {
  2205. if (pClient == NULL)
  2206. return ERROR_INVALID_PARAMETER;
  2207. EnterTracelibCritSection();
  2208. RemoveEntryList( &pClient->Entry );
  2209. LeaveTracelibCritSection();
  2210. free(pClient);
  2211. return ERROR_SUCCESS;
  2212. }
  2213. ULONG
  2214. DeleteSiteRecord(
  2215. PSITE_RECORD pSite
  2216. )
  2217. {
  2218. if (pSite == NULL)
  2219. return ERROR_INVALID_PARAMETER;
  2220. EnterTracelibCritSection();
  2221. RemoveEntryList( &pSite->Entry );
  2222. LeaveTracelibCritSection();
  2223. free(pSite);
  2224. return ERROR_SUCCESS;
  2225. }