idispatch_windows.go 6.5 KB

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