github.com/remoteit/go-ole@v1.2.7/idispatch_windows.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package ole
     5  
     6  import (
     7  	"math/big"
     8  	"syscall"
     9  	"time"
    10  	"unsafe"
    11  )
    12  
    13  func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) {
    14  	wnames := make([]*uint16, len(names))
    15  	for i := 0; i < len(names); i++ {
    16  		wnames[i] = syscall.StringToUTF16Ptr(names[i])
    17  	}
    18  	dispid = make([]int32, len(names))
    19  	namelen := uint32(len(names))
    20  	hr, _, _ := syscall.Syscall6(
    21  		disp.VTable().GetIDsOfNames,
    22  		6,
    23  		uintptr(unsafe.Pointer(disp)),
    24  		uintptr(unsafe.Pointer(IID_NULL)),
    25  		uintptr(unsafe.Pointer(&wnames[0])),
    26  		uintptr(namelen),
    27  		uintptr(GetUserDefaultLCID()),
    28  		uintptr(unsafe.Pointer(&dispid[0])))
    29  	if hr != 0 {
    30  		err = NewError(hr)
    31  	}
    32  	return
    33  }
    34  
    35  func getTypeInfoCount(disp *IDispatch) (c uint32, err error) {
    36  	hr, _, _ := syscall.Syscall(
    37  		disp.VTable().GetTypeInfoCount,
    38  		2,
    39  		uintptr(unsafe.Pointer(disp)),
    40  		uintptr(unsafe.Pointer(&c)),
    41  		0)
    42  	if hr != 0 {
    43  		err = NewError(hr)
    44  	}
    45  	return
    46  }
    47  
    48  func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) {
    49  	hr, _, _ := syscall.Syscall(
    50  		disp.VTable().GetTypeInfo,
    51  		3,
    52  		uintptr(unsafe.Pointer(disp)),
    53  		uintptr(GetUserDefaultLCID()),
    54  		uintptr(unsafe.Pointer(&tinfo)))
    55  	if hr != 0 {
    56  		err = NewError(hr)
    57  	}
    58  	return
    59  }
    60  
    61  func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
    62  	var dispparams DISPPARAMS
    63  
    64  	if dispatch&DISPATCH_PROPERTYPUT != 0 {
    65  		dispnames := [1]int32{DISPID_PROPERTYPUT}
    66  		dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
    67  		dispparams.cNamedArgs = 1
    68  	} else if dispatch&DISPATCH_PROPERTYPUTREF != 0 {
    69  		dispnames := [1]int32{DISPID_PROPERTYPUT}
    70  		dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
    71  		dispparams.cNamedArgs = 1
    72  	}
    73  	var vargs []VARIANT
    74  	if len(params) > 0 {
    75  		vargs = make([]VARIANT, len(params))
    76  		for i, v := range params {
    77  			//n := len(params)-i-1
    78  			n := len(params) - i - 1
    79  			VariantInit(&vargs[n])
    80  			switch vv := v.(type) {
    81  			case bool:
    82  				if vv {
    83  					vargs[n] = NewVariant(VT_BOOL, 0xffff)
    84  				} else {
    85  					vargs[n] = NewVariant(VT_BOOL, 0)
    86  				}
    87  			case *bool:
    88  				vargs[n] = NewVariant(VT_BOOL|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*bool)))))
    89  			case uint8:
    90  				vargs[n] = NewVariant(VT_I1, int64(v.(uint8)))
    91  			case *uint8:
    92  				vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8)))))
    93  			case int8:
    94  				vargs[n] = NewVariant(VT_I1, int64(v.(int8)))
    95  			case *int8:
    96  				vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int8)))))
    97  			case int16:
    98  				vargs[n] = NewVariant(VT_I2, int64(v.(int16)))
    99  			case *int16:
   100  				vargs[n] = NewVariant(VT_I2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int16)))))
   101  			case uint16:
   102  				vargs[n] = NewVariant(VT_UI2, int64(v.(uint16)))
   103  			case *uint16:
   104  				vargs[n] = NewVariant(VT_UI2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint16)))))
   105  			case int32:
   106  				vargs[n] = NewVariant(VT_I4, int64(v.(int32)))
   107  			case *int32:
   108  				vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int32)))))
   109  			case uint32:
   110  				vargs[n] = NewVariant(VT_UI4, int64(v.(uint32)))
   111  			case *uint32:
   112  				vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint32)))))
   113  			case int64:
   114  				vargs[n] = NewVariant(VT_I8, int64(v.(int64)))
   115  			case *int64:
   116  				vargs[n] = NewVariant(VT_I8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int64)))))
   117  			case uint64:
   118  				vargs[n] = NewVariant(VT_UI8, int64(uintptr(v.(uint64))))
   119  			case *uint64:
   120  				vargs[n] = NewVariant(VT_UI8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint64)))))
   121  			case int:
   122  				vargs[n] = NewVariant(VT_I4, int64(v.(int)))
   123  			case *int:
   124  				vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int)))))
   125  			case uint:
   126  				vargs[n] = NewVariant(VT_UI4, int64(v.(uint)))
   127  			case *uint:
   128  				vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint)))))
   129  			case float32:
   130  				vargs[n] = NewVariant(VT_R4, *(*int64)(unsafe.Pointer(&vv)))
   131  			case *float32:
   132  				vargs[n] = NewVariant(VT_R4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float32)))))
   133  			case float64:
   134  				vargs[n] = NewVariant(VT_R8, *(*int64)(unsafe.Pointer(&vv)))
   135  			case *float64:
   136  				vargs[n] = NewVariant(VT_R8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float64)))))
   137  			case *big.Int:
   138  				vargs[n] = NewVariant(VT_DECIMAL, v.(*big.Int).Int64())
   139  			case string:
   140  				vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(v.(string))))))
   141  			case *string:
   142  				vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*string)))))
   143  			case time.Time:
   144  				s := vv.Format("2006-01-02 15:04:05")
   145  				vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(s)))))
   146  			case *time.Time:
   147  				s := vv.Format("2006-01-02 15:04:05")
   148  				vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(&s))))
   149  			case *IDispatch:
   150  				vargs[n] = NewVariant(VT_DISPATCH, int64(uintptr(unsafe.Pointer(v.(*IDispatch)))))
   151  			case **IDispatch:
   152  				vargs[n] = NewVariant(VT_DISPATCH|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(**IDispatch)))))
   153  			case nil:
   154  				vargs[n] = NewVariant(VT_NULL, 0)
   155  			case *VARIANT:
   156  				vargs[n] = NewVariant(VT_VARIANT|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*VARIANT)))))
   157  			case []byte:
   158  				safeByteArray := safeArrayFromByteSlice(v.([]byte))
   159  				vargs[n] = NewVariant(VT_ARRAY|VT_UI1, int64(uintptr(unsafe.Pointer(safeByteArray))))
   160  				defer VariantClear(&vargs[n])
   161  			case []string:
   162  				safeByteArray := safeArrayFromStringSlice(v.([]string))
   163  				vargs[n] = NewVariant(VT_ARRAY|VT_BSTR, int64(uintptr(unsafe.Pointer(safeByteArray))))
   164  				defer VariantClear(&vargs[n])
   165  			default:
   166  				panic("unknown type")
   167  			}
   168  		}
   169  		dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
   170  		dispparams.cArgs = uint32(len(params))
   171  	}
   172  
   173  	result = new(VARIANT)
   174  	var excepInfo EXCEPINFO
   175  	VariantInit(result)
   176  	hr, _, _ := syscall.Syscall9(
   177  		disp.VTable().Invoke,
   178  		9,
   179  		uintptr(unsafe.Pointer(disp)),
   180  		uintptr(dispid),
   181  		uintptr(unsafe.Pointer(IID_NULL)),
   182  		uintptr(GetUserDefaultLCID()),
   183  		uintptr(dispatch),
   184  		uintptr(unsafe.Pointer(&dispparams)),
   185  		uintptr(unsafe.Pointer(result)),
   186  		uintptr(unsafe.Pointer(&excepInfo)),
   187  		0)
   188  	if hr != 0 {
   189  		excepInfo.renderStrings()
   190  		excepInfo.Clear()
   191  		err = NewErrorWithSubError(hr, excepInfo.description, excepInfo)
   192  	}
   193  	for i, varg := range vargs {
   194  		n := len(params) - i - 1
   195  		if varg.VT == VT_BSTR && varg.Val != 0 {
   196  			SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
   197  		}
   198  		if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 {
   199  			*(params[n].(*string)) = LpOleStrToString(*(**uint16)(unsafe.Pointer(uintptr(varg.Val))))
   200  		}
   201  	}
   202  	return
   203  }