Author: hbelusca Date: Mon Nov 7 13:29:09 2016 New Revision: 73167
URL: http://svn.reactos.org/svn/reactos?rev=73167&view=rev Log: [NTOS:IO][INCLUDES][EVENTLOG]: Fix support for event logging through the "ErrorLogPort" LPC. See the details in CORE-12301 #resolve
Added: trunk/reactos/sdk/include/reactos/subsys/iolog/ trunk/reactos/sdk/include/reactos/subsys/iolog/iolog.h (with props) Modified: trunk/reactos/base/services/eventlog/CMakeLists.txt trunk/reactos/base/services/eventlog/eventlog.c trunk/reactos/base/services/eventlog/eventlog.h trunk/reactos/base/services/eventlog/file.c trunk/reactos/base/services/eventlog/logport.c trunk/reactos/base/services/eventlog/rpc.c trunk/reactos/ntoskrnl/include/internal/io.h trunk/reactos/ntoskrnl/io/iomgr/error.c
Modified: trunk/reactos/base/services/eventlog/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/services/eventlog/CMak... ============================================================================== --- trunk/reactos/base/services/eventlog/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/base/services/eventlog/CMakeLists.txt [iso-8859-1] Mon Nov 7 13:29:09 2016 @@ -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})
Modified: trunk/reactos/base/services/eventlog/eventlog.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/services/eventlog/even... ============================================================================== --- trunk/reactos/base/services/eventlog/eventlog.c [iso-8859-1] (original) +++ trunk/reactos/base/services/eventlog/eventlog.c [iso-8859-1] Mon Nov 7 13:29:09 2016 @@ -548,71 +548,73 @@ 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); - - DPRINT("EventID = %lu\n", pRec->EventID); + DbgPrint("TimeWritten = %hu.%hu.%hu %hu:%hu:%hu\n", + Time.Day, Time.Month, Time.Year, + Time.Hour, Time.Minute, Time.Second); + + 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); - } - - 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))); - - i = (wcslen((PWSTR)((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD))) + 1) * sizeof(WCHAR); - - DPRINT("ComputerName: %S\n", (PWSTR)((ULONG_PTR)pRec + sizeof(EVENTLOGRECORD) + i)); + DbgPrint("EventType = %hu\n", pRec->EventType); + } + + 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 = sizeof(EVENTLOGRECORD); + DbgPrint("SourceName: %S\n", (PWSTR)((ULONG_PTR)pRec + 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)); +}
Modified: trunk/reactos/base/services/eventlog/eventlog.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/services/eventlog/even... ============================================================================== --- trunk/reactos/base/services/eventlog/eventlog.h [iso-8859-1] (original) +++ trunk/reactos/base/services/eventlog/eventlog.h [iso-8859-1] Mon Nov 7 13:29:09 2016 @@ -27,15 +27,6 @@
#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 @@ USHORT wType, USHORT wCategory, ULONG dwEventId, - PCWSTR SourceName, - PCWSTR ComputerName, + PUNICODE_STRING SourceName, + PUNICODE_STRING ComputerName, ULONG dwSidLength, PSID pUserSid, USHORT wNumStrings,
Modified: trunk/reactos/base/services/eventlog/file.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/services/eventlog/file... ============================================================================== --- trunk/reactos/base/services/eventlog/file.c [iso-8859-1] (original) +++ trunk/reactos/base/services/eventlog/file.c [iso-8859-1] Mon Nov 7 13:29:09 2016 @@ -898,8 +898,8 @@ 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 @@ 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; - - RecSize = sizeof(EVENTLOGRECORD) + (SourceNameLen + ComputerNameLen) * sizeof(WCHAR); + + SourceNameSize = (SourceName && SourceName->Buffer) ? SourceName->Length : 0; + ComputerNameSize = (ComputerName && ComputerName->Buffer) ? ComputerName->Length : 0; + + 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 @@
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 @@ 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 @@ 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))
Modified: trunk/reactos/base/services/eventlog/logport.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/services/eventlog/logp... ============================================================================== --- trunk/reactos/base/services/eventlog/logport.c [iso-8859-1] (original) +++ trunk/reactos/base/services/eventlog/logport.c [iso-8859-1] Mon Nov 7 13:29:09 2016 @@ -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 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 @@ }
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 @@ NTSTATUS ProcessPortMessage(VOID) { NTSTATUS Status; - IO_ERROR_LPC Request; - PIO_ERROR_LOG_MESSAGE Message; + 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; - PEVENTLOGRECORD pRec; - SIZE_T RecSize; - PLOGFILE SystemLog = NULL; + 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 @@ while (TRUE) { Status = NtReplyWaitReceivePort(MessagePortHandle, - 0, NULL, - &Request.Header); + NULL, + &Message->Header);
if (!NT_SUCCESS(Status)) { @@ -133,69 +135,108 @@
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) - { - DPRINT("Received datagram\n"); - // Message = (PIO_ERROR_LOG_MESSAGE)&Request.Message; - Message = &Request.Message; - + else if (Message->Header.u2.s2.Type == LPC_DATAGRAM) + { + DPRINT("Received datagram (0x%x, 0x%x)\n", + Message->Unknown[0], Message->Unknown[1]); + ErrorMessage = &Message->IoErrorMessage; + + // ASSERT(ErrorMessage->Type == IO_TYPE_ERROR_MESSAGE); + + RtlInitEmptyUnicodeString(&SourceName, NULL, 0); + if (ErrorMessage->DriverNameLength > sizeof(UNICODE_NULL)) // DriverNameLength counts NULL-terminator + { + SourceName.Buffer = (PWSTR)((ULONG_PTR)ErrorMessage + ErrorMessage->DriverNameOffset); + SourceName.MaximumLength = ErrorMessage->DriverNameLength; + SourceName.Length = SourceName.MaximumLength - sizeof(UNICODE_NULL); + } + + dwComputerNameLength = ARRAYSIZE(szComputerName); if (!GetComputerNameW(szComputerName, &dwComputerNameLength)) - { szComputerName[0] = L'\0'; - } - - 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) - { - DPRINT("LogfAllocAndBuildNewRecord failed!\n"); - return STATUS_NO_MEMORY; - } - - DPRINT("RecSize = %d\n", RecSize); - - DPRINT("\n --- EVENTLOG RECORD ---\n"); - PRINT_RECORD(pRec); - DPRINT("\n"); + + 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) + { + 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; + } + + /* + * 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); } } - - LogfFreeRecord(pRec); + else + { + DPRINT1("\n--- EVENTLOG RECORD ---\n"); + PRINT_RECORD(LogBuffer); + DPRINT1("\n"); + } + + LogfFreeRecord(LogBuffer); } }
Modified: trunk/reactos/base/services/eventlog/rpc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/services/eventlog/rpc.... ============================================================================== --- trunk/reactos/base/services/eventlog/rpc.c [iso-8859-1] (original) +++ trunk/reactos/base/services/eventlog/rpc.c [iso-8859-1] Mon Nov 7 13:29:09 2016 @@ -586,6 +586,7 @@ { NTSTATUS Status; PLOGHANDLE pLogHandle; + UNICODE_STRING LocalSourceName, LocalComputerName; PEVENTLOGRECORD LogBuffer; USHORT i; SIZE_T RecSize; @@ -655,21 +656,32 @@ 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))
Modified: trunk/reactos/ntoskrnl/include/internal/io.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] Mon Nov 7 13:29:09 2016 @@ -5,6 +5,7 @@ * PURPOSE: Internal header for the I/O Manager * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ + #include "ntdddisk.h"
// @@ -331,16 +332,6 @@ PDRIVER_OBJECT DriverObject; 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
Modified: trunk/reactos/ntoskrnl/io/iomgr/error.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/error.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/error.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/io/iomgr/error.c [iso-8859-1] Mon Nov 7 13:29:09 2016 @@ -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 @@
/* GLOBALS *******************************************************************/
+#define IOP_MAXIMUM_LOG_SIZE (100 * PAGE_SIZE) LONG IopTotalLogSize; LIST_ENTRY IopErrorLogListHead; KSPIN_LOCK IopLogListLock; @@ -105,16 +109,23 @@ 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 @@ 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 @@ 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; + ULONG ExtraStringLength; PWCHAR p; - ULONG ExtraStringLength; + 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 @@ 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 @@ 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; - - /* Check if there isn't a valid name*/ + { + NameString = NULL; + DriverNameLength = 0; + } + + /* Check if there isn't a valid name */ if (!DriverNameLength) { /* Query the name directly */ @@ -247,30 +268,35 @@ 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); - } - - /* Check if we have a driver name by here */ + NameString = L"Application Popup"; + DriverNameLength = (ULONG)wcslen(NameString) * sizeof(WCHAR); + } + + /* 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 @@ }
/* - * 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 @@ }
/* 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 @@ { /* 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 */ @@ -384,6 +412,9 @@ ExtraStringLength = LogEntry->Size - 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 @@ 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); - - /* Update size */ - InterlockedExchangeAdd(&IopTotalLogSize, - -(LONG)(LogEntry->Size - - sizeof(ERROR_LOG_ENTRY))); + if (LogEntry->DriverObject) ObDereferenceObject(LogEntry->DriverObject); + + /* 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 @@ /* 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; @@ -516,6 +553,21 @@ /* Fail */ 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; @@ -529,12 +581,12 @@ 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 @@ { 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 @@ 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 @@ 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 @@ /* Check if the worker is running */ if (!IopLogWorkerRunning) { -#if 0 /* It's not, initialize it and queue it */ - ExInitializeWorkItem(&IopErrorLogWorkItem, - IopLogWorker, - &IopErrorLogWorkItem); + IopLogWorkerRunning = TRUE; + ExInitializeWorkItem(&IopErrorLogWorkItem, IopLogWorker, NULL); ExQueueWorkItem(&IopErrorLogWorkItem, DelayedWorkQueue); - IopLogWorkerRunning = TRUE; -#endif }
/* Release the lock and return */
Added: trunk/reactos/sdk/include/reactos/subsys/iolog/iolog.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/reactos/subsys/... ============================================================================== --- trunk/reactos/sdk/include/reactos/subsys/iolog/iolog.h (added) +++ trunk/reactos/sdk/include/reactos/subsys/iolog/iolog.h [iso-8859-1] Mon Nov 7 13:29:09 2016 @@ -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 */
Propchange: trunk/reactos/sdk/include/reactos/subsys/iolog/iolog.h ------------------------------------------------------------------------------ svn:eol-style = native