返回 DeepSeek-Reasonix
guid.go
1 //go:build windows
2
3 package edge
4
5 // This code has been adapted from: https://github.com/go-ole/go-ole
6
7 /*
8
9 The MIT License (MIT)
10
11 Copyright © 2013-2017 Yasuhiro Matsumoto, <mattn.jp@gmail.com>
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy of
14 this software and associated documentation files (the “Software”), to deal in
15 the Software without restriction, including without limitation the rights to
16 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
17 of the Software, and to permit persons to whom the Software is furnished to do
18 so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30
31 */
32
33 const hextable = "0123456789ABCDEF"
34 const emptyGUID = "{00000000-0000-0000-0000-000000000000}"
35
36 // GUID is Windows API specific GUID type.
37 //
38 // This exists to match Windows GUID type for direct passing for COM.
39 // Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.
40 type GUID struct {
41 Data1 uint32
42 Data2 uint16
43 Data3 uint16
44 Data4 [8]byte
45 }
46
47 // NewGUID converts the given string into a globally unique identifier that is
48 // compliant with the Windows API.
49 //
50 // The supplied string may be in any of these formats:
51 //
52 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
53 // XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
54 // {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
55 //
56 // The conversion of the supplied string is not case-sensitive.
57 func NewGUID(guid string) *GUID {
58 d := []byte(guid)
59 var d1, d2, d3, d4a, d4b []byte
60
61 switch len(d) {
62 case 38:
63 if d[0] != '{' || d[37] != '}' {
64 return nil
65 }
66 d = d[1:37]
67 fallthrough
68 case 36:
69 if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' {
70 return nil
71 }
72 d1 = d[0:8]
73 d2 = d[9:13]
74 d3 = d[14:18]
75 d4a = d[19:23]
76 d4b = d[24:36]
77 case 32:
78 d1 = d[0:8]
79 d2 = d[8:12]
80 d3 = d[12:16]
81 d4a = d[16:20]
82 d4b = d[20:32]
83 default:
84 return nil
85 }
86
87 var g GUID
88 var ok1, ok2, ok3, ok4 bool
89 g.Data1, ok1 = decodeHexUint32(d1)
90 g.Data2, ok2 = decodeHexUint16(d2)
91 g.Data3, ok3 = decodeHexUint16(d3)
92 g.Data4, ok4 = decodeHexByte64(d4a, d4b)
93 if ok1 && ok2 && ok3 && ok4 {
94 return &g
95 }
96 return nil
97 }
98
99 func decodeHexUint32(src []byte) (value uint32, ok bool) {
100 var b1, b2, b3, b4 byte
101 var ok1, ok2, ok3, ok4 bool
102 b1, ok1 = decodeHexByte(src[0], src[1])
103 b2, ok2 = decodeHexByte(src[2], src[3])
104 b3, ok3 = decodeHexByte(src[4], src[5])
105 b4, ok4 = decodeHexByte(src[6], src[7])
106 value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4)
107 ok = ok1 && ok2 && ok3 && ok4
108 return
109 }
110
111 func decodeHexUint16(src []byte) (value uint16, ok bool) {
112 var b1, b2 byte
113 var ok1, ok2 bool
114 b1, ok1 = decodeHexByte(src[0], src[1])
115 b2, ok2 = decodeHexByte(src[2], src[3])
116 value = (uint16(b1) << 8) | uint16(b2)
117 ok = ok1 && ok2
118 return
119 }
120
121 func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) {
122 var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool
123 value[0], ok1 = decodeHexByte(s1[0], s1[1])
124 value[1], ok2 = decodeHexByte(s1[2], s1[3])
125 value[2], ok3 = decodeHexByte(s2[0], s2[1])
126 value[3], ok4 = decodeHexByte(s2[2], s2[3])
127 value[4], ok5 = decodeHexByte(s2[4], s2[5])
128 value[5], ok6 = decodeHexByte(s2[6], s2[7])
129 value[6], ok7 = decodeHexByte(s2[8], s2[9])
130 value[7], ok8 = decodeHexByte(s2[10], s2[11])
131 ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8
132 return
133 }
134
135 func decodeHexByte(c1, c2 byte) (value byte, ok bool) {
136 var n1, n2 byte
137 var ok1, ok2 bool
138 n1, ok1 = decodeHexChar(c1)
139 n2, ok2 = decodeHexChar(c2)
140 value = (n1 << 4) | n2
141 ok = ok1 && ok2
142 return
143 }
144
145 func decodeHexChar(c byte) (byte, bool) {
146 switch {
147 case '0' <= c && c <= '9':
148 return c - '0', true
149 case 'a' <= c && c <= 'f':
150 return c - 'a' + 10, true
151 case 'A' <= c && c <= 'F':
152 return c - 'A' + 10, true
153 }
154
155 return 0, false
156 }
157
158 // String converts the GUID to string form. It will adhere to this pattern:
159 //
160 // {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
161 //
162 // If the GUID is nil, the string representation of an empty GUID is returned:
163 //
164 // {00000000-0000-0000-0000-000000000000}
165 func (guid *GUID) String() string {
166 if guid == nil {
167 return emptyGUID
168 }
169
170 var c [38]byte
171 c[0] = '{'
172 putUint32Hex(c[1:9], guid.Data1)
173 c[9] = '-'
174 putUint16Hex(c[10:14], guid.Data2)
175 c[14] = '-'
176 putUint16Hex(c[15:19], guid.Data3)
177 c[19] = '-'
178 putByteHex(c[20:24], guid.Data4[0:2])
179 c[24] = '-'
180 putByteHex(c[25:37], guid.Data4[2:8])
181 c[37] = '}'
182 return string(c[:])
183 }
184
185 func putUint32Hex(b []byte, v uint32) {
186 b[0] = hextable[byte(v>>24)>>4]
187 b[1] = hextable[byte(v>>24)&0x0f]
188 b[2] = hextable[byte(v>>16)>>4]
189 b[3] = hextable[byte(v>>16)&0x0f]
190 b[4] = hextable[byte(v>>8)>>4]
191 b[5] = hextable[byte(v>>8)&0x0f]
192 b[6] = hextable[byte(v)>>4]
193 b[7] = hextable[byte(v)&0x0f]
194 }
195
196 func putUint16Hex(b []byte, v uint16) {
197 b[0] = hextable[byte(v>>8)>>4]
198 b[1] = hextable[byte(v>>8)&0x0f]
199 b[2] = hextable[byte(v)>>4]
200 b[3] = hextable[byte(v)&0x0f]
201 }
202
203 func putByteHex(dst, src []byte) {
204 for i := 0; i < len(src); i++ {
205 dst[i*2] = hextable[src[i]>>4]
206 dst[i*2+1] = hextable[src[i]&0x0f]
207 }
208 }
209
210 // IsEqualGUID compares two GUID.
211 //
212 // Not constant time comparison.
213 func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool {
214 return guid1.Data1 == guid2.Data1 &&
215 guid1.Data2 == guid2.Data2 &&
216 guid1.Data3 == guid2.Data3 &&
217 guid1.Data4[0] == guid2.Data4[0] &&
218 guid1.Data4[1] == guid2.Data4[1] &&
219 guid1.Data4[2] == guid2.Data4[2] &&
220 guid1.Data4[3] == guid2.Data4[3] &&
221 guid1.Data4[4] == guid2.Data4[4] &&
222 guid1.Data4[5] == guid2.Data4[5] &&
223 guid1.Data4[6] == guid2.Data4[6] &&
224 guid1.Data4[7] == guid2.Data4[7]
225 }
226
226 lines GO