[NTOS:IO][INCLUDES][EVENTLOG]: Fix support for event logging through the "ErrorLogPor...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 7 Nov 2016 13:29:09 +0000 (13:29 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 7 Nov 2016 13:29:09 +0000 (13:29 +0000)
svn path=/trunk/; revision=73167

reactos/base/services/eventlog/CMakeLists.txt
reactos/base/services/eventlog/eventlog.c
reactos/base/services/eventlog/eventlog.h
reactos/base/services/eventlog/file.c
reactos/base/services/eventlog/logport.c
reactos/base/services/eventlog/rpc.c
reactos/ntoskrnl/include/internal/io.h
reactos/ntoskrnl/io/iomgr/error.c
reactos/sdk/include/reactos/subsys/iolog/iolog.h [new file with mode: 0644]

index b5c4909..eafc415 100644 (file)
@@ -1,6 +1,7 @@
 
 include_directories(
     ${REACTOS_SOURCE_DIR}/sdk/lib/evtlib
+    ${REACTOS_SOURCE_DIR}/sdk/include/reactos/subsys
     ${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl
     ${CMAKE_CURRENT_BINARY_DIR})
 
index edb23bb..4e29c2e 100644 (file)
@@ -548,71 +548,73 @@ VOID PRINT_RECORD(PEVENTLOGRECORD pRec)
     LARGE_INTEGER SystemTime;
     TIME_FIELDS Time;
 
-    DPRINT("Length = %lu\n", pRec->Length);
-    DPRINT("Reserved = 0x%x\n", pRec->Reserved);
-    DPRINT("RecordNumber = %lu\n", pRec->RecordNumber);
+    DPRINT1("PRINT_RECORD(0x%p)\n", pRec);
+
+    DbgPrint("Length = %lu\n", pRec->Length);
+    DbgPrint("Reserved = 0x%x\n", pRec->Reserved);
+    DbgPrint("RecordNumber = %lu\n", pRec->RecordNumber);
 
     RtlSecondsSince1970ToTime(pRec->TimeGenerated, &SystemTime);
     RtlTimeToTimeFields(&SystemTime, &Time);
-    DPRINT("TimeGenerated = %hu.%hu.%hu %hu:%hu:%hu\n",
-           Time.Day, Time.Month, Time.Year,
-           Time.Hour, Time.Minute, Time.Second);
+    DbgPrint("TimeGenerated = %hu.%hu.%hu %hu:%hu:%hu\n",
+             Time.Day, Time.Month, Time.Year,
+             Time.Hour, Time.Minute, Time.Second);
 
     RtlSecondsSince1970ToTime(pRec->TimeWritten, &SystemTime);
     RtlTimeToTimeFields(&SystemTime, &Time);
-    DPRINT("TimeWritten = %hu.%hu.%hu %hu:%hu:%hu\n",
-           Time.Day, Time.Month, Time.Year,
-           Time.Hour, Time.Minute, Time.Second);
+    DbgPrint("TimeWritten = %hu.%hu.%hu %hu:%hu:%hu\n",
+             Time.Day, Time.Month, Time.Year,
+             Time.Hour, Time.Minute, Time.Second);
 
-    DPRINT("EventID = %lu\n", pRec->EventID);
+    DbgPrint("EventID = %lu\n", pRec->EventID);
 
     switch (pRec->EventType)
     {
         case EVENTLOG_ERROR_TYPE:
-            DPRINT("EventType = EVENTLOG_ERROR_TYPE\n");
+            DbgPrint("EventType = EVENTLOG_ERROR_TYPE\n");
             break;
         case EVENTLOG_WARNING_TYPE:
-            DPRINT("EventType = EVENTLOG_WARNING_TYPE\n");
+            DbgPrint("EventType = EVENTLOG_WARNING_TYPE\n");
             break;
         case EVENTLOG_INFORMATION_TYPE:
-            DPRINT("EventType = EVENTLOG_INFORMATION_TYPE\n");
+            DbgPrint("EventType = EVENTLOG_INFORMATION_TYPE\n");
             break;
         case EVENTLOG_AUDIT_SUCCESS:
-            DPRINT("EventType = EVENTLOG_AUDIT_SUCCESS\n");
+            DbgPrint("EventType = EVENTLOG_AUDIT_SUCCESS\n");
             break;
         case EVENTLOG_AUDIT_FAILURE:
-            DPRINT("EventType = EVENTLOG_AUDIT_FAILURE\n");
+            DbgPrint("EventType = EVENTLOG_AUDIT_FAILURE\n");
             break;
         default:
-            DPRINT("EventType = %hu\n", pRec->EventType);
+            DbgPrint("EventType = %hu\n", pRec->EventType);
     }
 
-    DPRINT("NumStrings = %hu\n", pRec->NumStrings);
-    DPRINT("EventCategory = %hu\n", pRec->EventCategory);
-    DPRINT("ReservedFlags = 0x%x\n", pRec->ReservedFlags);
-    DPRINT("ClosingRecordNumber = %lu\n", pRec->ClosingRecordNumber);
-    DPRINT("StringOffset = %lu\n", pRec->StringOffset);
-    DPRINT("UserSidLength = %lu\n", pRec->UserSidLength);
-    DPRINT("UserSidOffset = %lu\n", pRec->UserSidOffset);
-    DPRINT("DataLength = %lu\n", pRec->DataLength);
-    DPRINT("DataOffset = %lu\n", pRec->DataOffset);
-
-    DPRINT("SourceName: %S\n", (PWSTR)((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD)));
+    DbgPrint("NumStrings = %hu\n", pRec->NumStrings);
+    DbgPrint("EventCategory = %hu\n", pRec->EventCategory);
+    DbgPrint("ReservedFlags = 0x%x\n", pRec->ReservedFlags);
+    DbgPrint("ClosingRecordNumber = %lu\n", pRec->ClosingRecordNumber);
+    DbgPrint("StringOffset = %lu\n", pRec->StringOffset);
+    DbgPrint("UserSidLength = %lu\n", pRec->UserSidLength);
+    DbgPrint("UserSidOffset = %lu\n", pRec->UserSidOffset);
+    DbgPrint("DataLength = %lu\n", pRec->DataLength);
+    DbgPrint("DataOffset = %lu\n", pRec->DataOffset);
 
-    i = (wcslen((PWSTR)((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD))) + 1) * sizeof(WCHAR);
+    i = sizeof(EVENTLOGRECORD);
+    DbgPrint("SourceName: %S\n", (PWSTR)((ULONG_PTR)pRec + i));
 
-    DPRINT("ComputerName: %S\n", (PWSTR)((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD) + i));
+    i += (wcslen((PWSTR)((ULONG_PTR)pRec + i)) + 1) * sizeof(WCHAR);
+    DbgPrint("ComputerName: %S\n", (PWSTR)((ULONG_PTR)pRec + i));
 
     if (pRec->StringOffset < pRec->Length && pRec->NumStrings)
     {
-        DPRINT("Strings:\n");
+        DbgPrint("Strings:\n");
         str = (PWSTR)((ULONG_PTR)pRec + pRec->StringOffset);
         for (i = 0; i < pRec->NumStrings; i++)
         {
-            DPRINT("[%u] %S\n", i, str);
+            DbgPrint("[%u] %S\n", i, str);
             str += wcslen(str) + 1;
         }
     }
 
-    DPRINT("Length2 = %lu\n", *(PULONG)((ULONG_PTR)pRec + pRec->Length - 4));
+    DbgPrint("Length2 = %lu\n", *(PULONG)((ULONG_PTR)pRec + pRec->Length - 4));
 }
