Reputation: 488
I'm trying to call procedure (without name) from a DLL using the ordinal value.
I can use this DLL in C#, setting the ordinal value to the property EntryPoint
of DllImport
.
... or you can identify the entry point by its ordinal. Ordinals are prefixed with the # sign, for example, #1. [...]
Example in C#:
[DllImport("dllname.dll", EntryPoint = "#3", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern int DeviceList(ref IntPtr hDeviceList);
When try find the procedure with "#" sign in Go, it shows the the following error:
Failed to find #3 procedure in dllname.dll: The specified procedure could not be found.
I used dumpbin
to show the information of the DLL, no function has a name:
Is there a way to find a procedure with its ordinal value (like C#)?
Upvotes: 1
Views: 1234
Reputation: 5582
There is a github issue here for this, but it seems not to have been merged as of Go 1.10.3 (the version I am using right now).
Anyway, the github issue links to a changeset with the respective function from which I extracted the code to do what you want here:
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetProcAddress = kernel32.NewProc("GetProcAddress")
)
// GetProcAddressByOrdinal retrieves the address of the exported
// function from module by ordinal.
func GetProcAddressByOrdinal(module syscall.Handle, ordinal uintptr) (uintptr, error) {
r0, _, _ := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0)
proc := uintptr(r0)
if proc == 0 {
return 0, syscall.EINVAL
}
return proc, nil
}
For completeness, here is the full example with which I tested this, using the Dependecy Walker I found that the first function in kernel32.dll is AcquireSRWLockExclusive
and using the new function it shows that the proc addresses really match.
package main
import (
"fmt"
"syscall"
)
func main() {
dll, err := syscall.LoadDLL("kernel32.dll")
check(err)
want, err := syscall.GetProcAddress(dll.Handle, "AcquireSRWLockExclusive")
check(err)
fmt.Println(want)
first, err := GetProcAddressByOrdinal(dll.Handle, 1)
check(err)
fmt.Println(first)
}
func check(err error) {
if err != nil {
panic(err)
}
}
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetProcAddress = kernel32.NewProc("GetProcAddress")
)
// GetProcAddressByOrdinal retrieves the address of the exported
// function from module by ordinal.
func GetProcAddressByOrdinal(module syscall.Handle, ordinal uintptr) (uintptr, error) {
r0, _, _ := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0)
proc := uintptr(r0)
if proc == 0 {
return 0, syscall.EINVAL
}
return proc, nil
}
Upvotes: 1