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