[EVENTLOG]

- Get rid of MyHeap.
- Continue using safe string functions.
- Allow event logs themselves to be their own source. And store the full list of log sources in the "Sources" registry multi-string value.
- Correctly compute the number of records.
- Correctly return the event number and the write timestamp of reported events.
- Use a helper function for ElfrReportEventW/A and for ElfrReportEventAndSourceW that is now implemented.
- Rewrite the file.c functions using NT-APIs almost exclusively for file operations.
- Modify the logic of LogfReadEvents so that a RecordNumber == 0 in sequential read mode means we need to determine where to start the read operation, depending on whether a forwards-read or a backwards-read is performed. The log handle's CurrentRecord member is therefore initialized to 0 before usage.
- Adjust LogfAllocAndBuildNewRecord to take in input the event generation timestamp.
- Do not "compute" the RecordNumber of the new event in LogfAllocAndBuildNewRecord; it will be consistently assigned by LogfWriteRecord.
- Correctly initialize the OldestRecordNumber to zero for new (empty) logs.
- Perform extensive log validity checks when opening existing logs: log header and EOF record as well as boundary checks.
- Rewrite almost of the functions to support event log wrapping (see bb309026(v=vs.85).aspx ) and splitted records. Now our event logs are not corrupted anymore, and are readable under Windows 2k/xp/2k3/Vista+.
- As a consequence of supporting wrapping event logs we need to iterate through them at loading time in order to locate the valid EOF record (indeed it may happen that the log header is not correctly synced, and its Start/EndOffsets are invalid. The EOF record offsets contain on the other way the correct values).

The file.c fixes are a bit still work-in-progress, but the bulk of the code works. It is extensively tested in situ in my local VM since 2 months now.

CORE-11843 #resolve

svn path=/trunk/; revision=72236
This commit is contained in:
Hermès Bélusca-Maïto 2016-08-16 21:08:15 +00:00
parent d5ac073cbc
commit a2b693dfc4
6 changed files with 1759 additions and 913 deletions

View file

