merge 37282 from amd64-branch:
[reactos.git] / reactos / base / services / eventlog / eventlog.c
1 /*
2 * PROJECT: ReactOS kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: services/eventlog/eventlog.c
5 * PURPOSE: Event logging service
6 * COPYRIGHT: Copyright 2002 Eric Kohl
7 * Copyright 2005 Saveliy Tretiakov
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "eventlog.h"
13
14 /* GLOBALS ******************************************************************/
15
16 VOID CALLBACK ServiceMain(DWORD argc, LPTSTR * argv);
17
18 SERVICE_TABLE_ENTRY ServiceTable[2] =
19 {
20 { L"EventLog", (LPSERVICE_MAIN_FUNCTION) ServiceMain },
21 { NULL, NULL }
22 };
23
24 BOOL onLiveCD = FALSE; // On livecd events will go to debug output only
25 HANDLE MyHeap = NULL;
26
27 /* FUNCTIONS ****************************************************************/
28
29 VOID CALLBACK ServiceMain(DWORD argc, LPTSTR * argv)
30 {
31 HANDLE hThread;
32
33 hThread = CreateThread(NULL,
34 0,
35 (LPTHREAD_START_ROUTINE)
36 PortThreadRoutine,
37 NULL,
38 0,
39 NULL);
40
41 if (!hThread)
42 DPRINT("Can't create PortThread\n");
43 else
44 CloseHandle(hThread);
45
46 hThread = CreateThread(NULL,
47 0,
48 (LPTHREAD_START_ROUTINE)
49 RpcThreadRoutine,
50 NULL,
51 0,
52 NULL);
53
54 if (!hThread)
55 DPRINT("Can't create RpcThread\n");
56 else
57 CloseHandle(hThread);
58 }
59
60 BOOL LoadLogFile(HKEY hKey, WCHAR * LogName)
61 {
62 DWORD MaxValueLen, ValueLen, Type, ExpandedLen;
63 WCHAR *Buf = NULL, *Expanded = NULL;
64 LONG Result;
65 BOOL ret = TRUE;
66 PLOGFILE pLogf;
67
68 DPRINT("LoadLogFile: %S\n", LogName);
69
70 RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
71 NULL, NULL, &MaxValueLen, NULL, NULL);
72
73 Buf = HeapAlloc(MyHeap, 0, MaxValueLen);
74
75 if (!Buf)
76 {
77 DPRINT1("Can't allocate heap!\n");
78 return FALSE;
79 }
80
81 ValueLen = MaxValueLen;
82
83 Result = RegQueryValueEx(hKey,
84 L"File",
85 NULL,
86 &Type,
87 (LPBYTE) Buf,
88 &ValueLen);
89
90 if (Result != ERROR_SUCCESS)
91 {
92 DPRINT1("RegQueryValueEx failed: %d\n", GetLastError());
93 HeapFree(MyHeap, 0, Buf);
94 return FALSE;
95 }
96
97 if (Type != REG_EXPAND_SZ && Type != REG_SZ)
98 {
99 DPRINT1("%S\\File - value of wrong type %x.\n", LogName, Type);
100 HeapFree(MyHeap, 0, Buf);
101 return FALSE;
102 }
103
104 ExpandedLen = ExpandEnvironmentStrings(Buf, NULL, 0);
105 Expanded = HeapAlloc(MyHeap, 0, ExpandedLen * sizeof(WCHAR));
106
107 if (!Expanded)
108 {
109 DPRINT1("Can't allocate heap!\n");
110 HeapFree(MyHeap, 0, Buf);
111 return FALSE;
112 }
113
114 ExpandEnvironmentStrings(Buf, Expanded, ExpandedLen);
115
116 DPRINT("%S -> %S\n", Buf, Expanded);
117
118 pLogf = LogfCreate(LogName, Expanded);
119
120 if (pLogf == NULL)
121 {
122 DPRINT1("Failed to create %S!\n", Expanded);
123 ret = FALSE;
124 }
125
126 HeapFree(MyHeap, 0, Buf);
127 HeapFree(MyHeap, 0, Expanded);
128 return ret;
129 }
130
131 BOOL LoadLogFiles(HKEY eventlogKey)
132 {
133 LONG result;
134 DWORD MaxLognameLen, LognameLen;
135 WCHAR *Buf = NULL;
136 INT i;
137
138 RegQueryInfoKey(eventlogKey,
139 NULL, NULL, NULL, NULL,
140 &MaxLognameLen,
141 NULL, NULL, NULL, NULL, NULL, NULL);
142
143 MaxLognameLen++;
144
145 Buf = HeapAlloc(MyHeap, 0, MaxLognameLen * sizeof(WCHAR));
146
147 if (!Buf)
148 {
149 DPRINT1("Error: can't allocate heap!\n");
150 return FALSE;
151 }
152
153 i = 0;
154 LognameLen = MaxLognameLen;
155
156 while (RegEnumKeyEx(eventlogKey,
157 i,
158 Buf,
159 &LognameLen,
160 NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
161 {
162 HKEY SubKey;
163
164 DPRINT("%S\n", Buf);
165
166 result = RegOpenKeyEx(eventlogKey, Buf, 0, KEY_ALL_ACCESS, &SubKey);
167 if (result != ERROR_SUCCESS)
168 {
169 DPRINT1("Failed to open %S key.\n", Buf);
170 HeapFree(MyHeap, 0, Buf);
171 return FALSE;
172 }
173
174 if (!LoadLogFile(SubKey, Buf))
175 DPRINT1("Failed to load %S\n", Buf);
176 else
177 DPRINT("Loaded %S\n", Buf);
178
179 RegCloseKey(SubKey);
180 LognameLen = MaxLognameLen;
181 i++;
182 }
183
184 HeapFree(MyHeap, 0, Buf);
185 return TRUE;
186 }
187
188 INT wmain()
189 {
190 WCHAR LogPath[MAX_PATH];
191 INT RetCode = 0;
192 LONG result;
193 HKEY elogKey;
194
195 LogfListInitialize();
196
197 MyHeap = HeapCreate(0, 1024 * 256, 0);
198
199 if (!MyHeap)
200 {
201 DPRINT1("FATAL ERROR, can't create heap.\n");
202 RetCode = 1;
203 goto bye_bye;
204 }
205
206 GetWindowsDirectory(LogPath, MAX_PATH);
207
208 if (GetDriveType(LogPath) == DRIVE_CDROM)
209 {
210 DPRINT("LiveCD detected\n");
211 onLiveCD = TRUE;
212 }
213 else
214 {
215 result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
216 L"SYSTEM\\CurrentControlSet\\Services\\EventLog",
217 0,
218 KEY_ALL_ACCESS,
219 &elogKey);
220
221 if (result != ERROR_SUCCESS)
222 {
223 DPRINT1("Fatal error: can't open eventlog registry key.\n");
224 RetCode = 1;
225 goto bye_bye;
226 }
227
228 LoadLogFiles(elogKey);
229 }
230
231 StartServiceCtrlDispatcher(ServiceTable);
232
233 bye_bye:
234 LogfCloseAll();
235
236 if (MyHeap)
237 HeapDestroy(MyHeap);
238
239 return RetCode;
240 }
241
242 VOID EventTimeToSystemTime(DWORD EventTime, SYSTEMTIME * pSystemTime)
243 {
244 SYSTEMTIME st1970 = { 1970, 1, 0, 1, 0, 0, 0, 0 };
245 FILETIME ftLocal;
246 union
247 {
248 FILETIME ft;
249 ULONGLONG ll;
250 } u1970, uUCT;
251
252 uUCT.ft.dwHighDateTime = 0;
253 uUCT.ft.dwLowDateTime = EventTime;
254 SystemTimeToFileTime(&st1970, &u1970.ft);
255 uUCT.ll = uUCT.ll * 10000000 + u1970.ll;
256 FileTimeToLocalFileTime(&uUCT.ft, &ftLocal);
257 FileTimeToSystemTime(&ftLocal, pSystemTime);
258 }
259
260 VOID SystemTimeToEventTime(SYSTEMTIME * pSystemTime, DWORD * pEventTime)
261 {
262 SYSTEMTIME st1970 = { 1970, 1, 0, 1, 0, 0, 0, 0 };
263 union
264 {
265 FILETIME ft;
266 ULONGLONG ll;
267 } Time, u1970;
268
269 SystemTimeToFileTime(pSystemTime, &Time.ft);
270 SystemTimeToFileTime(&st1970, &u1970.ft);
271 *pEventTime = (Time.ll - u1970.ll) / 10000000;
272 }
273
274 VOID PRINT_HEADER(PEVENTLOGHEADER header)
275 {
276 DPRINT("HeaderSize = %d\n", header->HeaderSize);
277 DPRINT("Signature = 0x%x\n", header->Signature);
278 DPRINT("MajorVersion = %d\n", header->MajorVersion);
279 DPRINT("MinorVersion = %d\n", header->MinorVersion);
280 DPRINT("StartOffset = %d\n", header->StartOffset);
281 DPRINT("EndOffset = 0x%x\n", header->EndOffset);
282 DPRINT("CurrentRecordNumber = %d\n", header->CurrentRecordNumber);
283 DPRINT("OldestRecordNumber = %d\n", header->OldestRecordNumber);
284 DPRINT("MaxSize = 0x%x\n", header->MaxSize);
285 DPRINT("Retention = 0x%x\n", header->Retention);
286 DPRINT("EndHeaderSize = %d\n", header->EndHeaderSize);
287 DPRINT("Flags: ");
288 if (header->Flags & ELF_LOGFILE_HEADER_DIRTY) DPRINT("ELF_LOGFILE_HEADER_DIRTY");
289 if (header->Flags & ELF_LOGFILE_HEADER_WRAP) DPRINT("| ELF_LOGFILE_HEADER_WRAP ");
290 if (header->Flags & ELF_LOGGFILE_LOGFULL_WRITTEN) DPRINT("| ELF_LOGGFILE_LOGFULL_WRITTEN ");
291 if (header->Flags & ELF_LOGFILE_ARCHIVE_SET) DPRINT("| ELF_LOGFILE_ARCHIVE_SET ");
292 DPRINT("\n");
293 }
294
295 VOID PRINT_RECORD(PEVENTLOGRECORD pRec)
296 {
297 UINT i;
298 WCHAR *str;
299 SYSTEMTIME time;
300
301 DPRINT("Length = %d\n", pRec->Length);
302 DPRINT("Reserved = 0x%x\n", pRec->Reserved);
303 DPRINT("RecordNumber = %d\n", pRec->RecordNumber);
304
305 EventTimeToSystemTime(pRec->TimeGenerated, &time);
306 DPRINT("TimeGenerated = %d.%d.%d %d:%d:%d\n",
307 time.wDay, time.wMonth, time.wYear,
308 time.wHour, time.wMinute, time.wSecond);
309
310 EventTimeToSystemTime(pRec->TimeWritten, &time);
311 DPRINT("TimeWritten = %d.%d.%d %d:%d:%d\n",
312 time.wDay, time.wMonth, time.wYear,
313 time.wHour, time.wMinute, time.wSecond);
314
315 DPRINT("EventID = %d\n", pRec->EventID);
316
317 switch (pRec->EventType)
318 {
319 case EVENTLOG_ERROR_TYPE:
320 DPRINT("EventType = EVENTLOG_ERROR_TYPE\n");
321 break;
322 case EVENTLOG_WARNING_TYPE:
323 DPRINT("EventType = EVENTLOG_WARNING_TYPE\n");
324 break;
325 case EVENTLOG_INFORMATION_TYPE:
326 DPRINT("EventType = EVENTLOG_INFORMATION_TYPE\n");
327 break;
328 case EVENTLOG_AUDIT_SUCCESS:
329 DPRINT("EventType = EVENTLOG_AUDIT_SUCCESS\n");
330 break;
331 case EVENTLOG_AUDIT_FAILURE:
332 DPRINT("EventType = EVENTLOG_AUDIT_FAILURE\n");
333 break;
334 default:
335 DPRINT("EventType = %d\n", pRec->EventType);
336 }
337
338 DPRINT("NumStrings = %d\n", pRec->NumStrings);
339 DPRINT("EventCategory = %d\n", pRec->EventCategory);
340 DPRINT("ReservedFlags = 0x%x\n", pRec->ReservedFlags);
341 DPRINT("ClosingRecordNumber = %d\n", pRec->ClosingRecordNumber);
342 DPRINT("StringOffset = %d\n", pRec->StringOffset);
343 DPRINT("UserSidLength = %d\n", pRec->UserSidLength);
344 DPRINT("UserSidOffset = %d\n", pRec->UserSidOffset);
345 DPRINT("DataLength = %d\n", pRec->DataLength);
346 DPRINT("DataOffset = %d\n", pRec->DataOffset);
347
348 DPRINT("SourceName: %S\n", (WCHAR *) (((PBYTE) pRec) + sizeof(EVENTLOGRECORD)));
349
350 i = (lstrlenW((WCHAR *) (((PBYTE) pRec) + sizeof(EVENTLOGRECORD))) + 1) *
351 sizeof(WCHAR);
352
353 DPRINT("ComputerName: %S\n", (WCHAR *) (((PBYTE) pRec) + sizeof(EVENTLOGRECORD) + i));
354
355 if (pRec->StringOffset < pRec->Length && pRec->NumStrings)
356 {
357 DPRINT("Strings:\n");
358 str = (WCHAR *) (((PBYTE) pRec) + pRec->StringOffset);
359 for (i = 0; i < pRec->NumStrings; i++)
360 {
361 DPRINT("[%d] %S\n", i, str);
362 str = str + lstrlenW(str) + 1;
363 }
364 }
365
366 DPRINT("Length2 = %d\n", *(PDWORD) (((PBYTE) pRec) + pRec->Length - 4));
367 }