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