英文:
Pass structure with pointers to go memory in C code
问题
我相对于Go语言还比较新,正在学习如何操作本地API。这里有一个具体的例子,需要验证二进制文件是否已签名。为此,我想使用WinVerifyTrust Windows API。
问题是:
WinVerifyTrust提供了一个包含指向WINTRUST_FILE_INFO的指针的WINTRUST_DATA结构,而WINTRUST_FILE_INFO又包含了一个指向字符串的指针 =)
我们知道,在C或syscall中,禁止传递指向包含指向其他go内存的指针的内存的指针。
但我只是需要这样做。需要做些什么呢?
这里有一个包装上述函数的包:https://github.com/itchio/ox/blob/master/winox/verifytrust_windows.go,它们以一种被禁止的方式进行操作
winTrustData.FileOrCatalogOrBlobOrSgnrOrCert = uintptr(unsafe.Pointer(fileData))
trustErr := syscallex.WinVerifyTrust(syscall.Handle(0), &policyGUID, winTrustData)
在传递给syscall之前,不允许将uintptr存储到go对象的中间变量中
我想要做的是:
winTrustFileInfoMemory := C.malloc(unsafe.Sizeof(windows.WinTrustFileInfo{}))
if winTrustFileInfoMemory == nil {
return errors.New("out of memory")
}
defer C.free(winTrustFileInfoMemory)
winTrustFileInfo := (*windows.WinTrustFileInfo)(unsafe.Pointer(winTrustFileInfoMemory))
winTrustFileInfo.Size = uint32(unsafe.Sizeof(windows.WinTrustFileInfo{}))
....
winTrustData.FileOrCatalogOrBlobOrSgnrOrCert = unsafe.Pointer(winTrustFileInfoMemory)
但这看起来真的很丑陋,我们有没有办法可以固定内存或类似的方法?
英文:
I'm relatively new in Go and studying how to operate with native API. Here is a particular example, need to verify that binary file is signed. For that, I want to use WinVerifyTrust windows API.
The problem:
WinVerifyTrust supplies WINTRUST_DATA structure which contains a pointer to WINTRUST_FILE_INFO which in order contains a pointer to a string =)
As we know it is forbidden to pass a pointer to the memory which contains pointers to other go memory in C or syscall.
But I just need to do that. What needs to be done?
Here is a package which wraps function above https://github.com/itchio/ox/blob/master/winox/verifytrust_windows.go they do that in a forbidden way
winTrustData.FileOrCatalogOrBlobOrSgnrOrCert = uintptr(unsafe.Pointer(fileData))
trustErr := syscallex.WinVerifyTrust(syscall.Handle(0), &policyGUID, winTrustData)
it is not allowed to store uintptr to go object in the intermediate variable before passing to syscall
What I want to do os next:
winTrustFileInfoMemory := C.malloc(unsafe.Sizeof(windows.WinTrustFileInfo{}))
if winTrustFileInfoMemory == nil {
return errors.New("out of memory")
}
defer C.free(winTrustFileInfoMemory)
winTrustFileInfo := (*windows.WinTrustFileInfo)(unsafe.Pointer(winTrustFileInfoMemory))
winTrustFileInfo.Size = uint32(unsafe.Sizeof(windows.WinTrustFileInfo{}))
....
winTrustData.FileOrCatalogOrBlobOrSgnrOrCert = unsafe.Pointer(winTrustFileInfoMemory)
but it looks really ugly, do we have an ability to somehow pin the memory or something like it?
答案1
得分: 0
根据系统调用文档:
> 已弃用:此包已被锁定。调用者应改为使用 golang.org/x/sys 存储库中的相应包。
在你的情况下,相应的函数将是:
func WinVerifyTrustEx(hwnd HWND, actionId *GUID, data *WinTrustData) (ret error)
请注意函数名中的后缀“Ex”。在内部,它调用:
r0, _, _ := syscall.Syscall(procWinVerifyTrustEx.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(actionId)), uintptr(unsafe.Pointer(data)))
所以实际上,现在是由sys/windows
而不是你来打破指针规则。很抱歉没有更好的想法。
在此处查看更多信息。
英文:
Per the syscall docs:
> Deprecated: this package is locked down. Callers should use the
> corresponding package in the golang.org/x/sys repository instead.
In your case, the corresponding function would be
func WinVerifyTrustEx(hwnd HWND, actionId *GUID, data *WinTrustData) (ret error)
Note the trailing "Ex" in the function name. Internally, this calls:
r0, _, _ := syscall.Syscall(procWinVerifyTrustEx.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(actionId)), uintptr(unsafe.Pointer(data)))
So really, the pointer rule is now being broken by sys/windows
instead of you. Sorry there's no better idea.
see here for more.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论