mirror of
https://github.com/reactos/reactos.git
synced 2024-08-30 23:28:58 +00:00
1277 lines
32 KiB
C
1277 lines
32 KiB
C
/*
|
|
* PROJECT: ReactOS EventLog Service
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: base/services/eventlog/rpc.c
|
|
* PURPOSE: RPC Port Interface support
|
|
* COPYRIGHT: Copyright 2005 Saveliy Tretiakov
|
|
* Copyright 2008 Michael Martin
|
|
* Copyright 2010-2011 Eric Kohl
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include "eventlog.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
static LIST_ENTRY LogHandleListHead;
|
|
static CRITICAL_SECTION LogHandleListCs;
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
static NTSTATUS
|
|
ElfDeleteEventLogHandle(PIELF_HANDLE LogHandle);
|
|
|
|
DWORD WINAPI RpcThreadRoutine(LPVOID lpParameter)
|
|
{
|
|
RPC_STATUS Status;
|
|
|
|
InitializeCriticalSection(&LogHandleListCs);
|
|
InitializeListHead(&LogHandleListHead);
|
|
|
|
Status = RpcServerUseProtseqEpW(L"ncacn_np", 20, L"\\pipe\\EventLog", NULL);
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DPRINT("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
|
|
goto Quit;
|
|
}
|
|
|
|
Status = RpcServerRegisterIf(eventlog_v0_0_s_ifspec, NULL, NULL);
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DPRINT("RpcServerRegisterIf() failed (Status %lx)\n", Status);
|
|
goto Quit;
|
|
}
|
|
|
|
Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DPRINT("RpcServerListen() failed (Status %lx)\n", Status);
|
|
}
|
|
|
|
EnterCriticalSection(&LogHandleListCs);
|
|
while (!IsListEmpty(&LogHandleListHead))
|
|
{
|
|
IELF_HANDLE LogHandle = (IELF_HANDLE)CONTAINING_RECORD(LogHandleListHead.Flink, LOGHANDLE, LogHandleListEntry);
|
|
ElfDeleteEventLogHandle(&LogHandle);
|
|
}
|
|
LeaveCriticalSection(&LogHandleListCs);
|
|
|
|
Quit:
|
|
DeleteCriticalSection(&LogHandleListCs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
ElfCreateEventLogHandle(PLOGHANDLE* LogHandle,
|
|
PUNICODE_STRING LogName,
|
|
BOOLEAN Create)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PLOGHANDLE pLogHandle;
|
|
PLOGFILE currentLogFile = NULL;
|
|
DWORD i, LogsActive;
|
|
PEVENTSOURCE pEventSource;
|
|
|
|
DPRINT("ElfCreateEventLogHandle(%wZ)\n", LogName);
|
|
|
|
*LogHandle = NULL;
|
|
|
|
i = (LogName->Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
|
|
pLogHandle = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
FIELD_OFFSET(LOGHANDLE, szName[i]));
|
|
if (!pLogHandle)
|
|
{
|
|
DPRINT1("Failed to allocate Heap!\n");
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
StringCchCopyW(pLogHandle->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)
|
|
{
|
|
DPRINT1("EventLog service reports no log files!\n");
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
goto Done;
|
|
}
|
|
|
|
/* If Creating, default to the Application Log in case we fail, as documented on MSDN */
|
|
if (Create)
|
|
{
|
|
pEventSource = GetEventSourceByName(LogName->Buffer);
|
|
DPRINT("EventSource: %p\n", pEventSource);
|
|
if (pEventSource)
|
|
{
|
|
DPRINT("EventSource LogFile: %p\n", pEventSource->LogFile);
|
|
pLogHandle->LogFile = pEventSource->LogFile;
|
|
}
|
|
else
|
|
{
|
|
DPRINT("EventSource LogFile: Application log file\n");
|
|
pLogHandle->LogFile = LogfListItemByName(L"Application");
|
|
}
|
|
|
|
DPRINT("LogHandle LogFile: %p\n", pLogHandle->LogFile);
|
|
}
|
|
else
|
|
{
|
|
pLogHandle->LogFile = NULL;
|
|
|
|
for (i = 1; i <= LogsActive; i++)
|
|
{
|
|
currentLogFile = LogfListItemByIndex(i);
|
|
|
|
if (_wcsicmp(LogName->Buffer, currentLogFile->LogName) == 0)
|
|
{
|
|
pLogHandle->LogFile = currentLogFile;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Use the application log if the desired log does not exist */
|
|
if (pLogHandle->LogFile == NULL)
|
|
{
|
|
pLogHandle->LogFile = LogfListItemByName(L"Application");
|
|
if (pLogHandle->LogFile == NULL)
|
|
{
|
|
DPRINT1("Application log is missing!\n");
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
/* Reset the current record */
|
|
pLogHandle->CurrentRecord = 0;
|
|
}
|
|
|
|
if (!pLogHandle->LogFile)
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
Done:
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Append log handle */
|
|
EnterCriticalSection(&LogHandleListCs);
|
|
InsertTailList(&LogHandleListHead, &pLogHandle->LogHandleListEntry);
|
|
LeaveCriticalSection(&LogHandleListCs);
|
|
*LogHandle = pLogHandle;
|
|
}
|
|
else
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pLogHandle);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
ElfCreateBackupLogHandle(PLOGHANDLE* LogHandle,
|
|
PUNICODE_STRING FileName)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PLOGHANDLE pLogHandle;
|
|
|
|
DPRINT("ElfCreateBackupLogHandle(%wZ)\n", FileName);
|
|
|
|
*LogHandle = NULL;
|
|
|
|
pLogHandle = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(LOGHANDLE));
|
|
if (pLogHandle == NULL)
|
|
{
|
|
DPRINT1("Failed to allocate Heap!\n");
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
/* Create the log file */
|
|
Status = LogfCreate(&pLogHandle->LogFile,
|
|
NULL,
|
|
FileName,
|
|
0,
|
|
0,
|
|
FALSE,
|
|
TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create the log file! (Status 0x%08lx)\n", Status);
|
|
goto Done;
|
|
}
|
|
|
|
/* Set the backup flag */
|
|
pLogHandle->Flags |= LOG_HANDLE_BACKUP_FILE;
|
|
|
|
/* Reset the current record */
|
|
pLogHandle->CurrentRecord = 0;
|
|
|
|
Done:
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Append log handle */
|
|
EnterCriticalSection(&LogHandleListCs);
|
|
InsertTailList(&LogHandleListHead, &pLogHandle->LogHandleListEntry);
|
|
LeaveCriticalSection(&LogHandleListCs);
|
|
*LogHandle = pLogHandle;
|
|
}
|
|
else
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pLogHandle);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static PLOGHANDLE
|
|
ElfGetLogHandleEntryByHandle(IELF_HANDLE EventLogHandle)
|
|
{
|
|
PLIST_ENTRY CurrentEntry;
|
|
PLOGHANDLE Handle, pLogHandle = NULL;
|
|
|
|
EnterCriticalSection(&LogHandleListCs);
|
|
|
|
CurrentEntry = LogHandleListHead.Flink;
|
|
while (CurrentEntry != &LogHandleListHead)
|
|
{
|
|
Handle = CONTAINING_RECORD(CurrentEntry,
|
|
LOGHANDLE,
|
|
LogHandleListEntry);
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
|
|
if (Handle == EventLogHandle)
|
|
{
|
|
pLogHandle = Handle;
|
|
break;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&LogHandleListCs);
|
|
|
|
return pLogHandle;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
ElfDeleteEventLogHandle(PIELF_HANDLE LogHandle)
|
|
{
|
|
PLOGHANDLE pLogHandle;
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(*LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
EnterCriticalSection(&LogHandleListCs);
|
|
RemoveEntryList(&pLogHandle->LogHandleListEntry);
|
|
LeaveCriticalSection(&LogHandleListCs);
|
|
|
|
LogfClose(pLogHandle->LogFile, FALSE);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pLogHandle);
|
|
|
|
*LogHandle = NULL;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/* Function 0 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrClearELFW(
|
|
IELF_HANDLE LogHandle,
|
|
PRPC_UNICODE_STRING BackupFileName)
|
|
{
|
|
PLOGHANDLE pLogHandle;
|
|
|
|
DPRINT("ElfrClearELFW()\n");
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
/* Fail, if the log file is a backup file */
|
|
if (pLogHandle->Flags & LOG_HANDLE_BACKUP_FILE)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
return LogfClearFile(pLogHandle->LogFile,
|
|
(PUNICODE_STRING)BackupFileName);
|
|
}
|
|
|
|
|
|
/* Function 1 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrBackupELFW(
|
|
IELF_HANDLE LogHandle,
|
|
PRPC_UNICODE_STRING BackupFileName)
|
|
{
|
|
PLOGHANDLE pLogHandle;
|
|
|
|
DPRINT("ElfrBackupELFW()\n");
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
return LogfBackupFile(pLogHandle->LogFile,
|
|
(PUNICODE_STRING)BackupFileName);
|
|
}
|
|
|
|
|
|
/* Function 2 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrCloseEL(
|
|
PIELF_HANDLE LogHandle)
|
|
{
|
|
return ElfDeleteEventLogHandle(LogHandle);
|
|
}
|
|
|
|
|
|
/* Function 3 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrDeregisterEventSource(
|
|
PIELF_HANDLE LogHandle)
|
|
{
|
|
return ElfDeleteEventLogHandle(LogHandle);
|
|
}
|
|
|
|
|
|
/* Function 4 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrNumberOfRecords(
|
|
IELF_HANDLE LogHandle,
|
|
PULONG NumberOfRecords)
|
|
{
|
|
PLOGHANDLE pLogHandle;
|
|
PLOGFILE pLogFile;
|
|
ULONG OldestRecordNumber, CurrentRecordNumber;
|
|
|
|
DPRINT("ElfrNumberOfRecords()\n");
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
if (!NumberOfRecords)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
pLogFile = pLogHandle->LogFile;
|
|
|
|
/* Lock the log file shared */
|
|
RtlAcquireResourceShared(&pLogFile->Lock, TRUE);
|
|
|
|
OldestRecordNumber = ElfGetOldestRecord(&pLogFile->LogFile);
|
|
CurrentRecordNumber = ElfGetCurrentRecord(&pLogFile->LogFile);
|
|
|
|
/* Unlock the log file */
|
|
RtlReleaseResource(&pLogFile->Lock);
|
|
|
|
DPRINT("Oldest: %lu Current: %lu\n",
|
|
OldestRecordNumber, CurrentRecordNumber);
|
|
|
|
if (OldestRecordNumber == 0)
|
|
{
|
|
/* OldestRecordNumber == 0 when the log is empty */
|
|
*NumberOfRecords = 0;
|
|
}
|
|
else
|
|
{
|
|
/* The log contains events */
|
|
*NumberOfRecords = CurrentRecordNumber - OldestRecordNumber;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/* Function 5 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrOldestRecord(
|
|
IELF_HANDLE LogHandle,
|
|
PULONG OldestRecordNumber)
|
|
{
|
|
PLOGHANDLE pLogHandle;
|
|
PLOGFILE pLogFile;
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
if (!OldestRecordNumber)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
pLogFile = pLogHandle->LogFile;
|
|
|
|
/* Lock the log file shared */
|
|
RtlAcquireResourceShared(&pLogFile->Lock, TRUE);
|
|
|
|
*OldestRecordNumber = ElfGetOldestRecord(&pLogFile->LogFile);
|
|
|
|
/* Unlock the log file */
|
|
RtlReleaseResource(&pLogFile->Lock);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/* Function 6 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrChangeNotify(
|
|
IELF_HANDLE LogHandle,
|
|
RPC_CLIENT_ID ClientId,
|
|
ULONG Event)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
/* Function 7 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrOpenELW(
|
|
EVENTLOG_HANDLE_W UNCServerName,
|
|
PRPC_UNICODE_STRING ModuleName,
|
|
PRPC_UNICODE_STRING RegModuleName,
|
|
ULONG MajorVersion,
|
|
ULONG MinorVersion,
|
|
PIELF_HANDLE LogHandle)
|
|
{
|
|
if ((MajorVersion != 1) || (MinorVersion != 1))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* RegModuleName must be an empty string */
|
|
if (RegModuleName->Length > 0)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* FIXME: UNCServerName must specify the server */
|
|
|
|
/* FIXME: Must verify that caller has read access */
|
|
|
|
return ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle,
|
|
(PUNICODE_STRING)ModuleName,
|
|
FALSE);
|
|
}
|
|
|
|
|
|
/* Function 8 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrRegisterEventSourceW(
|
|
EVENTLOG_HANDLE_W UNCServerName,
|
|
PRPC_UNICODE_STRING ModuleName,
|
|
PRPC_UNICODE_STRING RegModuleName,
|
|
ULONG MajorVersion,
|
|
ULONG MinorVersion,
|
|
PIELF_HANDLE LogHandle)
|
|
{
|
|
DPRINT("ElfrRegisterEventSourceW()\n");
|
|
|
|
if ((MajorVersion != 1) || (MinorVersion != 1))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* RegModuleName must be an empty string */
|
|
if (RegModuleName->Length > 0)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
DPRINT("ModuleName: %wZ\n", ModuleName);
|
|
|
|
/* FIXME: UNCServerName must specify the server or empty for local */
|
|
|
|
/* FIXME: Must verify that caller has write access */
|
|
|
|
return ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle,
|
|
(PUNICODE_STRING)ModuleName,
|
|
TRUE);
|
|
}
|
|
|
|
|
|
/* Function 9 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrOpenBELW(
|
|
EVENTLOG_HANDLE_W UNCServerName,
|
|
PRPC_UNICODE_STRING BackupFileName,
|
|
ULONG MajorVersion,
|
|
ULONG MinorVersion,
|
|
PIELF_HANDLE LogHandle)
|
|
{
|
|
DPRINT("ElfrOpenBELW(%wZ)\n", BackupFileName);
|
|
|
|
if ((MajorVersion != 1) || (MinorVersion != 1))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* FIXME: UNCServerName must specify the server */
|
|
|
|
/* FIXME: Must verify that caller has read access */
|
|
|
|
return ElfCreateBackupLogHandle((PLOGHANDLE*)LogHandle,
|
|
(PUNICODE_STRING)BackupFileName);
|
|
}
|
|
|
|
|
|
/* Function 10 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrReadELW(
|
|
IELF_HANDLE LogHandle,
|
|
ULONG ReadFlags,
|
|
ULONG RecordOffset,
|
|
RULONG NumberOfBytesToRead,
|
|
PBYTE Buffer,
|
|
PULONG NumberOfBytesRead,
|
|
PULONG MinNumberOfBytesNeeded)
|
|
{
|
|
NTSTATUS Status;
|
|
PLOGHANDLE pLogHandle;
|
|
ULONG RecordNumber;
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
if (!Buffer)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* If sequential read, retrieve the CurrentRecord from this log handle */
|
|
if (ReadFlags & EVENTLOG_SEQUENTIAL_READ)
|
|
{
|
|
RecordNumber = pLogHandle->CurrentRecord;
|
|
}
|
|
else // (ReadFlags & EVENTLOG_SEEK_READ)
|
|
{
|
|
RecordNumber = RecordOffset;
|
|
}
|
|
|
|
Status = LogfReadEvents(pLogHandle->LogFile,
|
|
ReadFlags,
|
|
&RecordNumber,
|
|
NumberOfBytesToRead,
|
|
Buffer,
|
|
NumberOfBytesRead,
|
|
MinNumberOfBytesNeeded,
|
|
FALSE);
|
|
|
|
/* Update the handle's CurrentRecord if success */
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pLogHandle->CurrentRecord = RecordNumber;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Helper function for ElfrReportEventW/A and ElfrReportEventAndSourceW */
|
|
NTSTATUS
|
|
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,
|
|
PRPC_SID UserSID,
|
|
PRPC_UNICODE_STRING Strings[],
|
|
PBYTE Data,
|
|
USHORT Flags,
|
|
PULONG RecordNumber,
|
|
PULONG TimeWritten)
|
|
{
|
|
NTSTATUS Status;
|
|
PLOGHANDLE pLogHandle;
|
|
UNICODE_STRING LocalSourceName, LocalComputerName;
|
|
PEVENTLOGRECORD LogBuffer;
|
|
USHORT i;
|
|
SIZE_T RecSize;
|
|
ULONG dwStringsSize = 0;
|
|
ULONG dwUserSidLength = 0;
|
|
PWSTR lpStrings, str;
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
/* Flags must be 0 */
|
|
if (Flags)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
for (i = 0; i < NumStrings; i++)
|
|
{
|
|
switch (EventType)
|
|
{
|
|
case EVENTLOG_SUCCESS:
|
|
DPRINT("Success: %wZ\n", Strings[i]);
|
|
break;
|
|
|
|
case EVENTLOG_ERROR_TYPE:
|
|
DPRINT("Error: %wZ\n", Strings[i]);
|
|
break;
|
|
|
|
case EVENTLOG_WARNING_TYPE:
|
|
DPRINT("Warning: %wZ\n", Strings[i]);
|
|
break;
|
|
|
|
case EVENTLOG_INFORMATION_TYPE:
|
|
DPRINT("Info: %wZ\n", Strings[i]);
|
|
break;
|
|
|
|
case EVENTLOG_AUDIT_SUCCESS:
|
|
DPRINT("Audit Success: %wZ\n", Strings[i]);
|
|
break;
|
|
|
|
case EVENTLOG_AUDIT_FAILURE:
|
|
DPRINT("Audit Failure: %wZ\n", Strings[i]);
|
|
break;
|
|
|
|
default:
|
|
DPRINT1("Type %hu: %wZ\n", EventType, Strings[i]);
|
|
break;
|
|
}
|
|
dwStringsSize += Strings[i]->Length + sizeof(UNICODE_NULL);
|
|
}
|
|
|
|
lpStrings = HeapAlloc(GetProcessHeap(), 0, dwStringsSize);
|
|
if (!lpStrings)
|
|
{
|
|
DPRINT1("Failed to allocate heap\n");
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
str = lpStrings;
|
|
for (i = 0; i < NumStrings; i++)
|
|
{
|
|
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]);
|
|
|
|
if (SourceName && SourceName->Buffer)
|
|
LocalSourceName = *(PUNICODE_STRING)SourceName;
|
|
else
|
|
RtlInitUnicodeString(&LocalSourceName, pLogHandle->szName);
|
|
|
|
LocalComputerName = *(PUNICODE_STRING)ComputerName;
|
|
|
|
LogBuffer = LogfAllocAndBuildNewRecord(&RecSize,
|
|
Time,
|
|
EventType,
|
|
EventCategory,
|
|
EventID,
|
|
&LocalSourceName,
|
|
&LocalComputerName,
|
|
dwUserSidLength,
|
|
UserSID,
|
|
NumStrings,
|
|
lpStrings,
|
|
DataSize,
|
|
Data);
|
|
if (LogBuffer == NULL)
|
|
{
|
|
DPRINT1("LogfAllocAndBuildNewRecord failed!\n");
|
|
HeapFree(GetProcessHeap(), 0, lpStrings);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
Status = LogfWriteRecord(pLogHandle->LogFile, LogBuffer, RecSize);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("ERROR writing to event log `%S' (Status 0x%08lx)\n",
|
|
pLogHandle->LogFile->LogName, 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 Status;
|
|
}
|
|
|
|
|
|
/* Function 11 */
|
|
NTSTATUS
|
|
WINAPI
|
|
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);
|
|
}
|
|
|
|
|
|
/* Function 12 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrClearELFA(
|
|
IELF_HANDLE LogHandle,
|
|
PRPC_STRING BackupFileName)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING BackupFileNameW;
|
|
|
|
Status = RtlAnsiStringToUnicodeString(&BackupFileNameW,
|
|
(PANSI_STRING)BackupFileName,
|
|
TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
Status = ElfrClearELFW(LogHandle,
|
|
(PRPC_UNICODE_STRING)&BackupFileNameW);
|
|
|
|
RtlFreeUnicodeString(&BackupFileNameW);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 13 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrBackupELFA(
|
|
IELF_HANDLE LogHandle,
|
|
PRPC_STRING BackupFileName)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING BackupFileNameW;
|
|
|
|
Status = RtlAnsiStringToUnicodeString(&BackupFileNameW,
|
|
(PANSI_STRING)BackupFileName,
|
|
TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
Status = ElfrBackupELFW(LogHandle,
|
|
(PRPC_UNICODE_STRING)&BackupFileNameW);
|
|
|
|
RtlFreeUnicodeString(&BackupFileNameW);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 14 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrOpenELA(
|
|
EVENTLOG_HANDLE_A UNCServerName,
|
|
PRPC_STRING ModuleName,
|
|
PRPC_STRING RegModuleName,
|
|
ULONG MajorVersion,
|
|
ULONG MinorVersion,
|
|
PIELF_HANDLE LogHandle)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING ModuleNameW;
|
|
|
|
if ((MajorVersion != 1) || (MinorVersion != 1))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* RegModuleName must be an empty string */
|
|
if (RegModuleName->Length > 0)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
Status = RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
/* FIXME: Must verify that caller has read access */
|
|
|
|
Status = ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle,
|
|
&ModuleNameW,
|
|
FALSE);
|
|
|
|
RtlFreeUnicodeString(&ModuleNameW);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 15 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrRegisterEventSourceA(
|
|
EVENTLOG_HANDLE_A UNCServerName,
|
|
PRPC_STRING ModuleName,
|
|
PRPC_STRING RegModuleName,
|
|
ULONG MajorVersion,
|
|
ULONG MinorVersion,
|
|
PIELF_HANDLE LogHandle)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING ModuleNameW;
|
|
|
|
Status = RtlAnsiStringToUnicodeString(&ModuleNameW,
|
|
(PANSI_STRING)ModuleName,
|
|
TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("RtlAnsiStringToUnicodeString failed (Status 0x%08lx)\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/* RegModuleName must be an empty string */
|
|
if (RegModuleName->Length > 0)
|
|
{
|
|
RtlFreeUnicodeString(&ModuleNameW);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((MajorVersion != 1) || (MinorVersion != 1))
|
|
{
|
|
RtlFreeUnicodeString(&ModuleNameW);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* FIXME: Must verify that caller has write access */
|
|
|
|
Status = ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle,
|
|
&ModuleNameW,
|
|
TRUE);
|
|
|
|
RtlFreeUnicodeString(&ModuleNameW);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 16 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrOpenBELA(
|
|
EVENTLOG_HANDLE_A UNCServerName,
|
|
PRPC_STRING BackupFileName,
|
|
ULONG MajorVersion,
|
|
ULONG MinorVersion,
|
|
PIELF_HANDLE LogHandle)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING BackupFileNameW;
|
|
|
|
DPRINT("ElfrOpenBELA(%Z)\n", BackupFileName);
|
|
|
|
Status = RtlAnsiStringToUnicodeString(&BackupFileNameW,
|
|
(PANSI_STRING)BackupFileName,
|
|
TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("RtlAnsiStringToUnicodeString failed (Status 0x%08lx)\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
if ((MajorVersion != 1) || (MinorVersion != 1))
|
|
{
|
|
RtlFreeUnicodeString(&BackupFileNameW);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* FIXME: UNCServerName must specify the server */
|
|
|
|
/* FIXME: Must verify that caller has read access */
|
|
|
|
Status = ElfCreateBackupLogHandle((PLOGHANDLE*)LogHandle,
|
|
&BackupFileNameW);
|
|
|
|
RtlFreeUnicodeString(&BackupFileNameW);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 17 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrReadELA(
|
|
IELF_HANDLE LogHandle,
|
|
ULONG ReadFlags,
|
|
ULONG RecordOffset,
|
|
RULONG NumberOfBytesToRead,
|
|
PBYTE Buffer,
|
|
PULONG NumberOfBytesRead,
|
|
PULONG MinNumberOfBytesNeeded)
|
|
{
|
|
NTSTATUS Status;
|
|
PLOGHANDLE pLogHandle;
|
|
ULONG RecordNumber;
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
if (!Buffer)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* If sequential read, retrieve the CurrentRecord from this log handle */
|
|
if (ReadFlags & EVENTLOG_SEQUENTIAL_READ)
|
|
{
|
|
RecordNumber = pLogHandle->CurrentRecord;
|
|
}
|
|
else // (ReadFlags & EVENTLOG_SEEK_READ)
|
|
{
|
|
RecordNumber = RecordOffset;
|
|
}
|
|
|
|
Status = LogfReadEvents(pLogHandle->LogFile,
|
|
ReadFlags,
|
|
&RecordNumber,
|
|
NumberOfBytesToRead,
|
|
Buffer,
|
|
NumberOfBytesRead,
|
|
MinNumberOfBytesNeeded,
|
|
TRUE);
|
|
|
|
/* Update the handle's CurrentRecord if success */
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pLogHandle->CurrentRecord = RecordNumber;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 18 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrReportEventA(
|
|
IELF_HANDLE LogHandle,
|
|
ULONG Time,
|
|
USHORT EventType,
|
|
USHORT EventCategory,
|
|
ULONG EventID,
|
|
USHORT NumStrings,
|
|
ULONG DataSize,
|
|
PRPC_STRING ComputerName,
|
|
PRPC_SID UserSID,
|
|
PRPC_STRING Strings[],
|
|
PBYTE Data,
|
|
USHORT Flags,
|
|
PULONG RecordNumber,
|
|
PULONG TimeWritten)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
UNICODE_STRING ComputerNameW;
|
|
PUNICODE_STRING *StringsArrayW = NULL;
|
|
USHORT i;
|
|
|
|
DPRINT("ElfrReportEventA(%hu)\n", NumStrings);
|
|
|
|
#if 0
|
|
for (i = 0; i < NumStrings; i++)
|
|
{
|
|
if (Strings[i] == NULL)
|
|
{
|
|
DPRINT1("String %hu is null\n", i);
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("String %hu: %Z\n", i, Strings[i]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING)&ComputerNameW,
|
|
(PANSI_STRING)ComputerName,
|
|
TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
if (NumStrings != 0)
|
|
{
|
|
StringsArrayW = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
NumStrings * sizeof(PUNICODE_STRING));
|
|
if (StringsArrayW == NULL)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
for (i = 0; i < NumStrings; i++)
|
|
{
|
|
if (Strings[i] != NULL)
|
|
{
|
|
StringsArrayW[i] = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(UNICODE_STRING));
|
|
if (StringsArrayW[i] == NULL)
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
break;
|
|
}
|
|
|
|
Status = RtlAnsiStringToUnicodeString(StringsArrayW[i],
|
|
(PANSI_STRING)Strings[i],
|
|
TRUE);
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status = ElfrReportEventW(LogHandle,
|
|
Time,
|
|
EventType,
|
|
EventCategory,
|
|
EventID,
|
|
NumStrings,
|
|
DataSize,
|
|
(PRPC_UNICODE_STRING)&ComputerNameW,
|
|
UserSID,
|
|
(PRPC_UNICODE_STRING*)StringsArrayW,
|
|
Data,
|
|
Flags,
|
|
RecordNumber,
|
|
TimeWritten);
|
|
}
|
|
|
|
Done:
|
|
if (StringsArrayW != NULL)
|
|
{
|
|
for (i = 0; i < NumStrings; i++)
|
|
{
|
|
if ((StringsArrayW[i] != NULL) && (StringsArrayW[i]->Buffer))
|
|
{
|
|
RtlFreeUnicodeString(StringsArrayW[i]);
|
|
HeapFree(GetProcessHeap(), 0, StringsArrayW[i]);
|
|
}
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, StringsArrayW);
|
|
}
|
|
|
|
RtlFreeUnicodeString(&ComputerNameW);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 19 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrRegisterClusterSvc(
|
|
handle_t BindingHandle)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
/* Function 20 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrDeregisterClusterSvc(
|
|
handle_t BindingHandle)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
/* Function 21 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrWriteClusterEvents(
|
|
handle_t BindingHandle)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
/* Function 22 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrGetLogInformation(
|
|
IELF_HANDLE LogHandle,
|
|
ULONG InfoLevel,
|
|
PBYTE Buffer,
|
|
ULONG cbBufSize,
|
|
PULONG pcbBytesNeeded)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PLOGHANDLE pLogHandle;
|
|
PLOGFILE pLogFile;
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
pLogFile = pLogHandle->LogFile;
|
|
|
|
/* Lock the log file shared */
|
|
RtlAcquireResourceShared(&pLogFile->Lock, TRUE);
|
|
|
|
switch (InfoLevel)
|
|
{
|
|
case EVENTLOG_FULL_INFO:
|
|
{
|
|
LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer;
|
|
|
|
*pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
|
|
if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION))
|
|
{
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
efi->dwFull = !!(ElfGetFlags(&pLogFile->LogFile) & ELF_LOGFILE_LOGFULL_WRITTEN);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
Status = STATUS_INVALID_LEVEL;
|
|
break;
|
|
}
|
|
|
|
/* Unlock the log file */
|
|
RtlReleaseResource(&pLogFile->Lock);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 23 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrFlushEL(
|
|
IELF_HANDLE LogHandle)
|
|
{
|
|
NTSTATUS Status;
|
|
PLOGHANDLE pLogHandle;
|
|
PLOGFILE pLogFile;
|
|
|
|
pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!pLogHandle)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
pLogFile = pLogHandle->LogFile;
|
|
|
|
/* Lock the log file exclusive */
|
|
RtlAcquireResourceExclusive(&pLogFile->Lock, TRUE);
|
|
|
|
Status = ElfFlushFile(&pLogFile->LogFile);
|
|
|
|
/* Unlock the log file */
|
|
RtlReleaseResource(&pLogFile->Lock);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 24 */
|
|
NTSTATUS
|
|
WINAPI
|
|
ElfrReportEventAndSourceW(
|
|
IELF_HANDLE LogHandle,
|
|
ULONG Time,
|
|
USHORT EventType,
|
|
USHORT EventCategory,
|
|
ULONG EventID,
|
|
PRPC_UNICODE_STRING SourceName,
|
|
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 specified by the caller. */
|
|
return ElfrIntReportEventW(LogHandle,
|
|
Time,
|
|
EventType,
|
|
EventCategory,
|
|
EventID,
|
|
SourceName,
|
|
NumStrings,
|
|
DataSize,
|
|
ComputerName,
|
|
UserSID,
|
|
Strings,
|
|
Data,
|
|
Flags,
|
|
RecordNumber,
|
|
TimeWritten);
|
|
}
|
|
|
|
|
|
void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len)
|
|
{
|
|
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
|
|
}
|
|
|
|
|
|
void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, ptr);
|
|
}
|
|
|
|
|
|
void __RPC_USER IELF_HANDLE_rundown(IELF_HANDLE LogHandle)
|
|
{
|
|
/* Close the handle */
|
|
ElfDeleteEventLogHandle(&LogHandle); // ElfrCloseEL(&LogHandle);
|
|
}
|