[EVENTLOG]
[reactos.git] / reactos / base / services / eventlog / rpc.c
index 9a2c868..99f8d72 100644 (file)
@@ -11,6 +11,9 @@
 
 #include "eventlog.h"
 
+#define NDEBUG
+#include <debug.h>
+
 LIST_ENTRY LogHandleListHead;
 
 /* FUNCTIONS ****************************************************************/
@@ -44,12 +47,17 @@ DWORD WINAPI RpcThreadRoutine(LPVOID lpParameter)
     return 0;
 }
 
-PLOGHANDLE ElfCreateEventLogHandle(LPCWSTR Name, BOOL Create)
+
+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);
 
@@ -58,7 +66,7 @@ PLOGHANDLE ElfCreateEventLogHandle(LPCWSTR Name, BOOL Create)
     if (!lpLogHandle)
     {
         DPRINT1("Failed to allocate Heap!\n");
-        return NULL;
+        return STATUS_NO_MEMORY;
     }
 
     wcscpy(lpLogHandle->szName, Name);
@@ -68,7 +76,8 @@ PLOGHANDLE ElfCreateEventLogHandle(LPCWSTR Name, BOOL Create)
     if (LogsActive == 0)
     {
         DPRINT1("EventLog service reports no log files!\n");
-        goto Cleanup;
+        Status = STATUS_UNSUCCESSFUL;
+        goto Done;
     }
 
     /* If Creating, default to the Application Log in case we fail, as documented on MSDN */
@@ -104,48 +113,125 @@ PLOGHANDLE ElfCreateEventLogHandle(LPCWSTR Name, BOOL Create)
                 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)
-        goto Cleanup;
+        Status = STATUS_UNSUCCESSFUL;
+
+Done:
+    if (NT_SUCCESS(Status))
+    {
+        /* Append log handle */
+        InsertTailList(&LogHandleListHead, &lpLogHandle->LogHandleListEntry);
+        *LogHandle = lpLogHandle;
+    }
+    else
+    {
+        HeapFree(GetProcessHeap(), 0, lpLogHandle);
+    }
+
+    return Status;
+}
 
-    /* Append log handle */
-    InsertTailList(&LogHandleListHead, &lpLogHandle->LogHandleListEntry);
 
-    return lpLogHandle;
+static NTSTATUS
+ElfCreateBackupLogHandle(PLOGHANDLE *LogHandle,
+                         PUNICODE_STRING FileName)
+{
+    PLOGHANDLE lpLogHandle;
+
+    NTSTATUS Status = STATUS_SUCCESS;
 
-Cleanup:
-    HeapFree(GetProcessHeap(), 0, lpLogHandle);
+    DPRINT("ElfCreateBackupLogHandle(FileName: %wZ)\n", FileName);
 
-    return NULL;
+    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,
+                        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 */
+    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)
 {
+    PLIST_ENTRY CurrentEntry;
     PLOGHANDLE lpLogHandle;
 
-    if (IsListEmpty(&LogHandleListHead))
+    CurrentEntry = LogHandleListHead.Flink;
+    while (CurrentEntry != &LogHandleListHead)
     {
-        return NULL;
-    }
+        lpLogHandle = CONTAINING_RECORD(CurrentEntry,
+                                        LOGHANDLE,
+                                        LogHandleListEntry);
+        CurrentEntry = CurrentEntry->Flink;
 
-    lpLogHandle = CONTAINING_RECORD((PLOGHANDLE)EventLogHandle, LOGHANDLE, LogHandleListEntry);
+        if (lpLogHandle == EventLogHandle)
+            return lpLogHandle;
+    }
 
-    return lpLogHandle;
+    return NULL;
 }
 
-BOOL ElfDeleteEventLogHandle(IELF_HANDLE EventLogHandle)
+
+static NTSTATUS
+ElfDeleteEventLogHandle(IELF_HANDLE LogHandle)
 {
-    PLOGHANDLE lpLogHandle = (PLOGHANDLE)EventLogHandle;
-    if (!ElfGetLogHandleEntryByHandle(lpLogHandle))
+    PLOGHANDLE lpLogHandle;
+
+    lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
+    if (!lpLogHandle)
     {
-        return FALSE;
+        return STATUS_INVALID_HANDLE;
     }
 
     RemoveEntryList(&lpLogHandle->LogHandleListEntry);
-    HeapFree(GetProcessHeap(),0,lpLogHandle);
+    LogfClose(lpLogHandle->LogFile, FALSE);
+
+    HeapFree(GetProcessHeap(), 0, lpLogHandle);
 
-    return TRUE;
+    return STATUS_SUCCESS;
 }
 
 /* Function 0 */
@@ -153,8 +239,22 @@ NTSTATUS ElfrClearELFW(
     IELF_HANDLE LogHandle,
     PRPC_UNICODE_STRING BackupFileName)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    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);
 }
 
 
