// newWinEventLog creates and returns a new EventLog for reading event logs // using the Windows Event Log. func newWinEventLog(options map[string]interface{}) (EventLog, error) { var c winEventLogConfig if err := readConfig(options, &c, winEventLogConfigKeys); err != nil { return nil, err } query, err := win.Query{ Log: c.Name, IgnoreOlder: c.SimpleQuery.IgnoreOlder, Level: c.SimpleQuery.Level, EventID: c.SimpleQuery.EventID, Provider: c.SimpleQuery.Provider, }.Build() if 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{sys.FileHandle{Handle: uintptr(h)}} return mf } freeHandle := func(handle uintptr) error { return win.Close(win.EvtHandle(handle)) } return &winEventLog{ config: c, query: query, channelName: c.Name, maxRead: defaultMaxNumRead, renderBuf: make([]byte, renderBufferSize), cache: newMessageFilesCache(c.Name, eventMetadataHandle, freeHandle), logPrefix: fmt.Sprintf("WinEventLog[%s]", c.Name), eventMetadata: c.EventMetadata, }, nil }
// newWinEventLog creates and returns a new EventLog for reading event logs // using the Windows Event Log. func newWinEventLog(options map[string]interface{}) (EventLog, error) { c := defaultWinEventLogConfig if err := readConfig(options, &c, winEventLogConfigKeys); err != nil { return nil, err } query, err := win.Query{ Log: c.Name, IgnoreOlder: c.SimpleQuery.IgnoreOlder, Level: c.SimpleQuery.Level, EventID: c.SimpleQuery.EventID, Provider: c.SimpleQuery.Provider, }.Build() if 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)) } l := &winEventLog{ config: c, query: query, channelName: c.Name, maxRead: c.BatchReadSize, renderBuf: make([]byte, renderBufferSize), cache: newMessageFilesCache(c.Name, eventMetadataHandle, freeHandle), logPrefix: fmt.Sprintf("WinEventLog[%s]", c.Name), eventMetadata: c.EventMetadata, } // Forwarded events should be rendered using RenderEventXML. It is more // efficient and does not attempt to use local message files for rendering // the event's message. switch { case c.Forwarded == nil && c.Name == "ForwardedEvents", c.Forwarded != nil && *c.Forwarded == true: l.render = func(event win.EvtHandle) (string, error) { return win.RenderEventXML(event, l.renderBuf) } default: l.render = func(event win.EvtHandle) (string, error) { return win.RenderEvent(event, 0, l.renderBuf, l.cache.get) } } return l, nil }
// QueryEventMessageFiles queries the registry to get the value of // the EventMessageFile key that points to a DLL or EXE containing parameterized // event log messages. If found, it loads the libraries as a datafiles and // returns a slice of Handles to the libraries. Those handles must be closed // by the caller. func QueryEventMessageFiles(providerName, sourceName string) sys.MessageFiles { mf := sys.MessageFiles{SourceName: sourceName} // Open key in registry: registryKeyName := fmt.Sprintf( "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s", providerName, sourceName) key, err := registry.OpenKey(registry.LOCAL_MACHINE, registryKeyName, registry.QUERY_VALUE) if err != nil { mf.Err = fmt.Errorf("Failed to open HKLM\\%s", registryKeyName) return mf } defer func() { err := key.Close() if err != nil { logp.Warn("Failed to close registry key. key=%s err=%v", registryKeyName, err) } }() logp.Debug("eventlog", "RegOpenKey opened handle to HKLM\\%s, key=%v", registryKeyName, key) // Read value from registry: value, _, err := key.GetStringValue("EventMessageFile") if err != nil { mf.Err = fmt.Errorf("Failed querying EventMessageFile from "+ "HKLM\\%s. %v", registryKeyName, err) return mf } value, err = registry.ExpandString(value) if err != nil { mf.Err = fmt.Errorf("Failed to expand strings in '%s'. %v", value, err) return mf } // Split the value in case there is more than one file in the value. eventMessageFiles := strings.Split(value, ";") logp.Debug("eventlog", "RegQueryValueEx queried EventMessageFile from "+ "HKLM\\%s and got [%s]", registryKeyName, strings.Join(eventMessageFiles, ",")) // Load the libraries: var files []sys.FileHandle for _, eventMessageFile := range eventMessageFiles { sPtr, err := syscall.UTF16PtrFromString(eventMessageFile) if err != nil { logp.Debug("eventlog", "Failed to get UTF16Ptr for '%s'. "+ "Skipping. %v", eventMessageFile, err) continue } handle, err := _LoadLibraryEx(sPtr, 0, LOAD_LIBRARY_AS_DATAFILE) if err != nil { logp.Debug("eventlog", "Failed to load library '%s' as data file. "+ "Skipping. %v", eventMessageFile, err) } f := sys.FileHandle{File: eventMessageFile, Handle: uintptr(handle), Err: err} files = append(files, f) } logp.Debug("eventlog", "Returning message files %+v for sourceName %s", files, sourceName) mf.Handles = files return mf }