master ohmu/fastfetch-openbsd / src / detection / top / top_windows.c
ohmu  ·  2026-10-15
 1#include "top.h"
 2
 3#include "common/debug.h"
 4#include "common/mallocHelper.h"
 5#include "common/windows/unicode.h"
 6
 7#include <ntstatus.h>
 8#include <windows.h>
 9#include <winternl.h>
10
11const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) {
12    FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr;
13
14    // Multiple attempts in case processes change while
15    // we are in the middle of querying them.
16    ULONG size = 0;
17    for (int attempts = 0;; ++attempts) {
18        if (size) {
19            pstart = (SYSTEM_PROCESS_INFORMATION*) realloc(pstart, size);
20            assert(pstart);
21        }
22        NTSTATUS status = NtQuerySystemInformation(SystemProcessInformation, pstart, size, &size);
23        if (NT_SUCCESS(status)) {
24            break;
25        } else if (status == STATUS_INFO_LENGTH_MISMATCH && attempts < 4) {
26            size += sizeof(SYSTEM_PROCESS_INFORMATION) * 5;
27        } else {
28            FF_DEBUG("NtQuerySystemInformation(SystemProcessInformation) failed: %s", ffDebugNtStatus(status));
29            return "NtQuerySystemInformation(SystemProcessInformation) failed";
30        }
31    }
32
33    for (SYSTEM_PROCESS_INFORMATION* info = pstart;; info = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) info + info->NextEntryOffset)) {
34        uintptr_t pidValue = (uintptr_t) info->UniqueProcessId;
35        if (pidValue <= UINT32_MAX && (uintptr_t) info->InheritedFromUniqueProcessId > 0) {
36            FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots);
37            item->pid = (uint32_t) pidValue;
38            item->startTime = (uint64_t) info->CreateTime.QuadPart;
39            item->cpuTime = ((uint64_t) info->UserTime.QuadPart + (uint64_t) info->KernelTime.QuadPart) / 10000u;
40            item->memBytes = (uint64_t) info->VirtualMemoryCounters.WorkingSetSize;
41            item->bytesRead = (uint64_t) info->IoCounters.ReadTransferCount;
42            item->bytesWritten = (uint64_t) info->IoCounters.WriteTransferCount;
43            item->threads = info->NumberOfThreads;
44            ffStrbufInitNWS(&item->name, info->ImageName.Length / sizeof(wchar_t), info->ImageName.Buffer);
45        }
46        if (info->NextEntryOffset == 0) {
47            break;
48        }
49    }
50    return nullptr;
51}