133 lines
2.9 KiB
Go
133 lines
2.9 KiB
Go
//go:build windows
|
|
// +build windows
|
|
|
|
package wmiext
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/go-ole/go-ole"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type MethodExecutor struct {
|
|
err error
|
|
path string
|
|
method string
|
|
service *Service
|
|
inParam *Instance
|
|
outParam *Instance
|
|
}
|
|
|
|
// In sets an input parameter for the method of this invocation, converting appropriately
|
|
func (e *MethodExecutor) In(name string, value interface{}) *MethodExecutor {
|
|
if e.err == nil && e.inParam != nil {
|
|
switch t := value.(type) {
|
|
case *Instance:
|
|
var ref bool
|
|
if ref, e.err = e.inParam.IsReferenceProperty(name); e.err != nil {
|
|
return e
|
|
}
|
|
if !ref {
|
|
// Embedded Object
|
|
break
|
|
}
|
|
if value, e.err = t.Path(); e.err != nil {
|
|
return e
|
|
}
|
|
}
|
|
|
|
e.err = e.inParam.Put(name, value)
|
|
}
|
|
|
|
return e
|
|
}
|
|
|
|
// Out sets the specified output parameter, and assigns the value parameter to the result.
|
|
// The value parameter must be a reference to the field that should be set.
|
|
func (e *MethodExecutor) Out(name string, value interface{}) *MethodExecutor {
|
|
if e.err == nil && e.outParam != nil {
|
|
var variant *ole.VARIANT
|
|
var cimType CIMTYPE_ENUMERATION
|
|
var result interface{}
|
|
dest := reflect.ValueOf(value)
|
|
if dest.Kind() != reflect.Ptr {
|
|
e.err = fmt.Errorf("Out() on %q called with %T, out parameters must be a reference", name, value)
|
|
return e
|
|
}
|
|
dest = dest.Elem()
|
|
|
|
variant, cimType, _, e.err = e.outParam.GetAsVariant(name)
|
|
if e.err != nil || variant == nil {
|
|
return e
|
|
}
|
|
|
|
defer func() {
|
|
if err := variant.Clear(); err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
}()
|
|
|
|
if _, ok := value.(**Instance); ok && cimType == CIM_REFERENCE {
|
|
path := variant.ToString()
|
|
result, e.err = e.service.GetObject(path)
|
|
if e.err != nil {
|
|
return e
|
|
}
|
|
} else {
|
|
target := reflect.ValueOf(value).Elem()
|
|
result, e.err = convertToGoType(variant, target, target.Type())
|
|
if e.err != nil {
|
|
return e
|
|
}
|
|
}
|
|
|
|
newValue := reflect.ValueOf(result)
|
|
if result == nil {
|
|
// Nil must be typed to the destination
|
|
newValue = reflect.Zero(dest.Type())
|
|
}
|
|
|
|
dest.Set(newValue)
|
|
}
|
|
return e
|
|
}
|
|
|
|
// Execute executes the method after in parameters have been specified using In()
|
|
func (e *MethodExecutor) Execute() *MethodExecutor {
|
|
defer e.cleanupInputs()
|
|
|
|
if e.err == nil {
|
|
e.outParam, e.err = e.service.ExecMethod(e.path, e.method, e.inParam)
|
|
}
|
|
|
|
return e
|
|
}
|
|
|
|
func (e *MethodExecutor) cleanupInputs() {
|
|
if e.inParam != nil {
|
|
e.inParam.Close()
|
|
e.inParam = nil
|
|
}
|
|
}
|
|
|
|
// End completes the method invocation and returns an error indicating the return
|
|
// code of the underlying method
|
|
func (e *MethodExecutor) End() error {
|
|
e.cleanupInputs()
|
|
|
|
if e.outParam != nil {
|
|
e.outParam.Close()
|
|
e.outParam = nil
|
|
}
|
|
|
|
return e.err
|
|
}
|
|
|
|
// Obtains the last error that occurred while building the invocation. Once
|
|
// an error has occurred, all future operations are treated as a no-op.
|
|
func (e *MethodExecutor) Error() error {
|
|
return e.err
|
|
}
|