@@ -163,20 +263,26 @@ NTSTATUS ElfrBackupELFW(
     IELF_HANDLE LogHandle,
     PRPC_UNICODE_STRING BackupFileName)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    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)
 {
-    if (!ElfDeleteEventLogHandle(*LogHandle))
-    {
-        return STATUS_INVALID_HANDLE;
-    }
-
-    return STATUS_SUCCESS;
+    return ElfDeleteEventLogHandle(*LogHandle);
 }
 
 
@@ -184,12 +290,7 @@ NTSTATUS ElfrCloseEL(
 NTSTATUS ElfrDeregisterEventSource(
     IELF_HANDLE *LogHandle)
 {
-    if (!ElfDeleteEventLogHandle(*LogHandle))
-    {
-        return STATUS_INVALID_HANDLE;
-    }
-
-    return STATUS_SUCCESS;
+    return ElfDeleteEventLogHandle(*LogHandle);
 }
 
 
@@ -201,6 +302,8 @@ NTSTATUS ElfrNumberOfRecords(
     PLOGHANDLE lpLogHandle;
     PLOGFILE lpLogFile;
 
+    DPRINT("ElfrNumberOfRecords()\n");
+
     lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
     if (!lpLogHandle)
     {
@@ -209,11 +312,12 @@ NTSTATUS ElfrNumberOfRecords(
 
     lpLogFile = lpLogHandle->LogFile;
 
-    if (lpLogFile->Header.OldestRecordNumber == 0)
-        *NumberOfRecords = 0;
-    else
-        *NumberOfRecords = lpLogFile->Header.CurrentRecordNumber -
-                           lpLogFile->Header.OldestRecordNumber;
+    DPRINT("Oldest: %lu  Current: %lu\n",
+           lpLogFile->Header.OldestRecordNumber,
+           lpLogFile->Header.CurrentRecordNumber);
+
+    *NumberOfRecords = lpLogFile->Header.CurrentRecordNumber -
+                       lpLogFile->Header.OldestRecordNumber;
 
     return STATUS_SUCCESS;
 }
@@ -237,8 +341,8 @@ NTSTATUS ElfrOldestRecord(
         return STATUS_INVALID_PARAMETER;
     }
 
-    *OldestRecordNumber = 0;
     *OldestRecordNumber = LogfGetOldestRecord(lpLogHandle->LogFile);
+
     return STATUS_SUCCESS;
 }
 
@@ -249,6 +353,8 @@ NTSTATUS ElfrChangeNotify(
     RPC_CLIENT_ID ClientId,
     DWORD Event)
 {
+    DPRINT("ElfrChangeNotify()");
+
     UNIMPLEMENTED;
     return STATUS_NOT_IMPLEMENTED;
 }
@@ -274,14 +380,9 @@ NTSTATUS ElfrOpenELW(
 
     /*FIXME: Must verify that caller has read access */
 
-    *LogHandle = ElfCreateEventLogHandle(ModuleName->Buffer, FALSE);
-
-    if (*LogHandle == NULL)
-    {
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    return STATUS_SUCCESS;
+    return ElfCreateEventLogHandle((PLOGHANDLE *)LogHandle,
+                                   ModuleName->Buffer,
+                                   FALSE);
 }
 
 
@@ -294,7 +395,7 @@ NTSTATUS ElfrRegisterEventSourceW(
     DWORD MinorVersion,
     IELF_HANDLE *LogHandle)
 {
-    DPRINT1("ElfrRegisterEventSourceW()\n");
+    DPRINT("ElfrRegisterEventSourceW()\n");
 
     if ((MajorVersion != 1) || (MinorVersion != 1))
         return STATUS_INVALID_PARAMETER;
@@ -303,15 +404,15 @@ NTSTATUS ElfrRegisterEventSourceW(
     if (RegModuleName->Length > 0)
         return STATUS_INVALID_PARAMETER;
 
-    DPRINT1("ModuleName: %S\n", ModuleName->Buffer);
+    DPRINT("ModuleName: %S\n", ModuleName->Buffer);
 
     /*FIXME: UNCServerName must specify the server or empty for local */
 
     /*FIXME: Must verify that caller has write access */
 
-    *LogHandle = ElfCreateEventLogHandle(ModuleName->Buffer, TRUE);
-
-    return STATUS_SUCCESS;
+    return ElfCreateEventLogHandle((PLOGHANDLE *)LogHandle,
+                                   ModuleName->Buffer,
+                                   TRUE);
 }
 
 
@@ -323,8 +424,17 @@ NTSTATUS ElfrOpenBELW(
     DWORD MinorVersion,
     IELF_HANDLE *LogHandle)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    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);
 }
 
 
@@ -348,8 +458,8 @@ NTSTATUS ElfrReadELW(
         return STATUS_INVALID_HANDLE;
     }
 
-    if (!Buffer) 
-        return I_RpcMapWin32Status(ERROR_INVALID_PARAMETER);
+    if (!Buffer)
+        return STATUS_INVALID_PARAMETER;
 
     /* If sequential read, retrieve the CurrentRecord from this log handle */
     if (ReadFlags & EVENTLOG_SEQUENTIAL_READ)
@@ -362,7 +472,8 @@ NTSTATUS ElfrReadELW(
     }
 
     dwError = LogfReadEvent(lpLogHandle->LogFile, ReadFlags, &RecordNumber,
-                            NumberOfBytesToRead, Buffer, NumberOfBytesRead, MinNumberOfBytesNeeded);
+                            NumberOfBytesToRead, Buffer, NumberOfBytesRead, MinNumberOfBytesNeeded,
+                            FALSE);
 
     /* Update the handles CurrentRecord if success*/
     if (dwError == ERROR_SUCCESS)
@@ -370,6 +481,10 @@ NTSTATUS ElfrReadELW(
         lpLogHandle->CurrentRecord = RecordNumber;
     }
 
+    /* HACK!!! */
+    if (dwError == ERROR_HANDLE_EOF)
+        return STATUS_END_OF_FILE;
+
     return I_RpcMapWin32Status(dwError);
 }
 
