From 8dbc5d05d6edcc104950cc299a1ce6641235bc86 Mon Sep 17 00:00:00 2001 From: Hilko Bengen Date: Fri, 13 Oct 2017 15:31:29 +0200 Subject: [PATCH] windows: add GetProcAddressByOrdinal The current GetProcAddress implementation only resolves functions in DLLs by name. Add GetProcAddressByOrdinal that allows resolving functions by ordinal number, using the same GetProcAddress call from kernel32.dll in the background. This is particularly useful for some functions (e.g. IsOS from shlwapi.dll in some older versions of Windows) that cannot be found by name. Fixes golang/go#16507 Change-Id: Ib5fba7568c365a0aa2491c1261876b3a3929ec3d Reviewed-on: https://go-review.googlesource.com/70690 Reviewed-by: Alex Brainman Run-TryBot: Alex Brainman TryBot-Result: Gobot Gobot --- windows/syscall_test.go | 20 ++++++++++++++++++++ windows/syscall_windows.go | 15 +++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/windows/syscall_test.go b/windows/syscall_test.go index 62588b91..d7009e44 100644 --- a/windows/syscall_test.go +++ b/windows/syscall_test.go @@ -7,6 +7,7 @@ package windows_test import ( + "syscall" "testing" "golang.org/x/sys/windows" @@ -31,3 +32,22 @@ func TestEnv(t *testing.T) { // make sure TESTENV gets set to "", not deleted testSetGetenv(t, "TESTENV", "") } + +func TestGetProcAddressByOrdinal(t *testing.T) { + // Attempt calling shlwapi.dll:IsOS, resolving it by ordinal, as + // suggested in + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb773795.aspx + h, err := windows.LoadLibrary("shlwapi.dll") + if err != nil { + t.Fatalf("Failed to load shlwapi.dll: %s", err) + } + procIsOS, err := windows.GetProcAddressByOrdinal(h, 437) + if err != nil { + t.Fatalf("Could not find shlwapi.dll:IsOS by ordinal: %s", err) + } + const OS_NT = 1 + r, _, _ := syscall.Syscall(procIsOS, 1, OS_NT, 0, 0) + if r == 0 { + t.Error("shlwapi.dll:IsOS(OS_NT) returned 0, expected non-zero value") + } +} diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go index 9b5ed549..acd06e36 100644 --- a/windows/syscall_windows.go +++ b/windows/syscall_windows.go @@ -202,6 +202,21 @@ func NewCallbackCDecl(fn interface{}) uintptr { // syscall interface implementation for other packages +// GetProcAddressByOrdinal retrieves the address of the exported +// function from module by ordinal. +func GetProcAddressByOrdinal(module Handle, ordinal uintptr) (proc uintptr, err error) { + r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0) + proc = uintptr(r0) + if proc == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func Exit(code int) { ExitProcess(uint32(code)) } func makeInheritSa() *SecurityAttributes {