forked from psimsa/gowinlog
-
Notifications
You must be signed in to change notification settings - Fork 1
/
evt_variant.go
140 lines (125 loc) · 3.65 KB
/
evt_variant.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// +build windows
package winlog
import (
"fmt"
"time"
"unicode/utf16"
"unsafe"
)
/* Convenience functions to get values out of
an array of EvtVariant structures */
const (
EvtVarTypeNull = iota
EvtVarTypeString
EvtVarTypeAnsiString
EvtVarTypeSByte
EvtVarTypeByte
EvtVarTypeInt16
EvtVarTypeUInt16
EvtVarTypeInt32
EvtVarTypeUInt32
EvtVarTypeInt64
EvtVarTypeUInt64
EvtVarTypeSingle
EvtVarTypeDouble
EvtVarTypeBoolean
EvtVarTypeBinary
EvtVarTypeGuid
EvtVarTypeSizeT
EvtVarTypeFileTime
EvtVarTypeSysTime
EvtVarTypeSid
EvtVarTypeHexInt32
EvtVarTypeHexInt64
EvtVarTypeEvtHandle
EvtVarTypeEvtXml
)
type evtVariant struct {
Data uint64
Count uint32
Type uint32
}
type fileTime struct {
lowDateTime uint32
highDateTime uint32
}
type EvtVariant []byte
/* Given a byte array from EvtRender, make an EvtVariant.
EvtVariant wraps an array of variables. */
func NewEvtVariant(buffer []byte) EvtVariant {
return EvtVariant(buffer)
}
func (e EvtVariant) elemAt(index uint32) *evtVariant {
return (*evtVariant)(unsafe.Pointer(uintptr(16*index) + uintptr(unsafe.Pointer(&e[0]))))
}
func UTF16ToString(s []uint16) string {
for i, v := range s {
if v == 0 {
s = s[0:i]
break
}
}
return string(utf16.Decode(s))
}
/* Return the string value of the variable at `index`. If the
variable isn't a string, an error is returned */
func (e EvtVariant) String(index uint32) (string, error) {
elem := e.elemAt(index)
if elem.Type != EvtVarTypeString {
return "", fmt.Errorf("EvtVariant at index %v was not of type string, type was %v", index, elem.Type)
}
wideString := (*[1 << 29]uint16)(unsafe.Pointer(uintptr(elem.Data)))
str := UTF16ToString(wideString[0 : elem.Count+1])
return str, nil
}
/* Return the unsigned integer value at `index`. If the variable
isn't a Byte, UInt16, UInt32 or UInt64 an error is returned. */
func (e EvtVariant) Uint(index uint32) (uint64, error) {
elem := e.elemAt(index)
switch elem.Type {
case EvtVarTypeByte:
return uint64(byte(elem.Data)), nil
case EvtVarTypeUInt16:
return uint64(uint16(elem.Data)), nil
case EvtVarTypeUInt32:
return uint64(uint32(elem.Data)), nil
case EvtVarTypeUInt64:
return uint64(elem.Data), nil
default:
return 0, fmt.Errorf("EvtVariant at index %v was not an unsigned integer, type is %v", index, elem.Type)
}
}
/* Return the integer value at `index`. If the variable
isn't a SByte, Int16, Int32 or Int64 an error is returned. */
func (e EvtVariant) Int(index uint32) (int64, error) {
elem := e.elemAt(index)
switch elem.Type {
case EvtVarTypeSByte:
return int64(byte(elem.Data)), nil
case EvtVarTypeInt16:
return int64(int16(elem.Data)), nil
case EvtVarTypeInt32:
return int64(int32(elem.Data)), nil
case EvtVarTypeInt64:
return int64(elem.Data), nil
default:
return 0, fmt.Errorf("EvtVariant at index %v was not an integer, type is %v", index, elem.Type)
}
}
/* Return the FileTime at `index`, converted to Time.time. If the
variable isn't a FileTime an error is returned */
func (e EvtVariant) FileTime(index uint32) (time.Time, error) {
elem := e.elemAt(index)
if elem.Type != EvtVarTypeFileTime {
return time.Now(), fmt.Errorf("EvtVariant at index %v was not of type FileTime, type was %v", index, elem.Type)
}
var t = (*fileTime)(unsafe.Pointer(&elem.Data))
timeSecs := (((int64(t.highDateTime) << 32) | int64(t.lowDateTime)) / 10000000) - int64(11644473600)
timeNano := (((int64(t.highDateTime) << 32) | int64(t.lowDateTime)) % 10000000) * 100
return time.Unix(timeSecs, timeNano), nil
}
/* Return whether the variable was actually set, or whether it
has null type */
func (e EvtVariant) IsNull(index uint32) bool {
return e.elemAt(index).Type == EvtVarTypeNull
}