chore: enable golangci-lint on Windows and MacOS

Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
pull/1785/head
Matthieu MOREL 1 month ago
parent 90e59961ca
commit 9ce2ec161e

1
.gitattributes vendored

@ -0,0 +1 @@
*.go text eol=lf

@ -9,11 +9,15 @@ permissions:
jobs:
golangci:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
permissions:
contents: read # for actions/checkout to fetch code
pull-requests: read # for golangci/golangci-lint-action to fetch pull requests
name: lint
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

@ -6,11 +6,13 @@ package cpu
import (
"context"
"fmt"
"strconv"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/yusufpapurcu/wmi"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
)
var procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo")
@ -110,7 +112,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
cpu := InfoStat{
CPU: int32(i),
Family: fmt.Sprintf("%d", l.Family),
Family: strconv.FormatUint(uint64(l.Family), 10),
VendorID: l.Manufacturer,
ModelName: l.Name,
Cores: int32(l.NumberOfLogicalProcessors),

@ -222,7 +222,7 @@ func (i *ioCounters) getDriveStat(d uint32) (*IOCountersStat, error) {
defer i.ioObjectRelease(parent)
if !ioObjectConformsTo(parent, "IOBlockStorageDriver") {
//return nil, fmt.Errorf("ERROR: the object is not of the IOBlockStorageDriver class")
// return nil, fmt.Errorf("ERROR: the object is not of the IOBlockStorageDriver class")
return nil, nil
}

@ -6,13 +6,14 @@ package disk
import (
"bytes"
"context"
"fmt"
"errors"
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
"github.com/shirou/gopsutil/v4/internal/common"
)
var (
@ -202,11 +203,11 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
if typeret != windows.DRIVE_FIXED {
continue
}
szDevice := fmt.Sprintf(`\\.\%s`, path)
szDevice := `\\.\` + path
const IOCTL_DISK_PERFORMANCE = 0x70020
h, err := windows.CreateFile(syscall.StringToUTF16Ptr(szDevice), 0, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE, nil, windows.OPEN_EXISTING, 0, 0)
if err != nil {
if err == windows.ERROR_FILE_NOT_FOUND {
if errors.Is(err, windows.ERROR_FILE_NOT_FOUND) {
continue
}
return drivemap, err

@ -13,9 +13,10 @@ import (
"time"
"unsafe"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/shirou/gopsutil/v4/process"
"golang.org/x/sys/windows"
)
var (
@ -79,7 +80,7 @@ func HostIDWithContext(ctx context.Context) (string, error) {
hostID := windows.UTF16ToString(regBuf[:])
hostIDLen := len(hostID)
if hostIDLen != uuidLen {
return "", fmt.Errorf("HostID incorrect: %q\n", hostID)
return "", fmt.Errorf("HostID incorrect: %q\n", hostID) //nolint:revive //FIXME
}
return strings.ToLower(hostID), nil
@ -135,15 +136,15 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
return t, nil
}
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
platform, family, _, displayVersion, err := platformInformation(ctx)
func PlatformInformationWithContext(_ context.Context) (platform string, family string, version string, err error) {
platform, family, _, displayVersion, err := platformInformation()
if err != nil {
return "", "", "", err
}
return platform, family, displayVersion, nil
}
func platformInformation(ctx context.Context) (platform, family, version, displayVersion string, err error) {
func platformInformation() (platform, family, version, displayVersion string, err error) {
// GetVersionEx lies on Windows 8.1 and returns as Windows 8 if we don't declare compatibility in manifest
// RtlGetVersion bypasses this lying layer and returns the true Windows version
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-rtlgetversion
@ -152,26 +153,26 @@ func platformInformation(ctx context.Context) (platform, family, version, displa
osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo))
ret, _, err := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&osInfo)))
if ret != 0 {
return
return //nolint:nakedret //FIXME
}
// Platform
var h windows.Handle // like HostIDWithContext(), we query the registry using the raw windows.RegOpenKeyEx/RegQueryValueEx
err = windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Windows NT\CurrentVersion`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h)
if err != nil {
return
return //nolint:nakedret //FIXME
}
defer windows.RegCloseKey(h)
var bufLen uint32
var valType uint32
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, nil, &bufLen)
if err != nil {
return
return //nolint:nakedret //FIXME
}
regBuf := make([]uint16, bufLen/2+1)
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
if err != nil {
return
return //nolint:nakedret //FIXME
}
platform = windows.UTF16ToString(regBuf[:])
if strings.Contains(platform, "Windows 10") { // check build number to determine whether it's actually Windows 11
@ -243,8 +244,8 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, _, version, _, err := platformInformation(ctx)
func KernelVersionWithContext(_ context.Context) (string, error) {
_, _, version, _, err := platformInformation()
return version, err
}

@ -5,6 +5,7 @@ package common
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
@ -306,7 +307,7 @@ const (
func NewSMC(ioKit *Library) (*SMC, error) {
if ioKit.path != IOKit {
return nil, fmt.Errorf("library is not IOKit")
return nil, errors.New("library is not IOKit")
}
ioServiceGetMatchingService := GetFunc[IOServiceGetMatchingServiceFunc](ioKit, IOServiceGetMatchingServiceSym)
@ -324,7 +325,7 @@ func NewSMC(ioKit *Library) (*SMC, error) {
var conn uint32
if result := ioServiceOpen(service, machTaskSelf(), 0, &conn); result != 0 {
return nil, fmt.Errorf("ERROR: IOServiceOpen failed")
return nil, errors.New("ERROR: IOServiceOpen failed")
}
ioObjectRelease(service)
@ -343,7 +344,7 @@ func (s *SMC) Close() error {
ioServiceClose := GetFunc[IOServiceCloseFunc](s.lib, IOServiceCloseSym)
if result := ioServiceClose(s.conn); result != 0 {
return fmt.Errorf("ERROR: IOServiceClose failed")
return errors.New("ERROR: IOServiceClose failed")
}
return nil
}
@ -367,8 +368,8 @@ func (s CStr) Ptr() *byte {
return &s[0]
}
func (c CStr) Addr() uintptr {
return uintptr(unsafe.Pointer(c.Ptr()))
func (s CStr) Addr() uintptr {
return uintptr(unsafe.Pointer(s.Ptr()))
}
func (s CStr) GoString() string {

@ -273,19 +273,19 @@ type SystemExtendedHandleInformation struct {
// CallWithExpandingBuffer https://github.com/hillu/go-ntdll
func CallWithExpandingBuffer(fn func() NtStatus, buf *[]byte, resultLength *uint32) NtStatus {
for {
if st := fn(); st == STATUS_BUFFER_OVERFLOW || st == STATUS_BUFFER_TOO_SMALL || st == STATUS_INFO_LENGTH_MISMATCH {
st := fn()
if st == STATUS_BUFFER_OVERFLOW || st == STATUS_BUFFER_TOO_SMALL || st == STATUS_INFO_LENGTH_MISMATCH {
if int(*resultLength) <= cap(*buf) {
(*reflect.SliceHeader)(unsafe.Pointer(buf)).Len = int(*resultLength)
} else {
*buf = make([]byte, int(*resultLength))
}
continue
} else {
if !st.IsError() {
*buf = (*buf)[:int(*resultLength)]
}
return st
}
if !st.IsError() {
*buf = (*buf)[:int(*resultLength)]
}
return st
}
}

@ -14,9 +14,9 @@ import (
var (
loadErr error
loadAvg1M float64 = 0.0
loadAvg5M float64 = 0.0
loadAvg15M float64 = 0.0
loadAvg1M = 0.0
loadAvg5M = 0.0
loadAvg15M = 0.0
loadAvgMutex sync.RWMutex
loadAvgGoroutineOnce sync.Once
)
@ -27,10 +27,10 @@ var (
// code https://github.com/giampaolo/psutil/blob/8415355c8badc9c94418b19bdf26e622f06f0cce/psutil/arch/windows/wmi.c
func loadAvgGoroutine(ctx context.Context) {
var (
samplingFrequency time.Duration = 5 * time.Second
loadAvgFactor1M float64 = 1 / math.Exp(samplingFrequency.Seconds()/time.Minute.Seconds())
loadAvgFactor5M float64 = 1 / math.Exp(samplingFrequency.Seconds()/(5*time.Minute).Seconds())
loadAvgFactor15M float64 = 1 / math.Exp(samplingFrequency.Seconds()/(15*time.Minute).Seconds())
samplingFrequency = 5 * time.Second
loadAvgFactor1M = 1 / math.Exp(samplingFrequency.Seconds()/time.Minute.Seconds())
loadAvgFactor5M = 1 / math.Exp(samplingFrequency.Seconds()/(5*time.Minute).Seconds())
loadAvgFactor15M = 1 / math.Exp(samplingFrequency.Seconds()/(15*time.Minute).Seconds())
currentLoad float64
)

@ -9,39 +9,40 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestVirtualMemoryDarwin(t *testing.T) {
v, err := VirtualMemory()
assert.Nil(t, err)
require.NoError(t, err)
outBytes, err := invoke.Command("/usr/sbin/sysctl", "hw.memsize")
assert.Nil(t, err)
require.NoError(t, err)
outString := string(outBytes)
outString = strings.TrimSpace(outString)
outParts := strings.Split(outString, " ")
actualTotal, err := strconv.ParseInt(outParts[1], 10, 64)
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, uint64(actualTotal), v.Total)
assert.True(t, v.Available > 0)
assert.Positive(t, v.Available)
assert.Equal(t, v.Available, v.Free+v.Inactive, "%v", v)
assert.True(t, v.Used > 0)
assert.True(t, v.Used < v.Total)
assert.Positive(t, v.Used)
assert.Less(t, v.Used, v.Total)
assert.True(t, v.UsedPercent > 0)
assert.True(t, v.UsedPercent < 100)
assert.Positive(t, v.UsedPercent)
assert.Less(t, v.UsedPercent, 100.0)
assert.True(t, v.Free > 0)
assert.True(t, v.Free < v.Available)
assert.Positive(t, v.Free)
assert.Less(t, v.Free, v.Available)
assert.True(t, v.Active > 0)
assert.True(t, v.Active < v.Total)
assert.Positive(t, v.Active)
assert.Less(t, v.Active, v.Total)
assert.True(t, v.Inactive > 0)
assert.True(t, v.Inactive < v.Total)
assert.Positive(t, v.Inactive)
assert.Less(t, v.Inactive, v.Total)
assert.True(t, v.Wired > 0)
assert.True(t, v.Wired < v.Total)
assert.Positive(t, v.Wired)
assert.Less(t, v.Wired, v.Total)
}

@ -9,8 +9,9 @@ import (
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
)
var (

@ -30,14 +30,14 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
if columns[0] == "Name" {
err = errNetstatHeader
return
return //nolint:nakedret //FIXME
}
// try to extract the numeric value from <Link#123>
if subMatch := netstatLinkRegexp.FindStringSubmatch(columns[2]); len(subMatch) == 2 {
numericValue, err = strconv.ParseUint(subMatch[1], 10, 64)
if err != nil {
return
return //nolint:nakedret //FIXME
}
linkIDUint := uint(numericValue)
linkID = &linkIDUint
@ -51,7 +51,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
}
if numberColumns < 11 || numberColumns > 13 {
err = fmt.Errorf("Line %q do have an invalid number of columns %d", line, numberColumns)
return
return //nolint:nakedret //FIXME
}
parsed := make([]uint64, 0, 7)
@ -74,7 +74,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
}
if numericValue, err = strconv.ParseUint(target, 10, 64); err != nil {
return
return //nolint:nakedret //FIXME
}
parsed = append(parsed, numericValue)
}
@ -91,7 +91,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
if len(parsed) == 7 {
stat.Dropout = parsed[6]
}
return
return //nolint:nakedret //FIXME
}
type netstatInterface struct {

@ -137,5 +137,5 @@ func TestParseNetstatTruncated(t *testing.T) {
mapUsage := newMapInterfaceNameUsage(nsInterfaces)
assert.True(t, mapUsage.isTruncated())
assert.Equal(t, 3, len(mapUsage.notTruncated()), "en0, gif0 and stf0")
assert.Len(t, mapUsage.notTruncated(), 3, "en0, gif0 and stf0")
}

@ -5,14 +5,16 @@ package net
import (
"context"
"errors"
"fmt"
"net"
"os"
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
)
var (
@ -197,7 +199,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
return IOCounters(pernic)
return IOCounters(pernic) //nolint:contextcheck //FIXME
}
func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
@ -238,7 +240,7 @@ func getProcInet(kinds []netConnectionKindType, pid int32) ([]ConnectionStat, er
func getNetStatWithKind(kindType netConnectionKindType) ([]ConnectionStat, error) {
if kindType.filename == "" {
return nil, fmt.Errorf("kind filename must be required")
return nil, errors.New("kind filename must be required")
}
switch kindType.filename {
@ -360,7 +362,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
)
if family == 0 {
return nil, fmt.Errorf("faimly must be required")
return nil, errors.New("faimly must be required")
}
for {
@ -390,7 +392,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
if err == nil {
break
}
if err != windows.ERROR_INSUFFICIENT_BUFFER {
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
buf = make([]byte, size)
@ -441,7 +443,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
)
if family == 0 {
return nil, fmt.Errorf("faimly must be required")
return nil, errors.New("faimly must be required")
}
for {
@ -473,7 +475,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
if err == nil {
break
}
if err != windows.ERROR_INSUFFICIENT_BUFFER {
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
buf = make([]byte, size)

@ -7,6 +7,7 @@ import (
"bytes"
"context"
"encoding/binary"
"errors"
"fmt"
"path/filepath"
"runtime"
@ -348,7 +349,7 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
ret := procPidInfo(p.Pid, common.PROC_PIDVNODEPATHINFO, 0, uintptr(unsafe.Pointer(&vpi)), vpiSize)
errno, _ := lib.Dlsym("errno")
err = *(**unix.Errno)(unsafe.Pointer(&errno))
if err == unix.EPERM {
if errors.Is(err, unix.EPERM) {
return "", ErrorNotPermitted
}
@ -373,11 +374,11 @@ func procArgs(pid int32) ([]byte, int, error) {
return procargs, int(binary.LittleEndian.Uint32(nargs)), nil
}
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
return p.cmdlineSliceWithContext(ctx, true)
func (p *Process) CmdlineSliceWithContext(_ context.Context) ([]string, error) {
return p.cmdlineSlice()
}
func (p *Process) cmdlineSliceWithContext(ctx context.Context, fallback bool) ([]string, error) {
func (p *Process) cmdlineSlice() ([]string, error) {
pargs, nargs, err := procArgs(p.Pid)
if err != nil {
return nil, err
@ -408,8 +409,8 @@ func (p *Process) cmdlineSliceWithContext(ctx context.Context, fallback bool) ([
}
// cmdNameWithContext returns the command name (including spaces) without any arguments
func (p *Process) cmdNameWithContext(ctx context.Context) (string, error) {
r, err := p.cmdlineSliceWithContext(ctx, false)
func (p *Process) cmdNameWithContext(_ context.Context) (string, error) {
r, err := p.cmdlineSlice()
if err != nil {
return "", err
}

@ -18,10 +18,11 @@ import (
"unicode/utf16"
"unsafe"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/shirou/gopsutil/v4/net"
"golang.org/x/sys/windows"
)
type Signal = syscall.Signal
@ -245,7 +246,7 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
// inspired by https://gist.github.com/henkman/3083408
// and https://github.com/giampaolo/psutil/blob/1c3a15f637521ba5c0031283da39c733fda53e4c/psutil/arch/windows/process_info.c#L315-L329
var ret []int32
var read uint32 = 0
var read uint32
var psSize uint32 = 1024
const dwordSize uint32 = 4
@ -288,10 +289,10 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
return false, err
}
h, err := windows.OpenProcess(windows.SYNCHRONIZE, false, uint32(pid))
if err == windows.ERROR_ACCESS_DENIED {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
return true, nil
}
if err == windows.ERROR_INVALID_PARAMETER {
if errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return false, nil
}
if err != nil {
@ -330,7 +331,7 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
exe, err := p.ExeWithContext(ctx)
if err != nil {
return "", fmt.Errorf("could not get Name: %s", err)
return "", fmt.Errorf("could not get Name: %w", err)
}
return filepath.Base(exe), nil
@ -370,7 +371,7 @@ func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
cmdline, err := getProcessCommandLine(p.Pid)
if err != nil {
return "", fmt.Errorf("could not get CommandLine: %s", err)
return "", fmt.Errorf("could not get CommandLine: %w", err)
}
return cmdline, nil
}
@ -386,7 +387,7 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
ru, err := getRusage(p.Pid)
if err != nil {
return 0, fmt.Errorf("could not get CreationDate: %s", err)
return 0, fmt.Errorf("could not get CreationDate: %w", err)
}
return ru.CreationTime.Nanoseconds() / 1000000, nil
@ -394,7 +395,7 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
func (p *Process) CwdWithContext(_ context.Context) (string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(p.Pid))
if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return "", nil
}
if err != nil {
@ -822,9 +823,9 @@ func (p *Process) KillWithContext(ctx context.Context) error {
}
func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
envVars, err := getProcessEnvironmentVariables(p.Pid, ctx)
envVars, err := getProcessEnvironmentVariables(ctx, p.Pid)
if err != nil {
return nil, fmt.Errorf("could not get environment variables: %s", err)
return nil, fmt.Errorf("could not get environment variables: %w", err)
}
return envVars, nil
}
@ -844,7 +845,7 @@ func (p *Process) setPpid(ppid int32) {
p.parent = ppid
}
func getFromSnapProcess(pid int32) (int32, int32, string, error) {
func getFromSnapProcess(pid int32) (int32, int32, string, error) { //nolint:unparam //FIXME
snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, uint32(pid))
if err != nil {
return 0, 0, "", err
@ -872,7 +873,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
pids, err := PidsWithContext(ctx)
if err != nil {
return out, fmt.Errorf("could not get Processes %s", err)
return out, fmt.Errorf("could not get Processes %w", err)
}
for _, pid := range pids {
@ -963,13 +964,13 @@ func getUserProcessParams32(handle windows.Handle) (rtlUserProcessParameters32,
buf := readProcessMemory(syscall.Handle(handle), true, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock32{})))
if len(buf) != int(unsafe.Sizeof(processEnvironmentBlock32{})) {
return rtlUserProcessParameters32{}, fmt.Errorf("cannot read process PEB")
return rtlUserProcessParameters32{}, errors.New("cannot read process PEB")
}
peb := (*processEnvironmentBlock32)(unsafe.Pointer(&buf[0]))
userProcessAddress := uint64(peb.ProcessParameters)
buf = readProcessMemory(syscall.Handle(handle), true, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters32{})))
if len(buf) != int(unsafe.Sizeof(rtlUserProcessParameters32{})) {
return rtlUserProcessParameters32{}, fmt.Errorf("cannot read user process parameters")
return rtlUserProcessParameters32{}, errors.New("cannot read user process parameters")
}
return *(*rtlUserProcessParameters32)(unsafe.Pointer(&buf[0])), nil
}
@ -982,13 +983,13 @@ func getUserProcessParams64(handle windows.Handle) (rtlUserProcessParameters64,
buf := readProcessMemory(syscall.Handle(handle), false, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock64{})))
if len(buf) != int(unsafe.Sizeof(processEnvironmentBlock64{})) {
return rtlUserProcessParameters64{}, fmt.Errorf("cannot read process PEB")
return rtlUserProcessParameters64{}, errors.New("cannot read process PEB")
}
peb := (*processEnvironmentBlock64)(unsafe.Pointer(&buf[0]))
userProcessAddress := peb.ProcessParameters
buf = readProcessMemory(syscall.Handle(handle), false, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters64{})))
if len(buf) != int(unsafe.Sizeof(rtlUserProcessParameters64{})) {
return rtlUserProcessParameters64{}, fmt.Errorf("cannot read user process parameters")
return rtlUserProcessParameters64{}, errors.New("cannot read user process parameters")
}
return *(*rtlUserProcessParameters64)(unsafe.Pointer(&buf[0])), nil
}
@ -1038,9 +1039,9 @@ func is32BitProcess(h windows.Handle) bool {
return procIs32Bits
}
func getProcessEnvironmentVariables(pid int32, ctx context.Context) ([]string, error) {
func getProcessEnvironmentVariables(ctx context.Context, pid int32) ([]string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(pid))
if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return nil, nil
}
if err != nil {
@ -1124,7 +1125,7 @@ func (p *processReader) Read(buf []byte) (int, error) {
func getProcessCommandLine(pid int32) (string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(pid))
if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return "", nil
}
if err != nil {

@ -7,8 +7,9 @@ import (
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
)
type PROCESS_MEMORY_COUNTERS struct {
@ -38,26 +39,23 @@ func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, er
)
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return uint64(wow64), nil
} else {
return 0, windows.NTStatus(ret)
}
} else {
// we are on a 64-bit process reading an external 64-bit process
var info processBasicInformation64
return 0, windows.NTStatus(ret)
}
// we are on a 64-bit process reading an external 64-bit process
var info processBasicInformation64
ret, _, _ := common.ProcNtQueryInformationProcess.Call(
uintptr(procHandle),
uintptr(common.ProcessBasicInformation),
uintptr(unsafe.Pointer(&info)),
uintptr(unsafe.Sizeof(info)),
uintptr(0),
)
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return info.PebBaseAddress, nil
} else {
return 0, windows.NTStatus(ret)
}
ret, _, _ := common.ProcNtQueryInformationProcess.Call(
uintptr(procHandle),
uintptr(common.ProcessBasicInformation),
uintptr(unsafe.Pointer(&info)),
uintptr(unsafe.Sizeof(info)),
uintptr(0),
)
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return info.PebBaseAddress, nil
}
return 0, windows.NTStatus(ret)
}
func readProcessMemory(procHandle syscall.Handle, _ bool, address uint64, size uint) []byte {

@ -7,8 +7,9 @@ import (
"context"
"math"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/yusufpapurcu/wmi"
"github.com/shirou/gopsutil/v4/internal/common"
)
type msAcpi_ThermalZoneTemperature struct {

@ -5,6 +5,7 @@ package winservices
import (
"context"
"errors"
"unsafe"
"golang.org/x/sys/windows"
@ -86,7 +87,7 @@ func (s *Service) QueryStatusWithContext(ctx context.Context) (ServiceStatus, er
var bytesNeeded uint32
var buf []byte
if err := windows.QueryServiceStatusEx(s.srv.Handle, windows.SC_STATUS_PROCESS_INFO, nil, 0, &bytesNeeded); err != windows.ERROR_INSUFFICIENT_BUFFER {
if err := windows.QueryServiceStatusEx(s.srv.Handle, windows.SC_STATUS_PROCESS_INFO, nil, 0, &bytesNeeded); !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return ServiceStatus{}, err
}

Loading…
Cancel
Save