@@ -436,6 +551,14 @@ NTSTATUS ElfrReportEventW(
                 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;
@@ -493,8 +616,21 @@ NTSTATUS ElfrClearELFA(
     IELF_HANDLE LogHandle,
     PRPC_STRING BackupFileName)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    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;
 }
 
 
@@ -503,8 +639,21 @@ NTSTATUS ElfrBackupELFA(
     IELF_HANDLE LogHandle,
     PRPC_STRING BackupFileName)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    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;
 }
 
 
@@ -518,6 +667,7 @@ NTSTATUS ElfrOpenELA(
     IELF_HANDLE *LogHandle)
 {
     UNICODE_STRING ModuleNameW;
+    NTSTATUS Status;
 
     if ((MajorVersion != 1) || (MinorVersion != 1))
         return STATUS_INVALID_PARAMETER;
@@ -526,20 +676,19 @@ NTSTATUS ElfrOpenELA(
     if (RegModuleName->Length > 0)
         return STATUS_INVALID_PARAMETER;
 
-    RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE);
+    Status = RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE);
+    if (!NT_SUCCESS(Status))
+        return Status;
 
     /* FIXME: Must verify that caller has read access */
 
-    *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer, FALSE);
+    Status = ElfCreateEventLogHandle((PLOGHANDLE *)LogHandle,
+                                     ModuleNameW.Buffer,
+                                     FALSE);
 
     RtlFreeUnicodeString(&ModuleNameW);
 
-    if (*LogHandle == NULL)
-    {
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 
@@ -552,12 +701,16 @@ NTSTATUS ElfrRegisterEventSourceA(
     DWORD MinorVersion,
     IELF_HANDLE *LogHandle)
 {
-    UNICODE_STRING ModuleNameW    = { 0, 0, NULL };
+    UNICODE_STRING ModuleNameW;
+    NTSTATUS Status;
 
-    if (ModuleName &&
-        !RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE))
+    Status = RtlAnsiStringToUnicodeString(&ModuleNameW,
+                                          (PANSI_STRING)ModuleName,
+                                          TRUE);
+    if (!NT_SUCCESS(Status))
     {
-        return STATUS_NO_MEMORY;
+        DPRINT1("RtlAnsiStringToUnicodeString failed (Status 0x%08lx)\n", Status);
+        return Status;
     }
 
     /* RegModuleName must be an empty string */
@@ -575,12 +728,13 @@ NTSTATUS ElfrRegisterEventSourceA(
 
     /* FIXME: Must verify that caller has write access */
 
-    *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer,
-                                         TRUE);
+    Status = ElfCreateEventLogHandle((PLOGHANDLE *)LogHandle,
+                                     ModuleNameW.Buffer,
+                                     TRUE);
 
     RtlFreeUnicodeString(&ModuleNameW);
 
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 
@@ -592,8 +746,36 @@ NTSTATUS ElfrOpenBELA(
     DWORD MinorVersion,
     IELF_HANDLE *LogHandle)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    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;
 }
 
 
@@ -607,8 +789,49 @@ NTSTATUS ElfrReadELA(
     DWORD *NumberOfBytesRead,
     DWORD *MinNumberOfBytesNeeded)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    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);
 }
 
 
@@ -629,8 +852,106 @@ NTSTATUS ElfrReportEventA(
     DWORD *RecordNumber,
     DWORD *TimeWritten)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    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;
 }