some refactoring and commenting

This commit is contained in:
Ronnie Flathers
2020-03-14 19:55:33 -05:00
parent ad8d54d75b
commit 89549b0317
16 changed files with 213 additions and 210 deletions
+4 -3
View File
@@ -86,6 +86,7 @@ type AppDomainVtbl struct {
get_DynamicDirectory uintptr
}
// GetAppDomain is a wrapper function that returns an appDomain from an existing ICORRuntimeHost object
func GetAppDomain(runtimeHost *ICORRuntimeHost) (appDomain *AppDomain, err error) {
var pAppDomain uintptr
var pIUnknown uintptr
@@ -94,13 +95,13 @@ func GetAppDomain(runtimeHost *ICORRuntimeHost) (appDomain *AppDomain, err error
if err != nil {
return
}
iu := NewIUnknown(pIUnknown)
iu := NewIUnknownFromPtr(pIUnknown)
hr = iu.QueryInterface(&IID_AppDomain, &pAppDomain)
err = checkOK(hr, "IUnknown.QueryInterface")
return NewAppDomain(pAppDomain), err
return NewAppDomainFromPtr(pAppDomain), err
}
func NewAppDomain(ppv uintptr) *AppDomain {
func NewAppDomainFromPtr(ppv uintptr) *AppDomain {
return (*AppDomain)(unsafe.Pointer(ppv))
}
+1 -1
View File
@@ -69,7 +69,7 @@ type AssemblyVtbl struct {
get_GlobalAssemblyCache uintptr
}
func NewAssembly(ppv uintptr) *Assembly {
func NewAssemblyFromPtr(ppv uintptr) *Assembly {
return (*Assembly)(unsafe.Pointer(ppv))
}
+2 -2
View File
@@ -36,7 +36,7 @@ func main() {
hr := metahost.GetRuntime(pwzVersion, &clr.IID_ICLRRuntimeInfo, &pRuntimeInfo)
checkOK(hr, "metaHost.GetRuntime")
runtimeInfo := clr.NewICLRRuntimeInfo(pRuntimeInfo)
runtimeInfo := clr.NewICLRRuntimeInfoFromPtr(pRuntimeInfo)
fmt.Printf("[+] Using runtime: %s\n", versionString)
var isLoadable bool
@@ -49,7 +49,7 @@ func main() {
var pRuntimeHost uintptr
hr = runtimeInfo.GetInterface(&clr.CLSID_CLRRuntimeHost, &clr.IID_ICLRRuntimeHost, &pRuntimeHost)
checkOK(hr, "runtimeInfo.GetInterface")
runtimeHost := clr.NewICLRRuntimeHost(pRuntimeHost)
runtimeHost := clr.NewICLRRuntimeHostFromPtr(pRuntimeHost)
hr = runtimeHost.Start()
checkOK(hr, "runtimeHost.Start")
+121 -121
View File
@@ -1,121 +1,121 @@
// +build windows
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"runtime"
"syscall"
"unsafe"
clr "github.com/ropnop/go-clr"
)
func must(err error) {
if err != nil {
log.Fatal(err)
}
}
func checkOK(hr uintptr, caller string) {
if hr != 0x0 {
log.Fatalf("%s returned 0x%08x", caller, hr)
}
}
func init() {
if len(os.Args) != 2 {
fmt.Println("Usage: EXEfromMemory.exe <exe_file>")
os.Exit(1)
}
}
func main() {
filename := os.Args[1]
exebytes, err := ioutil.ReadFile(filename)
must(err)
runtime.KeepAlive(exebytes)
var pMetaHost uintptr
hr := clr.CLRCreateInstance(&clr.CLSID_CLRMetaHost, &clr.IID_ICLRMetaHost, &pMetaHost)
checkOK(hr, "CLRCreateInstance")
metaHost := clr.NewICLRMetaHost(pMetaHost)
versionString := "v4.0.30319"
pwzVersion, _ := syscall.UTF16PtrFromString(versionString)
var pRuntimeInfo uintptr
hr = metaHost.GetRuntime(pwzVersion, &clr.IID_ICLRRuntimeInfo, &pRuntimeInfo)
checkOK(hr, "metahost.GetRuntime")
runtimeInfo := clr.NewICLRRuntimeInfo(pRuntimeInfo)
var isLoadable bool
hr = runtimeInfo.IsLoadable(&isLoadable)
checkOK(hr, "runtimeInfo.IsLoadable")
if !isLoadable {
log.Fatal("[!] IsLoadable returned false. Bailing...")
}
hr = runtimeInfo.BindAsLegacyV2Runtime()
checkOK(hr, "runtimeInfo.BindAsLegacyV2Runtime")
var pRuntimeHost uintptr
hr = runtimeInfo.GetInterface(&clr.CLSID_CorRuntimeHost, &clr.IID_ICorRuntimeHost, &pRuntimeHost)
runtimeHost := clr.NewICORRuntimeHost(pRuntimeHost)
hr = runtimeHost.Start()
checkOK(hr, "runtimeHost.Start")
fmt.Println("[+] Loaded CLR into this process")
var pAppDomain uintptr
var pIUnknown uintptr
hr = runtimeHost.GetDefaultDomain(&pIUnknown)
checkOK(hr, "runtimeHost.GetDefaultDomain")
iu := clr.NewIUnknown(pIUnknown)
hr = iu.QueryInterface(&clr.IID_AppDomain, &pAppDomain)
checkOK(hr, "iu.QueryInterface")
appDomain := clr.NewAppDomain(pAppDomain)
fmt.Println("[+] Got default AppDomain")
fmt.Printf("[+] Loaded %d bytes into memory from %s\n", len(exebytes), filename)
safeArray, err := clr.CreateSafeArray(exebytes)
must(err)
runtime.KeepAlive(safeArray)
fmt.Println("[+] Crated SafeArray from byte array")
var pAssembly uintptr
hr = appDomain.Load_3(uintptr(unsafe.Pointer(&safeArray)), &pAssembly)
checkOK(hr, "appDomain.Load_3")
assembly := clr.NewAssembly(pAssembly)
fmt.Printf("[+] Executable loaded into memory at 0x%08x\n", pAssembly)
var pEntryPointInfo uintptr
hr = assembly.GetEntryPoint(&pEntryPointInfo)
checkOK(hr, "assembly.GetEntryPoint")
fmt.Printf("[+] Executable entrypoint found at 0x%08x. Calling...\n", pEntryPointInfo)
fmt.Println("-------")
methodInfo := clr.NewMethodInfo(pEntryPointInfo)
var pRetCode uintptr
nullVariant := clr.Variant{
VT: 1,
Val: uintptr(0),
}
hr = methodInfo.Invoke_3(
nullVariant,
uintptr(0),
&pRetCode)
fmt.Println("-------")
checkOK(hr, "methodInfo.Invoke_3")
fmt.Printf("[+] Executable returned code %d\n", pRetCode)
appDomain.Release()
runtimeHost.Release()
runtimeInfo.Release()
metaHost.Release()
}
// +build windows
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"runtime"
"syscall"
"unsafe"
clr "github.com/ropnop/go-clr"
)
func must(err error) {
if err != nil {
log.Fatal(err)
}
}
func checkOK(hr uintptr, caller string) {
if hr != 0x0 {
log.Fatalf("%s returned 0x%08x", caller, hr)
}
}
func init() {
if len(os.Args) != 2 {
fmt.Println("Usage: EXEfromMemory.exe <exe_file>")
os.Exit(1)
}
}
func main() {
filename := os.Args[1]
exebytes, err := ioutil.ReadFile(filename)
must(err)
runtime.KeepAlive(exebytes)
var pMetaHost uintptr
hr := clr.CLRCreateInstance(&clr.CLSID_CLRMetaHost, &clr.IID_ICLRMetaHost, &pMetaHost)
checkOK(hr, "CLRCreateInstance")
metaHost := clr.NewICLRMetaHostFromPtr(pMetaHost)
versionString := "v4.0.30319"
pwzVersion, _ := syscall.UTF16PtrFromString(versionString)
var pRuntimeInfo uintptr
hr = metaHost.GetRuntime(pwzVersion, &clr.IID_ICLRRuntimeInfo, &pRuntimeInfo)
checkOK(hr, "metahost.GetRuntime")
runtimeInfo := clr.NewICLRRuntimeInfoFromPtr(pRuntimeInfo)
var isLoadable bool
hr = runtimeInfo.IsLoadable(&isLoadable)
checkOK(hr, "runtimeInfo.IsLoadable")
if !isLoadable {
log.Fatal("[!] IsLoadable returned false. Bailing...")
}
hr = runtimeInfo.BindAsLegacyV2Runtime()
checkOK(hr, "runtimeInfo.BindAsLegacyV2Runtime")
var pRuntimeHost uintptr
hr = runtimeInfo.GetInterface(&clr.CLSID_CorRuntimeHost, &clr.IID_ICorRuntimeHost, &pRuntimeHost)
runtimeHost := clr.NewICORRuntimeHostFromPtr(pRuntimeHost)
hr = runtimeHost.Start()
checkOK(hr, "runtimeHost.Start")
fmt.Println("[+] Loaded CLR into this process")
var pAppDomain uintptr
var pIUnknown uintptr
hr = runtimeHost.GetDefaultDomain(&pIUnknown)
checkOK(hr, "runtimeHost.GetDefaultDomain")
iu := clr.NewIUnknownFromPtr(pIUnknown)
hr = iu.QueryInterface(&clr.IID_AppDomain, &pAppDomain)
checkOK(hr, "iu.QueryInterface")
appDomain := clr.NewAppDomainFromPtr(pAppDomain)
fmt.Println("[+] Got default AppDomain")
fmt.Printf("[+] Loaded %d bytes into memory from %s\n", len(exebytes), filename)
safeArray, err := clr.CreateSafeArray(exebytes)
must(err)
runtime.KeepAlive(safeArray)
fmt.Println("[+] Crated SafeArray from byte array")
var pAssembly uintptr
hr = appDomain.Load_3(uintptr(unsafe.Pointer(&safeArray)), &pAssembly)
checkOK(hr, "appDomain.Load_3")
assembly := clr.NewAssemblyFromPtr(pAssembly)
fmt.Printf("[+] Executable loaded into memory at 0x%08x\n", pAssembly)
var pEntryPointInfo uintptr
hr = assembly.GetEntryPoint(&pEntryPointInfo)
checkOK(hr, "assembly.GetEntryPoint")
fmt.Printf("[+] Executable entrypoint found at 0x%08x. Calling...\n", pEntryPointInfo)
fmt.Println("-------")
methodInfo := clr.NewMethodInfoFromPtr(pEntryPointInfo)
var pRetCode uintptr
nullVariant := clr.Variant{
VT: 1,
Val: uintptr(0),
}
hr = methodInfo.Invoke_3(
nullVariant,
uintptr(0),
&pRetCode)
fmt.Println("-------")
checkOK(hr, "methodInfo.Invoke_3")
fmt.Printf("[+] Executable returned code %d\n", pRetCode)
appDomain.Release()
runtimeHost.Release()
runtimeInfo.Release()
metaHost.Release()
}
+12 -57
View File
@@ -10,16 +10,7 @@ import (
"unsafe"
)
func GetMetaHost() (*ICLRMetaHost, error) {
var pMetaHost uintptr
hr := CLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, &pMetaHost)
err := checkOK(hr, "CLRCreateInstance")
if err != nil {
return nil, err
}
return NewICLRMetaHost(pMetaHost), nil
}
// GetInstallRuntimes is a wrapper function that returns an array of installed runtimes. Requires an existing ICLRMetaHost
func GetInstalledRuntimes(metahost *ICLRMetaHost) ([]string, error) {
var runtimes []string
var pInstalledRuntimes uintptr
@@ -28,7 +19,7 @@ func GetInstalledRuntimes(metahost *ICLRMetaHost) ([]string, error) {
if err != nil {
return runtimes, err
}
installedRuntimes := NewIEnumUnknown(pInstalledRuntimes)
installedRuntimes := NewIEnumUnknownFromPtr(pInstalledRuntimes)
var pRuntimeInfo uintptr
var fetched = uint32(0)
var versionString string
@@ -40,7 +31,7 @@ func GetInstalledRuntimes(metahost *ICLRMetaHost) ([]string, error) {
if hr != S_OK {
break
}
runtimeInfo = NewICLRRuntimeInfo(pRuntimeInfo)
runtimeInfo = NewICLRRuntimeInfoFromPtr(pRuntimeInfo)
if ret := runtimeInfo.GetVersionString(&versionStringBytes[0], &versionStringSize); ret != S_OK {
return runtimes, fmt.Errorf("GetVersionString returned 0x%08x", ret)
}
@@ -54,51 +45,12 @@ func GetInstalledRuntimes(metahost *ICLRMetaHost) ([]string, error) {
return runtimes, err
}
func GetRuntimeInfo(metahost *ICLRMetaHost, version string) (*ICLRRuntimeInfo, error) {
pwzVersion, err := syscall.UTF16PtrFromString(version)
if err != nil {
return nil, err
}
var pRuntimeInfo uintptr
hr := metahost.GetRuntime(pwzVersion, &IID_ICLRRuntimeInfo, &pRuntimeInfo)
err = checkOK(hr, "metahost.GetRuntime")
if err != nil {
return nil, err
}
return NewICLRRuntimeInfo(pRuntimeInfo), nil
}
func GetICLRRuntimeHost(runtimeInfo *ICLRRuntimeInfo) (*ICLRRuntimeHost, error) {
var pRuntimeHost uintptr
hr := runtimeInfo.GetInterface(&CLSID_CLRRuntimeHost, &IID_ICLRRuntimeHost, &pRuntimeHost)
err := checkOK(hr, "runtimeInfo.GetInterface")
if err != nil {
return nil, err
}
runtimeHost := NewICLRRuntimeHost(pRuntimeHost)
hr = runtimeHost.Start()
err = checkOK(hr, "runtimeHost.Start")
return runtimeHost, err
}
func GetICORRuntimeHost(runtimeInfo *ICLRRuntimeInfo) (*ICORRuntimeHost, error) {
var pRuntimeHost uintptr
hr := runtimeInfo.GetInterface(&CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, &pRuntimeHost)
err := checkOK(hr, "runtimeInfo.GetInterface")
if err != nil {
return nil, err
}
runtimeHost := NewICORRuntimeHost(pRuntimeHost)
hr = runtimeHost.Start()
err = checkOK(hr, "runtimeHost.Start")
return runtimeHost, err
}
// ExecuteDLL is a wrapper function that will automatically load the latest installed CLR into the current process
// and execute a DLL on disk in the default app domain
// and execute a DLL on disk in the default app domain. It takes in the DLLPath, TypeName, MethodName and Argument to use
// as strings. It returns the return code from the assembly
func ExecuteDLL(dllpath, typeName, methodName, argument string) (retCode int16, err error) {
retCode = -1
metahost, err := GetMetaHost()
metahost, err := GetICLRMetaHost()
if err != nil {
return
}
@@ -151,9 +103,12 @@ func ExecuteDLL(dllpath, typeName, methodName, argument string) (retCode int16,
}
// ExecuteByteArray is a wrapper function that will automatically load the latest supported framework into the current
// process using the legacy APIs, then load and execute an executable from memory. It takes in a byte array of the
// executable to load and run and returns the return code. It currently does not support any arguments on the entry point
func ExecuteByteArray(rawBytes []byte) (retCode int32, err error) {
retCode = -1
metahost, err := GetMetaHost()
metahost, err := GetICLRMetaHost()
if err != nil {
return
}
@@ -203,14 +158,14 @@ func ExecuteByteArray(rawBytes []byte) (retCode int32, err error) {
if err != nil {
return
}
assembly := NewAssembly(pAssembly)
assembly := NewAssemblyFromPtr(pAssembly)
var pEntryPointInfo uintptr
hr = assembly.GetEntryPoint(&pEntryPointInfo)
err = checkOK(hr, "assembly.GetEntryPoint")
if err != nil {
return
}
methodInfo := NewMethodInfo(pEntryPointInfo)
methodInfo := NewMethodInfoFromPtr(pEntryPointInfo)
var pRetCode uintptr
nullVariant := Variant{
VT: 1,
+1
View File
@@ -11,6 +11,7 @@ var (
CLSID_CLRRuntimeHost = windows.GUID{0x90F1A06E, 0x7712, 0x4762, [8]byte{0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02}}
IID_ICLRRuntimeHost = windows.GUID{0x90F1A06C, 0x7712, 0x4762, [8]byte{0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02}}
IID_ICorRuntimeHost = windows.GUID{0xcb2f6722, 0xab3a, 0x11d2, [8]byte{0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e}}
CLSID_CorRuntimeHost = windows.GUID{0xcb2f6723, 0xab3a, 0x11d2, [8]byte{0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e}}
+17 -17
View File
@@ -14,6 +14,7 @@ var (
procCLRCreateInstance = modMSCoree.NewProc("CLRCreateInstance")
)
// Wrapper for the mscorree.dll CLRCreateInstance syscall
func CLRCreateInstance(clsid, riid *windows.GUID, ppInterface *uintptr) uintptr {
ret, _, _ := procCLRCreateInstance.Call(
uintptr(unsafe.Pointer(clsid)),
@@ -22,24 +23,15 @@ func CLRCreateInstance(clsid, riid *windows.GUID, ppInterface *uintptr) uintptr
return ret
}
func GetICLRMetaHost() (metahost *ICLRMetaHost, err error) {
var pMetaHost uintptr
hr := CLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, &pMetaHost)
err = checkOK(hr, "CLRCreateInstance")
if err != nil {
return
}
metahost = NewICLRMetaHost(pMetaHost)
return
}
//ICLRMetaHost Interface from metahost.h
// Couldnt have done any of this without this SO answer I stumbled on:
// https://stackoverflow.com/questions/37781676/how-to-use-com-component-object-model-in-golang
//ICLRMetaHost Interface from metahost.h
type ICLRMetaHost struct {
vtbl *ICLRMetaHostVtbl
}
type ICLRMetaHostVtbl struct {
QueryInterface uintptr
AddRef uintptr
@@ -53,8 +45,20 @@ type ICLRMetaHostVtbl struct {
ExitProcess uintptr
}
// newICLRMetaHost takes a uintptr to ICLRMetahost, which must come from the syscall CLRCreateInstance
func NewICLRMetaHost(ppv uintptr) *ICLRMetaHost {
// GetICLRMetaHost is a wrapper function to create and return an ICLRMetahost object
func GetICLRMetaHost() (metahost *ICLRMetaHost, err error) {
var pMetaHost uintptr
hr := CLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, &pMetaHost)
err = checkOK(hr, "CLRCreateInstance")
if err != nil {
return
}
metahost = NewICLRMetaHostFromPtr(pMetaHost)
return
}
// NewICLRMetaHost takes a uintptr to an ICLRMetahost struct in memory. This pointer should come from the syscall CLRCreateInstance
func NewICLRMetaHostFromPtr(ppv uintptr) *ICLRMetaHost {
return (*ICLRMetaHost)(unsafe.Pointer(ppv))
}
@@ -89,10 +93,6 @@ func (obj *ICLRMetaHost) EnumerateInstalledRuntimes(pInstalledRuntimes *uintptr)
}
func (obj *ICLRMetaHost) GetRuntime(pwzVersion *uint16, riid *windows.GUID, pRuntimeHost *uintptr) uintptr {
// v4Ptr, err := syscall.UTF16PtrFromString("v4.0.30319")
// if err != nil {
// panic(err)
// }
ret, _, _ := syscall.Syscall6(
obj.vtbl.GetRuntime,
4,
+15 -1
View File
@@ -25,8 +25,22 @@ type ICLRRuntimeHostVtbl struct {
ExecuteApplication uintptr
ExecuteInDefaultAppDomain uintptr
}
// GetICLRRuntimeHost is a wrapper function that takes an ICLRRuntimeInfo object and
// returns an ICLRRuntimeHost and loads it into the current process
func GetICLRRuntimeHost(runtimeInfo *ICLRRuntimeInfo) (*ICLRRuntimeHost, error) {
var pRuntimeHost uintptr
hr := runtimeInfo.GetInterface(&CLSID_CLRRuntimeHost, &IID_ICLRRuntimeHost, &pRuntimeHost)
err := checkOK(hr, "runtimeInfo.GetInterface")
if err != nil {
return nil, err
}
runtimeHost := NewICLRRuntimeHostFromPtr(pRuntimeHost)
hr = runtimeHost.Start()
err = checkOK(hr, "runtimeHost.Start")
return runtimeHost, err
}
func NewICLRRuntimeHost(ppv uintptr) *ICLRRuntimeHost {
func NewICLRRuntimeHostFromPtr(ppv uintptr) *ICLRRuntimeHost {
return (*ICLRRuntimeHost)(unsafe.Pointer(ppv))
}
+16 -1
View File
@@ -30,7 +30,22 @@ type ICLRRuntimeInfoVtbl struct {
IsStarted uintptr
}
func NewICLRRuntimeInfo(ppv uintptr) *ICLRRuntimeInfo {
// GetRuntimeInfo is a wrapper function to return an ICLRRuntimeInfo from a standard version string
func GetRuntimeInfo(metahost *ICLRMetaHost, version string) (*ICLRRuntimeInfo, error) {
pwzVersion, err := syscall.UTF16PtrFromString(version)
if err != nil {
return nil, err
}
var pRuntimeInfo uintptr
hr := metahost.GetRuntime(pwzVersion, &IID_ICLRRuntimeInfo, &pRuntimeInfo)
err = checkOK(hr, "metahost.GetRuntime")
if err != nil {
return nil, err
}
return NewICLRRuntimeInfoFromPtr(pRuntimeInfo), nil
}
func NewICLRRuntimeInfoFromPtr(ppv uintptr) *ICLRRuntimeInfo {
return (*ICLRRuntimeInfo)(unsafe.Pointer(ppv))
}
+17 -1
View File
@@ -36,7 +36,23 @@ type ICORRuntimeHostVtbl struct {
CurrentDomain uintptr
}
func NewICORRuntimeHost(ppv uintptr) *ICORRuntimeHost {
// 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) {
var pRuntimeHost uintptr
hr := runtimeInfo.GetInterface(&CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, &pRuntimeHost)
err := checkOK(hr, "runtimeInfo.GetInterface")
if err != nil {
return nil, err
}
runtimeHost := NewICORRuntimeHostFromPtr(pRuntimeHost)
hr = runtimeHost.Start()
err = checkOK(hr, "runtimeHost.Start")
return runtimeHost, err
}
func NewICORRuntimeHostFromPtr(ppv uintptr) *ICORRuntimeHost {
return (*ICORRuntimeHost)(unsafe.Pointer(ppv))
}
+1 -1
View File
@@ -21,7 +21,7 @@ type IEnumUnknownVtbl struct {
Clone uintptr
}
func NewIEnumUnknown(ppv uintptr) *IEnumUnknown {
func NewIEnumUnknownFromPtr(ppv uintptr) *IEnumUnknown {
return (*IEnumUnknown)(unsafe.Pointer(ppv))
}
+1 -1
View File
@@ -19,7 +19,7 @@ type IUnknownVtbl struct {
Release uintptr
}
func NewIUnknown(ppv uintptr) *IUnknown {
func NewIUnknownFromPtr(ppv uintptr) *IUnknown {
return (*IUnknown)(unsafe.Pointer(ppv))
}
-1
View File
@@ -1 +0,0 @@
package clr
+1 -1
View File
@@ -59,7 +59,7 @@ type MethodInfoVtbl struct {
GetBaseDefinition uintptr
}
func NewMethodInfo(ppv uintptr) *MethodInfo {
func NewMethodInfoFromPtr(ppv uintptr) *MethodInfo {
return (*MethodInfo)(unsafe.Pointer(ppv))
}
+2
View File
@@ -32,6 +32,8 @@ type SafeArrayBound struct {
lLbound int32
}
// CreateSafeArray is a wrapper function that takes in a Go byte array and creates a SafeArray by making two syscalls
// and copying raw memory into the correct spot.
func CreateSafeArray(rawBytes []byte) (SafeArray, error) {
modOleAuto, err := syscall.LoadDLL("OleAut32.dll")
if err != nil {
+2 -2
View File
@@ -4,7 +4,7 @@ package clr
import "unsafe"
//from https://github.com/go-ole/go-ole/blob/master/variant_amd64.go
// from https://github.com/go-ole/go-ole/blob/master/variant_amd64.go
type Variant struct {
VT uint16 // VARTYPE
@@ -15,6 +15,6 @@ type Variant struct {
_ [8]byte
}
func variantFromPtr(ppv uintptr) *Variant {
func NewVariantFromPtr(ppv uintptr) *Variant {
return (*Variant)(unsafe.Pointer(ppv))
}