index fc64b5b..b13ef6d 100644 (file)
 #include <eventlogrpc_s.h>
 #include <strsafe.h>
 
-// FIXME: For that we may directly include NTOS header??
-typedef struct _IO_ERROR_LPC
-{
-    PORT_MESSAGE Header;
-    IO_ERROR_LOG_MESSAGE Message;
-} IO_ERROR_LPC, *PIO_ERROR_LPC;
-
-// C_ASSERT(sizeof(IO_ERROR_LPC) == 0x100);
-
 /* Defined in evtlib.h */
 // #define LOGFILE_SIGNATURE   0x654c664c  // "LfLe"
 
@@ -140,8 +131,8 @@ LogfAllocAndBuildNewRecord(PSIZE_T pRecSize,
                            USHORT  wType,
                            USHORT  wCategory,
                            ULONG   dwEventId,
-                           PCWSTR  SourceName,
-                           PCWSTR  ComputerName,
+                           PUNICODE_STRING SourceName,
+                           PUNICODE_STRING ComputerName,
                            ULONG   dwSidLength,
                            PSID    pUserSid,
                            USHORT  wNumStrings,
index 95db1b3..0643e29 100644 (file)
@@ -898,8 +898,8 @@ LogfAllocAndBuildNewRecord(PSIZE_T pRecSize,
                            USHORT  wType,
                            USHORT  wCategory,
                            ULONG   dwEventId,
-                           PCWSTR  SourceName,
-                           PCWSTR  ComputerName,
+                           PUNICODE_STRING SourceName,
+                           PUNICODE_STRING ComputerName,
                            ULONG   dwSidLength,
                            PSID    pUserSid,
                            USHORT  wNumStrings,
@@ -908,16 +908,17 @@ LogfAllocAndBuildNewRecord(PSIZE_T pRecSize,
                            PVOID   pRawData)
 {
     SIZE_T RecSize;
+    SIZE_T SourceNameSize, ComputerNameSize, StringLen;
     PBYTE Buffer;
     PEVENTLOGRECORD pRec;
     PWSTR str;
     UINT i, pos;
-    SIZE_T SourceNameLen, ComputerNameLen, StringLen;
 
-    SourceNameLen = (SourceName ? wcslen(SourceName) : 0) + 1;
-    ComputerNameLen = (ComputerName ? wcslen(ComputerName) : 0) + 1;
+    SourceNameSize   = (SourceName   && SourceName->Buffer)   ? SourceName->Length   : 0;
+    ComputerNameSize = (ComputerName && ComputerName->Buffer) ? ComputerName->Length : 0;
 
-    RecSize = sizeof(EVENTLOGRECORD) + (SourceNameLen + ComputerNameLen) * sizeof(WCHAR);
+    RecSize = sizeof(EVENTLOGRECORD) + /* Add the sizes of the strings, NULL-terminated */
+        SourceNameSize + ComputerNameSize + 2*sizeof(UNICODE_NULL);
 
     /* Align on DWORD boundary for the SID */
     RecSize = ROUND_UP(RecSize, sizeof(ULONG));
@@ -975,12 +976,19 @@ LogfAllocAndBuildNewRecord(PSIZE_T pRecSize,
 
     pos = sizeof(EVENTLOGRECORD);
 
-    if (SourceName)
-        StringCchCopyW((PWSTR)(Buffer + pos), SourceNameLen, SourceName);
-    pos += SourceNameLen * sizeof(WCHAR);
-    if (ComputerName)
-        StringCchCopyW((PWSTR)(Buffer + pos), ComputerNameLen, ComputerName);
-    pos += ComputerNameLen * sizeof(WCHAR);
+    /* NOTE: Equivalents of RtlStringCbCopyUnicodeString calls */
+    if (SourceNameSize)
+    {
+        StringCbCopyNW((PWSTR)(Buffer + pos), SourceNameSize + sizeof(UNICODE_NULL),
+                       SourceName->Buffer, SourceNameSize);
+    }
+    pos += SourceNameSize + sizeof(UNICODE_NULL);
+    if (ComputerNameSize)
+    {
+        StringCbCopyNW((PWSTR)(Buffer + pos), ComputerNameSize + sizeof(UNICODE_NULL),
+                       ComputerName->Buffer, ComputerNameSize);
+    }
+    pos += ComputerNameSize + sizeof(UNICODE_NULL);
 
     /* Align on DWORD boundary for the SID */
     pos = ROUND_UP(pos, sizeof(ULONG));
@@ -1035,20 +1043,24 @@ LogfReportEvent(USHORT wType,
                 PVOID  pRawData)
 {
     NTSTATUS Status;
-    WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
-    DWORD dwComputerNameLength = MAX_COMPUTERNAME_LENGTH + 1;
+    UNICODE_STRING SourceName, ComputerName;
     PEVENTLOGRECORD LogBuffer;
     LARGE_INTEGER SystemTime;
     ULONG Time;
     SIZE_T RecSize;
+    DWORD dwComputerNameLength;
+    WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
 
     if (!EventLogSource)
         return;
 
+    RtlInitUnicodeString(&SourceName, EventLogSource->szName);
+
+    dwComputerNameLength = ARRAYSIZE(szComputerName);
     if (!GetComputerNameW(szComputerName, &dwComputerNameLength))
-    {
         szComputerName[0] = L'\0';
-    }
+
+    RtlInitUnicodeString(&ComputerName, szComputerName);
 
     NtQuerySystemTime(&SystemTime);
     RtlTimeToSecondsSince1970(&SystemTime, &Time);
@@ -1058,14 +1070,19 @@ LogfReportEvent(USHORT wType,
                                            wType,
                                            wCategory,
                                            dwEventId,
-                                           EventLogSource->szName,
-                                           szComputerName,
+                                           &SourceName,
+                                           &ComputerName,
                                            0,
                                            NULL,
                                            wNumStrings,
                                            pStrings,
                                            dwDataSize,
                                            pRawData);
+    if (LogBuffer == NULL)
+    {
+        DPRINT1("LogfAllocAndBuildNewRecord failed!\n");
+        return;
+    }
 
     Status = LogfWriteRecord(EventLogSource->LogFile, LogBuffer, RecSize);
     if (!NT_SUCCESS(Status))
index 0af242a..2294eb7 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "eventlog.h"
 #include <ndk/lpcfuncs.h>
+#include <iolog/iolog.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -46,22 +47,20 @@ NTSTATUS WINAPI PortThreadRoutine(PVOID Param)
 NTSTATUS InitLogPort(VOID)
 {
     NTSTATUS Status;
-    UNICODE_STRING PortName;
+    UNICODE_STRING PortName = RTL_CONSTANT_STRING(ELF_PORT_NAME);
     OBJECT_ATTRIBUTES ObjectAttributes;
     PORT_MESSAGE Request;
 
     ConnectPortHandle = NULL;
     MessagePortHandle = NULL;
 
-    RtlInitUnicodeString(&PortName, L"\\ErrorLogPort");
     InitializeObjectAttributes(&ObjectAttributes, &PortName, 0, NULL, NULL);
 
     Status = NtCreatePort(&ConnectPortHandle,
                           &ObjectAttributes,
                           0,
-                          0x100,
-                          0x2000);
-
+                          PORT_MAXIMUM_MESSAGE_LENGTH, // IO_ERROR_LOG_MESSAGE_LENGTH,
+                          2 * PAGE_SIZE);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtCreatePort() failed (Status %lx)\n", Status);
@@ -76,7 +75,7 @@ NTSTATUS InitLogPort(VOID)
     }
 
     Status = NtAcceptConnectPort(&MessagePortHandle, ConnectPortHandle,
-                                 NULL, TRUE, NULL, NULL);
+                                 &Request, TRUE, NULL, NULL);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtAcceptConnectPort() failed (Status %lx)\n", Status);
@@ -105,14 +104,17 @@ ByeBye:
 NTSTATUS ProcessPortMessage(VOID)
 {
     NTSTATUS Status;
-    IO_ERROR_LPC Request;
-    PIO_ERROR_LOG_MESSAGE Message;
-    ULONG Time;
-    PEVENTLOGRECORD pRec;
-    SIZE_T RecSize;
     PLOGFILE SystemLog = NULL;
+    UCHAR Buffer[PORT_MAXIMUM_MESSAGE_LENGTH]; // IO_ERROR_LOG_MESSAGE_LENGTH
+    PELF_API_MSG Message = (PELF_API_MSG)Buffer;
+    PIO_ERROR_LOG_MESSAGE ErrorMessage;
+    PEVENTLOGRECORD LogBuffer;
+    SIZE_T RecSize;
+    ULONG Time;
+    USHORT EventType;
+    UNICODE_STRING SourceName, ComputerName;
+    DWORD dwComputerNameLength;
     WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
-    DWORD dwComputerNameLength = MAX_COMPUTERNAME_LENGTH + 1;
 
     DPRINT("ProcessPortMessage() called\n");
 
@@ -121,9 +123,9 @@ NTSTATUS ProcessPortMessage(VOID)
     while (TRUE)
     {
         Status = NtReplyWaitReceivePort(MessagePortHandle,
-                                        0,
                                         NULL,
-                                        &Request.Header);
+                                        NULL,
+                                        &Message->Header);
 
         if (!NT_SUCCESS(Status))
         {
@@ -133,69 +135,108 @@ NTSTATUS ProcessPortMessage(VOID)
 
         DPRINT("Received message\n");
 
-        if (Request.Header.u2.s2.Type == LPC_PORT_CLOSED)
+        if (Message->Header.u2.s2.Type == LPC_PORT_CLOSED)
         {
             DPRINT("Port closed\n");
             return STATUS_SUCCESS;
         }
 
-        if (Request.Header.u2.s2.Type == LPC_REQUEST)
+        if (Message->Header.u2.s2.Type == LPC_REQUEST)
         {
             DPRINT("Received request\n");
         }
-        else if (Request.Header.u2.s2.Type == LPC_DATAGRAM)
+        else if (Message->Header.u2.s2.Type == LPC_DATAGRAM)
         {
-            DPRINT("Received datagram\n");
-            // Message = (PIO_ERROR_LOG_MESSAGE)&Request.Message;
-            Message = &Request.Message;
+            DPRINT("Received datagram (0x%x, 0x%x)\n",
+                   Message->Unknown[0], Message->Unknown[1]);
+            ErrorMessage = &Message->IoErrorMessage;
 
-            if (!GetComputerNameW(szComputerName, &dwComputerNameLength))
+            // ASSERT(ErrorMessage->Type == IO_TYPE_ERROR_MESSAGE);
+
+            RtlInitEmptyUnicodeString(&SourceName, NULL, 0);
+            if (ErrorMessage->DriverNameLength > sizeof(UNICODE_NULL)) // DriverNameLength counts NULL-terminator
             {
-                szComputerName[0] = L'\0';
+                SourceName.Buffer = (PWSTR)((ULONG_PTR)ErrorMessage + ErrorMessage->DriverNameOffset);
+                SourceName.MaximumLength = ErrorMessage->DriverNameLength;
+                SourceName.Length = SourceName.MaximumLength - sizeof(UNICODE_NULL);
             }
 
-            RtlTimeToSecondsSince1970(&Message->TimeStamp, &Time);
-
-            // TODO: Log more information??
-
-            pRec = LogfAllocAndBuildNewRecord(
-                        &RecSize,
-                        Time,
-                        Message->Type,
-                        Message->EntryData.EventCategory,
-                        Message->EntryData.ErrorCode,
-                        (PWSTR)((ULONG_PTR)Message + Message->DriverNameOffset), // FIXME: Use DriverNameLength too!
-                        szComputerName,
-                        0,
-                        NULL,
-                        Message->EntryData.NumberOfStrings,
-                        (PWSTR)((ULONG_PTR)Message + Message->EntryData.StringOffset),
-                        Message->EntryData.DumpDataSize,
-                        (PVOID)((ULONG_PTR)Message + FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)));
-
-            if (pRec == NULL)
+            dwComputerNameLength = ARRAYSIZE(szComputerName);
+            if (!GetComputerNameW(szComputerName, &dwComputerNameLength))
+                szComputerName[0] = L'\0';
+
+            RtlInitUnicodeString(&ComputerName, szComputerName);
+
+            RtlTimeToSecondsSince1970(&ErrorMessage->TimeStamp, &Time);
+
+            /* Set the event type based on the error code severity */
+            EventType = (USHORT)(ErrorMessage->EntryData.ErrorCode >> 30);
+            if (EventType == STATUS_SEVERITY_SUCCESS)
             {
-                DPRINT("LogfAllocAndBuildNewRecord failed!\n");
-                return STATUS_NO_MEMORY;
+                EventType = EVENTLOG_SUCCESS;
+            }
+            else if (EventType == STATUS_SEVERITY_INFORMATIONAL) // NT_INFORMATION
+            {
+                EventType = EVENTLOG_INFORMATION_TYPE;
+            }
+            else if (EventType == STATUS_SEVERITY_WARNING)       // NT_WARNING
+            {
+                EventType = EVENTLOG_WARNING_TYPE;
+            }
+            else if (EventType == STATUS_SEVERITY_ERROR)         // NT_ERROR
+            {
+                EventType = EVENTLOG_ERROR_TYPE;
+            }
+            else
+            {
+                /* Unknown severity, set to error */
+                EventType = EVENTLOG_ERROR_TYPE;
             }
 
-            DPRINT("RecSize = %d\n", RecSize);
-
-            DPRINT("\n --- EVENTLOG RECORD ---\n");
-            PRINT_RECORD(pRec);
-            DPRINT("\n");
+            /*
+             * The data being saved consists of the IO_ERROR_LOG_PACKET structure
+             * header, plus the additional raw data from the driver.
+             */
+            LogBuffer = LogfAllocAndBuildNewRecord(
+                            &RecSize,
+                            Time,
+                            EventType,
+                            ErrorMessage->EntryData.EventCategory,
+                            ErrorMessage->EntryData.ErrorCode,
+                            &SourceName,
+                            &ComputerName,
+                            0,
+                            NULL,
+                            ErrorMessage->EntryData.NumberOfStrings,
+                            (PWSTR)((ULONG_PTR)ErrorMessage +
+                                ErrorMessage->EntryData.StringOffset),
+                            FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) +
+                                ErrorMessage->EntryData.DumpDataSize,
+                            (PVOID)&ErrorMessage->EntryData);
+            if (LogBuffer == NULL)
+            {
+                DPRINT1("LogfAllocAndBuildNewRecord failed!\n");
+                // return STATUS_NO_MEMORY;
+                continue;
+            }
 
             if (!onLiveCD && SystemLog)
             {
-                Status = LogfWriteRecord(SystemLog, pRec, RecSize);
+                Status = LogfWriteRecord(SystemLog, LogBuffer, RecSize);
                 if (!NT_SUCCESS(Status))
                 {
                     DPRINT1("ERROR writing to event log `%S' (Status 0x%08lx)\n",
                             SystemLog->LogName, Status);
                 }
             }
+            else
+            {
+                DPRINT1("\n--- EVENTLOG RECORD ---\n");
+                PRINT_RECORD(LogBuffer);
+                DPRINT1("\n");
+            }
 
-            LogfFreeRecord(pRec);
+            LogfFreeRecord(LogBuffer);
         }
     }
 
index 40290fc..01cd920 100644 (file)
@@ -586,6 +586,7 @@ ElfrIntReportEventW(
 {
     NTSTATUS Status;
     PLOGHANDLE pLogHandle;
+    UNICODE_STRING LocalSourceName, LocalComputerName;
     PEVENTLOGRECORD LogBuffer;
     USHORT i;
     SIZE_T RecSize;
@@ -655,21 +656,32 @@ ElfrIntReportEventW(
     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,
-                                           (SourceName && SourceName->Buffer)
-                                                ? SourceName->Buffer
-                                                : pLogHandle->szName,
-                                           ComputerName->Buffer,
+                                           &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))
index 0b2af9d..bd3f568 100644 (file)
@@ -5,6 +5,7 @@
 * PURPOSE:         Internal header for the I/O Manager
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
 */
+
 #include "ntdddisk.h"
 
 //
@@ -332,16 +333,6 @@ typedef struct _ERROR_LOG_ENTRY
     LARGE_INTEGER TimeStamp;
 } ERROR_LOG_ENTRY, *PERROR_LOG_ENTRY;
 
-//
-// Event Log LPC Message
-//
-typedef struct _ELF_API_MSG
-{
-    PORT_MESSAGE h;
-    ULONG Unknown[2];
-    IO_ERROR_LOG_MESSAGE IoErrorMessage;
-} ELF_API_MSG, *PELF_API_MSG;
-
 //
 // To simplify matters, the kernel is made to support both the checked and free
 // version of the I/O Remove Lock in the same binary. This structure includes
index f6817da..e21cb90 100644 (file)
@@ -6,9 +6,12 @@
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  *                  Eric Kohl
  */
+
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
+#include <subsys/iolog/iolog.h>
+
 #define NDEBUG
 #include <debug.h>
 
@@ -22,6 +25,7 @@ typedef struct _IOP_ERROR_LOG_WORKER_DPC
 
 /* GLOBALS *******************************************************************/
 
+#define IOP_MAXIMUM_LOG_SIZE    (100 * PAGE_SIZE)
 LONG IopTotalLogSize;
 LIST_ENTRY IopErrorLogListHead;
 KSPIN_LOCK IopLogListLock;
@@ -105,16 +109,23 @@ BOOLEAN
 NTAPI
 IopConnectLogPort(VOID)
 {
-    UNICODE_STRING PortName = RTL_CONSTANT_STRING(L"\\ErrorLogPort");
     NTSTATUS Status;
+    UNICODE_STRING PortName = RTL_CONSTANT_STRING(ELF_PORT_NAME);
+    SECURITY_QUALITY_OF_SERVICE SecurityQos;
 
     /* Make sure we're not already connected */
     if (IopLogPortConnected) return TRUE;
 
+    /* Setup the QoS structure */
+    SecurityQos.Length = sizeof(SecurityQos);
+    SecurityQos.ImpersonationLevel = SecurityIdentification;
+    SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
+    SecurityQos.EffectiveOnly = TRUE;
+
     /* Connect the port */
     Status = ZwConnectPort(&IopLogPort,
                            &PortName,
-                           NULL,
+                           &SecurityQos,
                            NULL,
                            NULL,
                            NULL,
@@ -136,6 +147,9 @@ VOID
 NTAPI
 IopLogWorker(IN PVOID Parameter)
 {
+#define IO_ERROR_OBJECT_NAMES_LENGTH    100
+
+    NTSTATUS Status;
     PELF_API_MSG Message;
     PIO_ERROR_LOG_MESSAGE ErrorMessage;
     PLIST_ENTRY ListEntry;
@@ -144,22 +158,24 @@ IopLogWorker(IN PVOID Parameter)
     PCHAR StringBuffer;
     ULONG RemainingLength;
     PDRIVER_OBJECT DriverObject;
-    ULONG DriverNameLength = 0, DeviceNameLength;
-    UNICODE_STRING DriverNameString;
-    NTSTATUS Status;
-    UCHAR Buffer[256];
+    PWCHAR NameString;
+    ULONG DriverNameLength, DeviceNameLength;
+    UCHAR Buffer[sizeof(OBJECT_NAME_INFORMATION) + IO_ERROR_OBJECT_NAMES_LENGTH];
     POBJECT_NAME_INFORMATION ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer;
-    POBJECT_NAME_INFORMATION PoolObjectNameInfo = NULL;
+    POBJECT_NAME_INFORMATION PoolObjectNameInfo;
     ULONG ReturnedLength, MessageLength;
-    PWCHAR p;
     ULONG ExtraStringLength;
+    PWCHAR p;
+
     PAGED_CODE();
 
+    UNREFERENCED_PARAMETER(Parameter);
+
     /* Connect to the port */
     if (!IopConnectLogPort()) return;
 
     /* Allocate the message */
-    Message = ExAllocatePool(PagedPool, IO_ERROR_LOG_MESSAGE_LENGTH);
+    Message = ExAllocatePoolWithTag(PagedPool, IO_ERROR_LOG_MESSAGE_LENGTH, TAG_IO);
     if (!Message)
     {
         /* Couldn't allocate, try again */
@@ -167,10 +183,8 @@ IopLogWorker(IN PVOID Parameter)
         return;
     }
 
-    /* Copy the message */
-    RtlZeroMemory(Message, sizeof(ELF_API_MSG));
-
-    /* Get the actual I/O Structure */
+    /* Zero out the message and get the actual I/O structure */
+    RtlZeroMemory(Message, sizeof(*Message));
     ErrorMessage = &Message->IoErrorMessage;
 
     /* Start loop */
@@ -225,21 +239,28 @@ IopLogWorker(IN PVOID Parameter)
                                   IO_ERROR_LOG_MESSAGE_LENGTH -
                                   (ULONG_PTR)StringBuffer);
 
+        NameString = NULL;
+        DriverNameLength = 0; DeviceNameLength = 0;
+        PoolObjectNameInfo = NULL;
+        ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer;
+
         /* Now check if there is a driver object */
         DriverObject = LogEntry->DriverObject;
         if (DriverObject)
         {
-            /* Check if the driver has a name */
+            /* Check if the driver has a name, and use it if so */
             if (DriverObject->DriverName.Buffer)
             {
-                /* Use its name */
-                DriverNameString.Buffer = DriverObject->DriverName.Buffer;
+                NameString = DriverObject->DriverName.Buffer;
                 DriverNameLength = DriverObject->DriverName.Length;
             }
             else
-                DriverNameString.Buffer = NULL;
+            {
+                NameString = NULL;
+                DriverNameLength = 0;
+            }
 
-            /* Check if there isn't a valid name*/
+            /* Check if there isn't a valid name */
             if (!DriverNameLength)
             {
                 /* Query the name directly */
@@ -247,30 +268,35 @@ IopLogWorker(IN PVOID Parameter)
                                            ObjectNameInfo,
                                            sizeof(Buffer),
                                            &ReturnedLength);
-                if (!(NT_SUCCESS(Status)) || !(ObjectNameInfo->Name.Length))
+                if (!NT_SUCCESS(Status) || (ObjectNameInfo->Name.Length == 0))
                 {
                     /* We don't have a name */
                     DriverNameLength = 0;
                 }
+                else
+                {
+                    NameString = ObjectNameInfo->Name.Buffer;
+                    DriverNameLength = ObjectNameInfo->Name.Length;
+                }
             }
         }
         else
         {
             /* Use default name */
-            DriverNameString.Buffer = L"Application Popup";
-            DriverNameLength = (ULONG)wcslen(DriverNameString.Buffer) * sizeof(WCHAR);
+            NameString = L"Application Popup";
+            DriverNameLength = (ULONG)wcslen(NameString) * sizeof(WCHAR);
         }
 
-        /* Check if we have a driver name by here */
+        /* Check if we have a driver name */
         if (DriverNameLength)
         {
             /* Skip to the end of the driver's name */
-            p = &DriverNameString.Buffer[DriverNameLength / sizeof(WCHAR)];
+            p = &NameString[DriverNameLength / sizeof(WCHAR)];
 
             /* Now we'll walk backwards and assume the minimum size */
             DriverNameLength = sizeof(WCHAR);
             p--;
-            while ((*p != L'\\') && (p != DriverNameString.Buffer))
+            while ((*p != L'\\') && (p != NameString))
             {
                 /* No backslash found, keep going */
                 p--;
@@ -285,8 +311,9 @@ IopLogWorker(IN PVOID Parameter)
             }
 
             /*
-             * Now make sure that the driver name fits in our buffer, minus 3
-             * NULL chars, and copy the name in our string buffer
+             * Now make sure that the driver name fits in the buffer, minus
+             * 3 NULL chars (driver name, device name, and remaining strings),
+             * and copy the driver name in the string buffer.
              */
             DriverNameLength = min(DriverNameLength,
                                    RemainingLength - 3 * sizeof(UNICODE_NULL));
@@ -294,29 +321,29 @@ IopLogWorker(IN PVOID Parameter)
         }
 
         /* Null-terminate the driver name */
-        *((PWSTR)(StringBuffer + DriverNameLength)) = L'\0';
+        *((PWSTR)(StringBuffer + DriverNameLength)) = UNICODE_NULL;
         DriverNameLength += sizeof(WCHAR);
 
         /* Go to the next string buffer position */
         StringBuffer += DriverNameLength;
         RemainingLength -= DriverNameLength;
 
-        /* Update the string offset and check if we have a device object */
-        ErrorMessage->EntryData.StringOffset = (USHORT)
-                                               ((ULONG_PTR)StringBuffer -
-                                               (ULONG_PTR)ErrorMessage);
+        /* Update the string offset */
+        ErrorMessage->EntryData.StringOffset =
+            (USHORT)((ULONG_PTR)StringBuffer - (ULONG_PTR)ErrorMessage);
+
+        /* Check if we have a device object */
         if (LogEntry->DeviceObject)
         {
             /* We do, query its name */
             Status = ObQueryNameString(LogEntry->DeviceObject,
                                        ObjectNameInfo,
-                                       sizeof(Buffer),
+                                       sizeof(Buffer) - DriverNameLength,
                                        &ReturnedLength);
             if (!NT_SUCCESS(Status) || (ObjectNameInfo->Name.Length == 0))
             {
                 /* Setup an empty name */
-                ObjectNameInfo->Name.Length = 0;
-                ObjectNameInfo->Name.Buffer = L"";
+                RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, L"", 0);
 
                 /* Check if we failed because our buffer wasn't large enough */
                 if (Status == STATUS_INFO_LENGTH_MISMATCH)
@@ -337,39 +364,40 @@ IopLogWorker(IN PVOID Parameter)
                         {
                             /* Success, update the information */
                             ObjectNameInfo->Name.Length =
-                                100 - (USHORT)DriverNameLength;
+                                IO_ERROR_OBJECT_NAMES_LENGTH - (USHORT)DriverNameLength;
                         }
                     }
                 }
             }
+
+            NameString = ObjectNameInfo->Name.Buffer;
+            DeviceNameLength = ObjectNameInfo->Name.Length;
         }
         else
         {
             /* No device object, setup an empty name */
-            ObjectNameInfo->Name.Length = 0;
-            ObjectNameInfo->Name.Buffer = L"";
+            NameString = L"";
+            DeviceNameLength = 0;
         }
 
         /*
-         * Now make sure that the device name fits in our buffer, minus 2
-         * NULL chars, and copy the name in our string buffer
+         * Now make sure that the device name fits in the buffer, minus
+         * 2 NULL chars (device name, and remaining strings), and copy
+         * the device name in the string buffer.
          */
