1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// much of this code is public-domain
//
#include "boinc_win.h"
#include "error_numbers.h"
#include "diagnostics_win.h"
#include "str_util.h"
#include "str_replace.h"
#include "procinfo.h"
using std::vector;
// NtQuerySystemInformation
typedef NTSTATUS (WINAPI *tNTQSI)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
static int get_process_information(PVOID* ppBuffer, PULONG pcbBuffer) {
NTSTATUS Status = STATUS_INFO_LENGTH_MISMATCH;
HANDLE hHeap = GetProcessHeap();
HMODULE hNTDllLib = GetModuleHandle(_T("ntdll.dll"));
tNTQSI pNTQSI = (tNTQSI)GetProcAddress(hNTDllLib, "NtQuerySystemInformation");
ULONG cbBuffer = 0;
while (1) {
// Store the buffer size since it appears that somebody is monkeying around
// with the return values on some systems.
cbBuffer = *pcbBuffer;
*ppBuffer = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, *pcbBuffer);
if (*ppBuffer == NULL) {
return ERR_MALLOC;
}
Status = pNTQSI(
SystemProcessInformation,
*ppBuffer,
*pcbBuffer,
pcbBuffer
);
if (*pcbBuffer < cbBuffer) {
// Somebody is trying to screw us up,
// so set the value back to the cached size
// so we can do something smart like increase the buffer size.
*pcbBuffer = cbBuffer;
}
if (Status == STATUS_INFO_LENGTH_MISMATCH) {
HeapFree(hHeap, NULL, *ppBuffer);
*pcbBuffer *= 2;
} else if (!NT_SUCCESS(Status)) {
HeapFree(hHeap, NULL, *ppBuffer);
return ERR_GETRUSAGE;
} else {
return 0;
}
}
return 0; // never reached
}
// Note: the following will work on both NT and XP,
// because the NT process structure differs only at the end
//
int get_procinfo_XP(PROC_MAP& pm) {
ULONG cbBuffer = 128*1024; // 128k initial buffer
PVOID pBuffer = NULL;
PSYSTEM_PROCESSES pProcesses = NULL;
static DWORD pid = 0;
if (!pid) {
pid = GetCurrentProcessId();
}
#if 0
printf("FILETIME: %d\n", sizeof(FILETIME));
printf("LARGE_INTEGER: %d\n", sizeof(LARGE_INTEGER));
printf("DWORD: %d\n", sizeof(DWORD));
printf("UNICODE_STRING: %d\n", sizeof(UNICODE_STRING));
printf("KPRIORITY: %d\n", sizeof(KPRIORITY));
printf("ULONG: %d\n", sizeof(ULONG));
printf("SIZE_T: %d\n", sizeof(SIZE_T));
#endif
get_process_information(&pBuffer, &cbBuffer);
pProcesses = (PSYSTEM_PROCESSES)pBuffer;
while (pProcesses) {
PROCINFO p;
p.clear();
p.id = pProcesses->ProcessId;
p.parentid = pProcesses->InheritedFromProcessId;
p.swap_size = pProcesses->VmCounters.PagefileUsage;
p.working_set_size = pProcesses->VmCounters.WorkingSetSize;
p.page_fault_count = pProcesses->VmCounters.PageFaultCount;
p.user_time = ((double) pProcesses->UserTime.QuadPart)/1e7;
p.kernel_time = ((double) pProcesses->KernelTime.QuadPart)/1e7;
p.id = pProcesses->ProcessId;
p.parentid = pProcesses->InheritedFromProcessId;
p.is_low_priority = (pProcesses->BasePriority <= 4);
WideCharToMultiByte(CP_ACP, 0,
pProcesses->ProcessName.Buffer,
pProcesses->ProcessName.Length,
p.command,
sizeof(p.command),
NULL, NULL
);
p.is_boinc_app = (p.id == (int)pid) || (strcasestr(p.command, "boinc") != NULL);
#ifdef _CHARITYENGINE
if (!strcmp(p.command, "charityengine.exe")) {
p.is_boinc_app = true;
}
#endif
#ifdef _GRIDREPUBLIC
if (!strcmp(p.command, "gridrepublic.exe")) {
p.is_boinc_app = true;
}
#endif
#ifdef _PROGRESSTHRUPROCESSORS
if (!strcmp(p.command, "progressthruprocessors.exe")) {
p.is_boinc_app = true;
}
#endif
pm.insert(std::pair<int, PROCINFO>(p.id, p));
if (!pProcesses->NextEntryDelta) {
break;
}
pProcesses = (PSYSTEM_PROCESSES)(((LPBYTE)pProcesses) + pProcesses->NextEntryDelta);
}
if (pBuffer) HeapFree(GetProcessHeap(), NULL, pBuffer);
find_children(pm);
return 0;
}
// get a list of all running processes.
//
int procinfo_setup(PROC_MAP& pm) {
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(&osvi);
switch(osvi.dwPlatformId) {
case VER_PLATFORM_WIN32_WINDOWS:
// Win95, Win98, WinME
return 0; // not supported
case VER_PLATFORM_WIN32_NT:
return get_procinfo_XP(pm);
}
return 0;
}
|