forked from ropnop/go-clr
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathicorruntimehost.go
231 lines (215 loc) · 8.27 KB
/
icorruntimehost.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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// +build windows
package clr
import (
"fmt"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type ICORRuntimeHost struct {
vtbl *ICORRuntimeHostVtbl
}
// ICORRuntimeHostVtbl Provides methods that enable the host to start and stop the common language runtime (CLR)
// explicitly, to create and configure application domains, to access the default domain, and to enumerate all
// domains running in the process.
// https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/icorruntimehost-interface
type ICORRuntimeHostVtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
// CreateLogicalThreadState Do not use.
CreateLogicalThreadState uintptr
// DeleteLogicalThreadSate Do not use.
DeleteLogicalThreadState uintptr
// SwitchInLogicalThreadState Do not use.
SwitchInLogicalThreadState uintptr
// SwitchOutLogicalThreadState Do not use.
SwitchOutLogicalThreadState uintptr
// LocksHeldByLogicalThreadState Do not use.
LocksHeldByLogicalThreadState uintptr
// MapFile Maps the specified file into memory. This method is obsolete.
MapFile uintptr
// GetConfiguration Gets an object that allows the host to specify the callback configuration of the CLR.
GetConfiguration uintptr
// Start Starts the CLR.
Start uintptr
// Stop Stops the execution of code in the runtime for the current process.
Stop uintptr
// CreateDomain Creates an application domain. The caller receives an interface pointer of
// type _AppDomain to an instance of type System.AppDomain.
CreateDomain uintptr
// GetDefaultDomain Gets an interface pointer of type _AppDomain that represents the default domain for the current process.
GetDefaultDomain uintptr
// EnumDomains Gets an enumerator for the domains in the current process.
EnumDomains uintptr
// NextDomain Gets an interface pointer to the next domain in the enumeration.
NextDomain uintptr
// CloseEnum Resets a domain enumerator back to the beginning of the domain list.
CloseEnum uintptr
// CreateDomainEx Creates an application domain. This method allows the caller to pass an
// IAppDomainSetup instance to configure additional features of the returned _AppDomain instance.
CreateDomainEx uintptr
// CreateDomainSetup Gets an interface pointer of type IAppDomainSetup to an AppDomainSetup instance.
// IAppDomainSetup provides methods to configure aspects of an application domain before it is created.
CreateDomainSetup uintptr
// CreateEvidence Gets an interface pointer of type IIdentity, which allows the host to create security
// evidence to pass to CreateDomain or CreateDomainEx.
CreateEvidence uintptr
// UnloadDomain Unloads the specified application domain from the current process.
UnloadDomain uintptr
// CurrentDomain Gets an interface pointer of type _AppDomain that represents the domain loaded on the current thread.
CurrentDomain uintptr
}
// GetICORRuntimeHost is a wrapper function that takes in an ICLRRuntimeInfo and returns an ICORRuntimeHost object
// and loads it into the current process. This is the "deprecated" API, but the only way currently to load an assembly
// from memory (afaict)
func GetICORRuntimeHost(runtimeInfo *ICLRRuntimeInfo) (*ICORRuntimeHost, error) {
debugPrint("Entering into icorruntimehost.GetICORRuntimeHost()...")
var runtimeHost *ICORRuntimeHost
err := runtimeInfo.GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, unsafe.Pointer(&runtimeHost))
if err != nil {
return nil, err
}
err = runtimeHost.Start()
return runtimeHost, err
}
func (obj *ICORRuntimeHost) QueryInterface(riid windows.GUID, ppvObject unsafe.Pointer) error {
debugPrint("Entering into icorruntimehost.QueryInterface()...")
hr, _, err := syscall.Syscall(
obj.vtbl.QueryInterface,
3,
uintptr(unsafe.Pointer(obj)),
uintptr(unsafe.Pointer(&riid)), // A reference to the interface identifier (IID) of the interface being queried for.
uintptr(ppvObject),
)
if err != syscall.Errno(0) {
fmt.Println("1111111111111")
return fmt.Errorf("the IUknown::QueryInterface method returned an error:\r\n%s", err)
}
if hr != S_OK {
fmt.Println("222222222222222222")
return fmt.Errorf("the IUknown::QueryInterface method method returned a non-zero HRESULT: 0x%x", hr)
}
return nil
}
func (obj *ICORRuntimeHost) AddRef() uintptr {
ret, _, _ := syscall.Syscall(
obj.vtbl.AddRef,
1,
uintptr(unsafe.Pointer(obj)),
0,
0)
return ret
}
func (obj *ICORRuntimeHost) Release() uintptr {
ret, _, _ := syscall.Syscall(
obj.vtbl.Release,
1,
uintptr(unsafe.Pointer(obj)),
0,
0)
return ret
}
// Start starts the common language runtime (CLR).
// HRESULT Start ();
// https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/icorruntimehost-start-method
func (obj *ICORRuntimeHost) Start() error {
debugPrint("Entering into icorruntimehost.Start()...")
hr, _, err := syscall.Syscall(
obj.vtbl.Start,
1,
uintptr(unsafe.Pointer(obj)),
0,
0,
)
if err != syscall.Errno(0) {
// The system could not find the environment option that was entered.
// TODO Why is this error message returned?
debugPrint(fmt.Sprintf("the ICORRuntimeHost::Start method returned an error:\r\n%s", err))
}
if hr != S_OK {
return fmt.Errorf("the ICORRuntimeHost::Start method method returned a non-zero HRESULT: 0x%x", hr)
}
return nil
}
// GetDefaultDomain gets an interface pointer of type System._AppDomain that represents the default domain for the current process.
// HRESULT GetDefaultDomain (
// [out] IUnknown** pAppDomain
// );
// https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/icorruntimehost-getdefaultdomain-method
func (obj *ICORRuntimeHost) GetDefaultDomain() (IUnknown *IUnknown, err error) {
debugPrint("Entering into icorruntimehost.GetDefaultDomain()...")
hr, _, err := syscall.Syscall(
obj.vtbl.GetDefaultDomain,
2,
uintptr(unsafe.Pointer(obj)),
uintptr(unsafe.Pointer(&IUnknown)),
0,
)
if err != syscall.Errno(0) {
// The specified procedure could not be found.
// TODO Why is this error message returned?
debugPrint(fmt.Sprintf("the ICORRuntimeHost::GetDefaultDomain method returned an error:\r\n%s", err))
}
if hr != S_OK {
err = fmt.Errorf("the ICORRuntimeHost::GetDefaultDomain method method returned a non-zero HRESULT: 0x%x", hr)
return
}
err = nil
return
}
// CreateDomain Creates an application domain. The caller receives an interface pointer of type _AppDomain to an instance of type System.AppDomain.
// HRESULT CreateDomain (
// [in] LPWSTR pwzFriendlyName,
// [in] IUnknown* pIdentityArray,
// [out] void **pAppDomain
// );
// https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms164322(v=vs.100)
func (obj *ICORRuntimeHost) CreateDomain(pwzFriendlyName *uint16) (pAppDomain *AppDomain, err error) {
debugPrint("Entering into icorruntimehost.CreateDomain()...")
hr, _, err := syscall.Syscall6(
obj.vtbl.CreateDomain,
4,
uintptr(unsafe.Pointer(obj)),
uintptr(unsafe.Pointer(pwzFriendlyName)), // [in] LPWSTR pwzFriendlyName - An optional parameter used to give a friendly name to the domain
uintptr(unsafe.Pointer(nil)), // [in] IUnknown* pIdentityArray - An optional array of pointers to IIdentity instances that represent evidence mapped through security policy to establish a permission set
uintptr(unsafe.Pointer(&pAppDomain)), // [out] IUnknown** pAppDomain
0,
0,
)
if err != syscall.Errno(0) {
// The specified procedure could not be found.
// TODO Why is this error message returned?
debugPrint(fmt.Sprintf("the ICORRuntimeHost::CreateDomain method returned an error:\r\n%s", err))
}
if hr != S_OK {
err = fmt.Errorf("the ICORRuntimeHost::CreateDomain method returned a non-zero HRESULT: 0x%x", hr)
return
}
err = nil
return
}
// EnumDomains Gets an enumerator for the domains in the current process.
// HRESULT EnumDomains (
// [out] HCORENUM *hEnum
// );
func (obj *ICORRuntimeHost) EnumDomains() (hEnum *uintptr, err error) {
debugPrint("Enterin into icorruntimehost.EnumDomains()...")
hr, _, err := syscall.Syscall(
obj.vtbl.EnumDomains,
(uintptr(unsafe.Pointer(hEnum))),
0,
0,
0,
)
if err != syscall.Errno(0) {
err = fmt.Errorf("the ICORRuntimeHost::EnumDomains method returned an error:\n%s", err)
return
}
if hr != S_OK {
err = fmt.Errorf("the ICORRuntimeHost::EnumDomains method returned a non-zero HRESULT: 0x%x", hr)
return
}
err = nil
return
}