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