//go:build windows // +build windows /* ** Zabbix ** Copyright (C) 2001-2023 Zabbix SIA ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ package win32 import ( "fmt" "syscall" "unsafe" "golang.org/x/sys/windows" ) var ( hKernel32 Hlib globalMemoryStatusEx uintptr getProcessIoCounters uintptr getProcessHandleCount uintptr getLogicalProcessorInformationEx uintptr getActiveProcessorGroupCount uintptr getDiskFreeSpaceW uintptr getVolumePathNameW uintptr getNativeSystemInfo uintptr ) const ( RelationProcessorCore = iota RelationNumaNode RelationCache RelationProcessorPackage RelationGroup RelationAll = 0xfff ) type SystemInfo struct { WProcessorArchitecture uint16 WReserved uint16 DWPageSize uint32 LPMinimumApplicationAddress *uint64 LPMaximumApplicationAddress *uint64 DWActiveProcessorMask *uint32 DWNumberOfProcessors uint32 DWProcessorType uint32 DWAllocationGranularity uint32 WProcessorLevel uint16 WProcessorRevision uint16 } func init() { var err error hKernel32 = mustLoadLibrary("kernel32.dll") globalMemoryStatusEx = hKernel32.mustGetProcAddress("GlobalMemoryStatusEx") getProcessIoCounters = hKernel32.mustGetProcAddress("GetProcessIoCounters") getLogicalProcessorInformationEx = hKernel32.mustGetProcAddress("GetLogicalProcessorInformationEx") getActiveProcessorGroupCount = hKernel32.mustGetProcAddress("GetActiveProcessorGroupCount") getDiskFreeSpaceW = hKernel32.mustGetProcAddress("GetDiskFreeSpaceW") getVolumePathNameW = hKernel32.mustGetProcAddress("GetVolumePathNameW") getProcessHandleCount = hKernel32.mustGetProcAddress("GetProcessHandleCount") getNativeSystemInfo, err = hKernel32.getProcAddress("GetNativeSystemInfo") if err != nil { getNativeSystemInfo = hKernel32.mustGetProcAddress("GetSystemInfo") } } func GlobalMemoryStatusEx() (m *MEMORYSTATUSEX, err error) { m = &MEMORYSTATUSEX{} m.Length = uint32(unsafe.Sizeof(*m)) ret, _, syserr := syscall.Syscall(globalMemoryStatusEx, 1, uintptr(unsafe.Pointer(m)), 0, 0) if ret == 0 { return nil, syserr } return } func GetProcessIoCounters(proc syscall.Handle) (ioc *IO_COUNTERS, err error) { ioc = &IO_COUNTERS{} ret, _, syserr := syscall.Syscall(getProcessIoCounters, 2, uintptr(proc), uintptr(unsafe.Pointer(ioc)), 0) if ret == 0 { return nil, syserr } return } func GetProcessHandleCount(proc syscall.Handle) (pdwHandleCount int32, err error) { var count int32 ret, _, syserr := syscall.Syscall(getProcessHandleCount, 2, uintptr(proc), uintptr(unsafe.Pointer(&count)), 0) if ret == 0 { return count, syserr } return count, nil } func GetLogicalProcessorInformationEx(relation int, info []byte) (size uint32, err error) { var buffer uintptr if info != nil { size = uint32(len(info)) buffer = uintptr(unsafe.Pointer(&info[0])) } ret, _, syserr := syscall.Syscall(getLogicalProcessorInformationEx, 3, uintptr(relation), buffer, uintptr(unsafe.Pointer(&size))) if ret == 0 { if syscall.Errno(syserr) != syscall.ERROR_INSUFFICIENT_BUFFER { return 0, syserr } } return } func GetActiveProcessorGroupCount() (count int) { ret, _, _ := syscall.Syscall(getActiveProcessorGroupCount, 0, 0, 0, 0) return int(ret) } func GetFullPathName(path string) (string, uint32, error) { var wPath []uint16 wPath, err := windows.UTF16FromString(path) if err != nil { return "", 0, err } buf := make([]uint16, windows.MAX_PATH) len, err := syscall.GetFullPathName(&wPath[0], windows.MAX_PATH, &buf[0], nil) if err != nil { return "", 0, err } return syscall.UTF16ToString(buf), len, nil } func GetVolumePathName(path string, len uint32) (disk string, err error) { var wPath []uint16 wPath, err = windows.UTF16FromString(path) if err != nil { return } wdisk := make([]uint16, len) ret, _, err := syscall.Syscall( getVolumePathNameW, 3, uintptr(unsafe.Pointer(&wPath)), uintptr(unsafe.Pointer(&wdisk[0])), uintptr(unsafe.Pointer(&len)), ) if ret == 0 { return "", fmt.Errorf("failed to get volume name for path %s, %s", path, err.Error()) } return syscall.UTF16ToString(wdisk), nil } func GetDiskFreeSpace(path string) (c CLUSTER, err error) { var p []uint16 p, err = windows.UTF16FromString(path) if err != nil { return } ptrPath := uintptr(unsafe.Pointer(&p[0])) var ret uintptr ret, _, err = syscall.Syscall6( getDiskFreeSpaceW, 6, ptrPath, uintptr(unsafe.Pointer(&c.LpSectorsPerCluster)), uintptr(unsafe.Pointer(&c.LpBytesPerSector)), uintptr(unsafe.Pointer(&c.LpNumberOfFreeClusters)), uintptr(unsafe.Pointer(&c.LpTotalNumberOfClusters)), 0) if ret == 0 { return c, fmt.Errorf("failed to get disk free space for path :%s, %s", path, err.Error()) } return c, nil } func GetNativeSystemInfo() (sysInfo SystemInfo) { syscall.Syscall(getNativeSystemInfo, 1, uintptr(unsafe.Pointer(&sysInfo)), 0, 0) return sysInfo }