mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 12:54:51 +00:00
1058 lines
26 KiB
C
1058 lines
26 KiB
C
/*
|
|
* PROJECT: ReactOS kernel
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: services/eventlog/rpc.c
|
|
* PURPOSE: Event logging service
|
|
* COPYRIGHT: Copyright 2005 Saveliy Tretiakov
|
|
* Copyright 2008 Michael Martin
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include "eventlog.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
LIST_ENTRY LogHandleListHead;
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
DWORD WINAPI RpcThreadRoutine(LPVOID lpParameter)
|
|
{
|
|
RPC_STATUS Status;
|
|
|
|
InitializeListHead(&LogHandleListHead);
|
|
|
|
Status = RpcServerUseProtseqEpW(L"ncacn_np", 20, L"\\pipe\\EventLog", NULL);
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DPRINT("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
|
|
return 0;
|
|
}
|
|
|
|
Status = RpcServerRegisterIf(eventlog_v0_0_s_ifspec, NULL, NULL);
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DPRINT("RpcServerRegisterIf() failed (Status %lx)\n", Status);
|
|
return 0;
|
|
}
|
|
|
|
Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DPRINT("RpcServerListen() failed (Status %lx)\n", Status);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
ElfCreateEventLogHandle(PLOGHANDLE *LogHandle,
|
|
LPCWSTR Name,
|
|
BOOL Create)
|
|
{
|
|
PLOGHANDLE lpLogHandle;
|
|
PLOGFILE currentLogFile = NULL;
|
|
INT i, LogsActive;
|
|
PEVENTSOURCE pEventSource;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
DPRINT("ElfCreateEventLogHandle(Name: %S)\n", Name);
|
|
|
|
lpLogHandle = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGHANDLE)
|
|
+ ((wcslen(Name) + 1) * sizeof(WCHAR)));
|
|
if (!lpLogHandle)
|
|
{
|
|
DPRINT1("Failed to allocate Heap!\n");
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
wcscpy(lpLogHandle->szName, Name);
|
|
|
|
/* Get the number of Log Files the EventLog service found */
|
|
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 == TRUE)
|
|
{
|
|
pEventSource = GetEventSourceByName(Name);
|
|
DPRINT("EventSource: %p\n", pEventSource);
|
|
if (pEventSource)
|
|
{
|
|
DPRINT("EventSource LogFile: %p\n", pEventSource->LogFile);
|
|
lpLogHandle->LogFile = pEventSource->LogFile;
|
|
}
|
|
else
|
|
{
|
|
DPRINT("EventSource LogFile: Application log file\n");
|
|
lpLogHandle->LogFile = LogfListItemByName(L"Application");
|
|
}
|
|
|
|
DPRINT("LogHandle LogFile: %p\n", lpLogHandle->LogFile);
|
|
}
|
|
else
|
|
{
|
|
lpLogHandle->LogFile = NULL;
|
|
|
|
for (i = 1; i <= LogsActive; i++)
|
|
{
|
|
currentLogFile = LogfListItemByIndex(i);
|
|
|
|
if (_wcsicmp(Name, currentLogFile->LogName) == 0)
|
|
{
|
|
lpLogHandle->LogFile = LogfListItemByIndex(i);
|
|
lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Use the application log if the desired log does not exist */
|
|
if (lpLogHandle->LogFile == NULL)
|
|
{
|
|
lpLogHandle->LogFile = LogfListItemByName(L"Application");
|
|
lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile);
|
|
}
|
|
}
|
|
|
|
if (!lpLogHandle->LogFile)
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
Done:
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Append log handle */
|
|
InsertTailList(&LogHandleListHead, &lpLogHandle->LogHandleListEntry);
|
|
*LogHandle = lpLogHandle;
|
|
}
|
|
else
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, lpLogHandle);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
ElfCreateBackupLogHandle(PLOGHANDLE *LogHandle,
|
|
PUNICODE_STRING FileName)
|
|
{
|
|
PLOGHANDLE lpLogHandle;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
DPRINT("ElfCreateBackupLogHandle(FileName: %wZ)\n", FileName);
|
|
|
|
lpLogHandle = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGHANDLE));
|
|
if (lpLogHandle == NULL)
|
|
{
|
|
DPRINT1("Failed to allocate Heap!\n");
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
/* Create the log file */
|
|
Status = LogfCreate(&lpLogHandle->LogFile,
|
|
NULL,
|
|
FileName,
|
|
FALSE,
|
|
TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create the log file! (Status 0x%08lx)\n", Status);
|
|
goto Done;
|
|
}
|
|
|
|
/* Set the backup flag */
|
|
lpLogHandle->Flags |= LOG_HANDLE_BACKUP_FILE;
|
|
|
|
/* Get the current record */
|
|
lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile);
|
|
|
|
Done:
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Append log handle */
|
|
InsertTailList(&LogHandleListHead, &lpLogHandle->LogHandleListEntry);
|
|
*LogHandle = lpLogHandle;
|
|
}
|
|
else
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, lpLogHandle);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
PLOGHANDLE ElfGetLogHandleEntryByHandle(IELF_HANDLE EventLogHandle)
|
|
{
|
|
PLOGHANDLE lpLogHandle;
|
|
|
|
if (IsListEmpty(&LogHandleListHead))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
lpLogHandle = CONTAINING_RECORD((PLOGHANDLE)EventLogHandle, LOGHANDLE, LogHandleListEntry);
|
|
|
|
return lpLogHandle;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
ElfDeleteEventLogHandle(IELF_HANDLE EventLogHandle)
|
|
{
|
|
PLOGHANDLE lpLogHandle = (PLOGHANDLE)EventLogHandle;
|
|
|
|
if (!ElfGetLogHandleEntryByHandle(lpLogHandle))
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
LogfClose(lpLogHandle->LogFile, FALSE);
|
|
|
|
RemoveEntryList(&lpLogHandle->LogHandleListEntry);
|
|
HeapFree(GetProcessHeap(),0,lpLogHandle);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* Function 0 */
|
|
NTSTATUS ElfrClearELFW(
|
|
IELF_HANDLE LogHandle,
|
|
PRPC_UNICODE_STRING BackupFileName)
|
|
{
|
|
PLOGHANDLE lpLogHandle;
|
|
|
|
DPRINT("ElfrClearELFW()\n");
|
|
|
|
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!lpLogHandle)
|
|
{
|
|
return STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
/* Fail, if the log file is a backup file */
|
|
if (lpLogHandle->Flags & LOG_HANDLE_BACKUP_FILE)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
return LogfClearFile(lpLogHandle->LogFile,
|
|
(PUNICODE_STRING)BackupFileName);
|
|
}
|
|
|
|
|
|
/* Function 1 */
|
|
NTSTATUS ElfrBackupELFW(
|
|
IELF_HANDLE LogHandle,
|
|
PRPC_UNICODE_STRING BackupFileName)
|
|
{
|
|
PLOGHANDLE lpLogHandle;
|
|
|
|
DPRINT("ElfrBackupELFW()\n");
|
|
|
|
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!lpLogHandle)
|
|
{
|
|
return STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
return LogfBackupFile(lpLogHandle->LogFile,
|
|
(PUNICODE_STRING)BackupFileName);
|
|
}
|
|
|
|
|
|
/* Function 2 */
|
|
NTSTATUS ElfrCloseEL(
|
|
IELF_HANDLE *LogHandle)
|
|
{
|
|
return ElfDeleteEventLogHandle(*LogHandle);
|
|
}
|
|
|
|
|
|
/* Function 3 */
|
|
NTSTATUS ElfrDeregisterEventSource(
|
|
IELF_HANDLE *LogHandle)
|
|
{
|
|
return ElfDeleteEventLogHandle(*LogHandle);
|
|
}
|
|
|
|
|
|
/* Function 4 */
|
|
NTSTATUS ElfrNumberOfRecords(
|
|
IELF_HANDLE LogHandle,
|
|
DWORD *NumberOfRecords)
|
|
{
|
|
PLOGHANDLE lpLogHandle;
|
|
PLOGFILE lpLogFile;
|
|
|
|
DPRINT("ElfrNumberOfRecords()");
|
|
|
|
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!lpLogHandle)
|
|
{
|
|
return STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
lpLogFile = lpLogHandle->LogFile;
|
|
|
|
DPRINT("Oldest: %lu Current: %lu\n",
|
|
lpLogFile->Header.OldestRecordNumber,
|
|
lpLogFile->Header.CurrentRecordNumber);
|
|
|
|
*NumberOfRecords = lpLogFile->Header.CurrentRecordNumber -
|
|
lpLogFile->Header.OldestRecordNumber;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/* Function 5 */
|
|
NTSTATUS ElfrOldestRecord(
|
|
IELF_HANDLE LogHandle,
|
|
DWORD *OldestRecordNumber)
|
|
{
|
|
PLOGHANDLE lpLogHandle;
|
|
|
|
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!lpLogHandle)
|
|
{
|
|
return STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
if (!OldestRecordNumber)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
*OldestRecordNumber = LogfGetOldestRecord(lpLogHandle->LogFile);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/* Function 6 */
|
|
NTSTATUS ElfrChangeNotify(
|
|
IELF_HANDLE *LogHandle,
|
|
RPC_CLIENT_ID ClientId,
|
|
DWORD Event)
|
|
{
|
|
DPRINT("ElfrChangeNotify()");
|
|
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
/* Function 7 */
|
|
NTSTATUS ElfrOpenELW(
|
|
EVENTLOG_HANDLE_W UNCServerName,
|
|
PRPC_UNICODE_STRING ModuleName,
|
|
PRPC_UNICODE_STRING RegModuleName,
|
|
DWORD MajorVersion,
|
|
DWORD MinorVersion,
|
|
IELF_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,
|
|
ModuleName->Buffer,
|
|
FALSE);
|
|
}
|
|
|
|
|
|
/* Function 8 */
|
|
NTSTATUS ElfrRegisterEventSourceW(
|
|
EVENTLOG_HANDLE_W UNCServerName,
|
|
PRPC_UNICODE_STRING ModuleName,
|
|
PRPC_UNICODE_STRING RegModuleName,
|
|
DWORD MajorVersion,
|
|
DWORD MinorVersion,
|
|
IELF_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: %S\n", ModuleName->Buffer);
|
|
|
|
/*FIXME: UNCServerName must specify the server or empty for local */
|
|
|
|
/*FIXME: Must verify that caller has write access */
|
|
|
|
return ElfCreateEventLogHandle((PLOGHANDLE *)LogHandle,
|
|
ModuleName->Buffer,
|
|
TRUE);
|
|
}
|
|
|
|
|
|
/* Function 9 */
|
|
NTSTATUS ElfrOpenBELW(
|
|
EVENTLOG_HANDLE_W UNCServerName,
|
|
PRPC_UNICODE_STRING BackupFileName,
|
|
DWORD MajorVersion,
|
|
DWORD MinorVersion,
|
|
IELF_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 ElfrReadELW(
|
|
IELF_HANDLE LogHandle,
|
|
DWORD ReadFlags,
|
|
DWORD RecordOffset,
|
|
RULONG NumberOfBytesToRead,
|
|
BYTE *Buffer,
|
|
DWORD *NumberOfBytesRead,
|
|
DWORD *MinNumberOfBytesNeeded)
|
|
{
|
|
PLOGHANDLE lpLogHandle;
|
|
DWORD dwError;
|
|
DWORD RecordNumber;
|
|
|
|
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!lpLogHandle)
|
|
{
|
|
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 = lpLogHandle->CurrentRecord;
|
|
}
|
|
else
|
|
{
|
|
RecordNumber = RecordOffset;
|
|
}
|
|
|
|
dwError = LogfReadEvent(lpLogHandle->LogFile, ReadFlags, &RecordNumber,
|
|
NumberOfBytesToRead, Buffer, NumberOfBytesRead, MinNumberOfBytesNeeded,
|
|
FALSE);
|
|
|
|
/* Update the handles CurrentRecord if success*/
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
lpLogHandle->CurrentRecord = RecordNumber;
|
|
}
|
|
|
|
/* HACK!!! */
|
|
if (dwError == ERROR_HANDLE_EOF)
|
|
return STATUS_END_OF_FILE;
|
|
|
|
return I_RpcMapWin32Status(dwError);
|
|
}
|
|
|
|
|
|
/* Function 11 */
|
|
NTSTATUS ElfrReportEventW(
|
|
IELF_HANDLE LogHandle,
|
|
DWORD Time,
|
|
USHORT EventType,
|
|
USHORT EventCategory,
|
|
DWORD EventID,
|
|
USHORT NumStrings,
|
|
DWORD DataSize,
|
|
PRPC_UNICODE_STRING ComputerName,
|
|
PRPC_SID UserSID,
|
|
PRPC_UNICODE_STRING Strings[],
|
|
BYTE *Data,
|
|
USHORT Flags,
|
|
DWORD *RecordNumber,
|
|
DWORD *TimeWritten)
|
|
{
|
|
USHORT i;
|
|
PBYTE LogBuffer;
|
|
PLOGHANDLE lpLogHandle;
|
|
DWORD lastRec;
|
|
DWORD recSize;
|
|
DWORD dwStringsSize = 0;
|
|
DWORD dwUserSidLength = 0;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
WCHAR *lpStrings;
|
|
int pos = 0;
|
|
|
|
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!lpLogHandle)
|
|
{
|
|
return STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
/* Flags must be 0 */
|
|
if (Flags)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
lastRec = LogfGetCurrentRecord(lpLogHandle->LogFile);
|
|
|
|
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;
|
|
}
|
|
|
|
for (i = 0; i < NumStrings; i++)
|
|
{
|
|
CopyMemory(lpStrings + pos, Strings[i]->Buffer, Strings[i]->Length);
|
|
pos += Strings[i]->Length / sizeof(WCHAR);
|
|
lpStrings[pos] = UNICODE_NULL;
|
|
pos += sizeof UNICODE_NULL / sizeof(WCHAR);
|
|
}
|
|
|
|
if (UserSID)
|
|
dwUserSidLength = FIELD_OFFSET(SID, SubAuthority[UserSID->SubAuthorityCount]);
|
|
LogBuffer = LogfAllocAndBuildNewRecord(&recSize,
|
|
lastRec,
|
|
EventType,
|
|
EventCategory,
|
|
EventID,
|
|
lpLogHandle->szName,
|
|
ComputerName->Buffer,
|
|
dwUserSidLength,
|
|
UserSID,
|
|
NumStrings,
|
|
lpStrings,
|
|
DataSize,
|
|
Data);
|
|
|
|
dwError = LogfWriteData(lpLogHandle->LogFile, recSize, LogBuffer);
|
|
if (!dwError)
|
|
{
|
|
DPRINT1("ERROR WRITING TO EventLog %S\n", lpLogHandle->LogFile->FileName);
|
|
}
|
|
|
|
LogfFreeRecord(LogBuffer);
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpStrings);
|
|
|
|
return I_RpcMapWin32Status(dwError);
|
|
}
|
|
|
|
|
|
/* Function 12 */
|
|
NTSTATUS ElfrClearELFA(
|
|
IELF_HANDLE LogHandle,
|
|
PRPC_STRING BackupFileName)
|
|
{
|
|
UNICODE_STRING BackupFileNameW;
|
|
NTSTATUS Status;
|
|
|
|
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 ElfrBackupELFA(
|
|
IELF_HANDLE LogHandle,
|
|
PRPC_STRING BackupFileName)
|
|
{
|
|
UNICODE_STRING BackupFileNameW;
|
|
NTSTATUS Status;
|
|
|
|
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 ElfrOpenELA(
|
|
EVENTLOG_HANDLE_A UNCServerName,
|
|
PRPC_STRING ModuleName,
|
|
PRPC_STRING RegModuleName,
|
|
DWORD MajorVersion,
|
|
DWORD MinorVersion,
|
|
IELF_HANDLE *LogHandle)
|
|
{
|
|
UNICODE_STRING ModuleNameW;
|
|
NTSTATUS Status;
|
|
|
|
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.Buffer,
|
|
FALSE);
|
|
|
|
RtlFreeUnicodeString(&ModuleNameW);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 15 */
|
|
NTSTATUS ElfrRegisterEventSourceA(
|
|
EVENTLOG_HANDLE_A UNCServerName,
|
|
PRPC_STRING ModuleName,
|
|
PRPC_STRING RegModuleName,
|
|
DWORD MajorVersion,
|
|
DWORD MinorVersion,
|
|
IELF_HANDLE *LogHandle)
|
|
{
|
|
UNICODE_STRING ModuleNameW;
|
|
NTSTATUS Status;
|
|
|
|
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.Buffer,
|
|
TRUE);
|
|
|
|
RtlFreeUnicodeString(&ModuleNameW);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 16 */
|
|
NTSTATUS ElfrOpenBELA(
|
|
EVENTLOG_HANDLE_A UNCServerName,
|
|
PRPC_STRING BackupFileName,
|
|
DWORD MajorVersion,
|
|
DWORD MinorVersion,
|
|
IELF_HANDLE *LogHandle)
|
|
{
|
|
UNICODE_STRING BackupFileNameW;
|
|
NTSTATUS Status;
|
|
|
|
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 ElfrReadELA(
|
|
IELF_HANDLE LogHandle,
|
|
DWORD ReadFlags,
|
|
DWORD RecordOffset,
|
|
RULONG NumberOfBytesToRead,
|
|
BYTE *Buffer,
|
|
DWORD *NumberOfBytesRead,
|
|
DWORD *MinNumberOfBytesNeeded)
|
|
{
|
|
PLOGHANDLE lpLogHandle;
|
|
DWORD dwError;
|
|
DWORD RecordNumber;
|
|
|
|
lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
|
|
if (!lpLogHandle)
|
|
{
|
|
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 = lpLogHandle->CurrentRecord;
|
|
}
|
|
else
|
|
{
|
|
RecordNumber = RecordOffset;
|
|
}
|
|
|
|
dwError = LogfReadEvent(lpLogHandle->LogFile,
|
|
ReadFlags,
|
|
&RecordNumber,
|
|
NumberOfBytesToRead,
|
|
Buffer,
|
|
NumberOfBytesRead,
|
|
MinNumberOfBytesNeeded,
|
|
TRUE);
|
|
|
|
/* Update the handles CurrentRecord if success*/
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
lpLogHandle->CurrentRecord = RecordNumber;
|
|
}
|
|
|
|
/* HACK!!! */
|
|
if (dwError == ERROR_HANDLE_EOF)
|
|
return STATUS_END_OF_FILE;
|
|
|
|
return I_RpcMapWin32Status(dwError);
|
|
}
|
|
|
|
|
|
/* Function 18 */
|
|
NTSTATUS ElfrReportEventA(
|
|
IELF_HANDLE LogHandle,
|
|
DWORD Time,
|
|
USHORT EventType,
|
|
USHORT EventCategory,
|
|
DWORD EventID,
|
|
USHORT NumStrings,
|
|
DWORD DataSize,
|
|
PRPC_STRING ComputerName,
|
|
PRPC_SID UserSID,
|
|
PRPC_STRING Strings[],
|
|
BYTE *Data,
|
|
USHORT Flags,
|
|
DWORD *RecordNumber,
|
|
DWORD *TimeWritten)
|
|
{
|
|
UNICODE_STRING ComputerNameW;
|
|
PUNICODE_STRING *StringsArrayW = NULL;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
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(MyHeap,
|
|
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(MyHeap,
|
|
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)
|
|
{
|
|
if (StringsArrayW[i]->Buffer)
|
|
{
|
|
RtlFreeUnicodeString(StringsArrayW[i]);
|
|
HeapFree(MyHeap, 0, StringsArrayW[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
HeapFree(MyHeap, 0, StringsArrayW);
|
|
}
|
|
|
|
RtlFreeUnicodeString(&ComputerNameW);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 19 */
|
|
NTSTATUS ElfrRegisterClusterSvc(
|
|
handle_t BindingHandle)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
/* Function 20 */
|
|
NTSTATUS ElfrDeregisterClusterSvc(
|
|
handle_t BindingHandle)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
/* Function 21 */
|
|
NTSTATUS ElfrWriteClusterEvents(
|
|
handle_t BindingHandle)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
/* Function 22 */
|
|
NTSTATUS ElfrGetLogInformation(
|
|
IELF_HANDLE LogHandle,
|
|
DWORD InfoLevel,
|
|
BYTE *Buffer,
|
|
DWORD cbBufSize,
|
|
DWORD *pcbBytesNeeded)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
/* FIXME: check handle first */
|
|
|
|
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))
|
|
{
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
efi->dwFull = 0; /* FIXME */
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_INVALID_LEVEL;
|
|
break;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/* Function 23 */
|
|
NTSTATUS ElfrFlushEL(
|
|
IELF_HANDLE LogHandle)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
/* Function 24 */
|
|
NTSTATUS ElfrReportEventAndSourceW(
|
|
IELF_HANDLE LogHandle,
|
|
DWORD Time,
|
|
USHORT EventType,
|
|
USHORT EventCategory,
|
|
ULONG EventID,
|
|
PRPC_UNICODE_STRING SourceName,
|
|
USHORT NumStrings,
|
|
DWORD DataSize,
|
|
PRPC_UNICODE_STRING ComputerName,
|
|
PRPC_SID UserSID,
|
|
PRPC_UNICODE_STRING Strings[],
|
|
BYTE *Data,
|
|
USHORT Flags,
|
|
DWORD *RecordNumber,
|
|
DWORD *TimeWritten)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
}
|