go - 如何使用其序数值从 DLL 中查找过程?

标签 go dll

我正在尝试使用序号值从 DLL 调用过程(没有名称)。

我可以在 C# 中使用此 DLL,将 序号值 设置为属性 EntryPointDllImport

... or you can identify the entry point by its ordinal. Ordinals are prefixed with the # sign, for example, #1. [...]

C# 示例:

[DllImport("dllname.dll", EntryPoint = "#3", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern int DeviceList(ref IntPtr hDeviceList);

在Go中尝试查找带有“#”符号的过程时,出现如下错误:

Failed to find #3 procedure in dllname.dll: The specified procedure could not be found.

我用了dumpbin显示DLL的信息,没有函数有名字:

dumpbin results

有没有一种方法可以找到具有其序数值的过程(如 C#)?

最佳答案

a github issue here为此,但从 Go 1.10.3(我现在使用的版本)开始,它似乎还没有被合并。

无论如何,github 问题链接到 a changeset with the respective function我从中提取了代码来执行您在这里想要执行的操作:

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
}

为了完整起见,这里是我测试它的完整示例,使用 Dependecy Walker 我发现 kernel32.dll 中的第一个函数是 AcquireSRWLockExclusive 并使用新函数它显示了 proc地址确实匹配。

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
}

关于go - 如何使用其序数值从 DLL 中查找过程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51507398/

相关文章:

c# - 网络摄像头、C# 和可靠的包装器

C# 在调用耗费大量内存的 native 代码 DLL (Delphi) 后内存不足

api - 我可以使用 Go lang 进行自动化测试而不是机器人框架测试吗?

go - 如何使用接口(interface)填充 slice ?

json - golang json 解码,请求体为空

c# - 在大型多解决方案应用程序中维护 .NET 项目依赖项和更新二进制文件的最佳方式

c++ - 编写库时是否应将可见性/导出宏应用于模板?

docker - 从 gRPC 服务器到 http 服务器的 http.Post() 在 docker-compose 设置上返回 EOF 错误

html - 无法从 html/template Golang 访问数据

c - 为什么 LIB 文件是具有这种口是心非性质的野兽?