mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 19:45:39 +00:00
[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:
parent
d5ac073cbc
commit
a2b693dfc4
6 changed files with 1759 additions and 913 deletions
|
@ -5,6 +5,7 @@
|
|||
* PURPOSE: Event logging service
|
||||
* COPYRIGHT: Copyright 2002 Eric Kohl
|
||||
* Copyright 2005 Saveliy Tretiakov
|
||||
* Hermes Belusca-Maito
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -19,7 +20,7 @@
|
|||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
static VOID CALLBACK ServiceMain(DWORD, LPWSTR *);
|
||||
static VOID CALLBACK ServiceMain(DWORD, LPWSTR*);
|
||||
static WCHAR ServiceName[] = L"EventLog";
|
||||
static SERVICE_TABLE_ENTRYW ServiceTable[2] =
|
||||
{
|
||||
|
@ -30,8 +31,7 @@ static SERVICE_TABLE_ENTRYW ServiceTable[2] =
|
|||
SERVICE_STATUS ServiceStatus;
|
||||
SERVICE_STATUS_HANDLE ServiceStatusHandle;
|
||||
|
||||
BOOL onLiveCD = FALSE; // On livecd events will go to debug output only
|
||||
HANDLE MyHeap = NULL;
|
||||
BOOL onLiveCD = FALSE; // On LiveCD events will go to debug output only
|
||||
|
||||
PEVENTSOURCE EventLogSource = NULL;
|
||||
|
||||
|
@ -157,7 +157,8 @@ ReportProductInfoEvent(VOID)
|
|||
{
|
||||
OSVERSIONINFOW versionInfo;
|
||||
WCHAR szBuffer[512];
|
||||
DWORD dwLength;
|
||||
PWSTR str;
|
||||
size_t cchRemain;
|
||||
HKEY hKey;
|
||||
DWORD dwValueLength;
|
||||
DWORD dwType;
|
||||
|
@ -171,21 +172,32 @@ ReportProductInfoEvent(VOID)
|
|||
return;
|
||||
|
||||
ZeroMemory(szBuffer, sizeof(szBuffer));
|
||||
str = szBuffer;
|
||||
cchRemain = ARRAYSIZE(szBuffer);
|
||||
|
||||
/* Write version into the buffer */
|
||||
dwLength = swprintf(szBuffer,
|
||||
/* Write the version number into the buffer */
|
||||
StringCchPrintfExW(str, cchRemain,
|
||||
&str, &cchRemain, 0,
|
||||
L"%lu.%lu",
|
||||
versionInfo.dwMajorVersion,
|
||||
versionInfo.dwMinorVersion) + 1;
|
||||
versionInfo.dwMinorVersion);
|
||||
str++;
|
||||
cchRemain++;
|
||||
|
||||
/* Write build number into the buffer */
|
||||
dwLength += swprintf(&szBuffer[dwLength],
|
||||
/* Write the build number into the buffer */
|
||||
StringCchPrintfExW(str, cchRemain,
|
||||
&str, &cchRemain, 0,
|
||||
L"%lu",
|
||||
versionInfo.dwBuildNumber) + 1;
|
||||
versionInfo.dwBuildNumber);
|
||||
str++;
|
||||
cchRemain++;
|
||||
|
||||
/* Write service pack info into the buffer */
|
||||
wcscpy(&szBuffer[dwLength], versionInfo.szCSDVersion);
|
||||
dwLength += wcslen(versionInfo.szCSDVersion) + 1;
|
||||
/* Write the service pack info into the buffer */
|
||||
StringCchCopyExW(str, cchRemain,
|
||||
versionInfo.szCSDVersion,
|
||||
&str, &cchRemain, 0);
|
||||
str++;
|
||||
cchRemain++;
|
||||
|
||||
/* Read 'CurrentType' from the registry and write it into the buffer */
|
||||
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
|
@ -195,12 +207,12 @@ ReportProductInfoEvent(VOID)
|
|||
&hKey);
|
||||
if (lResult == ERROR_SUCCESS)
|
||||
{
|
||||
dwValueLength = ARRAYSIZE(szBuffer) - dwLength;
|
||||
dwValueLength = cchRemain;
|
||||
lResult = RegQueryValueEx(hKey,
|
||||
L"CurrentType",
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&szBuffer[dwLength],
|
||||
(LPBYTE)str,
|
||||
&dwValueLength);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
@ -219,7 +231,7 @@ ReportProductInfoEvent(VOID)
|
|||
|
||||
static VOID CALLBACK
|
||||
ServiceMain(DWORD argc,
|
||||
LPWSTR *argv)
|
||||
LPWSTR* argv)
|
||||
{
|
||||
DWORD dwError;
|
||||
|
||||
|
@ -267,10 +279,10 @@ ServiceMain(DWORD argc,
|
|||
|
||||
|
||||
static PLOGFILE
|
||||
LoadLogFile(HKEY hKey, WCHAR* LogName)
|
||||
LoadLogFile(HKEY hKey, PWSTR LogName)
|
||||
{
|
||||
DWORD MaxValueLen, ValueLen, Type, ExpandedLen;
|
||||
WCHAR *Buf = NULL, *Expanded = NULL;
|
||||
PWSTR Buf = NULL, Expanded = NULL;
|
||||
LONG Result;
|
||||
PLOGFILE pLogf = NULL;
|
||||
UNICODE_STRING FileName;
|
||||
|
@ -288,7 +300,7 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
|
|||
}
|
||||
|
||||
MaxValueLen = ROUND_DOWN(MaxValueLen, sizeof(WCHAR));
|
||||
Buf = HeapAlloc(MyHeap, 0, MaxValueLen);
|
||||
Buf = HeapAlloc(GetProcessHeap(), 0, MaxValueLen);
|
||||
if (!Buf)
|
||||
{
|
||||
DPRINT1("Cannot allocate heap!\n");
|
||||
|
@ -312,11 +324,11 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
|
|||
MaxValueLen = (wcslen(L"%SystemRoot%\\System32\\Config\\") +
|
||||
wcslen(LogName) + wcslen(L".evt") + 1) * sizeof(WCHAR);
|
||||
|
||||
Expanded = HeapReAlloc(MyHeap, 0, Buf, MaxValueLen);
|
||||
Expanded = HeapReAlloc(GetProcessHeap(), 0, Buf, MaxValueLen);
|
||||
if (!Expanded)
|
||||
{
|
||||
DPRINT1("Cannot reallocate heap!\n");
|
||||
HeapFree(MyHeap, 0, Buf);
|
||||
HeapFree(GetProcessHeap(), 0, Buf);
|
||||
return NULL;
|
||||
}
|
||||
Buf = Expanded;
|
||||
|
@ -335,17 +347,17 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
|
|||
if (Result != ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT1("RegSetValueEx failed: %lu\n", Result);
|
||||
HeapFree(MyHeap, 0, Buf);
|
||||
HeapFree(GetProcessHeap(), 0, Buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ExpandedLen = ExpandEnvironmentStringsW(Buf, NULL, 0);
|
||||
Expanded = HeapAlloc(MyHeap, 0, ExpandedLen * sizeof(WCHAR));
|
||||
Expanded = HeapAlloc(GetProcessHeap(), 0, ExpandedLen * sizeof(WCHAR));
|
||||
if (!Expanded)
|
||||
{
|
||||
DPRINT1("Cannot allocate heap!\n");
|
||||
HeapFree(MyHeap, 0, Buf);
|
||||
HeapFree(GetProcessHeap(), 0, Buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -354,8 +366,8 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
|
|||
if (!RtlDosPathNameToNtPathName_U(Expanded, &FileName, NULL, NULL))
|
||||
{
|
||||
DPRINT1("Cannot convert path!\n");
|
||||
HeapFree(MyHeap, 0, Expanded);
|
||||
HeapFree(MyHeap, 0, Buf);
|
||||
HeapFree(GetProcessHeap(), 0, Expanded);
|
||||
HeapFree(GetProcessHeap(), 0, Buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -409,8 +421,8 @@ LoadLogFile(HKEY hKey, WCHAR* LogName)
|
|||
DPRINT1("Failed to create %S! (Status %08lx)\n", Expanded, Status);
|
||||
}
|
||||
|
||||
HeapFree(MyHeap, 0, Expanded);
|
||||
HeapFree(MyHeap, 0, Buf);
|
||||
HeapFree(GetProcessHeap(), 0, Expanded);
|
||||
HeapFree(GetProcessHeap(), 0, Buf);
|
||||
return pLogf;
|
||||
}
|
||||
|
||||
|
@ -419,7 +431,7 @@ LoadLogFiles(HKEY eventlogKey)
|
|||
{
|
||||
LONG Result;
|
||||
DWORD MaxLognameLen, LognameLen;
|
||||
WCHAR *Buf = NULL;
|
||||
PWSTR Buf = NULL;
|
||||
DWORD dwIndex;
|
||||
PLOGFILE pLogFile;
|
||||
|
||||
|
@ -433,7 +445,7 @@ LoadLogFiles(HKEY eventlogKey)
|
|||
|
||||
MaxLognameLen++;
|
||||
|
||||
Buf = HeapAlloc(MyHeap, 0, MaxLognameLen * sizeof(WCHAR));
|
||||
Buf = HeapAlloc(GetProcessHeap(), 0, MaxLognameLen * sizeof(WCHAR));
|
||||
if (!Buf)
|
||||
{
|
||||
DPRINT1("Error: cannot allocate heap!\n");
|
||||
|
@ -456,7 +468,7 @@ LoadLogFiles(HKEY eventlogKey)
|
|||
if (Result != ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT1("Failed to open %S key.\n", Buf);
|
||||
HeapFree(MyHeap, 0, Buf);
|
||||
HeapFree(GetProcessHeap(), 0, Buf);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -477,7 +489,7 @@ LoadLogFiles(HKEY eventlogKey)
|
|||
dwIndex++;
|
||||
}
|
||||
|
||||
HeapFree(MyHeap, 0, Buf);
|
||||
HeapFree(GetProcessHeap(), 0, Buf);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -492,15 +504,6 @@ int wmain(int argc, WCHAR* argv[])
|
|||
LogfListInitialize();
|
||||
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);
|
||||
|
||||
if (GetDriveTypeW(LogPath) == DRIVE_CDROM)
|
||||
|
@ -537,9 +540,6 @@ int wmain(int argc, WCHAR* argv[])
|
|||
bye_bye:
|
||||
LogfCloseAll();
|
||||
|
||||
if (MyHeap)
|
||||
HeapDestroy(MyHeap);
|
||||
|
||||
return RetCode;
|
||||
}
|
||||
|
||||
|
@ -589,7 +589,7 @@ VOID PRINT_HEADER(PEVENTLOGHEADER header)
|
|||
VOID PRINT_RECORD(PEVENTLOGRECORD pRec)
|
||||
{
|
||||
UINT i;
|
||||
WCHAR *str;
|
||||
PWSTR str;
|
||||
LARGE_INTEGER SystemTime;
|
||||
TIME_FIELDS Time;
|
||||
|
||||
|
@ -642,23 +642,22 @@ VOID PRINT_RECORD(PEVENTLOGRECORD pRec)
|
|||
DPRINT("DataLength = %lu\n", pRec->DataLength);
|
||||
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) *
|
||||
sizeof(WCHAR);
|
||||
i = (wcslen((PWSTR)((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD))) + 1) * 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)
|
||||
{
|
||||
DPRINT("Strings:\n");
|
||||
str = (WCHAR *) ((ULONG_PTR)pRec + pRec->StringOffset);
|
||||
str = (PWSTR)((ULONG_PTR)pRec + pRec->StringOffset);
|
||||
for (i = 0; i < pRec->NumStrings; i++)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -79,6 +79,9 @@ typedef struct _EVENTLOGEOF
|
|||
ULONG RecordSizeEnd;
|
||||
} EVENTLOGEOF, *PEVENTLOGEOF;
|
||||
|
||||
#define EVENTLOGEOF_SIZE_FIXED (5 * sizeof(ULONG))
|
||||
C_ASSERT(EVENTLOGEOF_SIZE_FIXED == FIELD_OFFSET(EVENTLOGEOF, BeginRecord));
|
||||
|
||||
typedef struct _EVENT_OFFSET_INFO
|
||||
{
|
||||
ULONG EventNumber;
|
||||
|
@ -89,6 +92,7 @@ typedef struct _LOGFILE
|
|||
{
|
||||
HANDLE hFile;
|
||||
EVENTLOGHEADER Header;
|
||||
ULONG CurrentSize; /* Equivalent to the file size, is <= MaxSize and can be extended to MaxSize if needed */
|
||||
WCHAR *LogName;
|
||||
WCHAR *FileName;
|
||||
RTL_RESOURCE Lock;
|
||||
|
@ -122,7 +126,6 @@ typedef struct _LOGHANDLE
|
|||
|
||||
|
||||
/* eventlog.c */
|
||||
extern HANDLE MyHeap;
|
||||
extern PEVENTSOURCE EventLogSource;
|
||||
|
||||
VOID PRINT_HEADER(PEVENTLOGHEADER header);
|
||||
|
@ -153,18 +156,20 @@ PLOGFILE LogfListItemByName(LPCWSTR Name);
|
|||
|
||||
|
||||
|
||||
DWORD LogfReadEvent(PLOGFILE LogFile,
|
||||
DWORD Flags,
|
||||
DWORD * RecordNumber,
|
||||
DWORD BufSize,
|
||||
NTSTATUS
|
||||
LogfReadEvents(PLOGFILE LogFile,
|
||||
ULONG Flags,
|
||||
PULONG RecordNumber,
|
||||
ULONG BufSize,
|
||||
PBYTE Buffer,
|
||||
DWORD * BytesRead,
|
||||
DWORD * BytesNeeded,
|
||||
BOOL Ansi);
|
||||
PULONG BytesRead,
|
||||
PULONG BytesNeeded,
|
||||
BOOLEAN Ansi);
|
||||
|
||||
BOOL LogfWriteData(PLOGFILE LogFile,
|
||||
DWORD BufSize,
|
||||
PBYTE Buffer);
|
||||
NTSTATUS
|
||||
LogfWriteRecord(PLOGFILE LogFile,
|
||||
ULONG BufSize, // SIZE_T
|
||||
PEVENTLOGRECORD Record);
|
||||
|
||||
NTSTATUS
|
||||
LogfClearFile(PLOGFILE LogFile,
|
||||
|
@ -175,27 +180,23 @@ LogfBackupFile(PLOGFILE LogFile,
|
|||
PUNICODE_STRING BackupFileName);
|
||||
|
||||
NTSTATUS
|
||||
LogfCreate(PLOGFILE *Logfile,
|
||||
WCHAR * LogName,
|
||||
LogfCreate(PLOGFILE* LogFile,
|
||||
PCWSTR LogName,
|
||||
PUNICODE_STRING FileName,
|
||||
ULONG ulMaxSize,
|
||||
ULONG ulRetention,
|
||||
BOOL Permanent,
|
||||
BOOL Backup);
|
||||
BOOLEAN Permanent,
|
||||
BOOLEAN Backup);
|
||||
|
||||
VOID
|
||||
LogfClose(PLOGFILE LogFile,
|
||||
BOOL ForceClose);
|
||||
BOOLEAN ForceClose);
|
||||
|
||||
VOID LogfCloseAll(VOID);
|
||||
|
||||
DWORD LogfGetOldestRecord(PLOGFILE LogFile);
|
||||
|
||||
DWORD LogfGetCurrentRecord(PLOGFILE LogFile);
|
||||
|
||||
PBYTE
|
||||
PEVENTLOGRECORD
|
||||
LogfAllocAndBuildNewRecord(PULONG lpRecSize,
|
||||
ULONG dwRecordNumber, // FIXME!
|
||||
ULONG Time,
|
||||
USHORT wType,
|
||||
USHORT wCategory,
|
||||
ULONG dwEventId,
|
||||
|
@ -204,13 +205,13 @@ LogfAllocAndBuildNewRecord(PULONG lpRecSize,
|
|||
ULONG dwSidLength,
|
||||
PSID lpUserSid,
|
||||
USHORT wNumStrings,
|
||||
WCHAR* lpStrings,
|
||||
PWSTR lpStrings,
|
||||
ULONG dwDataSize,
|
||||
PVOID lpRawData);
|
||||
|
||||
static __inline void LogfFreeRecord(LPVOID Rec)
|
||||
static __inline void LogfFreeRecord(PEVENTLOGRECORD Record)
|
||||
{
|
||||
HeapFree(MyHeap, 0, Rec);
|
||||
HeapFree(GetProcessHeap(), 0, Record);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -218,7 +219,7 @@ LogfReportEvent(USHORT wType,
|
|||
USHORT wCategory,
|
||||
ULONG dwEventId,
|
||||
USHORT wNumStrings,
|
||||
WCHAR* lpStrings,
|
||||
PWSTR lpStrings,
|
||||
ULONG dwDataSize,
|
||||
PVOID lpRawData);
|
||||
|
||||
|
|
|
@ -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
|
||||
LoadEventSources(HKEY hKey,
|
||||
PLOGFILE pLogFile)
|
||||
{
|
||||
PEVENTSOURCE lpEventSource;
|
||||
DWORD dwMaxSubKeyLength;
|
||||
DWORD dwEventSourceNameLength;
|
||||
BOOL Success;
|
||||
DWORD dwNumSubKeys, dwMaxSubKeyLength;
|
||||
DWORD dwEventSourceNameLength, MaxValueLen;
|
||||
DWORD dwIndex;
|
||||
WCHAR *Buf = NULL;
|
||||
PWSTR Buf = NULL, SourceList = NULL, Source = NULL;
|
||||
size_t cchRemaining = 0;
|
||||
LONG Result;
|
||||
|
||||
DPRINT("LoadEventSources\n");
|
||||
|
||||
Result = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, &dwMaxSubKeyLength, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
Result = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwNumSubKeys, &dwMaxSubKeyLength,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (Result != ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT1("RegQueryInfoKeyW failed: %lu\n", Result);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT("dwMaxSubKeyLength: %lu\n", dwMaxSubKeyLength);
|
||||
|
||||
dwMaxSubKeyLength++;
|
||||
|
||||
Buf = HeapAlloc(MyHeap, 0, dwMaxSubKeyLength * sizeof(WCHAR));
|
||||
Buf = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLength * sizeof(WCHAR));
|
||||
if (!Buf)
|
||||
{
|
||||
DPRINT1("Error: cannot allocate heap!\n");
|
||||
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;
|
||||
dwIndex = 0;
|
||||
while (RegEnumKeyExW(hKey,
|
||||
|
@ -93,28 +141,56 @@ LoadEventSources(HKEY hKey,
|
|||
&dwEventSourceNameLength,
|
||||
NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT("Event Source: %S\n", Buf);
|
||||
|
||||
lpEventSource = HeapAlloc(MyHeap, 0, sizeof(EVENTSOURCE) + wcslen(Buf) * sizeof(WCHAR));
|
||||
if (lpEventSource != NULL)
|
||||
if (_wcsicmp(pLogFile->LogName, Buf) != 0)
|
||||
{
|
||||
wcscpy(lpEventSource->szName, Buf);
|
||||
lpEventSource->LogFile = pLogFile;
|
||||
|
||||
DPRINT("Insert event source: %S\n", lpEventSource->szName);
|
||||
|
||||
|
||||
EnterCriticalSection(&EventSourceListCs);
|
||||
InsertTailList(&EventSourceListHead,
|
||||
&lpEventSource->EventSourceListEntry);
|
||||
LeaveCriticalSection(&EventSourceListCs);
|
||||
DPRINT("Event Source: %S\n", Buf);
|
||||
Success = AddNewEventSource(pLogFile, Buf);
|
||||
if (Success && (Source != NULL))
|
||||
{
|
||||
/* Append the event source name and an extra NULL-terminator */
|
||||
StringCchCopyExW(Source, cchRemaining, Buf, &Source, &cchRemaining, 0);
|
||||
if (cchRemaining > 0)
|
||||
{
|
||||
*++Source = L'\0';
|
||||
cchRemaining--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dwEventSourceNameLength = dwMaxSubKeyLength;
|
||||
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();
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -107,8 +107,8 @@ NTSTATUS ProcessPortMessage(VOID)
|
|||
{
|
||||
IO_ERROR_LPC Request;
|
||||
PIO_ERROR_LOG_MESSAGE Message;
|
||||
ULONG Time;
|
||||
PEVENTLOGRECORD pRec;
|
||||
ULONG ulRecNum;
|
||||
DWORD dwRecSize;
|
||||
NTSTATUS Status;
|
||||
PLOGFILE SystemLog = NULL;
|
||||
|
@ -147,30 +147,32 @@ NTSTATUS ProcessPortMessage(VOID)
|
|||
else if (Request.Header.u2.s2.Type == LPC_DATAGRAM)
|
||||
{
|
||||
DPRINT("Received datagram\n");
|
||||
Message = (PIO_ERROR_LOG_MESSAGE) & Request.Message;
|
||||
ulRecNum = SystemLog ? SystemLog->Header.CurrentRecordNumber : 0;
|
||||
// Message = (PIO_ERROR_LOG_MESSAGE)&Request.Message;
|
||||
Message = &Request.Message;
|
||||
|
||||
if (!GetComputerNameW(szComputerName, &dwComputerNameLength))
|
||||
{
|
||||
szComputerName[0] = L'\0';
|
||||
}
|
||||
|
||||
RtlTimeToSecondsSince1970(&Message->TimeStamp, &Time);
|
||||
|
||||
// TODO: Log more information??
|
||||
|
||||
pRec = (PEVENTLOGRECORD) LogfAllocAndBuildNewRecord(
|
||||
pRec = LogfAllocAndBuildNewRecord(
|
||||
&dwRecSize,
|
||||
ulRecNum, // FIXME!
|
||||
Time,
|
||||
Message->Type,
|
||||
Message->EntryData.EventCategory,
|
||||
Message->EntryData.ErrorCode,
|
||||
(WCHAR *) ((ULONG_PTR)Message + Message->DriverNameOffset), // FIXME: Use DriverNameLength too!
|
||||
(PWSTR)((ULONG_PTR)Message + Message->DriverNameOffset), // FIXME: Use DriverNameLength too!
|
||||
szComputerName,
|
||||
0,
|
||||
NULL,
|
||||
Message->EntryData.NumberOfStrings,
|
||||
(WCHAR *) ((ULONG_PTR)Message + Message->EntryData.StringOffset),
|
||||
(PWSTR)((ULONG_PTR)Message + Message->EntryData.StringOffset),
|
||||
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)
|
||||
{
|
||||
|
@ -186,10 +188,12 @@ NTSTATUS ProcessPortMessage(VOID)
|
|||
|
||||
if (!onLiveCD && SystemLog)
|
||||
{
|
||||
if (!LogfWriteData(SystemLog, dwRecSize, (PBYTE) pRec))
|
||||
DPRINT("LogfWriteData failed!\n");
|
||||
else
|
||||
DPRINT("Data written to Log!\n");
|
||||
Status = LogfWriteRecord(SystemLog, dwRecSize, pRec);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("ERROR WRITING TO EventLog %S (Status 0x%08lx)\n",
|
||||
SystemLog->FileName, Status);
|
||||
}
|
||||
}
|
||||
|
||||
LogfFreeRecord(pRec);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
LIST_ENTRY LogHandleListHead;
|
||||
static LIST_ENTRY LogHandleListHead;
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
|
@ -77,6 +77,8 @@ ElfCreateEventLogHandle(PLOGHANDLE* LogHandle,
|
|||
StringCchCopy(lpLogHandle->szName, i, LogName->Buffer);
|
||||
|
||||
/* 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();
|
||||
if (LogsActive == 0)
|
||||
{
|
||||
|
@ -114,7 +116,6 @@ ElfCreateEventLogHandle(PLOGHANDLE* LogHandle,
|
|||
if (_wcsicmp(LogName->Buffer, currentLogFile->LogName) == 0)
|
||||
{
|
||||
lpLogHandle->LogFile = currentLogFile;
|
||||
lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -123,16 +124,16 @@ ElfCreateEventLogHandle(PLOGHANDLE* LogHandle,
|
|||
if (lpLogHandle->LogFile == NULL)
|
||||
{
|
||||
lpLogHandle->LogFile = LogfListItemByName(L"Application");
|
||||
|
||||
if (lpLogHandle->LogFile == NULL)
|
||||
{
|
||||
DPRINT1("Application log is missing!\n");
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile);
|
||||
}
|
||||
|
||||
/* Reset the current record */
|
||||
lpLogHandle->CurrentRecord = 0;
|
||||
}
|
||||
|
||||
if (!lpLogHandle->LogFile)
|
||||
|
@ -189,8 +190,8 @@ ElfCreateBackupLogHandle(PLOGHANDLE* LogHandle,
|
|||
/* Set the backup flag */
|
||||
lpLogHandle->Flags |= LOG_HANDLE_BACKUP_FILE;
|
||||
|
||||
/* Get the current record */
|
||||
lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile);
|
||||
/* Reset the current record */
|
||||
lpLogHandle->CurrentRecord = 0;
|
||||
|
||||
Done:
|
||||
if (NT_SUCCESS(Status))
|
||||
|
@ -334,8 +335,17 @@ ElfrNumberOfRecords(
|
|||
lpLogFile->Header.OldestRecordNumber,
|
||||
lpLogFile->Header.CurrentRecordNumber);
|
||||
|
||||
if (lpLogFile->Header.OldestRecordNumber == 0)
|
||||
{
|
||||
/* OldestRecordNumber == 0 when the log is empty */
|
||||
*NumberOfRecords = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The log contains events */
|
||||
*NumberOfRecords = lpLogFile->Header.CurrentRecordNumber -
|
||||
lpLogFile->Header.OldestRecordNumber;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -356,7 +366,7 @@ ElfrOldestRecord(
|
|||
if (!OldestRecordNumber)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
*OldestRecordNumber = LogfGetOldestRecord(lpLogHandle->LogFile);
|
||||
*OldestRecordNumber = lpLogHandle->LogFile->Header.OldestRecordNumber;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -466,9 +476,9 @@ ElfrReadELW(
|
|||
PULONG NumberOfBytesRead,
|
||||
PULONG MinNumberOfBytesNeeded)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PLOGHANDLE lpLogHandle;
|
||||
DWORD dwError;
|
||||
DWORD RecordNumber;
|
||||
ULONG RecordNumber;
|
||||
|
||||
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
||||
if (!lpLogHandle)
|
||||
|
@ -482,12 +492,12 @@ ElfrReadELW(
|
|||
{
|
||||
RecordNumber = lpLogHandle->CurrentRecord;
|
||||
}
|
||||
else
|
||||
else // (ReadFlags & EVENTLOG_SEEK_READ)
|
||||
{
|
||||
RecordNumber = RecordOffset;
|
||||
}
|
||||
|
||||
dwError = LogfReadEvent(lpLogHandle->LogFile,
|
||||
Status = LogfReadEvents(lpLogHandle->LogFile,
|
||||
ReadFlags,
|
||||
&RecordNumber,
|
||||
NumberOfBytesToRead,
|
||||
|
@ -497,27 +507,24 @@ ElfrReadELW(
|
|||
FALSE);
|
||||
|
||||
/* Update the handle's CurrentRecord if success */
|
||||
if (dwError == ERROR_SUCCESS)
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
lpLogHandle->CurrentRecord = RecordNumber;
|
||||
}
|
||||
|
||||
/* HACK!!! */
|
||||
if (dwError == ERROR_HANDLE_EOF)
|
||||
return STATUS_END_OF_FILE;
|
||||
|
||||
return I_RpcMapWin32Status(dwError);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/* Function 11 */
|
||||
/* Helper function for ElfrReportEventW/A and ElfrReportEventAndSourceW */
|
||||
NTSTATUS
|
||||
ElfrReportEventW(
|
||||
ElfrIntReportEventW(
|
||||
IELF_HANDLE LogHandle,
|
||||
ULONG Time,
|
||||
USHORT EventType,
|
||||
USHORT EventCategory,
|
||||
ULONG EventID,
|
||||
PRPC_UNICODE_STRING SourceName OPTIONAL,
|
||||
USHORT NumStrings,
|
||||
ULONG DataSize,
|
||||
PRPC_UNICODE_STRING ComputerName,
|
||||
|
@ -528,16 +535,14 @@ ElfrReportEventW(
|
|||
PULONG RecordNumber,
|
||||
PULONG TimeWritten)
|
||||
{
|
||||
USHORT i;
|
||||
PBYTE LogBuffer;
|
||||
NTSTATUS Status;
|
||||
PLOGHANDLE lpLogHandle;
|
||||
DWORD lastRec;
|
||||
DWORD recSize;
|
||||
DWORD dwStringsSize = 0;
|
||||
DWORD dwUserSidLength = 0;
|
||||
DWORD dwError = ERROR_SUCCESS;
|
||||
WCHAR *lpStrings;
|
||||
int pos = 0;
|
||||
PEVENTLOGRECORD LogBuffer;
|
||||
USHORT i;
|
||||
ULONG recSize;
|
||||
ULONG dwStringsSize = 0;
|
||||
ULONG dwUserSidLength = 0;
|
||||
PWSTR lpStrings, str;
|
||||
|
||||
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
||||
if (!lpLogHandle)
|
||||
|
@ -547,8 +552,6 @@ ElfrReportEventW(
|
|||
if (Flags)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
lastRec = LogfGetCurrentRecord(lpLogHandle->LogFile);
|
||||
|
||||
for (i = 0; i < NumStrings; i++)
|
||||
{
|
||||
switch (EventType)
|
||||
|
@ -591,22 +594,26 @@ ElfrReportEventW(
|
|||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
str = lpStrings;
|
||||
for (i = 0; i < NumStrings; i++)
|
||||
{
|
||||
RtlCopyMemory(lpStrings + pos, Strings[i]->Buffer, Strings[i]->Length);
|
||||
pos += Strings[i]->Length / sizeof(WCHAR);
|
||||
lpStrings[pos] = UNICODE_NULL;
|
||||
pos += sizeof(UNICODE_NULL) / sizeof(WCHAR);
|
||||
RtlCopyMemory(str, Strings[i]->Buffer, Strings[i]->Length);
|
||||
str += Strings[i]->Length / sizeof(WCHAR);
|
||||
*str = UNICODE_NULL;
|
||||
str++;
|
||||
}
|
||||
|
||||
if (UserSID)
|
||||
dwUserSidLength = FIELD_OFFSET(SID, SubAuthority[UserSID->SubAuthorityCount]);
|
||||
|
||||
LogBuffer = LogfAllocAndBuildNewRecord(&recSize,
|
||||
lastRec, // FIXME!
|
||||
Time,
|
||||
EventType,
|
||||
EventCategory,
|
||||
EventID,
|
||||
lpLogHandle->szName,
|
||||
(SourceName && SourceName->Buffer)
|
||||
? SourceName->Buffer
|
||||
: lpLogHandle->szName,
|
||||
ComputerName->Buffer,
|
||||
dwUserSidLength,
|
||||
UserSID,
|
||||
|
@ -615,17 +622,64 @@ ElfrReportEventW(
|
|||
DataSize,
|
||||
Data);
|
||||
|
||||
dwError = LogfWriteData(lpLogHandle->LogFile, recSize, LogBuffer);
|
||||
if (!dwError)
|
||||
Status = LogfWriteRecord(lpLogHandle->LogFile, recSize, LogBuffer);
|
||||
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);
|
||||
|
||||
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 MinNumberOfBytesNeeded)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PLOGHANDLE lpLogHandle;
|
||||
DWORD dwError;
|
||||
DWORD RecordNumber;
|
||||
ULONG RecordNumber;
|
||||
|
||||
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
||||
if (!lpLogHandle)
|
||||
|
@ -829,12 +883,12 @@ ElfrReadELA(
|
|||
{
|
||||
RecordNumber = lpLogHandle->CurrentRecord;
|
||||
}
|
||||
else
|
||||
else // (ReadFlags & EVENTLOG_SEEK_READ)
|
||||
{
|
||||
RecordNumber = RecordOffset;
|
||||
}
|
||||
|
||||
dwError = LogfReadEvent(lpLogHandle->LogFile,
|
||||
Status = LogfReadEvents(lpLogHandle->LogFile,
|
||||
ReadFlags,
|
||||
&RecordNumber,
|
||||
NumberOfBytesToRead,
|
||||
|
@ -844,16 +898,12 @@ ElfrReadELA(
|
|||
TRUE);
|
||||
|
||||
/* Update the handle's CurrentRecord if success */
|
||||
if (dwError == ERROR_SUCCESS)
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
lpLogHandle->CurrentRecord = RecordNumber;
|
||||
}
|
||||
|
||||
/* HACK!!! */
|
||||
if (dwError == ERROR_HANDLE_EOF)
|
||||
return STATUS_END_OF_FILE;
|
||||
|
||||
return I_RpcMapWin32Status(dwError);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -904,7 +954,7 @@ ElfrReportEventA(
|
|||
|
||||
if (NumStrings != 0)
|
||||
{
|
||||
StringsArrayW = HeapAlloc(MyHeap,
|
||||
StringsArrayW = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
NumStrings * sizeof(PUNICODE_STRING));
|
||||
if (StringsArrayW == NULL)
|
||||
|
@ -917,7 +967,7 @@ ElfrReportEventA(
|
|||
{
|
||||
if (Strings[i] != NULL)
|
||||
{
|
||||
StringsArrayW[i] = HeapAlloc(MyHeap,
|
||||
StringsArrayW[i] = HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(UNICODE_STRING));
|
||||
if (StringsArrayW[i] == NULL)
|
||||
|
@ -964,12 +1014,12 @@ Done:
|
|||
if (StringsArrayW[i]->Buffer)
|
||||
{
|
||||
RtlFreeUnicodeString(StringsArrayW[i]);
|
||||
HeapFree(MyHeap, 0, StringsArrayW[i]);
|
||||
HeapFree(GetProcessHeap(), 0, StringsArrayW[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeapFree(MyHeap, 0, StringsArrayW);
|
||||
HeapFree(GetProcessHeap(), 0, StringsArrayW);
|
||||
}
|
||||
|
||||
RtlFreeUnicodeString(&ComputerNameW);
|
||||
|
@ -1043,8 +1093,8 @@ ElfrGetLogInformation(
|
|||
* size threshold "MaxSize" contained in its header.
|
||||
*/
|
||||
efi->dwFull = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Status = STATUS_INVALID_LEVEL;
|
||||
|
@ -1060,6 +1110,12 @@ NTSTATUS
|
|||
ElfrFlushEL(
|
||||
IELF_HANDLE LogHandle)
|
||||
{
|
||||
PLOGHANDLE lpLogHandle;
|
||||
|
||||
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
||||
if (!lpLogHandle)
|
||||
return STATUS_INVALID_HANDLE;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -1084,8 +1140,22 @@ ElfrReportEventAndSourceW(
|
|||
PULONG RecordNumber,
|
||||
PULONG TimeWritten)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
/* Call the helper function. The event source is specified by the caller. */
|
||||
return ElfrIntReportEventW(LogHandle,
|
||||
Time,
|
||||
EventType,
|
||||
EventCategory,
|
||||
EventID,
|
||||
SourceName,
|
||||
NumStrings,
|
||||
DataSize,
|
||||
ComputerName,
|
||||
UserSID,
|
||||
Strings,
|
||||
Data,
|
||||
Flags,
|
||||
RecordNumber,
|
||||
TimeWritten);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue