memmod: use resource functions from x/sys
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
497ba95de7
commit
4885e7c954
|
@ -16,7 +16,6 @@ import (
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/tun/wintun/memmod"
|
"golang.zx2c4.com/wireguard/tun/wintun/memmod"
|
||||||
"golang.zx2c4.com/wireguard/tun/wintun/resource"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type lazyDLL struct {
|
type lazyDLL struct {
|
||||||
|
@ -37,11 +36,11 @@ func (d *lazyDLL) Load() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ourModule windows.Handle = 0
|
const ourModule windows.Handle = 0
|
||||||
resInfo, err := resource.FindByName(ourModule, d.Name, resource.RT_RCDATA)
|
resInfo, err := windows.FindResource(ourModule, d.Name, windows.RT_RCDATA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to find \"%v\" RCDATA resource: %w", d.Name, err)
|
return fmt.Errorf("Unable to find \"%v\" RCDATA resource: %w", d.Name, err)
|
||||||
}
|
}
|
||||||
data, err := resource.Load(ourModule, resInfo)
|
data, err := windows.LoadResourceData(ourModule, resInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to load resource: %w", err)
|
return fmt.Errorf("Unable to load resource: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
/* SPDX-License-Identifier: MIT
|
|
||||||
*
|
|
||||||
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package resource
|
|
||||||
|
|
||||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go resource_windows.go
|
|
|
@ -1,143 +0,0 @@
|
||||||
/* SPDX-License-Identifier: MIT
|
|
||||||
*
|
|
||||||
* Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package resource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
func MAKEINTRESOURCE(i uint16) *uint16 {
|
|
||||||
return (*uint16)(unsafe.Pointer(uintptr(i)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Predefined Resource Types
|
|
||||||
var (
|
|
||||||
VS_VERSION_INFO uint16 = 1
|
|
||||||
|
|
||||||
RT_CURSOR = MAKEINTRESOURCE(1)
|
|
||||||
RT_BITMAP = MAKEINTRESOURCE(2)
|
|
||||||
RT_ICON = MAKEINTRESOURCE(3)
|
|
||||||
RT_MENU = MAKEINTRESOURCE(4)
|
|
||||||
RT_DIALOG = MAKEINTRESOURCE(5)
|
|
||||||
RT_STRING = MAKEINTRESOURCE(6)
|
|
||||||
RT_FONTDIR = MAKEINTRESOURCE(7)
|
|
||||||
RT_FONT = MAKEINTRESOURCE(8)
|
|
||||||
RT_ACCELERATOR = MAKEINTRESOURCE(9)
|
|
||||||
RT_RCDATA = MAKEINTRESOURCE(10)
|
|
||||||
RT_MESSAGETABLE = MAKEINTRESOURCE(11)
|
|
||||||
RT_GROUP_CURSOR = MAKEINTRESOURCE(12)
|
|
||||||
RT_GROUP_ICON = MAKEINTRESOURCE(14)
|
|
||||||
RT_VERSION = MAKEINTRESOURCE(16)
|
|
||||||
RT_DLGINCLUDE = MAKEINTRESOURCE(17)
|
|
||||||
RT_PLUGPLAY = MAKEINTRESOURCE(19)
|
|
||||||
RT_VXD = MAKEINTRESOURCE(20)
|
|
||||||
RT_ANICURSOR = MAKEINTRESOURCE(21)
|
|
||||||
RT_ANIICON = MAKEINTRESOURCE(22)
|
|
||||||
RT_HTML = MAKEINTRESOURCE(23)
|
|
||||||
RT_MANIFEST = MAKEINTRESOURCE(24)
|
|
||||||
CREATEPROCESS_MANIFEST_RESOURCE_ID = MAKEINTRESOURCE(1)
|
|
||||||
ISOLATIONAWARE_MANIFEST_RESOURCE_ID = MAKEINTRESOURCE(2)
|
|
||||||
ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID = MAKEINTRESOURCE(3)
|
|
||||||
ISOLATIONPOLICY_MANIFEST_RESOURCE_ID = MAKEINTRESOURCE(4)
|
|
||||||
ISOLATIONPOLICY_BROWSER_MANIFEST_RESOURCE_ID = MAKEINTRESOURCE(5)
|
|
||||||
MINIMUM_RESERVED_MANIFEST_RESOURCE_ID = MAKEINTRESOURCE(1 /*inclusive*/)
|
|
||||||
MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID = MAKEINTRESOURCE(16 /*inclusive*/)
|
|
||||||
)
|
|
||||||
|
|
||||||
//sys findResource(module windows.Handle, name *uint16, resType *uint16) (resInfo windows.Handle, err error) = kernel32.FindResourceW
|
|
||||||
|
|
||||||
func FindByID(module windows.Handle, id uint16, resType *uint16) (resInfo windows.Handle, err error) {
|
|
||||||
return findResource(module, MAKEINTRESOURCE(id), resType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FindByName(module windows.Handle, name string, resType *uint16) (resInfo windows.Handle, err error) {
|
|
||||||
var name16 *uint16
|
|
||||||
name16, err = windows.UTF16PtrFromString(name)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resInfo, err = findResource(module, name16, resType)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys sizeofResource(module windows.Handle, resInfo windows.Handle) (size uint32, err error) = kernel32.SizeofResource
|
|
||||||
//sys loadResource(module windows.Handle, resInfo windows.Handle) (resData windows.Handle, err error) = kernel32.LoadResource
|
|
||||||
//sys lockResource(resData windows.Handle) (addr uintptr, err error) = kernel32.LockResource
|
|
||||||
|
|
||||||
func Load(module, resInfo windows.Handle) (data []byte, err error) {
|
|
||||||
size, err := sizeofResource(module, resInfo)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("Unable to size resource: %w", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resData, err := loadResource(module, resInfo)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("Unable to load resource: %w", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ptr, err := lockResource(resData)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("Unable to lock resource: %w", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
unsafeSlice(unsafe.Pointer(&data), unsafe.Pointer(ptr), int(size))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type VS_FIXEDFILEINFO struct {
|
|
||||||
Signature uint32
|
|
||||||
StrucVersion uint32
|
|
||||||
FileVersionMS uint32
|
|
||||||
FileVersionLS uint32
|
|
||||||
ProductVersionMS uint32
|
|
||||||
ProductVersionLS uint32
|
|
||||||
FileFlagsMask uint32
|
|
||||||
FileFlags uint32
|
|
||||||
FileOS uint32
|
|
||||||
FileType uint32
|
|
||||||
FileSubtype uint32
|
|
||||||
FileDateMS uint32
|
|
||||||
FileDateLS uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys verQueryValue(block *byte, section *uint16, value **byte, size *uint32) (err error) = version.VerQueryValueW
|
|
||||||
|
|
||||||
func VerQueryRootValue(block []byte) (ffi *VS_FIXEDFILEINFO, err error) {
|
|
||||||
var data *byte
|
|
||||||
var size uint32
|
|
||||||
err = verQueryValue(&block[0], windows.StringToUTF16Ptr("\\"), &data, &size)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if uintptr(size) < unsafe.Sizeof(VS_FIXEDFILEINFO{}) {
|
|
||||||
err = errors.New("Incomplete VS_FIXEDFILEINFO")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ffi = (*VS_FIXEDFILEINFO)(unsafe.Pointer(data))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// unsafeSlice updates the slice slicePtr to be a slice
|
|
||||||
// referencing the provided data with its length & capacity set to
|
|
||||||
// lenCap.
|
|
||||||
//
|
|
||||||
// TODO: when Go 1.16 or Go 1.17 is the minimum supported version,
|
|
||||||
// update callers to use unsafe.Slice instead of this.
|
|
||||||
func unsafeSlice(slicePtr, data unsafe.Pointer, lenCap int) {
|
|
||||||
type sliceHeader struct {
|
|
||||||
Data unsafe.Pointer
|
|
||||||
Len int
|
|
||||||
Cap int
|
|
||||||
}
|
|
||||||
h := (*sliceHeader)(slicePtr)
|
|
||||||
h.Data = data
|
|
||||||
h.Len = lenCap
|
|
||||||
h.Cap = lenCap
|
|
||||||
}
|
|
|
@ -1,112 +0,0 @@
|
||||||
// Code generated by 'go generate'; DO NOT EDIT.
|
|
||||||
|
|
||||||
package resource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ unsafe.Pointer
|
|
||||||
|
|
||||||
// Do the interface allocations only once for common
|
|
||||||
// Errno values.
|
|
||||||
const (
|
|
||||||
errnoERROR_IO_PENDING = 997
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
|
||||||
)
|
|
||||||
|
|
||||||
// errnoErr returns common boxed Errno values, to prevent
|
|
||||||
// allocations at runtime.
|
|
||||||
func errnoErr(e syscall.Errno) error {
|
|
||||||
switch e {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case errnoERROR_IO_PENDING:
|
|
||||||
return errERROR_IO_PENDING
|
|
||||||
}
|
|
||||||
// TODO: add more here, after collecting data on the common
|
|
||||||
// error values see on Windows. (perhaps when running
|
|
||||||
// all.bat?)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
|
||||||
modversion = windows.NewLazySystemDLL("version.dll")
|
|
||||||
|
|
||||||
procFindResourceW = modkernel32.NewProc("FindResourceW")
|
|
||||||
procSizeofResource = modkernel32.NewProc("SizeofResource")
|
|
||||||
procLoadResource = modkernel32.NewProc("LoadResource")
|
|
||||||
procLockResource = modkernel32.NewProc("LockResource")
|
|
||||||
procVerQueryValueW = modversion.NewProc("VerQueryValueW")
|
|
||||||
)
|
|
||||||
|
|
||||||
func findResource(module windows.Handle, name *uint16, resType *uint16) (resInfo windows.Handle, err error) {
|
|
||||||
r0, _, e1 := syscall.Syscall(procFindResourceW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(resType)))
|
|
||||||
resInfo = windows.Handle(r0)
|
|
||||||
if resInfo == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func sizeofResource(module windows.Handle, resInfo windows.Handle) (size uint32, err error) {
|
|
||||||
r0, _, e1 := syscall.Syscall(procSizeofResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0)
|
|
||||||
size = uint32(r0)
|
|
||||||
if size == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadResource(module windows.Handle, resInfo windows.Handle) (resData windows.Handle, err error) {
|
|
||||||
r0, _, e1 := syscall.Syscall(procLoadResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0)
|
|
||||||
resData = windows.Handle(r0)
|
|
||||||
if resData == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func lockResource(resData windows.Handle) (addr uintptr, err error) {
|
|
||||||
r0, _, e1 := syscall.Syscall(procLockResource.Addr(), 1, uintptr(resData), 0, 0)
|
|
||||||
addr = uintptr(r0)
|
|
||||||
if addr == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func verQueryValue(block *byte, section *uint16, value **byte, size *uint32) (err error) {
|
|
||||||
r1, _, e1 := syscall.Syscall6(procVerQueryValueW.Addr(), 4, uintptr(unsafe.Pointer(block)), uintptr(unsafe.Pointer(section)), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(size)), 0, 0)
|
|
||||||
if r1 == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
Loading…
Reference in a new issue