github.com/hspan/go-ole@v0.0.0/guid.go (about) 1 package ole 2 3 var ( 4 // IID_NULL is null Interface ID, used when no other Interface ID is known. 5 IID_NULL = NewGUID("{00000000-0000-0000-0000-000000000000}") 6 7 // IID_IUnknown is for IUnknown interfaces. 8 IID_IUnknown = NewGUID("{00000000-0000-0000-C000-000000000046}") 9 10 // IID_IDispatch is for IDispatch interfaces. 11 IID_IDispatch = NewGUID("{00020400-0000-0000-C000-000000000046}") 12 13 // IID_IEnumVariant is for IEnumVariant interfaces 14 IID_IEnumVariant = NewGUID("{00020404-0000-0000-C000-000000000046}") 15 16 // IID_IConnectionPointContainer is for IConnectionPointContainer interfaces. 17 IID_IConnectionPointContainer = NewGUID("{B196B284-BAB4-101A-B69C-00AA00341D07}") 18 19 // IID_IConnectionPoint is for IConnectionPoint interfaces. 20 IID_IConnectionPoint = NewGUID("{B196B286-BAB4-101A-B69C-00AA00341D07}") 21 22 // IID_IInspectable is for IInspectable interfaces. 23 IID_IInspectable = NewGUID("{AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}") 24 25 // IID_IProvideClassInfo is for IProvideClassInfo interfaces. 26 IID_IProvideClassInfo = NewGUID("{B196B283-BAB4-101A-B69C-00AA00341D07}") 27 ) 28 29 // These are for testing and not part of any library. 30 var ( 31 // IID_ICOMTestString is for ICOMTestString interfaces. 32 // 33 // {E0133EB4-C36F-469A-9D3D-C66B84BE19ED} 34 IID_ICOMTestString = NewGUID("{E0133EB4-C36F-469A-9D3D-C66B84BE19ED}") 35 36 // IID_ICOMTestInt8 is for ICOMTestInt8 interfaces. 37 // 38 // {BEB06610-EB84-4155-AF58-E2BFF53680B4} 39 IID_ICOMTestInt8 = NewGUID("{BEB06610-EB84-4155-AF58-E2BFF53680B4}") 40 41 // IID_ICOMTestInt16 is for ICOMTestInt16 interfaces. 42 // 43 // {DAA3F9FA-761E-4976-A860-8364CE55F6FC} 44 IID_ICOMTestInt16 = NewGUID("{DAA3F9FA-761E-4976-A860-8364CE55F6FC}") 45 46 // IID_ICOMTestInt32 is for ICOMTestInt32 interfaces. 47 // 48 // {E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0} 49 IID_ICOMTestInt32 = NewGUID("{E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0}") 50 51 // IID_ICOMTestInt64 is for ICOMTestInt64 interfaces. 52 // 53 // {8D437CBC-B3ED-485C-BC32-C336432A1623} 54 IID_ICOMTestInt64 = NewGUID("{8D437CBC-B3ED-485C-BC32-C336432A1623}") 55 56 // IID_ICOMTestFloat is for ICOMTestFloat interfaces. 57 // 58 // {BF1ED004-EA02-456A-AA55-2AC8AC6B054C} 59 IID_ICOMTestFloat = NewGUID("{BF1ED004-EA02-456A-AA55-2AC8AC6B054C}") 60 61 // IID_ICOMTestDouble is for ICOMTestDouble interfaces. 62 // 63 // {BF908A81-8687-4E93-999F-D86FAB284BA0} 64 IID_ICOMTestDouble = NewGUID("{BF908A81-8687-4E93-999F-D86FAB284BA0}") 65 66 // IID_ICOMTestBoolean is for ICOMTestBoolean interfaces. 67 // 68 // {D530E7A6-4EE8-40D1-8931-3D63B8605010} 69 IID_ICOMTestBoolean = NewGUID("{D530E7A6-4EE8-40D1-8931-3D63B8605010}") 70 71 // IID_ICOMEchoTestObject is for ICOMEchoTestObject interfaces. 72 // 73 // {6485B1EF-D780-4834-A4FE-1EBB51746CA3} 74 IID_ICOMEchoTestObject = NewGUID("{6485B1EF-D780-4834-A4FE-1EBB51746CA3}") 75 76 // IID_ICOMTestTypes is for ICOMTestTypes interfaces. 77 // 78 // {CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0} 79 IID_ICOMTestTypes = NewGUID("{CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0}") 80 81 // CLSID_COMEchoTestObject is for COMEchoTestObject class. 82 // 83 // {3C24506A-AE9E-4D50-9157-EF317281F1B0} 84 CLSID_COMEchoTestObject = NewGUID("{3C24506A-AE9E-4D50-9157-EF317281F1B0}") 85 86 // CLSID_COMTestScalarClass is for COMTestScalarClass class. 87 // 88 // {865B85C5-0334-4AC6-9EF6-AACEC8FC5E86} 89 CLSID_COMTestScalarClass = NewGUID("{865B85C5-0334-4AC6-9EF6-AACEC8FC5E86}") 90 ) 91 92 const hextable = "0123456789ABCDEF" 93 const emptyGUID = "{00000000-0000-0000-0000-000000000000}" 94 95 // GUID is Windows API specific GUID type. 96 // 97 // This exists to match Windows GUID type for direct passing for COM. 98 // Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx. 99 type GUID struct { 100 Data1 uint32 101 Data2 uint16 102 Data3 uint16 103 Data4 [8]byte 104 } 105 106 // NewGUID converts the given string into a globally unique identifier that is 107 // compliant with the Windows API. 108 // 109 // The supplied string may be in any of these formats: 110 // 111 // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 112 // XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 113 // {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} 114 // 115 // The conversion of the supplied string is not case-sensitive. 116 func NewGUID(guid string) *GUID { 117 d := []byte(guid) 118 var d1, d2, d3, d4a, d4b []byte 119 120 switch len(d) { 121 case 38: 122 if d[0] != '{' || d[37] != '}' { 123 return nil 124 } 125 d = d[1:37] 126 fallthrough 127 case 36: 128 if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' { 129 return nil 130 } 131 d1 = d[0:8] 132 d2 = d[9:13] 133 d3 = d[14:18] 134 d4a = d[19:23] 135 d4b = d[24:36] 136 case 32: 137 d1 = d[0:8] 138 d2 = d[8:12] 139 d3 = d[12:16] 140 d4a = d[16:20] 141 d4b = d[20:32] 142 default: 143 return nil 144 } 145 146 var g GUID 147 var ok1, ok2, ok3, ok4 bool 148 g.Data1, ok1 = decodeHexUint32(d1) 149 g.Data2, ok2 = decodeHexUint16(d2) 150 g.Data3, ok3 = decodeHexUint16(d3) 151 g.Data4, ok4 = decodeHexByte64(d4a, d4b) 152 if ok1 && ok2 && ok3 && ok4 { 153 return &g 154 } 155 return nil 156 } 157 158 func decodeHexUint32(src []byte) (value uint32, ok bool) { 159 var b1, b2, b3, b4 byte 160 var ok1, ok2, ok3, ok4 bool 161 b1, ok1 = decodeHexByte(src[0], src[1]) 162 b2, ok2 = decodeHexByte(src[2], src[3]) 163 b3, ok3 = decodeHexByte(src[4], src[5]) 164 b4, ok4 = decodeHexByte(src[6], src[7]) 165 value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4) 166 ok = ok1 && ok2 && ok3 && ok4 167 return 168 } 169 170 func decodeHexUint16(src []byte) (value uint16, ok bool) { 171 var b1, b2 byte 172 var ok1, ok2 bool 173 b1, ok1 = decodeHexByte(src[0], src[1]) 174 b2, ok2 = decodeHexByte(src[2], src[3]) 175 value = (uint16(b1) << 8) | uint16(b2) 176 ok = ok1 && ok2 177 return 178 } 179 180 func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) { 181 var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool 182 value[0], ok1 = decodeHexByte(s1[0], s1[1]) 183 value[1], ok2 = decodeHexByte(s1[2], s1[3]) 184 value[2], ok3 = decodeHexByte(s2[0], s2[1]) 185 value[3], ok4 = decodeHexByte(s2[2], s2[3]) 186 value[4], ok5 = decodeHexByte(s2[4], s2[5]) 187 value[5], ok6 = decodeHexByte(s2[6], s2[7]) 188 value[6], ok7 = decodeHexByte(s2[8], s2[9]) 189 value[7], ok8 = decodeHexByte(s2[10], s2[11]) 190 ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8 191 return 192 } 193 194 func decodeHexByte(c1, c2 byte) (value byte, ok bool) { 195 var n1, n2 byte 196 var ok1, ok2 bool 197 n1, ok1 = decodeHexChar(c1) 198 n2, ok2 = decodeHexChar(c2) 199 value = (n1 << 4) | n2 200 ok = ok1 && ok2 201 return 202 } 203 204 func decodeHexChar(c byte) (byte, bool) { 205 switch { 206 case '0' <= c && c <= '9': 207 return c - '0', true 208 case 'a' <= c && c <= 'f': 209 return c - 'a' + 10, true 210 case 'A' <= c && c <= 'F': 211 return c - 'A' + 10, true 212 } 213 214 return 0, false 215 } 216 217 // String converts the GUID to string form. It will adhere to this pattern: 218 // 219 // {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} 220 // 221 // If the GUID is nil, the string representation of an empty GUID is returned: 222 // 223 // {00000000-0000-0000-0000-000000000000} 224 func (guid *GUID) String() string { 225 if guid == nil { 226 return emptyGUID 227 } 228 229 var c [38]byte 230 c[0] = '{' 231 putUint32Hex(c[1:9], guid.Data1) 232 c[9] = '-' 233 putUint16Hex(c[10:14], guid.Data2) 234 c[14] = '-' 235 putUint16Hex(c[15:19], guid.Data3) 236 c[19] = '-' 237 putByteHex(c[20:24], guid.Data4[0:2]) 238 c[24] = '-' 239 putByteHex(c[25:37], guid.Data4[2:8]) 240 c[37] = '}' 241 return string(c[:]) 242 } 243 244 func putUint32Hex(b []byte, v uint32) { 245 b[0] = hextable[byte(v>>24)>>4] 246 b[1] = hextable[byte(v>>24)&0x0f] 247 b[2] = hextable[byte(v>>16)>>4] 248 b[3] = hextable[byte(v>>16)&0x0f] 249 b[4] = hextable[byte(v>>8)>>4] 250 b[5] = hextable[byte(v>>8)&0x0f] 251 b[6] = hextable[byte(v)>>4] 252 b[7] = hextable[byte(v)&0x0f] 253 } 254 255 func putUint16Hex(b []byte, v uint16) { 256 b[0] = hextable[byte(v>>8)>>4] 257 b[1] = hextable[byte(v>>8)&0x0f] 258 b[2] = hextable[byte(v)>>4] 259 b[3] = hextable[byte(v)&0x0f] 260 } 261 262 func putByteHex(dst, src []byte) { 263 for i := 0; i < len(src); i++ { 264 dst[i*2] = hextable[src[i]>>4] 265 dst[i*2+1] = hextable[src[i]&0x0f] 266 } 267 } 268 269 // IsEqualGUID compares two GUID. 270 // 271 // Not constant time comparison. 272 func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool { 273 return guid1.Data1 == guid2.Data1 && 274 guid1.Data2 == guid2.Data2 && 275 guid1.Data3 == guid2.Data3 && 276 guid1.Data4[0] == guid2.Data4[0] && 277 guid1.Data4[1] == guid2.Data4[1] && 278 guid1.Data4[2] == guid2.Data4[2] && 279 guid1.Data4[3] == guid2.Data4[3] && 280 guid1.Data4[4] == guid2.Data4[4] && 281 guid1.Data4[5] == guid2.Data4[5] && 282 guid1.Data4[6] == guid2.Data4[6] && 283 guid1.Data4[7] == guid2.Data4[7] 284 }