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 }