| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- //go:build windows
- package ole
- import (
- "syscall"
- "unicode/utf16"
- "unsafe"
- )
- var (
- procCoInitialize = modole32.NewProc("CoInitialize")
- procCoInitializeEx = modole32.NewProc("CoInitializeEx")
- procCoUninitialize = modole32.NewProc("CoUninitialize")
- procCoCreateInstance = modole32.NewProc("CoCreateInstance")
- procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
- procCLSIDFromProgID = modole32.NewProc("CLSIDFromProgID")
- procCLSIDFromString = modole32.NewProc("CLSIDFromString")
- procStringFromCLSID = modole32.NewProc("StringFromCLSID")
- procStringFromIID = modole32.NewProc("StringFromIID")
- procIIDFromString = modole32.NewProc("IIDFromString")
- procCoGetObject = modole32.NewProc("CoGetObject")
- procGetUserDefaultLCID = modkernel32.NewProc("GetUserDefaultLCID")
- procCopyMemory = modkernel32.NewProc("RtlMoveMemory")
- procVariantInit = modoleaut32.NewProc("VariantInit")
- procVariantClear = modoleaut32.NewProc("VariantClear")
- procVariantTimeToSystemTime = modoleaut32.NewProc("VariantTimeToSystemTime")
- procSysAllocString = modoleaut32.NewProc("SysAllocString")
- procSysAllocStringLen = modoleaut32.NewProc("SysAllocStringLen")
- procSysFreeString = modoleaut32.NewProc("SysFreeString")
- procSysStringLen = modoleaut32.NewProc("SysStringLen")
- procCreateDispTypeInfo = modoleaut32.NewProc("CreateDispTypeInfo")
- procCreateStdDispatch = modoleaut32.NewProc("CreateStdDispatch")
- procGetActiveObject = modoleaut32.NewProc("GetActiveObject")
- procGetMessageW = moduser32.NewProc("GetMessageW")
- procDispatchMessageW = moduser32.NewProc("DispatchMessageW")
- )
- // coInitialize initializes COM library on current thread.
- //
- // MSDN documentation suggests that this function should not be called. Call
- // CoInitializeEx() instead. The reason has to do with threading and this
- // function is only for single-threaded apartments.
- //
- // That said, most users of the library have gotten away with just this
- // function. If you are experiencing threading issues, then use
- // CoInitializeEx().
- func coInitialize() (err error) {
- // http://msdn.microsoft.com/en-us/library/windows/desktop/ms678543(v=vs.85).aspx
- // Suggests that no value should be passed to CoInitialized.
- // Could just be Call() since the parameter is optional. <-- Needs testing to be sure.
- hr, _, _ := procCoInitialize.Call(uintptr(0))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- // coInitializeEx initializes COM library with concurrency model.
- func coInitializeEx(coinit uint32) (err error) {
- // http://msdn.microsoft.com/en-us/library/windows/desktop/ms695279(v=vs.85).aspx
- // Suggests that the first parameter is not only optional but should always be NULL.
- hr, _, _ := procCoInitializeEx.Call(uintptr(0), uintptr(coinit))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- // CoInitialize initializes COM library on current thread.
- //
- // MSDN documentation suggests that this function should not be called. Call
- // CoInitializeEx() instead. The reason has to do with threading and this
- // function is only for single-threaded apartments.
- //
- // That said, most users of the library have gotten away with just this
- // function. If you are experiencing threading issues, then use
- // CoInitializeEx().
- func CoInitialize(p uintptr) (err error) {
- // p is ignored and won't be used.
- // Avoid any variable not used errors.
- p = uintptr(0)
- return coInitialize()
- }
- // CoInitializeEx initializes COM library with concurrency model.
- func CoInitializeEx(p uintptr, coinit uint32) (err error) {
- // Avoid any variable not used errors.
- p = uintptr(0)
- return coInitializeEx(coinit)
- }
- // CoUninitialize uninitializes COM Library.
- func CoUninitialize() {
- procCoUninitialize.Call()
- }
- // CoTaskMemFree frees memory pointer.
- func CoTaskMemFree(memptr uintptr) {
- procCoTaskMemFree.Call(memptr)
- }
- // CLSIDFromProgID retrieves Class Identifier with the given Program Identifier.
- //
- // The Programmatic Identifier must be registered, because it will be looked up
- // in the Windows Registry. The registry entry has the following keys: CLSID,
- // Insertable, Protocol and Shell
- // (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx).
- //
- // programID identifies the class id with less precision and is not guaranteed
- // to be unique. These are usually found in the registry under
- // HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of
- // "Program.Component.Version" with version being optional.
- //
- // CLSIDFromProgID in Windows API.
- func CLSIDFromProgID(progId string) (clsid *GUID, err error) {
- var guid GUID
- lpszProgID := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId)))
- hr, _, _ := procCLSIDFromProgID.Call(lpszProgID, uintptr(unsafe.Pointer(&guid)))
- if hr != 0 {
- err = NewError(hr)
- }
- clsid = &guid
- return
- }
- // CLSIDFromString retrieves Class ID from string representation.
- //
- // This is technically the string version of the GUID and will convert the
- // string to object.
- //
- // CLSIDFromString in Windows API.
- func CLSIDFromString(str string) (clsid *GUID, err error) {
- var guid GUID
- lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str)))
- hr, _, _ := procCLSIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid)))
- if hr != 0 {
- err = NewError(hr)
- }
- clsid = &guid
- return
- }
- // StringFromCLSID returns GUID formated string from GUID object.
- func StringFromCLSID(clsid *GUID) (str string, err error) {
- var p *uint16
- hr, _, _ := procStringFromCLSID.Call(uintptr(unsafe.Pointer(clsid)), uintptr(unsafe.Pointer(&p)))
- if hr != 0 {
- err = NewError(hr)
- }
- str = LpOleStrToString(p)
- return
- }
- // IIDFromString returns GUID from program ID.
- func IIDFromString(progId string) (clsid *GUID, err error) {
- var guid GUID
- lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId)))
- hr, _, _ := procIIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid)))
- if hr != 0 {
- err = NewError(hr)
- }
- clsid = &guid
- return
- }
- // StringFromIID returns GUID formatted string from GUID object.
- func StringFromIID(iid *GUID) (str string, err error) {
- var p *uint16
- hr, _, _ := procStringFromIID.Call(uintptr(unsafe.Pointer(iid)), uintptr(unsafe.Pointer(&p)))
- if hr != 0 {
- err = NewError(hr)
- }
- str = LpOleStrToString(p)
- return
- }
- // CreateInstance of single uninitialized object with GUID.
- func CreateInstance(clsid, iid *GUID) (unk *IUnknown, err error) {
- if iid == nil {
- iid = IID_IUnknown
- }
- hr, _, _ := procCoCreateInstance.Call(
- uintptr(unsafe.Pointer(clsid)),
- 0,
- CLSCTX_SERVER,
- uintptr(unsafe.Pointer(iid)),
- uintptr(unsafe.Pointer(&unk)))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- // GetActiveObject retrieves pointer to active object.
- func GetActiveObject(clsid, iid *GUID) (unk *IUnknown, err error) {
- if iid == nil {
- iid = IID_IUnknown
- }
- hr, _, _ := procGetActiveObject.Call(
- uintptr(unsafe.Pointer(clsid)),
- uintptr(unsafe.Pointer(iid)),
- uintptr(unsafe.Pointer(&unk)))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- type BindOpts struct {
- CbStruct uint32
- GrfFlags uint32
- GrfMode uint32
- TickCountDeadline uint32
- }
- // GetObject retrieves pointer to active object.
- func GetObject(programID string, bindOpts *BindOpts, iid *GUID) (unk *IUnknown, err error) {
- if bindOpts != nil {
- bindOpts.CbStruct = uint32(unsafe.Sizeof(BindOpts{}))
- }
- if iid == nil {
- iid = IID_IUnknown
- }
- hr, _, _ := procCoGetObject.Call(
- uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(programID))),
- uintptr(unsafe.Pointer(bindOpts)),
- uintptr(unsafe.Pointer(iid)),
- uintptr(unsafe.Pointer(&unk)))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- // VariantInit initializes variant.
- func VariantInit(v *VARIANT) (err error) {
- hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v)))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- // VariantClear clears value in Variant settings to VT_EMPTY.
- func VariantClear(v *VARIANT) (err error) {
- hr, _, _ := procVariantClear.Call(uintptr(unsafe.Pointer(v)))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- // SysAllocString allocates memory for string and copies string into memory.
- func SysAllocString(v string) (ss *int16) {
- pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v))))
- ss = (*int16)(unsafe.Pointer(pss))
- return
- }
- // SysAllocStringLen copies up to length of given string returning pointer.
- func SysAllocStringLen(v string) (ss *int16) {
- utf16 := utf16.Encode([]rune(v + "\x00"))
- ptr := &utf16[0]
- pss, _, _ := procSysAllocStringLen.Call(uintptr(unsafe.Pointer(ptr)), uintptr(len(utf16)-1))
- ss = (*int16)(unsafe.Pointer(pss))
- return
- }
- // SysFreeString frees string system memory. This must be called with SysAllocString.
- func SysFreeString(v *int16) (err error) {
- hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v)))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- // SysStringLen is the length of the system allocated string.
- func SysStringLen(v *int16) uint32 {
- l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v)))
- return uint32(l)
- }
- // CreateStdDispatch provides default IDispatch implementation for IUnknown.
- //
- // This handles default IDispatch implementation for objects. It haves a few
- // limitations with only supporting one language. It will also only return
- // default exception codes.
- func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (disp *IDispatch, err error) {
- hr, _, _ := procCreateStdDispatch.Call(
- uintptr(unsafe.Pointer(unk)),
- v,
- uintptr(unsafe.Pointer(ptinfo)),
- uintptr(unsafe.Pointer(&disp)))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- // CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch.
- //
- // This will not handle the full implementation of the interface.
- func CreateDispTypeInfo(idata *INTERFACEDATA) (pptinfo *IUnknown, err error) {
- hr, _, _ := procCreateDispTypeInfo.Call(
- uintptr(unsafe.Pointer(idata)),
- uintptr(GetUserDefaultLCID()),
- uintptr(unsafe.Pointer(&pptinfo)))
- if hr != 0 {
- err = NewError(hr)
- }
- return
- }
- // copyMemory moves location of a block of memory.
- func copyMemory(dest, src unsafe.Pointer, length uint32) {
- procCopyMemory.Call(uintptr(dest), uintptr(src), uintptr(length))
- }
- // GetUserDefaultLCID retrieves current user default locale.
- func GetUserDefaultLCID() (lcid uint32) {
- ret, _, _ := procGetUserDefaultLCID.Call()
- lcid = uint32(ret)
- return
- }
- // GetMessage in message queue from runtime.
- //
- // This function appears to block. PeekMessage does not block.
- func GetMessage(msg *Msg, hwnd, MsgFilterMin, MsgFilterMax uint32) (ret int32, err error) {
- r0, _, err := procGetMessageW.Call(uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax))
- ret = int32(r0)
- return
- }
- // DispatchMessage to window procedure.
- func DispatchMessage(msg *Msg) (ret int32) {
- r0, _, _ := procDispatchMessageW.Call(uintptr(unsafe.Pointer(msg)))
- ret = int32(r0)
- return
- }
|