[EVENTLOG]
[reactos.git] / reactos / base / services / eventlog / file.c
index a88b578..3316c25 100644 (file)
@@ -34,6 +34,7 @@ BOOL LogfInitializeNew(PLOGFILE LogFile)
     LogFile->Header.MajorVersion = MAJORVER;
     LogFile->Header.MinorVersion = MINORVER;
     LogFile->Header.CurrentRecordNumber = 1;
+    LogFile->Header.OldestRecordNumber = 1;
     /* FIXME: Read MaxSize from registry for this LogFile.
        But for now limit EventLog size to just under 5K. */
     LogFile->Header.MaxSize = 5000;
@@ -261,7 +262,7 @@ BOOL LogfInitializeExisting(PLOGFILE LogFile)
        But for now limit EventLog size to just under 5K. */
     LogFile->Header.MaxSize = 5000;
 
-    if (!SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
+    if (SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
         INVALID_SET_FILE_POINTER)
     {
         DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
@@ -364,7 +365,8 @@ PLOGFILE LogfCreate(WCHAR * LogName, WCHAR * FileName)
     if (!bResult)
         goto fail;
 
-    InitializeCriticalSection(&LogFile->cs);
+    RtlInitializeResource(&LogFile->Lock);
+
     LogfListAddItem(LogFile);
     return LogFile;
 
@@ -391,13 +393,13 @@ VOID LogfClose(PLOGFILE LogFile)
     if (LogFile == NULL)
         return;
 
-    EnterCriticalSection(&LogFile->cs);
+    RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
 
     FlushFileBuffers(LogFile->hFile);
     CloseHandle(LogFile->hFile);
     LogfListRemoveItem(LogFile);
 
-    DeleteCriticalSection(&LogFile->cs);
+    RtlDeleteResource(&LogFile->Lock);
 
     HeapFree(MyHeap, 0, LogFile->LogName);
     HeapFree(MyHeap, 0, LogFile->FileName);
@@ -511,7 +513,7 @@ PLOGFILE LogfListItemByIndex(INT Index)
     return Result;
 }
 
-INT LogfListItemCount()
+INT LogfListItemCount(VOID)
 {
     PLIST_ENTRY CurrentEntry;
     INT i = 0;
@@ -543,13 +545,171 @@ VOID LogfListRemoveItem(PLOGFILE Item)
     LeaveCriticalSection(&LogFileListCs);
 }
 
+static BOOL
+ReadAnsiLogEntry(HANDLE hFile,
+                 LPVOID lpBuffer,
+                 DWORD nNumberOfBytesToRead,
+                 LPDWORD lpNumberOfBytesRead)
+{
+    PEVENTLOGRECORD Dst;
+    PEVENTLOGRECORD Src;
+    ANSI_STRING StringA;
+    UNICODE_STRING StringW;
+    LPWSTR SrcPtr;
+    LPSTR DstPtr;
+    LPWSTR SrcString;
+    LPSTR DstString;
+    LPVOID lpUnicodeBuffer = NULL;
+    DWORD dwRead = 0;
+    DWORD i;
+    DWORD dwPadding;
+    DWORD dwEntryLength;
+    PDWORD pLength;
+    NTSTATUS Status;
+    BOOL ret = TRUE;
+
+    *lpNumberOfBytesRead = 0;
+
+    lpUnicodeBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nNumberOfBytesToRead);
+    if (lpUnicodeBuffer == NULL)
+    {
+        DPRINT1("Alloc failed!\n");
+        return FALSE;
+    }
+
+    if (!ReadFile(hFile, lpUnicodeBuffer, nNumberOfBytesToRead, &dwRead, NULL))
+    {
+        DPRINT1("Read failed!\n");
+        ret = FALSE;
+        goto done;
+    }
+
+    Dst = (PEVENTLOGRECORD)lpBuffer;
+    Src = (PEVENTLOGRECORD)lpUnicodeBuffer;
+
+    Dst->TimeGenerated = Src->TimeGenerated;
+    Dst->Reserved = Src->Reserved;
+    Dst->RecordNumber = Src->RecordNumber;
+    Dst->TimeWritten = Src->TimeWritten;
+    Dst->EventID = Src->EventID;
+    Dst->EventType = Src->EventType;
+    Dst->EventCategory = Src->EventCategory;
+    Dst->NumStrings = Src->NumStrings;
+    Dst->UserSidLength = Src->UserSidLength;
+    Dst->DataLength = Src->DataLength;
+
+    SrcPtr = (LPWSTR)((DWORD_PTR)Src + sizeof(EVENTLOGRECORD));
+    DstPtr = (LPSTR)((DWORD_PTR)Dst + sizeof(EVENTLOGRECORD));
+
+    /* Convert the module name */
+    RtlInitUnicodeString(&StringW, SrcPtr);
+    Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
+    if (NT_SUCCESS(Status))
+    {
+        RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength);
+
+        DstPtr = (PVOID)((DWORD_PTR)DstPtr + StringA.MaximumLength);
+
+        RtlFreeAnsiString(&StringA);
+    }
+
+    /* Convert the computer name */
+    if (NT_SUCCESS(Status))
+    {
+        SrcPtr = (PWSTR)((DWORD_PTR)SrcPtr + StringW.MaximumLength);
+
+        RtlInitUnicodeString(&StringW, SrcPtr);
+        Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
+        if (NT_SUCCESS(Status))
+        {
+            RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength);
+
+            DstPtr = (PVOID)((DWORD_PTR)DstPtr + StringA.MaximumLength);
+
+            RtlFreeAnsiString(&StringA);
+        }
+    }
+
+    /* Add the padding and the User SID*/
+    if (NT_SUCCESS(Status))
+    {
+        dwPadding = sizeof(DWORD) - (((DWORD_PTR)DstPtr - (DWORD_PTR)Dst) % sizeof(DWORD));
+        RtlZeroMemory(DstPtr, dwPadding);
+
+        DstPtr = (LPSTR)((DWORD_PTR)DstPtr + dwPadding);
+        RtlCopyMemory(DstPtr,
+                      (PVOID)((DWORD_PTR)Src + Src->UserSidOffset),
+                      Src->UserSidLength);
+
+        Dst->UserSidOffset = (DWORD)((DWORD_PTR)DstPtr - (DWORD_PTR)Dst);
+    }
+
+
+    /* Convert the strings */
+    if (NT_SUCCESS(Status))
+    {
+        DstPtr = (PVOID)((DWORD_PTR)DstPtr + Src->UserSidLength);
+
+        SrcString = (LPWSTR)((DWORD_PTR)Src + (DWORD)Src->StringOffset);
+        DstString = (LPSTR)DstPtr;
+
+        for (i = 0; i < Dst->NumStrings; i++)
+        {
+            RtlInitUnicodeString(&StringW, SrcString);
+
+            RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
+
+            RtlCopyMemory(DstString, StringA.Buffer, StringA.MaximumLength);
+
+            SrcString = (LPWSTR)((DWORD_PTR)SrcString +
+                                 (DWORD)StringW.MaximumLength);
+
+            DstString = (LPSTR)((DWORD_PTR)DstString +
+                                (DWORD)StringA.MaximumLength);
+
+            RtlFreeAnsiString(&StringA);
+        }
+
+        Dst->StringOffset = (DWORD)((DWORD_PTR)DstPtr - (DWORD_PTR)Dst);
+
+
+        /* Copy the binary data */
+        DstPtr = (PVOID)DstString;
+        Dst->DataOffset = (DWORD_PTR)DstPtr - (DWORD_PTR)Dst;
+
+        RtlCopyMemory(DstPtr, (PVOID)((DWORD_PTR)Src + Src->DataOffset), Src->DataLength);
+
+        /* Add the padding */
+        DstPtr = (PVOID)((DWORD_PTR)DstPtr + Src->DataLength);
+        dwPadding = sizeof(DWORD) - (((DWORD_PTR)DstPtr-(DWORD_PTR)Dst) % sizeof(DWORD));
+        RtlZeroMemory(DstPtr, dwPadding);
+
+        dwEntryLength = (DWORD)((DWORD_PTR)DstPtr + dwPadding + sizeof(DWORD) - (DWORD_PTR)Dst);
+
+        /* Set the entry length at the end of the entry*/
+        pLength = (PDWORD)((DWORD_PTR)DstPtr + dwPadding);
+        *pLength = dwEntryLength;
+        Dst->Length = dwEntryLength;
+
+        *lpNumberOfBytesRead = dwEntryLength;
+    }
+
+done:
+    if (lpUnicodeBuffer != NULL)
+        HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer);
+
+    return ret;
+}
+
+
 DWORD LogfReadEvent(PLOGFILE LogFile,
                    DWORD Flags,
                    DWORD * RecordNumber,
                    DWORD BufSize,
                    PBYTE Buffer,
                    DWORD * BytesRead,
-                   DWORD * BytesNeeded)
+                   DWORD * BytesNeeded,
+                   BOOL Ansi)
 {
     DWORD dwOffset, dwRead, dwRecSize;
     DWORD dwBufferUsage = 0, dwRecNum;
@@ -569,7 +729,8 @@ DWORD LogfReadEvent(PLOGFILE LogFile,
     }
 
     dwRecNum = *RecordNumber;
-    EnterCriticalSection(&LogFile->cs);
+
+    RtlAcquireResourceShared(&LogFile->Lock, TRUE);
 
     *BytesRead = 0;
     *BytesNeeded = 0;
@@ -578,7 +739,7 @@ DWORD LogfReadEvent(PLOGFILE LogFile,
 
     if (!dwOffset)
     {
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return ERROR_HANDLE_EOF;
     }
 
@@ -598,7 +759,7 @@ DWORD LogfReadEvent(PLOGFILE LogFile,
     if (dwRecSize > BufSize)
     {
         *BytesNeeded = dwRecSize;
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return ERROR_INSUFFICIENT_BUFFER;
     }
 
@@ -611,10 +772,21 @@ DWORD LogfReadEvent(PLOGFILE LogFile,
         goto Done;
     }
 
-    if (!ReadFile(LogFile->hFile, Buffer, dwRecSize, &dwRead, NULL))
+    if (Ansi == TRUE)
     {
-        DPRINT1("ReadFile() failed!\n");
-        goto Done;
+        if (!ReadAnsiLogEntry(LogFile->hFile, Buffer, dwRecSize, &dwRead))
+        {
+            DPRINT1("ReadAnsiLogEntry() failed!\n");
+            goto Done;
+        }
+    }
+    else
+    {
+        if (!ReadFile(LogFile->hFile, Buffer, dwRecSize, &dwRead, NULL))
+        {
+            DPRINT1("ReadFile() failed!\n");
+            goto Done;
+        }
     }
 
     dwBufferUsage += dwRead;
@@ -659,14 +831,28 @@ DWORD LogfReadEvent(PLOGFILE LogFile,
             goto Done;
         }
 
-        if (!ReadFile(LogFile->hFile,
-                      Buffer + dwBufferUsage,
-                      dwRecSize,
-                      &dwRead,
-                      NULL))
+        if (Ansi == TRUE)
         {
-            DPRINT1("ReadFile() failed!\n");
-            goto Done;
+            if (!ReadAnsiLogEntry(LogFile->hFile,
+                                  Buffer + dwBufferUsage,
+                                  dwRecSize,
+                                  &dwRead))
+            {
+                DPRINT1("ReadAnsiLogEntry() failed!\n");
+                goto Done;
+            }
+        }
+        else
+        {
+            if (!ReadFile(LogFile->hFile,
+                          Buffer + dwBufferUsage,
+                          dwRecSize,
+                          &dwRead,
+                          NULL))
+            {
+                DPRINT1("ReadFile() failed!\n");
+                goto Done;
+            }
         }
 
         dwBufferUsage += dwRead;
@@ -674,12 +860,12 @@ DWORD LogfReadEvent(PLOGFILE LogFile,
 
     *BytesRead = dwBufferUsage;
     * RecordNumber = dwRecNum;
-    LeaveCriticalSection(&LogFile->cs);
+    RtlReleaseResource(&LogFile->Lock);
     return ERROR_SUCCESS;
 
 Done:
     DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
-    LeaveCriticalSection(&LogFile->cs);
+    RtlReleaseResource(&LogFile->Lock);
     return GetLastError();
 }
 
@@ -700,11 +886,11 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
     GetSystemTime(&st);
     SystemTimeToEventTime(&st, &((PEVENTLOGRECORD) Buffer)->TimeWritten);
 
-    EnterCriticalSection(&LogFile->cs);
+    RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
 
     if (!GetFileSizeEx(LogFile->hFile, &logFileSize))
     {
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return FALSE;
     }
 
@@ -723,7 +909,7 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
             {
                 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
                 HeapFree(GetProcessHeap(), 0, RecBuf);
-                LeaveCriticalSection(&LogFile->cs);
+                RtlReleaseResource(&LogFile->Lock);
                 return FALSE;
             }
 
@@ -737,7 +923,7 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
             {
                 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
                 HeapFree(GetProcessHeap(), 0, RecBuf);
-                LeaveCriticalSection(&LogFile->cs);
+                RtlReleaseResource(&LogFile->Lock);
                 return FALSE;
             }
 
@@ -745,14 +931,14 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
             {
                 DPRINT1("ReadFile() failed!\n");
                 HeapFree(GetProcessHeap(), 0, RecBuf);
-                LeaveCriticalSection(&LogFile->cs);
+                RtlReleaseResource(&LogFile->Lock);
                 return FALSE;
             }
 
             if (RecBuf->Reserved != LOGFILE_SIGNATURE)
             {
                 DPRINT1("LogFile corrupt!\n");
-                LeaveCriticalSection(&LogFile->cs);
+                RtlReleaseResource(&LogFile->Lock);
                 return FALSE;
             }
 
@@ -780,14 +966,14 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
                        FILE_BEGIN) == INVALID_SET_FILE_POINTER)
     {
         DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return FALSE;
     }
 
     if (!WriteFile(LogFile->hFile, Buffer, BufSize, &dwWritten, NULL))
     {
         DPRINT1("WriteFile() failed! %d\n", GetLastError());
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return FALSE;
     }
 
@@ -795,15 +981,12 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
                                   LogFile->Header.CurrentRecordNumber,
                                   WriteOffSet))
     {
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return FALSE;
     }
 
     LogFile->Header.CurrentRecordNumber++;
 
