From 01cf95a92d692ca5b14ce3a1c0335d9ea70f9c30 Mon Sep 17 00:00:00 2001 From: Lomanic <5020919+Lomanic@users.noreply.github.com> Date: Wed, 5 Jan 2022 01:02:27 +0100 Subject: [PATCH] [process][windows] Fix #1216 fix compilation on arm/arm64 go build ./... with GOARCH=arm64 is otherwise failing with the following: process\process_windows.go:412:11: undefined: readProcessMemory process\process_windows.go:425:11: undefined: readProcessMemory process\process_windows.go:896:32: undefined: PROCESS_MEMORY_COUNTERS process\process_windows.go:897:10: undefined: PROCESS_MEMORY_COUNTERS process\process_windows.go:910:50: undefined: PROCESS_MEMORY_COUNTERS process\process_windows.go:950:21: undefined: queryPebAddress process\process_windows.go:955:9: undefined: readProcessMemory process\process_windows.go:961:8: undefined: readProcessMemory process\process_windows.go:969:21: undefined: queryPebAddress process\process_windows.go:974:9: undefined: readProcessMemory process\process_windows.go:974:9: too many errors --- process/process_windows_32bit.go | 109 +++++++++++++++++++++++++++++++++++++++ process/process_windows_386.go | 109 --------------------------------------- process/process_windows_64bit.go | 79 ++++++++++++++++++++++++++++ process/process_windows_amd64.go | 79 ---------------------------- 4 files changed, 188 insertions(+), 188 deletions(-) create mode 100644 process/process_windows_32bit.go delete mode 100644 process/process_windows_386.go create mode 100644 process/process_windows_64bit.go delete mode 100644 process/process_windows_amd64.go diff --git a/process/process_windows_32bit.go b/process/process_windows_32bit.go new file mode 100644 index 0000000..982287d --- /dev/null +++ b/process/process_windows_32bit.go @@ -0,0 +1,109 @@ +//go:build (windows && 386) || (windows && arm) +// +build windows,386 windows,arm + +package process + +import ( + "errors" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" + + "github.com/shirou/gopsutil/v3/internal/common" +) + +type PROCESS_MEMORY_COUNTERS struct { + CB uint32 + PageFaultCount uint32 + PeakWorkingSetSize uint32 + WorkingSetSize uint32 + QuotaPeakPagedPoolUsage uint32 + QuotaPagedPoolUsage uint32 + QuotaPeakNonPagedPoolUsage uint32 + QuotaNonPagedPoolUsage uint32 + PagefileUsage uint32 + PeakPagefileUsage uint32 +} + +func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, error) { + if is32BitProcess { + // we are on a 32-bit process reading an external 32-bit process + var info processBasicInformation32 + + 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 uint64(info.PebBaseAddress), nil + } else { + return 0, windows.NTStatus(ret) + } + } else { + // we are on a 32-bit process reading an external 64-bit process + if common.ProcNtWow64QueryInformationProcess64.Find() == nil { // avoid panic + var info processBasicInformation64 + + ret, _, _ := common.ProcNtWow64QueryInformationProcess64.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) + } + } else { + return 0, errors.New("can't find API to query 64 bit process from 32 bit") + } + } +} + +func readProcessMemory(h syscall.Handle, is32BitProcess bool, address uint64, size uint) []byte { + if is32BitProcess { + var read uint + + buffer := make([]byte, size) + + ret, _, _ := common.ProcNtReadVirtualMemory.Call( + uintptr(h), + uintptr(address), + uintptr(unsafe.Pointer(&buffer[0])), + uintptr(size), + uintptr(unsafe.Pointer(&read)), + ) + if int(ret) >= 0 && read > 0 { + return buffer[:read] + } + } else { + // reading a 64-bit process from a 32-bit one + if common.ProcNtWow64ReadVirtualMemory64.Find() == nil { // avoid panic + var read uint64 + + buffer := make([]byte, size) + + ret, _, _ := common.ProcNtWow64ReadVirtualMemory64.Call( + uintptr(h), + uintptr(address&0xFFFFFFFF), // the call expects a 64-bit value + uintptr(address>>32), + uintptr(unsafe.Pointer(&buffer[0])), + uintptr(size), // the call expects a 64-bit value + uintptr(0), // but size is 32-bit so pass zero as the high dword + uintptr(unsafe.Pointer(&read)), + ) + if int(ret) >= 0 && read > 0 { + return buffer[:uint(read)] + } + } + } + + // if we reach here, an error happened + return nil +} diff --git a/process/process_windows_386.go b/process/process_windows_386.go deleted file mode 100644 index 982287d..0000000 --- a/process/process_windows_386.go +++ /dev/null @@ -1,109 +0,0 @@ -//go:build (windows && 386) || (windows && arm) -// +build windows,386 windows,arm - -package process - -import ( - "errors" - "syscall" - "unsafe" - - "golang.org/x/sys/windows" - - "github.com/shirou/gopsutil/v3/internal/common" -) - -type PROCESS_MEMORY_COUNTERS struct { - CB uint32 - PageFaultCount uint32 - PeakWorkingSetSize uint32 - WorkingSetSize uint32 - QuotaPeakPagedPoolUsage uint32 - QuotaPagedPoolUsage uint32 - QuotaPeakNonPagedPoolUsage uint32 - QuotaNonPagedPoolUsage uint32 - PagefileUsage uint32 - PeakPagefileUsage uint32 -} - -func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, error) { - if is32BitProcess { - // we are on a 32-bit process reading an external 32-bit process - var info processBasicInformation32 - - 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 uint64(info.PebBaseAddress), nil - } else { - return 0, windows.NTStatus(ret) - } - } else { - // we are on a 32-bit process reading an external 64-bit process - if common.ProcNtWow64QueryInformationProcess64.Find() == nil { // avoid panic - var info processBasicInformation64 - - ret, _, _ := common.ProcNtWow64QueryInformationProcess64.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) - } - } else { - return 0, errors.New("can't find API to query 64 bit process from 32 bit") - } - } -} - -func readProcessMemory(h syscall.Handle, is32BitProcess bool, address uint64, size uint) []byte { - if is32BitProcess { - var read uint - - buffer := make([]byte, size) - - ret, _, _ := common.ProcNtReadVirtualMemory.Call( - uintptr(h), - uintptr(address), - uintptr(unsafe.Pointer(&buffer[0])), - uintptr(size), - uintptr(unsafe.Pointer(&read)), - ) - if int(ret) >= 0 && read > 0 { - return buffer[:read] - } - } else { - // reading a 64-bit process from a 32-bit one - if common.ProcNtWow64ReadVirtualMemory64.Find() == nil { // avoid panic - var read uint64 - - buffer := make([]byte, size) - - ret, _, _ := common.ProcNtWow64ReadVirtualMemory64.Call( - uintptr(h), - uintptr(address&0xFFFFFFFF), // the call expects a 64-bit value - uintptr(address>>32), - uintptr(unsafe.Pointer(&buffer[0])), - uintptr(size), // the call expects a 64-bit value - uintptr(0), // but size is 32-bit so pass zero as the high dword - uintptr(unsafe.Pointer(&read)), - ) - if int(ret) >= 0 && read > 0 { - return buffer[:uint(read)] - } - } - } - - // if we reach here, an error happened - return nil -} diff --git a/process/process_windows_64bit.go b/process/process_windows_64bit.go new file mode 100644 index 0000000..74c6212 --- /dev/null +++ b/process/process_windows_64bit.go @@ -0,0 +1,79 @@ +//go:build (windows && amd64) || (windows && arm64) +// +build windows,amd64 windows,arm64 + +package process + +import ( + "syscall" + "unsafe" + + "github.com/shirou/gopsutil/v3/internal/common" + "golang.org/x/sys/windows" +) + +type PROCESS_MEMORY_COUNTERS struct { + CB uint32 + PageFaultCount uint32 + PeakWorkingSetSize uint64 + WorkingSetSize uint64 + QuotaPeakPagedPoolUsage uint64 + QuotaPagedPoolUsage uint64 + QuotaPeakNonPagedPoolUsage uint64 + QuotaNonPagedPoolUsage uint64 + PagefileUsage uint64 + PeakPagefileUsage uint64 +} + +func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, error) { + if is32BitProcess { + // we are on a 64-bit process reading an external 32-bit process + var wow64 uint + + ret, _, _ := common.ProcNtQueryInformationProcess.Call( + uintptr(procHandle), + uintptr(common.ProcessWow64Information), + uintptr(unsafe.Pointer(&wow64)), + uintptr(unsafe.Sizeof(wow64)), + uintptr(0), + ) + 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 + + 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) + } + } +} + +func readProcessMemory(procHandle syscall.Handle, _ bool, address uint64, size uint) []byte { + var read uint + + buffer := make([]byte, size) + + ret, _, _ := common.ProcNtReadVirtualMemory.Call( + uintptr(procHandle), + uintptr(address), + uintptr(unsafe.Pointer(&buffer[0])), + uintptr(size), + uintptr(unsafe.Pointer(&read)), + ) + if int(ret) >= 0 && read > 0 { + return buffer[:read] + } + return nil +} diff --git a/process/process_windows_amd64.go b/process/process_windows_amd64.go deleted file mode 100644 index 74c6212..0000000 --- a/process/process_windows_amd64.go +++ /dev/null @@ -1,79 +0,0 @@ -//go:build (windows && amd64) || (windows && arm64) -// +build windows,amd64 windows,arm64 - -package process - -import ( - "syscall" - "unsafe" - - "github.com/shirou/gopsutil/v3/internal/common" - "golang.org/x/sys/windows" -) - -type PROCESS_MEMORY_COUNTERS struct { - CB uint32 - PageFaultCount uint32 - PeakWorkingSetSize uint64 - WorkingSetSize uint64 - QuotaPeakPagedPoolUsage uint64 - QuotaPagedPoolUsage uint64 - QuotaPeakNonPagedPoolUsage uint64 - QuotaNonPagedPoolUsage uint64 - PagefileUsage uint64 - PeakPagefileUsage uint64 -} - -func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, error) { - if is32BitProcess { - // we are on a 64-bit process reading an external 32-bit process - var wow64 uint - - ret, _, _ := common.ProcNtQueryInformationProcess.Call( - uintptr(procHandle), - uintptr(common.ProcessWow64Information), - uintptr(unsafe.Pointer(&wow64)), - uintptr(unsafe.Sizeof(wow64)), - uintptr(0), - ) - 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 - - 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) - } - } -} - -func readProcessMemory(procHandle syscall.Handle, _ bool, address uint64, size uint) []byte { - var read uint - - buffer := make([]byte, size) - - ret, _, _ := common.ProcNtReadVirtualMemory.Call( - uintptr(procHandle), - uintptr(address), - uintptr(unsafe.Pointer(&buffer[0])), - uintptr(size), - uintptr(unsafe.Pointer(&read)), - ) - if int(ret) >= 0 && read > 0 { - return buffer[:read] - } - return nil -}