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
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS ******************************************************************/
16 VOID CALLBACK
ServiceMain(DWORD argc
, LPTSTR
* argv
);
18 SERVICE_TABLE_ENTRY ServiceTable
[2] =
20 { L
"EventLog", (LPSERVICE_MAIN_FUNCTION
) ServiceMain
},
24 BOOL onLiveCD
= FALSE
; // On livecd events will go to debug output only
27 /* FUNCTIONS ****************************************************************/
29 VOID CALLBACK
ServiceMain(DWORD argc
, LPTSTR
* argv
)
33 hThread
= CreateThread(NULL
,
35 (LPTHREAD_START_ROUTINE
)
42 DPRINT("Can't create PortThread\n");
46 hThread
= CreateThread(NULL
,
48 (LPTHREAD_START_ROUTINE
)
55 DPRINT("Can't create RpcThread\n");
60 BOOL
LoadLogFile(HKEY hKey
, WCHAR
* LogName
)
62 DWORD MaxValueLen
, ValueLen
, Type
, ExpandedLen
;
63 WCHAR
*Buf
= NULL
, *Expanded
= NULL
;
68 DPRINT("LoadLogFile: %S\n", LogName
);
70 RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
71 NULL
, NULL
, &MaxValueLen
, NULL
, NULL
);
73 Buf
= HeapAlloc(MyHeap
, 0, MaxValueLen
);
77 DPRINT1("Can't allocate heap!\n");
81 ValueLen
= MaxValueLen
;
83 Result
= RegQueryValueEx(hKey
,
90 if (Result
!= ERROR_SUCCESS
)
92 DPRINT1("RegQueryValueEx failed: %d\n", GetLastError());
93 HeapFree(MyHeap
, 0, Buf
);
97 if (Type
!= REG_EXPAND_SZ
&& Type
!= REG_SZ
)
99 DPRINT1("%S\\File - value of wrong type %x.\n", LogName
, Type
);
100 HeapFree(MyHeap
, 0, Buf
);
104 ExpandedLen
= ExpandEnvironmentStrings(Buf
, NULL
, 0);
105 Expanded
= HeapAlloc(MyHeap
, 0, ExpandedLen
* sizeof(WCHAR
));
109 DPRINT1("Can't allocate heap!\n");
110 HeapFree(MyHeap
, 0, Buf
);
114 ExpandEnvironmentStrings(Buf
, Expanded
, ExpandedLen
);
116 DPRINT("%S -> %S\n", Buf
, Expanded
);
118 pLogf
= LogfCreate(LogName
, Expanded
);
122 DPRINT1("Failed to create %S!\n", Expanded
);
126 HeapFree(MyHeap
, 0, Buf
);
127 HeapFree(MyHeap
, 0, Expanded
);
131 BOOL
LoadLogFiles(HKEY eventlogKey
)
134 DWORD MaxLognameLen
, LognameLen
;
138 RegQueryInfoKey(eventlogKey
,
139 NULL
, NULL
, NULL
, NULL
,
141 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
145 Buf
= HeapAlloc(MyHeap
, 0, MaxLognameLen
* sizeof(WCHAR
));
149 DPRINT1("Error: can't allocate heap!\n");
154 LognameLen
= MaxLognameLen
;
156 while (RegEnumKeyEx(eventlogKey
,
160 NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
166 result
= RegOpenKeyEx(eventlogKey
, Buf
, 0, KEY_ALL_ACCESS
, &SubKey
);
167 if (result
!= ERROR_SUCCESS
)
169 DPRINT1("Failed to open %S key.\n", Buf
);
170 HeapFree(MyHeap
, 0, Buf
);
174 if (!LoadLogFile(SubKey
, Buf
))
175 DPRINT1("Failed to load %S\n", Buf
);
177 DPRINT("Loaded %S\n", Buf
);
180 LognameLen
= MaxLognameLen
;
184 HeapFree(MyHeap
, 0, Buf
);
190 WCHAR LogPath
[MAX_PATH
];
195 LogfListInitialize();
197 MyHeap
= HeapCreate(0, 1024 * 256, 0);
201 DPRINT1("FATAL ERROR, can't create heap.\n");
206 GetWindowsDirectory(LogPath
, MAX_PATH
);
208 if (GetDriveType(LogPath
) == DRIVE_CDROM
)
210 DPRINT("LiveCD detected\n");
215 result
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
216 L
"SYSTEM\\CurrentControlSet\\Services\\EventLog",
221 if (result
!= ERROR_SUCCESS
)
223 DPRINT1("Fatal error: can't open eventlog registry key.\n");
228 LoadLogFiles(elogKey
);
231 StartServiceCtrlDispatcher(ServiceTable
);
242 VOID
EventTimeToSystemTime(DWORD EventTime
, SYSTEMTIME
* pSystemTime
)
244 SYSTEMTIME st1970
= { 1970, 1, 0, 1, 0, 0, 0, 0 };
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
);
260 VOID
SystemTimeToEventTime(SYSTEMTIME
* pSystemTime
, DWORD
* pEventTime
)
262 SYSTEMTIME st1970
= { 1970, 1, 0, 1, 0, 0, 0, 0 };
269 SystemTimeToFileTime(pSystemTime
, &Time
.ft
);
270 SystemTimeToFileTime(&st1970
, &u1970
.ft
);
271 *pEventTime
= (Time
.ll
- u1970
.ll
) / 10000000;
274 VOID
PRINT_HEADER(PEVENTLOGHEADER header
)
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
);
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 ");
295 VOID
PRINT_RECORD(PEVENTLOGRECORD pRec
)
301 DPRINT("Length = %d\n", pRec
->Length
);
302 DPRINT("Reserved = 0x%x\n", pRec
->Reserved
);
303 DPRINT("RecordNumber = %d\n", pRec
->RecordNumber
);
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
);
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
);
315 DPRINT("EventID = %d\n", pRec
->EventID
);
317 switch (pRec
->EventType
)
319 case EVENTLOG_ERROR_TYPE
:
320 DPRINT("EventType = EVENTLOG_ERROR_TYPE\n");
322 case EVENTLOG_WARNING_TYPE
:
323 DPRINT("EventType = EVENTLOG_WARNING_TYPE\n");
325 case EVENTLOG_INFORMATION_TYPE
:
326 DPRINT("EventType = EVENTLOG_INFORMATION_TYPE\n");
328 case EVENTLOG_AUDIT_SUCCESS
:
329 DPRINT("EventType = EVENTLOG_AUDIT_SUCCESS\n");
331 case EVENTLOG_AUDIT_FAILURE
:
332 DPRINT("EventType = EVENTLOG_AUDIT_FAILURE\n");
335 DPRINT("EventType = %d\n", pRec
->EventType
);
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
);
348 DPRINT("SourceName: %S\n", (WCHAR
*) (((PBYTE
) pRec
) + sizeof(EVENTLOGRECORD
)));
350 i
= (lstrlenW((WCHAR
*) (((PBYTE
) pRec
) + sizeof(EVENTLOGRECORD
))) + 1) *
353 DPRINT("ComputerName: %S\n", (WCHAR
*) (((PBYTE
) pRec
) + sizeof(EVENTLOGRECORD
) + i
));
355 if (pRec
->StringOffset
< pRec
->Length
&& pRec
->NumStrings
)
357 DPRINT("Strings:\n");
358 str
= (WCHAR
*) (((PBYTE
) pRec
) + pRec
->StringOffset
);
359 for (i
= 0; i
< pRec
->NumStrings
; i
++)
361 DPRINT("[%d] %S\n", i
, str
);
362 str
= str
+ lstrlenW(str
) + 1;
366 DPRINT("Length2 = %d\n", *(PDWORD
) (((PBYTE
) pRec
) + pRec
->Length
- 4));