github.com/go-ole/go-ole@v1.2.6/_example/winsock/winsock.go (about)

     1  // +build windows
     2  
     3  package main
     4  
     5  import (
     6  	"log"
     7  	"syscall"
     8  	"unsafe"
     9  
    10  	ole "github.com/go-ole/go-ole"
    11  	"github.com/go-ole/go-ole/oleutil"
    12  )
    13  
    14  type EventReceiver struct {
    15  	lpVtbl *EventReceiverVtbl
    16  	ref    int32
    17  	host   *ole.IDispatch
    18  }
    19  
    20  type EventReceiverVtbl struct {
    21  	pQueryInterface   uintptr
    22  	pAddRef           uintptr
    23  	pRelease          uintptr
    24  	pGetTypeInfoCount uintptr
    25  	pGetTypeInfo      uintptr
    26  	pGetIDsOfNames    uintptr
    27  	pInvoke           uintptr
    28  }
    29  
    30  func QueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 {
    31  	s, _ := ole.StringFromCLSID(iid)
    32  	*punk = nil
    33  	if ole.IsEqualGUID(iid, ole.IID_IUnknown) ||
    34  		ole.IsEqualGUID(iid, ole.IID_IDispatch) {
    35  		AddRef(this)
    36  		*punk = this
    37  		return ole.S_OK
    38  	}
    39  	if s == "{248DD893-BB45-11CF-9ABC-0080C7E7B78D}" {
    40  		AddRef(this)
    41  		*punk = this
    42  		return ole.S_OK
    43  	}
    44  	return ole.E_NOINTERFACE
    45  }
    46  
    47  func AddRef(this *ole.IUnknown) int32 {
    48  	pthis := (*EventReceiver)(unsafe.Pointer(this))
    49  	pthis.ref++
    50  	return pthis.ref
    51  }
    52  
    53  func Release(this *ole.IUnknown) int32 {
    54  	pthis := (*EventReceiver)(unsafe.Pointer(this))
    55  	pthis.ref--
    56  	return pthis.ref
    57  }
    58  
    59  func GetIDsOfNames(this *ole.IUnknown, iid *ole.GUID, wnames []*uint16, namelen int, lcid int, pdisp []int32) uintptr {
    60  	for n := 0; n < namelen; n++ {
    61  		pdisp[n] = int32(n)
    62  	}
    63  	return uintptr(ole.S_OK)
    64  }
    65  
    66  func GetTypeInfoCount(pcount *int) uintptr {
    67  	if pcount != nil {
    68  		*pcount = 0
    69  	}
    70  	return uintptr(ole.S_OK)
    71  }
    72  
    73  func GetTypeInfo(ptypeif *uintptr) uintptr {
    74  	return uintptr(ole.E_NOTIMPL)
    75  }
    76  
    77  func Invoke(this *ole.IDispatch, dispid int, riid *ole.GUID, lcid int, flags int16, dispparams *ole.DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr {
    78  	switch dispid {
    79  	case 0:
    80  		log.Println("DataArrival")
    81  		winsock := (*EventReceiver)(unsafe.Pointer(this)).host
    82  		var data ole.VARIANT
    83  		ole.VariantInit(&data)
    84  		oleutil.CallMethod(winsock, "GetData", &data)
    85  		s := string(data.ToArray().ToByteArray())
    86  		println()
    87  		println(s)
    88  		println()
    89  	case 1:
    90  		log.Println("Connected")
    91  		winsock := (*EventReceiver)(unsafe.Pointer(this)).host
    92  		oleutil.CallMethod(winsock, "SendData", "GET / HTTP/1.0\r\n\r\n")
    93  	case 3:
    94  		log.Println("SendProgress")
    95  	case 4:
    96  		log.Println("SendComplete")
    97  	case 5:
    98  		log.Println("Close")
    99  		this.Release()
   100  	case 6:
   101  		log.Fatal("Error")
   102  	default:
   103  		log.Println(dispid)
   104  	}
   105  	return ole.E_NOTIMPL
   106  }
   107  
   108  func main() {
   109  	ole.CoInitialize(0)
   110  
   111  	unknown, err := oleutil.CreateObject("{248DD896-BB45-11CF-9ABC-0080C7E7B78D}")
   112  	if err != nil {
   113  		panic(err.Error())
   114  	}
   115  	winsock, _ := unknown.QueryInterface(ole.IID_IDispatch)
   116  	iid, _ := ole.CLSIDFromString("{248DD893-BB45-11CF-9ABC-0080C7E7B78D}")
   117  
   118  	dest := &EventReceiver{}
   119  	dest.lpVtbl = &EventReceiverVtbl{}
   120  	dest.lpVtbl.pQueryInterface = syscall.NewCallback(QueryInterface)
   121  	dest.lpVtbl.pAddRef = syscall.NewCallback(AddRef)
   122  	dest.lpVtbl.pRelease = syscall.NewCallback(Release)
   123  	dest.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(GetTypeInfoCount)
   124  	dest.lpVtbl.pGetTypeInfo = syscall.NewCallback(GetTypeInfo)
   125  	dest.lpVtbl.pGetIDsOfNames = syscall.NewCallback(GetIDsOfNames)
   126  	dest.lpVtbl.pInvoke = syscall.NewCallback(Invoke)
   127  	dest.host = winsock
   128  
   129  	oleutil.ConnectObject(winsock, iid, (*ole.IUnknown)(unsafe.Pointer(dest)))
   130  	_, err = oleutil.CallMethod(winsock, "Connect", "127.0.0.1", 80)
   131  	if err != nil {
   132  		log.Fatal(err)
   133  	}
   134  
   135  	var m ole.Msg
   136  	for dest.ref != 0 {
   137  		ole.GetMessage(&m, 0, 0, 0)
   138  		ole.DispatchMessage(&m)
   139  	}
   140  }