|
3 | 3 | * ETW statistics collection
|
4 | 4 | *
|
5 | 5 | * Copyright (C) 2010-2011 wj32
|
6 |
| - * Copyright (C) 2019-2020 dmex |
| 6 | + * Copyright (C) 2019-2022 dmex |
7 | 7 | *
|
8 | 8 | * This file is part of Process Hacker.
|
9 | 9 | *
|
@@ -34,10 +34,17 @@ VOID NTAPI EtEtwNetworkItemsUpdatedCallback(
|
34 | 34 | _In_opt_ PVOID Context
|
35 | 35 | );
|
36 | 36 |
|
| 37 | +VOID EtpUpdateProcessInformation( |
| 38 | + VOID |
| 39 | + ); |
| 40 | + |
37 | 41 | BOOLEAN EtDiskExtEnabled = FALSE;
|
38 | 42 | static PH_CALLBACK_REGISTRATION EtpProcessesUpdatedCallbackRegistration;
|
39 | 43 | static PH_CALLBACK_REGISTRATION EtpNetworkItemsUpdatedCallbackRegistration;
|
40 | 44 |
|
| 45 | +static PVOID EtpProcessInformation = NULL; |
| 46 | +static PH_QUEUED_LOCK EtpProcessInformationLock = PH_QUEUED_LOCK_INIT; |
| 47 | + |
41 | 48 | ULONG EtpDiskReadRaw;
|
42 | 49 | ULONG EtpDiskWriteRaw;
|
43 | 50 | ULONG EtpNetworkReceiveRaw;
|
@@ -396,6 +403,8 @@ VOID NTAPI EtEtwProcessesUpdatedCallback(
|
396 | 403 | // Since Windows 8, we no longer get the correct process/thread IDs in the
|
397 | 404 | // event headers for disk events. We need to update our process information since
|
398 | 405 | // etwmon uses our EtThreadIdToProcessId function. (wj32)
|
| 406 | + if (PhWindowsVersion >= WINDOWS_8) |
| 407 | + EtpUpdateProcessInformation(); |
399 | 408 |
|
400 | 409 | // ETW is extremely lazy when it comes to flushing buffers, so we must do it manually. (wj32)
|
401 | 410 | //EtFlushEtwSession();
|
@@ -548,43 +557,56 @@ VOID NTAPI EtEtwNetworkItemsUpdatedCallback(
|
548 | 557 | }
|
549 | 558 | }
|
550 | 559 |
|
| 560 | +VOID EtpUpdateProcessInformation( |
| 561 | + VOID |
| 562 | + ) |
| 563 | +{ |
| 564 | + PhAcquireQueuedLockExclusive(&EtpProcessInformationLock); |
| 565 | + |
| 566 | + if (EtpProcessInformation) |
| 567 | + { |
| 568 | + PhFree(EtpProcessInformation); |
| 569 | + EtpProcessInformation = NULL; |
| 570 | + } |
| 571 | + |
| 572 | + PhEnumProcesses(&EtpProcessInformation); |
| 573 | + |
| 574 | + PhReleaseQueuedLockExclusive(&EtpProcessInformationLock); |
| 575 | +} |
| 576 | + |
551 | 577 | HANDLE EtThreadIdToProcessId(
|
552 | 578 | _In_ HANDLE ThreadId
|
553 | 579 | )
|
554 | 580 | {
|
555 |
| - // Note: no lock is needed because we use the list on the same thread (EtpEtwMonitorThreadStart). (dmex) |
556 |
| - static PVOID processInfo = NULL; |
557 |
| - static ULONG64 lastTickTotal = 0; |
558 | 581 | PSYSTEM_PROCESS_INFORMATION process;
|
559 |
| - ULONG64 tickCount; |
| 582 | + ULONG i; |
| 583 | + HANDLE processId; |
560 | 584 |
|
561 |
| - tickCount = NtGetTickCount64(); |
| 585 | + PhAcquireQueuedLockShared(&EtpProcessInformationLock); |
562 | 586 |
|
563 |
| - if (tickCount - lastTickTotal >= 2 * CLOCKS_PER_SEC) |
| 587 | + if (!EtpProcessInformation) |
564 | 588 | {
|
565 |
| - lastTickTotal = tickCount; |
566 |
| - |
567 |
| - if (processInfo) |
568 |
| - { |
569 |
| - PhFree(processInfo); |
570 |
| - processInfo = NULL; |
571 |
| - } |
572 |
| - |
573 |
| - PhEnumProcesses(&processInfo); |
| 589 | + PhReleaseQueuedLockShared(&EtpProcessInformationLock); |
| 590 | + return SYSTEM_PROCESS_ID; |
574 | 591 | }
|
575 | 592 |
|
576 |
| - process = PH_FIRST_PROCESS(processInfo); |
| 593 | + process = PH_FIRST_PROCESS(EtpProcessInformation); |
577 | 594 |
|
578 | 595 | do
|
579 | 596 | {
|
580 |
| - for (ULONG i = 0; i < process->NumberOfThreads; i++) |
| 597 | + for (i = 0; i < process->NumberOfThreads; i++) |
581 | 598 | {
|
582 | 599 | if (process->Threads[i].ClientId.UniqueThread == ThreadId)
|
583 | 600 | {
|
584 |
| - return process->UniqueProcessId; |
| 601 | + processId = process->UniqueProcessId; |
| 602 | + PhReleaseQueuedLockShared(&EtpProcessInformationLock); |
| 603 | + |
| 604 | + return processId; |
585 | 605 | }
|
586 | 606 | }
|
587 | 607 | } while (process = PH_NEXT_PROCESS(process));
|
588 | 608 |
|
| 609 | + PhReleaseQueuedLockShared(&EtpProcessInformationLock); |
| 610 | + |
589 | 611 | return SYSTEM_PROCESS_ID;
|
590 | 612 | }
|
0 commit comments