-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
Copy pathevent.go
139 lines (112 loc) · 3.79 KB
/
event.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
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
//go:build windows
package windows // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/input/windows"
import (
"errors"
"fmt"
"unicode/utf16"
"unsafe"
)
// systemPropertiesRenderContext stores a custom rendering context to get only the event properties.
var (
systemPropertiesRenderContext = uintptr(0)
systemPropertiesRenderContextErr error
)
func init() {
// This is not expected to fail, however, collecting the error if a new failure mode appears.
systemPropertiesRenderContext, systemPropertiesRenderContextErr = evtCreateRenderContext(0, nil, EvtRenderContextSystem)
}
// Event is an event stored in windows event log.
type Event struct {
handle uintptr
}
// GetPublisherName will get the publisher name of the event.
func (e *Event) GetPublisherName(buffer *Buffer) (string, error) {
if e.handle == 0 {
return "", fmt.Errorf("event handle does not exist")
}
if systemPropertiesRenderContextErr != nil {
return "", fmt.Errorf("failed to create render context: %w", systemPropertiesRenderContextErr)
}
bufferUsed, err := evtRender(systemPropertiesRenderContext, e.handle, EvtRenderEventValues, buffer.SizeBytes(), buffer.FirstByte())
if errors.Is(err, ErrorInsufficientBuffer) {
buffer.UpdateSizeBytes(*bufferUsed)
return e.GetPublisherName(buffer)
}
if err != nil {
return "", fmt.Errorf("failed to get provider name: %w", err)
}
utf16Ptr := (**uint16)(unsafe.Pointer(buffer.FirstByte()))
providerName := utf16PtrToString(*utf16Ptr)
return providerName, nil
}
// utf16PtrToString converts Windows API LPWSTR (pointer to string) to go string
func utf16PtrToString(s *uint16) string {
if s == nil {
return ""
}
utf16Len := 0
curPtr := unsafe.Pointer(s)
for *(*uint16)(curPtr) != 0 {
curPtr = unsafe.Pointer(uintptr(curPtr) + unsafe.Sizeof(*s))
utf16Len++
}
slice := unsafe.Slice(s, utf16Len)
return string(utf16.Decode(slice))
}
// NewEvent will create a new event from an event handle.
func NewEvent(handle uintptr) Event {
return Event{
handle: handle,
}
}
// RenderSimple will render the event as EventXML without formatted info.
func (e *Event) RenderSimple(buffer *Buffer) (*EventXML, error) {
if e.handle == 0 {
return nil, fmt.Errorf("event handle does not exist")
}
bufferUsed, err := evtRender(0, e.handle, EvtRenderEventXML, buffer.SizeBytes(), buffer.FirstByte())
if err != nil {
if errors.Is(err, ErrorInsufficientBuffer) {
buffer.UpdateSizeBytes(*bufferUsed)
return e.RenderSimple(buffer)
}
return nil, fmt.Errorf("syscall to 'EvtRender' failed: %w", err)
}
bytes, err := buffer.ReadBytes(*bufferUsed)
if err != nil {
return nil, fmt.Errorf("failed to read bytes from buffer: %w", err)
}
return unmarshalEventXML(bytes)
}
// RenderDeep will render the event as EventXML with all available formatted info.
func (e *Event) RenderDeep(buffer *Buffer, publisher Publisher) (*EventXML, error) {
if e.handle == 0 {
return nil, fmt.Errorf("event handle does not exist")
}
bufferUsed, err := evtFormatMessage(publisher.handle, e.handle, 0, 0, 0, EvtFormatMessageXML, buffer.SizeWide(), buffer.FirstByte())
if err != nil {
if errors.Is(err, ErrorInsufficientBuffer) {
buffer.UpdateSizeWide(*bufferUsed)
return e.RenderDeep(buffer, publisher)
}
return nil, fmt.Errorf("syscall to 'EvtFormatMessage' failed: %w", err)
}
bytes, err := buffer.ReadWideChars(*bufferUsed)
if err != nil {
return nil, fmt.Errorf("failed to read bytes from buffer: %w", err)
}
return unmarshalEventXML(bytes)
}
// Close will close the event handle.
func (e *Event) Close() error {
if e.handle == 0 {
return nil
}
if err := evtClose(e.handle); err != nil {
return fmt.Errorf("failed to close event handle: %w", err)
}
e.handle = 0
return nil
}