#include "extensions/browser/api/system_cpu/cpu_info_provider.h"
#include <windows.h>
#include <winternl.h>
#include <memory>
#include "base/containers/heap_array.h"
#include "base/system/sys_info.h"
namespace extensions {
namespace {
const wchar_t kNtdll[] = L"ntdll.dll";
const char kNtQuerySystemInformationName[] = "NtQuerySystemInformation";
typedef DWORD(WINAPI* NtQuerySystemInformationPF)(DWORD system_info_class,
PVOID system_info,
ULONG system_info_length,
PULONG return_length);
}
bool CpuInfoProvider::QueryCpuTimePerProcessor(
std::vector<api::system_cpu::ProcessorInfo>* infos) {
DCHECK(infos);
HMODULE ntdll = GetModuleHandle(kNtdll);
CHECK(ntdll != NULL);
NtQuerySystemInformationPF NtQuerySystemInformation =
reinterpret_cast<NtQuerySystemInformationPF>(
::GetProcAddress(ntdll, kNtQuerySystemInformationName));
CHECK(NtQuerySystemInformation != NULL);
int num_of_processors = base::SysInfo::NumberOfProcessors();
auto processor_info =
base::HeapArray<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION>::Uninit(
num_of_processors);
ULONG returned_bytes = 0,
bytes = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) *
num_of_processors;
if (!NT_SUCCESS(NtQuerySystemInformation(
SystemProcessorPerformanceInformation, processor_info.data(), bytes,
&returned_bytes))) {
return false;
}
int returned_num_of_processors =
returned_bytes / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
if (returned_num_of_processors != num_of_processors) {
return false;
}
DCHECK_EQ(num_of_processors, static_cast<int>(infos->size()));
for (size_t i = 0; i < processor_info.size(); ++i) {
double kernel = static_cast<double>(processor_info[i].KernelTime.QuadPart),
user = static_cast<double>(processor_info[i].UserTime.QuadPart),
idle = static_cast<double>(processor_info[i].IdleTime.QuadPart);
infos->at(i).usage.kernel = kernel - idle;
infos->at(i).usage.user = user;
infos->at(i).usage.idle = idle;
infos->at(i).usage.total = kernel + user;
}
return true;
}
}