xref: /reactos/base/services/eventlog/logport.c (revision c2c66aff)
1 /*
2  * PROJECT:         ReactOS EventLog Service
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            base/services/eventlog/logport.c
5  * PURPOSE:         LPC Port Interface support
6  * COPYRIGHT:       Copyright 2002 Eric Kohl
7  *                  Copyright 2005 Saveliy Tretiakov
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include "eventlog.h"
13 #include <ndk/lpcfuncs.h>
14 #include <iolog/iolog.h>
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 /* GLOBALS ******************************************************************/
20 
21 static HANDLE ConnectPortHandle = NULL;
22 static HANDLE MessagePortHandle = NULL;
23 extern BOOL onLiveCD;
24 
25 /* FUNCTIONS ****************************************************************/
26 
PortThreadRoutine(PVOID Param)27 NTSTATUS WINAPI PortThreadRoutine(PVOID Param)
28 {
29     NTSTATUS Status = STATUS_SUCCESS;
30 
31     Status = InitLogPort();
32     if (!NT_SUCCESS(Status))
33         return Status;
34 
35     while (NT_SUCCESS(Status))
36         Status = ProcessPortMessage();
37 
38     if (ConnectPortHandle != NULL)
39         NtClose(ConnectPortHandle);
40 
41     if (MessagePortHandle != NULL)
42         NtClose(MessagePortHandle);
43 
44     return Status;
45 }
46 
InitLogPort(VOID)47 NTSTATUS InitLogPort(VOID)
48 {
49     NTSTATUS Status;
50     UNICODE_STRING PortName = RTL_CONSTANT_STRING(ELF_PORT_NAME);
51     OBJECT_ATTRIBUTES ObjectAttributes;
52     PORT_MESSAGE Request;
53 
54     ConnectPortHandle = NULL;
55     MessagePortHandle = NULL;
56 
57     InitializeObjectAttributes(&ObjectAttributes, &PortName, 0, NULL, NULL);
58 
59     Status = NtCreatePort(&ConnectPortHandle,
60                           &ObjectAttributes,
61                           0,
62                           PORT_MAXIMUM_MESSAGE_LENGTH, // IO_ERROR_LOG_MESSAGE_LENGTH,
63                           2 * PAGE_SIZE);
64     if (!NT_SUCCESS(Status))
65     {
66         DPRINT1("NtCreatePort() failed (Status %lx)\n", Status);
67         goto ByeBye;
68     }
69 
70     Status = NtListenPort(ConnectPortHandle, &Request);
71     if (!NT_SUCCESS(Status))
72     {
73         DPRINT1("NtListenPort() failed (Status %lx)\n", Status);
74         goto ByeBye;
75     }
76 
77     Status = NtAcceptConnectPort(&MessagePortHandle, ConnectPortHandle,
78                                  &Request, TRUE, NULL, NULL);
79     if (!NT_SUCCESS(Status))
80     {
81         DPRINT1("NtAcceptConnectPort() failed (Status %lx)\n", Status);
82         goto ByeBye;
83     }
84 
85     Status = NtCompleteConnectPort(MessagePortHandle);
86     if (!NT_SUCCESS(Status))
87     {
88         DPRINT1("NtCompleteConnectPort() failed (Status %lx)\n", Status);
89         goto ByeBye;
90     }
91 
92 ByeBye:
93     if (!NT_SUCCESS(Status))
94     {
95         if (ConnectPortHandle != NULL)
96             NtClose(ConnectPortHandle);
97 
98         if (MessagePortHandle != NULL)
99             NtClose(MessagePortHandle);
100     }
101     return Status;
102 }
103 
ProcessPortMessage(VOID)104 NTSTATUS ProcessPortMessage(VOID)
105 {
106     NTSTATUS Status;
107     PLOGFILE SystemLog = NULL;
108     UCHAR Buffer[PORT_MAXIMUM_MESSAGE_LENGTH]; // IO_ERROR_LOG_MESSAGE_LENGTH
109     PELF_API_MSG Message = (PELF_API_MSG)Buffer;
110     PIO_ERROR_LOG_MESSAGE ErrorMessage;
111     PEVENTLOGRECORD LogBuffer;
112     SIZE_T RecSize;
113     ULONG Time;
114     USHORT EventType;
115     UNICODE_STRING SourceName, ComputerName;
116     DWORD dwComputerNameLength;
117     WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
118 
119     DPRINT("ProcessPortMessage() called\n");
120 
121     SystemLog = LogfListItemByName(L"System");
122 
123     while (TRUE)
124     {
125         Status = NtReplyWaitReceivePort(MessagePortHandle,
126                                         NULL,
127                                         NULL,
128                                         &Message->Header);
129 
130         if (!NT_SUCCESS(Status))
131         {
132             DPRINT1("NtReplyWaitReceivePort() failed (Status %lx)\n", Status);
133             break;
134         }
135 
136         DPRINT("Received message\n");
137 
138         if (Message->Header.u2.s2.Type == LPC_PORT_CLOSED)
139         {
140             DPRINT("Port closed\n");
141             return STATUS_SUCCESS;
142         }
143 
144         if (Message->Header.u2.s2.Type == LPC_REQUEST)
145         {
146             DPRINT("Received request\n");
147         }
148         else if (Message->Header.u2.s2.Type == LPC_DATAGRAM)
149         {
150             DPRINT("Received datagram (0x%x, 0x%x)\n",
151                    Message->Unknown[0], Message->Unknown[1]);
152             ErrorMessage = &Message->IoErrorMessage;
153 
154             // ASSERT(ErrorMessage->Type == IO_TYPE_ERROR_MESSAGE);
155 
156             RtlInitEmptyUnicodeString(&SourceName, NULL, 0);
157             if (ErrorMessage->DriverNameLength > sizeof(UNICODE_NULL)) // DriverNameLength counts NULL-terminator
158             {
159                 SourceName.Buffer = (PWSTR)((ULONG_PTR)ErrorMessage + ErrorMessage->DriverNameOffset);
160                 SourceName.MaximumLength = ErrorMessage->DriverNameLength;
161                 SourceName.Length = SourceName.MaximumLength - sizeof(UNICODE_NULL);
162             }
163 
164             dwComputerNameLength = ARRAYSIZE(szComputerName);
165             if (!GetComputerNameW(szComputerName, &dwComputerNameLength))
166                 szComputerName[0] = L'\0';
167 
168             RtlInitUnicodeString(&ComputerName, szComputerName);
169 
170             RtlTimeToSecondsSince1970(&ErrorMessage->TimeStamp, &Time);
171 
172             /* Set the event type based on the error code severity */
173             EventType = (USHORT)(ErrorMessage->EntryData.ErrorCode >> 30);
174             if (EventType == STATUS_SEVERITY_SUCCESS)
175             {
176                 EventType = EVENTLOG_SUCCESS;
177             }
178             else if (EventType == STATUS_SEVERITY_INFORMATIONAL) // NT_INFORMATION
179             {
180                 EventType = EVENTLOG_INFORMATION_TYPE;
181             }
182             else if (EventType == STATUS_SEVERITY_WARNING)       // NT_WARNING
183             {
184                 EventType = EVENTLOG_WARNING_TYPE;
185             }
186             else if (EventType == STATUS_SEVERITY_ERROR)         // NT_ERROR
187             {
188                 EventType = EVENTLOG_ERROR_TYPE;
189             }
190             else
191             {
192                 /* Unknown severity, set to error */
193                 EventType = EVENTLOG_ERROR_TYPE;
194             }
195 
196             /*
197              * The data being saved consists of the IO_ERROR_LOG_PACKET structure
198              * header, plus the additional raw data from the driver.
199              */
200             LogBuffer = LogfAllocAndBuildNewRecord(
201                             &RecSize,
202                             Time,
203                             EventType,
204                             ErrorMessage->EntryData.EventCategory,
205                             ErrorMessage->EntryData.ErrorCode,
206                             &SourceName,
207                             &ComputerName,
208                             0,
209                             NULL,
210                             ErrorMessage->EntryData.NumberOfStrings,
211                             (PWSTR)((ULONG_PTR)ErrorMessage +
212                                 ErrorMessage->EntryData.StringOffset),
213                             FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) +
214                                 ErrorMessage->EntryData.DumpDataSize,
215                             (PVOID)&ErrorMessage->EntryData);
216             if (LogBuffer == NULL)
217             {
218                 DPRINT1("LogfAllocAndBuildNewRecord failed!\n");
219                 // return STATUS_NO_MEMORY;
220                 continue;
221             }
222 
223             if (!onLiveCD && SystemLog)
224             {
225                 Status = LogfWriteRecord(SystemLog, LogBuffer, RecSize);
226                 if (!NT_SUCCESS(Status))
227                 {
228                     DPRINT1("ERROR writing to event log `%S' (Status 0x%08lx)\n",
229                             SystemLog->LogName, Status);
230                 }
231             }
232             else
233             {
234                 DPRINT1("\n--- EVENTLOG RECORD ---\n");
235                 PRINT_RECORD(LogBuffer);
236                 DPRINT1("\n");
237             }
238 
239             LogfFreeRecord(LogBuffer);
240         }
241     }
242 
243     return Status;
244 }
245