github.com/observiq/carbon@v0.9.11-0.20200820160507-1b872e368a5e/operator/builtin/input/windows/subscription.go (about) 1 // +build windows 2 3 package windows 4 5 import ( 6 "fmt" 7 "syscall" 8 9 "golang.org/x/sys/windows" 10 ) 11 12 // Subscription is a subscription to a windows eventlog channel. 13 type Subscription struct { 14 handle uintptr 15 } 16 17 // Open will open the subscription handle. 18 func (s *Subscription) Open(channel string, startAt string, bookmark Bookmark) error { 19 if s.handle != 0 { 20 return fmt.Errorf("subscription handle is already open") 21 } 22 23 signalEvent, err := windows.CreateEvent(nil, 0, 0, nil) 24 if err != nil { 25 return fmt.Errorf("failed to create signal handle: %s", err) 26 } 27 defer windows.CloseHandle(signalEvent) 28 29 channelPtr, err := syscall.UTF16PtrFromString(channel) 30 if err != nil { 31 return fmt.Errorf("failed to convert channel to utf16: %s", err) 32 } 33 34 flags := s.createFlags(startAt, bookmark) 35 subscriptionHandle, err := evtSubscribe(0, signalEvent, channelPtr, nil, bookmark.handle, 0, 0, flags) 36 if err != nil { 37 return fmt.Errorf("failed to subscribe to %s channel: %s", channel, err) 38 } 39 40 s.handle = subscriptionHandle 41 return nil 42 } 43 44 // Close will close the subscription. 45 func (s *Subscription) Close() error { 46 if s.handle == 0 { 47 return nil 48 } 49 50 if err := evtClose(s.handle); err != nil { 51 return fmt.Errorf("failed to close subscription handle: %s", err) 52 } 53 54 s.handle = 0 55 return nil 56 } 57 58 // Read will read events from the subscription. 59 func (s *Subscription) Read(maxReads int) ([]Event, error) { 60 if s.handle == 0 { 61 return nil, fmt.Errorf("subscription handle is not open") 62 } 63 64 if maxReads < 1 { 65 return nil, fmt.Errorf("max reads must be greater than 0") 66 } 67 68 eventHandles := make([]uintptr, maxReads) 69 var eventsRead uint32 70 err := evtNext(s.handle, uint32(maxReads), &eventHandles[0], 0, 0, &eventsRead) 71 72 if err == ErrorInvalidOperation && eventsRead == 0 { 73 return nil, nil 74 } 75 76 if err != nil && err != windows.ERROR_NO_MORE_ITEMS { 77 return nil, err 78 } 79 80 events := make([]Event, 0, eventsRead) 81 for _, eventHandle := range eventHandles[:eventsRead] { 82 event := NewEvent(eventHandle) 83 events = append(events, event) 84 } 85 86 return events, nil 87 } 88 89 // createFlags will create the necessary subscription flags from the supplied arguments. 90 func (s *Subscription) createFlags(startAt string, bookmark Bookmark) uint32 { 91 if bookmark.handle != 0 { 92 return EvtSubscribeStartAfterBookmark 93 } 94 95 if startAt == "beginning" { 96 return EvtSubscribeStartAtOldestRecord 97 } 98 99 return EvtSubscribeToFutureEvents 100 } 101 102 // NewSubscription will create a new subscription with an empty handle. 103 func NewSubscription() Subscription { 104 return Subscription{ 105 handle: 0, 106 } 107 }