utils.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright 2010-2012 The W32 Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build windows
  5. package w32
  6. import (
  7. "syscall"
  8. "unicode/utf16"
  9. "unsafe"
  10. )
  11. func MakeIntResource(id uint16) *uint16 {
  12. return (*uint16)(unsafe.Pointer(uintptr(id)))
  13. }
  14. func LOWORD(dw uint32) uint16 {
  15. return uint16(dw)
  16. }
  17. func HIWORD(dw uint32) uint16 {
  18. return uint16(dw >> 16 & 0xffff)
  19. }
  20. func BoolToBOOL(value bool) BOOL {
  21. if value {
  22. return 1
  23. }
  24. return 0
  25. }
  26. func UTF16PtrToString(cstr *uint16) string {
  27. if cstr != nil {
  28. us := make([]uint16, 0, 256)
  29. for p := uintptr(unsafe.Pointer(cstr)); ; p += 2 {
  30. u := *(*uint16)(unsafe.Pointer(p))
  31. if u == 0 {
  32. return string(utf16.Decode(us))
  33. }
  34. us = append(us, u)
  35. }
  36. }
  37. return ""
  38. }
  39. func ComAddRef(unknown *IUnknown) int32 {
  40. ret, _, _ := syscall.Syscall(unknown.lpVtbl.pAddRef, 1,
  41. uintptr(unsafe.Pointer(unknown)),
  42. 0,
  43. 0)
  44. return int32(ret)
  45. }
  46. func ComRelease(unknown *IUnknown) int32 {
  47. ret, _, _ := syscall.Syscall(unknown.lpVtbl.pRelease, 1,
  48. uintptr(unsafe.Pointer(unknown)),
  49. 0,
  50. 0)
  51. return int32(ret)
  52. }
  53. func ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch {
  54. var disp *IDispatch
  55. hr, _, _ := syscall.Syscall(unknown.lpVtbl.pQueryInterface, 3,
  56. uintptr(unsafe.Pointer(unknown)),
  57. uintptr(unsafe.Pointer(id)),
  58. uintptr(unsafe.Pointer(&disp)))
  59. if hr != 0 {
  60. panic("Invoke QieryInterface error.")
  61. }
  62. return disp
  63. }
  64. func ComGetIDsOfName(disp *IDispatch, names []string) []int32 {
  65. wnames := make([]*uint16, len(names))
  66. dispid := make([]int32, len(names))
  67. for i := 0; i < len(names); i++ {
  68. wnames[i] = syscall.StringToUTF16Ptr(names[i])
  69. }
  70. hr, _, _ := syscall.Syscall6(disp.lpVtbl.pGetIDsOfNames, 6,
  71. uintptr(unsafe.Pointer(disp)),
  72. uintptr(unsafe.Pointer(IID_NULL)),
  73. uintptr(unsafe.Pointer(&wnames[0])),
  74. uintptr(len(names)),
  75. uintptr(GetUserDefaultLCID()),
  76. uintptr(unsafe.Pointer(&dispid[0])))
  77. if hr != 0 {
  78. panic("Invoke GetIDsOfName error.")
  79. }
  80. return dispid
  81. }
  82. func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT) {
  83. var dispparams DISPPARAMS
  84. if dispatch&DISPATCH_PROPERTYPUT != 0 {
  85. dispnames := [1]int32{DISPID_PROPERTYPUT}
  86. dispparams.RgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
  87. dispparams.CNamedArgs = 1
  88. }
  89. var vargs []VARIANT
  90. if len(params) > 0 {
  91. vargs = make([]VARIANT, len(params))
  92. for i, v := range params {
  93. //n := len(params)-i-1
  94. n := len(params) - i - 1
  95. VariantInit(&vargs[n])
  96. switch v.(type) {
  97. case bool:
  98. if v.(bool) {
  99. vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff}
  100. } else {
  101. vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0}
  102. }
  103. case *bool:
  104. vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))}
  105. case byte:
  106. vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))}
  107. case *byte:
  108. vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))}
  109. case int16:
  110. vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))}
  111. case *int16:
  112. vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))}
  113. case uint16:
  114. vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))}
  115. case *uint16:
  116. vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))}
  117. case int, int32:
  118. vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))}
  119. case *int, *int32:
  120. vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))}
  121. case uint, uint32:
  122. vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))}
  123. case *uint, *uint32:
  124. vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))}
  125. case int64:
  126. vargs[n] = VARIANT{VT_I8, 0, 0, 0, v.(int64)}
  127. case *int64:
  128. vargs[n] = VARIANT{VT_I8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int64))))}
  129. case uint64:
  130. vargs[n] = VARIANT{VT_UI8, 0, 0, 0, int64(v.(uint64))}
  131. case *uint64:
  132. vargs[n] = VARIANT{VT_UI8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint64))))}
  133. case float32:
  134. vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))}
  135. case *float32:
  136. vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))}
  137. case float64:
  138. vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))}
  139. case *float64:
  140. vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))}
  141. case string:
  142. vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))}
  143. case *string:
  144. vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))}
  145. case *IDispatch:
  146. vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))}
  147. case **IDispatch:
  148. vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))}
  149. case nil:
  150. vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0}
  151. case *VARIANT:
  152. vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}
  153. default:
  154. panic("unknown type")
  155. }
  156. }
  157. dispparams.Rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
  158. dispparams.CArgs = uint32(len(params))
  159. }
  160. var ret VARIANT
  161. var excepInfo EXCEPINFO
  162. VariantInit(&ret)
  163. hr, _, _ := syscall.Syscall9(disp.lpVtbl.pInvoke, 8,
  164. uintptr(unsafe.Pointer(disp)),
  165. uintptr(dispid),
  166. uintptr(unsafe.Pointer(IID_NULL)),
  167. uintptr(GetUserDefaultLCID()),
  168. uintptr(dispatch),
  169. uintptr(unsafe.Pointer(&dispparams)),
  170. uintptr(unsafe.Pointer(&ret)),
  171. uintptr(unsafe.Pointer(&excepInfo)),
  172. 0)
  173. if hr != 0 {
  174. if excepInfo.BstrDescription != nil {
  175. bs := UTF16PtrToString(excepInfo.BstrDescription)
  176. panic(bs)
  177. }
  178. }
  179. for _, varg := range vargs {
  180. if varg.VT == VT_BSTR && varg.Val != 0 {
  181. SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
  182. }
  183. }
  184. result = &ret
  185. return
  186. }