reactos/base/services/eventlog/rpc.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);
}