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?
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.