-    if (LogFile->Header.OldestRecordNumber == 0)
-        LogFile->Header.OldestRecordNumber = 1;
-
     if (WriteOffSet == LogFile->Header.EndOffset)
     {
         LogFile->Header.EndOffset += dwWritten;
@@ -814,7 +997,7 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
                        FILE_BEGIN) == INVALID_SET_FILE_POINTER)
     {
         DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return FALSE;
     }
 
@@ -836,7 +1019,7 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
                    NULL))
     {
         DPRINT1("WriteFile() failed! %d\n", GetLastError());
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return FALSE;
     }
 
@@ -844,7 +1027,7 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
         INVALID_SET_FILE_POINTER)
     {
         DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return FALSE;
     }
 
@@ -855,24 +1038,244 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
                    NULL))
     {
         DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
-        LeaveCriticalSection(&LogFile->cs);
+        RtlReleaseResource(&LogFile->Lock);
         return FALSE;
     }
 
     if (!FlushFileBuffers(LogFile->hFile))
     {
-        LeaveCriticalSection(&LogFile->cs);
         DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
+        RtlReleaseResource(&LogFile->Lock);
         return FALSE;
     }
 
-    LeaveCriticalSection(&LogFile->cs);
+    RtlReleaseResource(&LogFile->Lock);
     return TRUE;
 }
 
