-
Notifications
You must be signed in to change notification settings - Fork 2
/
guid.go
113 lines (100 loc) · 2.59 KB
/
guid.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package wingo
import (
"fmt"
"github.com/rogeecn/wingo/proc"
"github.com/rogeecn/wingo/util"
"strconv"
"strings"
"syscall"
"unsafe"
"github.com/rogeecn/wingo/co"
"github.com/rogeecn/wingo/errco"
)
// Can be created with NewGuidFromClsid() or NewGuidFromIid().
//
// 📑 https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid
type GUID struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 uint64
}
// Used to retrieve class IDs to create COM Automation objects.
//
// If the progId is invalid, error returns errco.CO_E_CLASSSTRING.
//
// Example:
//
// clsId, _ := win.CLSIDFromProgID("Excel.Application")
//
// mainObj := win.CoCreateInstance(
// clsId, nil, co.CLSCTX_SERVER, co.IID_IUNKNOWN)
// defer mainObj.Release()
//
// excel := mainObj.QueryInterface(automco.IID_IDispatch)
// defer excel.Release()
//
// 📑 https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-clsidfromprogid
func CLSIDFromProgID(progId string) (co.CLSID, error) {
var guid GUID
ret, _, _ := syscall.Syscall(proc.CLSIDFromProgID.Addr(), 2,
uintptr(unsafe.Pointer(Str.ToNativePtr(progId))),
uintptr(unsafe.Pointer(&guid)), 0)
if hr := errco.ERROR(ret); hr == errco.S_OK {
return co.CLSID(guid.String()), nil
} else {
return "", hr
}
}
// Returns a GUID struct from a CLSID string.
func GuidFromClsid(clsid co.CLSID) *GUID {
return _NewGuidFromStr(string(clsid))
}
// Returns a GUID struct from an IID string.
func GuidFromIid(iid co.IID) *GUID {
return _NewGuidFromStr(string(iid))
}
// Formats the GUID as a string.
func (g *GUID) String() string {
data4 := util.ReverseBytes64(g.Data4)
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x",
g.Data1, g.Data2, g.Data3,
data4>>48, data4&0xffff_ffff_ffff)
}
func _NewGuidFromStr(strGuid string) *GUID {
strs := strings.Split(strGuid, "-")
if len(strs) != 5 {
panic(fmt.Sprintf("Malformed GUID parts: %s", strGuid))
}
num1, e := strconv.ParseUint(strs[0], 16, 32)
if e != nil {
panic(e)
}
if num1 > 0xffff_ffff {
panic(fmt.Sprintf("GUID part 1 overflow: %x", num1))
}
var nums16 [3]uint16
for p := 1; p <= 3; p++ {
num, e := strconv.ParseUint(strs[p], 16, 16)
if e != nil {
panic(e)
}
if num > 0xffff {
panic(fmt.Sprintf("GUID part %d overflows: %x", p, num))
}
nums16[p-1] = uint16(num)
}
num5, e := strconv.ParseUint(strs[4], 16, 64)
if e != nil {
panic(e)
}
if num5 > 0xffff_ffff_ffff {
panic(fmt.Sprintf("GUID part 5 overflow: %x", num5))
}
return &GUID{
Data1: uint32(num1),
Data2: nums16[0],
Data3: nums16[1],
Data4: util.ReverseBytes64((uint64(nums16[2]) << 48) | num5),
}
}