65 #define PROCESS_ID_BUCKETS 64
66 #define PROCESS_ID_TO_BUCKET_INDEX(ProcessId) (((ULONG)(ProcessId) / 4) & (PROCESS_ID_BUCKETS - 1))
68 typedef struct _PH_PROCESS_QUERY_DATA
70 SLIST_ENTRY ListEntry;
75 typedef struct _PH_PROCESS_QUERY_S1_DATA
85 TOKEN_ELEVATION_TYPE ElevationType;
87 MANDATORY_LEVEL IntegrityLevel;
88 PWSTR IntegrityString;
92 BOOLEAN IsInSignificantJob;
94 HANDLE ConsoleHostProcessId;
100 BOOLEAN IsWow64Valid;
103 typedef struct _PH_PROCESS_QUERY_S2_DATA
111 ULONG ImportFunctions;
115 typedef struct _PH_VERIFY_CACHE_ENTRY
210 static BOOLEAN PhProcessStatisticsInitialized =
FALSE;
211 static ULONG PhTimeSequenceNumber = 0;
212 static PH_CIRCULAR_BUFFER_ULONG PhTimeHistory;
231 #ifdef PH_RECORD_MAX_USAGE
238 static ULONG PhpTsNumberOfProcesses;
240 #ifdef PH_ENABLE_VERIFY_CACHE
251 PPH_CIRCULAR_BUFFER_FLOAT historyBuffer;
267 &PhInterruptsProcessInformation.
ImageName,
273 PhCpuInformation = PhAllocate(
279 sizeof(LARGE_INTEGER) *
283 sizeof(LARGE_INTEGER) *
287 usageBuffer = PhAllocate(
292 deltaBuffer = PhAllocate(
297 historyBuffer = PhAllocate(
298 sizeof(PH_CIRCULAR_BUFFER_FLOAT) *
306 PhCpusKernelDelta = deltaBuffer;
349 if (ClientId->UniqueThread)
359 name =
PhFormat(format, 5, ProcessName->Length + 16 *
sizeof(WCHAR));
396 _In_ ULONG PriorityClass
399 switch (PriorityClass)
406 return L
"Above Normal";
410 return L
"Below Normal";
505 return Value1->ProcessId == Value2->ProcessId;
512 return (ULONG)Value->ProcessId / 4;
539 for (; entry; entry = entry->
Next)
586 _Out_ PULONG NumberOfProcessItems
590 ULONG numberOfProcessItems;
609 for (entry = PhProcessHashSet[i]; entry; entry = entry->
Next)
613 processItems[count++] = processItem;
619 *ProcessItems = processItems;
620 *NumberOfProcessItems = numberOfProcessItems;
658 _In_opt_ PWSTR PackageFullName,
666 PCERT_CONTEXT *signatures;
667 ULONG numberOfSignatures;
686 if (additionalCatalogFileName)
688 Information->NumberOfCatalogFileNames = 1;
689 Information->CatalogFileNames = &additionalCatalogFileName->
Buffer;
696 numberOfSignatures = 0;
699 if (additionalCatalogFileName)
704 if (numberOfSignatures != 0)
733 _In_opt_ PWSTR PackageFullName,
735 _In_ BOOLEAN CachedOnly
738 #ifdef PH_ENABLE_VERIFY_CACHE
743 lookupEntry.FileName = FileName;
756 return entry->VerifyResult;
784 entry->FileName = FileName;
785 entry->VerifyResult = result;
786 entry->VerifySignerName = signerName;
798 if (entry->VerifySignerName)
810 *SignerName = signerName;
835 *SignerName = signerName;
853 HANDLE processId = processItem->
ProcessId;
854 HANDLE processHandleLimited = NULL;
869 Data->LargeIcon = NULL;
870 Data->SmallIcon = NULL;
879 if (!Data->SmallIcon || !Data->LargeIcon)
883 DestroyIcon(Data->SmallIcon);
884 Data->SmallIcon = NULL;
886 else if (Data->LargeIcon)
888 DestroyIcon(Data->LargeIcon);
889 Data->LargeIcon = NULL;
893 Data->SmallIcon = DuplicateIcon(NULL, Data->SmallIcon);
894 Data->LargeIcon = DuplicateIcon(NULL, Data->LargeIcon);
900 if (processHandleLimited)
903 Data->IsWow64Valid =
TRUE;
906 Data->IsWow64Valid =
TRUE;
911 HANDLE processHandle;
912 BOOLEAN queryAccess =
FALSE;
932 BOOLEAN isPosix =
FALSE;
933 BOOLEAN isDotNet =
FALSE;
940 Data->IsPosix = isPosix;
952 for (i = 0; i < (ULONG)commandLine->
Length / 2; i++)
954 if (commandLine->
Buffer[i] == 0)
955 commandLine->
Buffer[i] =
' ';
967 Data->CommandLine = commandLine;
983 Data->IsDotNet = isDotNet;
986 NtClose(processHandle);
991 if (processHandleLimited)
1004 &Data->ElevationType
1007 Data->IsElevated = Data->ElevationType == TokenElevationTypeFull;
1013 &Data->IntegrityLevel,
1014 &Data->IntegrityString
1017 NtClose(tokenHandle);
1023 if (processHandleLimited)
1027 HANDLE jobHandle = NULL;
1030 processHandleLimited,
1035 if (
NT_SUCCESS(status) && status != STATUS_PROCESS_NOT_IN_JOB && jobHandle)
1037 JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimits;
1039 Data->IsInJob =
TRUE;
1056 Data->IsInSignificantJob =
1057 basicLimits.LimitFlags != JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
1068 status = NtIsProcessInJob(processHandleLimited, NULL);
1071 Data->IsInJob = status == STATUS_PROCESS_IN_JOB;
1087 if (processHandleLimited)
1088 NtClose(processHandleLimited);
1110 &Data->VerifySignerName,
1114 if (packageFullName)
1120 &Data->ImportModules,
1121 &Data->ImportFunctions
1126 status == STATUS_INVALID_IMAGE_NOT_MZ ||
1127 status == STATUS_INVALID_IMAGE_FORMAT ||
1128 status == STATUS_ACCESS_VIOLATION
1131 Data->IsPacked =
TRUE;
1132 Data->ImportModules = -1;
1133 Data->ImportFunctions = -1;
1139 _In_ PVOID Parameter
1147 data->Header.Stage = 1;
1148 data->Header.ProcessItem = processItem;
1154 return STATUS_SUCCESS;
1158 _In_ PVOID Parameter
1166 data->Header.Stage = 2;
1167 data->Header.ProcessItem = processItem;
1173 return STATUS_SUCCESS;
1204 processItem->
SmallIcon = Data->SmallIcon;
1205 processItem->
LargeIcon = Data->LargeIcon;
1210 processItem->
JobName = Data->JobName;
1213 processItem->
IsDotNet = Data->IsDotNet;
1215 processItem->
IsInJob = Data->IsInJob;
1217 processItem->
IsPosix = Data->IsPosix;
1218 processItem->
IsWow64 = Data->IsWow64;
1232 processItem->
IsPacked = Data->IsPacked;
1243 HANDLE processHandle = NULL;
1245 ProcessItem->ParentProcessId = Process->InheritedFromUniqueProcessId;
1246 ProcessItem->SessionId = Process->SessionId;
1247 ProcessItem->CreateTime = Process->CreateTime;
1254 PhPrintUInt32(ProcessItem->ParentProcessIdString, (ULONG)ProcessItem->ParentProcessId);
1255 PhPrintUInt32(ProcessItem->SessionIdString, ProcessItem->SessionId);
1331 NtClose(tokenHandle);
1349 if (!PhpTsProcesses)
1354 &PhpTsNumberOfProcesses,
1363 for (i = 0; i < PhpTsNumberOfProcesses; i++)
1365 if (UlongToHandle(PhpTsProcesses[i].pTsProcessInfo->UniqueProcessId) == ProcessItem->ProcessId)
1374 NtClose(processHandle);
1382 ProcessItem->BasePriority = Process->BasePriority;
1384 if (ProcessItem->QueryHandle)
1389 ProcessItem->QueryHandle,
1390 ProcessPriorityClass,
1401 ProcessItem->PriorityClass = 0;
1404 ProcessItem->KernelTime = Process->KernelTime;
1405 ProcessItem->UserTime = Process->UserTime;
1406 ProcessItem->NumberOfHandles = Process->HandleCount;
1407 ProcessItem->NumberOfThreads = Process->NumberOfThreads;
1408 ProcessItem->WorkingSetPrivateSize = (SIZE_T)Process->WorkingSetPrivateSize.QuadPart;
1409 ProcessItem->PeakNumberOfThreads = Process->NumberOfThreadsHighWatermark;
1410 ProcessItem->HardFaultCount = Process->HardFaultCount;
1413 ProcessItem->VmCounters = *(PVM_COUNTERS_EX)&Process->PeakVirtualSize;
1414 ProcessItem->IoCounters = *(PIO_COUNTERS)&Process->ReadOperationCount;
1421 NtQuerySystemInformation(
1434 _In_ BOOLEAN SetCpuUsage,
1435 _Out_ PULONG64 TotalTime
1441 NtQuerySystemInformation(
1454 &PhCpuInformation[i];
1473 totalTime = PhCpusKernelDelta[i].
Delta + PhCpusUserDelta[i].
Delta + PhCpusIdleDelta[i].
Delta;
1492 totalTime = PhCpuKernelDelta.
Delta + PhCpuUserDelta.
Delta + PhCpuIdleDelta.
Delta;
1508 *TotalTime = totalTime;
1512 _Out_ PULONG64 IdleCycleTime
1522 NtQuerySystemInformation(
1538 *IdleCycleTime = PhCpuIdleCycleDelta.
Delta;
1542 NtQuerySystemInformation(
1560 _In_ ULONG64 TotalCycleTime,
1561 _In_ ULONG64 IdleCycleTime
1566 FLOAT totalTimeDelta;
1599 baseCpuUsage = 1 - (FLOAT)IdleCycleTime / TotalCycleTime;
1600 totalTimeDelta = (FLOAT)(PhCpuKernelDelta.
Delta + PhCpuUserDelta.
Delta);
1602 if (totalTimeDelta != 0)
1615 totalTime = PhCpusKernelDelta[i].
Delta + PhCpusUserDelta[i].
Delta + PhCpusIdleDelta[i].
Delta;
1646 #ifdef PH_RECORD_MAX_USAGE
1664 LARGE_INTEGER systemTime;
1665 ULONG secondsSince1980;
1692 PhAddItemCircularBuffer_ULONG(&PhTimeHistory, secondsSince1980);
1710 _Out_ PLARGE_INTEGER Time
1713 ULONG secondsSince1980;
1721 index = PhTimeSequenceNumber - ProcessItem->SequenceNumber + Index;
1723 if (index >= PhTimeHistory.Count)
1735 secondsSince1980 = PhGetItemCircularBuffer_ULONG(&PhTimeHistory, index);
1749 SYSTEMTIME systemTime;
1764 _In_ BOOLEAN SendModifiedEvent
1779 entry = entry->Next;
1782 if (data->Stage == 1)
1788 else if (data->Stage == 2)
1797 if (SendModifiedEvent && data->ProcessItem->AddedEventSent)
1800 data->ProcessItem->JustProcessed = 1;
1810 _Out_opt_ PBOOLEAN IsSuspended,
1811 _Out_opt_ PBOOLEAN IsPartiallySuspended,
1812 _Out_opt_ PULONG ContextSwitches
1816 BOOLEAN isSuspended;
1817 BOOLEAN isPartiallySuspended;
1818 ULONG contextSwitches;
1821 isPartiallySuspended =
FALSE;
1822 contextSwitches = 0;
1824 for (i = 0; i < Process->NumberOfThreads; i++)
1826 if (Process->Threads[i].ThreadState !=
Waiting ||
1827 Process->Threads[i].WaitReason != Suspended)
1829 isSuspended =
FALSE;
1833 isPartiallySuspended =
TRUE;
1836 contextSwitches += Process->Threads[i].ContextSwitches;
1840 *IsSuspended = isSuspended;
1841 if (IsPartiallySuspended)
1842 *IsPartiallySuspended = isPartiallySuspended;
1843 if (ContextSwitches)
1844 *ContextSwitches = contextSwitches;
1851 static ULONG runCount = 0;
1864 BOOLEAN isCycleCpuUsageEnabled =
FALSE;
1866 ULONG64 sysTotalTime;
1867 ULONG64 sysTotalCycleTime = 0;
1868 ULONG64 sysIdleCycleTime = 0;
1869 FLOAT maxCpuValue = 0;
1871 ULONG64 maxIoValue = 0;
1876 if (runCount % 5 == 0)
1881 if (runCount % 512 == 0)
1889 if (!PhProcessStatisticsInitialized)
1892 PhProcessStatisticsInitialized =
TRUE;
1897 if (isCycleCpuUsageEnabled)
1909 PhTimeSequenceNumber++;
1947 memset(pidBuckets, 0,
sizeof(pidBuckets));
1965 pidBuckets[bucketIndex] = process;
1967 if (isCycleCpuUsageEnabled)
1974 sysTotalCycleTime += process->
CycleTime;
1982 if (isCycleCpuUsageEnabled)
1985 PhInterruptsProcessInformation.
CycleTime = PhCpuSystemCycleDelta.
Value;
1986 sysTotalCycleTime += PhCpuSystemCycleDelta.
Delta;
2004 for (entry = PhProcessHashSet[i]; entry; entry = entry->
Next)
2029 LARGE_INTEGER exitTime;
2032 exitTime.QuadPart = 0;
2036 KERNEL_USER_TIMES times;
2037 ULONG64 finalCycleTime;
2041 exitTime = times.ExitTime;
2044 if (isCycleCpuUsageEnabled)
2061 if (exitTime.QuadPart == 0)
2070 if (!processesToRemove)
2079 if (processesToRemove)
2083 for (i = 0; i < processesToRemove->
Count; i++)
2096 if (sysTotalTime == 0)
2098 if (sysTotalCycleTime == 0)
2099 sysTotalCycleTime = -1;
2115 BOOLEAN isSuspended;
2116 BOOLEAN isPartiallySuspended;
2117 ULONG contextSwitches;
2126 processItem->
Record = processRecord;
2167 data.Header.Stage = 1;
2168 data.Header.ProcessItem = processItem;
2196 BOOLEAN modified =
FALSE;
2197 BOOLEAN isSuspended;
2198 BOOLEAN isPartiallySuspended;
2199 ULONG contextSwitches;
2201 FLOAT kernelCpuUsage;
2229 if (InterlockedExchange(&processItem->
JustProcessed, 0) != 0)
2232 if (isCycleCpuUsageEnabled)
2245 if (totalDelta != 0)
2248 userCpuUsage = newCpuUsage * ((FLOAT)processItem->
CpuUserDelta.
Delta / totalDelta);
2252 if (processItem->
UserTime.QuadPart != 0)
2254 kernelCpuUsage = newCpuUsage / 2;
2255 userCpuUsage = newCpuUsage / 2;
2259 kernelCpuUsage = newCpuUsage;
2268 newCpuUsage = kernelCpuUsage + userCpuUsage;
2271 processItem->
CpuUsage = newCpuUsage;
2275 PhAddItemCircularBuffer_FLOAT(&processItem->
CpuKernelHistory, kernelCpuUsage);
2276 PhAddItemCircularBuffer_FLOAT(&processItem->
CpuUserHistory, userCpuUsage);
2282 if (maxCpuValue < newCpuUsage)
2284 maxCpuValue = newCpuUsage;
2285 maxCpuProcessItem = processItem;
2289 if (maxIoValue < processItem->IoReadDelta.Delta + processItem->
IoWriteDelta.
Delta)
2292 maxIoProcessItem = processItem;
2299 BOOLEAN isBeingDebugged;
2337 BOOLEAN isImmersive;
2358 if (process == &PhInterruptsProcessInformation)
2362 else if (process == &PhDpcsProcessInformation)
2370 if (process == NULL)
2372 if (isCycleCpuUsageEnabled)
2388 PhpTsProcesses = NULL;
2396 if (isCycleCpuUsageEnabled)
2404 if (maxCpuProcessItem)
2407 #ifdef PH_RECORD_MAX_USAGE
2420 #ifdef PH_RECORD_MAX_USAGE
2425 if (maxIoProcessItem)
2428 #ifdef PH_RECORD_MAX_USAGE
2443 #ifdef PH_RECORD_MAX_USAGE
2466 processRecord->
ProcessId = ProcessItem->ProcessId;
2468 processRecord->
SessionId = ProcessItem->SessionId;
2469 processRecord->
CreateTime = ProcessItem->CreateTime;
2476 return processRecord;
2480 _In_ PLARGE_INTEGER Time,
2481 _Out_opt_ PULONG Index,
2482 _Out_opt_ PULONG InsertIndex
2489 BOOLEAN found =
FALSE;
2492 if (PhProcessRecordList->
Count == 0)
2503 high = PhProcessRecordList->
Count - 1;
2508 i = (low + high) / 2;
2513 if (comparison == 0)
2518 else if (comparison < 0)
2526 }
while (low <= high);
2533 return processRecord;
2538 *InsertIndex = i + (comparison > 0);
2579 assert(headProcessRecord);
2584 if (ProcessRecord == headProcessRecord)
2600 _InterlockedIncrement(&ProcessRecord->RefCount);
2625 if (_InterlockedDecrement(&ProcessRecord->RefCount) == 0)
2644 startProcessRecord = ProcessRecord;
2648 if (ProcessRecord->ProcessId == ProcessId)
2649 return ProcessRecord;
2651 ProcessRecord = CONTAINING_RECORD(ProcessRecord->ListEntry.Flink,
PH_PROCESS_RECORD, ListEntry);
2652 }
while (ProcessRecord != startProcessRecord);
2670 _In_ PLARGE_INTEGER Time
2677 if (PhProcessRecordList->
Count == 0)
2695 if (processRecord->
CreateTime.QuadPart < Time->QuadPart)
2747 return processRecord;
2762 LARGE_INTEGER threshold;
2765 if (PhProcessRecordList->
Count == 0)
2773 for (i = 0; i < PhProcessRecordList->
Count; i++)
2775 processRecord = PhProcessRecordList->
Items[i];
2776 startProcessRecord = processRecord;
2780 ULONG requiredFlags;
2784 if ((processRecord->
Flags & requiredFlags) == requiredFlags)
2788 if (processRecord->
ExitTime.QuadPart < threshold.QuadPart)
2803 }
while (processRecord != startProcessRecord);
2810 for (i = 0; i < derefList->
Count; i++)
2820 _In_ HANDLE ParentProcessId,
2822 _In_ PLARGE_INTEGER CreateTime
2827 if (ParentProcessId == ProcessId)
2837 if (processItem && processItem->
CreateTime.QuadPart <= CreateTime->QuadPart)
2857 if (processItem && processItem->
CreateTime.QuadPart == Record->CreateTime.QuadPart)