[EVTLIB] Do not preallocate event logs to MaxSize (#9071)

Keep the configured event log `MaxSize` as a capacity limit and track the
physical file size separately.

New logs now start at the Windows 64 KiB file-size granularity, instead of
growing immediately to the full configured maximum. They are then grown in
64 KiB chunks as records are written, while preserving the logical used area
in the header offsets and EOF record.
This commit is contained in:
Ahmed Arif
2026-06-28 20:14:56 +02:00
committed by GitHub
parent 1b91127bbe
commit 24e904e095
+37 -10
View File
@@ -23,6 +23,8 @@
/* GLOBALS *******************************************************************/
#define EVENTLOG_FILE_GRANULARITY (64 * 1024)
static const EVENTLOGEOF EOFRecord =
{
sizeof(EOFRecord),
@@ -304,6 +306,7 @@ ElfpInitNewFile(
LARGE_INTEGER FileOffset;
SIZE_T WrittenLength;
EVENTLOGEOF EofRec;
ULONG InitialSize;
/* Initialize the event log header */
RtlZeroMemory(&LogFile->Header, sizeof(EVENTLOGHEADER));
@@ -322,13 +325,23 @@ ElfpInitNewFile(
/* The event log is empty, there is no record so far */
LogFile->Header.OldestRecordNumber = 0;
// FIXME: Windows' EventLog log file sizes are always multiple of 64kB
// but that does not mean the real log size is == file size.
/*
* Windows keeps the file size in 64 kB chunks. The used log area is tracked
* by the header offsets and the EOF record, not by the physical file EOF.
*/
InitialSize = sizeof(EVENTLOGHEADER) + sizeof(EVENTLOGEOF); // TODO: Consider FileSize as well.
InitialSize = ROUND_UP(InitialSize, EVENTLOG_FILE_GRANULARITY);
LogFile->CurrentSize = InitialSize;
Status = LogFile->FileSetSize(LogFile, LogFile->CurrentSize, FileSize);
if (!NT_SUCCESS(Status))
{
EVTLTRACE1("FileSetSize() failed (Status 0x%08lx)\n", Status);
return Status;
}
/* Round MaxSize to be a multiple of ULONG (normally on Windows: multiple of 64 kB) */
LogFile->Header.MaxSize = ROUND_UP(MaxSize, sizeof(ULONG));
LogFile->CurrentSize = LogFile->Header.MaxSize; // or: FileSize ??
LogFile->FileSetSize(LogFile, LogFile->CurrentSize, 0);
/* Ensure that the log maximum size is greater than the initial file size */
MaxSize = max(MaxSize, InitialSize);
LogFile->Header.MaxSize = ROUND_UP(MaxSize, EVENTLOG_FILE_GRANULARITY);
LogFile->Header.Flags = 0;
LogFile->Header.Retention = Retention;
@@ -1488,11 +1501,25 @@ ElfWriteRecord(
*/
if (LogFile->CurrentSize < LogFile->Header.MaxSize)
{
EVTLTRACE1("Expanding the log file from %lu to %lu\n",
LogFile->CurrentSize, LogFile->Header.MaxSize);
ULONG NewSize = WriteOffset + BufSize + sizeof(EofRec);
LogFile->CurrentSize = LogFile->Header.MaxSize;
LogFile->FileSetSize(LogFile, LogFile->CurrentSize, 0);
if (WriteOffset < LogFile->Header.EndOffset || NewSize > LogFile->Header.MaxSize)
NewSize = LogFile->Header.MaxSize;
else
NewSize = ROUND_UP(NewSize, EVENTLOG_FILE_GRANULARITY);
if (NewSize > LogFile->CurrentSize)
{
EVTLTRACE1("Expanding the log file from %lu to %lu\n",
LogFile->CurrentSize, NewSize);
Status = LogFile->FileSetSize(LogFile, NewSize, LogFile->CurrentSize);
if (!NT_SUCCESS(Status))
{
EVTLTRACE1("FileSetSize() failed (Status 0x%08lx)\n", Status);
return Status;
}
LogFile->CurrentSize = NewSize;
}
}
/* Since we can write events in the log, clear the log full flag */