@ -5,6 +5,7 @@
* PURPOSE: Event logging service * PURPOSE: Event logging service
* COPYRIGHT: Copyright 2002 Eric Kohl * COPYRIGHT: Copyright 2002 Eric Kohl
* Copyright 2005 Saveliy Tretiakov * Copyright 2005 Saveliy Tretiakov
* Hermes Belusca-Maito
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -19,7 +20,7 @@
/* GLOBALS ******************************************************************/ /* GLOBALS ******************************************************************/
static VOID CALLBACK ServiceMain(DWORD, LPWSTR *); static VOID CALLBACK ServiceMain(DWORD, LPWSTR*);
static WCHAR ServiceName[] = L"EventLog"; static WCHAR ServiceName[] = L"EventLog";
static SERVICE_TABLE_ENTRYW ServiceTable[2] = static SERVICE_TABLE_ENTRYW ServiceTable[2] =
{ {
@ -30,8 +31,7 @@ static SERVICE_TABLE_ENTRYW ServiceTable[2] =
SERVICE_STATUS ServiceStatus; SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE ServiceStatusHandle; SERVICE_STATUS_HANDLE ServiceStatusHandle;
BOOL onLiveCD = FALSE; // On livecd events will go to debug output only BOOL onLiveCD = FALSE; // On LiveCD events will go to debug output only
HANDLE MyHeap = NULL;
PEVENTSOURCE EventLogSource = NULL; PEVENTSOURCE EventLogSource = NULL;
@ -157,7 +157,8 @@ ReportProductInfoEvent(VOID)
{ {
OSVERSIONINFOW versionInfo; OSVERSIONINFOW versionInfo;
WCHAR szBuffer[512]; WCHAR szBuffer[512];
DWORD dwLength; PWSTR str;
size_t cchRemain;
HKEY hKey; HKEY hKey;
DWORD dwValueLength; DWORD dwValueLength;
DWORD dwType; DWORD dwType;
@ -171,21 +172,32 @@ ReportProductInfoEvent(VOID)
return; return;
ZeroMemory(szBuffer, sizeof(szBuffer)); ZeroMemory(szBuffer, sizeof(szBuffer));
str = szBuffer;
cchRemain = ARRAYSIZE(szBuffer);
/* Write version into the buffer */ /* Write the version number into the buffer */
dwLength = swprintf(szBuffer, StringCchPrintfExW(str, cchRemain,
L"%lu.%lu", &str, &cchRemain, 0,
versionInfo.dwMajorVersion, L"%lu.%lu",
versionInfo.dwMinorVersion) + 1; versionInfo.dwMajorVersion,
versionInfo.dwMinorVersion);
str++;
cchRemain++;
/* Write build number into the buffer */ /* Write the build number into the buffer */
dwLength += swprintf(&szBuffer[dwLength], StringCchPrintfExW(str, cchRemain,
L"%lu", &str, &cchRemain, 0,
versionInfo.dwBuildNumber) + 1; L"%lu",
versionInfo.dwBuildNumber);
str++;
cchRemain++;
/* Write service pack info into the buffer */ /* Write the service pack info into the buffer */
wcscpy(&szBuffer[dwLength], versionInfo.szCSDVersion); StringCchCopyExW(str, cchRemain,
dwLength += wcslen(versionInfo.szCSDVersion) + 1; versionInfo.szCSDVersion,
&str, &cchRemain, 0);
str++;
cchRemain++;
/* Read 'CurrentType' from the registry and write it into the buffer */ /* Read 'CurrentType' from the registry and write it into the buffer */
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
@ -195,12 +207,12 @@ ReportProductInfoEvent(VOID)
&hKey); &hKey);
if (lResult == ERROR_SUCCESS) if (lResult == ERROR_SUCCESS)
{ {
dwValueLength = ARRAYSIZE(szBuffer) - dwLength; dwValueLength = cchRemain;
lResult = RegQueryValueEx(hKey, lResult = RegQueryValueEx(hKey,
L"CurrentType", L"CurrentType",
NULL, NULL,
&dwType, &dwType,
(LPBYTE)&szBuffer[dwLength], (LPBYTE)str,
&dwValueLength); &dwValueLength);
RegCloseKey(hKey); RegCloseKey(hKey);
@ -219,7 +231,7 @@ ReportProductInfoEvent(VOID)
static VOID CALLBACK static VOID CALLBACK
ServiceMain(DWORD argc, ServiceMain(DWORD argc,
LPWSTR *argv) LPWSTR* argv)
{ {
DWORD dwError; DWORD dwError;
@ -267,10 +279,10 @@ ServiceMain(DWORD argc,
static PLOGFILE static PLOGFILE
LoadLogFile(HKEY hKey, WCHAR* LogName) LoadLogFile(HKEY hKey, PWSTR LogName)
{ {
DWORD MaxValueLen, ValueLen, Type, ExpandedLen; DWORD MaxValueLen, ValueLen, Type, ExpandedLen;
WCHAR *Buf = NULL, *Expanded = NULL; PWSTR Buf = NULL, Expanded = NULL;
LONG Result; LONG Result;
PLOGFILE pLogf = NULL; PLOGFILE pLogf = NULL;
UNICODE_STRING FileName; UNICODE_STRING FileName;
@ -288,7 +300,7 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
} }
MaxValueLen = ROUND_DOWN(MaxValueLen, sizeof(WCHAR)); MaxValueLen = ROUND_DOWN(MaxValueLen, sizeof(WCHAR));
Buf = HeapAlloc(MyHeap, 0, MaxValueLen); Buf = HeapAlloc(GetProcessHeap(), 0, MaxValueLen);
if (!Buf) if (!Buf)
{ {
DPRINT1("Cannot allocate heap!\n"); DPRINT1("Cannot allocate heap!\n");
@ -312,11 +324,11 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
MaxValueLen = (wcslen(L"%SystemRoot%\\System32\\Config\\") + MaxValueLen = (wcslen(L"%SystemRoot%\\System32\\Config\\") +
wcslen(LogName) + wcslen(L".evt") + 1) * sizeof(WCHAR); wcslen(LogName) + wcslen(L".evt") + 1) * sizeof(WCHAR);
Expanded = HeapReAlloc(MyHeap, 0, Buf, MaxValueLen); Expanded = HeapReAlloc(GetProcessHeap(), 0, Buf, MaxValueLen);
if (!Expanded) if (!Expanded)
{ {
DPRINT1("Cannot reallocate heap!\n"); DPRINT1("Cannot reallocate heap!\n");
HeapFree(MyHeap, 0, Buf); HeapFree(GetProcessHeap(), 0, Buf);
return NULL; return NULL;
} }
Buf = Expanded; Buf = Expanded;
@ -335,17 +347,17 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
if (Result != ERROR_SUCCESS) if (Result != ERROR_SUCCESS)
{ {
DPRINT1("RegSetValueEx failed: %lu\n", Result); DPRINT1("RegSetValueEx failed: %lu\n", Result);
HeapFree(MyHeap, 0, Buf); HeapFree(GetProcessHeap(), 0, Buf);
return NULL; return NULL;
} }
} }
ExpandedLen = ExpandEnvironmentStringsW(Buf, NULL, 0); ExpandedLen = ExpandEnvironmentStringsW(Buf, NULL, 0);
Expanded = HeapAlloc(MyHeap, 0, ExpandedLen * sizeof(WCHAR)); Expanded = HeapAlloc(GetProcessHeap(), 0, ExpandedLen * sizeof(WCHAR));
if (!Expanded) if (!Expanded)
{ {
DPRINT1("Cannot allocate heap!\n"); DPRINT1("Cannot allocate heap!\n");
HeapFree(MyHeap, 0, Buf); HeapFree(GetProcessHeap(), 0, Buf);
return NULL; return NULL;
} }
@ -354,8 +366,8 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
if (!RtlDosPathNameToNtPathName_U(Expanded, &FileName, NULL, NULL)) if (!RtlDosPathNameToNtPathName_U(Expanded, &FileName, NULL, NULL))
{ {
DPRINT1("Cannot convert path!\n"); DPRINT1("Cannot convert path!\n");
HeapFree(MyHeap, 0, Expanded); HeapFree(GetProcessHeap(), 0, Expanded);
HeapFree(MyHeap, 0, Buf); HeapFree(GetProcessHeap(), 0, Buf);
return NULL; return NULL;
} }
@ -409,8 +421,8 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
DPRINT1("Failed to create %S! (Status %08lx)\n", Expanded, Status); DPRINT1("Failed to create %S! (Status %08lx)\n", Expanded, Status);
} }
HeapFree(MyHeap, 0, Expanded); HeapFree(GetProcessHeap(), 0, Expanded);
HeapFree(MyHeap, 0, Buf); HeapFree(GetProcessHeap(), 0, Buf);
return pLogf; return pLogf;
} }
@ -419,7 +431,7 @@ LoadLogFiles(HKEY eventlogKey)
{ {
LONG Result; LONG Result;
DWORD MaxLognameLen, LognameLen; DWORD MaxLognameLen, LognameLen;
WCHAR *Buf = NULL; PWSTR Buf = NULL;
DWORD dwIndex; DWORD dwIndex;
PLOGFILE pLogFile; PLOGFILE pLogFile;
@ -433,7 +445,7 @@ LoadLogFiles(HKEY eventlogKey)
MaxLognameLen++; MaxLognameLen++;
Buf = HeapAlloc(MyHeap, 0, MaxLognameLen * sizeof(WCHAR)); Buf = HeapAlloc(GetProcessHeap(), 0, MaxLognameLen * sizeof(WCHAR));
if (!Buf) if (!Buf)
{ {
DPRINT1("Error: cannot allocate heap!\n"); DPRINT1("Error: cannot allocate heap!\n");
@ -456,7 +468,7 @@ LoadLogFiles(HKEY eventlogKey)
if (Result != ERROR_SUCCESS) if (Result != ERROR_SUCCESS)
{ {
DPRINT1("Failed to open %S key.\n", Buf); DPRINT1("Failed to open %S key.\n", Buf);
HeapFree(MyHeap, 0, Buf); HeapFree(GetProcessHeap(), 0, Buf);
return FALSE; return FALSE;
} }
@ -477,7 +489,7 @@ LoadLogFiles(HKEY eventlogKey)
dwIndex++; dwIndex++;
} }
HeapFree(MyHeap, 0, Buf); HeapFree(GetProcessHeap(), 0, Buf);
return TRUE; return TRUE;
} }
@ -492,15 +504,6 @@ int wmain(int argc, WCHAR* argv[])
LogfListInitialize(); LogfListInitialize();
InitEventSourceList(); InitEventSourceList();
MyHeap = HeapCreate(0, 1024 * 256, 0);
if (!MyHeap)
{
DPRINT1("FATAL ERROR, can't create heap.\n");
RetCode = 1;
goto bye_bye;
}
GetWindowsDirectoryW(LogPath, MAX_PATH); GetWindowsDirectoryW(LogPath, MAX_PATH);
if (GetDriveTypeW(LogPath) == DRIVE_CDROM) if (GetDriveTypeW(LogPath) == DRIVE_CDROM)
@ -537,9 +540,6 @@ int wmain(int argc, WCHAR* argv[])
bye_bye: bye_bye:
LogfCloseAll(); LogfCloseAll();
if (MyHeap)
HeapDestroy(MyHeap);
return RetCode; return RetCode;
} }
@ -589,7 +589,7 @@ VOID PRINT_HEADER(PEVENTLOGHEADER header)
VOID PRINT_RECORD(PEVENTLOGRECORD pRec) VOID PRINT_RECORD(PEVENTLOGRECORD pRec)
{ {
UINT i; UINT i;
WCHAR *str; PWSTR str;
LARGE_INTEGER SystemTime; LARGE_INTEGER SystemTime;
TIME_FIELDS Time; TIME_FIELDS Time;
@ -642,23 +642,22 @@ VOID PRINT_RECORD(PEVENTLOGRECORD pRec)
DPRINT("DataLength = %lu\n", pRec->DataLength); DPRINT("DataLength = %lu\n", pRec->DataLength);
DPRINT("DataOffset = %lu\n", pRec->DataOffset); DPRINT("DataOffset = %lu\n", pRec->DataOffset);
DPRINT("SourceName: %S\n", (WCHAR *) ((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD))); DPRINT("SourceName: %S\n", (PWSTR)((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD)));
i = (lstrlenW((WCHAR *) ((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD))) + 1) * i = (wcslen((PWSTR)((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD))) + 1) * sizeof(WCHAR);
sizeof(WCHAR);
DPRINT("ComputerName: %S\n", (WCHAR *) ((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD) + i)); DPRINT("ComputerName: %S\n", (PWSTR)((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD) + i));
if (pRec->StringOffset < pRec->Length && pRec->NumStrings) if (pRec->StringOffset < pRec->Length && pRec->NumStrings)
{ {
DPRINT("Strings:\n"); DPRINT("Strings:\n");
str = (WCHAR *) ((ULONG_PTR)pRec + pRec->StringOffset); str = (PWSTR)((ULONG_PTR)pRec + pRec->StringOffset);
for (i = 0; i < pRec->NumStrings; i++) for (i = 0; i < pRec->NumStrings; i++)
{ {
DPRINT("[%u] %S\n", i, str); DPRINT("[%u] %S\n", i, str);
str = str + lstrlenW(str) + 1; str += wcslen(str) + 1;
} }
} }
DPRINT("Length2 = %lu\n", *(PDWORD) ((ULONG_PTR)pRec + pRec->Length - 4)); DPRINT("Length2 = %lu\n", *(PULONG)((ULONG_PTR)pRec + pRec->Length - 4));
} }

View file

@ -79,6 +79,9 @@ typedef struct _EVENTLOGEOF
ULONG RecordSizeEnd; ULONG RecordSizeEnd;
} EVENTLOGEOF, *PEVENTLOGEOF; } EVENTLOGEOF, *PEVENTLOGEOF;
#define EVENTLOGEOF_SIZE_FIXED (5 * sizeof(ULONG))
C_ASSERT(EVENTLOGEOF_SIZE_FIXED == FIELD_OFFSET(EVENTLOGEOF, BeginRecord));
typedef struct _EVENT_OFFSET_INFO typedef struct _EVENT_OFFSET_INFO
{ {
ULONG EventNumber; ULONG EventNumber;
@ -89,6 +92,7 @@ typedef struct _LOGFILE
{ {
HANDLE hFile; HANDLE hFile;
EVENTLOGHEADER Header; EVENTLOGHEADER Header;
ULONG CurrentSize; /* Equivalent to the file size, is <= MaxSize and can be extended to MaxSize if needed */
WCHAR *LogName; WCHAR *LogName;
WCHAR *FileName; WCHAR *FileName;
RTL_RESOURCE Lock; RTL_RESOURCE Lock;
@ -122,7 +126,6 @@ typedef struct _LOGHANDLE
/* eventlog.c */ /* eventlog.c */
extern HANDLE MyHeap;
extern PEVENTSOURCE EventLogSource; extern PEVENTSOURCE EventLogSource;
VOID PRINT_HEADER(PEVENTLOGHEADER header); VOID PRINT_HEADER(PEVENTLOGHEADER header);
@ -153,18 +156,20 @@ PLOGFILE LogfListItemByName(LPCWSTR Name);
DWORD LogfReadEvent(PLOGFILE LogFile, NTSTATUS
DWORD Flags, LogfReadEvents(PLOGFILE LogFile,
DWORD * RecordNumber, ULONG Flags,
DWORD BufSize, PULONG RecordNumber,
PBYTE Buffer, ULONG BufSize,
DWORD * BytesRead, PBYTE Buffer,
DWORD * BytesNeeded, PULONG BytesRead,
BOOL Ansi); PULONG BytesNeeded,
BOOLEAN Ansi);
BOOL LogfWriteData(PLOGFILE LogFile, NTSTATUS
DWORD BufSize, LogfWriteRecord(PLOGFILE LogFile,
PBYTE Buffer); ULONG BufSize, // SIZE_T
PEVENTLOGRECORD Record);
NTSTATUS NTSTATUS
LogfClearFile(PLOGFILE LogFile, LogfClearFile(PLOGFILE LogFile,
@ -175,27 +180,23 @@ LogfBackupFile(PLOGFILE LogFile,
PUNICODE_STRING BackupFileName); PUNICODE_STRING BackupFileName);
NTSTATUS NTSTATUS
LogfCreate(PLOGFILE *Logfile, LogfCreate(PLOGFILE* LogFile,
WCHAR * LogName, PCWSTR LogName,
PUNICODE_STRING FileName, PUNICODE_STRING FileName,
ULONG ulMaxSize, ULONG ulMaxSize,
ULONG ulRetention, ULONG ulRetention,
BOOL Permanent, BOOLEAN Permanent,
BOOL Backup); BOOLEAN Backup);
VOID VOID
LogfClose(PLOGFILE LogFile, LogfClose(PLOGFILE LogFile,
BOOL ForceClose); BOOLEAN ForceClose);
VOID LogfCloseAll(VOID); VOID LogfCloseAll(VOID);
DWORD LogfGetOldestRecord(PLOGFILE LogFile); PEVENTLOGRECORD
DWORD LogfGetCurrentRecord(PLOGFILE LogFile);
PBYTE
LogfAllocAndBuildNewRecord(PULONG lpRecSize, LogfAllocAndBuildNewRecord(PULONG lpRecSize,
ULONG dwRecordNumber, // FIXME! ULONG Time,
USHORT wType, USHORT wType,
USHORT wCategory, USHORT wCategory,
ULONG dwEventId, ULONG dwEventId,
@ -204,13 +205,13 @@ LogfAllocAndBuildNewRecord(PULONG lpRecSize,
ULONG dwSidLength, ULONG dwSidLength,
PSID lpUserSid, PSID lpUserSid,
USHORT wNumStrings, USHORT wNumStrings,
WCHAR* lpStrings, PWSTR lpStrings,
ULONG dwDataSize, ULONG dwDataSize,
PVOID lpRawData); PVOID lpRawData);
static __inline void LogfFreeRecord(LPVOID Rec) static __inline void LogfFreeRecord(PEVENTLOGRECORD Record)
{ {
HeapFree(MyHeap, 0, Rec); HeapFree(GetProcessHeap(), 0, Record);
} }
VOID VOID
@ -218,7 +219,7 @@ LogfReportEvent(USHORT wType,
USHORT wCategory, USHORT wCategory,
ULONG dwEventId, ULONG dwEventId,
USHORT wNumStrings, USHORT wNumStrings,
WCHAR* lpStrings, PWSTR lpStrings,
ULONG dwDataSize, ULONG dwDataSize,
PVOID lpRawData); PVOID lpRawData);

View file

@ -53,38 +53,86 @@ DumpEventSourceList(VOID)
} }
static BOOL
AddNewEventSource(PLOGFILE pLogFile,
PWSTR lpSourceName)
{
PEVENTSOURCE lpEventSource;
lpEventSource = HeapAlloc(GetProcessHeap(), 0,
FIELD_OFFSET(EVENTSOURCE, szName[wcslen(lpSourceName) + 1]));
if (lpEventSource != NULL)
{
wcscpy(lpEventSource->szName, lpSourceName);
lpEventSource->LogFile = pLogFile;
DPRINT("Insert event source: %S\n", lpEventSource->szName);
EnterCriticalSection(&EventSourceListCs);
InsertTailList(&EventSourceListHead,
&lpEventSource->EventSourceListEntry);
LeaveCriticalSection(&EventSourceListCs);
}
return (lpEventSource != NULL);
}
BOOL BOOL
LoadEventSources(HKEY hKey, LoadEventSources(HKEY hKey,
PLOGFILE pLogFile) PLOGFILE pLogFile)
{ {
PEVENTSOURCE lpEventSource; BOOL Success;
DWORD dwMaxSubKeyLength; DWORD dwNumSubKeys, dwMaxSubKeyLength;
DWORD dwEventSourceNameLength; DWORD dwEventSourceNameLength, MaxValueLen;
DWORD dwIndex; DWORD dwIndex;
WCHAR *Buf = NULL; PWSTR Buf = NULL, SourceList = NULL, Source = NULL;
size_t cchRemaining = 0;
LONG Result; LONG Result;
DPRINT("LoadEventSources\n"); DPRINT("LoadEventSources\n");
Result = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, &dwMaxSubKeyLength, NULL, Result = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwNumSubKeys, &dwMaxSubKeyLength,
NULL, NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL, NULL, NULL);
if (Result != ERROR_SUCCESS) if (Result != ERROR_SUCCESS)
{ {
DPRINT1("RegQueryInfoKeyW failed: %lu\n", Result); DPRINT1("RegQueryInfoKeyW failed: %lu\n", Result);
return FALSE; return FALSE;
} }
DPRINT("dwMaxSubKeyLength: %lu\n", dwMaxSubKeyLength);
dwMaxSubKeyLength++; dwMaxSubKeyLength++;
Buf = HeapAlloc(MyHeap, 0, dwMaxSubKeyLength * sizeof(WCHAR)); Buf = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLength * sizeof(WCHAR));
if (!Buf) if (!Buf)
{ {
DPRINT1("Error: cannot allocate heap!\n"); DPRINT1("Error: cannot allocate heap!\n");
return FALSE; return FALSE;
} }
/*
* Allocate a buffer for storing the names of the sources as a REG_MULTI_SZ
* in the registry. Also add the event log as its own source.
* Add a final NULL-terminator.
*/
MaxValueLen = dwNumSubKeys * dwMaxSubKeyLength + wcslen(pLogFile->LogName) + 2;
SourceList = HeapAlloc(GetProcessHeap(), 0, MaxValueLen * sizeof(WCHAR));
if (!SourceList)
{
DPRINT1("Error: cannot allocate heap!\n");
/* It is not dramatic if we cannot create it */
}
else
{
cchRemaining = MaxValueLen;
Source = SourceList;
}
/*
* Enumerate all the subkeys of the event log key, that constitute
* all the possible event sources for this event log. At this point,
* skip the possible existing source having the same name as the
* event log, it will be added later on.
*/
dwEventSourceNameLength = dwMaxSubKeyLength; dwEventSourceNameLength = dwMaxSubKeyLength;
dwIndex = 0; dwIndex = 0;
while (RegEnumKeyExW(hKey, while (RegEnumKeyExW(hKey,
@ -93,28 +141,56 @@ LoadEventSources(HKEY hKey,
&dwEventSourceNameLength, &dwEventSourceNameLength,
NULL, NULL, NULL, NULL) == ERROR_SUCCESS) NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{ {
DPRINT("Event Source: %S\n", Buf); if (_wcsicmp(pLogFile->LogName, Buf) != 0)
lpEventSource = HeapAlloc(MyHeap, 0, sizeof(EVENTSOURCE) + wcslen(Buf) * sizeof(WCHAR));
if (lpEventSource != NULL)
{ {
wcscpy(lpEventSource->szName, Buf); DPRINT("Event Source: %S\n", Buf);
lpEventSource->LogFile = pLogFile; Success = AddNewEventSource(pLogFile, Buf);
if (Success && (Source != NULL))
DPRINT("Insert event source: %S\n", lpEventSource->szName); {
/* Append the event source name and an extra NULL-terminator */
StringCchCopyExW(Source, cchRemaining, Buf, &Source, &cchRemaining, 0);
EnterCriticalSection(&EventSourceListCs); if (cchRemaining > 0)
InsertTailList(&EventSourceListHead, {
&lpEventSource->EventSourceListEntry); *++Source = L'\0';
LeaveCriticalSection(&EventSourceListCs); cchRemaining--;
}
}
} }
dwEventSourceNameLength = dwMaxSubKeyLength; dwEventSourceNameLength = dwMaxSubKeyLength;
dwIndex++; dwIndex++;
} }
HeapFree(MyHeap, 0, Buf); /* Finally, allow the event log itself to be its own source */
DPRINT("Event Source: %S\n", pLogFile->LogName);
Success = AddNewEventSource(pLogFile, pLogFile->LogName);
if (Success && (Source != NULL))
{
/* Append the event source name and an extra NULL-terminator */
StringCchCopyExW(Source, cchRemaining, pLogFile->LogName, &Source, &cchRemaining, 0);
if (cchRemaining > 0)
{
*++Source = L'\0';
cchRemaining--;
}
}
/* Save the list of sources in the registry */
Result = RegSetValueEx(hKey,
L"Sources",
0,
REG_MULTI_SZ,
(LPBYTE)SourceList,
(MaxValueLen - cchRemaining + 1) * sizeof(WCHAR));
if (Result != ERROR_SUCCESS)
{
DPRINT1("RegSetValueEx failed: %lu\n", Result);
}
if (SourceList)
HeapFree(GetProcessHeap(), 0, SourceList);
HeapFree(GetProcessHeap(), 0, Buf);
DumpEventSourceList(); DumpEventSourceList();

File diff suppressed because it is too large Load diff

View file

@ -107,8 +107,8 @@ NTSTATUS ProcessPortMessage(VOID)
{ {
IO_ERROR_LPC Request; IO_ERROR_LPC Request;
PIO_ERROR_LOG_MESSAGE Message; PIO_ERROR_LOG_MESSAGE Message;
ULONG Time;
PEVENTLOGRECORD pRec; PEVENTLOGRECORD pRec;
ULONG ulRecNum;
DWORD dwRecSize; DWORD dwRecSize;
NTSTATUS Status; NTSTATUS Status;
PLOGFILE SystemLog = NULL; PLOGFILE SystemLog = NULL;
@ -147,30 +147,32 @@ NTSTATUS ProcessPortMessage(VOID)
else if (Request.Header.u2.s2.Type == LPC_DATAGRAM) else if (Request.Header.u2.s2.Type == LPC_DATAGRAM)
{ {
DPRINT("Received datagram\n"); DPRINT("Received datagram\n");
Message = (PIO_ERROR_LOG_MESSAGE) & Request.Message; // Message = (PIO_ERROR_LOG_MESSAGE)&Request.Message;
ulRecNum = SystemLog ? SystemLog->Header.CurrentRecordNumber : 0; Message = &Request.Message;
if (!GetComputerNameW(szComputerName, &dwComputerNameLength)) if (!GetComputerNameW(szComputerName, &dwComputerNameLength))
{ {
szComputerName[0] = L'\0'; szComputerName[0] = L'\0';
} }
RtlTimeToSecondsSince1970(&Message->TimeStamp, &Time);
// TODO: Log more information?? // TODO: Log more information??
pRec = (PEVENTLOGRECORD) LogfAllocAndBuildNewRecord( pRec = LogfAllocAndBuildNewRecord(
&dwRecSize, &dwRecSize,
ulRecNum, // FIXME! Time,
Message->Type, Message->Type,
Message->EntryData.EventCategory, Message->EntryData.EventCategory,
Message->EntryData.ErrorCode, Message->EntryData.ErrorCode,
(WCHAR *) ((ULONG_PTR)Message + Message->DriverNameOffset), // FIXME: Use DriverNameLength too! (PWSTR)((ULONG_PTR)Message + Message->DriverNameOffset), // FIXME: Use DriverNameLength too!
szComputerName, szComputerName,
0, 0,
NULL, NULL,
Message->EntryData.NumberOfStrings, Message->EntryData.NumberOfStrings,
(WCHAR *) ((ULONG_PTR)Message + Message->EntryData.StringOffset), (PWSTR)((ULONG_PTR)Message + Message->EntryData.StringOffset),
Message->EntryData.DumpDataSize, Message->EntryData.DumpDataSize,
(LPVOID) ((ULONG_PTR)Message + FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData))); (PVOID)((ULONG_PTR)Message + FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)));
if (pRec == NULL) if (pRec == NULL)
{ {
@ -186,10 +188,12 @@ NTSTATUS ProcessPortMessage(VOID)
if (!onLiveCD && SystemLog) if (!onLiveCD && SystemLog)
{ {
if (!LogfWriteData(SystemLog, dwRecSize, (PBYTE) pRec)) Status = LogfWriteRecord(SystemLog, dwRecSize, pRec);
DPRINT("LogfWriteData failed!\n"); if (!NT_SUCCESS(Status))
else {
DPRINT("Data written to Log!\n"); DPRINT1("ERROR WRITING TO EventLog %S (Status 0x%08lx)\n",
SystemLog->FileName, Status);
}
} }
LogfFreeRecord(pRec); LogfFreeRecord(pRec);

View file

@ -15,7 +15,7 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
LIST_ENTRY LogHandleListHead; static LIST_ENTRY LogHandleListHead;
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
@ -77,6 +77,8 @@ ElfCreateEventLogHandle(PLOGHANDLE* LogHandle,
StringCchCopy(lpLogHandle->szName, i, LogName->Buffer); StringCchCopy(lpLogHandle->szName, i, LogName->Buffer);
/* Get the number of Log Files the EventLog service found */ /* Get the number of Log Files the EventLog service found */
// NOTE: We could just as well loop only once within the list of logs
// and retrieve what the code below that calls LogfListItemByIndex, does!!
LogsActive = LogfListItemCount(); LogsActive = LogfListItemCount();
if (LogsActive == 0) if (LogsActive == 0)
{ {
@ -114,7 +116,6 @@ ElfCreateEventLogHandle(PLOGHANDLE* LogHandle,
if (_wcsicmp(LogName->Buffer, currentLogFile->LogName) == 0) if (_wcsicmp(LogName->Buffer, currentLogFile->LogName) == 0)
{ {
lpLogHandle->LogFile = currentLogFile; lpLogHandle->LogFile = currentLogFile;
lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile);
break; break;
} }
} }
@ -123,16 +124,16 @@ ElfCreateEventLogHandle(PLOGHANDLE* LogHandle,
if (lpLogHandle->LogFile == NULL) if (lpLogHandle->LogFile == NULL)
{ {
lpLogHandle->LogFile = LogfListItemByName(L"Application"); lpLogHandle->LogFile = LogfListItemByName(L"Application");
if (lpLogHandle->LogFile == NULL) if (lpLogHandle->LogFile == NULL)
{ {
DPRINT1("Application log is missing!\n"); DPRINT1("Application log is missing!\n");
Status = STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
goto Done; goto Done;
} }
lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile);
} }
/* Reset the current record */
lpLogHandle->CurrentRecord = 0;
} }
if (!lpLogHandle->LogFile) if (!lpLogHandle->LogFile)
@ -189,8 +190,8 @@ ElfCreateBackupLogHandle(PLOGHANDLE* LogHandle,
/* Set the backup flag */ /* Set the backup flag */
lpLogHandle->Flags |= LOG_HANDLE_BACKUP_FILE; lpLogHandle->Flags |= LOG_HANDLE_BACKUP_FILE;
/* Get the current record */ /* Reset the current record */
lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile); lpLogHandle->CurrentRecord = 0;
Done: Done:
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
@ -334,8 +335,17 @@ ElfrNumberOfRecords(
lpLogFile->Header.OldestRecordNumber, lpLogFile->Header.OldestRecordNumber,
lpLogFile->Header.CurrentRecordNumber); lpLogFile->Header.CurrentRecordNumber);
*NumberOfRecords = lpLogFile->Header.CurrentRecordNumber - if (lpLogFile->Header.OldestRecordNumber == 0)
lpLogFile->Header.OldestRecordNumber; {
/* OldestRecordNumber == 0 when the log is empty */
*NumberOfRecords = 0;
}
else
{
/* The log contains events */
*NumberOfRecords = lpLogFile->Header.CurrentRecordNumber -
lpLogFile->Header.OldestRecordNumber;
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -356,7 +366,7 @@ ElfrOldestRecord(
if (!OldestRecordNumber) if (!OldestRecordNumber)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
*OldestRecordNumber = LogfGetOldestRecord(lpLogHandle->LogFile); *OldestRecordNumber = lpLogHandle->LogFile->Header.OldestRecordNumber;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -466,9 +476,9 @@ ElfrReadELW(
PULONG NumberOfBytesRead, PULONG NumberOfBytesRead,
PULONG MinNumberOfBytesNeeded) PULONG MinNumberOfBytesNeeded)
{ {
NTSTATUS Status;
PLOGHANDLE lpLogHandle; PLOGHANDLE lpLogHandle;
DWORD dwError; ULONG RecordNumber;
DWORD RecordNumber;
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
if (!lpLogHandle) if (!lpLogHandle)
@ -482,12 +492,12 @@ ElfrReadELW(
{ {
RecordNumber = lpLogHandle->CurrentRecord; RecordNumber = lpLogHandle->CurrentRecord;
} }
else else // (ReadFlags & EVENTLOG_SEEK_READ)
{ {
RecordNumber = RecordOffset; RecordNumber = RecordOffset;
} }
dwError = LogfReadEvent(lpLogHandle->LogFile, Status = LogfReadEvents(lpLogHandle->LogFile,
ReadFlags, ReadFlags,
&RecordNumber, &RecordNumber,
NumberOfBytesToRead, NumberOfBytesToRead,
@ -497,27 +507,24 @@ ElfrReadELW(
FALSE); FALSE);
/* Update the handle's CurrentRecord if success */ /* Update the handle's CurrentRecord if success */
if (dwError == ERROR_SUCCESS) if (NT_SUCCESS(Status))
{ {
lpLogHandle->CurrentRecord = RecordNumber; lpLogHandle->CurrentRecord = RecordNumber;
} }
/* HACK!!! */ return Status;
if (dwError == ERROR_HANDLE_EOF)
return STATUS_END_OF_FILE;
return I_RpcMapWin32Status(dwError);
} }
/* Function 11 */ /* Helper function for ElfrReportEventW/A and ElfrReportEventAndSourceW */
NTSTATUS NTSTATUS
ElfrReportEventW( ElfrIntReportEventW(
IELF_HANDLE LogHandle, IELF_HANDLE LogHandle,
ULONG Time, ULONG Time,
USHORT EventType, USHORT EventType,
USHORT EventCategory, USHORT EventCategory,
ULONG EventID, ULONG EventID,
PRPC_UNICODE_STRING SourceName OPTIONAL,
USHORT NumStrings, USHORT NumStrings,
ULONG DataSize, ULONG DataSize,
PRPC_UNICODE_STRING ComputerName, PRPC_UNICODE_STRING ComputerName,
@ -528,16 +535,14 @@ ElfrReportEventW(
PULONG RecordNumber, PULONG RecordNumber,
PULONG TimeWritten) PULONG TimeWritten)
{ {
USHORT i; NTSTATUS Status;
PBYTE LogBuffer;
PLOGHANDLE lpLogHandle; PLOGHANDLE lpLogHandle;
DWORD lastRec; PEVENTLOGRECORD LogBuffer;
DWORD recSize; USHORT i;
DWORD dwStringsSize = 0; ULONG recSize;
DWORD dwUserSidLength = 0; ULONG dwStringsSize = 0;
DWORD dwError = ERROR_SUCCESS; ULONG dwUserSidLength = 0;
WCHAR *lpStrings; PWSTR lpStrings, str;
int pos = 0;
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
if (!lpLogHandle) if (!lpLogHandle)
@ -547,8 +552,6 @@ ElfrReportEventW(
if (Flags) if (Flags)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
lastRec = LogfGetCurrentRecord(lpLogHandle->LogFile);
for (i = 0; i < NumStrings; i++) for (i = 0; i < NumStrings; i++)
{ {
switch (EventType) switch (EventType)
@ -591,22 +594,26 @@ ElfrReportEventW(
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
str = lpStrings;
for (i = 0; i < NumStrings; i++) for (i = 0; i < NumStrings; i++)
{ {
RtlCopyMemory(lpStrings + pos, Strings[i]->Buffer, Strings[i]->Length); RtlCopyMemory(str, Strings[i]->Buffer, Strings[i]->Length);
pos += Strings[i]->Length / sizeof(WCHAR); str += Strings[i]->Length / sizeof(WCHAR);
lpStrings[pos] = UNICODE_NULL; *str = UNICODE_NULL;
pos += sizeof(UNICODE_NULL) / sizeof(WCHAR); str++;
} }
if (UserSID) if (UserSID)
dwUserSidLength = FIELD_OFFSET(SID, SubAuthority[UserSID->SubAuthorityCount]); dwUserSidLength = FIELD_OFFSET(SID, SubAuthority[UserSID->SubAuthorityCount]);
LogBuffer = LogfAllocAndBuildNewRecord(&recSize, LogBuffer = LogfAllocAndBuildNewRecord(&recSize,
lastRec, // FIXME! Time,
EventType, EventType,
EventCategory, EventCategory,
EventID, EventID,
lpLogHandle->szName, (SourceName && SourceName->Buffer)
? SourceName->Buffer
: lpLogHandle->szName,
ComputerName->Buffer, ComputerName->Buffer,
dwUserSidLength, dwUserSidLength,
UserSID, UserSID,
@ -615,17 +622,64 @@ ElfrReportEventW(
DataSize, DataSize,
Data); Data);
dwError = LogfWriteData(lpLogHandle->LogFile, recSize, LogBuffer); Status = LogfWriteRecord(lpLogHandle->LogFile, recSize, LogBuffer);
if (!dwError) if (!NT_SUCCESS(Status))
{ {
DPRINT1("ERROR WRITING TO EventLog %S\n", lpLogHandle->LogFile->FileName); DPRINT1("ERROR WRITING TO EventLog %S (Status 0x%08lx)\n",
lpLogHandle->LogFile->FileName, Status);
}
if (NT_SUCCESS(Status))
{
/* Retrieve the two fields that were set by LogfWriteRecord into the record */
if (RecordNumber)
*RecordNumber = LogBuffer->RecordNumber;
if (TimeWritten)
*TimeWritten = LogBuffer->TimeWritten;
} }
LogfFreeRecord(LogBuffer); LogfFreeRecord(LogBuffer);
HeapFree(GetProcessHeap(), 0, lpStrings); HeapFree(GetProcessHeap(), 0, lpStrings);
return I_RpcMapWin32Status(dwError); return Status;
}
/* Function 11 */
NTSTATUS
ElfrReportEventW(
IELF_HANDLE LogHandle,
ULONG Time,
USHORT EventType,
USHORT EventCategory,
ULONG EventID,
USHORT NumStrings,
ULONG DataSize,
PRPC_UNICODE_STRING ComputerName,
PRPC_SID UserSID,
PRPC_UNICODE_STRING Strings[],
PBYTE Data,
USHORT Flags,
PULONG RecordNumber,
PULONG TimeWritten)
{
/* Call the helper function. The event source is provided via the log handle. */
return ElfrIntReportEventW(LogHandle,
Time,
EventType,
EventCategory,
EventID,
NULL,
NumStrings,
DataSize,
ComputerName,
UserSID,
Strings,
Data,
Flags,
RecordNumber,
TimeWritten);
} }
@ -813,9 +867,9 @@ ElfrReadELA(
PULONG NumberOfBytesRead, PULONG NumberOfBytesRead,
PULONG MinNumberOfBytesNeeded) PULONG MinNumberOfBytesNeeded)
{ {
NTSTATUS Status;
PLOGHANDLE lpLogHandle; PLOGHANDLE lpLogHandle;
DWORD dwError; ULONG RecordNumber;
DWORD RecordNumber;
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
if (!lpLogHandle) if (!lpLogHandle)
@ -829,12 +883,12 @@ ElfrReadELA(
{ {
RecordNumber = lpLogHandle->CurrentRecord; RecordNumber = lpLogHandle->CurrentRecord;
} }
else else // (ReadFlags & EVENTLOG_SEEK_READ)
{ {
RecordNumber = RecordOffset; RecordNumber = RecordOffset;
} }
dwError = LogfReadEvent(lpLogHandle->LogFile, Status = LogfReadEvents(lpLogHandle->LogFile,
ReadFlags, ReadFlags,
&RecordNumber, &RecordNumber,
NumberOfBytesToRead, NumberOfBytesToRead,
@ -844,16 +898,12 @@ ElfrReadELA(
TRUE); TRUE);
/* Update the handle's CurrentRecord if success */ /* Update the handle's CurrentRecord if success */
if (dwError == ERROR_SUCCESS) if (NT_SUCCESS(Status))
{ {
lpLogHandle->CurrentRecord = RecordNumber; lpLogHandle->CurrentRecord = RecordNumber;
} }
/* HACK!!! */ return Status;
if (dwError == ERROR_HANDLE_EOF)
return STATUS_END_OF_FILE;
return I_RpcMapWin32Status(dwError);
} }
@ -904,7 +954,7 @@ ElfrReportEventA(
if (NumStrings != 0) if (NumStrings != 0)
{ {
StringsArrayW = HeapAlloc(MyHeap, StringsArrayW = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
NumStrings * sizeof(PUNICODE_STRING)); NumStrings * sizeof(PUNICODE_STRING));
if (StringsArrayW == NULL) if (StringsArrayW == NULL)
@ -917,7 +967,7 @@ ElfrReportEventA(
{ {
if (Strings[i] != NULL) if (Strings[i] != NULL)
{ {
StringsArrayW[i] = HeapAlloc(MyHeap, StringsArrayW[i] = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
sizeof(UNICODE_STRING)); sizeof(UNICODE_STRING));
if (StringsArrayW[i] == NULL) if (StringsArrayW[i] == NULL)
@ -964,12 +1014,12 @@ Done:
if (StringsArrayW[i]->Buffer) if (StringsArrayW[i]->Buffer)
{ {
RtlFreeUnicodeString(StringsArrayW[i]); RtlFreeUnicodeString(StringsArrayW[i]);
HeapFree(MyHeap, 0, StringsArrayW[i]); HeapFree(GetProcessHeap(), 0, StringsArrayW[i]);
} }
} }
} }
HeapFree(MyHeap, 0, StringsArrayW); HeapFree(GetProcessHeap(), 0, StringsArrayW);
} }
RtlFreeUnicodeString(&ComputerNameW); RtlFreeUnicodeString(&ComputerNameW);
@ -1027,24 +1077,24 @@ ElfrGetLogInformation(
switch (InfoLevel) switch (InfoLevel)
{ {
case EVENTLOG_FULL_INFO: case EVENTLOG_FULL_INFO:
{
LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer;
*pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION))
{ {
LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer; Status = STATUS_BUFFER_TOO_SMALL;
break;
*pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
/*
* FIXME. To check whether an event log is "full" one needs
* to compare its current size with respect to the maximum
* size threshold "MaxSize" contained in its header.
*/
efi->dwFull = 0;
} }
/*
* FIXME. To check whether an event log is "full" one needs
* to compare its current size with respect to the maximum
* size threshold "MaxSize" contained in its header.
*/
efi->dwFull = 0;
break; break;
}
default: default:
Status = STATUS_INVALID_LEVEL; Status = STATUS_INVALID_LEVEL;
@ -1060,6 +1110,12 @@ NTSTATUS
ElfrFlushEL( ElfrFlushEL(
IELF_HANDLE LogHandle) IELF_HANDLE LogHandle)
{ {
PLOGHANDLE lpLogHandle;
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
if (!lpLogHandle)
return STATUS_INVALID_HANDLE;
UNIMPLEMENTED; UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
@ -1084,8 +1140,22 @@ ElfrReportEventAndSourceW(
PULONG RecordNumber, PULONG RecordNumber,
PULONG TimeWritten) PULONG TimeWritten)
{ {
UNIMPLEMENTED; /* Call the helper function. The event source is specified by the caller. */
return STATUS_NOT_IMPLEMENTED; return ElfrIntReportEventW(LogHandle,
Time,
EventType,
EventCategory,
EventID,
SourceName,
NumStrings,
DataSize,
ComputerName,
UserSID,
Strings,
Data,
Flags,
RecordNumber,
TimeWritten);
} }