func Invoke(obj interface{}, method uintptr, displayID DisplayID, dispatchContext DispatchContext, params ...interface{}) (result *com.Variant, err error) { var displayParams com.DisplayParameter var vargs []com.Variant if dispatchContext&com.PropertySetDispatchContext != 0 { displayNames := [1]int32{com.PropertySetDisplayID} displayParams.NamedArgs = uintptr(unsafe.Pointer(&displayNames[0])) displayParams.NamedArgsLength = 1 } if len(params) > 0 { vargs = make([]com.Variant, len(params)) for i, v := range params { //n := len(params)-i-1 n := len(params) - i - 1 vargs[n] = com.VariantByValueType(v) // This should clear all variant types. defer com.VariantClear(vargs[n]) } displayParams.Args = uintptr(unsafe.Pointer(&vargs[0])) displayParams.ArgsLength = uint32(len(params)) } result = new(com.Variant) var excepInfo EXCEPINFO com.VariantInit(result) hr, _, _ := syscall.Syscall9( method, uintptr(9), uintptr(unsafe.Pointer(obj)), uintptr(displayID), uintptr(unsafe.Pointer(com.NullInterfaceID)), uintptr(com.GetDefaultUserLocaleID()), uintptr(dispatchContext), uintptr(unsafe.Pointer(&displayParams)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(&excepInfo)), uintptr(0)) if hr != 0 { err = NewErrorWithSubError(hr, BstrToString(excepInfo.bstrDescription), excepInfo) } /* // This is now deferred and should clear all variants. for _, varg := range vargs { // This should clear all variant types. com.VariantClear(varg) if varg.VariantType == BinaryStringVariantType && varg.Val != 0 { SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val))))) } /* if varg.VariantType == (BinaryStringVariantType|ByReferenceVariantType) && varg.Val != 0 { *(params[n].(*string)) = LpOleStrToString((*uint16)(unsafe.Pointer(uintptr(varg.Val)))) println(*(params[n].(*string))) fmt.Fprintln(os.Stderr, *(params[n].(*string))) } //* / } */ return }
func Example_winsock() { queryInterface := func(self *interface{}, interfaceID *com.GUID, client **interface{}) uint32 { code := iunknown.QueryInterfaceService(self, interfaceID, *client) if code == com.NoInterfaceErrorCode { s := com.StringFromClassID(interfaceID) if s == "{248DD893-BB45-11CF-9ABC-0080C7E7B78D}" { iunknown.AddRefService(self) *client = self return com.SuccessResponseCode } } return com.NoInterfaceErrorCode } getIDsOfNames := func(this *iunknown.IUnknown, iid *com.GUID, wnames []*uint16, namelen int, lcid int, pdisp []int32) uintptr { for n := 0; n < namelen; n++ { pdisp[n] = int32(n) } return uintptr(com.SuccessResponseCode) } invoke := func(this *IDispatch, dispid int32, riid *com.GUID, lcid int, flags int16, dispparams *com.DISPPARAMS, result *com.Variant, pexcepinfo *com.EXCEPINFO, nerr *uint) { switch dispid { case 0: log.Println("DataArrival") winsock := (*com.EventReceiver)(unsafe.Pointer(this)).host var data com.Variant com.VariantInit(&data) CallMethod(winsock, "GetData", &data) s := string(data.ToArray().ToByteArray()) println() println(s) println() case 1: log.Println("Connected") winsock := (*com.EventReceiver)(unsafe.Pointer(this)).host oleutil.CallMethod(winsock, "SendData", "GET / HTTP/1.0\r\n\r\n") case 3: log.Println("SendProgress") case 4: log.Println("SendComplete") case 5: log.Println("Close") this.Release() case 6: log.Fatal("Error") default: log.Println(dispid) } return com.NotImplementedErrorCode } com.CoInitialize() defer com.CoUninitialize() var unknown *iunknown.Unknown var winsock *Dispatch err := com.CreateObject("{248DD896-BB45-11CF-9ABC-0080C7E7B78D}", &unknown) if err != nil { panic(err.Error()) } unknown.QueryInterface(com.IDispatchInterfaceID, &winsock) defer winsock.Release() classID, _ := com.ClassIDFromString("{248DD893-BB45-11CF-9ABC-0080C7E7B78D}") destination := &com.EventReceiver{} destination.VirtualTable = &VirtualTable{ QueryInterface: syscall.NewCallback(queryInterface), AddRef: syscall.NewCallback(iunknown.AddRefService), Release: syscall.NewCallback(iunknown.ReleaseService), GetTypeInfoCount: syscall.NewCallback(GetTypeInfoCountService), GetTypeInfo: syscall.NewCallback(GetTypeInfoService), GetIDsOfNames: syscall.NewCallback(getIDsOfNames), Invoke: syscall.NewCallback(invoke)} destination.Host = winsock iconnectionpointcontainer.ConnectObject(winsock, classID, (*iunknown.Unknown)(unsafe.Pointer(destination))) _, err = CallMethod(winsock, "Connect", "127.0.0.1", 80) if err != nil { log.Fatal(err) } var m com.Msg for dest.ReferenceCount != 0 { com.GetMessage(&m, 0, 0, 0) com.DispatchMessage(&m) } }