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  }