/*
- * PROJECT: ReactOS kernel
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: services/eventlog/file.c
- * PURPOSE: Event logging service
- * COPYRIGHT: Copyright 2005 Saveliy Tretiakov
- Michael Martin
+ * PROJECT: ReactOS EventLog Service
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/services/eventlog/file.c
+ * PURPOSE: Event log file support wrappers
+ * COPYRIGHT: Copyright 2005 Saveliy Tretiakov
+ * Michael Martin
+ * Hermes Belusca-Maito
*/
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
#include "eventlog.h"
-
#include <ndk/iofuncs.h>
+#include <ndk/kefuncs.h>
#define NDEBUG
#include <debug.h>
-/* GLOBALS ******************************************************************/
+/* LOG FILE LIST - GLOBALS ***************************************************/
static LIST_ENTRY LogFileListHead;
static CRITICAL_SECTION LogFileListCs;
-/* FUNCTIONS ****************************************************************/
-
-static NTSTATUS
-LogfInitializeNew(PLOGFILE LogFile)
-{
- DWORD dwWritten;
- EVENTLOGEOF EofRec;
-
- ZeroMemory(&LogFile->Header, sizeof(EVENTLOGHEADER));
- SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN);
- SetEndOfFile(LogFile->hFile);
-
- LogFile->Header.HeaderSize = sizeof(EVENTLOGHEADER);
- LogFile->Header.EndHeaderSize = sizeof(EVENTLOGHEADER);
- LogFile->Header.StartOffset = sizeof(EVENTLOGHEADER);
- LogFile->Header.EndOffset = sizeof(EVENTLOGHEADER);
- LogFile->Header.MajorVersion = MAJORVER;
- LogFile->Header.MinorVersion = MINORVER;
- LogFile->Header.CurrentRecordNumber = 1;
- LogFile->Header.OldestRecordNumber = 1;
- /* FIXME: Read MaxSize from registry for this LogFile.
- But for now limit EventLog size to just under 5K. */
- LogFile->Header.MaxSize = 5000;
- LogFile->Header.Signature = LOGFILE_SIGNATURE;
- if (!WriteFile(LogFile->hFile,
- &LogFile->Header,
- sizeof(EVENTLOGHEADER),
- &dwWritten,
- NULL))
- {
- DPRINT1("WriteFile failed:%d!\n", GetLastError());
- return STATUS_UNSUCCESSFUL;
- }
-
- EofRec.Ones = 0x11111111;
- EofRec.Twos = 0x22222222;
- EofRec.Threes = 0x33333333;
- EofRec.Fours = 0x44444444;
- EofRec.RecordSizeBeginning = sizeof(EVENTLOGEOF);
- EofRec.RecordSizeEnd = sizeof(EVENTLOGEOF);
- EofRec.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
- EofRec.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
- EofRec.BeginRecord = LogFile->Header.StartOffset;
- EofRec.EndRecord = LogFile->Header.EndOffset;
-
- if (!WriteFile(LogFile->hFile,
- &EofRec,
- sizeof(EVENTLOGEOF),
- &dwWritten,
- NULL))
- {
- DPRINT1("WriteFile failed:%d!\n", GetLastError());
- return STATUS_UNSUCCESSFUL;
- }
-
- if (!FlushFileBuffers(LogFile->hFile))
- {
- DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
- return STATUS_UNSUCCESSFUL;
- }
-
- return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS
-LogfInitializeExisting(PLOGFILE LogFile, BOOL Backup)
-{
- DWORD dwRead;
- DWORD dwRecordsNumber = 0;
- DWORD dwRecSize, dwRecSign, dwFilePointer;
- PDWORD pdwRecSize2;
- PEVENTLOGRECORD RecBuf;
- BOOL OvewrWrittenRecords = FALSE;
-
- DPRINT("Initializing LogFile %S\n",LogFile->LogName);
-
- if (SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
- INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer failed! %d\n", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (!ReadFile(LogFile->hFile,
- &LogFile->Header,
- sizeof(EVENTLOGHEADER),
- &dwRead,
- NULL))
- {
- DPRINT1("ReadFile failed! %d\n", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (dwRead != sizeof(EVENTLOGHEADER))
- {
- DPRINT("EventLog: Invalid file %S.\n", LogFile->FileName);
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (LogFile->Header.HeaderSize != sizeof(EVENTLOGHEADER) ||
- LogFile->Header.EndHeaderSize != sizeof(EVENTLOGHEADER))
- {
- DPRINT("EventLog: Invalid header size in %S.\n", LogFile->FileName);
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (LogFile->Header.Signature != LOGFILE_SIGNATURE)
- {
- DPRINT("EventLog: Invalid signature %x in %S.\n",
- LogFile->Header.Signature, LogFile->FileName);
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (LogFile->Header.EndOffset > GetFileSize(LogFile->hFile, NULL) + 1)
- {
- DPRINT("EventLog: Invalid eof offset %x in %S.\n",
- LogFile->Header.EndOffset, LogFile->FileName);
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- /* Set the read location to the oldest record */
- dwFilePointer = SetFilePointer(LogFile->hFile, LogFile->Header.StartOffset, NULL, FILE_BEGIN);
- if (dwFilePointer == INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer failed! %d\n", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- for (;;)
- {
- dwFilePointer = SetFilePointer(LogFile->hFile, 0, NULL, FILE_CURRENT);
-
- if (dwFilePointer == INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer failed! %d\n", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- /* If the EVENTLOGEOF info has been reached and the oldest record was not immediately after the Header */
- if ((dwFilePointer == LogFile->Header.EndOffset) && (LogFile->Header.StartOffset != sizeof(EVENTLOGHEADER)))
- {
- OvewrWrittenRecords = TRUE;
- /* The file has records that overwrote old ones so read them */
- dwFilePointer = SetFilePointer(LogFile->hFile, sizeof(EVENTLOGHEADER), NULL, FILE_BEGIN);
- }
-
- if (!ReadFile(LogFile->hFile,
- &dwRecSize,
- sizeof(dwRecSize),
- &dwRead,
- NULL))
- {
- DPRINT1("ReadFile failed! %d\n", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (dwRead != sizeof(dwRecSize))
- break;
-
- if (!ReadFile(LogFile->hFile,
- &dwRecSign,
- sizeof(dwRecSign),
- &dwRead,
- NULL))
- {
- DPRINT1("ReadFile() failed! %d\n", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (dwRead != sizeof(dwRecSize))
- break;
-
- if (dwRecSign != LOGFILE_SIGNATURE ||
- dwRecSize + dwFilePointer > GetFileSize(LogFile->hFile, NULL) + 1 ||
- dwRecSize < sizeof(EVENTLOGRECORD))
- {
- break;
- }
-
- if (SetFilePointer(LogFile->hFile,
- -((LONG) sizeof(DWORD) * 2),
- NULL,
- FILE_CURRENT) == INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed! %d", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- RecBuf = (PEVENTLOGRECORD) HeapAlloc(MyHeap, 0, dwRecSize);
- if (RecBuf == NULL)
- {
- DPRINT1("Can't allocate heap!\n");
- return STATUS_NO_MEMORY;
- }
-
- if (!ReadFile(LogFile->hFile, RecBuf, dwRecSize, &dwRead, NULL))
- {
- DPRINT1("ReadFile() failed! %d\n", GetLastError());
- HeapFree(MyHeap, 0, RecBuf);
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (dwRead != dwRecSize)
- {
- HeapFree(MyHeap, 0, RecBuf);
- break;
- }
-
- /* if OvewrWrittenRecords is TRUE and this record has already been read */
- if ((OvewrWrittenRecords == TRUE) && (RecBuf->RecordNumber == LogFile->Header.OldestRecordNumber))
- {
- HeapFree(MyHeap, 0, RecBuf);
- break;
- }
-
- pdwRecSize2 = (PDWORD) (((PBYTE) RecBuf) + dwRecSize - 4);
-
- if (*pdwRecSize2 != dwRecSize)
- {
- DPRINT1("Invalid RecordSizeEnd of record %d (%x) in %S\n",
- dwRecordsNumber, *pdwRecSize2, LogFile->LogName);
- HeapFree(MyHeap, 0, RecBuf);
- break;
- }
-
- dwRecordsNumber++;
-
- if (!LogfAddOffsetInformation(LogFile,
- RecBuf->RecordNumber,
- dwFilePointer))
- {
- DPRINT1("LogfAddOffsetInformation() failed!\n");
- HeapFree(MyHeap, 0, RecBuf);
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- HeapFree(MyHeap, 0, RecBuf);
- }
-
- LogFile->Header.CurrentRecordNumber = dwRecordsNumber + LogFile->Header.OldestRecordNumber;
- if (LogFile->Header.CurrentRecordNumber == 0)
- LogFile->Header.CurrentRecordNumber = 1;
-
- /* FIXME: Read MaxSize from registry for this LogFile.
- But for now limit EventLog size to just under 5K. */
- LogFile->Header.MaxSize = 5000;
-
- if (!Backup)
- {
- if (SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
- INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (!WriteFile(LogFile->hFile,
- &LogFile->Header,
- sizeof(EVENTLOGHEADER),
- &dwRead,
- NULL))
- {
- DPRINT1("WriteFile failed! %d\n", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
-
- if (!FlushFileBuffers(LogFile->hFile))
- {
- DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
- return STATUS_EVENTLOG_FILE_CORRUPT;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-LogfCreate(PLOGFILE *LogFile,
- WCHAR * LogName,
- PUNICODE_STRING FileName,
- BOOL Permanent,
- BOOL Backup)
-{
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- PLOGFILE pLogFile;
- BOOL bCreateNew = FALSE;
- NTSTATUS Status = STATUS_SUCCESS;
-
- pLogFile = (LOGFILE *) HeapAlloc(MyHeap, HEAP_ZERO_MEMORY, sizeof(LOGFILE));
- if (!pLogFile)
- {
- DPRINT1("Can't allocate heap!\n");
- return STATUS_NO_MEMORY;
- }
-
- InitializeObjectAttributes(&ObjectAttributes,
- FileName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtCreateFile(&pLogFile->hFile,
- Backup ? (GENERIC_READ | SYNCHRONIZE) : (GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE),
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- FILE_SHARE_READ,
- Backup ? FILE_OPEN : FILE_OPEN_IF,
- FILE_SYNCHRONOUS_IO_NONALERT,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Can't create file %wZ (Status: 0x%08lx)\n", FileName, Status);
- goto fail;
- }
-
- bCreateNew = (IoStatusBlock.Information == FILE_CREATED) ? TRUE: FALSE;
-
- pLogFile->LogName =
- (WCHAR *) HeapAlloc(MyHeap,
- HEAP_ZERO_MEMORY,
- (lstrlenW(LogName) + 1) * sizeof(WCHAR));
- if (pLogFile->LogName == NULL)
- {
- DPRINT1("Can't allocate heap\n");
- Status = STATUS_NO_MEMORY;
- goto fail;
- }
-
- lstrcpyW(pLogFile->LogName, LogName);
-
- pLogFile->FileName =
- (WCHAR *) HeapAlloc(MyHeap,
- HEAP_ZERO_MEMORY,
- (lstrlenW(FileName->Buffer) + 1) * sizeof(WCHAR));
- if (pLogFile->FileName == NULL)
- {
- DPRINT1("Can't allocate heap\n");
- Status = STATUS_NO_MEMORY;
- goto fail;
- }
-
- lstrcpyW(pLogFile->FileName, FileName->Buffer);
-
- pLogFile->OffsetInfo =
- (PEVENT_OFFSET_INFO) HeapAlloc(MyHeap,
- HEAP_ZERO_MEMORY,
- sizeof(EVENT_OFFSET_INFO) * 64);
- if (pLogFile->OffsetInfo == NULL)
- {
- DPRINT1("Can't allocate heap\n");
- Status = STATUS_NO_MEMORY;
- goto fail;
- }
-
- pLogFile->OffsetInfoSize = 64;
-
- pLogFile->Permanent = Permanent;
-
- if (bCreateNew)
- Status = LogfInitializeNew(pLogFile);
- else
- Status = LogfInitializeExisting(pLogFile, Backup);
-
- if (!NT_SUCCESS(Status))
- goto fail;
-
- RtlInitializeResource(&pLogFile->Lock);
-
- LogfListAddItem(pLogFile);
-
- fail:
- if (!NT_SUCCESS(Status))
- {
- if ((pLogFile->hFile != NULL) && (pLogFile->hFile != INVALID_HANDLE_VALUE))
- CloseHandle(pLogFile->hFile);
-
- if (pLogFile->OffsetInfo)
- HeapFree(MyHeap, 0, pLogFile->OffsetInfo);
-
- if (pLogFile->FileName)
- HeapFree(MyHeap, 0, pLogFile->FileName);
-
- if (pLogFile->LogName)
- HeapFree(MyHeap, 0, pLogFile->LogName);
-
- HeapFree(MyHeap, 0, pLogFile);
- }
- else
- {
- *LogFile = pLogFile;
- }
-
- return Status;
-}
-
-
-VOID
-LogfClose(PLOGFILE LogFile,
- BOOL ForceClose)
-{
- if (LogFile == NULL)
- return;
-
- if ((ForceClose == FALSE) &&
- (LogFile->Permanent == TRUE))
- return;
-
- RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
-
- FlushFileBuffers(LogFile->hFile);
- CloseHandle(LogFile->hFile);
- LogfListRemoveItem(LogFile);
-
- RtlDeleteResource(&LogFile->Lock);
-
- HeapFree(MyHeap, 0, LogFile->LogName);
- HeapFree(MyHeap, 0, LogFile->FileName);
- HeapFree(MyHeap, 0, LogFile->OffsetInfo);
- HeapFree(MyHeap, 0, LogFile);
-
- return;
-}
-
-VOID LogfCloseAll(VOID)
-{
- while (!IsListEmpty(&LogFileListHead))
- {
- LogfClose(LogfListHead(), TRUE);
- }
-
- DeleteCriticalSection(&LogFileListCs);
-}
+/* LOG FILE LIST - FUNCTIONS *************************************************/
VOID LogfListInitialize(VOID)
{
InitializeListHead(&LogFileListHead);
}
-PLOGFILE LogfListHead(VOID)
-{
- return CONTAINING_RECORD(LogFileListHead.Flink, LOGFILE, ListEntry);
-}
-
-PLOGFILE LogfListItemByName(WCHAR * Name)
+PLOGFILE LogfListItemByName(LPCWSTR Name)
{
PLIST_ENTRY CurrentEntry;
- PLOGFILE Result = NULL;
+ PLOGFILE Item, Result = NULL;
+
+ ASSERT(Name);
EnterCriticalSection(&LogFileListCs);
CurrentEntry = LogFileListHead.Flink;
while (CurrentEntry != &LogFileListHead)
{
- PLOGFILE Item = CONTAINING_RECORD(CurrentEntry,
- LOGFILE,
- ListEntry);
+ Item = CONTAINING_RECORD(CurrentEntry, LOGFILE, ListEntry);
- if (Item->LogName && !lstrcmpi(Item->LogName, Name))
+ if (Item->LogName && !_wcsicmp(Item->LogName, Name))
{
Result = Item;
break;
return Result;
}
+#if 0
/* Index starting from 1 */
-INT LogfListItemIndexByName(WCHAR * Name)
+DWORD LogfListItemIndexByName(LPCWSTR Name)
{
PLIST_ENTRY CurrentEntry;
- INT Result = 0;
- INT i = 1;
+ DWORD Result = 0;
+ DWORD i = 1;
+
+ ASSERT(Name);
EnterCriticalSection(&LogFileListCs);
CurrentEntry = LogFileListHead.Flink;
while (CurrentEntry != &LogFileListHead)
{
- PLOGFILE Item = CONTAINING_RECORD(CurrentEntry,
- LOGFILE,
- ListEntry);
+ PLOGFILE Item = CONTAINING_RECORD(CurrentEntry, LOGFILE, ListEntry);
- if (Item->LogName && !lstrcmpi(Item->LogName, Name))
+ if (Item->LogName && !_wcsicmp(Item->LogName, Name))
{
Result = i;
break;
LeaveCriticalSection(&LogFileListCs);
return Result;
}
+#endif
/* Index starting from 1 */
-PLOGFILE LogfListItemByIndex(INT Index)
+PLOGFILE LogfListItemByIndex(DWORD Index)
{
PLIST_ENTRY CurrentEntry;
PLOGFILE Result = NULL;
- INT i = 1;
+ DWORD i = 1;
EnterCriticalSection(&LogFileListCs);
return Result;
}
-INT LogfListItemCount(VOID)
+DWORD LogfListItemCount(VOID)
{
PLIST_ENTRY CurrentEntry;
- INT i = 0;
+ DWORD i = 0;
EnterCriticalSection(&LogFileListCs);
return i;
}
-VOID LogfListAddItem(PLOGFILE Item)
+static VOID
+LogfListAddItem(PLOGFILE Item)
{
EnterCriticalSection(&LogFileListCs);
InsertTailList(&LogFileListHead, &Item->ListEntry);
LeaveCriticalSection(&LogFileListCs);
}
-VOID LogfListRemoveItem(PLOGFILE Item)
+static VOID
+LogfListRemoveItem(PLOGFILE Item)
{
EnterCriticalSection(&LogFileListCs);
RemoveEntryList(&Item->ListEntry);
LeaveCriticalSection(&LogFileListCs);
}
-static BOOL
-ReadAnsiLogEntry(HANDLE hFile,
- LPVOID lpBuffer,
- DWORD nNumberOfBytesToRead,
- LPDWORD lpNumberOfBytesRead)
-{
- PEVENTLOGRECORD Dst;
- PEVENTLOGRECORD Src;
- ANSI_STRING StringA;
- UNICODE_STRING StringW;
- LPWSTR SrcPtr;
- LPSTR DstPtr;
- LPWSTR SrcString;
- LPSTR DstString;
- LPVOID lpUnicodeBuffer = NULL;
- DWORD dwRead = 0;
- DWORD i;
- DWORD dwPadding;
- DWORD dwEntryLength;
- PDWORD pLength;
- NTSTATUS Status;
- BOOL ret = TRUE;
-
- *lpNumberOfBytesRead = 0;
-
- lpUnicodeBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nNumberOfBytesToRead);
- if (lpUnicodeBuffer == NULL)
- {
- DPRINT1("Alloc failed!\n");
- return FALSE;
- }
-
- if (!ReadFile(hFile, lpUnicodeBuffer, nNumberOfBytesToRead, &dwRead, NULL))
- {
- DPRINT1("Read failed!\n");
- ret = FALSE;
- goto done;
- }
-
- Dst = (PEVENTLOGRECORD)lpBuffer;
- Src = (PEVENTLOGRECORD)lpUnicodeBuffer;
-
- Dst->TimeGenerated = Src->TimeGenerated;
- Dst->Reserved = Src->Reserved;
- Dst->RecordNumber = Src->RecordNumber;
- Dst->TimeWritten = Src->TimeWritten;
- Dst->EventID = Src->EventID;
- Dst->EventType = Src->EventType;
- Dst->EventCategory = Src->EventCategory;
- Dst->NumStrings = Src->NumStrings;
- Dst->UserSidLength = Src->UserSidLength;
- Dst->DataLength = Src->DataLength;
-
- SrcPtr = (LPWSTR)((DWORD_PTR)Src + sizeof(EVENTLOGRECORD));
- DstPtr = (LPSTR)((DWORD_PTR)Dst + sizeof(EVENTLOGRECORD));
-
- /* Convert the module name */
- RtlInitUnicodeString(&StringW, SrcPtr);
- Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
- if (NT_SUCCESS(Status))
- {
- RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength);
-
- DstPtr = (PVOID)((DWORD_PTR)DstPtr + StringA.MaximumLength);
-
- RtlFreeAnsiString(&StringA);
- }
-
- /* Convert the computer name */
- if (NT_SUCCESS(Status))
- {
- SrcPtr = (PWSTR)((DWORD_PTR)SrcPtr + StringW.MaximumLength);
- RtlInitUnicodeString(&StringW, SrcPtr);
- Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
- if (NT_SUCCESS(Status))
- {
- RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength);
+/* FUNCTIONS *****************************************************************/
- DstPtr = (PVOID)((DWORD_PTR)DstPtr + StringA.MaximumLength);
-
- RtlFreeAnsiString(&StringA);
- }
- }
-
- /* Add the padding and the User SID*/
- if (NT_SUCCESS(Status))
- {
- dwPadding = sizeof(DWORD) - (((DWORD_PTR)DstPtr - (DWORD_PTR)Dst) % sizeof(DWORD));
- RtlZeroMemory(DstPtr, dwPadding);
-
- DstPtr = (LPSTR)((DWORD_PTR)DstPtr + dwPadding);
- RtlCopyMemory(DstPtr,
- (PVOID)((DWORD_PTR)Src + Src->UserSidOffset),
- Src->UserSidLength);
-
- Dst->UserSidOffset = (DWORD)((DWORD_PTR)DstPtr - (DWORD_PTR)Dst);
- }
-
-
- /* Convert the strings */
- if (NT_SUCCESS(Status))
- {
- DstPtr = (PVOID)((DWORD_PTR)DstPtr + Src->UserSidLength);
-
- SrcString = (LPWSTR)((DWORD_PTR)Src + (DWORD)Src->StringOffset);
- DstString = (LPSTR)DstPtr;
-
- for (i = 0; i < Dst->NumStrings; i++)
- {
- RtlInitUnicodeString(&StringW, SrcString);
-
- RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
-
- RtlCopyMemory(DstString, StringA.Buffer, StringA.MaximumLength);
-
- SrcString = (LPWSTR)((DWORD_PTR)SrcString +
- (DWORD)StringW.MaximumLength);
-
- DstString = (LPSTR)((DWORD_PTR)DstString +
- (DWORD)StringA.MaximumLength);
+// PELF_ALLOCATE_ROUTINE
+static
+PVOID NTAPI
+LogfpAlloc(IN SIZE_T Size,
+ IN ULONG Flags,
+ IN ULONG Tag)
+{
+ UNREFERENCED_PARAMETER(Tag);
+ return RtlAllocateHeap(GetProcessHeap(), Flags, Size);
+}
- RtlFreeAnsiString(&StringA);
- }
+// PELF_FREE_ROUTINE
+static
+VOID NTAPI
+LogfpFree(IN PVOID Ptr,
+ IN ULONG Flags,
+ IN ULONG Tag)
+{
+ UNREFERENCED_PARAMETER(Tag);
+ RtlFreeHeap(GetProcessHeap(), Flags, Ptr);
+}
- Dst->StringOffset = (DWORD)((DWORD_PTR)DstPtr - (DWORD_PTR)Dst);
+// PELF_FILE_READ_ROUTINE
+static
+NTSTATUS NTAPI
+LogfpReadFile(IN PEVTLOGFILE LogFile,
+ IN PLARGE_INTEGER FileOffset,
+ OUT PVOID Buffer,
+ IN SIZE_T Length,
+ OUT PSIZE_T ReadLength OPTIONAL)
+{
+ NTSTATUS Status;
+ PLOGFILE pLogFile = (PLOGFILE)LogFile;
+ IO_STATUS_BLOCK IoStatusBlock;
+ if (ReadLength)
+ *ReadLength = 0;
- /* Copy the binary data */
- DstPtr = (PVOID)DstString;
- Dst->DataOffset = (DWORD_PTR)DstPtr - (DWORD_PTR)Dst;
+ Status = NtReadFile(pLogFile->FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ Length,
+ FileOffset,
+ NULL);
- RtlCopyMemory(DstPtr, (PVOID)((DWORD_PTR)Src + Src->DataOffset), Src->DataLength);
+ if (ReadLength)
+ *ReadLength = IoStatusBlock.Information;
- /* Add the padding */
- DstPtr = (PVOID)((DWORD_PTR)DstPtr + Src->DataLength);
- dwPadding = sizeof(DWORD) - (((DWORD_PTR)DstPtr-(DWORD_PTR)Dst) % sizeof(DWORD));
- RtlZeroMemory(DstPtr, dwPadding);
+ return Status;
+}
- dwEntryLength = (DWORD)((DWORD_PTR)DstPtr + dwPadding + sizeof(DWORD) - (DWORD_PTR)Dst);
+// PELF_FILE_WRITE_ROUTINE
+static
+NTSTATUS NTAPI
+LogfpWriteFile(IN PEVTLOGFILE LogFile,
+ IN PLARGE_INTEGER FileOffset,
+ IN PVOID Buffer,
+ IN SIZE_T Length,
+ OUT PSIZE_T WrittenLength OPTIONAL)
+{
+ NTSTATUS Status;
+ PLOGFILE pLogFile = (PLOGFILE)LogFile;
+ IO_STATUS_BLOCK IoStatusBlock;
- /* Set the entry length at the end of the entry*/
- pLength = (PDWORD)((DWORD_PTR)DstPtr + dwPadding);
- *pLength = dwEntryLength;
- Dst->Length = dwEntryLength;
+ if (WrittenLength)
+ *WrittenLength = 0;
- *lpNumberOfBytesRead = dwEntryLength;
- }
+ Status = NtWriteFile(pLogFile->FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ Length,
+ FileOffset,
+ NULL);
-done:
- if (lpUnicodeBuffer != NULL)
- HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer);
+ if (WrittenLength)
+ *WrittenLength = IoStatusBlock.Information;
- return ret;
+ return Status;
}
-
-DWORD LogfReadEvent(PLOGFILE LogFile,
- DWORD Flags,
- DWORD * RecordNumber,
- DWORD BufSize,
- PBYTE Buffer,
- DWORD * BytesRead,
- DWORD * BytesNeeded,
- BOOL Ansi)
+// PELF_FILE_SET_SIZE_ROUTINE
+static
+NTSTATUS NTAPI
+LogfpSetFileSize(IN PEVTLOGFILE LogFile,
+ IN ULONG FileSize, // SIZE_T
+ IN ULONG OldFileSize) // SIZE_T
{
- DWORD dwOffset, dwRead, dwRecSize;
- DWORD dwBufferUsage = 0, dwRecNum;
+ NTSTATUS Status;
+ PLOGFILE pLogFile = (PLOGFILE)LogFile;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_END_OF_FILE_INFORMATION FileEofInfo;
+ FILE_ALLOCATION_INFORMATION FileAllocInfo;
- if (Flags & EVENTLOG_FORWARDS_READ && Flags & EVENTLOG_BACKWARDS_READ)
- return ERROR_INVALID_PARAMETER;
+ UNREFERENCED_PARAMETER(OldFileSize);
- if (!(Flags & EVENTLOG_FORWARDS_READ) && !(Flags & EVENTLOG_BACKWARDS_READ))
- return ERROR_INVALID_PARAMETER;
+ // FIXME: Should we round up FileSize ??
- if (!Buffer || !BytesRead || !BytesNeeded)
- return ERROR_INVALID_PARAMETER;
+ FileEofInfo.EndOfFile.QuadPart = FileSize;
+ Status = NtSetInformationFile(pLogFile->FileHandle,
+ &IoStatusBlock,
+ &FileEofInfo,
+ sizeof(FileEofInfo),
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(Status))
+ return Status;
- if ((*RecordNumber==0) && !(EVENTLOG_SEQUENTIAL_READ))
- {
- return ERROR_INVALID_PARAMETER;
- }
+ FileAllocInfo.AllocationSize.QuadPart = FileSize;
+ Status = NtSetInformationFile(pLogFile->FileHandle,
+ &IoStatusBlock,
+ &FileAllocInfo,
+ sizeof(FileAllocInfo),
+ FileAllocationInformation);
- dwRecNum = *RecordNumber;
+ return Status;
+}
- RtlAcquireResourceShared(&LogFile->Lock, TRUE);
+// PELF_FILE_FLUSH_ROUTINE
+static
+NTSTATUS NTAPI
+LogfpFlushFile(IN PEVTLOGFILE LogFile,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length)
+{
+ PLOGFILE pLogFile = (PLOGFILE)LogFile;
+ IO_STATUS_BLOCK IoStatusBlock;
- *BytesRead = 0;
- *BytesNeeded = 0;
+ UNREFERENCED_PARAMETER(FileOffset);
+ UNREFERENCED_PARAMETER(Length);
- dwOffset = LogfOffsetByNumber(LogFile, dwRecNum);
+ return NtFlushBuffersFile(pLogFile->FileHandle, &IoStatusBlock);
+}
- if (!dwOffset)
- {
- RtlReleaseResource(&LogFile->Lock);
- return ERROR_HANDLE_EOF;
- }
+NTSTATUS
+LogfCreate(PLOGFILE* LogFile,
+ PCWSTR LogName,
+ PUNICODE_STRING FileName,
+ ULONG MaxSize,
+ ULONG Retention,
+ BOOLEAN Permanent,
+ BOOLEAN Backup)
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_STANDARD_INFORMATION FileStdInfo;
+ PLOGFILE pLogFile;
+ SIZE_T LogNameLen;
+ BOOLEAN CreateNew;
- if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) ==
- INVALID_SET_FILE_POINTER)
+ pLogFile = LogfpAlloc(sizeof(*pLogFile), HEAP_ZERO_MEMORY, TAG_ELF);
+ if (!pLogFile)
{
- DPRINT1("SetFilePointer() failed!\n");
- goto Done;
+ DPRINT1("Cannot allocate heap!\n");
+ return STATUS_NO_MEMORY;
}
- if (!ReadFile(LogFile->hFile, &dwRecSize, sizeof(DWORD), &dwRead, NULL))
+ LogNameLen = (LogName ? wcslen(LogName) : 0) + 1;
+ pLogFile->LogName = LogfpAlloc(LogNameLen * sizeof(WCHAR), HEAP_ZERO_MEMORY, 0);
+ if (pLogFile->LogName == NULL)
{
- DPRINT1("ReadFile() failed!\n");
- goto Done;
+ DPRINT1("Cannot allocate heap\n");
+ Status = STATUS_NO_MEMORY;
+ goto Quit;
}
- if (dwRecSize > BufSize)
- {
- *BytesNeeded = dwRecSize;
- RtlReleaseResource(&LogFile->Lock);
- return ERROR_INSUFFICIENT_BUFFER;
- }
+ if (LogName)
+ StringCchCopyW(pLogFile->LogName, LogNameLen, LogName);
- if (SetFilePointer(LogFile->hFile,
- -((LONG) sizeof(DWORD)),
- NULL,
- FILE_CURRENT) == INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed!\n");
- goto Done;
- }
+ InitializeObjectAttributes(&ObjectAttributes,
+ FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
- if (Ansi == TRUE)
+ DPRINT("Going to create or open %wZ\n", FileName);
+ Status = NtCreateFile(&pLogFile->FileHandle,
+ Backup ? (GENERIC_READ | SYNCHRONIZE)
+ : (GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE),
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ Backup ? FILE_OPEN : FILE_OPEN_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
{
- if (!ReadAnsiLogEntry(LogFile->hFile, Buffer, dwRecSize, &dwRead))
- {
- DPRINT1("ReadAnsiLogEntry() failed!\n");
- goto Done;
- }
- }
- else
+ DPRINT1("Cannot create file `%wZ' (Status 0x%08lx)\n", FileName, Status);
+ goto Quit;
+ }
+
+ CreateNew = (IoStatusBlock.Information == FILE_CREATED);
+ DPRINT("%wZ %s successfully\n", FileName, CreateNew ? "created" : "opened");
+
+ /*
+ * Retrieve the log file size and check whether the file is not too large;
+ * this log format only supports files of theoretical size < 0xFFFFFFFF .
+ *
+ * As it happens that, on Windows (and ReactOS), retrieving the End-Of-File
+ * information using NtQueryInformationFile with the FileEndOfFileInformation
+ * class is invalid (who knows why...), use instead the FileStandardInformation
+ * class, and the EndOfFile member of the returned FILE_STANDARD_INFORMATION
+ * structure will give the desired information.
+ */
+ Status = NtQueryInformationFile(pLogFile->FileHandle,
+ &IoStatusBlock,
+ &FileStdInfo,
+ sizeof(FileStdInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
{
- if (!ReadFile(LogFile->hFile, Buffer, dwRecSize, &dwRead, NULL))
- {
- DPRINT1("ReadFile() failed!\n");
- goto Done;
- }
+ DPRINT1("EventLog: NtQueryInformationFile failed (Status 0x%08lx)\n", Status);
+ goto Quit;
}
-
- dwBufferUsage += dwRead;
-
- while (dwBufferUsage <= BufSize)
+ if (FileStdInfo.EndOfFile.HighPart != 0)
{
- if (Flags & EVENTLOG_FORWARDS_READ)
- dwRecNum++;
- else
- dwRecNum--;
-
- dwOffset = LogfOffsetByNumber(LogFile, dwRecNum);
- if (!dwOffset)
- break;
-
- if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) ==
- INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed!\n");
- goto Done;
- }
-
- if (!ReadFile(LogFile->hFile,
- &dwRecSize,
- sizeof(DWORD),
- &dwRead,
- NULL))
- {
- DPRINT1("ReadFile() failed!\n");
- goto Done;
- }
-
- if (dwBufferUsage + dwRecSize > BufSize)
- break;
-
- if (SetFilePointer(LogFile->hFile,
- -((LONG) sizeof(DWORD)),
- NULL,
- FILE_CURRENT) == INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed!\n");
- goto Done;
- }
-
- if (Ansi == TRUE)
- {
- if (!ReadAnsiLogEntry(LogFile->hFile,
- Buffer + dwBufferUsage,
- dwRecSize,
- &dwRead))
- {
- DPRINT1("ReadAnsiLogEntry() failed!\n");
- goto Done;
- }
- }
- else
- {
- if (!ReadFile(LogFile->hFile,
- Buffer + dwBufferUsage,
- dwRecSize,
- &dwRead,
- NULL))
- {
- DPRINT1("ReadFile() failed!\n");
- goto Done;
- }
- }
-
- dwBufferUsage += dwRead;
+ DPRINT1("EventLog: Log `%wZ' is too large.\n", FileName);
+ Status = STATUS_EVENTLOG_FILE_CORRUPT; // STATUS_FILE_TOO_LARGE;
+ goto Quit;
}
- *BytesRead = dwBufferUsage;
- * RecordNumber = dwRecNum;
- RtlReleaseResource(&LogFile->Lock);
- return ERROR_SUCCESS;
-
-Done:
- DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
- RtlReleaseResource(&LogFile->Lock);
- return GetLastError();
-}
-
-BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
-{
- DWORD dwWritten;
- DWORD dwRead;
- SYSTEMTIME st;
- EVENTLOGEOF EofRec;
- PEVENTLOGRECORD RecBuf;
- LARGE_INTEGER logFileSize;
- ULONG RecOffSet;
- ULONG WriteOffSet;
+ DPRINT("Initializing LogFile `%S'\n", pLogFile->LogName);
- if (!Buffer)
- return FALSE;
-
- GetSystemTime(&st);
- SystemTimeToEventTime(&st, &((PEVENTLOGRECORD) Buffer)->TimeWritten);
-
- RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
-
- if (!GetFileSizeEx(LogFile->hFile, &logFileSize))
- {
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
-
- /* If the size of the file is over MaxSize */
- if ((logFileSize.QuadPart + BufSize)> LogFile->Header.MaxSize)
- {
- ULONG OverWriteLength = 0;
- WriteOffSet = LogfOffsetByNumber(LogFile, LogFile->Header.OldestRecordNumber);
- RecBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(EVENTLOGRECORD));
- /* Determine how many records need to be overwritten */
- while (TRUE)
- {
- DPRINT("EventLogFile has reached maximume size\n");
-
- if (!RecBuf)
- {
- DPRINT1("Failed to allocate buffer for OldestRecord!\n");
- HeapFree(GetProcessHeap(), 0, RecBuf);
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
-
- /* Get the oldest record data */
- RecOffSet = LogfOffsetByNumber(LogFile, LogFile->Header.OldestRecordNumber);
+ Status = ElfCreateFile(&pLogFile->LogFile,
+ FileName,
+ FileStdInfo.EndOfFile.LowPart,
+ MaxSize,
+ Retention,
+ CreateNew,
+ Backup,
+ LogfpAlloc,
+ LogfpFree,
+ LogfpSetFileSize,
+ LogfpWriteFile,
+ LogfpReadFile,
+ LogfpFlushFile);
+ if (!NT_SUCCESS(Status))
+ goto Quit;
- if (SetFilePointer(LogFile->hFile,
- RecOffSet,
- NULL,
- FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
- HeapFree(GetProcessHeap(), 0, RecBuf);
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
+ pLogFile->Permanent = Permanent;
- if (!ReadFile(LogFile->hFile, RecBuf, sizeof(EVENTLOGRECORD), &dwRead, NULL))
- {
- DPRINT1("ReadFile() failed!\n");
- HeapFree(GetProcessHeap(), 0, RecBuf);
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
+ RtlInitializeResource(&pLogFile->Lock);
- if (RecBuf->Reserved != LOGFILE_SIGNATURE)
- {
- DPRINT1("LogFile corrupt!\n");
- HeapFree(GetProcessHeap(), 0, RecBuf);
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
+ LogfListAddItem(pLogFile);
- LogfDeleteOffsetInformation(LogFile,LogFile->Header.OldestRecordNumber);
+Quit:
+ if (!NT_SUCCESS(Status))
+ {
+ if (pLogFile->FileHandle != NULL)
+ NtClose(pLogFile->FileHandle);
- LogFile->Header.OldestRecordNumber++;
+ if (pLogFile->LogName)
+ LogfpFree(pLogFile->LogName, 0, 0);
- OverWriteLength += RecBuf->Length;
- /* Check the size of the record as the record adding may be larger */
- if (OverWriteLength >= BufSize)
- {
- DPRINT("Record will fit. Length %d, BufSize %d\n", OverWriteLength, BufSize);
- LogFile->Header.StartOffset = LogfOffsetByNumber(LogFile, LogFile->Header.OldestRecordNumber);
- break;
- }
- }
- HeapFree(GetProcessHeap(), 0, RecBuf);
+ LogfpFree(pLogFile, 0, TAG_ELF);
}
else
- WriteOffSet = LogFile->Header.EndOffset;
-
- if (SetFilePointer(LogFile->hFile,
- WriteOffSet,
- NULL,
- FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
- DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
+ *LogFile = pLogFile;
}
- if (!WriteFile(LogFile->hFile, Buffer, BufSize, &dwWritten, NULL))
- {
- DPRINT1("WriteFile() failed! %d\n", GetLastError());
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
+ return Status;
+}
- if (!LogfAddOffsetInformation(LogFile,
- LogFile->Header.CurrentRecordNumber,
- WriteOffSet))
- {
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
+VOID
+LogfClose(PLOGFILE LogFile,
+ BOOLEAN ForceClose)
+{
+ if (LogFile == NULL)
+ return;
- LogFile->Header.CurrentRecordNumber++;
+ if (!ForceClose && LogFile->Permanent)
+ return;
- if (WriteOffSet == LogFile->Header.EndOffset)
- {
- LogFile->Header.EndOffset += dwWritten;
- }
- if (SetFilePointer(LogFile->hFile,
- LogFile->Header.EndOffset,
- NULL,
- FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
+ RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
- EofRec.Ones = 0x11111111;
- EofRec.Twos = 0x22222222;
- EofRec.Threes = 0x33333333;
- EofRec.Fours = 0x44444444;
- EofRec.RecordSizeBeginning = sizeof(EVENTLOGEOF);
- EofRec.RecordSizeEnd = sizeof(EVENTLOGEOF);
- EofRec.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
- EofRec.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
- EofRec.BeginRecord = LogFile->Header.StartOffset;
- EofRec.EndRecord = LogFile->Header.EndOffset;
-
- if (!WriteFile(LogFile->hFile,
- &EofRec,
- sizeof(EVENTLOGEOF),
- &dwWritten,
- NULL))
- {
- DPRINT1("WriteFile() failed! %d\n", GetLastError());
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
+ LogfListRemoveItem(LogFile);
- if (SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
- INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
+ ElfCloseFile(&LogFile->LogFile);
+ NtClose(LogFile->FileHandle);
+ LogfpFree(LogFile->LogName, 0, 0);
- if (!WriteFile(LogFile->hFile,
- &LogFile->Header,
- sizeof(EVENTLOGHEADER),
- &dwWritten,
- NULL))
- {
- DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
- }
+ RtlDeleteResource(&LogFile->Lock);
+
+ LogfpFree(LogFile, 0, TAG_ELF);
+
+ return;
+}
+
+VOID LogfCloseAll(VOID)
+{
+ EnterCriticalSection(&LogFileListCs);
- if (!FlushFileBuffers(LogFile->hFile))
+ while (!IsListEmpty(&LogFileListHead))
{
- DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
- RtlReleaseResource(&LogFile->Lock);
- return FALSE;
+ LogfClose(CONTAINING_RECORD(LogFileListHead.Flink, LOGFILE, ListEntry), TRUE);
}
- RtlReleaseResource(&LogFile->Lock);
- return TRUE;
-}
+ LeaveCriticalSection(&LogFileListCs);
+ DeleteCriticalSection(&LogFileListCs);
+}
NTSTATUS
LogfClearFile(PLOGFILE LogFile,
{
NTSTATUS Status;
+ /* Lock the log file exclusive */
RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
if (BackupFileName->Length > 0)
{
/* Write a backup file */
- Status = LogfBackupFile(LogFile,
- BackupFileName);
+ Status = LogfBackupFile(LogFile, BackupFileName);
if (!NT_SUCCESS(Status))
{
- DPRINT1("LogfBackupFile failed (Status: 0x%08lx)\n", Status);
- return Status;
+ DPRINT1("LogfBackupFile failed (Status 0x%08lx)\n", Status);
+ goto Quit;
}
}
- Status = LogfInitializeNew(LogFile);
+ Status = ElfReCreateFile(&LogFile->LogFile);
if (!NT_SUCCESS(Status))
{
- DPRINT1("LogfInitializeNew failed (Status: 0x%08lx)\n", Status);
+ DPRINT1("LogfInitializeNew failed (Status 0x%08lx)\n", Status);
}
+Quit:
+ /* Unlock the log file */
RtlReleaseResource(&LogFile->Lock);
-
return Status;
}
-
NTSTATUS
LogfBackupFile(PLOGFILE LogFile,
PUNICODE_STRING BackupFileName)
{
+ NTSTATUS Status;
+ LOGFILE BackupLogFile;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- EVENTLOGHEADER Header;
- EVENTLOGEOF EofRec;
- HANDLE FileHandle = NULL;
- ULONG i;
- LARGE_INTEGER FileOffset;
- NTSTATUS Status;
- PUCHAR Buffer = NULL;
-
- DWORD dwOffset, dwRead, dwRecSize;
DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile, BackupFileName);
NULL,
NULL);
- Status = NtCreateFile(&FileHandle,
+ Status = NtCreateFile(&BackupLogFile.FileHandle,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
0);
if (!NT_SUCCESS(Status))
{
- DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName, Status);
- goto Done;
+ DPRINT("Cannot create backup file `%wZ' (Status 0x%08lx)\n", BackupFileName, Status);
+ goto Quit;
}
- /* Initialize the (dirty) log file header */
- Header.HeaderSize = sizeof(EVENTLOGHEADER);
- Header.Signature = LOGFILE_SIGNATURE;
- Header.MajorVersion = MAJORVER;
- Header.MinorVersion = MINORVER;
- Header.StartOffset = sizeof(EVENTLOGHEADER);
- Header.EndOffset = sizeof(EVENTLOGHEADER);
- Header.CurrentRecordNumber = 1;
- Header.OldestRecordNumber = 1;
- Header.MaxSize = 0;
- Header.Flags = ELF_LOGFILE_HEADER_DIRTY;
- Header.Retention = LogFile->Header.Retention;
- Header.EndHeaderSize = sizeof(EVENTLOGHEADER);
-
- /* Write the (dirty) log file header */
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- &Header,
- sizeof(EVENTLOGHEADER),
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
+ Status = ElfBackupFile(&LogFile->LogFile,
+ &BackupLogFile.LogFile);
+
+Quit:
+ /* Close the backup file */
+ if (BackupLogFile.FileHandle != NULL)
+ NtClose(BackupLogFile.FileHandle);
+
+ /* Unlock the log file */
+ RtlReleaseResource(&LogFile->Lock);
+
+ return Status;
+}
+
+
+static NTSTATUS
+ReadRecord(IN PEVTLOGFILE LogFile,
+ IN ULONG RecordNumber,
+ OUT PEVENTLOGRECORD Record,
+ IN SIZE_T BufSize, // Length
+ OUT PSIZE_T BytesRead OPTIONAL,
+ OUT PSIZE_T BytesNeeded OPTIONAL,
+ IN BOOLEAN Ansi)
+{
+ NTSTATUS Status;
+ PEVENTLOGRECORD UnicodeBuffer = NULL;
+ PEVENTLOGRECORD Src, Dst;
+ ANSI_STRING StringA;
+ UNICODE_STRING StringW;
+ PVOID SrcPtr, DstPtr;
+ DWORD i;
+ DWORD dwPadding;
+ DWORD dwRecordLength;
+ PDWORD pLength;
+
+ if (!Ansi)
{
- DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status);
- goto Done;
+ return ElfReadRecord(LogFile,
+ RecordNumber,
+ Record,
+ BufSize,
+ BytesRead,
+ BytesNeeded);
}
- for (i = LogFile->Header.OldestRecordNumber; i < LogFile->Header.CurrentRecordNumber; i++)
- {
- dwOffset = LogfOffsetByNumber(LogFile, i);
- if (dwOffset == 0)
- break;
+ if (BytesRead)
+ *BytesRead = 0;
- if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed!\n");
- goto Done;
- }
+ if (BytesNeeded)
+ *BytesNeeded = 0;
- if (!ReadFile(LogFile->hFile, &dwRecSize, sizeof(DWORD), &dwRead, NULL))
- {
- DPRINT1("ReadFile() failed!\n");
- goto Done;
- }
+ UnicodeBuffer = LogfpAlloc(BufSize, HEAP_ZERO_MEMORY, TAG_ELF_BUF);
+ if (UnicodeBuffer == NULL)
+ {
+ DPRINT1("Alloc failed!\n");
+ return STATUS_NO_MEMORY;
+ }
- if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- {
- DPRINT1("SetFilePointer() failed!\n");
- goto Done;
- }
+ Status = ElfReadRecord(LogFile,
+ RecordNumber,
+ UnicodeBuffer,
+ BufSize,
+ BytesRead,
+ BytesNeeded);
+ if (!NT_SUCCESS(Status))
+ goto Quit;
- Buffer = HeapAlloc(MyHeap, 0, dwRecSize);
- if (Buffer == NULL)
- {
- DPRINT1("HeapAlloc() failed!\n");
- goto Done;
- }
+ Src = UnicodeBuffer;
+ Dst = Record;
- if (!ReadFile(LogFile->hFile, &Buffer, dwRecSize, &dwRead, NULL))
- {
- DPRINT1("ReadFile() failed!\n");
- goto Done;
- }
+ Dst->Reserved = Src->Reserved;
+ Dst->RecordNumber = Src->RecordNumber;
+ Dst->TimeGenerated = Src->TimeGenerated;
+ Dst->TimeWritten = Src->TimeWritten;
+ Dst->EventID = Src->EventID;
+ Dst->EventType = Src->EventType;
+ Dst->EventCategory = Src->EventCategory;
+ Dst->NumStrings = Src->NumStrings;
+ Dst->UserSidLength = Src->UserSidLength;
+ Dst->DataLength = Src->DataLength;
- /* Write the event record */
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- Buffer,
- dwRecSize,
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtWriteFile() failed!\n");
- goto Done;
- }
+ SrcPtr = (PVOID)((ULONG_PTR)Src + sizeof(EVENTLOGRECORD));
+ DstPtr = (PVOID)((ULONG_PTR)Dst + sizeof(EVENTLOGRECORD));
- /* Update the header information */
- Header.EndOffset += dwRecSize;
+ /* Convert the module name */
+ RtlInitUnicodeString(&StringW, SrcPtr);
+ Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength);
+ DstPtr = (PVOID)((ULONG_PTR)DstPtr + StringA.MaximumLength);
- /* Free the buffer */
- HeapFree(MyHeap, 0, Buffer);
- Buffer = NULL;
+ RtlFreeAnsiString(&StringA);
+ }
+ else
+ {
+ RtlZeroMemory(DstPtr, StringW.MaximumLength / sizeof(WCHAR));
+ DstPtr = (PVOID)((ULONG_PTR)DstPtr + StringW.MaximumLength / sizeof(WCHAR));
}
+ SrcPtr = (PVOID)((ULONG_PTR)SrcPtr + StringW.MaximumLength);
- /* Initialize the EOF record */
- EofRec.RecordSizeBeginning = sizeof(EVENTLOGEOF);
- EofRec.Ones = 0x11111111;
- EofRec.Twos = 0x22222222;
- EofRec.Threes = 0x33333333;
- EofRec.Fours = 0x44444444;
- EofRec.BeginRecord = sizeof(EVENTLOGHEADER);
- EofRec.EndRecord = Header.EndOffset;
- EofRec.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
- EofRec.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
- EofRec.RecordSizeEnd = sizeof(EVENTLOGEOF);
-
- /* Write the EOF record */
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- &EofRec,
- sizeof(EVENTLOGEOF),
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
+ /* Convert the computer name */
+ RtlInitUnicodeString(&StringW, SrcPtr);
+ Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength);
+ DstPtr = (PVOID)((ULONG_PTR)DstPtr + StringA.MaximumLength);
+
+ RtlFreeAnsiString(&StringA);
+ }
+ else
{
- DPRINT1("NtWriteFile() failed!\n");
- goto Done;
+ RtlZeroMemory(DstPtr, StringW.MaximumLength / sizeof(WCHAR));
+ DstPtr = (PVOID)((ULONG_PTR)DstPtr + StringW.MaximumLength / sizeof(WCHAR));
}
- /* Update the header information */
- Header.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
- Header.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
- Header.MaxSize = Header.EndOffset + sizeof(EVENTLOGEOF);
- Header.Flags = 0;
+ /* Add the padding and the User SID */
+ dwPadding = sizeof(ULONG) - (((ULONG_PTR)DstPtr - (ULONG_PTR)Dst) % sizeof(ULONG));
+ RtlZeroMemory(DstPtr, dwPadding);
- /* Write the (clean) log file header */
- FileOffset.QuadPart = 0;
- Status = NtWriteFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- &Header,
- sizeof(EVENTLOGHEADER),
- &FileOffset,
- NULL);
- if (!NT_SUCCESS(Status))
+ SrcPtr = (PVOID)((ULONG_PTR)Src + Src->UserSidOffset);
+ DstPtr = (PVOID)((ULONG_PTR)DstPtr + dwPadding);
+
+ Dst->UserSidOffset = (DWORD)((ULONG_PTR)DstPtr - (ULONG_PTR)Dst);
+ RtlCopyMemory(DstPtr, SrcPtr, Src->UserSidLength);
+
+ /* Convert the strings */
+ SrcPtr = (PVOID)((ULONG_PTR)Src + Src->StringOffset);
+ DstPtr = (PVOID)((ULONG_PTR)DstPtr + Src->UserSidLength);
+ Dst->StringOffset = (DWORD)((ULONG_PTR)DstPtr - (ULONG_PTR)Dst);
+
+ for (i = 0; i < Dst->NumStrings; i++)
{
- DPRINT1("NtWriteFile() failed!\n");
+ RtlInitUnicodeString(&StringW, SrcPtr);
+ Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength);
+ DstPtr = (PVOID)((ULONG_PTR)DstPtr + StringA.MaximumLength);
+
+ RtlFreeAnsiString(&StringA);
+ }
+ else
+ {
+ RtlZeroMemory(DstPtr, StringW.MaximumLength / sizeof(WCHAR));
+ DstPtr = (PVOID)((ULONG_PTR)DstPtr + StringW.MaximumLength / sizeof(WCHAR));
+ }
+ SrcPtr = (PVOID)((ULONG_PTR)SrcPtr + StringW.MaximumLength);
}
-Done:
- /* Free the buffer */
- if (Buffer != NULL)
- HeapFree(MyHeap, 0, Buffer);
+ /* Copy the binary data */
+ SrcPtr = (PVOID)((ULONG_PTR)Src + Src->DataOffset);
+ Dst->DataOffset = (ULONG_PTR)DstPtr - (ULONG_PTR)Dst;
+ RtlCopyMemory(DstPtr, SrcPtr, Src->DataLength);
+ DstPtr = (PVOID)((ULONG_PTR)DstPtr + Src->DataLength);
- /* Close the backup file */
- if (FileHandle != NULL)
- NtClose(FileHandle);
+ /* Add the padding */
+ dwPadding = sizeof(ULONG) - (((ULONG_PTR)DstPtr - (ULONG_PTR)Dst) % sizeof(ULONG));
+ RtlZeroMemory(DstPtr, dwPadding);
- /* Unlock the log file */
- RtlReleaseResource(&LogFile->Lock);
+ /* Set the record length at the beginning and the end of the record */
+ dwRecordLength = (DWORD)((ULONG_PTR)DstPtr + dwPadding + sizeof(ULONG) - (ULONG_PTR)Dst);
+ Dst->Length = dwRecordLength;
+ pLength = (PDWORD)((ULONG_PTR)DstPtr + dwPadding);
+ *pLength = dwRecordLength;
- return Status;
-}
+ if (BytesRead)
+ *BytesRead = dwRecordLength;
+ Status = STATUS_SUCCESS;
-/* Returns 0 if nothing found. */
-ULONG LogfOffsetByNumber(PLOGFILE LogFile, DWORD RecordNumber)
-{
- DWORD i;
+Quit:
+ LogfpFree(UnicodeBuffer, 0, TAG_ELF_BUF);
- for (i = 0; i < LogFile->OffsetInfoNext; i++)
- {
- if (LogFile->OffsetInfo[i].EventNumber == RecordNumber)
- return LogFile->OffsetInfo[i].EventOffset;
- }
- return 0;
+ return Status;
}
-DWORD LogfGetOldestRecord(PLOGFILE LogFile)
+/*
+ * NOTE:
+ * 'RecordNumber' is a pointer to the record number at which the read operation
+ * should start. If the record number is 0 and the flags given in the 'Flags'
+ * parameter contain EVENTLOG_SEQUENTIAL_READ, an adequate record number is
+ * computed.
+ */
+NTSTATUS
+LogfReadEvents(PLOGFILE LogFile,
+ ULONG Flags,
+ PULONG RecordNumber,
+ ULONG BufSize,
+ PBYTE Buffer,
+ PULONG BytesRead,
+ PULONG BytesNeeded,
+ BOOLEAN Ansi)
{
- return LogFile->Header.OldestRecordNumber;
-}
+ NTSTATUS Status;
+ ULONG RecNum;
+ SIZE_T ReadLength, NeededSize;
+ ULONG BufferUsage;
-DWORD LogfGetCurrentRecord(PLOGFILE LogFile)
-{
- return LogFile->Header.CurrentRecordNumber;
-}
+ /* Parameters validation */
-BOOL LogfDeleteOffsetInformation(PLOGFILE LogFile, ULONG ulNumber)
-{
- DWORD i;
+ /* EVENTLOG_SEQUENTIAL_READ and EVENTLOG_SEEK_READ are mutually exclusive */
+ if ((Flags & EVENTLOG_SEQUENTIAL_READ) && (Flags & EVENTLOG_SEEK_READ))
+ return STATUS_INVALID_PARAMETER;
+
+ if (!(Flags & EVENTLOG_SEQUENTIAL_READ) && !(Flags & EVENTLOG_SEEK_READ))
+ return STATUS_INVALID_PARAMETER;
+
+ /* EVENTLOG_FORWARDS_READ and EVENTLOG_BACKWARDS_READ are mutually exclusive */
+ if ((Flags & EVENTLOG_FORWARDS_READ) && (Flags & EVENTLOG_BACKWARDS_READ))
+ return STATUS_INVALID_PARAMETER;
+
+ if (!(Flags & EVENTLOG_FORWARDS_READ) && !(Flags & EVENTLOG_BACKWARDS_READ))
+ return STATUS_INVALID_PARAMETER;
+
+ if (!Buffer || !BytesRead || !BytesNeeded)
+ return STATUS_INVALID_PARAMETER;
- if (ulNumber != LogFile->OffsetInfo[0].EventNumber)
+ /* In seek read mode, a record number of 0 is invalid */
+ if (!(Flags & EVENTLOG_SEQUENTIAL_READ) && (*RecordNumber == 0))
+ return STATUS_INVALID_PARAMETER;
+
+ /* Lock the log file shared */
+ RtlAcquireResourceShared(&LogFile->Lock, TRUE);
+
+ /*
+ * In sequential read mode, a record number of 0 means we need
+ * to determine where to start the read operation. Otherwise
+ * we just use the provided record number.
+ */
+ if ((Flags & EVENTLOG_SEQUENTIAL_READ) && (*RecordNumber == 0))
{
- return FALSE;
+ if (Flags & EVENTLOG_FORWARDS_READ)
+ {
+ *RecordNumber = ElfGetOldestRecord(&LogFile->LogFile);
+ }
+ else // if (Flags & EVENTLOG_BACKWARDS_READ)
+ {
+ *RecordNumber = ElfGetCurrentRecord(&LogFile->LogFile) - 1;
+ }
}
- for (i = 0; i < LogFile->OffsetInfoNext - 1; i++)
- {
- LogFile->OffsetInfo[i].EventNumber = LogFile->OffsetInfo[i + 1].EventNumber;
- LogFile->OffsetInfo[i].EventOffset = LogFile->OffsetInfo[i + 1].EventOffset;
+ RecNum = *RecordNumber;
+
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ BufferUsage = 0;
+ do
+ {
+ Status = ReadRecord(&LogFile->LogFile,
+ RecNum,
+ (PEVENTLOGRECORD)(Buffer + BufferUsage),
+ BufSize - BufferUsage,
+ &ReadLength,
+ &NeededSize,
+ Ansi);
+ if (Status == STATUS_NOT_FOUND)
+ {
+ if (BufferUsage == 0)
+ {
+ Status = STATUS_END_OF_FILE;
+ goto Quit;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ if (Status == STATUS_BUFFER_TOO_SMALL)
+ {
+ if (BufferUsage == 0)
+ {
+ *BytesNeeded = NeededSize;
+ // Status = STATUS_BUFFER_TOO_SMALL;
+ goto Quit;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ElfReadRecord failed (Status 0x%08lx)\n", Status);
+ goto Quit;
+ }
+
+ /* Go to the next event record */
+ /*
+ * NOTE: This implicitly supposes that all the other record numbers
+ * are consecutive (and do not jump than more than one unit); but if
+ * it is not the case, then we would prefer here to call some
+ * "get_next_record_number" function.
+ */
+ if (Flags & EVENTLOG_FORWARDS_READ)
+ RecNum++;
+ else // if (Flags & EVENTLOG_BACKWARDS_READ)
+ RecNum--;
+
+ BufferUsage += ReadLength;
}
- LogFile->OffsetInfoNext--;
- return TRUE;
+ while (BufferUsage <= BufSize);
+
+ *BytesRead = BufferUsage;
+ *RecordNumber = RecNum;
+
+ Status = STATUS_SUCCESS;
+
+Quit:
+ /* Unlock the log file */
+ RtlReleaseResource(&LogFile->Lock);
+
+ if (!NT_SUCCESS(Status))
+ DPRINT1("LogfReadEvents failed (Status 0x%08lx)\n", Status);
+
+ return Status;
}
-BOOL LogfAddOffsetInformation(PLOGFILE LogFile, ULONG ulNumber, ULONG ulOffset)
+NTSTATUS
+LogfWriteRecord(PLOGFILE LogFile,
+ PEVENTLOGRECORD Record,
+ SIZE_T BufSize)
{
- LPVOID NewOffsetInfo;
+ NTSTATUS Status;
+ LARGE_INTEGER SystemTime;
- if (LogFile->OffsetInfoNext == LogFile->OffsetInfoSize)
- {
- NewOffsetInfo = HeapReAlloc(MyHeap,
- HEAP_ZERO_MEMORY,
- LogFile->OffsetInfo,
- (LogFile->OffsetInfoSize + 64) *
- sizeof(EVENT_OFFSET_INFO));
+ // ASSERT(sizeof(*Record) == sizeof(RecBuf));
- if (!NewOffsetInfo)
- {
- DPRINT1("Can't reallocate heap.\n");
- return FALSE;
- }
+ if (!Record || BufSize < sizeof(*Record))
+ return STATUS_INVALID_PARAMETER;
+
+ /* Lock the log file exclusive */
+ RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
- LogFile->OffsetInfo = (PEVENT_OFFSET_INFO) NewOffsetInfo;
- LogFile->OffsetInfoSize += 64;
+ /*
+ * Retrieve the record written time now, that will also be compared
+ * with the existing events timestamps in case the log is wrapping.
+ */
+ NtQuerySystemTime(&SystemTime);
+ RtlTimeToSecondsSince1970(&SystemTime, &Record->TimeWritten);
+
+ Status = ElfWriteRecord(&LogFile->LogFile, Record, BufSize);
+ if (Status == STATUS_LOG_FILE_FULL)
+ {
+ /* The event log file is full, queue a message box for the user and exit */
+ // TODO!
+ DPRINT1("Log file `%S' is full!\n", LogFile->LogName);
}
- LogFile->OffsetInfo[LogFile->OffsetInfoNext].EventNumber = ulNumber;
- LogFile->OffsetInfo[LogFile->OffsetInfoNext].EventOffset = ulOffset;
- LogFile->OffsetInfoNext++;
+ /* Unlock the log file */
+ RtlReleaseResource(&LogFile->Lock);
- return TRUE;
+ return Status;
}
-PBYTE LogfAllocAndBuildNewRecord(LPDWORD lpRecSize,
- DWORD dwRecordNumber,
- WORD wType,
- WORD wCategory,
- DWORD dwEventId,
- LPCWSTR SourceName,
- LPCWSTR ComputerName,
- DWORD dwSidLength,
- PSID lpUserSid,
- WORD wNumStrings,
- WCHAR * lpStrings,
- DWORD dwDataSize,
- LPVOID lpRawData)
+
+PEVENTLOGRECORD
+LogfAllocAndBuildNewRecord(PSIZE_T pRecSize,
+ ULONG Time,
+ USHORT wType,
+ USHORT wCategory,
+ ULONG dwEventId,
+ PUNICODE_STRING SourceName,
+ PUNICODE_STRING ComputerName,
+ ULONG dwSidLength,
+ PSID pUserSid,
+ USHORT wNumStrings,
+ PWSTR pStrings,
+ ULONG dwDataSize,
+ PVOID pRawData)
{
- DWORD dwRecSize;
+ SIZE_T RecSize;
+ SIZE_T SourceNameSize, ComputerNameSize, StringLen;
+ PBYTE Buffer;
PEVENTLOGRECORD pRec;
- SYSTEMTIME SysTime;
- WCHAR *str;
+ PWSTR str;
UINT i, pos;
- PBYTE Buffer;
- dwRecSize =
- sizeof(EVENTLOGRECORD) + (lstrlenW(ComputerName) +
- lstrlenW(SourceName) + 2) * sizeof(WCHAR);
+ SourceNameSize = (SourceName && SourceName->Buffer) ? SourceName->Length : 0;
+ ComputerNameSize = (ComputerName && ComputerName->Buffer) ? ComputerName->Length : 0;
- if (dwRecSize % 4 != 0)
- dwRecSize += 4 - (dwRecSize % 4);
+ RecSize = sizeof(EVENTLOGRECORD) + /* Add the sizes of the strings, NULL-terminated */
+ SourceNameSize + ComputerNameSize + 2*sizeof(UNICODE_NULL);
- dwRecSize += dwSidLength;
+ /* Align on DWORD boundary for the SID */
+ RecSize = ROUND_UP(RecSize, sizeof(ULONG));
- for (i = 0, str = lpStrings; i < wNumStrings; i++)
+ RecSize += dwSidLength;
+
+ /* Add the sizes for the strings array */
+ ASSERT((pStrings == NULL && wNumStrings == 0) ||
+ (pStrings != NULL && wNumStrings >= 0));
+ for (i = 0, str = pStrings; i < wNumStrings; i++)
{
- dwRecSize += (lstrlenW(str) + 1) * sizeof(WCHAR);
- str += lstrlenW(str) + 1;
+ StringLen = wcslen(str) + 1; // str must be != NULL
+ RecSize += StringLen * sizeof(WCHAR);
+ str += StringLen;
}
- dwRecSize += dwDataSize;
- if (dwRecSize % 4 != 0)
- dwRecSize += 4 - (dwRecSize % 4);
+ /* Add the data size */
+ RecSize += dwDataSize;
- dwRecSize += 4;
+ /* Align on DWORD boundary for the full structure */
+ RecSize = ROUND_UP(RecSize, sizeof(ULONG));
- Buffer = HeapAlloc(MyHeap, HEAP_ZERO_MEMORY, dwRecSize);
+ /* Size of the trailing 'Length' member */
+ RecSize += sizeof(ULONG);
+ Buffer = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, RecSize);
if (!Buffer)
{
- DPRINT1("Can't allocate heap!\n");
+ DPRINT1("Cannot allocate heap!\n");
return NULL;
}
- pRec = (PEVENTLOGRECORD) Buffer;
- pRec->Length = dwRecSize;
+ pRec = (PEVENTLOGRECORD)Buffer;
+ pRec->Length = RecSize;
pRec->Reserved = LOGFILE_SIGNATURE;
- pRec->RecordNumber = dwRecordNumber;
- GetSystemTime(&SysTime);
- SystemTimeToEventTime(&SysTime, &pRec->TimeGenerated);
- SystemTimeToEventTime(&SysTime, &pRec->TimeWritten);
+ /*
+ * Do not assign here any precomputed record number to the event record.
+ * The true record number will be assigned atomically and sequentially in
+ * LogfWriteRecord, so that all the event records will have consistent and
+ * unique record numbers.
+ */
+ pRec->RecordNumber = 0;
+
+ /*
+ * Set the generated time, and temporarily set the written time
+ * with the generated time.
+ */
+ pRec->TimeGenerated = Time;
+ pRec->TimeWritten = Time;
pRec->EventID = dwEventId;
pRec->EventType = wType;
pos = sizeof(EVENTLOGRECORD);
- lstrcpyW((WCHAR *) (Buffer + pos), SourceName);
- pos += (lstrlenW(SourceName) + 1) * sizeof(WCHAR);
- lstrcpyW((WCHAR *) (Buffer + pos), ComputerName);
- pos += (lstrlenW(ComputerName) + 1) * sizeof(WCHAR);
-
- pRec->UserSidOffset = pos;
+ /* NOTE: Equivalents of RtlStringCbCopyUnicodeString calls */
+ if (SourceNameSize)
+ {
+ StringCbCopyNW((PWSTR)(Buffer + pos), SourceNameSize + sizeof(UNICODE_NULL),
+ SourceName->Buffer, SourceNameSize);
+ }
+ pos += SourceNameSize + sizeof(UNICODE_NULL);
+ if (ComputerNameSize)
+ {
+ StringCbCopyNW((PWSTR)(Buffer + pos), ComputerNameSize + sizeof(UNICODE_NULL),
+ ComputerName->Buffer, ComputerNameSize);
+ }
+ pos += ComputerNameSize + sizeof(UNICODE_NULL);
- if (pos % 4 != 0)
- pos += 4 - (pos % 4);
+ /* Align on DWORD boundary for the SID */
+ pos = ROUND_UP(pos, sizeof(ULONG));
+ pRec->UserSidLength = 0;
+ pRec->UserSidOffset = 0;
if (dwSidLength)
{
- CopyMemory(Buffer + pos, lpUserSid, dwSidLength);
+ RtlCopyMemory(Buffer + pos, pUserSid, dwSidLength);
pRec->UserSidLength = dwSidLength;
pRec->UserSidOffset = pos;
pos += dwSidLength;
}
pRec->StringOffset = pos;
- for (i = 0, str = lpStrings; i < wNumStrings; i++)
+ for (i = 0, str = pStrings; i < wNumStrings; i++)
{
- lstrcpyW((WCHAR *) (Buffer + pos), str);
- pos += (lstrlenW(str) + 1) * sizeof(WCHAR);
- str += lstrlenW(str) + 1;
+ StringLen = wcslen(str) + 1; // str must be != NULL
+ StringCchCopyW((PWSTR)(Buffer + pos), StringLen, str);
+ str += StringLen;
+ pos += StringLen * sizeof(WCHAR);
}
pRec->NumStrings = wNumStrings;
- pRec->DataOffset = pos;
+ pRec->DataLength = 0;
+ pRec->DataOffset = 0;
if (dwDataSize)
{
+ RtlCopyMemory(Buffer + pos, pRawData, dwDataSize);
pRec->DataLength = dwDataSize;
- CopyMemory(Buffer + pos, lpRawData, dwDataSize);
+ pRec->DataOffset = pos;
pos += dwDataSize;
}
- if (pos % 4 != 0)
- pos += 4 - (pos % 4);
+ /* Align on DWORD boundary for the full structure */
+ pos = ROUND_UP(pos, sizeof(ULONG));
- *((PDWORD) (Buffer + pos)) = dwRecSize;
+ /* Initialize the trailing 'Length' member */
+ *((PDWORD)(Buffer + pos)) = RecSize;
- *lpRecSize = dwRecSize;
- return Buffer;
+ *pRecSize = RecSize;
+ return pRec;
}
-
VOID
-LogfReportEvent(WORD wType,
- WORD wCategory,
- DWORD dwEventId,
- WORD wNumStrings,
- WCHAR *lpStrings,
- DWORD dwDataSize,
- LPVOID lpRawData)
+LogfReportEvent(USHORT wType,
+ USHORT wCategory,
+ ULONG dwEventId,
+ USHORT wNumStrings,
+ PWSTR pStrings,
+ ULONG dwDataSize,
+ PVOID pRawData)
{
+ NTSTATUS Status;
+ UNICODE_STRING SourceName, ComputerName;
+ PEVENTLOGRECORD LogBuffer;
+ LARGE_INTEGER SystemTime;
+ ULONG Time;
+ SIZE_T RecSize;
+ DWORD dwComputerNameLength;
WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
- DWORD dwComputerNameLength = MAX_COMPUTERNAME_LENGTH + 1;
- PEVENTSOURCE pEventSource = NULL;
- PBYTE logBuffer;
- DWORD lastRec;
- DWORD recSize;
- DWORD dwError;
+ if (!EventLogSource)
+ return;
+
+ RtlInitUnicodeString(&SourceName, EventLogSource->szName);
+
+ dwComputerNameLength = ARRAYSIZE(szComputerName);
if (!GetComputerNameW(szComputerName, &dwComputerNameLength))
- {
- szComputerName[0] = 0;
- }
+ szComputerName[0] = L'\0';
- pEventSource = GetEventSourceByName(L"EventLog");
- if (pEventSource == NULL)
- {
- return;
- }
+ RtlInitUnicodeString(&ComputerName, szComputerName);
- lastRec = LogfGetCurrentRecord(pEventSource->LogFile);
+ NtQuerySystemTime(&SystemTime);
+ RtlTimeToSecondsSince1970(&SystemTime, &Time);
- logBuffer = LogfAllocAndBuildNewRecord(&recSize,
- lastRec,
+ LogBuffer = LogfAllocAndBuildNewRecord(&RecSize,
+ Time,
wType,
wCategory,
dwEventId,
- pEventSource->szName,
- (LPCWSTR)szComputerName,
+ &SourceName,
+ &ComputerName,
0,
NULL,
wNumStrings,
- lpStrings,
+ pStrings,
dwDataSize,
- lpRawData);
+ pRawData);
+ if (LogBuffer == NULL)
+ {
+ DPRINT1("LogfAllocAndBuildNewRecord failed!\n");
+ return;
+ }
- dwError = LogfWriteData(pEventSource->LogFile, recSize, logBuffer);
- if (!dwError)
+ Status = LogfWriteRecord(EventLogSource->LogFile, LogBuffer, RecSize);
+ if (!NT_SUCCESS(Status))
{
- DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource->LogFile->FileName);
+ DPRINT1("ERROR writing to event log `%S' (Status 0x%08lx)\n",
+ EventLogSource->LogFile->LogName, Status);
}
- LogfFreeRecord(logBuffer);
+ LogfFreeRecord(LogBuffer);
}