mirror of
https://github.com/rwinkhart/sys.git
synced 2026-08-31 14:26:40 -04:00
windows: add QueryWorkingSetEx
This change adds the QueryWorkingSetEx function for inspecting the virtual memory details of pointers. https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-queryworkingsetex Change-Id: I2bc92bb0b65d34ed1caf88e4d368d64946dfcc5c GitHub-Last-Rev: c5ac00435245c4d6b83003949dd06014b52e59e0 GitHub-Pull-Request: golang/sys#124 Reviewed-on: https://go-review.googlesource.com/c/sys/+/402494 Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Alex Brainman <alex.brainman@gmail.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
committed by
Alex Brainman
parent
3c1f35247d
commit
1609e554cd
@@ -417,6 +417,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
|||||||
//sys GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) = psapi.GetModuleInformation
|
//sys GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) = psapi.GetModuleInformation
|
||||||
//sys GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) = psapi.GetModuleFileNameExW
|
//sys GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) = psapi.GetModuleFileNameExW
|
||||||
//sys GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) = psapi.GetModuleBaseNameW
|
//sys GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) = psapi.GetModuleBaseNameW
|
||||||
|
//sys QueryWorkingSetEx(process Handle, pv uintptr, cb uint32) (err error) = psapi.QueryWorkingSetEx
|
||||||
|
|
||||||
// NT Native APIs
|
// NT Native APIs
|
||||||
//sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb
|
//sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||||
@@ -1707,3 +1708,71 @@ func LoadResourceData(module, resInfo Handle) (data []byte, err error) {
|
|||||||
h.Cap = int(size)
|
h.Cap = int(size)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PSAPI_WORKING_SET_EX_BLOCK contains extended working set information for a page.
|
||||||
|
type PSAPI_WORKING_SET_EX_BLOCK uint64
|
||||||
|
|
||||||
|
// Valid returns the validity of this page.
|
||||||
|
// If this bit is 1, the subsequent members are valid; otherwise they should be ignored.
|
||||||
|
func (b PSAPI_WORKING_SET_EX_BLOCK) Valid() bool {
|
||||||
|
return (b & 1) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShareCount is the number of processes that share this page. The maximum value of this member is 7.
|
||||||
|
func (b PSAPI_WORKING_SET_EX_BLOCK) ShareCount() uint64 {
|
||||||
|
return b.intField(1, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Win32Protection is the memory protection attributes of the page. For a list of values, see
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants
|
||||||
|
func (b PSAPI_WORKING_SET_EX_BLOCK) Win32Protection() uint64 {
|
||||||
|
return b.intField(4, 11)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shared returns the shared status of this page.
|
||||||
|
// If this bit is 1, the page can be shared.
|
||||||
|
func (b PSAPI_WORKING_SET_EX_BLOCK) Shared() bool {
|
||||||
|
return (b & (1 << 15)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node is the NUMA node. The maximum value of this member is 63.
|
||||||
|
func (b PSAPI_WORKING_SET_EX_BLOCK) Node() uint64 {
|
||||||
|
return b.intField(16, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locked returns the locked status of this page.
|
||||||
|
// If this bit is 1, the virtual page is locked in physical memory.
|
||||||
|
func (b PSAPI_WORKING_SET_EX_BLOCK) Locked() bool {
|
||||||
|
return (b & (1 << 22)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// LargePage returns the large page status of this page.
|
||||||
|
// If this bit is 1, the page is a large page.
|
||||||
|
func (b PSAPI_WORKING_SET_EX_BLOCK) LargePage() bool {
|
||||||
|
return (b & (1 << 23)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bad returns the bad status of this page.
|
||||||
|
// If this bit is 1, the page is has been reported as bad.
|
||||||
|
func (b PSAPI_WORKING_SET_EX_BLOCK) Bad() bool {
|
||||||
|
return (b & (1 << 31)) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// intField extracts an integer field in the PSAPI_WORKING_SET_EX_BLOCK union.
|
||||||
|
func (b PSAPI_WORKING_SET_EX_BLOCK) intField(start, length int) uint64 {
|
||||||
|
var mask PSAPI_WORKING_SET_EX_BLOCK
|
||||||
|
for pos := start; pos < start+length; pos++ {
|
||||||
|
mask |= (1 << pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
masked := b & mask
|
||||||
|
return uint64(masked >> start)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSAPI_WORKING_SET_EX_INFORMATION contains extended working set information for a process.
|
||||||
|
type PSAPI_WORKING_SET_EX_INFORMATION struct {
|
||||||
|
// The virtual address.
|
||||||
|
VirtualAddress Pointer
|
||||||
|
// A PSAPI_WORKING_SET_EX_BLOCK union that indicates the attributes of the page at VirtualAddress.
|
||||||
|
VirtualAttributes PSAPI_WORKING_SET_EX_BLOCK
|
||||||
|
}
|
||||||
|
|||||||
@@ -777,6 +777,25 @@ func TestProcessModules(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestQueryWorkingSetEx(t *testing.T) {
|
||||||
|
var a int
|
||||||
|
|
||||||
|
process := windows.CurrentProcess()
|
||||||
|
information := windows.PSAPI_WORKING_SET_EX_INFORMATION{
|
||||||
|
VirtualAddress: windows.Pointer(unsafe.Pointer(&a)),
|
||||||
|
}
|
||||||
|
infos := []windows.PSAPI_WORKING_SET_EX_INFORMATION{information}
|
||||||
|
|
||||||
|
cb := uint32(uintptr(len(infos)) * unsafe.Sizeof(infos[0]))
|
||||||
|
if err := windows.QueryWorkingSetEx(process, uintptr(unsafe.Pointer(&infos[0])), cb); err != nil {
|
||||||
|
t.Fatalf("%+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !infos[0].VirtualAttributes.Valid() {
|
||||||
|
t.Errorf("memory location not valid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestReadWriteProcessMemory(t *testing.T) {
|
func TestReadWriteProcessMemory(t *testing.T) {
|
||||||
testBuffer := []byte{0xBA, 0xAD, 0xF0, 0x0D}
|
testBuffer := []byte{0xBA, 0xAD, 0xF0, 0x0D}
|
||||||
|
|
||||||
|
|||||||
@@ -408,6 +408,7 @@ var (
|
|||||||
procGetModuleBaseNameW = modpsapi.NewProc("GetModuleBaseNameW")
|
procGetModuleBaseNameW = modpsapi.NewProc("GetModuleBaseNameW")
|
||||||
procGetModuleFileNameExW = modpsapi.NewProc("GetModuleFileNameExW")
|
procGetModuleFileNameExW = modpsapi.NewProc("GetModuleFileNameExW")
|
||||||
procGetModuleInformation = modpsapi.NewProc("GetModuleInformation")
|
procGetModuleInformation = modpsapi.NewProc("GetModuleInformation")
|
||||||
|
procQueryWorkingSetEx = modpsapi.NewProc("QueryWorkingSetEx")
|
||||||
procSubscribeServiceChangeNotifications = modsechost.NewProc("SubscribeServiceChangeNotifications")
|
procSubscribeServiceChangeNotifications = modsechost.NewProc("SubscribeServiceChangeNotifications")
|
||||||
procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications")
|
procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications")
|
||||||
procGetUserNameExW = modsecur32.NewProc("GetUserNameExW")
|
procGetUserNameExW = modsecur32.NewProc("GetUserNameExW")
|
||||||
@@ -3504,6 +3505,14 @@ func GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func QueryWorkingSetEx(process Handle, pv uintptr, cb uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall(procQueryWorkingSetEx.Addr(), 3, uintptr(process), uintptr(pv), uintptr(cb))
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) {
|
func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) {
|
||||||
ret = procSubscribeServiceChangeNotifications.Find()
|
ret = procSubscribeServiceChangeNotifications.Find()
|
||||||
if ret != nil {
|
if ret != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user