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