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  }