-
Notifications
You must be signed in to change notification settings - Fork 2
/
syscall_windows.go
176 lines (161 loc) · 5.01 KB
/
syscall_windows.go
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//go:build windows
// +build windows
package comutil
import (
"syscall"
"unicode/utf16"
"unsafe"
"github.com/go-ole/go-ole"
"github.com/google/uuid"
)
var (
modole32, _ = syscall.LoadDLL("ole32.dll")
modoleaut32, _ = syscall.LoadDLL("oleaut32.dll")
modactiveds, _ = syscall.LoadDLL("activeds.dll")
)
var (
procCoCreateInstanceEx, _ = modole32.FindProc("CoCreateInstanceEx")
procIIDFromString, _ = modole32.FindProc("IIDFromString")
procSafeArrayCopy, _ = modoleaut32.FindProc("SafeArrayCopy")
procSafeArrayCreateVector, _ = modoleaut32.FindProc("SafeArrayCreateVector")
procSafeArrayGetElement, _ = modoleaut32.FindProc("SafeArrayGetElement")
procSafeArrayPutElement, _ = modoleaut32.FindProc("SafeArrayPutElement")
procSafeArrayGetDim, _ = modoleaut32.FindProc("SafeArrayGetDim")
procADsBuildVarArrayStr, _ = modactiveds.FindProc("ADsBuildVarArrayStr")
)
// CreateInstanceEx supports remote creation of multiple interfaces within one
// class.
//
// This is a low-level function. Use of the higher level object creation
// functions like CreateObject and CreateRemoteObject are recommended unless
// specific creation parameters are required.
//
// MSDN: https://msdn.microsoft.com/library/ms680701
func CreateInstanceEx(clsid uuid.UUID, context uint, serverInfo *CoServerInfo, results []MultiQI) (err error) {
var _p0 *MultiQI
if len(results) > 0 {
_p0 = &results[0]
}
hr, _, _ := procCoCreateInstanceEx.Call(
uintptr(unsafe.Pointer(GUID(clsid))),
0,
uintptr(context),
uintptr(unsafe.Pointer(serverInfo)),
uintptr(len(results)),
uintptr(unsafe.Pointer(_p0)))
if hr != 0 {
err = ole.NewError(hr)
}
return
}
// IIDFromString takes the given value and attempts to convert it into a valid
// GUID. If it fails it returns an error. It does not provide any additional
// validation, such as checking the Windows registry for its registration.
//
// It is safe to use this function to parse any GUID, not just COM interface
// identifiers.
//
// MSDN: https://msdn.microsoft.com/library/ms687262
// Raymond Chen: https://blogs.msdn.microsoft.com/oldnewthing/20151015-00/?p=91351
func IIDFromString(value string) (iid *ole.GUID, err error) {
bvalue := ole.SysAllocStringLen(value)
if bvalue == nil {
return nil, ole.NewError(ole.E_OUTOFMEMORY)
}
defer ole.SysFreeString(bvalue)
iid = new(ole.GUID)
hr, _, _ := procIIDFromString.Call(
uintptr(unsafe.Pointer(bvalue)),
uintptr(unsafe.Pointer(iid)))
if hr != 0 {
err = ole.NewError(hr)
}
return
}
// SafeArrayCopy returns a copy of the given SafeArray.
//
// AKA: SafeArrayCopy in Windows API.
func SafeArrayCopy(original *ole.SafeArray) (duplicate *ole.SafeArray, err error) {
hr, _, _ := procSafeArrayCopy.Call(
uintptr(unsafe.Pointer(original)),
uintptr(unsafe.Pointer(&duplicate)))
if hr != 0 {
err = ole.NewError(hr)
}
return
}
// SafeArrayCreateVector creates SafeArray.
//
// AKA: SafeArrayCreateVector in Windows API.
func SafeArrayCreateVector(variantType ole.VT, lowerBound int32, length uint32) (safearray *ole.SafeArray, err error) {
sa, _, err := procSafeArrayCreateVector.Call(
uintptr(variantType),
uintptr(lowerBound),
uintptr(length))
safearray = (*ole.SafeArray)(unsafe.Pointer(uintptr(sa)))
return
}
// SafeArrayGetElement stores the data element at the specified location in the
// array.
//
// AKA: SafeArrayGetElement in Windows API.
func SafeArrayGetElement(safearray *ole.SafeArray, index int32, element unsafe.Pointer) (err error) {
hr, _, _ := procSafeArrayGetElement.Call(
uintptr(unsafe.Pointer(safearray)),
uintptr(unsafe.Pointer(&index)),
uintptr(element))
if hr != 0 {
err = ole.NewError(hr)
}
return
}
// SafeArrayPutElement stores the data element at the specified location in the
// array.
//
// AKA: SafeArrayPutElement in Windows API.
func SafeArrayPutElement(safearray *ole.SafeArray, index int32, element unsafe.Pointer) (err error) {
hr, _, _ := procSafeArrayPutElement.Call(
uintptr(unsafe.Pointer(safearray)),
uintptr(unsafe.Pointer(&index)),
uintptr(element))
if hr != 0 {
err = ole.NewError(hr)
}
return
}
// SafeArrayGetDim returns the number of dimensions in the given safe array.
//
// AKA: SafeArrayGetDim in Windows API.
func SafeArrayGetDim(safearray *ole.SafeArray) (dimensions uint32, err error) {
d, _, err := procSafeArrayGetDim.Call(uintptr(unsafe.Pointer(safearray)))
dimensions = uint32(d)
return
}
// BuildVarArrayStr returns a variant array of strings with values populated
// by the given elements.
//
// AKA: ADsBuildVarArrayStr in Windows API.
func BuildVarArrayStr(elements ...string) (v *ole.VARIANT, err error) {
v = &ole.VARIANT{}
err = ole.VariantInit(v)
if err != nil {
return
}
var ptr **uint16
if len(elements) > 0 {
array := make([]*uint16, len(elements))
for i := range elements {
u := utf16.Encode([]rune(elements[i] + "\x00"))
array[i] = &u[0]
}
ptr = &array[0]
}
hr, _, _ := procADsBuildVarArrayStr.Call(
uintptr(unsafe.Pointer(ptr)),
uintptr(len(elements)),
uintptr(unsafe.Pointer(v)))
if hr != 0 {
err = ole.NewError(hr)
}
return
}