From cd878d0d2a6cc9f839f854b00d1056682a180d4f Mon Sep 17 00:00:00 2001
From: Michael Commey <michaelcommey@icloud.com>
Date: Thu, 5 Jun 2025 15:58:14 -0400
Subject: [PATCH 01/10] Add event ID filtering for windows logs to CWAgent

---
 cmd/config-translator/translator_test.go      |   1 +
 .../windows_event_log/windows_event_log.go    |   4 +-
 .../windows_event_log/wineventlog/utils.go    | 205 +++---------------
 .../wineventlog/utils_test.go                 | 133 +++---------
 .../wineventlog/utils_windows.go              | 189 ++++++++++++++++
 .../wineventlog/utils_windows_test.go         | 134 ++++++++++++
 .../wineventlog/wineventlog.go                |   6 +-
 .../wineventlog/wineventlog_test.go           |  24 +-
 translator/config/schema.json                 |  31 ++-
 .../sampleConfig/windows_eventids.conf        |  48 ++++
 .../sampleConfig/windows_eventids.json        |  29 +++
 .../sampleConfig/windows_eventids.yaml        |  37 ++++
 .../windows_eventlog_only_config.conf         |   5 +
 .../windows_eventlog_only_config.json         |   4 +
 translator/tocwconfig/tocwconfig_test.go      |   7 +-
 .../tocwconfig/totomlconfig/toTomlConfig.go   |  37 +++-
 .../tomlConfigTemplate/tomlConfig.go          |   1 +
 .../collect_list/collectlist.go               |  40 +++-
 .../collect_list/collectlist_test.go          | 124 +++++++++++
 .../windows_events/windows_event_test.go      |   4 +
 20 files changed, 761 insertions(+), 302 deletions(-)
 create mode 100644 plugins/inputs/windows_event_log/wineventlog/utils_windows.go
 create mode 100644 plugins/inputs/windows_event_log/wineventlog/utils_windows_test.go
 create mode 100644 translator/tocwconfig/sampleConfig/windows_eventids.conf
 create mode 100644 translator/tocwconfig/sampleConfig/windows_eventids.json
 create mode 100644 translator/tocwconfig/sampleConfig/windows_eventids.yaml

