diff --git a/winlogbeat/beater/winlogbeat.go b/winlogbeat/beater/winlogbeat.go index 0c28ef3ca46a..57e3dbd88cc2 100644 --- a/winlogbeat/beater/winlogbeat.go +++ b/winlogbeat/beater/winlogbeat.go @@ -88,18 +88,20 @@ func (eb *Winlogbeat) init(b *beat.Beat) error { // configuration. eb.eventLogs = make([]*eventLogger, 0, len(config.EventLogs)) for _, config := range config.EventLogs { - eventLog, err := eventlog.New(config) + eventLogs, err := eventlog.New(config) if err != nil { return fmt.Errorf("Failed to create new event log. %v", err) } - debugf("Initialized EventLog[%s]", eventLog.Name()) + for _, eventLog := range eventLogs { + debugf("Initialized EventLog[%s]", eventLog.Name()) - logger, err := newEventLogger(eventLog, config) - if err != nil { - return fmt.Errorf("Failed to create new event log. %v", err) - } + logger, err := newEventLogger(eventLog, config) + if err != nil { + return fmt.Errorf("Failed to create new event log. %v", err) + } - eb.eventLogs = append(eb.eventLogs, logger) + eb.eventLogs = append(eb.eventLogs, logger) + } } return nil diff --git a/winlogbeat/eventlog/eventlogging.go b/winlogbeat/eventlog/eventlogging.go index 4e2b97b545f4..ac0cfc423cf7 100644 --- a/winlogbeat/eventlog/eventlogging.go +++ b/winlogbeat/eventlog/eventlogging.go @@ -276,7 +276,7 @@ func (l *eventLogging) ignoreOlder(r *Record) bool { // newEventLogging creates and returns a new EventLog for reading event logs // using the Event Logging API. -func newEventLogging(options *common.Config) (EventLog, error) { +func newEventLogging(options *common.Config) ([]EventLog, error) { c := eventLoggingConfig{ ReadBufferSize: win.MaxEventBufferSize, FormatBufferSize: win.MaxFormatMessageBufferSize, @@ -285,7 +285,7 @@ func newEventLogging(options *common.Config) (EventLog, error) { return nil, err } - return &eventLogging{ + return []EventLog{&eventLogging{ config: c, name: c.Name, handles: newMessageFilesCache(c.Name, win.QueryEventMessageFiles, @@ -293,7 +293,7 @@ func newEventLogging(options *common.Config) (EventLog, error) { logPrefix: fmt.Sprintf("EventLogging[%s]", c.Name), readBuf: make([]byte, 0, c.ReadBufferSize), formatBuf: make([]byte, c.FormatBufferSize), - }, nil + }}, nil } func init() { diff --git a/winlogbeat/eventlog/factory.go b/winlogbeat/eventlog/factory.go index 5b2ef3e9849c..419843bc3e52 100644 --- a/winlogbeat/eventlog/factory.go +++ b/winlogbeat/eventlog/factory.go @@ -76,7 +76,7 @@ func readConfig( } // Producer produces a new event log instance for reading event log records. -type producer func(*common.Config) (EventLog, error) +type producer func(*common.Config) ([]EventLog, error) // Channels lists the available channels (event logs). type channels func() ([]string, error) @@ -110,9 +110,9 @@ func Register(apiName string, priority int, producer producer, channels channels } } -// New creates and returns a new EventLog instance based on the given config +// New creates and returns multiple EventLog instance based on the given config // and the registered EventLog producers. -func New(options *common.Config) (EventLog, error) { +func New(options *common.Config) ([]EventLog, error) { if len(eventLogs) == 0 { return nil, fmt.Errorf("No event log API is available on this system") } diff --git a/winlogbeat/eventlog/wineventlog.go b/winlogbeat/eventlog/wineventlog.go index eec37549666a..7355b60fd448 100644 --- a/winlogbeat/eventlog/wineventlog.go +++ b/winlogbeat/eventlog/wineventlog.go @@ -201,7 +201,7 @@ func (l *winEventLog) Close() error { } func (l *winEventLog) eventHandles(maxRead int) ([]win.EvtHandle, int, error) { - handles, err := win.EventHandles(l.subscription, maxRead) + handles, err := win.EventHandles(l.subscription, maxRead, 0) switch err { case nil: if l.maxRead > maxRead { @@ -271,7 +271,7 @@ func (l *winEventLog) buildRecordFromXML(x []byte, recoveredErr error) (Record, // newWinEventLog creates and returns a new EventLog for reading event logs // using the Windows Event Log. -func newWinEventLog(options *common.Config) (EventLog, error) { +func newWinEventLog(options *common.Config) ([]EventLog, error) { c := defaultWinEventLogConfig if err := readConfig(options, &c, winEventLogConfigKeys); err != nil { return nil, err @@ -330,7 +330,7 @@ func newWinEventLog(options *common.Config) (EventLog, error) { } } - return l, nil + return []EventLog{l}, nil } func (l *winEventLog) createBookmarkFromEvent(evtHandle win.EvtHandle) (string, error) { diff --git a/winlogbeat/eventlog/wineventlog_file.go b/winlogbeat/eventlog/wineventlog_file.go new file mode 100644 index 000000000000..bac2f1aa22f0 --- /dev/null +++ b/winlogbeat/eventlog/wineventlog_file.go @@ -0,0 +1,293 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// +build windows + +package eventlog + +import ( + "fmt" + "io" + "path/filepath" + "syscall" + + "github.com/elastic/beats/libbeat/common" + "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/winlogbeat/checkpoint" + "github.com/elastic/beats/winlogbeat/sys" + win "github.com/elastic/beats/winlogbeat/sys/wineventlog" + "github.com/pkg/errors" +) + +const ( + // winEventLogApiName is the name used to identify the Windows Event Log API + // as both an event type and an API. + winEventLogFileAPIName = "wineventlogfile" +) + +var winEventLogFileConfigKeys = append(commonConfigKeys, "batch_read_size", "include_xml") + +type winEventLogFileConfig struct { + ConfigCommon `config:",inline"` + BatchReadSize int `config:"batch_read_size"` + IncludeXML bool `config:"include_xml"` +} + +// defaultWinEventLogConfig is the default configuration for new wineventlog readers. +var defaultWinEventLogFileConfig = winEventLogFileConfig{ + BatchReadSize: 100, +} + +type winEventFileLog struct { + config winEventLogFileConfig + path string + evtHandle win.EvtHandle // Handle to the query. + maxRead int // Maximum number returned in one Read. + lastRead checkpoint.EventLogState // Record number of the last read event. + render func(event win.EvtHandle, out io.Writer) error // Function for rendering the event to XML. + renderBuf []byte // Buffer used for rendering event. + outputBuf *sys.ByteBuffer // Buffer for receiving XML + cache *messageFilesCache // Cached mapping of source name to event message file handles. + + logPrefix string // String to prefix on log messages. +} + +// Name returns the file path of the event log (i.e. Application, Security, etc.). +func (l *winEventFileLog) Name() string { + return l.path +} + +func (l *winEventFileLog) Open(state checkpoint.EventLogState) error { + var bookmark win.EvtHandle + var err error + if len(state.Bookmark) > 0 { + bookmark, err = win.CreateBookmarkFromXML(state.Bookmark) + } else { + bookmark, err = win.CreateBookmarkFromRecordID(l.path, state.RecordNumber) + } + if err != nil { + return err + } + defer win.Close(bookmark) + + debugf("%s using EvtQuery and EvtSeek to read from file %s", l.logPrefix, l.path) + + queryHandle, err := win.EvtQuery(0, l.path, "", win.EvtQueryFilePath) + if err != nil { + return err + } + l.evtHandle = queryHandle + err = win.EvtSeek(l.evtHandle, 0, bookmark) + if err != nil { + return err + } + + return nil +} + +func (l *winEventFileLog) Read() ([]Record, error) { + handles, _, err := l.eventHandles(l.maxRead) + if err != nil || len(handles) == 0 { + return nil, err + } + + defer func() { + for _, h := range handles { + win.Close(h) + } + }() + detailf("%s EventHandles returned %d handles", l.logPrefix, len(handles)) + var records []Record + for _, h := range handles { + l.outputBuf.Reset() + err := l.render(h, l.outputBuf) + if bufErr, ok := err.(sys.InsufficientBufferError); ok { + detailf("%s Increasing render buffer size to %d", l.logPrefix, + bufErr.RequiredSize) + l.renderBuf = make([]byte, bufErr.RequiredSize) + l.outputBuf.Reset() + err = l.render(h, l.outputBuf) + } + if err != nil && l.outputBuf.Len() == 0 { + logp.Err("%s Dropping event with rendering error. %v", l.logPrefix, err) + incrementMetric(dropReasons, err) + continue + } + + r, err := l.buildRecordFromXML(l.outputBuf.Bytes(), err) + if err != nil { + logp.Err("%s Dropping event. %v", l.logPrefix, err) + incrementMetric(dropReasons, err) + continue + } + + r.Offset = checkpoint.EventLogState{ + Name: l.path, + RecordNumber: r.RecordID, + Timestamp: r.TimeCreated.SystemTime, + } + if r.Offset.Bookmark, err = l.createBookmarkFromEvent(h); err != nil { + logp.Warn("%s failed creating bookmark: %v", l.logPrefix, err) + } + records = append(records, r) + l.lastRead = r.Offset + } + + debugf("%s Read() is returning %d records", l.logPrefix, len(records)) + return records, nil + +} + +func (l *winEventFileLog) eventHandles(maxRead int) ([]win.EvtHandle, int, error) { + handles, err := win.EventHandles(l.evtHandle, maxRead, 0) + switch err { + case nil: + if l.maxRead > maxRead { + debugf("%s Recovered from RPC_S_INVALID_BOUND error (errno 1734) "+ + "by decreasing batch_read_size to %v", l.logPrefix, maxRead) + } + return handles, maxRead, nil + case win.ERROR_NO_MORE_ITEMS: + detailf("%s No more events", l.logPrefix) + return nil, maxRead, nil + case win.RPC_S_INVALID_BOUND: + incrementMetric(readErrors, err) + if err := l.Close(); err != nil { + return nil, 0, errors.Wrap(err, "failed to recover from RPC_S_INVALID_BOUND") + } + if err := l.Open(l.lastRead); err != nil { + return nil, 0, errors.Wrap(err, "failed to recover from RPC_S_INVALID_BOUND") + } + return l.eventHandles(maxRead / 2) + default: + incrementMetric(readErrors, err) + logp.Warn("%s EventHandles returned error %v", l.logPrefix, err) + return nil, 0, err + } +} + +func (l *winEventFileLog) Close() error { + debugf("%s Closing handle", l.logPrefix) + return win.Close(l.evtHandle) +} + +func (l *winEventFileLog) buildRecordFromXML(x []byte, recoveredErr error) (Record, error) { + e, err := sys.UnmarshalEventXML(x) + if err != nil { + return Record{}, fmt.Errorf("Failed to unmarshal XML='%s'. %v", x, err) + } + + err = sys.PopulateAccount(&e.User) + if err != nil { + debugf("%s SID %s account lookup failed. %v", l.logPrefix, + e.User.Identifier, err) + } + + if e.RenderErrorCode != 0 { + // Convert the render error code to an error message that can be + // included in the "message_error" field. + e.RenderErr = syscall.Errno(e.RenderErrorCode).Error() + } else if recoveredErr != nil { + e.RenderErr = recoveredErr.Error() + } + + if e.Level == "" { + // Fallback on LevelRaw if the Level is not set in the RenderingInfo. + e.Level = win.EventLevel(e.LevelRaw).String() + } + + if logp.IsDebug(detailSelector) { + detailf("%s XML=%s Event=%+v", l.logPrefix, string(x), e) + } + + r := Record{ + API: winEventLogAPIName, + Event: e, + } + + if l.config.IncludeXML { + r.XML = string(x) + } + + return r, nil +} + +func newWinEvetLogFile(options *common.Config) ([]EventLog, error) { + c := defaultWinEventLogFileConfig + if err := readConfig(options, &c, winEventLogFileConfigKeys); err != nil { + return nil, err + } + + eventMetadataHandle := func(providerName, sourceName string) sys.MessageFiles { + mf := sys.MessageFiles{SourceName: sourceName} + h, err := win.OpenPublisherMetadata(0, sourceName, 0) + if err != nil { + mf.Err = err + return mf + } + + mf.Handles = []sys.FileHandle{{Handle: uintptr(h)}} + return mf + } + + freeHandle := func(handle uintptr) error { + return win.Close(win.EvtHandle(handle)) + } + + //c.Name must be a filepath, allow contains Go glob + matchFiles, err := filepath.Glob(c.Name) + if err != nil { + return nil, err + } + + retMe := make([]EventLog, 0) + for _, mf := range matchFiles { + l := &winEventFileLog{ + config: c, + path: mf, + maxRead: c.BatchReadSize, + renderBuf: make([]byte, renderBufferSize), + outputBuf: sys.NewByteBuffer(renderBufferSize), + cache: newMessageFilesCache(c.Name, eventMetadataHandle, freeHandle), + logPrefix: fmt.Sprintf("WinEventLogFile[%s]", c.Name), + } + l.render = func(event win.EvtHandle, out io.Writer) error { + return win.RenderEvent(event, 0, l.renderBuf, l.cache.get, out) + } + retMe = append(retMe, l) + } + return retMe, nil +} + +func (l *winEventFileLog) createBookmarkFromEvent(evtHandle win.EvtHandle) (string, error) { + bmHandle, err := win.CreateBookmarkFromEvent(evtHandle) + if err != nil { + return "", err + } + l.outputBuf.Reset() + err = win.RenderBookmarkXML(bmHandle, l.renderBuf, l.outputBuf) + win.Close(bmHandle) + return string(l.outputBuf.Bytes()), err +} + +func init() { + // Register wineventlog API if it is available. + available, _ := win.IsAvailable() + if available { + Register(winEventLogFileAPIName, 2, newWinEvetLogFile, win.Channels) + } +} diff --git a/winlogbeat/sys/wineventlog/syscall_windows.go b/winlogbeat/sys/wineventlog/syscall_windows.go index ea5c75b7ee73..8d5e53430e22 100644 --- a/winlogbeat/sys/wineventlog/syscall_windows.go +++ b/winlogbeat/sys/wineventlog/syscall_windows.go @@ -30,6 +30,7 @@ const ( ERROR_INSUFFICIENT_BUFFER syscall.Errno = 122 ERROR_NO_MORE_ITEMS syscall.Errno = 259 ERROR_NONE_MAPPED syscall.Errno = 1332 + ERROR_TIMEOUT syscall.Errno = 1460 RPC_S_INVALID_BOUND syscall.Errno = 1734 ERROR_INVALID_OPERATION syscall.Errno = 4317 ERROR_EVT_MESSAGE_NOT_FOUND syscall.Errno = 15027 @@ -52,6 +53,33 @@ const ( EvtSubscribeStrict EvtSubscribeFlag = 0x10000 ) +//Defines the values that specify how to return the query results and whether you are query against a channel or log file. +type EvtQueryFlag uint32 + +// EVT_QUERY_FLAGS enumeration +// https://docs.microsoft.com/zh-cn/windows/desktop/api/winevt/ne-winevt-_evt_query_flags +const ( + EvtQueryChannelPath EvtQueryFlag = 0x1 + EvtQueryFilePath EvtQueryFlag = 0x2 + EvtQueryForwardDirection EvtQueryFlag = 0x100 + EvtQueryReverseDirection EvtQueryFlag = 0x200 + EvtQueryTolerateQueryErrors EvtQueryFlag = 0x1000 +) + +// Defines the relative position in the result set from which to seek. +type EvtSeekFlag uint32 + +// EVT_SEEK_FLAGS EVT_SEEK_FLAGS +// https://docs.microsoft.com/zh-cn/windows/desktop/api/winevt/ne-winevt-_evt_seek_flags +const ( + EvtSeekRelativeToFirst EvtSeekFlag = 1 + EvtSeekRelativeToLast EvtSeekFlag = 2 + EvtSeekRelativeToCurrent EvtSeekFlag = 3 + EvtSeekRelativeToBookmark EvtSeekFlag = 4 + EvtSeekOriginMask EvtSeekFlag = 7 + EvtSeekStrict EvtSeekFlag = 0x10000 +) + // EvtRenderFlag defines the values that specify what to render. type EvtRenderFlag uint32 @@ -246,12 +274,14 @@ func (et EventLevel) String() string { // Windows API calls //sys _EvtOpenLog(session EvtHandle, path *uint16, flags uint32) (handle EvtHandle, err error) = wevtapi.EvtOpenLog //sys _EvtSubscribe(session EvtHandle, signalEvent uintptr, channelPath *uint16, query *uint16, bookmark EvtHandle, context uintptr, callback syscall.Handle, flags EvtSubscribeFlag) (handle EvtHandle, err error) = wevtapi.EvtSubscribe +//sys _EvtQuery(session EvtHandle, chanelOrFilePath *uint16, query *uint16, flags EvtQueryFlag) (handle EvtHandle, err error) = wevtapi.EvtQuery //sys _EvtCreateBookmark(bookmarkXML *uint16) (handle EvtHandle, err error) = wevtapi.EvtCreateBookmark //sys _EvtUpdateBookmark(bookmark EvtHandle, event EvtHandle) (err error) = wevtapi.EvtUpdateBookmark //sys _EvtCreateRenderContext(ValuePathsCount uint32, valuePaths uintptr, flags EvtRenderContextFlag) (handle EvtHandle, err error) = wevtapi.EvtCreateRenderContext //sys _EvtRender(context EvtHandle, fragment EvtHandle, flags EvtRenderFlag, bufferSize uint32, buffer *byte, bufferUsed *uint32, propertyCount *uint32) (err error) = wevtapi.EvtRender //sys _EvtClose(object EvtHandle) (err error) = wevtapi.EvtClose //sys _EvtNext(resultSet EvtHandle, eventArraySize uint32, eventArray *EvtHandle, timeout uint32, flags uint32, numReturned *uint32) (err error) = wevtapi.EvtNext +//sys _EvtSeek(resultSet EvtHandle, position uint64, bookmark EvtHandle, timeout uint32, flags EvtSeekFlag) (err error) = wevtapi.EvtSeek //sys _EvtOpenChannelEnum(session EvtHandle, flags uint32) (handle EvtHandle, err error) = wevtapi.EvtOpenChannelEnum //sys _EvtNextChannelPath(channelEnum EvtHandle, channelPathBufferSize uint32, channelPathBuffer *uint16, channelPathBufferUsed *uint32) (err error) = wevtapi.EvtNextChannelPath //sys _EvtFormatMessage(publisherMetadata EvtHandle, event EvtHandle, messageID uint32, valueCount uint32, values uintptr, flags EvtFormatMessageFlag, bufferSize uint32, buffer *byte, bufferUsed *uint32) (err error) = wevtapi.EvtFormatMessage diff --git a/winlogbeat/sys/wineventlog/wineventlog_windows.go b/winlogbeat/sys/wineventlog/wineventlog_windows.go index 357990624376..76519d179cc8 100644 --- a/winlogbeat/sys/wineventlog/wineventlog_windows.go +++ b/winlogbeat/sys/wineventlog/wineventlog_windows.go @@ -103,6 +103,36 @@ loop: return channels, nil } +func EvtQuery(session EvtHandle, channelOrFilePath string, query string, flags EvtQueryFlag) (EvtHandle, error) { + var err error + var cp *uint16 + if channelOrFilePath != "" { + cp, err = syscall.UTF16PtrFromString(channelOrFilePath) + if err != nil { + return 0, err + } + } + + var q *uint16 + if query != "" { + q, err = syscall.UTF16PtrFromString(query) + if err != nil { + return 0, err + } + } + + eventHandle, err := _EvtQuery(session, cp, q, flags) + if err != nil { + return 0, err + } + + return eventHandle, nil +} + +func EvtSeek(handle EvtHandle, pos uint64, bookmark EvtHandle) error { + return _EvtSeek(handle, 0, bookmark, 0, EvtSeekRelativeToBookmark) +} + // Subscribe creates a new subscription to an event log channel. func Subscribe( session EvtHandle, @@ -142,7 +172,7 @@ func Subscribe( // at most maxHandles. ErrorNoMoreHandles is returned when there are no more // handles available to return. Close must be called on each returned EvtHandle // when finished with the handle. -func EventHandles(subscription EvtHandle, maxHandles int) ([]EvtHandle, error) { +func EventHandles(subscription EvtHandle, maxHandles int, timeout uint32) ([]EvtHandle, error) { if maxHandles < 1 { return nil, fmt.Errorf("maxHandles must be greater than 0") } @@ -151,7 +181,7 @@ func EventHandles(subscription EvtHandle, maxHandles int) ([]EvtHandle, error) { var numRead uint32 err := _EvtNext(subscription, uint32(len(eventHandles)), - &eventHandles[0], 0, 0, &numRead) + &eventHandles[0], timeout, 0, &numRead) if err != nil { // Munge ERROR_INVALID_OPERATION to ERROR_NO_MORE_ITEMS when no handles // were read. This happens you call the method and there are no events diff --git a/winlogbeat/sys/wineventlog/zsyscall_windows.go b/winlogbeat/sys/wineventlog/zsyscall_windows.go index f3da0b26f496..627f63a3cf15 100644 --- a/winlogbeat/sys/wineventlog/zsyscall_windows.go +++ b/winlogbeat/sys/wineventlog/zsyscall_windows.go @@ -19,23 +19,54 @@ package wineventlog -import "unsafe" -import "syscall" +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) var _ unsafe.Pointer +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + var ( - modwevtapi = syscall.NewLazyDLL("wevtapi.dll") - modole32 = syscall.NewLazyDLL("ole32.dll") + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modwevtapi = windows.NewLazySystemDLL("wevtapi.dll") + modole32 = windows.NewLazySystemDLL("ole32.dll") procEvtOpenLog = modwevtapi.NewProc("EvtOpenLog") procEvtSubscribe = modwevtapi.NewProc("EvtSubscribe") + procEvtQuery = modwevtapi.NewProc("EvtQuery") procEvtCreateBookmark = modwevtapi.NewProc("EvtCreateBookmark") procEvtUpdateBookmark = modwevtapi.NewProc("EvtUpdateBookmark") procEvtCreateRenderContext = modwevtapi.NewProc("EvtCreateRenderContext") procEvtRender = modwevtapi.NewProc("EvtRender") procEvtClose = modwevtapi.NewProc("EvtClose") procEvtNext = modwevtapi.NewProc("EvtNext") + procEvtSeek = modwevtapi.NewProc("EvtSeek") procEvtOpenChannelEnum = modwevtapi.NewProc("EvtOpenChannelEnum") procEvtNextChannelPath = modwevtapi.NewProc("EvtNextChannelPath") procEvtFormatMessage = modwevtapi.NewProc("EvtFormatMessage") @@ -48,7 +79,7 @@ func _EvtOpenLog(session EvtHandle, path *uint16, flags uint32) (handle EvtHandl handle = EvtHandle(r0) if handle == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -61,7 +92,20 @@ func _EvtSubscribe(session EvtHandle, signalEvent uintptr, channelPath *uint16, handle = EvtHandle(r0) if handle == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _EvtQuery(session EvtHandle, chanelOrFilePath *uint16, query *uint16, flags EvtQueryFlag) (handle EvtHandle, err error) { + r0, _, e1 := syscall.Syscall6(procEvtQuery.Addr(), 4, uintptr(session), uintptr(unsafe.Pointer(chanelOrFilePath)), uintptr(unsafe.Pointer(query)), uintptr(flags), 0, 0) + handle = EvtHandle(r0) + if handle == 0 { + if e1 != 0 { + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -74,7 +118,7 @@ func _EvtCreateBookmark(bookmarkXML *uint16) (handle EvtHandle, err error) { handle = EvtHandle(r0) if handle == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -86,7 +130,7 @@ func _EvtUpdateBookmark(bookmark EvtHandle, event EvtHandle) (err error) { r1, _, e1 := syscall.Syscall(procEvtUpdateBookmark.Addr(), 2, uintptr(bookmark), uintptr(event), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -99,7 +143,7 @@ func _EvtCreateRenderContext(ValuePathsCount uint32, valuePaths uintptr, flags E handle = EvtHandle(r0) if handle == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -111,7 +155,7 @@ func _EvtRender(context EvtHandle, fragment EvtHandle, flags EvtRenderFlag, buff r1, _, e1 := syscall.Syscall9(procEvtRender.Addr(), 7, uintptr(context), uintptr(fragment), uintptr(flags), uintptr(bufferSize), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(bufferUsed)), uintptr(unsafe.Pointer(propertyCount)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -123,7 +167,7 @@ func _EvtClose(object EvtHandle) (err error) { r1, _, e1 := syscall.Syscall(procEvtClose.Addr(), 1, uintptr(object), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -135,7 +179,19 @@ func _EvtNext(resultSet EvtHandle, eventArraySize uint32, eventArray *EvtHandle, r1, _, e1 := syscall.Syscall6(procEvtNext.Addr(), 6, uintptr(resultSet), uintptr(eventArraySize), uintptr(unsafe.Pointer(eventArray)), uintptr(timeout), uintptr(flags), uintptr(unsafe.Pointer(numReturned))) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _EvtSeek(resultSet EvtHandle, position uint64, bookmark EvtHandle, timeout uint32, flags EvtSeekFlag) (err error) { + r1, _, e1 := syscall.Syscall6(procEvtSeek.Addr(), 5, uintptr(resultSet), uintptr(position), uintptr(bookmark), uintptr(timeout), uintptr(flags), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -148,7 +204,7 @@ func _EvtOpenChannelEnum(session EvtHandle, flags uint32) (handle EvtHandle, err handle = EvtHandle(r0) if handle == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -160,7 +216,7 @@ func _EvtNextChannelPath(channelEnum EvtHandle, channelPathBufferSize uint32, ch r1, _, e1 := syscall.Syscall6(procEvtNextChannelPath.Addr(), 4, uintptr(channelEnum), uintptr(channelPathBufferSize), uintptr(unsafe.Pointer(channelPathBuffer)), uintptr(unsafe.Pointer(channelPathBufferUsed)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -172,7 +228,7 @@ func _EvtFormatMessage(publisherMetadata EvtHandle, event EvtHandle, messageID u r1, _, e1 := syscall.Syscall9(procEvtFormatMessage.Addr(), 9, uintptr(publisherMetadata), uintptr(event), uintptr(messageID), uintptr(valueCount), uintptr(values), uintptr(flags), uintptr(bufferSize), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(bufferUsed))) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -185,7 +241,7 @@ func _EvtOpenPublisherMetadata(session EvtHandle, publisherIdentity *uint16, log handle = EvtHandle(r0) if handle == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -197,7 +253,7 @@ func _StringFromGUID2(rguid *syscall.GUID, pStr *uint16, strSize uint32) (err er r1, _, e1 := syscall.Syscall(procStringFromGUID2.Addr(), 3, uintptr(unsafe.Pointer(rguid)), uintptr(unsafe.Pointer(pStr)), uintptr(strSize)) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL }