idispatch_windows.go 6.4 KB

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