-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathsignature.go
70 lines (60 loc) · 2.19 KB
/
signature.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package winrt
import (
"crypto/sha1" // #nosec this is not used for security purposes
"encoding/binary"
"fmt"
"strings"
"github.com/go-ole/go-ole"
)
// Primitive types signatures
const (
SignatureUInt8 = "u1"
SignatureUInt16 = "u2"
SignatureUInt32 = "u4"
SignatureUInt64 = "u8"
SignatureInt8 = "i1"
SignatureInt16 = "i2"
SignatureInt32 = "i4"
SignatureInt64 = "i8"
SignatureFloat32 = "f4"
SignatureFloat64 = "f8"
SignatureBool = "b1"
SignatureChar = "c2"
SignatureString = "string"
SignatureGUID = "g16"
)
// ParameterizedInstanceGUID creates a `GUID` for a "generic" WinRT delegate or interface. This was ported from the RUST implementation
// of WinRT, checkout for the source code:
// https://github.com/microsoft/windows-rs/blob/68576f37df4c02f09bc6e4dd1ed8ed8844c6eb9c/crates/libs/windows/src/core/guid.rs#L44
//
// Checkout the following link for documentation on how the signatures are generated:
// https://docs.microsoft.com/en-us/uwp/winrt-cref/winrt-type-system#guid-generation-for-parameterized-types
func ParameterizedInstanceGUID(baseGUID string, signatures ...string) string {
res := fmt.Sprintf("pinterface({%s};%s)", baseGUID, strings.Join(signatures, ";"))
return guidFromSignature(res)
}
func guidFromSignature(signature string) string {
// base wrt_pinterface_namespace => 11f47ad5-7b73-42c0-abae-878b1e16adee
data := []byte{0x11, 0xf4, 0x7a, 0xd5, 0x7b, 0x73, 0x42, 0xc0, 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee}
data = append(data, []byte(signature)...)
hash := sha1.New() // #nosec this is not used for security purposes
if _, err := hash.Write(data); err != nil {
return "_ERROR_"
}
bytes := hash.Sum(nil)
first := binary.BigEndian.Uint32(bytes[0:4])
second := binary.BigEndian.Uint16(bytes[4:6])
third := binary.BigEndian.Uint16(bytes[6:8])
third = (third & 0x0fff) | (5 << 12)
fourth := (bytes[8] & 0x3f) | 0x80
guid := guidFromValues(first, second, third, [8]byte{fourth, bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]})
return guid.String()
}
func guidFromValues(first uint32, second, third uint16, rest [8]byte) ole.GUID {
return ole.GUID{
Data1: first,
Data2: second,
Data3: third,
Data4: rest,
}
}