-ULONG LogfOffsetByNumber(PLOGFILE LogFile, DWORD RecordNumber)
+
+NTSTATUS
+LogfClearFile(PLOGFILE LogFile,
+              PUNICODE_STRING BackupFileName)
+{
+    RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
+
+    if (BackupFileName->Length > 0)
+    {
+        /* FIXME: Write a backup file */
+    }
+
+    LogfInitializeNew(LogFile);
+
+    RtlReleaseResource(&LogFile->Lock);
+
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+LogfBackupFile(PLOGFILE LogFile,
+               PUNICODE_STRING BackupFileName)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    EVENTLOGHEADER Header;
+    EVENTLOGEOF EofRec;
+    HANDLE FileHandle = NULL;
+    ULONG i;
+    LARGE_INTEGER FileOffset;
+    NTSTATUS Status;
+    PUCHAR Buffer = NULL;
+
+    DWORD dwOffset, dwRead, dwRecSize;
+
+    DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile, BackupFileName);
+
+    /* Lock the log file shared */
+    RtlAcquireResourceShared(&LogFile->Lock, TRUE);
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               BackupFileName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtCreateFile(&FileHandle,
+                          GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+                          &ObjectAttributes,
+                          &IoStatusBlock,
+                          NULL,
+                          FILE_ATTRIBUTE_NORMAL,
+                          FILE_SHARE_READ,
+                          FILE_CREATE,
+                          FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
+                          NULL,
+                          0);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName, Status);
+        goto Done;
+    }
+
+    /* Initialize the (dirty) log file header */
+    Header.HeaderSize = sizeof(EVENTLOGHEADER);
+    Header.Signature = LOGFILE_SIGNATURE;
+    Header.MajorVersion = MAJORVER;
+    Header.MinorVersion = MINORVER;
+    Header.StartOffset = sizeof(EVENTLOGHEADER);
+    Header.EndOffset = sizeof(EVENTLOGHEADER);
+    Header.CurrentRecordNumber = 1;
+    Header.OldestRecordNumber = 1;
+    Header.MaxSize = 0;
+    Header.Flags = ELF_LOGFILE_HEADER_DIRTY;
+    Header.Retention = LogFile->Header.Retention;
+    Header.EndHeaderSize = sizeof(EVENTLOGHEADER);
+
+    /* Write the (dirty) log file header */
+    Status = NtWriteFile(FileHandle,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &IoStatusBlock,
+                         &Header,
+                         sizeof(EVENTLOGHEADER),
+                         NULL,
+                         NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status);
+        goto Done;
+    }
+
+    for (i = LogFile->Header.OldestRecordNumber; i < LogFile->Header.CurrentRecordNumber; i++)
+    {
+        dwOffset = LogfOffsetByNumber(LogFile, i);
+        if (dwOffset == 0)
+            break;
+
+        if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+        {
+            DPRINT1("SetFilePointer() failed!\n");
+            goto Done;
+        }
+
+        if (!ReadFile(LogFile->hFile, &dwRecSize, sizeof(DWORD), &dwRead, NULL))
+        {
+            DPRINT1("ReadFile() failed!\n");
+            goto Done;
+        }
+
+        if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+        {
+            DPRINT1("SetFilePointer() failed!\n");
+            goto Done;
+        }
+
+        Buffer = HeapAlloc(MyHeap, 0, dwRecSize);
+        if (Buffer == NULL)
+        {
+            DPRINT1("HeapAlloc() failed!\n");
+            goto Done;
+        }
+
+        if (!ReadFile(LogFile->hFile, &Buffer, dwRecSize, &dwRead, NULL))
+        {
+            DPRINT1("ReadFile() failed!\n");
+            goto Done;
+        }
+
+        /* Write the event record */
+        Status = NtWriteFile(FileHandle,
+                             NULL,
+                             NULL,
+                             NULL,
+                             &IoStatusBlock,
+                             Buffer,
+                             dwRecSize,
+                             NULL,
+                             NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("NtWriteFile() failed!\n");
+            goto Done;
+        }
+
+        /* Update the header information */
+        Header.EndOffset += dwRecSize;
+
+        /* Free the buffer */
+        HeapFree(MyHeap, 0, Buffer);
+        Buffer = NULL;
+    }
+
+    /* Initialize the EOF record */
+    EofRec.RecordSizeBeginning = sizeof(EVENTLOGEOF);
+    EofRec.Ones = 0x11111111;
+    EofRec.Twos = 0x22222222;
+    EofRec.Threes = 0x33333333;
+    EofRec.Fours = 0x44444444;
+    EofRec.BeginRecord = sizeof(EVENTLOGHEADER);
+    EofRec.EndRecord = Header.EndOffset;
+    EofRec.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
+    EofRec.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
+    EofRec.RecordSizeEnd = sizeof(EVENTLOGEOF);
+
+    /* Write the EOF record */
+    Status = NtWriteFile(FileHandle,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &IoStatusBlock,
+                         &EofRec,
+                         sizeof(EVENTLOGEOF),
+                         NULL,
+                         NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtWriteFile() failed!\n");
+        goto Done;
+    }
+
+    /* Update the header information */
+    Header.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
+    Header.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
+    Header.MaxSize = Header.EndOffset + sizeof(EVENTLOGEOF);
+    Header.Flags = 0;
+
+    /* Write the (clean) log file header */
+    FileOffset.QuadPart = 0;
+    Status = NtWriteFile(FileHandle,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &IoStatusBlock,
+                         &Header,
+                         sizeof(EVENTLOGHEADER),
+                         &FileOffset,
+                         NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtWriteFile() failed!\n");
+    }
+
+Done:
+    /* Free the buffer */
+    if (Buffer != NULL)
+        HeapFree(MyHeap, 0, Buffer);
+
+    /* Close the backup file */
+    if (FileHandle != NULL)
+        NtClose(FileHandle);
+
+    /* Unlock the log file */
+    RtlReleaseResource(&LogFile->Lock);
+
+    return Status;
+}
+
 
 /* Returns 0 if nothing found. */
+ULONG LogfOffsetByNumber(PLOGFILE LogFile, DWORD RecordNumber)
 {
     DWORD i;
 
@@ -1012,10 +1415,12 @@ PBYTE LogfAllocAndBuildNewRecord(LPDWORD lpRecSize,
     pos += (lstrlenW(ComputerName) + 1) * sizeof(WCHAR);
 
     pRec->UserSidOffset = pos;
+
+    if (pos % 4 != 0)
+        pos += 4 - (pos % 4);
+
     if (dwSidLength)
     {
-        if (pos % 4 != 0)
-            pos += 4 - (pos % 4);
         CopyMemory(Buffer + pos, lpUserSid, dwSidLength);
         pRec->UserSidLength = dwSidLength;
         pRec->UserSidOffset = pos;