guid.go 7.9 KB

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