1package ole
2
3import (
4	"unicode/utf16"
5	"unsafe"
6)
7
8// ClassIDFrom retrieves class ID whether given is program ID or application string.
9//
10// Helper that provides check against both Class ID from Program ID and Class ID from string. It is
11// faster, if you know which you are using, to use the individual functions, but this will check
12// against available functions for you.
13func ClassIDFrom(programID string) (classID *GUID, err error) {
14	classID, err = CLSIDFromProgID(programID)
15	if err != nil {
16		classID, err = CLSIDFromString(programID)
17		if err != nil {
18			return
19		}
20	}
21	return
22}
23
24// BytePtrToString converts byte pointer to a Go string.
25func BytePtrToString(p *byte) string {
26	a := (*[10000]uint8)(unsafe.Pointer(p))
27	i := 0
28	for a[i] != 0 {
29		i++
30	}
31	return string(a[:i])
32}
33
34// UTF16PtrToString is alias for LpOleStrToString.
35//
36// Kept for compatibility reasons.
37func UTF16PtrToString(p *uint16) string {
38	return LpOleStrToString(p)
39}
40
41// LpOleStrToString converts COM Unicode to Go string.
42func LpOleStrToString(p *uint16) string {
43	if p == nil {
44		return ""
45	}
46
47	length := lpOleStrLen(p)
48	a := make([]uint16, length)
49
50	ptr := unsafe.Pointer(p)
51
52	for i := 0; i < int(length); i++ {
53		a[i] = *(*uint16)(ptr)
54		ptr = unsafe.Pointer(uintptr(ptr) + 2)
55	}
56
57	return string(utf16.Decode(a))
58}
59
60// BstrToString converts COM binary string to Go string.
61func BstrToString(p *uint16) string {
62	if p == nil {
63		return ""
64	}
65	length := SysStringLen((*int16)(unsafe.Pointer(p)))
66	a := make([]uint16, length)
67
68	ptr := unsafe.Pointer(p)
69
70	for i := 0; i < int(length); i++ {
71		a[i] = *(*uint16)(ptr)
72		ptr = unsafe.Pointer(uintptr(ptr) + 2)
73	}
74	return string(utf16.Decode(a))
75}
76
77// lpOleStrLen returns the length of Unicode string.
78func lpOleStrLen(p *uint16) (length int64) {
79	if p == nil {
80		return 0
81	}
82
83	ptr := unsafe.Pointer(p)
84
85	for i := 0; ; i++ {
86		if 0 == *(*uint16)(ptr) {
87			length = int64(i)
88			break
89		}
90		ptr = unsafe.Pointer(uintptr(ptr) + 2)
91	}
92	return
93}
94
95// convertHresultToError converts syscall to error, if call is unsuccessful.
96func convertHresultToError(hr uintptr, r2 uintptr, ignore error) (err error) {
97	if hr != 0 {
98		err = NewError(hr)
99	}
100	return
101}
102