├── install.bat └── src ├── doc2pdf ├── main_windows.go └── office2pdf │ ├── excel_windows.go │ ├── interface_windows.go │ ├── powerpoint_windows.go │ └── word_windows.go └── github.com └── mattn └── go-ole ├── README.md ├── com.go ├── com_test.go ├── connect.go ├── connect_test.go ├── constants.go ├── data └── screenshot.png ├── example ├── excel │ └── excel.go ├── ie │ └── ie.go ├── mediaplayer │ └── mediaplayer.go ├── msagent │ └── msagent.go ├── msxml │ └── rssreader.go └── winsock │ └── winsock.go ├── iconnectionpoint.go ├── iconnectionpointcontainer.go ├── idispatch.go ├── iprovideclassinfo.go ├── itypeinfo.go ├── iunknown.go ├── ole.go ├── oleutil ├── Makefile └── oleutil.go ├── safearray.go ├── safearray_test.go ├── safearrayconversion.go ├── safearrayconversion_test.go ├── utility.go └── variables.go /install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | setlocal 4 | 5 | if exist install.bat goto ok 6 | echo install.bat must be run from its folder 7 | goto end 8 | 9 | : ok 10 | 11 | set OLDGOPATH=%GOPATH% 12 | set GOPATH=%~dp0 13 | 14 | gofmt -tabs=false -tabwidth=4 -w src 15 | 16 | go install -v doc2pdf 17 | 18 | :end 19 | echo finished -------------------------------------------------------------------------------- /src/doc2pdf/main_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | // main_windows 4 | package main 5 | 6 | import ( 7 | "doc2pdf/office2pdf" 8 | "fmt" 9 | "log" 10 | "net/http" 11 | "os" 12 | "path/filepath" 13 | "strings" 14 | ) 15 | 16 | func fileIsExist(path string) bool { 17 | if _, err := os.Stat(path); os.IsNotExist(err) { 18 | return false 19 | } 20 | return true 21 | } 22 | 23 | func exporterMap() (m map[string]interface{}) { 24 | m = map[string]interface{}{ 25 | ".doc": new(office2pdf.Word), 26 | ".docx": new(office2pdf.Word), 27 | ".xls": new(office2pdf.Excel), 28 | ".xlsx": new(office2pdf.Excel), 29 | ".ppt": new(office2pdf.PowerPoint), 30 | ".pptx": new(office2pdf.PowerPoint), 31 | } 32 | return 33 | } 34 | 35 | func export(w http.ResponseWriter, r *http.Request) { 36 | 37 | r.ParseForm() 38 | 39 | inFile, outDir := strings.Join(r.Form["infile"], ""), strings.Join(r.Form["outdir"], "") 40 | 41 | log.Println("input file: " + inFile + "\noutput dir: " + outDir) 42 | 43 | if fileIsExist(inFile) && fileIsExist(outDir) { 44 | exporter := exporterMap()[filepath.Ext(inFile)] 45 | if _, ok := exporter.(office2pdf.Exporter); ok { 46 | outFile, err := exporter.(office2pdf.Exporter).Export(inFile, outDir) 47 | if err != nil { 48 | log.Fatal(err) 49 | } 50 | log.Println("output file: " + outFile) 51 | fmt.Fprintf(w, "%v", outFile) 52 | } 53 | } 54 | } 55 | 56 | func main() { 57 | port := "9000" 58 | if len(os.Args) > 1 { 59 | port = os.Args[1] 60 | } 61 | http.HandleFunc("/", export) 62 | log.Println("Server is listening on port " + port) 63 | err := http.ListenAndServe(":"+port, nil) 64 | if err != nil { 65 | log.Fatal("ListenAndServe: ", err) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/doc2pdf/office2pdf/excel_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | // excel_windows 4 | package office2pdf 5 | 6 | import ( 7 | "github.com/mattn/go-ole" 8 | "github.com/mattn/go-ole/oleutil" 9 | "path/filepath" 10 | ) 11 | 12 | type Excel struct { 13 | app *ole.IDispatch 14 | workbooks *ole.VARIANT 15 | xls *ole.VARIANT 16 | } 17 | 18 | func (el *Excel) open(inFile string) (err error) { 19 | 20 | ole.CoInitialize(0) 21 | 22 | var unknown *ole.IUnknown 23 | 24 | unknown, err = oleutil.CreateObject("Excel.Application") 25 | if err != nil { 26 | return 27 | } 28 | 29 | el.app, err = unknown.QueryInterface(ole.IID_IDispatch) 30 | if err != nil { 31 | return 32 | } 33 | 34 | _, err = oleutil.PutProperty(el.app, "Visible", false) 35 | if err != nil { 36 | return 37 | } 38 | 39 | _, err = oleutil.PutProperty(el.app, "DisplayAlerts", false) 40 | if err != nil { 41 | return 42 | } 43 | 44 | el.workbooks, err = oleutil.GetProperty(el.app, "Workbooks") 45 | if err != nil { 46 | return 47 | } 48 | 49 | el.xls, err = oleutil.CallMethod(el.workbooks.ToIDispatch(), "Open", inFile) 50 | if err != nil { 51 | return 52 | } 53 | 54 | return 55 | } 56 | 57 | func (el *Excel) Export(inFile, outDir string) (outFile string, err error) { 58 | 59 | outFile = filepath.Join(outDir, filepath.Base(inFile+".pdf")) 60 | 61 | defer func() { 62 | if err != nil { 63 | outFile = "" 64 | } 65 | el.close() 66 | }() 67 | 68 | err = el.open(inFile) 69 | if err != nil { 70 | return 71 | } 72 | 73 | _, err = oleutil.CallMethod(el.xls.ToIDispatch(), "ExportAsFixedFormat", 0, outFile) 74 | if err != nil { 75 | return 76 | } 77 | 78 | return 79 | } 80 | 81 | func (el *Excel) close() { 82 | 83 | if el.xls != nil { 84 | oleutil.MustPutProperty(el.xls.ToIDispatch(), "Saved", true) 85 | } 86 | 87 | if el.workbooks != nil { 88 | oleutil.MustCallMethod(el.workbooks.ToIDispatch(), "Close") 89 | } 90 | 91 | if el.app != nil { 92 | oleutil.MustCallMethod(el.app, "Quit") 93 | el.app.Release() 94 | } 95 | 96 | ole.CoUninitialize() 97 | } 98 | -------------------------------------------------------------------------------- /src/doc2pdf/office2pdf/interface_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | // interface_windows 4 | package office2pdf 5 | 6 | type Exporter interface { 7 | Export(inFile, outDir string) (outFile string, err error) 8 | } 9 | -------------------------------------------------------------------------------- /src/doc2pdf/office2pdf/powerpoint_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | // powerpoint_windows 4 | package office2pdf 5 | 6 | import ( 7 | "github.com/mattn/go-ole" 8 | "github.com/mattn/go-ole/oleutil" 9 | "path/filepath" 10 | ) 11 | 12 | type PowerPoint struct { 13 | app *ole.IDispatch 14 | presentations *ole.VARIANT 15 | ppt *ole.VARIANT 16 | } 17 | 18 | func (pt *PowerPoint) open(inFile string) (err error) { 19 | 20 | ole.CoInitialize(0) 21 | 22 | var unknown *ole.IUnknown 23 | 24 | unknown, err = oleutil.CreateObject("PowerPoint.Application") 25 | if err != nil { 26 | return 27 | } 28 | 29 | pt.app, err = unknown.QueryInterface(ole.IID_IDispatch) 30 | if err != nil { 31 | return 32 | } 33 | 34 | _, err = oleutil.PutProperty(pt.app, "DisplayAlerts", 1) 35 | if err != nil { 36 | return 37 | } 38 | 39 | pt.presentations, err = oleutil.GetProperty(pt.app, "Presentations") 40 | if err != nil { 41 | return 42 | } 43 | 44 | pt.ppt, err = oleutil.CallMethod(pt.presentations.ToIDispatch(), "Open", inFile, -1, 0, 0) 45 | if err != nil { 46 | return 47 | } 48 | 49 | return 50 | } 51 | 52 | func (pt *PowerPoint) Export(inFile, outDir string) (outFile string, err error) { 53 | 54 | outFile = filepath.Join(outDir, filepath.Base(inFile+".pdf")) 55 | 56 | defer func() { 57 | if err != nil { 58 | outFile = "" 59 | } 60 | pt.close() 61 | }() 62 | 63 | err = pt.open(inFile) 64 | if err != nil { 65 | return 66 | } 67 | 68 | _, err = oleutil.CallMethod(pt.ppt.ToIDispatch(), "SaveAs", outFile, 32) 69 | if err != nil { 70 | return 71 | } 72 | 73 | return 74 | } 75 | 76 | func (pt *PowerPoint) close() { 77 | 78 | if pt.ppt != nil { 79 | oleutil.MustPutProperty(pt.ppt.ToIDispatch(), "Saved", -1) 80 | oleutil.MustCallMethod(pt.ppt.ToIDispatch(), "Close") 81 | } 82 | 83 | if pt.app != nil { 84 | oleutil.MustCallMethod(pt.app, "Quit") 85 | pt.app.Release() 86 | } 87 | 88 | ole.CoUninitialize() 89 | } 90 | -------------------------------------------------------------------------------- /src/doc2pdf/office2pdf/word_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | // word_windows 4 | package office2pdf 5 | 6 | import ( 7 | "github.com/mattn/go-ole" 8 | "github.com/mattn/go-ole/oleutil" 9 | "path/filepath" 10 | ) 11 | 12 | type Word struct { 13 | app *ole.IDispatch 14 | documents *ole.VARIANT 15 | doc *ole.VARIANT 16 | } 17 | 18 | func (wd *Word) open(inFile string) (err error) { 19 | 20 | ole.CoInitialize(0) 21 | 22 | var unknown *ole.IUnknown 23 | 24 | unknown, err = oleutil.CreateObject("Word.Application") 25 | if err != nil { 26 | return 27 | } 28 | 29 | wd.app, err = unknown.QueryInterface(ole.IID_IDispatch) 30 | if err != nil { 31 | return 32 | } 33 | 34 | _, err = oleutil.PutProperty(wd.app, "Visible", false) 35 | if err != nil { 36 | return 37 | } 38 | 39 | _, err = oleutil.PutProperty(wd.app, "DisplayAlerts", 0) 40 | if err != nil { 41 | return 42 | } 43 | 44 | wd.documents, err = oleutil.GetProperty(wd.app, "Documents") 45 | if err != nil { 46 | return 47 | } 48 | 49 | wd.doc, err = oleutil.CallMethod(wd.documents.ToIDispatch(), "Open", inFile) 50 | if err != nil { 51 | return 52 | } 53 | 54 | return 55 | } 56 | 57 | func (wd *Word) Export(inFile, outDir string) (outFile string, err error) { 58 | 59 | outFile = filepath.Join(outDir, filepath.Base(inFile+".pdf")) 60 | 61 | defer func() { 62 | if err != nil { 63 | outFile = "" 64 | } 65 | wd.close() 66 | }() 67 | 68 | err = wd.open(inFile) 69 | if err != nil { 70 | return 71 | } 72 | 73 | _, err = oleutil.CallMethod(wd.doc.ToIDispatch(), "ExportAsFixedFormat", outFile, 17) 74 | if err != nil { 75 | return 76 | } 77 | 78 | return 79 | } 80 | 81 | func (wd *Word) close() { 82 | 83 | if wd.doc != nil { 84 | oleutil.MustPutProperty(wd.doc.ToIDispatch(), "Saved", true) 85 | } 86 | 87 | if wd.documents != nil { 88 | oleutil.MustCallMethod(wd.documents.ToIDispatch(), "Close") 89 | } 90 | 91 | if wd.app != nil { 92 | oleutil.MustCallMethod(wd.app, "Quit") 93 | wd.app.Release() 94 | } 95 | 96 | ole.CoUninitialize() 97 | } 98 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/README.md: -------------------------------------------------------------------------------- 1 | go-ole 2 | ====== 3 | 4 | WHATS: 5 | ------ 6 | 7 | Go bindings for Windows COM based off of mattn Go OLE repository. 8 | 9 | INSTALL: 10 | -------- 11 | 12 | To experiment with go-ole, you can just compile and run the example 13 | program: 14 | 15 | go get github.com/mattn/go-ole 16 | cd /path/to/go-ole/ 17 | go test 18 | 19 | cd /path/to/go-ole/example/excel 20 | go run excel.go 21 | 22 | LICENSE: 23 | -------- 24 | 25 | under the MIT License: http://mattn.mit-license.org/2013 26 | 27 | AUTHOR: 28 | ------- 29 | 30 | * Yasuhiro Matsumoto 31 | * Jacob Santos 32 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/com.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | var ( 9 | procCoInitialize, _ = modole32.FindProc("CoInitialize") 10 | procCoInitializeEx, _ = modole32.FindProc("CoInitializeEx") 11 | procCoUninitialize, _ = modole32.FindProc("CoUninitialize") 12 | procCoCreateInstance, _ = modole32.FindProc("CoCreateInstance") 13 | procCLSIDFromProgID, _ = modole32.FindProc("CLSIDFromProgID") 14 | procCLSIDFromString, _ = modole32.FindProc("CLSIDFromString") 15 | procStringFromCLSID, _ = modole32.FindProc("StringFromCLSID") 16 | procStringFromIID, _ = modole32.FindProc("StringFromIID") 17 | procIIDFromString, _ = modole32.FindProc("IIDFromString") 18 | procGetUserDefaultLCID, _ = modkernel32.FindProc("GetUserDefaultLCID") 19 | procCopyMemory, _ = modkernel32.FindProc("RtlMoveMemory") 20 | procVariantInit, _ = modoleaut32.FindProc("VariantInit") 21 | procSysAllocString, _ = modoleaut32.FindProc("SysAllocString") 22 | procSysFreeString, _ = modoleaut32.FindProc("SysFreeString") 23 | procSysStringLen, _ = modoleaut32.FindProc("SysStringLen") 24 | procCreateDispTypeInfo, _ = modoleaut32.FindProc("CreateDispTypeInfo") 25 | procCreateStdDispatch, _ = modoleaut32.FindProc("CreateStdDispatch") 26 | procGetActiveObject, _ = modoleaut32.FindProc("GetActiveObject") 27 | 28 | procGetMessageW, _ = moduser32.FindProc("GetMessageW") 29 | procDispatchMessageW, _ = moduser32.FindProc("DispatchMessageW") 30 | ) 31 | 32 | func coInitialize() (err error) { 33 | // http://msdn.microsoft.com/en-us/library/windows/desktop/ms678543(v=vs.85).aspx 34 | // Suggests that no value should be passed to CoInitialized. 35 | // Could just be Call() since the parameter is optional. <-- Needs testing to be sure. 36 | hr, _, _ := procCoInitialize.Call(uintptr(0)) 37 | if hr != 0 { 38 | err = NewError(hr) 39 | } 40 | return 41 | } 42 | 43 | func coInitializeEx(coinit uint32) (err error) { 44 | // http://msdn.microsoft.com/en-us/library/windows/desktop/ms695279(v=vs.85).aspx 45 | // Suggests that the first parameter is not only optional but should always be NULL. 46 | hr, _, _ := procCoInitializeEx.Call(uintptr(0), uintptr(coinit)) 47 | if hr != 0 { 48 | err = NewError(hr) 49 | } 50 | return 51 | } 52 | 53 | func CoInitialize(p uintptr) (err error) { 54 | // p is ignored and won't be used. 55 | // Avoid any variable not used errors. 56 | p = uintptr(0) 57 | return coInitialize() 58 | } 59 | 60 | func CoInitializeEx(p uintptr, coinit uint32) (err error) { 61 | // Avoid any variable not used errors. 62 | p = uintptr(0) 63 | return coInitializeEx(coinit) 64 | } 65 | 66 | func CoUninitialize() { 67 | procCoUninitialize.Call() 68 | } 69 | 70 | func CLSIDFromProgID(progId string) (clsid *GUID, err error) { 71 | var guid GUID 72 | lpszProgID := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) 73 | hr, _, _ := procCLSIDFromProgID.Call(lpszProgID, uintptr(unsafe.Pointer(&guid))) 74 | if hr != 0 { 75 | err = NewError(hr) 76 | } 77 | clsid = &guid 78 | return 79 | } 80 | 81 | func CLSIDFromString(str string) (clsid *GUID, err error) { 82 | var guid GUID 83 | lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str))) 84 | hr, _, _ := procCLSIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) 85 | if hr != 0 { 86 | err = NewError(hr) 87 | } 88 | clsid = &guid 89 | return 90 | } 91 | 92 | func StringFromCLSID(clsid *GUID) (str string, err error) { 93 | var p *uint16 94 | hr, _, _ := procStringFromCLSID.Call(uintptr(unsafe.Pointer(clsid)), uintptr(unsafe.Pointer(&p))) 95 | if hr != 0 { 96 | err = NewError(hr) 97 | } 98 | str = UTF16PtrToString(p) 99 | return 100 | } 101 | 102 | func IIDFromString(progId string) (clsid *GUID, err error) { 103 | var guid GUID 104 | lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) 105 | hr, _, _ := procIIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) 106 | if hr != 0 { 107 | err = NewError(hr) 108 | } 109 | clsid = &guid 110 | return 111 | } 112 | 113 | func StringFromIID(iid *GUID) (str string, err error) { 114 | var p *uint16 115 | hr, _, _ := procStringFromIID.Call(uintptr(unsafe.Pointer(iid)), uintptr(unsafe.Pointer(&p))) 116 | if hr != 0 { 117 | err = NewError(hr) 118 | } 119 | str = UTF16PtrToString(p) 120 | return 121 | } 122 | 123 | func CreateInstance(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { 124 | if iid == nil { 125 | iid = IID_IUnknown 126 | } 127 | hr, _, _ := procCoCreateInstance.Call( 128 | uintptr(unsafe.Pointer(clsid)), 129 | 0, 130 | CLSCTX_SERVER, 131 | uintptr(unsafe.Pointer(iid)), 132 | uintptr(unsafe.Pointer(&unk))) 133 | if hr != 0 { 134 | err = NewError(hr) 135 | } 136 | return 137 | } 138 | 139 | func GetActiveObject(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { 140 | if iid == nil { 141 | iid = IID_IUnknown 142 | } 143 | hr, _, _ := procGetActiveObject.Call( 144 | uintptr(unsafe.Pointer(clsid)), 145 | uintptr(unsafe.Pointer(iid)), 146 | uintptr(unsafe.Pointer(&unk))) 147 | if hr != 0 { 148 | err = NewError(hr) 149 | } 150 | return 151 | } 152 | 153 | func VariantInit(v *VARIANT) (err error) { 154 | hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v))) 155 | if hr != 0 { 156 | err = NewError(hr) 157 | } 158 | return 159 | } 160 | 161 | func SysAllocString(v string) (ss *int16) { 162 | pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v)))) 163 | ss = (*int16)(unsafe.Pointer(pss)) 164 | return 165 | } 166 | 167 | func SysFreeString(v *int16) (err error) { 168 | hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v))) 169 | if hr != 0 { 170 | err = NewError(hr) 171 | } 172 | return 173 | } 174 | 175 | func SysStringLen(v *int16) uint32 { 176 | l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v))) 177 | return uint32(l) 178 | } 179 | 180 | func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (disp *IDispatch, err error) { 181 | hr, _, _ := procCreateStdDispatch.Call( 182 | uintptr(unsafe.Pointer(unk)), 183 | v, 184 | uintptr(unsafe.Pointer(ptinfo)), 185 | uintptr(unsafe.Pointer(&disp))) 186 | if hr != 0 { 187 | err = NewError(hr) 188 | } 189 | return 190 | } 191 | 192 | func CreateDispTypeInfo(idata *INTERFACEDATA) (pptinfo *IUnknown, err error) { 193 | hr, _, _ := procCreateDispTypeInfo.Call( 194 | uintptr(unsafe.Pointer(idata)), 195 | uintptr(GetUserDefaultLCID()), 196 | uintptr(unsafe.Pointer(&pptinfo))) 197 | if hr != 0 { 198 | err = NewError(hr) 199 | } 200 | return 201 | } 202 | 203 | func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) { 204 | procCopyMemory.Call(uintptr(dest), uintptr(src), uintptr(length)) 205 | } 206 | 207 | func GetUserDefaultLCID() (lcid uint32) { 208 | ret, _, _ := procGetUserDefaultLCID.Call() 209 | lcid = uint32(ret) 210 | return 211 | } 212 | 213 | func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) { 214 | r0, _, err := procGetMessageW.Call(uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax)) 215 | ret = int32(r0) 216 | return 217 | } 218 | 219 | func DispatchMessage(msg *Msg) (ret int32) { 220 | r0, _, _ := procDispatchMessageW.Call(uintptr(unsafe.Pointer(msg))) 221 | ret = int32(r0) 222 | return 223 | } 224 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/com_test.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestComSetupAndShutDown(t *testing.T) { 9 | defer func() { 10 | if r := recover(); r != nil { 11 | t.Log(r) 12 | t.Fail() 13 | } 14 | }() 15 | 16 | coInitialize() 17 | CoUninitialize() 18 | } 19 | 20 | func TestComPublicSetupAndShutDown(t *testing.T) { 21 | defer func() { 22 | if r := recover(); r != nil { 23 | t.Log(r) 24 | t.Fail() 25 | } 26 | }() 27 | 28 | CoInitialize(0) 29 | CoUninitialize() 30 | } 31 | 32 | func TestComPublicSetupAndShutDown_WithValue(t *testing.T) { 33 | defer func() { 34 | if r := recover(); r != nil { 35 | t.Log(r) 36 | t.Fail() 37 | } 38 | }() 39 | 40 | CoInitialize(5) 41 | CoUninitialize() 42 | } 43 | 44 | func TestComExSetupAndShutDown(t *testing.T) { 45 | defer func() { 46 | if r := recover(); r != nil { 47 | t.Log(r) 48 | t.Fail() 49 | } 50 | }() 51 | 52 | coInitializeEx(COINIT_MULTITHREADED) 53 | CoUninitialize() 54 | } 55 | 56 | func TestComPublicExSetupAndShutDown(t *testing.T) { 57 | defer func() { 58 | if r := recover(); r != nil { 59 | t.Log(r) 60 | t.Fail() 61 | } 62 | }() 63 | 64 | CoInitializeEx(0, COINIT_MULTITHREADED) 65 | CoUninitialize() 66 | } 67 | 68 | func TestComPublicExSetupAndShutDown_WithValue(t *testing.T) { 69 | defer func() { 70 | if r := recover(); r != nil { 71 | t.Log(r) 72 | t.Fail() 73 | } 74 | }() 75 | 76 | CoInitializeEx(5, COINIT_MULTITHREADED) 77 | CoUninitialize() 78 | } 79 | 80 | func TestClsidFromProgID_WindowsMediaNSSManager(t *testing.T) { 81 | defer func() { 82 | if r := recover(); r != nil { 83 | t.Log(r) 84 | t.Fail() 85 | } 86 | }() 87 | 88 | expected := &GUID{0x92498132, 0x4D1A, 0x4297, [8]byte{0x9B, 0x78, 0x9E, 0x2E, 0x4B, 0xA9, 0x9C, 0x07}} 89 | 90 | coInitialize() 91 | defer CoUninitialize() 92 | actual, err := CLSIDFromProgID("WMPNSSCI.NSSManager") 93 | if err == nil { 94 | if !IsEqualGUID(expected, actual) { 95 | t.Log(err) 96 | t.Log(fmt.Sprintf("Actual GUID: %+v\n", actual)) 97 | t.Fail() 98 | } 99 | } 100 | } 101 | 102 | func TestClsidFromString_WindowsMediaNSSManager(t *testing.T) { 103 | defer func() { 104 | if r := recover(); r != nil { 105 | t.Log(r) 106 | t.Fail() 107 | } 108 | }() 109 | 110 | expected := &GUID{0x92498132, 0x4D1A, 0x4297, [8]byte{0x9B, 0x78, 0x9E, 0x2E, 0x4B, 0xA9, 0x9C, 0x07}} 111 | 112 | coInitialize() 113 | defer CoUninitialize() 114 | actual, err := CLSIDFromString("{92498132-4D1A-4297-9B78-9E2E4BA99C07}") 115 | 116 | if !IsEqualGUID(expected, actual) { 117 | t.Log(err) 118 | t.Log(fmt.Sprintf("Actual GUID: %+v\n", actual)) 119 | t.Fail() 120 | } 121 | } 122 | 123 | func TestCreateInstance_WindowsMediaNSSManager(t *testing.T) { 124 | defer func() { 125 | if r := recover(); r != nil { 126 | t.Log(r) 127 | t.Fail() 128 | } 129 | }() 130 | 131 | expected := &GUID{0x92498132, 0x4D1A, 0x4297, [8]byte{0x9B, 0x78, 0x9E, 0x2E, 0x4B, 0xA9, 0x9C, 0x07}} 132 | 133 | coInitialize() 134 | defer CoUninitialize() 135 | actual, err := CLSIDFromProgID("WMPNSSCI.NSSManager") 136 | 137 | if err == nil { 138 | if !IsEqualGUID(expected, actual) { 139 | t.Log(err) 140 | t.Log(fmt.Sprintf("Actual GUID: %+v\n", actual)) 141 | t.Fail() 142 | } 143 | 144 | unknown, err := CreateInstance(actual, IID_IUnknown) 145 | if err != nil { 146 | t.Log(err) 147 | t.Fail() 148 | } 149 | unknown.Release() 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/connect.go: -------------------------------------------------------------------------------- 1 | // Helpers for COM 2 | package ole 3 | 4 | import () 5 | 6 | type Connection struct { 7 | Object *IUnknown // Access COM 8 | } 9 | 10 | func (*Connection) Initialize() (err error) { 11 | return coInitialize() 12 | } 13 | 14 | func (*Connection) Uninitialize() { 15 | CoUninitialize() 16 | } 17 | 18 | // Creates Unknown object based first on ProgId and then from String. 19 | func (c *Connection) Create(progId string) (err error) { 20 | var clsid *GUID 21 | clsid, err = CLSIDFromProgID(progId) 22 | if err != nil { 23 | clsid, err = CLSIDFromString(progId) 24 | if err != nil { 25 | return 26 | } 27 | } 28 | 29 | unknown, err := CreateInstance(clsid, IID_IUnknown) 30 | if err != nil { 31 | return 32 | } 33 | c.Object = unknown 34 | 35 | return 36 | } 37 | 38 | func (c *Connection) Release() { 39 | c.Object.Release() 40 | } 41 | 42 | // Loads COM object if in list 43 | func (c *Connection) Load(names ...string) (errors []error) { 44 | var tempErrors []error = make([]error, len(names)) 45 | var numErrors int = 0 46 | for _, name := range names { 47 | err := c.Create(name) 48 | if err != nil { 49 | tempErrors = append(tempErrors, err) 50 | numErrors += 1 51 | continue 52 | } 53 | break 54 | } 55 | 56 | copy(errors, tempErrors[0:numErrors]) 57 | return 58 | } 59 | 60 | func (c *Connection) Dispatch() (object *Dispatch, err error) { 61 | dispatch, err := c.Object.QueryInterface(IID_IDispatch) 62 | if err != nil { 63 | return 64 | } 65 | object = &Dispatch{dispatch} 66 | return 67 | } 68 | 69 | type Dispatch struct { 70 | Object *IDispatch // Dispatch object. 71 | } 72 | 73 | func (d *Dispatch) Call(method string, params ...interface{}) (result *VARIANT, err error) { 74 | id, err := d.GetId(method) 75 | if err != nil { 76 | return 77 | } 78 | 79 | result, err = d.Invoke(id, DISPATCH_METHOD, params) 80 | return 81 | } 82 | 83 | func (d *Dispatch) MustCall(method string, params ...interface{}) (result *VARIANT) { 84 | id, err := d.GetId(method) 85 | if err != nil { 86 | panic(err) 87 | } 88 | 89 | result, err = d.Invoke(id, DISPATCH_METHOD, params) 90 | if err != nil { 91 | panic(err) 92 | } 93 | 94 | return 95 | } 96 | 97 | func (d *Dispatch) Get(name string, params ...interface{}) (result *VARIANT, err error) { 98 | id, err := d.GetId(name) 99 | if err != nil { 100 | return 101 | } 102 | result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) 103 | return 104 | } 105 | 106 | func (d *Dispatch) MustGet(name string, params ...interface{}) (result *VARIANT) { 107 | id, err := d.GetId(name) 108 | if err != nil { 109 | panic(err) 110 | } 111 | 112 | result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) 113 | if err != nil { 114 | panic(err) 115 | } 116 | return 117 | } 118 | 119 | func (d *Dispatch) Set(name string, params ...interface{}) (result *VARIANT, err error) { 120 | id, err := d.GetId(name) 121 | if err != nil { 122 | return 123 | } 124 | result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) 125 | return 126 | } 127 | 128 | func (d *Dispatch) MustSet(name string, params ...interface{}) (result *VARIANT) { 129 | id, err := d.GetId(name) 130 | if err != nil { 131 | panic(err) 132 | } 133 | 134 | result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) 135 | if err != nil { 136 | panic(err) 137 | } 138 | return 139 | } 140 | 141 | func (d *Dispatch) GetId(name string) (id int32, err error) { 142 | var dispid []int32 143 | dispid, err = d.Object.GetIDsOfName([]string{name}) 144 | if err != nil { 145 | return 146 | } 147 | id = dispid[0] 148 | return 149 | } 150 | 151 | func (d *Dispatch) GetIds(names ...string) (dispid []int32, err error) { 152 | dispid, err = d.Object.GetIDsOfName(names) 153 | return 154 | } 155 | 156 | // There have been problems where if send cascading params..., it would error out because the 157 | // parameters would be empty. 158 | func (d *Dispatch) Invoke(id int32, dispatch int16, params []interface{}) (result *VARIANT, err error) { 159 | if len(params) < 1 { 160 | result, err = d.Object.Invoke(id, dispatch) 161 | } else { 162 | result, err = d.Object.Invoke(id, dispatch, params...) 163 | } 164 | return 165 | } 166 | 167 | func (d *Dispatch) Release() { 168 | d.Object.Release() 169 | } 170 | 171 | func Connect(names ...string) (connection *Connection) { 172 | connection.Initialize() 173 | connection.Load(names...) 174 | return 175 | } 176 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/connect_test.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "testing" 7 | _ "unsafe" 8 | ) 9 | 10 | func TestConnectHelper_QuickBooks(t *testing.T) { 11 | var err error 12 | 13 | connection := &Connection{nil} 14 | 15 | err = connection.Initialize() 16 | if err != nil { 17 | t.Log(err) 18 | t.FailNow() 19 | } 20 | defer connection.Uninitialize() 21 | 22 | err = connection.Create("QBXMLRP2.RequestProcessor.1") 23 | if err != nil { 24 | if err.(OleError).Code() == CO_E_CLASSSTRING { 25 | return 26 | } 27 | t.Log(err) 28 | t.FailNow() 29 | } 30 | defer connection.Release() 31 | 32 | dispatch, err := connection.Dispatch() 33 | if err != nil { 34 | t.Log(err) 35 | t.FailNow() 36 | } 37 | defer dispatch.Release() 38 | } 39 | 40 | func TestConnectHelperCallDispatch_QuickBooks(t *testing.T) { 41 | var err error 42 | 43 | connection := &Connection{nil} 44 | 45 | err = connection.Initialize() 46 | if err != nil { 47 | t.Log(err) 48 | t.FailNow() 49 | } 50 | defer connection.Uninitialize() 51 | 52 | err = connection.Create("QBXMLRP2.RequestProcessor.1") 53 | if err != nil { 54 | if err.(OleError).Code() == CO_E_CLASSSTRING { 55 | return 56 | } 57 | t.Log(err) 58 | t.FailNow() 59 | } 60 | defer connection.Release() 61 | 62 | dispatch, err := connection.Dispatch() 63 | if err != nil { 64 | t.Log(err) 65 | t.FailNow() 66 | } 67 | defer dispatch.Release() 68 | 69 | var result *VARIANT 70 | 71 | _, err = dispatch.Call("OpenConnection2", "", "Test Application 1", 1) 72 | if err != nil { 73 | t.Log(err) 74 | t.FailNow() 75 | } 76 | 77 | result, err = dispatch.Call("BeginSession", "", 2) 78 | if err != nil { 79 | t.Log(err) 80 | t.FailNow() 81 | } 82 | 83 | ticket := result.ToString() 84 | 85 | _, err = dispatch.Call("EndSession", ticket) 86 | if err != nil { 87 | t.Log(err) 88 | t.Fail() 89 | } 90 | 91 | _, err = dispatch.Call("CloseConnection") 92 | if err != nil { 93 | t.Log(err) 94 | t.Fail() 95 | } 96 | } 97 | 98 | func TestConnectHelperDispatchProperty_QuickBooks(t *testing.T) { 99 | var err error 100 | 101 | connection := &Connection{nil} 102 | 103 | err = connection.Initialize() 104 | if err != nil { 105 | t.Log(err) 106 | t.FailNow() 107 | } 108 | defer connection.Uninitialize() 109 | 110 | err = connection.Create("QBXMLRP2.RequestProcessor.1") 111 | if err != nil { 112 | if err.(OleError).Code() == CO_E_CLASSSTRING { 113 | return 114 | } 115 | t.Log(err) 116 | t.FailNow() 117 | } 118 | defer connection.Release() 119 | 120 | dispatch, err := connection.Dispatch() 121 | if err != nil { 122 | t.Log(err) 123 | t.FailNow() 124 | } 125 | defer dispatch.Release() 126 | 127 | var result *VARIANT 128 | 129 | _, err = dispatch.Call("OpenConnection2", "", "Test Application 1", 1) 130 | if err != nil { 131 | t.Log(err) 132 | t.FailNow() 133 | } 134 | 135 | result, err = dispatch.Call("BeginSession", "", 2) 136 | if err != nil { 137 | t.Log(err) 138 | t.FailNow() 139 | } 140 | 141 | ticket := result.ToString() 142 | 143 | result, err = dispatch.Get("QBXMLVersionsForSession", ticket) 144 | if err != nil { 145 | t.Log(err) 146 | t.FailNow() 147 | } 148 | 149 | conversion := result.ToArray() 150 | 151 | totalElements, _ := conversion.TotalElements(0) 152 | if totalElements != 13 { 153 | t.Log(fmt.Sprintf("%d total elements does not equal 13\n", totalElements)) 154 | t.Fail() 155 | } 156 | 157 | versions := conversion.ToStringArray() 158 | expectedVersionString := "1.0, 1.1, 2.0, 2.1, 3.0, 4.0, 4.1, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0" 159 | versionString := strings.Join(versions, ", ") 160 | 161 | if len(versions) != 13 { 162 | t.Log(fmt.Sprintf("%s\n", versionString)) 163 | t.Fail() 164 | } 165 | 166 | if expectedVersionString != versionString { 167 | t.Log(fmt.Sprintf("Expected: %s\nActual: %s", expectedVersionString, versionString)) 168 | t.Fail() 169 | } 170 | 171 | conversion.Release() 172 | 173 | _, err = dispatch.Call("EndSession", ticket) 174 | if err != nil { 175 | t.Log(err) 176 | t.Fail() 177 | } 178 | 179 | _, err = dispatch.Call("CloseConnection") 180 | if err != nil { 181 | t.Log(err) 182 | t.Fail() 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/constants.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import () 4 | 5 | const ( 6 | CLSCTX_INPROC_SERVER = 1 7 | CLSCTX_INPROC_HANDLER = 2 8 | CLSCTX_LOCAL_SERVER = 4 9 | CLSCTX_INPROC_SERVER16 = 8 10 | CLSCTX_REMOTE_SERVER = 16 11 | CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER 12 | CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER 13 | CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER 14 | ) 15 | 16 | const ( 17 | COINIT_APARTMENTTHREADED = 0x2 18 | COINIT_MULTITHREADED = 0x0 19 | COINIT_DISABLE_OLE1DDE = 0x4 20 | COINIT_SPEED_OVER_MEMORY = 0x8 21 | ) 22 | 23 | const ( 24 | DISPATCH_METHOD = 1 25 | DISPATCH_PROPERTYGET = 2 26 | DISPATCH_PROPERTYPUT = 4 27 | DISPATCH_PROPERTYPUTREF = 8 28 | ) 29 | 30 | const ( 31 | S_OK = 0x00000000 32 | E_UNEXPECTED = 0x8000FFFF 33 | E_NOTIMPL = 0x80004001 34 | E_OUTOFMEMORY = 0x8007000E 35 | E_INVALIDARG = 0x80070057 36 | E_NOINTERFACE = 0x80004002 37 | E_POINTER = 0x80004003 38 | E_HANDLE = 0x80070006 39 | E_ABORT = 0x80004004 40 | E_FAIL = 0x80004005 41 | E_ACCESSDENIED = 0x80070005 42 | E_PENDING = 0x8000000A 43 | 44 | CO_E_CLASSSTRING = 0x800401F3 45 | ) 46 | 47 | const ( 48 | CC_FASTCALL = iota 49 | CC_CDECL 50 | CC_MSCPASCAL 51 | CC_PASCAL = CC_MSCPASCAL 52 | CC_MACPASCAL 53 | CC_STDCALL 54 | CC_FPFASTCALL 55 | CC_SYSCALL 56 | CC_MPWCDECL 57 | CC_MPWPASCAL 58 | CC_MAX = CC_MPWPASCAL 59 | ) 60 | 61 | const ( 62 | VT_EMPTY = 0x0 63 | VT_NULL = 0x1 64 | VT_I2 = 0x2 65 | VT_I4 = 0x3 66 | VT_R4 = 0x4 67 | VT_R8 = 0x5 68 | VT_CY = 0x6 69 | VT_DATE = 0x7 70 | VT_BSTR = 0x8 71 | VT_DISPATCH = 0x9 72 | VT_ERROR = 0xa 73 | VT_BOOL = 0xb 74 | VT_VARIANT = 0xc 75 | VT_UNKNOWN = 0xd 76 | VT_DECIMAL = 0xe 77 | VT_I1 = 0x10 78 | VT_UI1 = 0x11 79 | VT_UI2 = 0x12 80 | VT_UI4 = 0x13 81 | VT_I8 = 0x14 82 | VT_UI8 = 0x15 83 | VT_INT = 0x16 84 | VT_UINT = 0x17 85 | VT_VOID = 0x18 86 | VT_HRESULT = 0x19 87 | VT_PTR = 0x1a 88 | VT_SAFEARRAY = 0x1b 89 | VT_CARRAY = 0x1c 90 | VT_USERDEFINED = 0x1d 91 | VT_LPSTR = 0x1e 92 | VT_LPWSTR = 0x1f 93 | VT_RECORD = 0x24 94 | VT_INT_PTR = 0x25 95 | VT_UINT_PTR = 0x26 96 | VT_FILETIME = 0x40 97 | VT_BLOB = 0x41 98 | VT_STREAM = 0x42 99 | VT_STORAGE = 0x43 100 | VT_STREAMED_OBJECT = 0x44 101 | VT_STORED_OBJECT = 0x45 102 | VT_BLOB_OBJECT = 0x46 103 | VT_CF = 0x47 104 | VT_CLSID = 0x48 105 | VT_BSTR_BLOB = 0xfff 106 | VT_VECTOR = 0x1000 107 | VT_ARRAY = 0x2000 108 | VT_BYREF = 0x4000 109 | VT_RESERVED = 0x8000 110 | VT_ILLEGAL = 0xffff 111 | VT_ILLEGALMASKED = 0xfff 112 | VT_TYPEMASK = 0xfff 113 | ) 114 | 115 | const ( 116 | DISPID_UNKNOWN = -1 117 | DISPID_VALUE = 0 118 | DISPID_PROPERTYPUT = -3 119 | DISPID_NEWENUM = -4 120 | DISPID_EVALUATE = -5 121 | DISPID_CONSTRUCTOR = -6 122 | DISPID_DESTRUCTOR = -7 123 | DISPID_COLLECT = -8 124 | ) 125 | 126 | const ( 127 | TKIND_ENUM = 1 128 | TKIND_RECORD = 2 129 | TKIND_MODULE = 3 130 | TKIND_INTERFACE = 4 131 | TKIND_DISPATCH = 5 132 | TKIND_COCLASS = 6 133 | TKIND_ALIAS = 7 134 | TKIND_UNION = 8 135 | TKIND_MAX = 9 136 | ) 137 | 138 | // Safe Array Feature Flags 139 | 140 | const ( 141 | FADF_AUTO = 0x0001 142 | FADF_STATIC = 0x0002 143 | FADF_EMBEDDED = 0x0004 144 | FADF_FIXEDSIZE = 0x0010 145 | FADF_RECORD = 0x0020 146 | FADF_HAVEIID = 0x0040 147 | FADF_HAVEVARTYPE = 0x0080 148 | FADF_BSTR = 0x0100 149 | FADF_UNKNOWN = 0x0200 150 | FADF_DISPATCH = 0x0400 151 | FADF_VARIANT = 0x0800 152 | FADF_RESERVED = 0xF008 153 | ) 154 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/data/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piaobocpp/doc2pdf-go/0f773dba5c8d1554caa7856043ba8522b569687c/src/github.com/mattn/go-ole/data/screenshot.png -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/example/excel/excel.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/mattn/go-ole" 5 | "github.com/mattn/go-ole/oleutil" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | ole.CoInitialize(0) 11 | unknown, _ := oleutil.CreateObject("Excel.Application") 12 | excel, _ := unknown.QueryInterface(ole.IID_IDispatch) 13 | oleutil.PutProperty(excel, "Visible", true) 14 | workbooks := oleutil.MustGetProperty(excel, "Workbooks").ToIDispatch() 15 | workbook := oleutil.MustCallMethod(workbooks, "Add", nil).ToIDispatch() 16 | worksheet := oleutil.MustGetProperty(workbook, "Worksheets", 1).ToIDispatch() 17 | cell := oleutil.MustGetProperty(worksheet, "Cells", 1, 1).ToIDispatch() 18 | oleutil.PutProperty(cell, "Value", 12345) 19 | 20 | time.Sleep(2000000000) 21 | 22 | oleutil.PutProperty(workbook, "Saved", true) 23 | oleutil.CallMethod(workbook, "Close", false) 24 | oleutil.CallMethod(excel, "Quit") 25 | excel.Release() 26 | 27 | ole.CoUninitialize() 28 | } 29 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/example/ie/ie.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/mattn/go-ole" 5 | "github.com/mattn/go-ole/oleutil" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | ole.CoInitialize(0) 11 | unknown, _ := oleutil.CreateObject("InternetExplorer.Application") 12 | ie, _ := unknown.QueryInterface(ole.IID_IDispatch) 13 | oleutil.CallMethod(ie, "Navigate", "http://www.google.com") 14 | oleutil.PutProperty(ie, "Visible", true) 15 | for { 16 | if oleutil.MustGetProperty(ie, "Busy").Val == 0 { 17 | break 18 | } 19 | } 20 | 21 | time.Sleep(1e9) 22 | 23 | document := oleutil.MustGetProperty(ie, "document").ToIDispatch() 24 | window := oleutil.MustGetProperty(document, "parentWindow").ToIDispatch() 25 | // set 'golang' to text box. 26 | oleutil.MustCallMethod(window, "eval", "document.getElementsByName('q')[0].value = 'golang'") 27 | // click btnG. 28 | btnG := oleutil.MustCallMethod(window, "eval", "document.getElementsByName('btnG')[0]").ToIDispatch() 29 | oleutil.MustCallMethod(btnG, "click") 30 | } 31 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/example/mediaplayer/mediaplayer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/mattn/go-ole" 6 | "github.com/mattn/go-ole/oleutil" 7 | "log" 8 | ) 9 | 10 | func main() { 11 | ole.CoInitialize(0) 12 | unknown, err := oleutil.CreateObject("WMPlayer.OCX") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | wmp := unknown.MustQueryInterface(ole.IID_IDispatch) 17 | collection := oleutil.MustGetProperty(wmp, "MediaCollection").ToIDispatch() 18 | list := oleutil.MustCallMethod(collection, "getAll").ToIDispatch() 19 | count := int(oleutil.MustGetProperty(list, "count").Val) 20 | for i := 0; i < count; i++ { 21 | item := oleutil.MustGetProperty(list, "item", i).ToIDispatch() 22 | name := oleutil.MustGetProperty(item, "name").ToString() 23 | sourceURL := oleutil.MustGetProperty(item, "sourceURL").ToString() 24 | fmt.Println(name, sourceURL) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/example/msagent/msagent.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/mattn/go-ole" 5 | "time" 6 | ) 7 | import "github.com/mattn/go-ole/oleutil" 8 | 9 | func main() { 10 | ole.CoInitialize(0) 11 | unknown, _ := oleutil.CreateObject("Agent.Control.1") 12 | agent, _ := unknown.QueryInterface(ole.IID_IDispatch) 13 | oleutil.PutProperty(agent, "Connected", true) 14 | characters := oleutil.MustGetProperty(agent, "Characters").ToIDispatch() 15 | oleutil.CallMethod(characters, "Load", "Merlin", "c:\\windows\\msagent\\chars\\Merlin.acs") 16 | character := oleutil.MustCallMethod(characters, "Character", "Merlin").ToIDispatch() 17 | oleutil.CallMethod(character, "Show") 18 | oleutil.CallMethod(character, "Speak", "こんにちわ世界") 19 | 20 | time.Sleep(4000000000) 21 | } 22 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/example/msxml/rssreader.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/mattn/go-ole" 5 | "time" 6 | ) 7 | import "github.com/mattn/go-ole/oleutil" 8 | 9 | func main() { 10 | ole.CoInitialize(0) 11 | unknown, _ := oleutil.CreateObject("Microsoft.XMLHTTP") 12 | xmlhttp, _ := unknown.QueryInterface(ole.IID_IDispatch) 13 | oleutil.CallMethod(xmlhttp, "open", "GET", "http://rss.slashdot.org/Slashdot/slashdot", false) 14 | oleutil.CallMethod(xmlhttp, "send", nil) 15 | state := -1 16 | for state != 4 { 17 | state = int(oleutil.MustGetProperty(xmlhttp, "readyState").Val) 18 | time.Sleep(10000000) 19 | } 20 | responseXml := oleutil.MustGetProperty(xmlhttp, "responseXml").ToIDispatch() 21 | items := oleutil.MustCallMethod(responseXml, "selectNodes", "rdf:RDF/item").ToIDispatch() 22 | length := int(oleutil.MustGetProperty(items, "length").Val) 23 | 24 | for n := 0; n < length; n++ { 25 | item := oleutil.MustGetProperty(items, "item", n).ToIDispatch() 26 | 27 | title := oleutil.MustCallMethod(item, "selectSingleNode", "title").ToIDispatch() 28 | println(oleutil.MustGetProperty(title, "text").ToString()) 29 | 30 | link := oleutil.MustCallMethod(item, "selectSingleNode", "link").ToIDispatch() 31 | println(" " + oleutil.MustGetProperty(link, "text").ToString()) 32 | 33 | title.Release() 34 | link.Release() 35 | item.Release() 36 | } 37 | items.Release() 38 | xmlhttp.Release() 39 | } 40 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/example/winsock/winsock.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/mattn/go-ole" 5 | "github.com/mattn/go-ole/oleutil" 6 | "log" 7 | "syscall" 8 | "unsafe" 9 | ) 10 | 11 | type EventReceiver struct { 12 | lpVtbl *EventReceiverVtbl 13 | ref int32 14 | host *ole.IDispatch 15 | } 16 | 17 | type EventReceiverVtbl struct { 18 | pQueryInterface uintptr 19 | pAddRef uintptr 20 | pRelease uintptr 21 | pGetTypeInfoCount uintptr 22 | pGetTypeInfo uintptr 23 | pGetIDsOfNames uintptr 24 | pInvoke uintptr 25 | } 26 | 27 | func QueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 { 28 | s, _ := ole.StringFromCLSID(iid) 29 | *punk = nil 30 | if ole.IsEqualGUID(iid, ole.IID_IUnknown) || 31 | ole.IsEqualGUID(iid, ole.IID_IDispatch) { 32 | AddRef(this) 33 | *punk = this 34 | return ole.S_OK 35 | } 36 | if s == "{248DD893-BB45-11CF-9ABC-0080C7E7B78D}" { 37 | AddRef(this) 38 | *punk = this 39 | return ole.S_OK 40 | } 41 | return ole.E_NOINTERFACE 42 | } 43 | 44 | func AddRef(this *ole.IUnknown) int32 { 45 | pthis := (*EventReceiver)(unsafe.Pointer(this)) 46 | pthis.ref++ 47 | return pthis.ref 48 | } 49 | 50 | func Release(this *ole.IUnknown) int32 { 51 | pthis := (*EventReceiver)(unsafe.Pointer(this)) 52 | pthis.ref-- 53 | return pthis.ref 54 | } 55 | 56 | func GetIDsOfNames(this *ole.IUnknown, iid *ole.GUID, wnames []*uint16, namelen int, lcid int, pdisp []int32) uintptr { 57 | for n := 0; n < namelen; n++ { 58 | pdisp[n] = int32(n) 59 | } 60 | return uintptr(ole.S_OK) 61 | } 62 | 63 | func GetTypeInfoCount(pcount *int) uintptr { 64 | if pcount != nil { 65 | *pcount = 0 66 | } 67 | return uintptr(ole.S_OK) 68 | } 69 | 70 | func GetTypeInfo(ptypeif *uintptr) uintptr { 71 | return uintptr(ole.E_NOTIMPL) 72 | } 73 | 74 | 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 { 75 | switch dispid { 76 | case 0: 77 | log.Println("DataArrival") 78 | winsock := (*EventReceiver)(unsafe.Pointer(this)).host 79 | var data ole.VARIANT 80 | ole.VariantInit(&data) 81 | oleutil.CallMethod(winsock, "GetData", &data) 82 | array := (*ole.SAFEARRAY)(unsafe.Pointer(uintptr(data.Val))) 83 | s := ole.BytePtrToString((*byte)(unsafe.Pointer(uintptr(array.PvData)))) 84 | println() 85 | println(s) 86 | println() 87 | case 1: 88 | log.Println("Connected") 89 | winsock := (*EventReceiver)(unsafe.Pointer(this)).host 90 | oleutil.CallMethod(winsock, "SendData", "GET / HTTP/1.0\r\n\r\n") 91 | case 3: 92 | log.Println("SendProgress") 93 | case 4: 94 | log.Println("SendComplete") 95 | case 5: 96 | log.Println("Close") 97 | this.Release() 98 | case 6: 99 | log.Fatal("Error") 100 | default: 101 | log.Println(dispid) 102 | } 103 | return ole.E_NOTIMPL 104 | } 105 | 106 | func main() { 107 | ole.CoInitialize(0) 108 | 109 | unknown, _ := oleutil.CreateObject("{248DD896-BB45-11CF-9ABC-0080C7E7B78D}") 110 | winsock, _ := unknown.QueryInterface(ole.IID_IDispatch) 111 | iid, _ := ole.CLSIDFromString("{248DD893-BB45-11CF-9ABC-0080C7E7B78D}") 112 | 113 | dest := &EventReceiver{} 114 | dest.lpVtbl = &EventReceiverVtbl{} 115 | dest.lpVtbl.pQueryInterface = syscall.NewCallback(QueryInterface) 116 | dest.lpVtbl.pAddRef = syscall.NewCallback(AddRef) 117 | dest.lpVtbl.pRelease = syscall.NewCallback(Release) 118 | dest.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(GetTypeInfoCount) 119 | dest.lpVtbl.pGetTypeInfo = syscall.NewCallback(GetTypeInfo) 120 | dest.lpVtbl.pGetIDsOfNames = syscall.NewCallback(GetIDsOfNames) 121 | dest.lpVtbl.pInvoke = syscall.NewCallback(Invoke) 122 | dest.host = winsock 123 | 124 | oleutil.ConnectObject(winsock, iid, (*ole.IUnknown)(unsafe.Pointer(dest))) 125 | _, err := oleutil.CallMethod(winsock, "Connect", "127.0.0.1", 80) 126 | if err != nil { 127 | log.Fatal(err) 128 | } 129 | 130 | var m ole.Msg 131 | for dest.ref != 0 { 132 | ole.GetMessage(&m, 0, 0, 0) 133 | ole.DispatchMessage(&m) 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/iconnectionpoint.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | type IConnectionPoint struct { 9 | lpVtbl *pIConnectionPointVtbl 10 | } 11 | 12 | type pIConnectionPointVtbl struct { 13 | pQueryInterface uintptr 14 | pAddRef uintptr 15 | pRelease uintptr 16 | pGetConnectionInterface uintptr 17 | pGetConnectionPointContainer uintptr 18 | pAdvise uintptr 19 | pUnadvise uintptr 20 | pEnumConnections uintptr 21 | } 22 | 23 | func (v *IConnectionPoint) QueryInterface(iid *GUID) (disp *IDispatch, err error) { 24 | disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid) 25 | return 26 | } 27 | 28 | func (v *IConnectionPoint) AddRef() int32 { 29 | return addRef((*IUnknown)(unsafe.Pointer(v))) 30 | } 31 | 32 | func (v *IConnectionPoint) Release() int32 { 33 | return release((*IUnknown)(unsafe.Pointer(v))) 34 | } 35 | 36 | func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 { 37 | return release((*IUnknown)(unsafe.Pointer(v))) 38 | } 39 | 40 | func (v *IConnectionPoint) Advise(unknown *IUnknown) (cookie uint32, err error) { 41 | hr, _, _ := syscall.Syscall( 42 | uintptr(v.lpVtbl.pAdvise), 43 | 3, 44 | uintptr(unsafe.Pointer(v)), 45 | uintptr(unsafe.Pointer(unknown)), 46 | uintptr(unsafe.Pointer(&cookie))) 47 | if hr != 0 { 48 | err = NewError(hr) 49 | } 50 | return 51 | } 52 | 53 | func (v *IConnectionPoint) Unadvise(cookie uint32) (err error) { 54 | hr, _, _ := syscall.Syscall( 55 | uintptr(v.lpVtbl.pAdvise), 56 | 2, 57 | uintptr(unsafe.Pointer(v)), 58 | uintptr(cookie), 59 | 0) 60 | if hr != 0 { 61 | err = NewError(hr) 62 | } 63 | return 64 | } 65 | 66 | func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) (err error) { 67 | return NewError(E_NOTIMPL) 68 | } 69 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/iconnectionpointcontainer.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | type IConnectionPointContainer struct { 9 | lpVtbl *pIConnectionPointContainerVtbl 10 | } 11 | 12 | type pIConnectionPointContainerVtbl struct { 13 | pQueryInterface uintptr 14 | pAddRef uintptr 15 | pRelease uintptr 16 | pEnumConnectionPoints uintptr 17 | pFindConnectionPoint uintptr 18 | } 19 | 20 | func (v *IConnectionPointContainer) QueryInterface(iid *GUID) (disp *IDispatch, err error) { 21 | disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid) 22 | return 23 | } 24 | 25 | func (v *IConnectionPointContainer) AddRef() int32 { 26 | return addRef((*IUnknown)(unsafe.Pointer(v))) 27 | } 28 | 29 | func (v *IConnectionPointContainer) Release() int32 { 30 | return release((*IUnknown)(unsafe.Pointer(v))) 31 | } 32 | 33 | func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) (err error) { 34 | err = NewError(E_NOTIMPL) 35 | return 36 | } 37 | 38 | func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) (err error) { 39 | hr, _, _ := syscall.Syscall( 40 | uintptr(v.lpVtbl.pFindConnectionPoint), 41 | 3, 42 | uintptr(unsafe.Pointer(v)), 43 | uintptr(unsafe.Pointer(iid)), 44 | uintptr(unsafe.Pointer(point))) 45 | if hr != 0 { 46 | err = NewError(hr) 47 | } 48 | return 49 | } 50 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/idispatch.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | type IDispatch struct { 9 | lpVtbl *pIDispatchVtbl 10 | } 11 | 12 | type pIDispatchVtbl struct { 13 | pQueryInterface uintptr 14 | pAddRef uintptr 15 | pRelease uintptr 16 | pGetTypeInfoCount uintptr 17 | pGetTypeInfo uintptr 18 | pGetIDsOfNames uintptr 19 | pInvoke uintptr 20 | } 21 | 22 | func (v *IDispatch) QueryInterface(iid *GUID) (disp *IDispatch, err error) { 23 | disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid) 24 | return 25 | } 26 | 27 | func (v *IDispatch) MustQueryInterface(iid *GUID) (disp *IDispatch) { 28 | disp, _ = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid) 29 | return 30 | } 31 | 32 | func (v *IDispatch) AddRef() int32 { 33 | return addRef((*IUnknown)(unsafe.Pointer(v))) 34 | } 35 | 36 | func (v *IDispatch) Release() int32 { 37 | return release((*IUnknown)(unsafe.Pointer(v))) 38 | } 39 | 40 | func (v *IDispatch) GetIDsOfName(names []string) (dispid []int32, err error) { 41 | dispid, err = getIDsOfName(v, names) 42 | return 43 | } 44 | 45 | func (v *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { 46 | result, err = invoke(v, dispid, dispatch, params...) 47 | return 48 | } 49 | 50 | func (v *IDispatch) GetTypeInfoCount() (c uint32, err error) { 51 | c, err = getTypeInfoCount(v) 52 | return 53 | } 54 | 55 | func (v *IDispatch) GetTypeInfo() (tinfo *ITypeInfo, err error) { 56 | tinfo, err = getTypeInfo(v) 57 | return 58 | } 59 | 60 | func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) { 61 | wnames := make([]*uint16, len(names)) 62 | for i := 0; i < len(names); i++ { 63 | wnames[i] = syscall.StringToUTF16Ptr(names[i]) 64 | } 65 | dispid = make([]int32, len(names)) 66 | hr, _, _ := syscall.Syscall6( 67 | disp.lpVtbl.pGetIDsOfNames, 68 | 6, 69 | uintptr(unsafe.Pointer(disp)), 70 | uintptr(unsafe.Pointer(IID_NULL)), 71 | uintptr(unsafe.Pointer(&wnames[0])), 72 | uintptr(len(names)), 73 | uintptr(GetUserDefaultLCID()), 74 | uintptr(unsafe.Pointer(&dispid[0]))) 75 | if hr != 0 { 76 | err = NewError(hr) 77 | } 78 | return 79 | } 80 | 81 | func getTypeInfoCount(disp *IDispatch) (c uint32, err error) { 82 | hr, _, _ := syscall.Syscall( 83 | disp.lpVtbl.pGetTypeInfoCount, 84 | 2, 85 | uintptr(unsafe.Pointer(disp)), 86 | uintptr(unsafe.Pointer(&c)), 87 | 0) 88 | if hr != 0 { 89 | err = NewError(hr) 90 | } 91 | return 92 | } 93 | 94 | func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) { 95 | hr, _, _ := syscall.Syscall( 96 | disp.lpVtbl.pGetTypeInfo, 97 | 3, 98 | uintptr(unsafe.Pointer(disp)), 99 | uintptr(GetUserDefaultLCID()), 100 | uintptr(unsafe.Pointer(&tinfo))) 101 | if hr != 0 { 102 | err = NewError(hr) 103 | } 104 | return 105 | } 106 | 107 | func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { 108 | var dispparams DISPPARAMS 109 | 110 | if dispatch&DISPATCH_PROPERTYPUT != 0 { 111 | dispnames := [1]int32{DISPID_PROPERTYPUT} 112 | dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) 113 | dispparams.cNamedArgs = 1 114 | } 115 | var vargs []VARIANT 116 | if len(params) > 0 { 117 | vargs = make([]VARIANT, len(params)) 118 | for i, v := range params { 119 | //n := len(params)-i-1 120 | n := len(params) - i - 1 121 | VariantInit(&vargs[n]) 122 | switch v.(type) { 123 | case bool: 124 | if v.(bool) { 125 | vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff} 126 | } else { 127 | vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0} 128 | } 129 | case *bool: 130 | vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))} 131 | case byte: 132 | vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))} 133 | case *byte: 134 | vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))} 135 | case int16: 136 | vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))} 137 | case *int16: 138 | vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))} 139 | case uint16: 140 | vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))} 141 | case *uint16: 142 | vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))} 143 | case int, int32: 144 | vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))} 145 | case *int, *int32: 146 | vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))} 147 | case uint, uint32: 148 | vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))} 149 | case *uint, *uint32: 150 | vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))} 151 | case int64: 152 | vargs[n] = VARIANT{VT_I8, 0, 0, 0, int64(v.(int64))} 153 | case *int64: 154 | vargs[n] = VARIANT{VT_I8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int64))))} 155 | case uint64: 156 | vargs[n] = VARIANT{VT_UI8, 0, 0, 0, v.(int64)} 157 | case *uint64: 158 | vargs[n] = VARIANT{VT_UI8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint64))))} 159 | case float32: 160 | vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))} 161 | case *float32: 162 | vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))} 163 | case float64: 164 | vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))} 165 | case *float64: 166 | vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))} 167 | case string: 168 | vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))} 169 | case *string: 170 | vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))} 171 | case *IDispatch: 172 | vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))} 173 | case **IDispatch: 174 | vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))} 175 | case nil: 176 | vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0} 177 | case *VARIANT: 178 | vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))} 179 | default: 180 | panic("unknown type") 181 | } 182 | } 183 | dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0])) 184 | dispparams.cArgs = uint32(len(params)) 185 | } 186 | 187 | result = new(VARIANT) 188 | var excepInfo EXCEPINFO 189 | VariantInit(result) 190 | hr, _, _ := syscall.Syscall9( 191 | disp.lpVtbl.pInvoke, 192 | 9, 193 | uintptr(unsafe.Pointer(disp)), 194 | uintptr(dispid), 195 | uintptr(unsafe.Pointer(IID_NULL)), 196 | uintptr(GetUserDefaultLCID()), 197 | uintptr(dispatch), 198 | uintptr(unsafe.Pointer(&dispparams)), 199 | uintptr(unsafe.Pointer(result)), 200 | uintptr(unsafe.Pointer(&excepInfo)), 201 | 0) 202 | if hr != 0 { 203 | if excepInfo.bstrDescription == nil { 204 | err = NewError(hr) 205 | } else { 206 | bs := UTF16PtrToString(excepInfo.bstrDescription) 207 | err = NewErrorWithDescription(hr, bs) 208 | } 209 | } 210 | for _, varg := range vargs { 211 | if varg.VT == VT_BSTR && varg.Val != 0 { 212 | SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val))))) 213 | } 214 | /* 215 | if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 { 216 | *(params[n].(*string)) = UTF16PtrToString((*uint16)(unsafe.Pointer(uintptr(varg.Val)))) 217 | println(*(params[n].(*string))) 218 | fmt.Fprintln(os.Stderr, *(params[n].(*string))) 219 | } 220 | */ 221 | } 222 | return 223 | } 224 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/iprovideclassinfo.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | type IProvideClassInfo struct { 9 | lpVtbl *pIProvideClassInfoVtbl 10 | } 11 | 12 | type pIProvideClassInfoVtbl struct { 13 | pQueryInterface uintptr 14 | pAddRef uintptr 15 | pRelease uintptr 16 | pGetClassInfo uintptr 17 | } 18 | 19 | func (v *IProvideClassInfo) QueryInterface(iid *GUID) (disp *IDispatch, err error) { 20 | disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid) 21 | return 22 | } 23 | 24 | func (v *IProvideClassInfo) AddRef() int32 { 25 | return addRef((*IUnknown)(unsafe.Pointer(v))) 26 | } 27 | 28 | func (v *IProvideClassInfo) Release() int32 { 29 | return release((*IUnknown)(unsafe.Pointer(v))) 30 | } 31 | 32 | func (v *IProvideClassInfo) GetClassInfo() (cinfo *ITypeInfo, err error) { 33 | cinfo, err = getClassInfo(v) 34 | return 35 | } 36 | 37 | func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) { 38 | hr, _, _ := syscall.Syscall( 39 | disp.lpVtbl.pGetClassInfo, 40 | 2, 41 | uintptr(unsafe.Pointer(disp)), 42 | uintptr(unsafe.Pointer(&tinfo)), 43 | 0) 44 | if hr != 0 { 45 | err = NewError(hr) 46 | } 47 | return 48 | } 49 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/itypeinfo.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | type ITypeInfo struct { 9 | lpVtbl *pITypeInfoVtbl 10 | } 11 | 12 | type pITypeInfoVtbl struct { 13 | pQueryInterface uintptr 14 | pAddRef uintptr 15 | pRelease uintptr 16 | pGetTypeAttr uintptr 17 | pGetTypeComp uintptr 18 | pGetFuncDesc uintptr 19 | pGetVarDesc uintptr 20 | pGetNames uintptr 21 | pGetRefTypeOfImplType uintptr 22 | pGetImplTypeFlags uintptr 23 | pGetIDsOfNames uintptr 24 | pInvoke uintptr 25 | pGetDocumentation uintptr 26 | pGetDllEntry uintptr 27 | pGetRefTypeInfo uintptr 28 | pAddressOfMember uintptr 29 | pCreateInstance uintptr 30 | pGetMops uintptr 31 | pGetContainingTypeLib uintptr 32 | pReleaseTypeAttr uintptr 33 | pReleaseFuncDesc uintptr 34 | pReleaseVarDesc uintptr 35 | } 36 | 37 | func (v *ITypeInfo) QueryInterface(iid *GUID) (disp *IDispatch, err error) { 38 | disp, err = queryInterface((*IUnknown)(unsafe.Pointer(v)), iid) 39 | return 40 | } 41 | 42 | func (v *ITypeInfo) AddRef() int32 { 43 | return addRef((*IUnknown)(unsafe.Pointer(v))) 44 | } 45 | 46 | func (v *ITypeInfo) Release() int32 { 47 | return release((*IUnknown)(unsafe.Pointer(v))) 48 | } 49 | 50 | func (v *ITypeInfo) GetTypeAttr() (tattr *TYPEATTR, err error) { 51 | hr, _, _ := syscall.Syscall( 52 | uintptr(v.lpVtbl.pGetTypeAttr), 53 | 2, 54 | uintptr(unsafe.Pointer(v)), 55 | uintptr(unsafe.Pointer(&tattr)), 56 | 0) 57 | if hr != 0 { 58 | err = NewError(hr) 59 | } 60 | return 61 | } 62 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/iunknown.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | type IUnknown struct { 9 | lpVtbl *pIUnknownVtbl 10 | } 11 | 12 | type pIUnknownVtbl struct { 13 | pQueryInterface uintptr 14 | pAddRef uintptr 15 | pRelease uintptr 16 | } 17 | 18 | type UnknownLike interface { 19 | QueryInterface(iid *GUID) (disp *IDispatch, err error) 20 | AddRef() int32 21 | Release() int32 22 | } 23 | 24 | func (v *IUnknown) QueryInterface(iid *GUID) (disp *IDispatch, err error) { 25 | disp, err = queryInterface(v, iid) 26 | return 27 | } 28 | 29 | func (v *IUnknown) MustQueryInterface(iid *GUID) (disp *IDispatch) { 30 | disp, _ = queryInterface(v, iid) 31 | return 32 | } 33 | 34 | func (v *IUnknown) AddRef() int32 { 35 | return addRef(v) 36 | } 37 | 38 | func (v *IUnknown) Release() int32 { 39 | return release(v) 40 | } 41 | 42 | func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) { 43 | hr, _, _ := syscall.Syscall( 44 | unk.lpVtbl.pQueryInterface, 45 | 3, 46 | uintptr(unsafe.Pointer(unk)), 47 | uintptr(unsafe.Pointer(iid)), 48 | uintptr(unsafe.Pointer(&disp))) 49 | if hr != 0 { 50 | err = NewError(hr) 51 | } 52 | return 53 | } 54 | 55 | func addRef(unk *IUnknown) int32 { 56 | ret, _, _ := syscall.Syscall( 57 | unk.lpVtbl.pAddRef, 58 | 1, 59 | uintptr(unsafe.Pointer(unk)), 60 | 0, 61 | 0) 62 | return int32(ret) 63 | } 64 | 65 | func release(unk *IUnknown) int32 { 66 | ret, _, _ := syscall.Syscall( 67 | unk.lpVtbl.pRelease, 68 | 1, 69 | uintptr(unsafe.Pointer(unk)), 70 | 0, 71 | 0) 72 | return int32(ret) 73 | } 74 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/ole.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "fmt" 5 | "syscall" 6 | "unicode/utf16" 7 | "unsafe" 8 | ) 9 | 10 | type OleError struct { 11 | hr uintptr 12 | description string 13 | } 14 | 15 | func errstr(errno int) string { 16 | // ask windows for the remaining errors 17 | var flags uint32 = syscall.FORMAT_MESSAGE_FROM_SYSTEM | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS 18 | b := make([]uint16, 300) 19 | n, err := syscall.FormatMessage(flags, 0, uint32(errno), 0, b, nil) 20 | if err != nil { 21 | return fmt.Sprintf("error %d (FormatMessage failed with: %v)", errno, err) 22 | } 23 | // trim terminating \r and \n 24 | for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- { 25 | } 26 | return string(utf16.Decode(b[:n])) 27 | } 28 | 29 | func NewError(hr uintptr) *OleError { 30 | return &OleError{hr, ""} 31 | } 32 | 33 | func NewErrorWithDescription(hr uintptr, description string) *OleError { 34 | return &OleError{hr, description} 35 | } 36 | 37 | func (v *OleError) Code() uintptr { 38 | return uintptr(v.hr) 39 | } 40 | 41 | func (v *OleError) String() string { 42 | if v.description != "" { 43 | return errstr(int(v.hr)) + "(" + v.description + ")" 44 | } 45 | return errstr(int(v.hr)) 46 | } 47 | 48 | func (v *OleError) Error() string { 49 | return errstr(int(v.hr)) 50 | } 51 | 52 | func (v *OleError) Description() string { 53 | return v.description 54 | } 55 | 56 | type DISPPARAMS struct { 57 | rgvarg uintptr 58 | rgdispidNamedArgs uintptr 59 | cArgs uint32 60 | cNamedArgs uint32 61 | } 62 | 63 | type VARIANT struct { 64 | VT uint16 // 2 65 | wReserved1 uint16 // 4 66 | wReserved2 uint16 // 6 67 | wReserved3 uint16 // 8 68 | Val int64 // 16 69 | } 70 | 71 | func (v *VARIANT) ToIUnknown() *IUnknown { 72 | return (*IUnknown)(unsafe.Pointer(uintptr(v.Val))) 73 | } 74 | 75 | func (v *VARIANT) ToIDispatch() *IDispatch { 76 | return (*IDispatch)(unsafe.Pointer(uintptr(v.Val))) 77 | } 78 | 79 | func (v *VARIANT) ToArray() *SafeArrayConversion { 80 | var safeArray *SafeArray = (*SafeArray)(unsafe.Pointer(uintptr(v.Val))) 81 | return &SafeArrayConversion{safeArray} 82 | } 83 | 84 | func (v *VARIANT) ToString() string { 85 | return UTF16PtrToString(*(**uint16)(unsafe.Pointer(&v.Val))) 86 | } 87 | 88 | type EXCEPINFO struct { 89 | wCode uint16 90 | wReserved uint16 91 | bstrSource *uint16 92 | bstrDescription *uint16 93 | bstrHelpFile *uint16 94 | dwHelpContext uint32 95 | pvReserved uintptr 96 | pfnDeferredFillIn uintptr 97 | scode int32 98 | } 99 | 100 | type PARAMDATA struct { 101 | Name *int16 102 | Vt uint16 103 | } 104 | 105 | type METHODDATA struct { 106 | Name *uint16 107 | Data *PARAMDATA 108 | Dispid int32 109 | Meth uint32 110 | CC int32 111 | CArgs uint32 112 | Flags uint16 113 | VtReturn uint32 114 | } 115 | 116 | type INTERFACEDATA struct { 117 | MethodData *METHODDATA 118 | CMembers uint32 119 | } 120 | 121 | type Point struct { 122 | X int32 123 | Y int32 124 | } 125 | 126 | type Msg struct { 127 | Hwnd uint32 128 | Message uint32 129 | Wparam int32 130 | Lparam int32 131 | Time uint32 132 | Pt Point 133 | } 134 | 135 | type TYPEDESC struct { 136 | Hreftype uint32 137 | VT uint16 138 | } 139 | 140 | type IDLDESC struct { 141 | DwReserved uint32 142 | WIDLFlags uint16 143 | } 144 | 145 | type TYPEATTR struct { 146 | Guid GUID 147 | Lcid uint32 148 | dwReserved uint32 149 | MemidConstructor int32 150 | MemidDestructor int32 151 | LpstrSchema *uint16 152 | CbSizeInstance uint32 153 | Typekind int32 154 | CFuncs uint16 155 | CVars uint16 156 | CImplTypes uint16 157 | CbSizeVft uint16 158 | CbAlignment uint16 159 | WTypeFlags uint16 160 | WMajorVerNum uint16 161 | WMinorVerNum uint16 162 | TdescAlias TYPEDESC 163 | IdldescType IDLDESC 164 | } 165 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/oleutil/Makefile: -------------------------------------------------------------------------------- 1 | include $(GOROOT)/src/Make.inc 2 | 3 | TARG = github.com/mattn/go-ole/oleutil 4 | GOFILES = oleutil.go 5 | 6 | include $(GOROOT)/src/Make.pkg 7 | 8 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/oleutil/oleutil.go: -------------------------------------------------------------------------------- 1 | package oleutil 2 | 3 | import ( 4 | "github.com/mattn/go-ole" 5 | "reflect" 6 | "syscall" 7 | "unsafe" 8 | ) 9 | 10 | func CreateObject(progId string) (unknown *ole.IUnknown, err error) { 11 | var clsid *ole.GUID 12 | clsid, err = ole.CLSIDFromProgID(progId) 13 | if err != nil { 14 | clsid, err = ole.CLSIDFromString(progId) 15 | if err != nil { 16 | return 17 | } 18 | } 19 | 20 | unknown, err = ole.CreateInstance(clsid, ole.IID_IUnknown) 21 | if err != nil { 22 | return 23 | } 24 | return 25 | } 26 | 27 | func GetActiveObject(progId string) (unknown *ole.IUnknown, err error) { 28 | var clsid *ole.GUID 29 | clsid, err = ole.CLSIDFromProgID(progId) 30 | if err != nil { 31 | clsid, err = ole.CLSIDFromString(progId) 32 | if err != nil { 33 | return 34 | } 35 | } 36 | 37 | unknown, err = ole.GetActiveObject(clsid, ole.IID_IUnknown) 38 | if err != nil { 39 | return 40 | } 41 | return 42 | } 43 | 44 | func CallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { 45 | var dispid []int32 46 | dispid, err = disp.GetIDsOfName([]string{name}) 47 | if err != nil { 48 | return 49 | } 50 | result, err = disp.Invoke(dispid[0], ole.DISPATCH_METHOD, params...) 51 | return 52 | } 53 | 54 | func MustCallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { 55 | r, _ := CallMethod(disp, name, params...) 56 | return r 57 | } 58 | 59 | func GetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { 60 | var dispid []int32 61 | dispid, err = disp.GetIDsOfName([]string{name}) 62 | if err != nil { 63 | return 64 | } 65 | result, err = disp.Invoke(dispid[0], ole.DISPATCH_PROPERTYGET, params...) 66 | return 67 | } 68 | 69 | func MustGetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { 70 | r, _ := GetProperty(disp, name, params...) 71 | return r 72 | } 73 | 74 | func PutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { 75 | var dispid []int32 76 | dispid, err = disp.GetIDsOfName([]string{name}) 77 | if err != nil { 78 | return 79 | } 80 | result, err = disp.Invoke(dispid[0], ole.DISPATCH_PROPERTYPUT, params...) 81 | return 82 | } 83 | 84 | func MustPutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { 85 | r, _ := GetProperty(disp, name, params...) 86 | return r 87 | } 88 | 89 | type stdDispatch struct { 90 | lpVtbl *stdDispatchVtbl 91 | ref int32 92 | iid *ole.GUID 93 | iface interface{} 94 | funcMap map[string]int32 95 | } 96 | 97 | type stdDispatchVtbl struct { 98 | pQueryInterface uintptr 99 | pAddRef uintptr 100 | pRelease uintptr 101 | pGetTypeInfoCount uintptr 102 | pGetTypeInfo uintptr 103 | pGetIDsOfNames uintptr 104 | pInvoke uintptr 105 | } 106 | 107 | func dispQueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 { 108 | pthis := (*stdDispatch)(unsafe.Pointer(this)) 109 | *punk = nil 110 | if ole.IsEqualGUID(iid, ole.IID_IUnknown) || 111 | ole.IsEqualGUID(iid, ole.IID_IDispatch) { 112 | dispAddRef(this) 113 | *punk = this 114 | return ole.S_OK 115 | } 116 | if ole.IsEqualGUID(iid, pthis.iid) { 117 | dispAddRef(this) 118 | *punk = this 119 | return ole.S_OK 120 | } 121 | return ole.E_NOINTERFACE 122 | } 123 | 124 | func dispAddRef(this *ole.IUnknown) int32 { 125 | pthis := (*stdDispatch)(unsafe.Pointer(this)) 126 | pthis.ref++ 127 | return pthis.ref 128 | } 129 | 130 | func dispRelease(this *ole.IUnknown) int32 { 131 | pthis := (*stdDispatch)(unsafe.Pointer(this)) 132 | pthis.ref-- 133 | return pthis.ref 134 | } 135 | 136 | func dispGetIDsOfNames(this *ole.IUnknown, iid *ole.GUID, wnames []*uint16, namelen int, lcid int, pdisp []int32) uintptr { 137 | pthis := (*stdDispatch)(unsafe.Pointer(this)) 138 | names := make([]string, len(wnames)) 139 | for i := 0; i < len(names); i++ { 140 | names[i] = ole.UTF16PtrToString(wnames[i]) 141 | } 142 | for n := 0; n < namelen; n++ { 143 | if id, ok := pthis.funcMap[names[n]]; ok { 144 | pdisp[n] = id 145 | } 146 | } 147 | return ole.S_OK 148 | } 149 | 150 | func dispGetTypeInfoCount(pcount *int) uintptr { 151 | if pcount != nil { 152 | *pcount = 0 153 | } 154 | return ole.S_OK 155 | } 156 | 157 | func dispGetTypeInfo(ptypeif *uintptr) uintptr { 158 | return ole.E_NOTIMPL 159 | } 160 | 161 | func dispInvoke(this *ole.IDispatch, dispid int32, riid *ole.GUID, lcid int, flags int16, dispparams *ole.DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr { 162 | pthis := (*stdDispatch)(unsafe.Pointer(this)) 163 | found := "" 164 | for name, id := range pthis.funcMap { 165 | if id == dispid { 166 | found = name 167 | } 168 | } 169 | if found != "" { 170 | rv := reflect.ValueOf(pthis.iface).Elem() 171 | rm := rv.MethodByName(found) 172 | rr := rm.Call([]reflect.Value{}) 173 | println(len(rr)) 174 | return ole.S_OK 175 | } 176 | return ole.E_NOTIMPL 177 | } 178 | 179 | func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (cookie uint32, err error) { 180 | unknown, err := disp.QueryInterface(ole.IID_IConnectionPointContainer) 181 | if err != nil { 182 | return 183 | } 184 | 185 | container := (*ole.IConnectionPointContainer)(unsafe.Pointer(unknown)) 186 | var point *ole.IConnectionPoint 187 | err = container.FindConnectionPoint(iid, &point) 188 | if err != nil { 189 | return 190 | } 191 | if edisp, ok := idisp.(*ole.IUnknown); ok { 192 | cookie, err = point.Advise(edisp) 193 | container.Release() 194 | if err != nil { 195 | return 196 | } 197 | } 198 | rv := reflect.ValueOf(disp).Elem() 199 | if rv.Type().Kind() == reflect.Struct { 200 | dest := &stdDispatch{} 201 | dest.lpVtbl = &stdDispatchVtbl{} 202 | dest.lpVtbl.pQueryInterface = syscall.NewCallback(dispQueryInterface) 203 | dest.lpVtbl.pAddRef = syscall.NewCallback(dispAddRef) 204 | dest.lpVtbl.pRelease = syscall.NewCallback(dispRelease) 205 | dest.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(dispGetTypeInfoCount) 206 | dest.lpVtbl.pGetTypeInfo = syscall.NewCallback(dispGetTypeInfo) 207 | dest.lpVtbl.pGetIDsOfNames = syscall.NewCallback(dispGetIDsOfNames) 208 | dest.lpVtbl.pInvoke = syscall.NewCallback(dispInvoke) 209 | dest.iface = disp 210 | dest.iid = iid 211 | cookie, err = point.Advise((*ole.IUnknown)(unsafe.Pointer(dest))) 212 | container.Release() 213 | if err != nil { 214 | point.Release() 215 | return 216 | } 217 | } 218 | 219 | container.Release() 220 | 221 | return 0, ole.NewError(ole.E_INVALIDARG) 222 | } 223 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/safearray.go: -------------------------------------------------------------------------------- 1 | // Package is meant to retrieve and process safe array data returned from COM. 2 | package ole 3 | 4 | import ( 5 | _ "fmt" 6 | _ "syscall" 7 | "unsafe" 8 | ) 9 | 10 | var ( 11 | procSafeArrayAccessData, _ = modoleaut32.FindProc("SafeArrayAccessData") 12 | procSafeArrayAllocData, _ = modoleaut32.FindProc("SafeArrayAllocData") 13 | procSafeArrayAllocDescriptor, _ = modoleaut32.FindProc("SafeArrayAllocDescriptor") 14 | procSafeArrayAllocDescriptorEx, _ = modoleaut32.FindProc("SafeArrayAllocDescriptorEx") 15 | procSafeArrayCopy, _ = modoleaut32.FindProc("SafeArrayCopy") 16 | procSafeArrayCopyData, _ = modoleaut32.FindProc("SafeArrayCopyData") 17 | procSafeArrayCreate, _ = modoleaut32.FindProc("SafeArrayCreate") 18 | procSafeArrayCreateEx, _ = modoleaut32.FindProc("SafeArrayCreateEx") 19 | procSafeArrayCreateVector, _ = modoleaut32.FindProc("SafeArrayCreateVector") 20 | procSafeArrayCreateVectorEx, _ = modoleaut32.FindProc("SafeArrayCreateVectorEx") 21 | procSafeArrayDestroy, _ = modoleaut32.FindProc("SafeArrayDestroy") 22 | procSafeArrayDestroyData, _ = modoleaut32.FindProc("SafeArrayDestroyData") 23 | procSafeArrayDestroyDescriptor, _ = modoleaut32.FindProc("SafeArrayDestroyDescriptor") 24 | procSafeArrayGetDim, _ = modoleaut32.FindProc("SafeArrayGetDim") 25 | procSafeArrayGetElement, _ = modoleaut32.FindProc("SafeArrayGetElement") 26 | procSafeArrayGetElemsize, _ = modoleaut32.FindProc("SafeArrayGetElemsize") 27 | procSafeArrayGetIID, _ = modoleaut32.FindProc("SafeArrayGetIID") 28 | procSafeArrayGetLBound, _ = modoleaut32.FindProc("SafeArrayGetLBound") 29 | procSafeArrayGetUBound, _ = modoleaut32.FindProc("SafeArrayGetUBound") 30 | procSafeArrayGetVartype, _ = modoleaut32.FindProc("SafeArrayGetVartype") 31 | procSafeArrayLock, _ = modoleaut32.FindProc("SafeArrayLock") 32 | procSafeArrayPtrOfIndex, _ = modoleaut32.FindProc("SafeArrayPtrOfIndex") 33 | procSafeArrayUnaccessData, _ = modoleaut32.FindProc("SafeArrayUnaccessData") 34 | procSafeArrayUnlock, _ = modoleaut32.FindProc("SafeArrayUnlock") 35 | //procSafeArrayPutElement, _ = modoleaut32.FindProc("SafeArrayPutElement") // TODO 36 | //procSafeArrayRedim, _ = modoleaut32.FindProc("SafeArrayRedim") // TODO 37 | //procSafeArraySetIID, _ = modoleaut32.FindProc("SafeArraySetIID") // TODO 38 | //procSafeArrayGetRecordInfo, _ = modoleaut32.FindProc("SafeArrayGetRecordInfo") // TODO 39 | //procSafeArraySetRecordInfo, _ = modoleaut32.FindProc("SafeArraySetRecordInfo") // TODO 40 | ) 41 | 42 | // Returns Raw Array 43 | // Todo: Test 44 | func safeArrayAccessData(safearray *SafeArray) (element uintptr, err error) { 45 | err = convertHresultToError( 46 | procSafeArrayAccessData.Call( 47 | uintptr(unsafe.Pointer(safearray)), 48 | uintptr(unsafe.Pointer(&element)))) 49 | return 50 | } 51 | 52 | func safeArrayUnaccessData(safearray *SafeArray) (err error) { 53 | err = convertHresultToError(procSafeArrayUnaccessData.Call(uintptr(unsafe.Pointer(safearray)))) 54 | return 55 | } 56 | 57 | func safeArrayAllocData(safearray *SafeArray) (err error) { 58 | err = convertHresultToError(procSafeArrayAllocData.Call(uintptr(unsafe.Pointer(safearray)))) 59 | return 60 | } 61 | 62 | func safeArrayAllocDescriptor(dimensions uint32) (safearray *SafeArray, err error) { 63 | err = convertHresultToError( 64 | procSafeArrayAllocDescriptor.Call(uintptr(dimensions), uintptr(unsafe.Pointer(&safearray)))) 65 | return 66 | } 67 | 68 | func safeArrayAllocDescriptorEx(variantType uint16, dimensions uint32) (safearray *SafeArray, err error) { 69 | err = convertHresultToError( 70 | procSafeArrayAllocDescriptorEx.Call( 71 | uintptr(variantType), 72 | uintptr(dimensions), 73 | uintptr(unsafe.Pointer(&safearray)))) 74 | return 75 | } 76 | 77 | func safeArrayCopy(original *SafeArray) (safearray *SafeArray, err error) { 78 | err = convertHresultToError( 79 | procSafeArrayCopy.Call( 80 | uintptr(unsafe.Pointer(original)), 81 | uintptr(unsafe.Pointer(&safearray)))) 82 | return 83 | } 84 | 85 | func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) (err error) { 86 | err = convertHresultToError( 87 | procSafeArrayCopyData.Call( 88 | uintptr(unsafe.Pointer(original)), 89 | uintptr(unsafe.Pointer(duplicate)))) 90 | return 91 | } 92 | 93 | func safeArrayCreate(variantType uint16, dimensions uint32, bounds *SafeArrayBound) (safearray *SafeArray, err error) { 94 | sa, _, err := procSafeArrayCreate.Call( 95 | uintptr(variantType), 96 | uintptr(dimensions), 97 | uintptr(unsafe.Pointer(bounds))) 98 | safearray = (*SafeArray)(unsafe.Pointer(&sa)) 99 | return 100 | } 101 | 102 | func safeArrayCreateEx(variantType uint16, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (safearray *SafeArray, err error) { 103 | sa, _, err := procSafeArrayCreateEx.Call( 104 | uintptr(variantType), 105 | uintptr(dimensions), 106 | uintptr(unsafe.Pointer(bounds)), 107 | extra) 108 | safearray = (*SafeArray)(unsafe.Pointer(sa)) 109 | return 110 | } 111 | 112 | func safeArrayCreateVector(variantType uint16, lowerBound int32, length uint32) (safearray *SafeArray, err error) { 113 | sa, _, err := procSafeArrayCreateVector.Call( 114 | uintptr(variantType), 115 | uintptr(lowerBound), 116 | uintptr(length)) 117 | safearray = (*SafeArray)(unsafe.Pointer(sa)) 118 | return 119 | } 120 | 121 | func safeArrayCreateVectorEx(variantType uint16, lowerBound int32, length uint32, extra uintptr) (safearray *SafeArray, err error) { 122 | sa, _, err := procSafeArrayCreateVectorEx.Call( 123 | uintptr(variantType), 124 | uintptr(lowerBound), 125 | uintptr(length), 126 | extra) 127 | safearray = (*SafeArray)(unsafe.Pointer(sa)) 128 | return 129 | } 130 | 131 | func safeArrayDestroy(safearray *SafeArray) (err error) { 132 | err = convertHresultToError(procSafeArrayDestroy.Call(uintptr(unsafe.Pointer(safearray)))) 133 | return 134 | } 135 | 136 | func safeArrayDestroyData(safearray *SafeArray) (err error) { 137 | err = convertHresultToError(procSafeArrayDestroyData.Call(uintptr(unsafe.Pointer(safearray)))) 138 | return 139 | } 140 | 141 | func safeArrayDestroyDescriptor(safearray *SafeArray) (err error) { 142 | err = convertHresultToError(procSafeArrayDestroyDescriptor.Call(uintptr(unsafe.Pointer(safearray)))) 143 | return 144 | } 145 | 146 | func safeArrayGetDim(safearray *SafeArray) (dimensions *uint32, err error) { 147 | l, _, err := procSafeArrayGetDim.Call(uintptr(unsafe.Pointer(safearray))) 148 | dimensions = (*uint32)(unsafe.Pointer(l)) 149 | return 150 | } 151 | 152 | func safeArrayGetElementSize(safearray *SafeArray) (length *uint32, err error) { 153 | l, _, err := procSafeArrayGetElemsize.Call(uintptr(unsafe.Pointer(safearray))) 154 | length = (*uint32)(unsafe.Pointer(l)) 155 | return 156 | } 157 | 158 | func safeArrayGetElement(safearray *SafeArray, index int64) (element uintptr, err error) { 159 | err = convertHresultToError( 160 | procSafeArrayGetElement.Call( 161 | uintptr(unsafe.Pointer(safearray)), 162 | uintptr(unsafe.Pointer(&index)), 163 | uintptr(unsafe.Pointer(&element)))) 164 | return 165 | } 166 | 167 | func safeArrayGetElementString(safearray *SafeArray, index int64) (str string, err error) { 168 | var element *int16 169 | err = convertHresultToError( 170 | procSafeArrayGetElement.Call( 171 | uintptr(unsafe.Pointer(safearray)), 172 | uintptr(unsafe.Pointer(&index)), 173 | uintptr(unsafe.Pointer(&element)))) 174 | str = UTF16PtrToString(*(**uint16)(unsafe.Pointer(&element))) 175 | SysFreeString(element) 176 | return 177 | } 178 | 179 | func safeArrayGetIID(safearray *SafeArray) (guid *GUID, err error) { 180 | err = convertHresultToError( 181 | procSafeArrayGetIID.Call( 182 | uintptr(unsafe.Pointer(safearray)), 183 | uintptr(unsafe.Pointer(&guid)))) 184 | return 185 | } 186 | 187 | func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (lowerBound int64, err error) { 188 | err = convertHresultToError( 189 | procSafeArrayGetLBound.Call( 190 | uintptr(unsafe.Pointer(safearray)), 191 | uintptr(dimension), 192 | uintptr(unsafe.Pointer(&lowerBound)))) 193 | return 194 | } 195 | 196 | func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (upperBound int64, err error) { 197 | err = convertHresultToError( 198 | procSafeArrayGetUBound.Call( 199 | uintptr(unsafe.Pointer(safearray)), 200 | uintptr(dimension), 201 | uintptr(unsafe.Pointer(&upperBound)))) 202 | return 203 | } 204 | 205 | func safeArrayGetVartype(safearray *SafeArray) (varType uint16, err error) { 206 | err = convertHresultToError( 207 | procSafeArrayGetVartype.Call( 208 | uintptr(unsafe.Pointer(safearray)), 209 | uintptr(unsafe.Pointer(&varType)))) 210 | return 211 | } 212 | 213 | func safeArrayLock(safearray *SafeArray) (err error) { 214 | err = convertHresultToError(procSafeArrayLock.Call(uintptr(unsafe.Pointer(safearray)))) 215 | return 216 | } 217 | 218 | func safeArrayUnlock(safearray *SafeArray) (err error) { 219 | err = convertHresultToError(procSafeArrayUnlock.Call(uintptr(unsafe.Pointer(safearray)))) 220 | return 221 | } 222 | 223 | /* 224 | // TODO: Must implement IRecordInfo interface for this to return. 225 | func safeArrayGetRecordInfo(safearray *SafeArray) (recordInfo interface{}, err error) { 226 | err = convertHresultToError( 227 | procSafeArrayGetRecordInfo.Call( 228 | uintptr(unsafe.Pointer(safearray)), 229 | uintptr(unsafe.Pointer(&recordInfo)))) 230 | return 231 | } 232 | 233 | // TODO: Must implement IRecordInfo interface for this to work. 234 | func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) (err error) { 235 | err = convertHresultToError( 236 | procSafeArraySetRecordInfo.Call( 237 | uintptr(unsafe.Pointer(safearray)), 238 | uintptr(unsafe.Pointer(recordInfo)))) 239 | return 240 | } 241 | */ 242 | 243 | type SafeArrayBound struct { 244 | Elements uint32 245 | LowerBound int32 246 | } 247 | 248 | type SafeArray struct { 249 | Dimensions uint16 250 | FeaturesFlag uint16 251 | ElementsSize uint32 252 | LocksAmount uint32 253 | Data uint32 254 | Bounds SafeArrayBound 255 | } 256 | 257 | // Obsolete, exists for backwards compatibility. 258 | // Use SafeArray 259 | type SAFEARRAY SafeArray 260 | 261 | // Obsolete, exists for backwards compatibility. 262 | // Use SafeArrayBound 263 | type SAFEARRAYBOUND SafeArrayBound 264 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/safearray_test.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | _ "fmt" 5 | "testing" 6 | _ "unsafe" 7 | ) 8 | 9 | // This tests more than one function. It tests all of the functions needed in order to retrieve an 10 | // SafeArray populated with Strings. 11 | func TestGetSafeArrayString(t *testing.T) { 12 | CoInitialize(0) 13 | defer CoUninitialize() 14 | 15 | clsid, err := CLSIDFromProgID("QBXMLRP2.RequestProcessor.1") 16 | if err != nil { 17 | if err.(OleError).Code() == CO_E_CLASSSTRING { 18 | return 19 | } 20 | t.Log(err) 21 | t.FailNow() 22 | } 23 | 24 | unknown, err := CreateInstance(clsid, IID_IUnknown) 25 | if err != nil { 26 | t.Log(err) 27 | t.FailNow() 28 | } 29 | defer unknown.Release() 30 | 31 | dispatch, err := unknown.QueryInterface(IID_IDispatch) 32 | if err != nil { 33 | t.Log(err) 34 | t.FailNow() 35 | } 36 | 37 | var dispid []int32 38 | dispid, err = dispatch.GetIDsOfName([]string{"OpenConnection2"}) 39 | if err != nil { 40 | t.Log(err) 41 | t.FailNow() 42 | } 43 | 44 | var result *VARIANT 45 | _, err = dispatch.Invoke(dispid[0], DISPATCH_METHOD, "", "Test Application 1", 1) 46 | if err != nil { 47 | t.Log(err) 48 | t.FailNow() 49 | } 50 | 51 | dispid, err = dispatch.GetIDsOfName([]string{"BeginSession"}) 52 | if err != nil { 53 | t.Log(err) 54 | t.FailNow() 55 | } 56 | 57 | result, err = dispatch.Invoke(dispid[0], DISPATCH_METHOD, "", 2) 58 | if err != nil { 59 | t.Log(err) 60 | t.FailNow() 61 | } 62 | 63 | ticket := result.ToString() 64 | 65 | dispid, err = dispatch.GetIDsOfName([]string{"QBXMLVersionsForSession"}) 66 | if err != nil { 67 | t.Log(err) 68 | t.FailNow() 69 | } 70 | 71 | result, err = dispatch.Invoke(dispid[0], DISPATCH_PROPERTYGET, ticket) 72 | if err != nil { 73 | t.Log(err) 74 | t.FailNow() 75 | } 76 | 77 | // Where the real tests begin. 78 | var qbXMLVersions *SafeArray 79 | var qbXmlVersionStrings []string 80 | qbXMLVersions = result.ToArray().Array 81 | 82 | // Get array bounds 83 | var LowerBounds int64 84 | var UpperBounds int64 85 | LowerBounds, err = safeArrayGetLBound(qbXMLVersions, 1) 86 | if err != nil { 87 | t.Log("Safe Array Get Lower Bound") 88 | t.Log(err) 89 | t.FailNow() 90 | } 91 | t.Log("Lower Bounds:") 92 | t.Log(LowerBounds) 93 | 94 | UpperBounds, err = safeArrayGetUBound(qbXMLVersions, 1) 95 | if err != nil { 96 | t.Log("Safe Array Get Lower Bound") 97 | t.Log(err) 98 | t.FailNow() 99 | } 100 | t.Log("Upper Bounds:") 101 | t.Log(UpperBounds) 102 | 103 | totalElements := UpperBounds - LowerBounds + 1 104 | qbXmlVersionStrings = make([]string, totalElements) 105 | 106 | for i := int64(0); i < totalElements; i++ { 107 | qbXmlVersionStrings[int32(i)], _ = safeArrayGetElementString(qbXMLVersions, i) 108 | } 109 | 110 | // Release Safe Array memory 111 | safeArrayDestroy(qbXMLVersions) 112 | 113 | dispid, err = dispatch.GetIDsOfName([]string{"EndSession"}) 114 | if err != nil { 115 | t.Log(err) 116 | t.FailNow() 117 | } 118 | 119 | _, err = dispatch.Invoke(dispid[0], DISPATCH_METHOD, ticket) 120 | if err != nil { 121 | t.Log(err) 122 | t.FailNow() 123 | } 124 | 125 | dispid, err = dispatch.GetIDsOfName([]string{"CloseConnection"}) 126 | if err != nil { 127 | t.Log(err) 128 | t.FailNow() 129 | } 130 | 131 | _, err = dispatch.Invoke(dispid[0], DISPATCH_METHOD) 132 | if err != nil { 133 | t.Log(err) 134 | t.FailNow() 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/safearrayconversion.go: -------------------------------------------------------------------------------- 1 | // Helper for converting SafeArray to array of objects. 2 | package ole 3 | 4 | import () 5 | 6 | type SafeArrayConversion struct { 7 | Array *SafeArray 8 | } 9 | 10 | func (sac *SafeArrayConversion) ToStringArray() (strings []string) { 11 | totalElements, _ := sac.TotalElements(0) 12 | strings = make([]string, totalElements) 13 | 14 | for i := int64(0); i < totalElements; i++ { 15 | strings[int32(i)], _ = safeArrayGetElementString(sac.Array, i) 16 | } 17 | 18 | return 19 | } 20 | 21 | func (sac *SafeArrayConversion) GetType() (varType uint16, err error) { 22 | return safeArrayGetVartype(sac.Array) 23 | } 24 | 25 | func (sac *SafeArrayConversion) GetDimensions() (dimensions *uint32, err error) { 26 | return safeArrayGetDim(sac.Array) 27 | } 28 | 29 | func (sac *SafeArrayConversion) GetSize() (length *uint32, err error) { 30 | return safeArrayGetElementSize(sac.Array) 31 | } 32 | 33 | func (sac *SafeArrayConversion) TotalElements(index uint32) (totalElements int64, err error) { 34 | if index < 1 { 35 | index = 1 36 | } 37 | 38 | // Get array bounds 39 | var LowerBounds int64 40 | var UpperBounds int64 41 | 42 | LowerBounds, err = safeArrayGetLBound(sac.Array, index) 43 | if err != nil { 44 | return 45 | } 46 | 47 | UpperBounds, err = safeArrayGetUBound(sac.Array, index) 48 | if err != nil { 49 | return 50 | } 51 | 52 | totalElements = UpperBounds - LowerBounds + 1 53 | return 54 | } 55 | 56 | // Release Safe Array memory 57 | func (sac *SafeArrayConversion) Release() { 58 | safeArrayDestroy(sac.Array) 59 | } 60 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/safearrayconversion_test.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "testing" 7 | _ "unsafe" 8 | ) 9 | 10 | // This tests more than one function. It tests all of the functions needed in order to retrieve an 11 | // SafeArray populated with Strings. 12 | func TestSafeArrayConversionString(t *testing.T) { 13 | CoInitialize(0) 14 | defer CoUninitialize() 15 | 16 | clsid, err := CLSIDFromProgID("QBXMLRP2.RequestProcessor.1") 17 | if err != nil { 18 | if err.(OleError).Code() == CO_E_CLASSSTRING { 19 | return 20 | } 21 | t.Log(err) 22 | t.FailNow() 23 | } 24 | 25 | unknown, err := CreateInstance(clsid, IID_IUnknown) 26 | if err != nil { 27 | t.Log(err) 28 | t.FailNow() 29 | } 30 | defer unknown.Release() 31 | 32 | dispatch, err := unknown.QueryInterface(IID_IDispatch) 33 | if err != nil { 34 | t.Log(err) 35 | t.FailNow() 36 | } 37 | 38 | var dispid []int32 39 | dispid, err = dispatch.GetIDsOfName([]string{"OpenConnection2"}) 40 | if err != nil { 41 | t.Log(err) 42 | t.FailNow() 43 | } 44 | 45 | var result *VARIANT 46 | _, err = dispatch.Invoke(dispid[0], DISPATCH_METHOD, "", "Test Application 1", 1) 47 | if err != nil { 48 | t.Log(err) 49 | t.FailNow() 50 | } 51 | 52 | dispid, err = dispatch.GetIDsOfName([]string{"BeginSession"}) 53 | if err != nil { 54 | t.Log(err) 55 | t.FailNow() 56 | } 57 | 58 | result, err = dispatch.Invoke(dispid[0], DISPATCH_METHOD, "", 2) 59 | if err != nil { 60 | t.Log(err) 61 | t.FailNow() 62 | } 63 | 64 | ticket := result.ToString() 65 | 66 | dispid, err = dispatch.GetIDsOfName([]string{"QBXMLVersionsForSession"}) 67 | if err != nil { 68 | t.Log(err) 69 | t.FailNow() 70 | } 71 | 72 | result, err = dispatch.Invoke(dispid[0], DISPATCH_PROPERTYGET, ticket) 73 | if err != nil { 74 | t.Log(err) 75 | t.FailNow() 76 | } 77 | 78 | // Where the real tests begin. 79 | conversion := result.ToArray() 80 | 81 | totalElements, _ := conversion.TotalElements(0) 82 | if totalElements != 13 { 83 | t.Log(fmt.Sprintf("%d total elements does not equal 13\n", totalElements)) 84 | t.Fail() 85 | } 86 | 87 | versions := conversion.ToStringArray() 88 | if len(versions) != 13 { 89 | t.Log(fmt.Sprintf("%s\n", strings.Join(versions, ", "))) 90 | t.Fail() 91 | } 92 | 93 | conversion.Release() 94 | 95 | dispid, err = dispatch.GetIDsOfName([]string{"EndSession"}) 96 | if err != nil { 97 | t.Log(err) 98 | t.FailNow() 99 | } 100 | 101 | _, err = dispatch.Invoke(dispid[0], DISPATCH_METHOD, ticket) 102 | if err != nil { 103 | t.Log(err) 104 | t.FailNow() 105 | } 106 | 107 | dispid, err = dispatch.GetIDsOfName([]string{"CloseConnection"}) 108 | if err != nil { 109 | t.Log(err) 110 | t.FailNow() 111 | } 112 | 113 | _, err = dispatch.Invoke(dispid[0], DISPATCH_METHOD) 114 | if err != nil { 115 | t.Log(err) 116 | t.FailNow() 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/utility.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "unicode/utf16" 5 | "unsafe" 6 | ) 7 | 8 | func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool { 9 | return guid1.Data1 == guid2.Data1 && 10 | guid1.Data2 == guid2.Data2 && 11 | guid1.Data3 == guid2.Data3 && 12 | guid1.Data4[0] == guid2.Data4[0] && 13 | guid1.Data4[1] == guid2.Data4[1] && 14 | guid1.Data4[2] == guid2.Data4[2] && 15 | guid1.Data4[3] == guid2.Data4[3] && 16 | guid1.Data4[4] == guid2.Data4[4] && 17 | guid1.Data4[5] == guid2.Data4[5] && 18 | guid1.Data4[6] == guid2.Data4[6] && 19 | guid1.Data4[7] == guid2.Data4[7] 20 | } 21 | 22 | func BytePtrToString(p *byte) string { 23 | a := (*[10000]uint8)(unsafe.Pointer(p)) 24 | i := 0 25 | for a[i] != 0 { 26 | i++ 27 | } 28 | return string(a[:i]) 29 | } 30 | 31 | func UTF16PtrToString(p *uint16) string { 32 | if p == nil { 33 | return "" 34 | } 35 | a := (*[10000]uint16)(unsafe.Pointer(p)) 36 | i := 0 37 | for a[i] != 0 { 38 | i++ 39 | } 40 | return string(utf16.Decode(a[:i])) 41 | } 42 | 43 | func convertHresultToError(hr uintptr, r2 uintptr, ignore error) (err error) { 44 | if hr != 0 { 45 | err = NewError(hr) 46 | } 47 | return 48 | } 49 | -------------------------------------------------------------------------------- /src/github.com/mattn/go-ole/variables.go: -------------------------------------------------------------------------------- 1 | package ole 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | var ( 8 | modkernel32, _ = syscall.LoadDLL("kernel32.dll") 9 | modole32, _ = syscall.LoadDLL("ole32.dll") 10 | modoleaut32, _ = syscall.LoadDLL("oleaut32.dll") 11 | modmsvcrt, _ = syscall.LoadDLL("msvcrt.dll") 12 | moduser32, _ = syscall.LoadDLL("user32.dll") 13 | 14 | IID_NULL = &GUID{0x00000000, 0x0000, 0x0000, [8]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}} 15 | IID_IUnknown = &GUID{0x00000000, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}} 16 | IID_IDispatch = &GUID{0x00020400, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}} 17 | IID_IConnectionPointContainer = &GUID{0xB196B284, 0xBAB4, 0x101A, [8]byte{0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}} 18 | IID_IConnectionPoint = &GUID{0xB196B286, 0xBAB4, 0x101A, [8]byte{0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}} 19 | IID_IProvideClassInfo = &GUID{0xb196b283, 0xbab4, 0x101a, [8]byte{0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}} 20 | ) 21 | 22 | type GUID struct { 23 | Data1 uint32 24 | Data2 uint16 25 | Data3 uint16 26 | Data4 [8]byte 27 | } 28 | --------------------------------------------------------------------------------