1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
/* 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
}
|