windows_exporter/internal/headers/sysinfoapi/sysinfoapi.go
2024-10-03 20:23:56 +02:00

171 lines
5.6 KiB
Go

package sysinfoapi
import (
"unicode/utf16"
"unsafe"
"golang.org/x/sys/windows"
)
// MemoryStatusEx is a wrapper for MEMORYSTATUSEX
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-memorystatusex
type memoryStatusEx struct {
dwLength uint32
DwMemoryLoad uint32
UllTotalPhys uint64
UllAvailPhys uint64
UllTotalPageFile uint64
UllAvailPageFile uint64
UllTotalVirtual uint64
UllAvailVirtual uint64
UllAvailExtendedVirtual uint64
}
// MemoryStatus is an idiomatic wrapper for MemoryStatusEx.
type MemoryStatus struct {
MemoryLoad uint32
TotalPhys uint64
AvailPhys uint64
TotalPageFile uint64
AvailPageFile uint64
TotalVirtual uint64
AvailVirtual uint64
AvailExtendedVirtual uint64
}
// wProcessorArchitecture is a wrapper for the union found in LP_SYSTEM_INFO
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info
type wProcessorArchitecture struct {
WProcessorArchitecture uint16
WReserved uint16
}
// ProcessorArchitecture is an idiomatic wrapper for wProcessorArchitecture.
type ProcessorArchitecture uint16
// Idiomatic values for wProcessorArchitecture.
const (
AMD64 ProcessorArchitecture = 9
ARM ProcessorArchitecture = 5
ARM64 ProcessorArchitecture = 12
IA64 ProcessorArchitecture = 6
INTEL ProcessorArchitecture = 0
UNKNOWN ProcessorArchitecture = 0xffff
)
// LpSystemInfo is a wrapper for LPSYSTEM_INFO
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info
type lpSystemInfo struct {
Arch wProcessorArchitecture
DwPageSize uint32
LpMinimumApplicationAddress uintptr
LpMaximumApplicationAddress uintptr
DwActiveProcessorMask uint
DwNumberOfProcessors uint32
DwProcessorType uint32
DwAllocationGranularity uint32
WProcessorLevel uint16
WProcessorRevision uint16
}
// SystemInfo is an idiomatic wrapper for LpSystemInfo.
type SystemInfo struct {
Arch ProcessorArchitecture
PageSize uint32
MinimumApplicationAddress uintptr
MaximumApplicationAddress uintptr
ActiveProcessorMask uint
NumberOfProcessors uint32
ProcessorType uint32
AllocationGranularity uint32
ProcessorLevel uint16
ProcessorRevision uint16
}
// WinComputerNameFormat is a wrapper for COMPUTER_NAME_FORMAT.
type WinComputerNameFormat int
// Definitions for WinComputerNameFormat constants.
const (
ComputerNameNetBIOS WinComputerNameFormat = iota
ComputerNameDNSHostname
ComputerNameDNSDomain
ComputerNameDNSFullyQualified
ComputerNamePhysicalNetBIOS
ComputerNamePhysicalDNSHostname
ComputerNamePhysicalDNSDomain
ComputerNamePhysicalDNSFullyQualified
ComputerNameMax
)
var (
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
procGetSystemInfo = kernel32.NewProc("GetSystemInfo")
procGlobalMemoryStatusEx = kernel32.NewProc("GlobalMemoryStatusEx")
procGetComputerNameExW = kernel32.NewProc("GetComputerNameExW")
)
// GlobalMemoryStatusEx retrieves information about the system's current usage of both physical and virtual memory.
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex
func GlobalMemoryStatusEx() (MemoryStatus, error) {
var mse memoryStatusEx
mse.dwLength = (uint32)(unsafe.Sizeof(mse))
r1, _, err := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&mse)))
if ret := *(*bool)(unsafe.Pointer(&r1)); !ret {
return MemoryStatus{}, err
}
return MemoryStatus{
MemoryLoad: mse.DwMemoryLoad,
TotalPhys: mse.UllTotalPhys,
AvailPhys: mse.UllAvailPhys,
TotalPageFile: mse.UllTotalPageFile,
AvailPageFile: mse.UllAvailPageFile,
TotalVirtual: mse.UllTotalVirtual,
AvailVirtual: mse.UllAvailVirtual,
AvailExtendedVirtual: mse.UllAvailExtendedVirtual,
}, nil
}
// GetSystemInfo is an idiomatic wrapper for the GetSystemInfo function from sysinfoapi
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsysteminfo
func GetSystemInfo() SystemInfo {
var info lpSystemInfo
procGetSystemInfo.Call(uintptr(unsafe.Pointer(&info))) //nolint:errcheck
return SystemInfo{
Arch: ProcessorArchitecture(info.Arch.WProcessorArchitecture),
PageSize: info.DwPageSize,
MinimumApplicationAddress: info.LpMinimumApplicationAddress,
MaximumApplicationAddress: info.LpMinimumApplicationAddress,
ActiveProcessorMask: info.DwActiveProcessorMask,
NumberOfProcessors: info.DwNumberOfProcessors,
ProcessorType: info.DwProcessorType,
AllocationGranularity: info.DwAllocationGranularity,
ProcessorLevel: info.WProcessorLevel,
ProcessorRevision: info.WProcessorRevision,
}
}
// GetComputerName wraps the GetComputerNameW function in a more Go-like way
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getcomputernameexw
func GetComputerName(f WinComputerNameFormat) (string, error) {
// 1kb buffer to accept computer name. This should be more than enough as the maximum size
// returned is the max length of a DNS name, which this author believes is 253 characters.
size := 1024
var buffer [1024]uint16
r1, _, err := procGetComputerNameExW.Call(uintptr(f), uintptr(unsafe.Pointer(&buffer)), uintptr(unsafe.Pointer(&size)))
if r1 == 0 {
return "", err
}
bytes := buffer[0:size]
out := utf16.Decode(bytes)
return string(out), nil
}