зеркало из https://github.com/golang/sys.git
windows: add process module related syscalls
Add EnumProcessModules, EnumProcessModulesEx, GetModuleInformation, GetModuleFileNameEx and GetModuleBaseName.
https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocessmodules
https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocessmodulesex
https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmoduleinformation
https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmodulefilenameexw
https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmodulebasenamew
Change-Id: I75b062daec7a2cc9685e803dfa851825acee32b6
GitHub-Last-Rev: 7c208d6d3e
GitHub-Pull-Request: golang/sys#116
Reviewed-on: https://go-review.googlesource.com/c/sys/+/350870
Trust: Alex Brainman <alex.brainman@gmail.com>
Trust: Minux Ma <minux@golang.org>
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
Родитель
b8560ed6a9
Коммит
92d5a993a6
|
@ -398,6 +398,11 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
|||
|
||||
// Process Status API (PSAPI)
|
||||
//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
|
||||
//sys EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) = psapi.EnumProcessModules
|
||||
//sys EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) = psapi.EnumProcessModulesEx
|
||||
//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 GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) = psapi.GetModuleBaseNameW
|
||||
|
||||
// NT Native APIs
|
||||
//sys rtlNtStatusToDosErrorNoTeb(ntstatus NTStatus) (ret syscall.Errno) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||
|
|
|
@ -701,3 +701,79 @@ func TestWinVerifyTrust(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestProcessModules(t *testing.T) {
|
||||
process, err := windows.GetCurrentProcess()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get current process: %v", err)
|
||||
}
|
||||
// NB: Assume that we're always the first module. This technically isn't documented anywhere (that I could find), but seems to always hold.
|
||||
var module windows.Handle
|
||||
var cbNeeded uint32
|
||||
err = windows.EnumProcessModules(process, &module, uint32(unsafe.Sizeof(module)), &cbNeeded)
|
||||
if err != nil {
|
||||
t.Fatalf("EnumProcessModules failed: %v", err)
|
||||
}
|
||||
|
||||
var moduleEx windows.Handle
|
||||
err = windows.EnumProcessModulesEx(process, &moduleEx, uint32(unsafe.Sizeof(moduleEx)), &cbNeeded, windows.LIST_MODULES_DEFAULT)
|
||||
if err != nil {
|
||||
t.Fatalf("EnumProcessModulesEx failed: %v", err)
|
||||
}
|
||||
if module != moduleEx {
|
||||
t.Fatalf("module from EnumProcessModules does not match EnumProcessModulesEx: %v != %v", module, moduleEx)
|
||||
}
|
||||
|
||||
exePath, err := os.Executable()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get current executable path: %v", err)
|
||||
}
|
||||
|
||||
modulePathUTF16 := make([]uint16, len(exePath)+1)
|
||||
err = windows.GetModuleFileNameEx(process, module, &modulePathUTF16[0], uint32(len(modulePathUTF16)))
|
||||
if err != nil {
|
||||
t.Fatalf("GetModuleFileNameEx failed: %v", err)
|
||||
}
|
||||
|
||||
modulePath := windows.UTF16ToString(modulePathUTF16)
|
||||
if modulePath != exePath {
|
||||
t.Fatalf("module does not match executable for GetModuleFileNameEx: %s != %s", modulePath, exePath)
|
||||
}
|
||||
|
||||
err = windows.GetModuleBaseName(process, module, &modulePathUTF16[0], uint32(len(modulePathUTF16)))
|
||||
if err != nil {
|
||||
t.Fatalf("GetModuleBaseName failed: %v", err)
|
||||
}
|
||||
|
||||
modulePath = windows.UTF16ToString(modulePathUTF16)
|
||||
baseExePath := filepath.Base(exePath)
|
||||
if modulePath != baseExePath {
|
||||
t.Fatalf("module does not match executable for GetModuleBaseName: %s != %s", modulePath, baseExePath)
|
||||
}
|
||||
|
||||
var moduleInfo windows.ModuleInfo
|
||||
err = windows.GetModuleInformation(process, module, &moduleInfo, uint32(unsafe.Sizeof(moduleInfo)))
|
||||
if err != nil {
|
||||
t.Fatalf("GetModuleInformation failed: %v", err)
|
||||
}
|
||||
|
||||
peFile, err := pe.Open(exePath)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open current executable: %v", err)
|
||||
}
|
||||
defer peFile.Close()
|
||||
|
||||
var peSizeOfImage uint32
|
||||
switch runtime.GOARCH {
|
||||
case "amd64", "arm64":
|
||||
peSizeOfImage = peFile.OptionalHeader.(*pe.OptionalHeader64).SizeOfImage
|
||||
case "386", "arm":
|
||||
peSizeOfImage = peFile.OptionalHeader.(*pe.OptionalHeader32).SizeOfImage
|
||||
default:
|
||||
t.Fatalf("unable to test GetModuleInformation on arch %v", runtime.GOARCH)
|
||||
}
|
||||
|
||||
if moduleInfo.SizeOfImage != peSizeOfImage {
|
||||
t.Fatalf("module size does not match executable: %v != %v", moduleInfo.SizeOfImage, peSizeOfImage)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,6 +242,14 @@ const (
|
|||
TH32CS_INHERIT = 0x80000000
|
||||
)
|
||||
|
||||
const (
|
||||
// flags for EnumProcessModulesEx
|
||||
LIST_MODULES_32BIT = 0x01
|
||||
LIST_MODULES_64BIT = 0x02
|
||||
LIST_MODULES_ALL = 0x03
|
||||
LIST_MODULES_DEFAULT = 0x00
|
||||
)
|
||||
|
||||
const (
|
||||
// filters for ReadDirectoryChangesW and FindFirstChangeNotificationW
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME = 0x001
|
||||
|
@ -2773,3 +2781,9 @@ const (
|
|||
|
||||
// Flag for QueryFullProcessImageName.
|
||||
const PROCESS_NAME_NATIVE = 1
|
||||
|
||||
type ModuleInfo struct {
|
||||
BaseOfDll uintptr
|
||||
SizeOfImage uint32
|
||||
EntryPoint uintptr
|
||||
}
|
||||
|
|
|
@ -377,7 +377,12 @@ var (
|
|||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||
procCoUninitialize = modole32.NewProc("CoUninitialize")
|
||||
procStringFromGUID2 = modole32.NewProc("StringFromGUID2")
|
||||
procEnumProcessModules = modpsapi.NewProc("EnumProcessModules")
|
||||
procEnumProcessModulesEx = modpsapi.NewProc("EnumProcessModulesEx")
|
||||
procEnumProcesses = modpsapi.NewProc("EnumProcesses")
|
||||
procGetModuleBaseNameW = modpsapi.NewProc("GetModuleBaseNameW")
|
||||
procGetModuleFileNameExW = modpsapi.NewProc("GetModuleFileNameExW")
|
||||
procGetModuleInformation = modpsapi.NewProc("GetModuleInformation")
|
||||
procSubscribeServiceChangeNotifications = modsechost.NewProc("SubscribeServiceChangeNotifications")
|
||||
procUnsubscribeServiceChangeNotifications = modsechost.NewProc("UnsubscribeServiceChangeNotifications")
|
||||
procGetUserNameExW = modsecur32.NewProc("GetUserNameExW")
|
||||
|
@ -3225,6 +3230,22 @@ func stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) {
|
|||
return
|
||||
}
|
||||
|
||||
func EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procEnumProcessModules.Addr(), 4, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procEnumProcessModulesEx.Addr(), 5, uintptr(process), uintptr(unsafe.Pointer(module)), uintptr(cb), uintptr(unsafe.Pointer(cbNeeded)), uintptr(filterFlag), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) {
|
||||
var _p0 *uint32
|
||||
if len(processIds) > 0 {
|
||||
|
@ -3237,6 +3258,30 @@ func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func GetModuleBaseName(process Handle, module Handle, baseName *uint16, size uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetModuleBaseNameW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(baseName)), uintptr(size), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetModuleFileNameEx(process Handle, module Handle, filename *uint16, size uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetModuleFileNameExW.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetModuleInformation.Addr(), 4, uintptr(process), uintptr(module), uintptr(unsafe.Pointer(modinfo)), uintptr(cb), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) {
|
||||
ret = procSubscribeServiceChangeNotifications.Find()
|
||||
if ret != nil {
|
||||
|
|
Загрузка…
Ссылка в новой задаче