|
|
@ -18,10 +18,11 @@ import (
|
|
|
|
"unicode/utf16"
|
|
|
|
"unicode/utf16"
|
|
|
|
"unsafe"
|
|
|
|
"unsafe"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"golang.org/x/sys/windows"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/shirou/gopsutil/v4/cpu"
|
|
|
|
"github.com/shirou/gopsutil/v4/cpu"
|
|
|
|
"github.com/shirou/gopsutil/v4/internal/common"
|
|
|
|
"github.com/shirou/gopsutil/v4/internal/common"
|
|
|
|
"github.com/shirou/gopsutil/v4/net"
|
|
|
|
"github.com/shirou/gopsutil/v4/net"
|
|
|
|
"golang.org/x/sys/windows"
|
|
|
|
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type Signal = syscall.Signal
|
|
|
|
type Signal = syscall.Signal
|
|
|
@ -245,7 +246,7 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
|
|
|
|
// inspired by https://gist.github.com/henkman/3083408
|
|
|
|
// inspired by https://gist.github.com/henkman/3083408
|
|
|
|
// and https://github.com/giampaolo/psutil/blob/1c3a15f637521ba5c0031283da39c733fda53e4c/psutil/arch/windows/process_info.c#L315-L329
|
|
|
|
// and https://github.com/giampaolo/psutil/blob/1c3a15f637521ba5c0031283da39c733fda53e4c/psutil/arch/windows/process_info.c#L315-L329
|
|
|
|
var ret []int32
|
|
|
|
var ret []int32
|
|
|
|
var read uint32 = 0
|
|
|
|
var read uint32
|
|
|
|
var psSize uint32 = 1024
|
|
|
|
var psSize uint32 = 1024
|
|
|
|
const dwordSize uint32 = 4
|
|
|
|
const dwordSize uint32 = 4
|
|
|
|
|
|
|
|
|
|
|
@ -288,10 +289,10 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
|
|
|
|
return false, err
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
h, err := windows.OpenProcess(windows.SYNCHRONIZE, false, uint32(pid))
|
|
|
|
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
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err == windows.ERROR_INVALID_PARAMETER {
|
|
|
|
if errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
|
|
|
|
return false, nil
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
@ -330,7 +331,7 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
|
|
|
|
|
|
|
|
|
|
|
|
exe, err := p.ExeWithContext(ctx)
|
|
|
|
exe, err := p.ExeWithContext(ctx)
|
|
|
|
if err != nil {
|
|
|
|
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
|
|
|
|
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) {
|
|
|
|
func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
|
|
|
|
cmdline, err := getProcessCommandLine(p.Pid)
|
|
|
|
cmdline, err := getProcessCommandLine(p.Pid)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("could not get CommandLine: %s", err)
|
|
|
|
return "", fmt.Errorf("could not get CommandLine: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return cmdline, nil
|
|
|
|
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) {
|
|
|
|
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
|
|
|
|
ru, err := getRusage(p.Pid)
|
|
|
|
ru, err := getRusage(p.Pid)
|
|
|
|
if err != nil {
|
|
|
|
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
|
|
|
|
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) {
|
|
|
|
func (p *Process) CwdWithContext(_ context.Context) (string, error) {
|
|
|
|
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(p.Pid))
|
|
|
|
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
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err != 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) {
|
|
|
|
func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
|
|
|
|
envVars, err := getProcessEnvironmentVariables(p.Pid, ctx)
|
|
|
|
envVars, err := getProcessEnvironmentVariables(ctx, p.Pid)
|
|
|
|
if err != nil {
|
|
|
|
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
|
|
|
|
return envVars, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -844,7 +845,7 @@ func (p *Process) setPpid(ppid int32) {
|
|
|
|
p.parent = ppid
|
|
|
|
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))
|
|
|
|
snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, uint32(pid))
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return 0, 0, "", err
|
|
|
|
return 0, 0, "", err
|
|
|
@ -872,7 +873,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
|
|
|
|
|
|
|
|
|
|
|
|
pids, err := PidsWithContext(ctx)
|
|
|
|
pids, err := PidsWithContext(ctx)
|
|
|
|
if err != nil {
|
|
|
|
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 {
|
|
|
|
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{})))
|
|
|
|
buf := readProcessMemory(syscall.Handle(handle), true, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock32{})))
|
|
|
|
if len(buf) != int(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]))
|
|
|
|
peb := (*processEnvironmentBlock32)(unsafe.Pointer(&buf[0]))
|
|
|
|
userProcessAddress := uint64(peb.ProcessParameters)
|
|
|
|
userProcessAddress := uint64(peb.ProcessParameters)
|
|
|
|
buf = readProcessMemory(syscall.Handle(handle), true, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters32{})))
|
|
|
|
buf = readProcessMemory(syscall.Handle(handle), true, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters32{})))
|
|
|
|
if len(buf) != int(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
|
|
|
|
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{})))
|
|
|
|
buf := readProcessMemory(syscall.Handle(handle), false, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock64{})))
|
|
|
|
if len(buf) != int(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]))
|
|
|
|
peb := (*processEnvironmentBlock64)(unsafe.Pointer(&buf[0]))
|
|
|
|
userProcessAddress := peb.ProcessParameters
|
|
|
|
userProcessAddress := peb.ProcessParameters
|
|
|
|
buf = readProcessMemory(syscall.Handle(handle), false, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters64{})))
|
|
|
|
buf = readProcessMemory(syscall.Handle(handle), false, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters64{})))
|
|
|
|
if len(buf) != int(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
|
|
|
|
return *(*rtlUserProcessParameters64)(unsafe.Pointer(&buf[0])), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1038,9 +1039,9 @@ func is32BitProcess(h windows.Handle) bool {
|
|
|
|
return procIs32Bits
|
|
|
|
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))
|
|
|
|
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
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
@ -1124,7 +1125,7 @@ func (p *processReader) Read(buf []byte) (int, error) {
|
|
|
|
|
|
|
|
|
|
|
|
func getProcessCommandLine(pid int32) (string, error) {
|
|
|
|
func getProcessCommandLine(pid int32) (string, error) {
|
|
|
|
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(pid))
|
|
|
|
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
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|