-        DeviceNameLength = min(ObjectNameInfo->Name.Length,
+        DeviceNameLength = min(DeviceNameLength,
                                RemainingLength - 2 * sizeof(UNICODE_NULL));
-        RtlCopyMemory(StringBuffer,
-                      ObjectNameInfo->Name.Buffer,
-                      DeviceNameLength);
+        RtlCopyMemory(StringBuffer, NameString, DeviceNameLength);
 
         /* Null-terminate the device name */
-        *((PWSTR)(StringBuffer + DeviceNameLength)) = L'\0';
+        *((PWSTR)(StringBuffer + DeviceNameLength)) = UNICODE_NULL;
         DeviceNameLength += sizeof(WCHAR);
 
         /* Free the buffer if we had one */
         if (PoolObjectNameInfo)
         {
-            ExFreePool(PoolObjectNameInfo);
+            ExFreePoolWithTag(PoolObjectNameInfo, TAG_IO);
             PoolObjectNameInfo = NULL;
-            ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer;
         }
 
         /* Go to the next string buffer position */
@@ -385,6 +413,9 @@ IopLogWorker(IN PVOID Parameter)
                                 sizeof(ERROR_LOG_ENTRY) -
                                 Packet->StringOffset;
 
+            /* Round up the length */
+            ExtraStringLength = ROUND_UP(ExtraStringLength, sizeof(WCHAR));
+
             /* Make sure that the extra strings fit in our buffer */
             if (ExtraStringLength > (RemainingLength - sizeof(UNICODE_NULL)))
             {
@@ -399,50 +430,58 @@ IopLogWorker(IN PVOID Parameter)
                           ExtraStringLength);
 
             /* Null-terminate them */
-            *((PWSTR)(StringBuffer + ExtraStringLength)) = L'\0';
+            *((PWSTR)(StringBuffer + ExtraStringLength)) = UNICODE_NULL;
         }
 
         /* Set the driver name length */
         ErrorMessage->DriverNameLength = (USHORT)DriverNameLength;
 
