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