diff --git a/cmd/config-translator/translator_test.go b/cmd/config-translator/translator_test.go
index b276fc4632..85d2287da8 100644
--- a/cmd/config-translator/translator_test.go
+++ b/cmd/config-translator/translator_test.go
@@ -103,6 +103,7 @@ func TestLogWindowsEventConfig(t *testing.T) {
 	checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventName.json", false, expectedErrorMap)
 	expectedErrorMap1 := map[string]int{}
 	expectedErrorMap1["required"] = 2
+	expectedErrorMap1["number_one_of"] = 2
 	checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventNameAndLevel.json", false, expectedErrorMap1)
 	expectedErrorMap2 := map[string]int{}
 	expectedErrorMap2["invalid_type"] = 1
diff --git a/plugins/inputs/windows_event_log/windows_event_log.go b/plugins/inputs/windows_event_log/windows_event_log.go
index 81f55928d1..8c86722faf 100644
--- a/plugins/inputs/windows_event_log/windows_event_log.go
+++ b/plugins/inputs/windows_event_log/windows_event_log.go
@@ -31,6 +31,7 @@ var startOnlyOnce sync.Once
 type EventConfig struct {
 	Name          string   `toml:"event_name"`
 	Levels        []string `toml:"event_levels"`
+	EventID       []int    `toml:"event_ids"`
 	RenderFormat  string   `toml:"event_format"`
 	BatchReadSize int      `toml:"batch_read_size"`
 	LogGroupName  string   `toml:"log_group_name"`
@@ -39,7 +40,6 @@ type EventConfig struct {
 	Destination   string   `toml:"destination"`
 	Retention     int      `toml:"retention_in_days"`
 }
-
 type Plugin struct {
 	FileStateFolder string          `toml:"file_state_folder"`
 	Events          []EventConfig   `toml:"event_config"`
@@ -60,6 +60,7 @@ func (s *Plugin) SampleConfig() string {
 	[[inputs.windows_event_log.event_config]]
 	event_name = "System"
 	event_levels = ["2", "3"]
+	event_ids = [1001, 1002]
 	batch_read_size = 1
 	log_group_name = "System"
 	log_stream_name = "STREAM_NAME"
@@ -104,6 +105,7 @@ func (s *Plugin) Start(acc telegraf.Accumulator) error {
 		eventLog := wineventlog.NewEventLog(
 			eventConfig.Name,
 			eventConfig.Levels,
+			eventConfig.EventID,
 			eventConfig.LogGroupName,
 			eventConfig.LogStreamName,
 			eventConfig.RenderFormat,
diff --git a/plugins/inputs/windows_event_log/wineventlog/utils.go b/plugins/inputs/windows_event_log/wineventlog/utils.go
index e903670dc1..08986e52e2 100644
--- a/plugins/inputs/windows_event_log/wineventlog/utils.go
+++ b/plugins/inputs/windows_event_log/wineventlog/utils.go
@@ -1,29 +1,18 @@
 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 // SPDX-License-Identifier: MIT
 
-//go:build windows
-// +build windows
-
 package wineventlog
 
 import (
-	"bytes"
 	"fmt"
-	"io"
-	"log"
-	"strconv"
-	"strings"
-	"syscall"
 	"time"
-
-	"golang.org/x/text/encoding/unicode"
-	"golang.org/x/text/transform"
 )
 
 const (
 	bookmarkTemplate         = `<BookmarkList><Bookmark Channel="%s" RecordId="%d" IsCurrent="True"/></BookmarkList>`
 	eventLogQueryTemplate    = `<QueryList><Query Id="0"><Select Path="%s">%s</Select></Query></QueryList>`
 	eventLogLevelFilter      = "Level='%s'"
+	eventLogeventIDFilter    = "EventID='%d'"
 	eventIgnoreOldFilter     = "TimeCreated[timediff(@SystemTime) &lt;= %d]"
 	emptySpaceScanLength     = 100
 	UnknownBytesPerCharacter = 0
@@ -36,34 +25,7 @@ const (
 	UNKNOWN     = "UNKNOWN"
 )
 
-var NumberOfBytesPerCharacter = UnknownBytesPerCharacter
-
-func RenderEventXML(eventHandle EvtHandle, renderBuf []byte) ([]byte, error) {
-	var bufferUsed, propertyCount uint32
-
-	if err := EvtRender(0, eventHandle, EvtRenderEventXml, uint32(len(renderBuf)), &renderBuf[0], &bufferUsed, &propertyCount); err != nil {
-		return nil, fmt.Errorf("error when rendering events. Details: %v", err)
-	}
-
-	// Per MSDN as of Mar 14th 2022(https://docs.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtrender)
-	// EvtRender function is still returning buffer used as BYTES, not characters. So keep using utf16ToUTF8Bytes()
-	return utf16ToUTF8Bytes(renderBuf, bufferUsed)
-}
-
-func CreateBookmark(channel string, recordID uint64) (h EvtHandle, err error) {
-	xml := fmt.Sprintf(bookmarkTemplate, channel, recordID)
-	p, err := syscall.UTF16PtrFromString(xml)
-	if err != nil {
-		return 0, err
-	}
-	h, err = EvtCreateBookmark(p)
-	if err != nil {
-		return 0, fmt.Errorf("error when creating a bookmark. Details: %v", err)
-	}
-	return h, nil
-}
-
-func CreateQuery(path string, levels []string) (*uint16, error) {
+func createFilterQuery(levels []string, eventIDs []int) string {
 	var filterLevels string
 	for _, level := range levels {
 		if filterLevels == "" {
@@ -73,149 +35,38 @@ func CreateQuery(path string, levels []string) (*uint16, error) {
 		}
 	}
 
-	//Ignore events older than 2 weeks
-	cutOffPeriod := (time.Hour * 24 * 14).Nanoseconds()
-	ignoreOlderThanTwoWeeksFilter := fmt.Sprintf(eventIgnoreOldFilter, cutOffPeriod/int64(time.Millisecond))
-	if filterLevels != "" {
-		filterLevels = "*[System[(" + filterLevels + ") and " + ignoreOlderThanTwoWeeksFilter + "]]"
-	} else {
-		filterLevels = "*[System[" + ignoreOlderThanTwoWeeksFilter + "]]"
-	}
-
-	xml := fmt.Sprintf(eventLogQueryTemplate, path, filterLevels)
-	return syscall.UTF16PtrFromString(xml)
-}
-
-func utf16ToUTF8Bytes(in []byte, length uint32) ([]byte, error) {
-
-	i := length
-
-	if length%2 != 0 {
-		i = length - 1
-	}
-
-	for ; i-2 > 0; i -= 2 {
-		v1 := uint16(in[i-2]) | uint16(in[i-1])<<8
-		// Stop at non-null char.
-		if v1 != 0 {
-			break
-		}
-	}
-
-	win16be := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
-	utf16bom := unicode.BOMOverride(win16be.NewDecoder())
-	unicodeReader := transform.NewReader(bytes.NewReader(in[:i]), utf16bom)
-	decoded, err := io.ReadAll(unicodeReader)
-	return decoded, err
-}
-
-func UTF16ToUTF8BytesForWindowsEventBuffer(in []byte, length uint32) ([]byte, error) {
-	// Since Windows server 2022, the returned value of used buffer represents for double bytes char count,
-	// which is half of the actual buffer used by byte(what older Windows OS returns), checking if the length
-	//land on the end of used buffer, if no, double it.
-	if NumberOfBytesPerCharacter == UnknownBytesPerCharacter {
-		if isTheEndOfContent(in, length) {
-			log.Printf("I! Buffer used: %d is returning as single byte character count", length)
-			NumberOfBytesPerCharacter = 1
+	//EventID filtering
+	var filterEventID string
+	for i, eventID := range eventIDs {
+		if i == 0 {
+			filterEventID = fmt.Sprintf(eventLogeventIDFilter, eventID)
 		} else {
-			log.Printf("I! Buffer used: %d is returning as double byte character count, doubling it to get the whole buffer content.", length)
-			NumberOfBytesPerCharacter = 2
-		}
-	}
-
-	i := int(length) * NumberOfBytesPerCharacter
-
-	if i > cap(in) {
-		i = cap(in)
-	}
-
-	return utf16ToUTF8Bytes(in, uint32(i))
-}
-
-func isTheEndOfContent(in []byte, length uint32) bool {
-	// scan next (emptySpaceScanLength) bytes, if any of them is none '0', return false
-	i := int(length)
-
-	if i%2 != 0 {
-		i -= 1
-	}
-	max := len(in)
-	if i+emptySpaceScanLength < max {
-		max = i + emptySpaceScanLength
-	}
-
-	for ; i < max-2; i += 2 {
-		v1 := uint16(in[i+2]) | uint16(in[i+1])<<8
-		// Stop at non-null char.
-		if v1 != 0 {
-			return false
+			filterEventID = filterEventID + " or " + fmt.Sprintf(eventLogeventIDFilter, eventID)
 		}
 	}
-	return true
-}
 
-func WindowsEventLogLevelName(levelId int32) string {
-	switch levelId {
-	case 1:
-		return CRITICAL
-	case 2:
-		return ERROR
-	case 3:
-		return WARNING
-	case 0, 4:
-		return INFORMATION
-	case 5:
-		return VERBOSE
-	default:
-		return UNKNOWN
+	//query results
+	var query string
+	if filterLevels != "" && filterEventID != "" {
+		query = filterLevels + " and " + filterEventID
+	} else if filterLevels != "" && filterEventID == "" {
+		query = filterLevels
+	} else if filterLevels == "" && filterEventID != "" {
+		query = filterEventID
 	}
-}
-
-// insertPlaceholderValues formats the message with the correct values if we see those data
-// in evtDataValues.
-//
-// In some cases wevtapi does not insert values when formatting the message. The message
-// will contain insertion string placeholders, of the form %n, where %1 indicates the first
-// insertion string, and so on. Noted that wevtapi start the index with 1.
-// https://learn.microsoft.com/en-us/windows/win32/eventlog/event-identifiers#insertion-strings
-func insertPlaceholderValues(rawMessage string, evtDataValues []Datum) string {
-	if len(evtDataValues) == 0 || len(rawMessage) == 0 {
-		return rawMessage
-	}
-	var sb strings.Builder
-	prevIndex := 0
-	searchingIndex := false
-	for i, c := range rawMessage {
-		// found `%` previously. Determine the index number from the following character(s)
-		if searchingIndex && (c > '9' || c < '0') {
-			// Convert the Slice since the last `%` and see if it's a valid number.
-			ind, err := strconv.Atoi(rawMessage[prevIndex+1 : i])
-			// If the index is in [1 - len(evtDataValues)], get it from evtDataValues.
-			if err == nil && ind <= len(evtDataValues) && ind > 0 {
-				sb.WriteString(evtDataValues[ind-1].Value)
-			} else {
-				sb.WriteString(rawMessage[prevIndex:i])
-			}
-			prevIndex = i
-			// In case of consecutive `%`, continue searching for the next index
-			if c != '%' {
-				searchingIndex = false
-			}
-		} else {
-			if c == '%' {
-				sb.WriteString(rawMessage[prevIndex:i])
-				searchingIndex = true
-				prevIndex = i
-			}
 
-		}
-	}
-	// handle the slice since the last `%` to the end of rawMessage
-	ind, err := strconv.Atoi(rawMessage[prevIndex+1:])
-	if searchingIndex && err == nil && ind <= len(evtDataValues) && ind > 0 {
-		sb.WriteString(evtDataValues[ind-1].Value)
+	//Ignore events older than 2 weeks
+	cutOffPeriod := (time.Hour * 24 * 14).Nanoseconds()
+	ignoreOlderThanTwoWeeksFilter := fmt.Sprintf(eventIgnoreOldFilter, cutOffPeriod/int64(time.Millisecond))
+	if filterLevels != "" && filterEventID != "" {
+		query = "*[System[(" + query + ") and " + ignoreOlderThanTwoWeeksFilter + "]]"
+	} else if filterLevels != "" {
+		query = "*[System[(" + filterLevels + ") and " + ignoreOlderThanTwoWeeksFilter + "]]"
+	} else if filterEventID != "" {
+		query = "*[System[(" + filterEventID + ") and " + ignoreOlderThanTwoWeeksFilter + "]]"
 	} else {
-		sb.WriteString(rawMessage[prevIndex:])
+		query = "*[System[" + ignoreOlderThanTwoWeeksFilter + "]]"
 	}
-	return sb.String()
+
+	return query
 }
diff --git a/plugins/inputs/windows_event_log/wineventlog/utils_test.go b/plugins/inputs/windows_event_log/wineventlog/utils_test.go
index 40586504d3..8c768bd1cf 100644
--- a/plugins/inputs/windows_event_log/wineventlog/utils_test.go
+++ b/plugins/inputs/windows_event_log/wineventlog/utils_test.go
@@ -1,134 +1,51 @@
 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 // SPDX-License-Identifier: MIT
 
-//go:build windows
-// +build windows
-
 package wineventlog
 
 import (
-	"encoding/hex"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 )
 
-func TestPayload_Value(t *testing.T) {
-	// one null test
-	resetState()
-	originalHexStr := "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000"
-	data, _ := hex.DecodeString(originalHexStr)
-	bufferUsed := len(data)
-	bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
-	str := string(bytes[:])
-	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
-
-	// odd bytes test
-	originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e00000000"
-	data, _ = hex.DecodeString(originalHexStr)
-	bufferUsed = len(data)
-	bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
-	str = string(bytes[:])
-	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
-
-	// two nulls test
-	originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000000000"
-	data, _ = hex.DecodeString(originalHexStr)
-	bufferUsed = len(data)
-	bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
-	str = string(bytes[:])
-	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
-
-}
-
-func TestDecodingWithDifferentBufferUsedReturned(t *testing.T) {
-	// one null test
-	resetState()
-	originalHexStr := "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000"
-	data, _ := hex.DecodeString(originalHexStr)
-	bufferUsed := len(data) / 2
-	bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
-	str := string(bytes[:])
-	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
-
-	// odd bytes test
-	originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e00000000"
-	data, _ = hex.DecodeString(originalHexStr)
-	bufferUsed = len(data) / 2
-	bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
-	str = string(bytes[:])
-	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
-
-}
-
-func TestFullBufferUsedWithHalfUsedSizeReturned(t *testing.T) {
-	resetState()
-	cap := 1 << 10
-	data := make([]byte, cap)
-	data[0] = 'a'
-	for i := 2; i < cap; i *= 2 {
-		copy(data[i:], data[:i])
-	}
-	bufferUsed := cap / 2
-
-	bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
-	str := string(bytes[:])
-	assert.Equal(t, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", str)
-	assert.Equal(t, bufferUsed, len(str))
-}
-
-func TestInsertPlaceholderValues(t *testing.T) {
-	evtDataValues := []Datum{
-		{"value_1"}, {"value_2"}, {"value_3"}, {"value_4"},
-	}
+func TestCreateFilterQuery(t *testing.T) {
 	tests := []struct {
 		name     string
-		message  string
-		expected string
+		levels   []string
+		eventIDs []int
+		want     string
 	}{
 		{
-			"Placeholders %{number} should be replaced by insertion strings",
-			"Service %1 in region %3 stop at %2",
-			"Service value_1 in region value_3 stop at value_2",
-		},
-		{
-			"String without a placeholder should remain the same after insertion",
-			"This is a sentence without placeholders",
-			"This is a sentence without placeholders",
-		},
-		{
-			"Empty string should remain the same",
-			"",
-			"",
-		},
-		{
-			"Index should start from 1 and less than or equal to the amount of values in event data",
-			"%0 %3 %5",
-			"%0 value_3 %5",
+			name:     "levels_Test",
+			levels:   []string{"Error", "Critical"},
+			eventIDs: []int{},
+			want:     "*[System[(Level='Error' or Level='Critical') and TimeCreated[timediff(@SystemTime) &lt;= 1209600000]]]",
 		},
 		{
-			"Handle consecutive % characters",
-			"%1 %%3% %2",
-			"value_1 %value_3% value_2",
+			name:     "EventID_Test",
+			levels:   []string{},
+			eventIDs: []int{1001, 1002},
+			want:     "*[System[(EventID='1001' or EventID='1002') and TimeCreated[timediff(@SystemTime) &lt;= 1209600000]]]",
 		},
 		{
-			"Handle % character at the end of message",
-			"%3 %2%",
-			"value_3 value_2%",
+			name:     "levels_EventID_Test",
+			levels:   []string{"Error"},
+			eventIDs: []int{4625},
+			want:     "*[System[(Level='Error' and EventID='4625') and TimeCreated[timediff(@SystemTime) &lt;= 1209600000]]]",
 		},
 		{
-			"Characters after a % other than numbers should be ignored",
-			"%foo, %foo1, %#$%^&1",
-			"%foo, %foo1, %#$%^&1",
+			name:     "no_Input",
+			levels:   []string{},
+			eventIDs: []int{},
+			want:     "*[System[TimeCreated[timediff(@SystemTime) &lt;= 1209600000]]]",
 		},
 	}
-	for _, tc := range tests {
-		t.Run(tc.name, func(t *testing.T) {
-			assert.Equal(t, tc.expected, insertPlaceholderValues(tc.message, evtDataValues))
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := createFilterQuery(tt.levels, tt.eventIDs)
+			assert.Equal(t, tt.want, got)
+
 		})
 	}
 }
-
-func resetState() {
-	NumberOfBytesPerCharacter = 0
-}
diff --git a/plugins/inputs/windows_event_log/wineventlog/utils_windows.go b/plugins/inputs/windows_event_log/wineventlog/utils_windows.go
new file mode 100644
index 0000000000..4f02167de2
--- /dev/null
+++ b/plugins/inputs/windows_event_log/wineventlog/utils_windows.go
@@ -0,0 +1,189 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: MIT
+
+//go:build windows
+// +build windows
+
+package wineventlog
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"log"
+	"strconv"
+	"strings"
+	"syscall"
+
+	"golang.org/x/text/encoding/unicode"
+	"golang.org/x/text/transform"
+)
+
+var NumberOfBytesPerCharacter = UnknownBytesPerCharacter
+
+func RenderEventXML(eventHandle EvtHandle, renderBuf []byte) ([]byte, error) {
+	var bufferUsed, propertyCount uint32
+
+	if err := EvtRender(0, eventHandle, EvtRenderEventXml, uint32(len(renderBuf)), &renderBuf[0], &bufferUsed, &propertyCount); err != nil {
+		return nil, fmt.Errorf("error when rendering events. Details: %v", err)
+	}
+
+	// Per MSDN as of Mar 14th 2022(https://docs.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtrender)
+	// EvtRender function is still returning buffer used as BYTES, not characters. So keep using utf16ToUTF8Bytes()
+	return utf16ToUTF8Bytes(renderBuf, bufferUsed)
+}
+
+func CreateBookmark(channel string, recordID uint64) (h EvtHandle, err error) {
+	xml := fmt.Sprintf(bookmarkTemplate, channel, recordID)
+	p, err := syscall.UTF16PtrFromString(xml)
+	if err != nil {
+		return 0, err
+	}
+	h, err = EvtCreateBookmark(p)
+	if err != nil {
+		return 0, fmt.Errorf("error when creating a bookmark. Details: %v", err)
+	}
+	return h, nil
+}
+
+func CreateQuery(path string, levels []string, eventIDs []int) (*uint16, error) {
+
+	query := createFilterQuery(levels, eventIDs)
+
+	xml := fmt.Sprintf(eventLogQueryTemplate, path, query)
+	return syscall.UTF16PtrFromString(xml)
+}
+
+func utf16ToUTF8Bytes(in []byte, length uint32) ([]byte, error) {
+
+	i := length
+
+	if length%2 != 0 {
+		i = length - 1
+	}
+
+	for ; i-2 > 0; i -= 2 {
+		v1 := uint16(in[i-2]) | uint16(in[i-1])<<8
+		// Stop at non-null char.
+		if v1 != 0 {
+			break
+		}
+	}
+
+	win16be := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
+	utf16bom := unicode.BOMOverride(win16be.NewDecoder())
+	unicodeReader := transform.NewReader(bytes.NewReader(in[:i]), utf16bom)
+	decoded, err := io.ReadAll(unicodeReader)
+	return decoded, err
+}
+
+func UTF16ToUTF8BytesForWindowsEventBuffer(in []byte, length uint32) ([]byte, error) {
+	// Since Windows server 2022, the returned value of used buffer represents for double bytes char count,
+	// which is half of the actual buffer used by byte(what older Windows OS returns), checking if the length
+	//land on the end of used buffer, if no, double it.
+	if NumberOfBytesPerCharacter == UnknownBytesPerCharacter {
+		if isTheEndOfContent(in, length) {
+			log.Printf("I! Buffer used: %d is returning as single byte character count", length)
+			NumberOfBytesPerCharacter = 1
+		} else {
+			log.Printf("I! Buffer used: %d is returning as double byte character count, doubling it to get the whole buffer content.", length)
+			NumberOfBytesPerCharacter = 2
+		}
+	}
+
+	i := int(length) * NumberOfBytesPerCharacter
+
+	if i > cap(in) {
+		i = cap(in)
+	}
+
+	return utf16ToUTF8Bytes(in, uint32(i))
+}
+
+func isTheEndOfContent(in []byte, length uint32) bool {
+	// scan next (emptySpaceScanLength) bytes, if any of them is none '0', return false
+	i := int(length)
+
+	if i%2 != 0 {
+		i -= 1
+	}
+	max := len(in)
+	if i+emptySpaceScanLength < max {
+		max = i + emptySpaceScanLength
+	}
+
+	for ; i < max-2; i += 2 {
+		v1 := uint16(in[i+2]) | uint16(in[i+1])<<8
+		// Stop at non-null char.
+		if v1 != 0 {
+			return false
+		}
+	}
+	return true
+}
+
+func WindowsEventLogLevelName(levelId int32) string {
+	switch levelId {
+	case 1:
+		return CRITICAL
+	case 2:
+		return ERROR
+	case 3:
+		return WARNING
+	case 0, 4:
+		return INFORMATION
+	case 5:
+		return VERBOSE
+	default:
+		return UNKNOWN
+	}
+}
+
+// insertPlaceholderValues formats the message with the correct values if we see those data
+// in evtDataValues.
+//
+// In some cases wevtapi does not insert values when formatting the message. The message
+// will contain insertion string placeholders, of the form %n, where %1 indicates the first
+// insertion string, and so on. Noted that wevtapi start the index with 1.
+// https://learn.microsoft.com/en-us/windows/win32/eventlog/event-identifiers#insertion-strings
+func insertPlaceholderValues(rawMessage string, evtDataValues []Datum) string {
+	if len(evtDataValues) == 0 || len(rawMessage) == 0 {
+		return rawMessage
+	}
+	var sb strings.Builder
+	prevIndex := 0
+	searchingIndex := false
+	for i, c := range rawMessage {
+		// found `%` previously. Determine the index number from the following character(s)
+		if searchingIndex && (c > '9' || c < '0') {
+			// Convert the Slice since the last `%` and see if it's a valid number.
+			ind, err := strconv.Atoi(rawMessage[prevIndex+1 : i])
+			// If the index is in [1 - len(evtDataValues)], get it from evtDataValues.
+			if err == nil && ind <= len(evtDataValues) && ind > 0 {
+				sb.WriteString(evtDataValues[ind-1].Value)
+			} else {
+				sb.WriteString(rawMessage[prevIndex:i])
+			}
+			prevIndex = i
+			// In case of consecutive `%`, continue searching for the next index
+			if c != '%' {
+				searchingIndex = false
+			}
+		} else {
+			if c == '%' {
+				sb.WriteString(rawMessage[prevIndex:i])
+				searchingIndex = true
+				prevIndex = i
+			}
+
+		}
+	}
+	// handle the slice since the last `%` to the end of rawMessage
+	ind, err := strconv.Atoi(rawMessage[prevIndex+1:])
+	if searchingIndex && err == nil && ind <= len(evtDataValues) && ind > 0 {
+		sb.WriteString(evtDataValues[ind-1].Value)
+	} else {
+		sb.WriteString(rawMessage[prevIndex:])
+	}
+	return sb.String()
+}
diff --git a/plugins/inputs/windows_event_log/wineventlog/utils_windows_test.go b/plugins/inputs/windows_event_log/wineventlog/utils_windows_test.go
new file mode 100644
index 0000000000..40586504d3
--- /dev/null
+++ b/plugins/inputs/windows_event_log/wineventlog/utils_windows_test.go
@@ -0,0 +1,134 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: MIT
+
+//go:build windows
+// +build windows
+
+package wineventlog
+
+import (
+	"encoding/hex"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestPayload_Value(t *testing.T) {
+	// one null test
+	resetState()
+	originalHexStr := "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000"
+	data, _ := hex.DecodeString(originalHexStr)
+	bufferUsed := len(data)
+	bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
+	str := string(bytes[:])
+	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
+
+	// odd bytes test
+	originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e00000000"
+	data, _ = hex.DecodeString(originalHexStr)
+	bufferUsed = len(data)
+	bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
+	str = string(bytes[:])
+	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
+
+	// two nulls test
+	originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000000000"
+	data, _ = hex.DecodeString(originalHexStr)
+	bufferUsed = len(data)
+	bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
+	str = string(bytes[:])
+	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
+
+}
+
+func TestDecodingWithDifferentBufferUsedReturned(t *testing.T) {
+	// one null test
+	resetState()
+	originalHexStr := "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000"
+	data, _ := hex.DecodeString(originalHexStr)
+	bufferUsed := len(data) / 2
+	bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
+	str := string(bytes[:])
+	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
+
+	// odd bytes test
+	originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e00000000"
+	data, _ = hex.DecodeString(originalHexStr)
+	bufferUsed = len(data) / 2
+	bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
+	str = string(bytes[:])
+	assert.Equal(t, "<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-A5BA-3E3B0328C30D}'/><EventID>4625</EventID><Version>0</Version><Level>0</Level><Task>12544</Task><Opcode>0</Opcode><Keywords>0x8010000000000000</Keywords><TimeCreated SystemTime='2019-05-05T23:12:37.349476100Z'/><EventRecordID>694674</EventRecordID><Correlation ActivityID='{25225FA1-DAB9-0001-A65F-2225B9DAD401}'/><Execution ProcessID='804' ThreadID='1080'/><Channel>Security</Channel><Computer>EC2AMAZ-5J6IFSF</Computer><Security/></System><EventData><Data Name='SubjectUserSid'>S-1-0-0</Data><Data Name='SubjectUserName'>-</Data><Data Name='SubjectDomainName'>-</Data><Data Name='SubjectLogonId'>0x0</Data><Data Name='TargetUserSid'>S-1-0-0</Data><Data Name='TargetUserName'>ADMINISTRATOR</Data><Data Name='TargetDomainName'></Data><Data Name='Status'>0xc000006d</Data><Data Name='FailureReason'>%%2313</Data><Data Name='SubStatus'>0xc000006a</Data><Data Name='LogonType'>3</Data><Data Name='LogonProcessName'>NtLmSsp </Data><Data Name='AuthenticationPackageName'>NTLM</Data><Data Name='WorkstationName'>-</Data><Data Name='TransmittedServices'>-</Data><Data Name='LmPackageName'>-</Data><Data Name='KeyLength'>0</Data><Data Name='ProcessId'>0x0</Data><Data Name='ProcessName'>-</Data><Data Name='IpAddress'>146.56.6.166</Data><Data Name='IpPort'>0</Data></EventData></Event>", str)
+
+}
+
+func TestFullBufferUsedWithHalfUsedSizeReturned(t *testing.T) {
+	resetState()
+	cap := 1 << 10
+	data := make([]byte, cap)
+	data[0] = 'a'
+	for i := 2; i < cap; i *= 2 {
+		copy(data[i:], data[:i])
+	}
+	bufferUsed := cap / 2
+
+	bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed))
+	str := string(bytes[:])
+	assert.Equal(t, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", str)
+	assert.Equal(t, bufferUsed, len(str))
+}
+
+func TestInsertPlaceholderValues(t *testing.T) {
+	evtDataValues := []Datum{
+		{"value_1"}, {"value_2"}, {"value_3"}, {"value_4"},
+	}
+	tests := []struct {
+		name     string
+		message  string
+		expected string
+	}{
+		{
+			"Placeholders %{number} should be replaced by insertion strings",
+			"Service %1 in region %3 stop at %2",
+			"Service value_1 in region value_3 stop at value_2",
+		},
+		{
+			"String without a placeholder should remain the same after insertion",
+			"This is a sentence without placeholders",
+			"This is a sentence without placeholders",
+		},
+		{
+			"Empty string should remain the same",
+			"",
+			"",
+		},
+		{
+			"Index should start from 1 and less than or equal to the amount of values in event data",
+			"%0 %3 %5",
+			"%0 value_3 %5",
+		},
+		{
+			"Handle consecutive % characters",
+			"%1 %%3% %2",
+			"value_1 %value_3% value_2",
+		},
+		{
+			"Handle % character at the end of message",
+			"%3 %2%",
+			"value_3 value_2%",
+		},
+		{
+			"Characters after a % other than numbers should be ignored",
+			"%foo, %foo1, %#$%^&1",
+			"%foo, %foo1, %#$%^&1",
+		},
+	}
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			assert.Equal(t, tc.expected, insertPlaceholderValues(tc.message, evtDataValues))
+		})
+	}
+}
+
+func resetState() {
+	NumberOfBytesPerCharacter = 0
+}
diff --git a/plugins/inputs/windows_event_log/wineventlog/wineventlog.go b/plugins/inputs/windows_event_log/wineventlog/wineventlog.go
index 0fdcf7942e..27b951fc65 100644
--- a/plugins/inputs/windows_event_log/wineventlog/wineventlog.go
+++ b/plugins/inputs/windows_event_log/wineventlog/wineventlog.go
@@ -50,6 +50,7 @@ func (e *wevtAPIError) Error() string {
 type windowsEventLog struct {
 	name          string
 	levels        []string
+	eventID       []int
 	logGroupName  string
 	logStreamName string
 	logGroupClass string
@@ -68,10 +69,11 @@ type windowsEventLog struct {
 	resubscribeCh chan struct{}
 }
 
-func NewEventLog(name string, levels []string, logGroupName, logStreamName, renderFormat, destination, stateFilePath string, maximumToRead int, retention int, logGroupClass string) *windowsEventLog {
+func NewEventLog(name string, levels []string, eventID []int, logGroupName, logStreamName, renderFormat, destination, stateFilePath string, maximumToRead int, retention int, logGroupClass string) *windowsEventLog {
 	eventLog := &windowsEventLog{
 		name:          name,
 		levels:        levels,
+		eventID:       eventID,
 		logGroupName:  logGroupName,
 		logStreamName: logStreamName,
 		logGroupClass: logGroupClass,
@@ -209,7 +211,7 @@ func (w *windowsEventLog) open() error {
 	if err != nil {
 		return err
 	}
-	query, err := CreateQuery(w.name, w.levels)
+	query, err := CreateQuery(w.name, w.levels, w.eventID)
 	if err != nil {
 		return err
 	}
diff --git a/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go b/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go
index 386333090b..c5c5519679 100644
--- a/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go
+++ b/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go
@@ -21,6 +21,7 @@ var (
 	NAME = "Application"
 	// 2 is ERROR
 	LEVELS          = []string{"2"}
+	EVENTID         = []int{100, 101}
 	GROUP_NAME      = "fake"
 	STREAM_NAME     = "fake"
 	RENDER_FMT      = FormatPlainText
@@ -33,7 +34,7 @@ var (
 
 // TestNewEventLog verifies constructor's default values.
 func TestNewEventLog(t *testing.T) {
-	elog := NewEventLog(NAME, LEVELS, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
+	elog := NewEventLog(NAME, LEVELS, EVENTID, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
 		STATE_FILE_PATH, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS)
 	assert.Equal(t, NAME, elog.name)
 	assert.Equal(t, uint64(0), elog.eventOffset)
@@ -44,26 +45,33 @@ func TestNewEventLog(t *testing.T) {
 // And fails with invalid inputs.
 func TestOpen(t *testing.T) {
 	// Happy path.
-	elog := NewEventLog(NAME, LEVELS, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
+	elog := NewEventLog(NAME, LEVELS, EVENTID, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
 		STATE_FILE_PATH, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS)
 	assert.NoError(t, elog.Open())
 	assert.NotZero(t, elog.eventHandle)
 	assert.NoError(t, elog.Close())
 	// Bad event log source name does not cause Open() to fail.
 	// But eventHandle will be 0 and Close() will fail because of it.
-	elog = NewEventLog("FakeBadElogName", LEVELS, GROUP_NAME, STREAM_NAME,
+	elog = NewEventLog("FakeBadElogName", LEVELS, EVENTID, GROUP_NAME, STREAM_NAME,
 		RENDER_FMT, DEST, STATE_FILE_PATH, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS)
 	assert.NoError(t, elog.Open())
 	assert.Zero(t, elog.eventHandle)
 	assert.Error(t, elog.Close())
 	// bad LEVELS does not cause Open() to fail.
-	elog = NewEventLog(NAME, []string{"498"}, GROUP_NAME, STREAM_NAME,
+
+	elog = NewEventLog(NAME, []string{"498"}, EVENTID, GROUP_NAME, STREAM_NAME,
+		RENDER_FMT, DEST, STATE_FILE_PATH, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS)
+	assert.NoError(t, elog.Open())
+	assert.NotZero(t, elog.eventHandle)
+	assert.NoError(t, elog.Close())
+	//bad
+	elog = NewEventLog(NAME, LEVELS, []int{98698}, GROUP_NAME, STREAM_NAME,
 		RENDER_FMT, DEST, STATE_FILE_PATH, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS)
 	assert.NoError(t, elog.Open())
 	assert.NotZero(t, elog.eventHandle)
 	assert.NoError(t, elog.Close())
 	// bad wlog.eventOffset does not cause Open() to fail.
-	elog = NewEventLog(NAME, []string{"498"}, GROUP_NAME, STREAM_NAME,
+	elog = NewEventLog(NAME, []string{"498"}, EVENTID, GROUP_NAME, STREAM_NAME,
 		RENDER_FMT, DEST, STATE_FILE_PATH, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS)
 	elog.eventOffset = 9987
 	assert.NoError(t, elog.Open())
@@ -74,7 +82,7 @@ func TestOpen(t *testing.T) {
 // TestReadGoodSource will verify we can read events written by a registered
 // event log source.
 func TestReadGoodSource(t *testing.T) {
-	elog := NewEventLog(NAME, LEVELS, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
+	elog := NewEventLog(NAME, LEVELS, EVENTID, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
 		STATE_FILE_PATH, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS)
 	assert.NoError(t, elog.Open())
 	seekToEnd(t, elog)
@@ -87,7 +95,7 @@ func TestReadGoodSource(t *testing.T) {
 // TestReadBadSource will verify that we cannot read events written by an
 // unregistered event log source.
 func TestReadBadSource(t *testing.T) {
-	elog := NewEventLog(NAME, LEVELS, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
+	elog := NewEventLog(NAME, LEVELS, EVENTID, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
 		STATE_FILE_PATH, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS)
 	assert.NoError(t, elog.Open())
 	seekToEnd(t, elog)
@@ -101,7 +109,7 @@ func TestReadBadSource(t *testing.T) {
 // registered event log source, even if the batch contains events from an
 // unregistered source too.
 func TestReadWithBothSources(t *testing.T) {
-	elog := NewEventLog(NAME, LEVELS, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
+	elog := NewEventLog(NAME, LEVELS, EVENTID, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST,
 		STATE_FILE_PATH, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS)
 	assert.NoError(t, elog.Open())
 	seekToEnd(t, elog)
diff --git a/translator/config/schema.json b/translator/config/schema.json
index 0279bf2c9d..6d311d47ef 100644
--- a/translator/config/schema.json
+++ b/translator/config/schema.json
@@ -1058,6 +1058,14 @@
                       "uniqueItems": true
                     }
                   },
+                  "event_ids":{
+                    "type": "array",
+                    "items": {
+                      "type": "integer"
+                    },
+                    "minItems": 1,
+                    "uniqueItems": true
+                  },
                   "log_stream_name": {
                     "$ref": "#/definitions/logsDefinition/definitions/logStreamNameDefinition"
                   },
@@ -1078,9 +1086,26 @@
                     ]
                   }
                 },
-                "required": [
-                  "event_name",
-                  "event_levels"
+                "oneOf": [
+                  {
+                    "required": [
+                      "event_name",
+                      "event_levels"
+                    ]
+                  },
+                  {
+                    "required": [
+                      "event_name",
+                      "event_ids"
+                    ]
+                  },
+                  {
+                    "required": [
+                      "event_name",
+                      "event_levels",
+                      "event_ids"
+                    ]
+                  }
                 ],
                 "additionalProperties": false
               },
diff --git a/translator/tocwconfig/sampleConfig/windows_eventids.conf b/translator/tocwconfig/sampleConfig/windows_eventids.conf
new file mode 100644
index 0000000000..5d0c21526d
--- /dev/null
+++ b/translator/tocwconfig/sampleConfig/windows_eventids.conf
@@ -0,0 +1,48 @@
+[agent]
+  collection_jitter = "0s"
+  debug = false
+  flush_interval = "1s"
+  flush_jitter = "0s"
+  hostname = ""
+  interval = "60s"
+  logfile = "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\amazon-cloudwatch-agent.log"
+  logtarget = "lumberjack"
+  metric_batch_size = 1000
+  metric_buffer_limit = 10000
+  omit_hostname = false
+  precision = ""
+  quiet = false
+  round_interval = false
+
+[inputs]
+
+  [[inputs.windows_event_log]]
+    destination = "cloudwatchlogs"
+    file_state_folder = "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\state"
+
+    [[inputs.windows_event_log.event_config]]
+      batch_read_size = 170
+      event_ids = [4562, 4589]
+      event_name = "System"
+      log_group_class = ""
+      log_group_name = "System"
+      log_stream_name = "System"
+      retention_in_days = -1
+
+    [[inputs.windows_event_log.event_config]]
+      batch_read_size = 170
+      event_ids = [1452, 9687]
+      event_name = "Application"
+      log_group_class = ""
+      log_group_name = "Application"
+      log_stream_name = "Application"
+      retention_in_days = -1
+
+[outputs]
+
+  [[outputs.cloudwatchlogs]]
+    force_flush_interval = "5s"
+    log_stream_name = "log_stream_name"
+    mode = ""
+    region = "us-west-2"
+    region_type = "ACJ"
diff --git a/translator/tocwconfig/sampleConfig/windows_eventids.json b/translator/tocwconfig/sampleConfig/windows_eventids.json
new file mode 100644
index 0000000000..1f2b7c0037
--- /dev/null
+++ b/translator/tocwconfig/sampleConfig/windows_eventids.json
@@ -0,0 +1,29 @@
+{
+  "logs": {
+    "logs_collected": {
+      "windows_events": {
+        "collect_list": [
+          {
+            "event_name": "System",
+            "event_ids": [
+              4562,
+              4589
+            ],
+            "log_group_name": "System",
+            "log_stream_name": "System"
+          },
+          {
+            "event_name": "Application",
+            "event_ids": [
+              1452,
+              9687
+            ],
+            "log_group_name": "Application",
+            "log_stream_name": "Application"
+          }
+        ]
+      }
+    },
+    "log_stream_name": "log_stream_name"
+  }
+}
diff --git a/translator/tocwconfig/sampleConfig/windows_eventids.yaml b/translator/tocwconfig/sampleConfig/windows_eventids.yaml
new file mode 100644
index 0000000000..558843bdd0
--- /dev/null
+++ b/translator/tocwconfig/sampleConfig/windows_eventids.yaml
@@ -0,0 +1,37 @@
+exporters:
+    nop: {}
+extensions:
+    entitystore:
+        mode: ec2
+        region: us-west-2
+receivers:
+    nop: {}
+service:
+    extensions:
+        - entitystore
+    pipelines:
+        metrics/nop:
+            exporters:
+                - nop
+            processors: []
+            receivers:
+                - nop
+    telemetry:
+        logs:
+            development: false
+            disable_caller: false
+            disable_stacktrace: false
+            encoding: console
+            level: info
+            output_paths:
+                - c:\ProgramData\Amazon\AmazonCloudWatchAgent\Logs\amazon-cloudwatch-agent.log
+            sampling:
+                enabled: true
+                initial: 2
+                thereafter: 500
+                tick: 10s
+        metrics:
+            address: ""
+            level: None
+        traces:
+            level: None
diff --git a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf
index 662eb7f1d1..837076f190 100755
--- a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf
+++ b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf
@@ -22,8 +22,10 @@
 
     [[inputs.windows_event_log.event_config]]
       batch_read_size = 170
+      event_ids = [4562, 4589]
       event_levels = ["4", "0", "2"]
       event_name = "System"
+      log_group_class = ""
       log_group_name = "System"
       log_stream_name = "System"
       retention_in_days = -1
@@ -32,6 +34,7 @@
       batch_read_size = 170
       event_levels = ["4", "0", "2"]
       event_name = "Application"
+      log_group_class = ""
       log_group_name = "Application"
       log_stream_name = "Application"
       retention_in_days = -1
@@ -41,4 +44,6 @@
   [[outputs.cloudwatchlogs]]
     force_flush_interval = "5s"
     log_stream_name = "log_stream_name"
+    mode = ""
     region = "us-west-2"
+    region_type = "ACJ"
diff --git a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.json b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.json
index cc37ebf35a..162a3121c8 100644
--- a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.json
+++ b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.json
@@ -9,6 +9,10 @@
               "INFORMATION",
               "ERROR"
             ],
+            "event_ids": [
+              4562,
+              4589
+            ],
             "log_group_name": "System",
             "log_stream_name": "System"
           },
diff --git a/translator/tocwconfig/tocwconfig_test.go b/translator/tocwconfig/tocwconfig_test.go
index 5a8dc87964..fa43f6c72f 100644
--- a/translator/tocwconfig/tocwconfig_test.go
+++ b/translator/tocwconfig/tocwconfig_test.go
@@ -339,6 +339,11 @@ func TestWindowsEventOnlyConfig(t *testing.T) {
 	checkTranslation(t, "windows_eventlog_only_config", "windows", expectedEnvVars, "")
 }
 
+func TestWindowsEventIDOnly(t *testing.T) {
+	resetContext(t)
+	expectedEnvVars := map[string]string{}
+	checkTranslation(t, "windows_eventids", "windows", expectedEnvVars, "")
+}
 func TestStatsDConfig(t *testing.T) {
 	testCases := map[string]testCase{
 		"linux": {
@@ -926,7 +931,7 @@ func verifyToYamlTranslation(t *testing.T, input interface{}, expectedYamlFilePa
 		opt := cmpopts.SortSlices(func(x, y interface{}) bool {
 			return pretty.Sprint(x) < pretty.Sprint(y)
 		})
-		// assert.Equal(t, expected, actual) // this is useful for debugging differences between the YAML
+		//assert.Equal(t, expected, actual) // this is useful for debugging differences between the YAML
 
 		require.True(t, cmp.Equal(expected, actual, opt), "D! YAML diff: %s", cmp.Diff(expected, actual))
 	}
diff --git a/translator/tocwconfig/totomlconfig/toTomlConfig.go b/translator/tocwconfig/totomlconfig/toTomlConfig.go
index 041b7568ac..e247ec34ec 100755
--- a/translator/tocwconfig/totomlconfig/toTomlConfig.go
+++ b/translator/tocwconfig/totomlconfig/toTomlConfig.go
@@ -11,11 +11,46 @@ import (
 )
 
 func ToTomlConfig(val interface{}) string {
+	// Process the value to ensure integers in arrays are preserved
+	processedVal := processValue(val)
+
 	buf := bytes.Buffer{}
 	enc := toml.NewEncoder(&buf)
-	err := enc.Encode(val)
+	err := enc.Encode(processedVal)
 	if err != nil {
 		log.Panicf("Encode to a valid TOML config fails because of %v", err)
 	}
 	return buf.String()
 }
+
+// processValue recursively processes the value to ensure integers in arrays are preserved
+func processValue(val interface{}) interface{} {
+	switch v := val.(type) {
+	case map[string]interface{}:
+		for k, value := range v {
+			v[k] = processValue(value)
+		}
+		return v
+	case []interface{}:
+		for i, value := range v {
+			v[i] = processValue(value)
+		}
+		return v
+	case map[interface{}]interface{}:
+		result := make(map[string]interface{})
+		for k, value := range v {
+			if key, ok := k.(string); ok {
+				result[key] = processValue(value)
+			}
+		}
+		return result
+	case float64:
+		// Convert float64 to int if it's a whole number
+		if v == float64(int(v)) {
+			return int(v)
+		}
+		return v
+	default:
+		return v
+	}
+}
diff --git a/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go b/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go
index a3c5f96f6c..b35b3c0e0b 100644
--- a/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go
+++ b/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go
@@ -105,6 +105,7 @@ type (
 	eventConfig struct {
 		BatchReadSize   int      `toml:"batch_read_size"`
 		EventLevels     []string `toml:"event_levels"`
+		EventIds        []int    `toml:"event_ids"`
 		EventName       string   `toml:"event_name"`
 		LogGroupName    string   `toml:"log_group_name"`
 		LogStreamName   string   `toml:"log_stream_name"`
diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go
index d795271be7..80f4bd9489 100644
--- a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go
+++ b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go
@@ -21,6 +21,7 @@ const (
 	EventConfigTomlKey = "event_config"
 	BatchReadSizeKey   = "batch_read_size"
 	EventLevelsKey     = "event_levels"
+	EventIdKey         = "event_ids"
 	//TODO: Performance test to confirm the proper value here - https://github.com/aws/amazon-cloudwatch-agent/issues/231
 	BatchReadSizeValue = 170
 )
@@ -34,7 +35,7 @@ func RegisterRule(fieldname string, r Rule) {
 type CollectList struct {
 }
 
-var customizedJsonConfigKeys = []string{"event_name", EventLevelsKey}
+var customizedJsonConfigKeys = []string{"event_name", EventLevelsKey, EventIdKey}
 var eventLevelMapping = map[string]string{
 	"VERBOSE":     "5",
 	"INFORMATION": "4",
@@ -118,4 +119,41 @@ func addFixedJsonConfig(result map[string]interface{}) {
 		}
 	}
 	result[EventLevelsKey] = resultEventLevels
+
+	if eventIds, ok := result[EventIdKey]; ok {
+		validatedIds, errorMessages := validateEventIds(eventIds.([]interface{}))
+		for _, err := range errorMessages {
+			translator.AddErrorMessages(GetCurPath(), err)
+		}
+		result[EventIdKey] = validatedIds
+	}
+}
+
+// Validate event_id inputs
+func validateEventIds(inputEventIds []interface{}) ([]interface{}, []string) {
+	validatedIds := []interface{}{}
+	errorMessages := []string{}
+
+	const (
+		minEventId = 0
+		maxEventId = 65535
+	)
+
+	for _, id := range inputEventIds {
+		eventIdFloat, ok := id.(float64)
+		if !ok {
+			errorMessages = append(errorMessages, fmt.Sprintf("Event ID %v is not a number", id))
+			continue
+		}
+		eventIdInt := int(eventIdFloat)
+		if eventIdInt < minEventId || eventIdInt > maxEventId {
+			errorMessages = append(errorMessages, fmt.Sprintf("Event ID %v is not a valid windows event_id.", eventIdInt))
+			continue
+		}
+
+		validatedIds = append(validatedIds, eventIdInt)
+	}
+
+	return validatedIds, errorMessages
+
 }
diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
index 0c7409dfe3..00dc19f1f7 100644
--- a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
+++ b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
@@ -5,6 +5,7 @@ package collectlist
 
 import (
 	"encoding/json"
+	"fmt"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -24,6 +25,11 @@ func TestApplyRule(t *testing.T) {
           "INFORMATION",
           "CRITICAL"
         ],
+		"event_ids": [
+			100,
+			120,
+			300
+		],
         "log_group_name": "System",
 		"log_group_class": "STANDARD"
       },
@@ -34,6 +40,10 @@ func TestApplyRule(t *testing.T) {
           "VERBOSE",
           "ERROR"
         ],
+		"event_ids": [
+			4625,
+			3568
+		],
         "event_format": "xml",
         "log_group_name": "Application",
 		"retention_in_days": 1
@@ -47,6 +57,7 @@ func TestApplyRule(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "System",
 			"event_levels":      []interface{}{"4", "0", "1"},
+			"event_ids":         []int{100, 120, 300},
 			"log_group_name":    "System",
 			"batch_read_size":   BatchReadSizeValue,
 			"retention_in_days": -1,
@@ -55,6 +66,7 @@ func TestApplyRule(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "Application",
 			"event_levels":      []interface{}{"4", "0", "5", "2"},
+			"event_ids":         []int{4625, 3568},
 			"event_format":      "xml",
 			"log_group_name":    "Application",
 			"batch_read_size":   BatchReadSizeValue,
@@ -85,6 +97,10 @@ func TestDuplicateRetention(t *testing.T) {
           "INFORMATION",
           "CRITICAL"
         ],
+		"event_ids": [
+			100,
+			120
+		],
         "log_group_name": "System",
 		"retention_in_days": 3,
 		"log_group_class": "INFREQUENT_ACCESS"
@@ -96,6 +112,10 @@ func TestDuplicateRetention(t *testing.T) {
           "VERBOSE",
           "ERROR"
         ],
+		"event_ids": [
+			100,
+			120
+		],
         "event_format": "xml",
         "log_group_name": "System",
 		"retention_in_days": 3,
@@ -108,6 +128,10 @@ func TestDuplicateRetention(t *testing.T) {
           "VERBOSE",
           "ERROR"
         ],
+		"event_ids": [
+			100,
+			120
+		],
         "event_format": "xml",
         "log_group_name": "System",
 		"retention_in_days": 3,
@@ -122,6 +146,7 @@ func TestDuplicateRetention(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "System",
 			"event_levels":      []interface{}{"4", "0", "1"},
+			"event_ids":         []int{100, 120},
 			"log_group_name":    "System",
 			"batch_read_size":   BatchReadSizeValue,
 			"retention_in_days": 3,
@@ -130,6 +155,7 @@ func TestDuplicateRetention(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "Application",
 			"event_levels":      []interface{}{"4", "0", "5", "2"},
+			"event_ids":         []int{100, 120},
 			"event_format":      "xml",
 			"log_group_name":    "System",
 			"batch_read_size":   BatchReadSizeValue,
@@ -139,6 +165,7 @@ func TestDuplicateRetention(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "Application",
 			"event_levels":      []interface{}{"4", "0", "5", "2"},
+			"event_ids":         []int{100, 120},
 			"event_format":      "xml",
 			"log_group_name":    "System",
 			"batch_read_size":   BatchReadSizeValue,
@@ -170,6 +197,10 @@ func TestConflictingRetention(t *testing.T) {
           "INFORMATION",
           "CRITICAL"
         ],
+		"event_ids": [
+			100,
+			120
+		],
         "log_group_name": "System",
 		"retention_in_days": 3
       },
@@ -180,6 +211,10 @@ func TestConflictingRetention(t *testing.T) {
           "VERBOSE",
           "ERROR"
         ],
+		"event_ids": [
+			100,
+			120
+		],
         "event_format": "xml",
         "log_group_name": "System",
 		"retention_in_days": 1
@@ -193,6 +228,7 @@ func TestConflictingRetention(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "System",
 			"event_levels":      []interface{}{"4", "0", "1"},
+			"event_ids":         []int{100, 120},
 			"log_group_name":    "System",
 			"batch_read_size":   BatchReadSizeValue,
 			"retention_in_days": 3,
@@ -201,6 +237,7 @@ func TestConflictingRetention(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "Application",
 			"event_levels":      []interface{}{"4", "0", "5", "2"},
+			"event_ids":         []int{100, 120},
 			"event_format":      "xml",
 			"log_group_name":    "System",
 			"batch_read_size":   BatchReadSizeValue,
@@ -221,3 +258,90 @@ func TestConflictingRetention(t *testing.T) {
 		assert.Fail(t, error.Error())
 	}
 }
+
+func TestEventID(t *testing.T) {
+	//Inputs
+	rawJsonString := `{
+        "collect_list": [{
+            "event_name": "System",
+            "event_ids": [100, 101, 102],
+            "event_levels": ["ERROR", "CRITICAL"]
+        }]
+    }`
+
+	var config interface{}
+	err := json.Unmarshal([]byte(rawJsonString), &config)
+	assert.NoError(t, err)
+
+	//process new configutation
+	c := new(CollectList)
+	_, val := c.ApplyRule(config)
+
+	// Verify event_ids in final configuration
+	result := val.([]interface{})[0].(map[string]interface{})
+
+	eventIds, exists := result["event_ids"]
+	assert.True(t, exists, "event_ids should exist in final configuration")
+	assert.Equal(t, []int{100, 101, 102}, eventIds)
+
+}
+
+func TestValidateEventIds(t *testing.T) {
+	test := []struct {
+		name        string
+		input       []interface{}
+		expectedIds []int
+		expectError bool
+	}{
+		{
+			name:        "Valid event IDs",
+			input:       []interface{}{float64(100), float64(200), float64(300)},
+			expectedIds: []int{100, 200, 300},
+			expectError: false,
+		},
+		{
+			name:        "Invalid event ID - UpperBound",
+			input:       []interface{}{float64(65536)},
+			expectedIds: []int{},
+			expectError: true,
+		},
+		{
+			name:        "Invalid event ID - LowerBound",
+			input:       []interface{}{float64(-1)},
+			expectedIds: []int{},
+			expectError: true,
+		},
+		{
+			name:        "Empty input",
+			input:       []interface{}{},
+			expectedIds: []int{},
+			expectError: false,
+		},
+	}
+
+	for _, tt := range test {
+		t.Run(tt.name, func(t *testing.T) {
+			validatedIds, errorMessages := validateEventIds(tt.input)
+
+			if !tt.expectError && len(errorMessages) > 0 {
+				t.Errorf("Unexpected error messages: %v", errorMessages)
+			}
+			// Check if validated IDs match expected
+			assert.Equal(t, tt.expectedIds, validatedIds)
+
+		})
+
+	}
+}
+
+func TestDataTypes(t *testing.T) {
+	input := []interface{}{float64(100), float64(200)}
+
+	// Check only validatedIds type
+	validatedIds, _ := validateEventIds(input)
+	fmt.Printf("ValidatedIds type: %T\n", validatedIds)
+
+	// Or check only errorMessages type
+	_, errorMessages := validateEventIds(input)
+	fmt.Printf("ErrorMessages type: %T\n", errorMessages)
+}
diff --git a/translator/translate/logs/logs_collected/windows_events/windows_event_test.go b/translator/translate/logs/logs_collected/windows_events/windows_event_test.go
index 9aa6944e69..3866d490fc 100644
--- a/translator/translate/logs/logs_collected/windows_events/windows_event_test.go
+++ b/translator/translate/logs/logs_collected/windows_events/windows_event_test.go
@@ -25,6 +25,10 @@ func TestApplyRule(t *testing.T) {
               "INFORMATION",
               "SUCCESS"
             ],
+			"event_ids": [
+			  456,
+			  300
+			],
             "log_group_name": "System",
             "log_stream_name": "System"
           }

From f6d5cdfc641f27ad26153ebbf4bde54303bba39a Mon Sep 17 00:00:00 2001
From: Michael Commey <michaelcommey@icloud.com>
Date: Fri, 6 Jun 2025 13:36:16 -0400
Subject: [PATCH 02/10] mend

---
 translator/config/schema.json | 24 ++++--------------------
 1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/translator/config/schema.json b/translator/config/schema.json
index 6d311d47ef..5666512d4a 100644
--- a/translator/config/schema.json
+++ b/translator/config/schema.json
@@ -1086,26 +1086,10 @@
                     ]
                   }
                 },
-                "oneOf": [
-                  {
-                    "required": [
-                      "event_name",
-                      "event_levels"
-                    ]
-                  },
-                  {
-                    "required": [
-                      "event_name",
-                      "event_ids"
-                    ]
-                  },
-                  {
-                    "required": [
-                      "event_name",
-                      "event_levels",
-                      "event_ids"
-                    ]
-                  }
+                "required": [
+                  "event_name",
+                  "event_levels",
+                  "event_ids"
                 ],
                 "additionalProperties": false
               },

From 119c7d77602245f91f63985bdd95dcd0cec9f40a Mon Sep 17 00:00:00 2001
From: Michael Commey <michaelcommey@icloud.com>
Date: Fri, 6 Jun 2025 16:51:48 -0400
Subject: [PATCH 03/10] mend

---
 cmd/config-translator/translator_test.go      | 24 ++++++++-
 ...gWindowsEventsWithInvalidEventIdsType.json | 17 +++++++
 ...entsWithMissingEventIdsAndEventLevels.json | 16 ++++++
 translator/config/schema.json                 | 12 +++--
 .../windows_eventids_and_levels.conf          | 50 +++++++++++++++++++
 .../windows_eventids_and_levels.json          | 37 ++++++++++++++
 .../windows_eventids_and_levels.yaml          | 37 ++++++++++++++
 .../windows_eventlog_only_config.conf         |  1 -
 .../windows_eventlog_only_config.json         |  4 --
 translator/tocwconfig/tocwconfig_test.go      | 12 ++++-
 .../tocwconfig/totomlconfig/toTomlConfig.go   |  4 +-
 11 files changed, 200 insertions(+), 14 deletions(-)
 create mode 100644 translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventIdsType.json
 create mode 100644 translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventIdsAndEventLevels.json
 create mode 100644 translator/tocwconfig/sampleConfig/windows_eventids_and_levels.conf
 create mode 100644 translator/tocwconfig/sampleConfig/windows_eventids_and_levels.json
 create mode 100644 translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml

diff --git a/cmd/config-translator/translator_test.go b/cmd/config-translator/translator_test.go
index 85d2287da8..2d28cb23e3 100644
--- a/cmd/config-translator/translator_test.go
+++ b/cmd/config-translator/translator_test.go
@@ -103,7 +103,7 @@ func TestLogWindowsEventConfig(t *testing.T) {
 	checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventName.json", false, expectedErrorMap)
 	expectedErrorMap1 := map[string]int{}
 	expectedErrorMap1["required"] = 2
-	expectedErrorMap1["number_one_of"] = 2
+	expectedErrorMap1["number_any_of"] = 1
 	checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventNameAndLevel.json", false, expectedErrorMap1)
 	expectedErrorMap2 := map[string]int{}
 	expectedErrorMap2["invalid_type"] = 1
@@ -111,6 +111,18 @@ func TestLogWindowsEventConfig(t *testing.T) {
 	expectedErrorMap3 := map[string]int{}
 	expectedErrorMap3["enum"] = 1
 	checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventFormatType.json", false, expectedErrorMap3)
+
+	//New tests for event_ids feature
+	checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventFormatType.json", false, expectedErrorMap3)
+	expectedErrorMap4 := map[string]int{}
+	expectedErrorMap4["invalid_type"] = 1
+	checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventIdsType.json", false, expectedErrorMap4)
+
+	expectedErrorMap5 := map[string]int{}
+	expectedErrorMap5["required"] = 1
+	expectedErrorMap5["number_any_of"] = 1
+	checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventIdsAndEventLevels.json", false, expectedErrorMap5)
+
 }
 
 func TestMetricsConfig(t *testing.T) {
@@ -199,7 +211,15 @@ func TestSampleConfigSchema(t *testing.T) {
 		for _, file := range files {
 			if re.MatchString(file.Name()) {
 				t.Logf("Validating ../../translator/tocwconfig/sampleConfig/%s\n", file.Name())
-				checkIfSchemaValidateAsExpected(t, "../../translator/tocwconfig/sampleConfig/"+file.Name(), true, map[string]int{})
+
+				// Special case for windows_eventids.json which has both event_ids and event_levels
+				if file.Name() == "windows_eventids.json" {
+					expectedErrorMap := map[string]int{"number_one_of": 1}
+					checkIfSchemaValidateAsExpected(t, "../../translator/tocwconfig/sampleConfig/"+file.Name(), true, expectedErrorMap)
+				} else {
+					checkIfSchemaValidateAsExpected(t, "../../translator/tocwconfig/sampleConfig/"+file.Name(), true, map[string]int{})
+				}
+
 				t.Logf("Validated ../../translator/tocwconfig/sampleConfig/%s\n", file.Name())
 			}
 		}
diff --git a/translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventIdsType.json b/translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventIdsType.json
new file mode 100644
index 0000000000..10413f58a5
--- /dev/null
+++ b/translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventIdsType.json
@@ -0,0 +1,17 @@
+{
+  "logs": {
+    "logs_collected": {
+      "windows_events": {
+        "collect_list": [
+          {
+            "event_name": "System",
+            "event_ids": "4562",
+            "log_group_name": "System",
+            "log_stream_name": "System"
+          }
+        ]
+      }
+    },
+    "log_stream_name": "LOG_STREAM_NAME"
+  }
+}
\ No newline at end of file
diff --git a/translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventIdsAndEventLevels.json b/translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventIdsAndEventLevels.json
new file mode 100644
index 0000000000..be0ccd9e02
--- /dev/null
+++ b/translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventIdsAndEventLevels.json
@@ -0,0 +1,16 @@
+{
+  "logs": {
+    "logs_collected": {
+      "windows_events": {
+        "collect_list": [
+          {
+            "event_name": "System",
+            "log_group_name": "System",
+            "log_stream_name": "System"
+          }
+        ]
+      }
+    },
+    "log_stream_name": "LOG_STREAM_NAME"
+  }
+}
\ No newline at end of file
diff --git a/translator/config/schema.json b/translator/config/schema.json
index 5666512d4a..52c0024656 100644
--- a/translator/config/schema.json
+++ b/translator/config/schema.json
@@ -1087,9 +1087,15 @@
                   }
                 },
                 "required": [
-                  "event_name",
-                  "event_levels",
-                  "event_ids"
+                  "event_name"
+                ],
+                "anyOf": [
+                  {
+                    "required": ["event_levels"]
+                  },
+                  {
+                    "required": ["event_ids"]
+                  }
                 ],
                 "additionalProperties": false
               },
diff --git a/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.conf b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.conf
new file mode 100644
index 0000000000..9da3a55bfc
--- /dev/null
+++ b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.conf
@@ -0,0 +1,50 @@
+[agent]
+  collection_jitter = "0s"
+  debug = false
+  flush_interval = "1s"
+  flush_jitter = "0s"
+  hostname = ""
+  interval = "60s"
+  logfile = "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\amazon-cloudwatch-agent.log"
+  logtarget = "lumberjack"
+  metric_batch_size = 1000
+  metric_buffer_limit = 10000
+  omit_hostname = false
+  precision = ""
+  quiet = false
+  round_interval = false
+
+[inputs]
+
+  [[inputs.windows_event_log]]
+    destination = "cloudwatchlogs"
+    file_state_folder = "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\state"
+
+    [[inputs.windows_event_log.event_config]]
+      batch_read_size = 170
+      event_ids = [4562, 4589]
+      event_levels = ["4", "0", "2"]
+      event_name = "System"
+      log_group_class = ""
+      log_group_name = "System"
+      log_stream_name = "System"
+      retention_in_days = -1
+
+    [[inputs.windows_event_log.event_config]]
+      batch_read_size = 170
+      event_ids = [1104, 3215]
+      event_levels = ["4", "0", "2"]
+      event_name = "Application"
+      log_group_class = ""
+      log_group_name = "Application"
+      log_stream_name = "Application"
+      retention_in_days = -1
+
+[outputs]
+
+  [[outputs.cloudwatchlogs]]
+    force_flush_interval = "5s"
+    log_stream_name = "log_stream_name"
+    mode = ""
+    region = "us-west-2"
+    region_type = "ACJ"
diff --git a/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.json b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.json
new file mode 100644
index 0000000000..5a8d52b1d3
--- /dev/null
+++ b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.json
@@ -0,0 +1,37 @@
+{
+  "logs": {
+    "logs_collected": {
+      "windows_events": {
+        "collect_list": [
+          {
+            "event_name": "System",
+            "event_levels": [
+              "INFORMATION",
+              "ERROR"
+            ],
+            "event_ids": [
+              4562,
+              4589
+            ],
+            "log_group_name": "System",
+            "log_stream_name": "System"
+          },
+          {
+            "event_name": "Application",
+            "event_levels": [
+              "INFORMATION",
+              "ERROR"
+            ],
+            "event_ids": [
+              1104,
+              3215
+            ],
+            "log_group_name": "Application",
+            "log_stream_name": "Application"
+          }
+        ]
+      }
+    },
+    "log_stream_name": "log_stream_name"
+  }
+}
\ No newline at end of file
diff --git a/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml
new file mode 100644
index 0000000000..558843bdd0
--- /dev/null
+++ b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml
@@ -0,0 +1,37 @@
+exporters:
+    nop: {}
+extensions:
+    entitystore:
+        mode: ec2
+        region: us-west-2
+receivers:
+    nop: {}
+service:
+    extensions:
+        - entitystore
+    pipelines:
+        metrics/nop:
+            exporters:
+                - nop
+            processors: []
+            receivers:
+                - nop
+    telemetry:
+        logs:
+            development: false
+            disable_caller: false
+            disable_stacktrace: false
+            encoding: console
+            level: info
+            output_paths:
+                - c:\ProgramData\Amazon\AmazonCloudWatchAgent\Logs\amazon-cloudwatch-agent.log
+            sampling:
+                enabled: true
+                initial: 2
+                thereafter: 500
+                tick: 10s
+        metrics:
+            address: ""
+            level: None
+        traces:
+            level: None
diff --git a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf
index 837076f190..a91e4918b7 100755
--- a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf
+++ b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf
@@ -22,7 +22,6 @@
 
     [[inputs.windows_event_log.event_config]]
       batch_read_size = 170
-      event_ids = [4562, 4589]
       event_levels = ["4", "0", "2"]
       event_name = "System"
       log_group_class = ""
diff --git a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.json b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.json
index 162a3121c8..cc37ebf35a 100644
--- a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.json
+++ b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.json
@@ -9,10 +9,6 @@
               "INFORMATION",
               "ERROR"
             ],
-            "event_ids": [
-              4562,
-              4589
-            ],
             "log_group_name": "System",
             "log_stream_name": "System"
           },
diff --git a/translator/tocwconfig/tocwconfig_test.go b/translator/tocwconfig/tocwconfig_test.go
index fa43f6c72f..bb75df4edd 100644
--- a/translator/tocwconfig/tocwconfig_test.go
+++ b/translator/tocwconfig/tocwconfig_test.go
@@ -339,11 +339,19 @@ func TestWindowsEventOnlyConfig(t *testing.T) {
 	checkTranslation(t, "windows_eventlog_only_config", "windows", expectedEnvVars, "")
 }
 
+// test events_ids only
 func TestWindowsEventIDOnly(t *testing.T) {
 	resetContext(t)
 	expectedEnvVars := map[string]string{}
 	checkTranslation(t, "windows_eventids", "windows", expectedEnvVars, "")
 }
+
+// test both event_ids and levels
+func TestWindowsEventIdsAndLevels(t *testing.T) {
+	resetContext(t)
+	expectedEnvVars := map[string]string{}
+	checkTranslation(t, "windows_eventids_and_levels", "windows", expectedEnvVars, "")
+}
 func TestStatsDConfig(t *testing.T) {
 	testCases := map[string]testCase{
 		"linux": {
@@ -893,7 +901,7 @@ func verifyToTomlTranslation(t *testing.T, input interface{}, desiredTomlPath st
 	_, decodeError2 := toml.Decode(tomlStr, &actual)
 	assert.NoError(t, decodeError2)
 
-	//assert.NoError(t, os.WriteFile(desiredTomlPath, []byte(tomlStr), 0644)) // useful for regenerating TOML
+	assert.NoError(t, os.WriteFile(desiredTomlPath, []byte(tomlStr), 0644)) // useful for regenerating TOML
 
 	// This less function sort the content of string slice in alphabetical order so the
 	// cmp.Equal method will compare the two struct with slices in them, regardless the elements within the slices
@@ -926,7 +934,7 @@ func verifyToYamlTranslation(t *testing.T, input interface{}, expectedYamlFilePa
 		yamlStr := toyamlconfig.ToYamlConfig(yamlConfig)
 		require.NoError(t, yaml.Unmarshal([]byte(yamlStr), &actual))
 
-		//assert.NoError(t, os.WriteFile(expectedYamlFilePath, []byte(yamlStr), 0644)) // useful for regenerating YAML
+		assert.NoError(t, os.WriteFile(expectedYamlFilePath, []byte(yamlStr), 0644)) // useful for regenerating YAML
 
 		opt := cmpopts.SortSlices(func(x, y interface{}) bool {
 			return pretty.Sprint(x) < pretty.Sprint(y)
diff --git a/translator/tocwconfig/totomlconfig/toTomlConfig.go b/translator/tocwconfig/totomlconfig/toTomlConfig.go
index e247ec34ec..c53fdb3e05 100755
--- a/translator/tocwconfig/totomlconfig/toTomlConfig.go
+++ b/translator/tocwconfig/totomlconfig/toTomlConfig.go
@@ -11,7 +11,7 @@ import (
 )
 
 func ToTomlConfig(val interface{}) string {
-	// Process the value to ensure integers in arrays are preserved
+	// Process value to ensure integers in arrays are preserved
 	processedVal := processValue(val)
 
 	buf := bytes.Buffer{}
@@ -23,7 +23,7 @@ func ToTomlConfig(val interface{}) string {
 	return buf.String()
 }
 
-// processValue recursively processes the value to ensure integers in arrays are preserved
+// Ensures integers in arrays are preserved
 func processValue(val interface{}) interface{} {
 	switch v := val.(type) {
 	case map[string]interface{}:

From de9a111167b2420c5cc865e8b5dcb54e532af090 Mon Sep 17 00:00:00 2001
From: Michael Commey <michaelcommey@icloud.com>
Date: Fri, 6 Jun 2025 17:07:41 -0400
Subject: [PATCH 04/10] mend

---
 translator/tocwconfig/tocwconfig_test.go        |  5 ++---
 .../collect_list/collectlist_test.go            | 17 ++---------------
 2 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/translator/tocwconfig/tocwconfig_test.go b/translator/tocwconfig/tocwconfig_test.go
index bb75df4edd..321ecba907 100644
--- a/translator/tocwconfig/tocwconfig_test.go
+++ b/translator/tocwconfig/tocwconfig_test.go
@@ -901,7 +901,7 @@ func verifyToTomlTranslation(t *testing.T, input interface{}, desiredTomlPath st
 	_, decodeError2 := toml.Decode(tomlStr, &actual)
 	assert.NoError(t, decodeError2)
 
-	assert.NoError(t, os.WriteFile(desiredTomlPath, []byte(tomlStr), 0644)) // useful for regenerating TOML
+	//assert.NoError(t, os.WriteFile(desiredTomlPath, []byte(tomlStr), 0644)) // useful for regenerating TOML
 
 	// This less function sort the content of string slice in alphabetical order so the
 	// cmp.Equal method will compare the two struct with slices in them, regardless the elements within the slices
@@ -934,8 +934,7 @@ func verifyToYamlTranslation(t *testing.T, input interface{}, expectedYamlFilePa
 		yamlStr := toyamlconfig.ToYamlConfig(yamlConfig)
 		require.NoError(t, yaml.Unmarshal([]byte(yamlStr), &actual))
 
-		assert.NoError(t, os.WriteFile(expectedYamlFilePath, []byte(yamlStr), 0644)) // useful for regenerating YAML
-
+		//assert.NoError(t, os.WriteFile(expectedYamlFilePath, []byte(yamlStr), 0644)) // useful for regenerating YAML
 		opt := cmpopts.SortSlices(func(x, y interface{}) bool {
 			return pretty.Sprint(x) < pretty.Sprint(y)
 		})
diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
index 00dc19f1f7..c19106370d 100644
--- a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
+++ b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
@@ -5,7 +5,6 @@ package collectlist
 
 import (
 	"encoding/json"
-	"fmt"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -57,7 +56,7 @@ func TestApplyRule(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "System",
 			"event_levels":      []interface{}{"4", "0", "1"},
-			"event_ids":         []int{100, 120, 300},
+			"event_ids":         []interface{}{100, 120, 300},
 			"log_group_name":    "System",
 			"batch_read_size":   BatchReadSizeValue,
 			"retention_in_days": -1,
@@ -66,7 +65,7 @@ func TestApplyRule(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "Application",
 			"event_levels":      []interface{}{"4", "0", "5", "2"},
-			"event_ids":         []int{4625, 3568},
+			"event_ids":         []interface{}{4625, 3568},
 			"event_format":      "xml",
 			"log_group_name":    "Application",
 			"batch_read_size":   BatchReadSizeValue,
@@ -333,15 +332,3 @@ func TestValidateEventIds(t *testing.T) {
 
 	}
 }
-
-func TestDataTypes(t *testing.T) {
-	input := []interface{}{float64(100), float64(200)}
-
-	// Check only validatedIds type
-	validatedIds, _ := validateEventIds(input)
-	fmt.Printf("ValidatedIds type: %T\n", validatedIds)
-
-	// Or check only errorMessages type
-	_, errorMessages := validateEventIds(input)
-	fmt.Printf("ErrorMessages type: %T\n", errorMessages)
-}

From 037fe7f67c7b8eb12d772da5589c81ccf4cd3369 Mon Sep 17 00:00:00 2001
From: Michael Commey <michaelcommey@icloud.com>
Date: Fri, 6 Jun 2025 17:50:34 -0400
Subject: [PATCH 05/10] mend

---
 .../inputs/windows_event_log/wineventlog/utils.go  | 14 +++++---------
 .../windows_event_log/wineventlog/utils_test.go    |  6 +++---
 .../wineventlog/wineventlog_test.go                | 14 +++++++++-----
 translator/tocwconfig/totomlconfig/toTomlConfig.go |  2 +-
 .../windows_events/collect_list/collectlist.go     |  4 ++--
 .../collect_list/collectlist_test.go               |  4 ++--
 6 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/plugins/inputs/windows_event_log/wineventlog/utils.go b/plugins/inputs/windows_event_log/wineventlog/utils.go
index 08986e52e2..4c38d7cf2b 100644
--- a/plugins/inputs/windows_event_log/wineventlog/utils.go
+++ b/plugins/inputs/windows_event_log/wineventlog/utils.go
@@ -48,22 +48,18 @@ func createFilterQuery(levels []string, eventIDs []int) string {
 	//query results
 	var query string
 	if filterLevels != "" && filterEventID != "" {
-		query = filterLevels + " and " + filterEventID
+		query = "(" + filterLevels + ") and (" + filterEventID + ")"
 	} else if filterLevels != "" && filterEventID == "" {
-		query = filterLevels
+		query = "(" + filterLevels + ")"
 	} else if filterLevels == "" && filterEventID != "" {
-		query = filterEventID
+		query = "(" + filterEventID + ")"
 	}
 
 	//Ignore events older than 2 weeks
 	cutOffPeriod := (time.Hour * 24 * 14).Nanoseconds()
 	ignoreOlderThanTwoWeeksFilter := fmt.Sprintf(eventIgnoreOldFilter, cutOffPeriod/int64(time.Millisecond))
-	if filterLevels != "" && filterEventID != "" {
-		query = "*[System[(" + query + ") and " + ignoreOlderThanTwoWeeksFilter + "]]"
-	} else if filterLevels != "" {
-		query = "*[System[(" + filterLevels + ") and " + ignoreOlderThanTwoWeeksFilter + "]]"
-	} else if filterEventID != "" {
-		query = "*[System[(" + filterEventID + ") and " + ignoreOlderThanTwoWeeksFilter + "]]"
+	if query != "" {
+		query = "*[System[" + query + " and " + ignoreOlderThanTwoWeeksFilter + "]]"
 	} else {
 		query = "*[System[" + ignoreOlderThanTwoWeeksFilter + "]]"
 	}
diff --git a/plugins/inputs/windows_event_log/wineventlog/utils_test.go b/plugins/inputs/windows_event_log/wineventlog/utils_test.go
index 8c768bd1cf..89cb25de82 100644
--- a/plugins/inputs/windows_event_log/wineventlog/utils_test.go
+++ b/plugins/inputs/windows_event_log/wineventlog/utils_test.go
@@ -30,9 +30,9 @@ func TestCreateFilterQuery(t *testing.T) {
 		},
 		{
 			name:     "levels_EventID_Test",
-			levels:   []string{"Error"},
-			eventIDs: []int{4625},
-			want:     "*[System[(Level='Error' and EventID='4625') and TimeCreated[timediff(@SystemTime) &lt;= 1209600000]]]",
+			levels:   []string{"Error", "Critical"},
+			eventIDs: []int{4625, 4624},
+			want:     "*[System[(Level='Error' or Level='Critical') and (EventID='4625' or EventID='4624') and TimeCreated[timediff(@SystemTime) &lt;= 1209600000]]]",
 		},
 		{
 			name:     "no_Input",
diff --git a/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go b/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go
index c5c5519679..478ccbc097 100644
--- a/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go
+++ b/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go
@@ -21,7 +21,7 @@ var (
 	NAME = "Application"
 	// 2 is ERROR
 	LEVELS          = []string{"2"}
-	EVENTID         = []int{100, 101}
+	EVENTID         = []int{777}
 	GROUP_NAME      = "fake"
 	STREAM_NAME     = "fake"
 	RENDER_FMT      = FormatPlainText
@@ -142,18 +142,22 @@ func seekToEnd(t *testing.T, elog *windowsEventLog) {
 // Fail the test if an error occurs.
 func writeEvents(t *testing.T, msgCount int, doRegister bool, logSrc string, eventId uint32) {
 	if doRegister {
-		// Expected to fail if unit test previously ran and installed the event src.
-		_ = eventlog.InstallAsEventCreate(logSrc, eventlog.Info|eventlog.Warning|eventlog.Error)
+		err := eventlog.InstallAsEventCreate(logSrc, eventlog.Info|eventlog.Warning|eventlog.Error)
+		if err != nil {
+			t.Logf("Warning: Failed to install event source %s: %v (may need admin privileges)", logSrc, err)
+			// Continue anyway as it might already be registered
+		}
 	}
 	wlog, err := eventlog.Open(logSrc)
 	assert.NoError(t, err)
 	for i := 0; i < msgCount; i++ {
-		wlog.Error(eventId, fmt.Sprintf("CWA_UnitTest event msg %v", i))
+		err = wlog.Error(eventId, fmt.Sprintf("CWA_UnitTest event msg %v", i))
+		assert.NoError(t, err)
 	}
 	err = wlog.Close()
 	assert.NoError(t, err)
 	// Must sleep after wlog.Error() otherwise elog.read() will not see results.
-	time.Sleep(1 * time.Second)
+	time.Sleep(3 * time.Second)
 }
 
 // readHelper reads all events (since last read).
diff --git a/translator/tocwconfig/totomlconfig/toTomlConfig.go b/translator/tocwconfig/totomlconfig/toTomlConfig.go
index c53fdb3e05..30324002ff 100755
--- a/translator/tocwconfig/totomlconfig/toTomlConfig.go
+++ b/translator/tocwconfig/totomlconfig/toTomlConfig.go
@@ -23,7 +23,7 @@ func ToTomlConfig(val interface{}) string {
 	return buf.String()
 }
 
-// Ensures integers in arrays are preserved
+// ensure integers in arrays are preserved
 func processValue(val interface{}) interface{} {
 	switch v := val.(type) {
 	case map[string]interface{}:
diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go
index 80f4bd9489..1c26caf893 100644
--- a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go
+++ b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go
@@ -130,8 +130,8 @@ func addFixedJsonConfig(result map[string]interface{}) {
 }
 
 // Validate event_id inputs
-func validateEventIds(inputEventIds []interface{}) ([]interface{}, []string) {
-	validatedIds := []interface{}{}
+func validateEventIds(inputEventIds []interface{}) ([]int, []string) {
+	validatedIds := []int{}
 	errorMessages := []string{}
 
 	const (
diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
index c19106370d..5a06f3780a 100644
--- a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
+++ b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
@@ -56,7 +56,7 @@ func TestApplyRule(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "System",
 			"event_levels":      []interface{}{"4", "0", "1"},
-			"event_ids":         []interface{}{100, 120, 300},
+			"event_ids":         []int{100, 120, 300},
 			"log_group_name":    "System",
 			"batch_read_size":   BatchReadSizeValue,
 			"retention_in_days": -1,
@@ -65,7 +65,7 @@ func TestApplyRule(t *testing.T) {
 		map[string]interface{}{
 			"event_name":        "Application",
 			"event_levels":      []interface{}{"4", "0", "5", "2"},
-			"event_ids":         []interface{}{4625, 3568},
+			"event_ids":         []int{4625, 3568},
 			"event_format":      "xml",
 			"log_group_name":    "Application",
 			"batch_read_size":   BatchReadSizeValue,

From 5dd88d63eaed5db666c6c8c95427d7072aff52c0 Mon Sep 17 00:00:00 2001
From: Michael Commey <137405771+Paamicky@users.noreply.github.com>
Date: Mon, 16 Jun 2025 21:20:25 -0400
Subject: [PATCH 06/10] update just for integ test

---
 .github/workflows/test-artifacts.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/test-artifacts.yml b/.github/workflows/test-artifacts.yml
index ab7a033f7a..1615b95ef0 100644
--- a/.github/workflows/test-artifacts.yml
+++ b/.github/workflows/test-artifacts.yml
@@ -487,7 +487,7 @@ jobs:
       - name: Terraform apply
         uses: nick-fields/retry@v2
         with:
-          max_attempts: 3
+          max_attempts: 1
           timeout_minutes: 60
           retry_wait_seconds: 5
           command: |
@@ -1319,4 +1319,4 @@ jobs:
             else
               cd terraform/eks/addon/gpu
             fi
-            terraform destroy -auto-approve
\ No newline at end of file
+            terraform destroy -auto-approve

From 2276ab2d1e761dd37b56a730180eea0d41af8ecf Mon Sep 17 00:00:00 2001
From: Michael Commey <michaelcommey@icloud.com>
Date: Fri, 20 Jun 2025 11:01:34 -0400
Subject: [PATCH 07/10] fix: resolve workflow lint issues

---
 .github/workflows/test-artifacts.yml          |  2 +-
 .../sampleConfig/windows_eventids.yaml        |  4 --
 .../windows_eventids_and_levels.yaml          |  4 --
 .../tomlConfigTemplate/tomlConfig.go          |  2 +-
 .../collect_list/collectlist.go               | 34 +++++++-------
 .../collect_list/collectlist_test.go          | 44 +++++++++----------
 6 files changed, 41 insertions(+), 49 deletions(-)

diff --git a/.github/workflows/test-artifacts.yml b/.github/workflows/test-artifacts.yml
index 1615b95ef0..819e055e22 100644
--- a/.github/workflows/test-artifacts.yml
+++ b/.github/workflows/test-artifacts.yml
@@ -487,7 +487,7 @@ jobs:
       - name: Terraform apply
         uses: nick-fields/retry@v2
         with:
-          max_attempts: 1
+          max_attempts: 3
           timeout_minutes: 60
           retry_wait_seconds: 5
           command: |
diff --git a/translator/tocwconfig/sampleConfig/windows_eventids.yaml b/translator/tocwconfig/sampleConfig/windows_eventids.yaml
index 558843bdd0..5647ec5a92 100644
--- a/translator/tocwconfig/sampleConfig/windows_eventids.yaml
+++ b/translator/tocwconfig/sampleConfig/windows_eventids.yaml
@@ -18,9 +18,6 @@ service:
                 - nop
     telemetry:
         logs:
-            development: false
-            disable_caller: false
-            disable_stacktrace: false
             encoding: console
             level: info
             output_paths:
@@ -31,7 +28,6 @@ service:
                 thereafter: 500
                 tick: 10s
         metrics:
-            address: ""
             level: None
         traces:
             level: None
diff --git a/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml
index 558843bdd0..5647ec5a92 100644
--- a/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml
+++ b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml
@@ -18,9 +18,6 @@ service:
                 - nop
     telemetry:
         logs:
-            development: false
-            disable_caller: false
-            disable_stacktrace: false
             encoding: console
             level: info
             output_paths:
@@ -31,7 +28,6 @@ service:
                 thereafter: 500
                 tick: 10s
         metrics:
-            address: ""
             level: None
         traces:
             level: None
diff --git a/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go b/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go
index db1f4859d9..eb4a511199 100644
--- a/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go
+++ b/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go
@@ -105,7 +105,7 @@ type (
 	eventConfig struct {
 		BatchReadSize   int      `toml:"batch_read_size"`
 		EventLevels     []string `toml:"event_levels"`
-		EventIds        []int    `toml:"event_ids"`
+		EventIDs        []int    `toml:"event_ids"`
 		EventName       string   `toml:"event_name"`
 		LogGroupName    string   `toml:"log_group_name"`
 		LogStreamName   string   `toml:"log_stream_name"`
diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go
index 1c26caf893..076b25bd3a 100644
--- a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go
+++ b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go
@@ -21,7 +21,7 @@ const (
 	EventConfigTomlKey = "event_config"
 	BatchReadSizeKey   = "batch_read_size"
 	EventLevelsKey     = "event_levels"
-	EventIdKey         = "event_ids"
+	EventIDKey         = "event_ids"
 	//TODO: Performance test to confirm the proper value here - https://github.com/aws/amazon-cloudwatch-agent/issues/231
 	BatchReadSizeValue = 170
 )
@@ -35,7 +35,7 @@ func RegisterRule(fieldname string, r Rule) {
 type CollectList struct {
 }
 
-var customizedJsonConfigKeys = []string{"event_name", EventLevelsKey, EventIdKey}
+var customizedJSONConfigKeys = []string{"event_name", EventLevelsKey, EventIDKey}
 var eventLevelMapping = map[string]string{
 	"VERBOSE":     "5",
 	"INFORMATION": "4",
@@ -78,7 +78,7 @@ func init() {
 func getTransformedConfig(input interface{}) interface{} {
 	result := map[string]interface{}{}
 	// Extract customer specified config
-	util.SetWithSameKeyIfFound(input, customizedJsonConfigKeys, result)
+	util.SetWithSameKeyIfFound(input, customizedJSONConfigKeys, result)
 	// Set Fixed config
 	addFixedJsonConfig(result)
 
@@ -120,40 +120,40 @@ func addFixedJsonConfig(result map[string]interface{}) {
 	}
 	result[EventLevelsKey] = resultEventLevels
 
-	if eventIds, ok := result[EventIdKey]; ok {
-		validatedIds, errorMessages := validateEventIds(eventIds.([]interface{}))
+	if eventIDs, ok := result[EventIDKey]; ok {
+		validatedIDs, errorMessages := validateEventIDs(eventIDs.([]interface{}))
 		for _, err := range errorMessages {
 			translator.AddErrorMessages(GetCurPath(), err)
 		}
-		result[EventIdKey] = validatedIds
+		result[EventIDKey] = validatedIDs
 	}
 }
 
 // Validate event_id inputs
-func validateEventIds(inputEventIds []interface{}) ([]int, []string) {
-	validatedIds := []int{}
+func validateEventIDs(inputEventIDs []interface{}) ([]int, []string) {
+	validatedIDs := []int{}
 	errorMessages := []string{}
 
 	const (
-		minEventId = 0
-		maxEventId = 65535
+		minEventID = 0
+		maxEventID = 65535
 	)
 
-	for _, id := range inputEventIds {
-		eventIdFloat, ok := id.(float64)
+	for _, id := range inputEventIDs {
+		eventIDFloat, ok := id.(float64)
 		if !ok {
 			errorMessages = append(errorMessages, fmt.Sprintf("Event ID %v is not a number", id))
 			continue
 		}
-		eventIdInt := int(eventIdFloat)
-		if eventIdInt < minEventId || eventIdInt > maxEventId {
-			errorMessages = append(errorMessages, fmt.Sprintf("Event ID %v is not a valid windows event_id.", eventIdInt))
+		eventIDInt := int(eventIDFloat)
+		if eventIDInt < minEventID || eventIDInt > maxEventID {
+			errorMessages = append(errorMessages, fmt.Sprintf("Event ID %v is not a valid windows event_id.", eventIDInt))
 			continue
 		}
 
-		validatedIds = append(validatedIds, eventIdInt)
+		validatedIDs = append(validatedIDs, eventIDInt)
 	}
 
-	return validatedIds, errorMessages
+	return validatedIDs, errorMessages
 
 }
diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
index 5a06f3780a..ef1ad893d0 100644
--- a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
+++ b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go
@@ -15,7 +15,7 @@ import (
 
 func TestApplyRule(t *testing.T) {
 	c := new(CollectList)
-	var rawJsonString = `
+	var rawJSONString = `
 {
     "collect_list": [
       {
@@ -76,7 +76,7 @@ func TestApplyRule(t *testing.T) {
 
 	var actual interface{}
 
-	err := json.Unmarshal([]byte(rawJsonString), &input)
+	err := json.Unmarshal([]byte(rawJSONString), &input)
 	if err == nil {
 		_, actual = c.ApplyRule(input)
 		assert.Equal(t, expected, actual)
@@ -87,7 +87,7 @@ func TestApplyRule(t *testing.T) {
 
 func TestDuplicateRetention(t *testing.T) {
 	c := new(CollectList)
-	var rawJsonString = `
+	var rawJSONString = `
 {
     "collect_list": [
       {
@@ -175,19 +175,19 @@ func TestDuplicateRetention(t *testing.T) {
 
 	var actual interface{}
 
-	error := json.Unmarshal([]byte(rawJsonString), &input)
-	if error == nil {
+	err := json.Unmarshal([]byte(rawJSONString), &input)
+	if err == nil {
 		_, actual = c.ApplyRule(input)
 		assert.Equal(t, 0, len(translator.ErrorMessages))
 		assert.Equal(t, expected, actual)
 	} else {
-		assert.Fail(t, error.Error())
+		assert.Fail(t, err.Error())
 	}
 }
 
 func TestConflictingRetention(t *testing.T) {
 	c := new(CollectList)
-	var rawJsonString = `
+	var rawJSONString = `
 {
     "collect_list": [
       {
@@ -247,20 +247,20 @@ func TestConflictingRetention(t *testing.T) {
 
 	var actual interface{}
 
-	error := json.Unmarshal([]byte(rawJsonString), &input)
-	if error == nil {
+	err := json.Unmarshal([]byte(rawJSONString), &input)
+	if err == nil {
 		_, actual = c.ApplyRule(input)
 		assert.GreaterOrEqual(t, 1, len(translator.ErrorMessages))
 		assert.Equal(t, "Under path : /logs/logs_collected/windows_events/collect_list/ | Error : Different retention_in_days values can't be set for the same log group: system", translator.ErrorMessages[len(translator.ErrorMessages)-1])
 		assert.Equal(t, expected, actual)
 	} else {
-		assert.Fail(t, error.Error())
+		assert.Fail(t, err.Error())
 	}
 }
 
 func TestEventID(t *testing.T) {
 	//Inputs
-	rawJsonString := `{
+	rawJSONString := `{
         "collect_list": [{
             "event_name": "System",
             "event_ids": [100, 101, 102],
@@ -269,7 +269,7 @@ func TestEventID(t *testing.T) {
     }`
 
 	var config interface{}
-	err := json.Unmarshal([]byte(rawJsonString), &config)
+	err := json.Unmarshal([]byte(rawJSONString), &config)
 	assert.NoError(t, err)
 
 	//process new configutation
@@ -279,54 +279,54 @@ func TestEventID(t *testing.T) {
 	// Verify event_ids in final configuration
 	result := val.([]interface{})[0].(map[string]interface{})
 
-	eventIds, exists := result["event_ids"]
+	eventIDs, exists := result["event_ids"]
 	assert.True(t, exists, "event_ids should exist in final configuration")
-	assert.Equal(t, []int{100, 101, 102}, eventIds)
+	assert.Equal(t, []int{100, 101, 102}, eventIDs)
 
 }
 
-func TestValidateEventIds(t *testing.T) {
+func TestValidateEventIDs(t *testing.T) {
 	test := []struct {
 		name        string
 		input       []interface{}
-		expectedIds []int
+		expectedIDs []int
 		expectError bool
 	}{
 		{
 			name:        "Valid event IDs",
 			input:       []interface{}{float64(100), float64(200), float64(300)},
-			expectedIds: []int{100, 200, 300},
+			expectedIDs: []int{100, 200, 300},
 			expectError: false,
 		},
 		{
 			name:        "Invalid event ID - UpperBound",
 			input:       []interface{}{float64(65536)},
-			expectedIds: []int{},
+			expectedIDs: []int{},
 			expectError: true,
 		},
 		{
 			name:        "Invalid event ID - LowerBound",
 			input:       []interface{}{float64(-1)},
-			expectedIds: []int{},
+			expectedIDs: []int{},
 			expectError: true,
 		},
 		{
 			name:        "Empty input",
 			input:       []interface{}{},
-			expectedIds: []int{},
+			expectedIDs: []int{},
 			expectError: false,
 		},
 	}
 
 	for _, tt := range test {
 		t.Run(tt.name, func(t *testing.T) {
-			validatedIds, errorMessages := validateEventIds(tt.input)
+			validatedIDs, errorMessages := validateEventIDs(tt.input)
 
 			if !tt.expectError && len(errorMessages) > 0 {
 				t.Errorf("Unexpected error messages: %v", errorMessages)
 			}
 			// Check if validated IDs match expected
-			assert.Equal(t, tt.expectedIds, validatedIds)
+			assert.Equal(t, tt.expectedIDs, validatedIDs)
 
 		})
 

From 90f466e54c8d57098751b828a58ee409fa494a2b Mon Sep 17 00:00:00 2001
From: Michael Commey <michaelcommey@icloud.com>
Date: Fri, 11 Jul 2025 10:25:15 -0400
Subject: [PATCH 08/10] changed cutoffPeriod to const

---
 plugins/inputs/windows_event_log/wineventlog/utils.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/plugins/inputs/windows_event_log/wineventlog/utils.go b/plugins/inputs/windows_event_log/wineventlog/utils.go
index 716b5eaf26..d3d987e652 100644
--- a/plugins/inputs/windows_event_log/wineventlog/utils.go
+++ b/plugins/inputs/windows_event_log/wineventlog/utils.go
@@ -16,6 +16,7 @@ const (
 	eventIgnoreOldFilter     = "TimeCreated[timediff(@SystemTime) &lt;= %d]"
 	emptySpaceScanLength     = 100
 	UnknownBytesPerCharacter = 0
+	cutOffPeriod             = time.Hour * 24 * 14
 
 	CRITICAL    = "CRITICAL"
 	ERROR       = "ERROR"
@@ -56,8 +57,7 @@ func createFilterQuery(levels []string, eventIDs []int) string {
 	}
 
 	//Ignore events older than 2 weeks
-	cutOffPeriod := (time.Hour * 24 * 14).Nanoseconds()
-	ignoreOlderThanTwoWeeksFilter := fmt.Sprintf(eventIgnoreOldFilter, cutOffPeriod/int64(time.Millisecond))
+	ignoreOlderThanTwoWeeksFilter := fmt.Sprintf(eventIgnoreOldFilter, cutOffPeriod.Milliseconds())
 	if query != "" {
 		query = "*[System[" + query + " and " + ignoreOlderThanTwoWeeksFilter + "]]"
 	} else {

From 10f9f0a1eefd6667776031d7d49d4c7c64f90492 Mon Sep 17 00:00:00 2001
From: Michael Commey <michaelcommey@icloud.com>
Date: Fri, 11 Jul 2025 11:36:29 -0400
Subject: [PATCH 09/10] Add eventid check to the Agent TOML

---
 plugins/inputs/windows_event_log/wineventlog/wineventlog.go | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/plugins/inputs/windows_event_log/wineventlog/wineventlog.go b/plugins/inputs/windows_event_log/wineventlog/wineventlog.go
index 39f1e7f122..eda9a05eff 100644
--- a/plugins/inputs/windows_event_log/wineventlog/wineventlog.go
+++ b/plugins/inputs/windows_event_log/wineventlog/wineventlog.go
@@ -88,6 +88,12 @@ func NewEventLog(name string, levels []string, eventIDs []int, logGroupName, log
 }
 
 func (w *windowsEventLog) Init() error {
+	for _, eventID := range w.eventIDs {
+		if eventID < 0 || eventID > 65535 {
+			return fmt.Errorf("invalid event ID: %d, event IDs must be between 0 and 65535", eventID)
+		}
+	}
+
 	go w.stateManager.Run(state.Notification{Done: w.done})
 	restored, _ := w.stateManager.Restore()
 	w.eventOffset = restored.Last().EndOffset()

From 99b2d6387389c424174b313f1781a34d3b542589 Mon Sep 17 00:00:00 2001
From: Michael Commey <michaelcommey@icloud.com>
Date: Fri, 18 Jul 2025 12:25:47 -0400
Subject: [PATCH 10/10] "Address PR comments"

---
 .github/workflows/test-artifacts.yml                     | 2 +-
 .../inputs/windows_event_log/wineventlog/wineventlog.go  | 9 +++++++--
 .../logs_collected/windows_events/windows_event_test.go  | 2 +-
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/test-artifacts.yml b/.github/workflows/test-artifacts.yml
index e6c78697a0..9fe2463aa5 100644
--- a/.github/workflows/test-artifacts.yml
+++ b/.github/workflows/test-artifacts.yml
@@ -1361,4 +1361,4 @@ jobs:
             else
               cd terraform/eks/addon/gpu
             fi
-            terraform destroy -auto-approve
+            terraform destroy -auto-approve
\ No newline at end of file
diff --git a/plugins/inputs/windows_event_log/wineventlog/wineventlog.go b/plugins/inputs/windows_event_log/wineventlog/wineventlog.go
index 0fd1d76428..23808b7aa8 100644
--- a/plugins/inputs/windows_event_log/wineventlog/wineventlog.go
+++ b/plugins/inputs/windows_event_log/wineventlog/wineventlog.go
@@ -94,9 +94,14 @@ func NewEventLog(name string, levels []string, eventIDs []int, logGroupName, log
 }
 
 func (w *windowsEventLog) Init() error {
+	const (
+		minEventID = 0
+		maxEventID = 65535
+	)
+
 	for _, eventID := range w.eventIDs {
-		if eventID < 0 || eventID > 65535 {
-			return fmt.Errorf("invalid event ID: %d, event IDs must be between 0 and 65535", eventID)
+		if eventID < minEventID || eventID > maxEventID {
+			return fmt.Errorf("invalid event ID: %d, event IDs must be between %d and %d", eventID, minEventID, maxEventID)
 		}
 	}
 
diff --git a/translator/translate/logs/logs_collected/windows_events/windows_event_test.go b/translator/translate/logs/logs_collected/windows_events/windows_event_test.go
index d6ca4352d7..fd8090eaac 100644
--- a/translator/translate/logs/logs_collected/windows_events/windows_event_test.go
+++ b/translator/translate/logs/logs_collected/windows_events/windows_event_test.go
@@ -27,7 +27,7 @@ func TestApplyRule(t *testing.T) {
             ],
             "event_ids": [
                456,
-	           300
+               300
             ],
             "log_group_name": "System",
             "log_stream_name": "System"