-        /* Update the message length to include the device and driver names */
-        MessageLength += DeviceNameLength + DriverNameLength;
+        /* Update the message length to include the driver and device names */
+        MessageLength += DriverNameLength + DeviceNameLength;
         ErrorMessage->Size = (USHORT)MessageLength;
 
-        /* Now update it again, internally, for the size of the actual LPC */
+        /* Now update it again for the size of the actual LPC */
         MessageLength += (FIELD_OFFSET(ELF_API_MSG, IoErrorMessage) -
                           FIELD_OFFSET(ELF_API_MSG, Unknown[0]));
 
         /* Set the total and data lengths */
-        Message->h.u1.s1.TotalLength = (USHORT)(sizeof(PORT_MESSAGE) +
-                                                MessageLength);
-        Message->h.u1.s1.DataLength = (USHORT)(MessageLength);
+        Message->Header.u1.s1.TotalLength =
+            (USHORT)(sizeof(PORT_MESSAGE) + MessageLength);
+        Message->Header.u1.s1.DataLength = (USHORT)MessageLength;
 
         /* Send the message */
-        Status = NtRequestPort(IopLogPort, (PPORT_MESSAGE)Message);
+        Status = ZwRequestPort(IopLogPort, &Message->Header);
         if (!NT_SUCCESS(Status))
         {
-            /* Requeue log message and restart the worker */
-            ExInterlockedInsertTailList(&IopErrorLogListHead,
+            /*
+             * An error happened while sending the message on the port.
+             * Close the port, requeue the log message on top of the list
+             * and restart the worker.
+             */
+            ZwClose(IopLogPort);
+            IopLogPortConnected = FALSE;
+
+            ExInterlockedInsertHeadList(&IopErrorLogListHead,
                                         &LogEntry->ListEntry,
                                         &IopLogListLock);
-            IopLogWorkerRunning = FALSE;
+
             IopRestartLogWorker();
             break;
         }
 
-        /* Dereference the device object */
+        /* NOTE: The following is basically 'IoFreeErrorLogEntry(Packet)' */
+
+        /* Dereference both objects */
         if (LogEntry->DeviceObject) ObDereferenceObject(LogEntry->DeviceObject);
-        if (DriverObject) ObDereferenceObject(LogEntry->DriverObject);
+        if (LogEntry->DriverObject) ObDereferenceObject(LogEntry->DriverObject);
 
-        /* Update size */
-        InterlockedExchangeAdd(&IopTotalLogSize,
-                               -(LONG)(LogEntry->Size -
-                                       sizeof(ERROR_LOG_ENTRY)));
+        /* Decrease the total allocation size and free the entry */
+        InterlockedExchangeAdd(&IopTotalLogSize, -(LONG)LogEntry->Size);
+        ExFreePoolWithTag(LogEntry, TAG_ERROR_LOG);
     }
 
     /* Free the LPC Message */
-    ExFreePool(Message);
+    ExFreePoolWithTag(Message, TAG_IO);
 }
 
 VOID
@@ -495,17 +534,15 @@ IoAllocateErrorLogEntry(IN PVOID IoObject,
     /* Make sure we have an object */
     if (!IoObject) return NULL;
 
-    /* Check if we're past our buffer */
-    if (IopTotalLogSize > PAGE_SIZE) return NULL;
-
     /* Check if this is a device object or driver object */
-    if (((PDEVICE_OBJECT)IoObject)->Type == IO_TYPE_DEVICE)
+    DeviceObject = (PDEVICE_OBJECT)IoObject;
+    if (DeviceObject->Type == IO_TYPE_DEVICE)
     {
         /* It's a device, get the driver */
-        DeviceObject = (PDEVICE_OBJECT)IoObject;
+        // DeviceObject = (PDEVICE_OBJECT)IoObject;
         DriverObject = DeviceObject->DriverObject;
     }
-    else if (((PDEVICE_OBJECT)IoObject)->Type == IO_TYPE_DRIVER)
+    else if (DeviceObject->Type == IO_TYPE_DRIVER)
     {
         /* It's a driver, so we don't have a device */
         DeviceObject = NULL;
@@ -517,6 +554,21 @@ IoAllocateErrorLogEntry(IN PVOID IoObject,
         return NULL;
     }
 
+    /* Check if we're past our buffer */
+    // FIXME/TODO: Perform the checks by taking into account EntrySize.
+    if (IopTotalLogSize > IOP_MAXIMUM_LOG_SIZE) return NULL;
+
+    /* Check whether the size is too small or too large */
+    if ((EntrySize < sizeof(IO_ERROR_LOG_PACKET)) ||
+        (EntrySize > ERROR_LOG_MAXIMUM_SIZE))
+    {
+        /* Fail */
+        return NULL;
+    }
+
+    /* Round up the size */
+    EntrySize = ROUND_UP(EntrySize, sizeof(PVOID));
+
     /* Calculate the total size and allocate it */
     LogEntrySize = sizeof(ERROR_LOG_ENTRY) + EntrySize;
     LogEntry = ExAllocatePoolWithTag(NonPagedPool,
@@ -529,12 +581,12 @@ IoAllocateErrorLogEntry(IN PVOID IoObject,
     if (DriverObject) ObReferenceObject(DriverObject);
 
     /* Update log size */
-    InterlockedExchangeAdd(&IopTotalLogSize, EntrySize);
+    InterlockedExchangeAdd(&IopTotalLogSize, LogEntrySize);
 
     /* Clear the entry and set it up */
-    RtlZeroMemory(LogEntry, EntrySize);
+    RtlZeroMemory(LogEntry, LogEntrySize);
     LogEntry->Type = IO_TYPE_ERROR_LOG;
-    LogEntry->Size = EntrySize;
+    LogEntry->Size = LogEntrySize;
     LogEntry->DeviceObject = DeviceObject;
     LogEntry->DriverObject = DriverObject;
 
@@ -551,7 +603,7 @@ IoFreeErrorLogEntry(IN PVOID ElEntry)
 {
     PERROR_LOG_ENTRY LogEntry;
 
-    /* Make sure there's an entry */
+    /* Make sure there is an entry */
     if (!ElEntry) return;
 
     /* Get the actual header */
@@ -561,10 +613,9 @@ IoFreeErrorLogEntry(IN PVOID ElEntry)
     if (LogEntry->DeviceObject) ObDereferenceObject(LogEntry->DeviceObject);
     if (LogEntry->DriverObject) ObDereferenceObject(LogEntry->DriverObject);
 
-    /* Decrease total allocation size and free the entry */
-    InterlockedExchangeAdd(&IopTotalLogSize,
-                           -(LONG)(LogEntry->Size - sizeof(ERROR_LOG_ENTRY)));
-    ExFreePool(LogEntry);
+    /* Decrease the total allocation size and free the entry */
+    InterlockedExchangeAdd(&IopTotalLogSize, -(LONG)LogEntry->Size);
+    ExFreePoolWithTag(LogEntry, TAG_ERROR_LOG);
 }
 
 /*
@@ -577,9 +628,11 @@ IoWriteErrorLogEntry(IN PVOID ElEntry)
     PERROR_LOG_ENTRY LogEntry;
     KIRQL Irql;
 
-    /* Get the main header */
-    LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry -
-                                  sizeof(ERROR_LOG_ENTRY));
+    /* Make sure there is an entry */
+    if (!ElEntry) return;
+
+    /* Get the actual header */
+    LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry - sizeof(ERROR_LOG_ENTRY));
 
     /* Get time stamp */
     KeQuerySystemTime(&LogEntry->TimeStamp);
@@ -591,14 +644,10 @@ IoWriteErrorLogEntry(IN PVOID ElEntry)
     /* Check if the worker is running */
     if (!IopLogWorkerRunning)
     {
-#if 0
         /* It's not, initialize it and queue it */
-        ExInitializeWorkItem(&IopErrorLogWorkItem,
-                             IopLogWorker,
-                             &IopErrorLogWorkItem);
-        ExQueueWorkItem(&IopErrorLogWorkItem, DelayedWorkQueue);
         IopLogWorkerRunning = TRUE;
-#endif
+        ExInitializeWorkItem(&IopErrorLogWorkItem, IopLogWorker, NULL);
+        ExQueueWorkItem(&IopErrorLogWorkItem, DelayedWorkQueue);
     }
 
     /* Release the lock and return */
diff --git a/reactos/sdk/include/reactos/subsys/iolog/iolog.h b/reactos/sdk/include/reactos/subsys/iolog/iolog.h
new file mode 100644 (file)
index 0000000..abfd9fe
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * PROJECT:         ReactOS EventLog Service
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            include/reactos/subsys/iolog/iolog.h
+ * PURPOSE:         EventLog LPC API definitions
+ */
+
+#ifndef _IOLOG_H
+#define _IOLOG_H
+
+#pragma once
+
+// #include <iotypes.h> // For IO_ERROR_LOG_MESSAGE and associated
+
+#define ELF_PORT_NAME   L"\\ErrorLogPort"
+
+typedef struct _ELF_API_MSG
+{
+    PORT_MESSAGE Header;
+    ULONG Unknown[2]; // FIXME
+    IO_ERROR_LOG_MESSAGE IoErrorMessage;
+} ELF_API_MSG, *PELF_API_MSG;
+
+/*
+ * NOTE: The maximum data size sent to the EventLog LPC port
+ * is equal to: PORT_MAXIMUM_MESSAGE_LENGTH == 0x100 .
+ */
+
+#endif // _IOLOG_H
+
+/* EOF */