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
);
17 SERVICE_TABLE_ENTRY ServiceTable
[2] =
19 {L
"EventLog", (LPSERVICE_MAIN_FUNCTION
)ServiceMain
},
24 BOOL onLiveCD
= FALSE
; // On livecd events will go to debug output only
25 extern CRITICAL_SECTION LogListCs
;
26 extern PLOGFILE LogListHead
;
28 /* FUNCTIONS ****************************************************************/
30 VOID CALLBACK
ServiceMain(DWORD argc
, LPTSTR
*argv
)
34 hThread
= CreateThread(NULL
,
36 (LPTHREAD_START_ROUTINE
)
42 if(!hThread
) DPRINT("Can't create PortThread\n");
43 else CloseHandle(hThread
);
46 hThread
= CreateThread(NULL
,
48 (LPTHREAD_START_ROUTINE
)
54 if(!hThread
) DPRINT("Can't create RpcThread\n");
55 else CloseHandle(hThread
);
59 BOOL
LoadLogFile(HKEY hKey
, WCHAR
*LogName
)
61 DWORD MaxValueLen
, ValueLen
, Type
, ExpandedLen
;
62 WCHAR
*Buf
= NULL
, *Expanded
= NULL
;
67 DPRINT("LoadLogFile: %S\n", LogName
);
69 RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
70 NULL
, &MaxValueLen
, NULL
, NULL
);
72 Buf
= HeapAlloc(MyHeap
, 0, MaxValueLen
);
76 DPRINT1("Can't allocate heap!\n");
80 ValueLen
= MaxValueLen
;
82 Result
= RegQueryValueEx(hKey
, L
"File",
88 if(Result
!= ERROR_SUCCESS
)
90 DPRINT1("RegQueryValueEx failed: %d\n", GetLastError());
91 HeapFree(MyHeap
, 0, Buf
);
94 if(Type
!= REG_EXPAND_SZ
&& Type
!= REG_SZ
)
96 DPRINT1("%S\\File - value of wrong type %x.\n", LogName
, Type
);
97 HeapFree(MyHeap
, 0, Buf
);
101 ExpandedLen
= ExpandEnvironmentStrings(Buf
, NULL
, 0);
102 Expanded
= HeapAlloc(MyHeap
, 0, ExpandedLen
*sizeof(WCHAR
));
106 DPRINT1("Can't allocate heap!\n");
107 HeapFree(MyHeap
, 0, Buf
);
111 ExpandEnvironmentStrings(Buf
, Expanded
, ExpandedLen
);
113 DPRINT("%S -> %S\n", Buf
, Expanded
);
115 pLogf
= LogfCreate(LogName
, Expanded
);
119 DPRINT1("Failed to create %S!\n", Expanded
);
123 HeapFree(MyHeap
, 0, Buf
);
124 HeapFree(MyHeap
, 0, Expanded
);
128 BOOL
LoadLogFiles(HKEY eventlogKey
)
131 DWORD MaxLognameLen
, LognameLen
;
135 RegQueryInfoKey(eventlogKey
, NULL
, NULL
, NULL
, NULL
, &MaxLognameLen
,
136 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
140 Buf
= HeapAlloc(MyHeap
, 0, MaxLognameLen
*sizeof(WCHAR
));
144 DPRINT1("Error: can't allocate heap!\n");
149 LognameLen
=MaxLognameLen
;
151 while(RegEnumKeyEx(eventlogKey
, i
, Buf
, &LognameLen
, NULL
, NULL
,
152 NULL
, NULL
) == ERROR_SUCCESS
)
157 result
= RegOpenKeyEx(eventlogKey
, Buf
, 0, KEY_ALL_ACCESS
, &SubKey
);
158 if(result
!= ERROR_SUCCESS
)
160 DPRINT1("Failed to open %S key.\n", Buf
);
161 HeapFree(MyHeap
, 0, Buf
);
165 if(!LoadLogFile(SubKey
, Buf
))
166 DPRINT1("Failed to load %S\n", Buf
);
167 else DPRINT("Loaded %S\n", Buf
);
170 LognameLen
=MaxLognameLen
;
174 HeapFree(MyHeap
, 0, Buf
);
180 WCHAR LogPath
[MAX_PATH
];
186 InitializeCriticalSection(&LogListCs
);
188 MyHeap
= HeapCreate(0, 1024*256, 0);
192 DPRINT1("FATAL ERROR, can't create heap.\n");
197 GetWindowsDirectory(LogPath
, MAX_PATH
);
198 if(GetDriveType(LogPath
) == DRIVE_CDROM
)
200 DPRINT("LiveCD detected\n");
205 result
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
206 L
"SYSTEM\\CurrentControlSet\\Services\\EventLog",
211 if(result
!= ERROR_SUCCESS
)
213 DPRINT1("Fatal error: can't open eventlog registry key.\n");
218 LoadLogFiles(elogKey
);
221 StartServiceCtrlDispatcher(ServiceTable
);
224 DeleteCriticalSection(&LogListCs
);
226 // Close all log files.
227 for(pLogf
= LogListHead
; pLogf
; pLogf
= ((PLOGFILE
)pLogf
)->Next
)
230 if(MyHeap
) HeapDestroy(MyHeap
);
235 VOID
EventTimeToSystemTime(DWORD EventTime
,
236 SYSTEMTIME
*pSystemTime
)
238 SYSTEMTIME st1970
= { 1970, 1, 0, 1, 0, 0, 0, 0 };
245 uUCT
.ft
.dwHighDateTime
= 0;
246 uUCT
.ft
.dwLowDateTime
= EventTime
;
247 SystemTimeToFileTime(&st1970
, &u1970
.ft
);
248 uUCT
.ll
= uUCT
.ll
* 10000000 + u1970
.ll
;
249 FileTimeToLocalFileTime(&uUCT
.ft
, &ftLocal
);
250 FileTimeToSystemTime(&ftLocal
, pSystemTime
);
253 VOID
SystemTimeToEventTime(SYSTEMTIME
*pSystemTime
,
256 SYSTEMTIME st1970
= { 1970, 1, 0, 1, 0, 0, 0, 0 };
262 SystemTimeToFileTime(pSystemTime
, &Time
.ft
);
263 SystemTimeToFileTime(&st1970
, &u1970
.ft
);
264 *pEventTime
= (Time
.ll
- u1970
.ll
) / 10000000;
267 VOID
PRINT_HEADER(PFILE_HEADER header
)
269 DPRINT("SizeOfHeader=%d\n",header
->SizeOfHeader
);
270 DPRINT("Signature=0x%x\n",header
->Signature
);
271 DPRINT("MajorVersion=%d\n",header
->MajorVersion
);
272 DPRINT("MinorVersion=%d\n",header
->MinorVersion
);
273 DPRINT("FirstRecordOffset=%d\n",header
->FirstRecordOffset
);
274 DPRINT("EofOffset=0x%x\n",header
->EofOffset
);
275 DPRINT("NextRecord=%d\n",header
->NextRecord
);
276 DPRINT("OldestRecord=%d\n",header
->OldestRecord
);
277 DPRINT("unknown1=0x%x\n",header
->unknown1
);
278 DPRINT("unknown2=0x%x\n",header
->unknown2
);
279 DPRINT("SizeOfHeader2=%d\n",header
->SizeOfHeader2
);
281 if(header
->Flags
& LOGFILE_FLAG1
)DPRINT("LOGFILE_FLAG1 ");
282 if(header
->Flags
& LOGFILE_FLAG2
)DPRINT("| LOGFILE_FLAG2 ");
283 if(header
->Flags
& LOGFILE_FLAG3
)DPRINT("| LOGFILE_FLAG3 ");
284 if(header
->Flags
& LOGFILE_FLAG4
)DPRINT("| LOGFILE_FLAG4");
288 VOID
PRINT_RECORD(PEVENTLOGRECORD pRec
)
294 DPRINT("Length=%d\n", pRec
->Length
);
295 DPRINT("Reserved=0x%x\n", pRec
->Reserved
);
296 DPRINT("RecordNumber=%d\n", pRec
->RecordNumber
);
298 EventTimeToSystemTime(pRec
->TimeGenerated
, &time
);
299 DPRINT("TimeGenerated=%d.%d.%d %d:%d:%d\n",
300 time
.wDay
, time
.wMonth
, time
.wYear
,
301 time
.wHour
, time
.wMinute
, time
.wSecond
);
303 EventTimeToSystemTime(pRec
->TimeWritten
, &time
);
304 DPRINT("TimeWritten=%d.%d.%d %d:%d:%d\n",
305 time
.wDay
, time
.wMonth
, time
.wYear
,
306 time
.wHour
, time
.wMinute
, time
.wSecond
);
308 DPRINT("EventID=%d\n", pRec
->EventID
);
310 switch(pRec
->EventType
)
312 case EVENTLOG_ERROR_TYPE
:
313 DPRINT("EventType = EVENTLOG_ERROR_TYPE\n");
315 case EVENTLOG_WARNING_TYPE
:
316 DPRINT("EventType = EVENTLOG_WARNING_TYPE\n");
318 case EVENTLOG_INFORMATION_TYPE
:
319 DPRINT("EventType = EVENTLOG_INFORMATION_TYPE\n");
321 case EVENTLOG_AUDIT_SUCCESS
:
322 DPRINT("EventType = EVENTLOG_AUDIT_SUCCESS\n");
324 case EVENTLOG_AUDIT_FAILURE
:
325 DPRINT("EventType = EVENTLOG_AUDIT_FAILURE\n");
328 DPRINT("EventType = %x\n");
331 DPRINT("NumStrings=%d\n", pRec
->NumStrings
);
332 DPRINT("EventCategory=%d\n", pRec
->EventCategory
);
333 DPRINT("ReservedFlags=0x%x\n", pRec
->ReservedFlags
);
334 DPRINT("ClosingRecordNumber=%d\n", pRec
->ClosingRecordNumber
);
335 DPRINT("StringOffset=%d\n", pRec
->StringOffset
);
336 DPRINT("UserSidLength=%d\n", pRec
->UserSidLength
);
337 DPRINT("UserSidOffset=%d\n", pRec
->UserSidOffset
);
338 DPRINT("DataLength=%d\n", pRec
->DataLength
);
339 DPRINT("DataOffset=%d\n", pRec
->DataOffset
);
341 DPRINT("SourceName: %S\n", (WCHAR
*)(((PBYTE
)pRec
)+sizeof(EVENTLOGRECORD
)));
342 i
= (lstrlenW((WCHAR
*)(((PBYTE
)pRec
)+sizeof(EVENTLOGRECORD
)))+1)*sizeof(WCHAR
);
343 DPRINT("ComputerName: %S\n", (WCHAR
*)(((PBYTE
)pRec
)+sizeof(EVENTLOGRECORD
)+i
));
345 if(pRec
->StringOffset
< pRec
->Length
&& pRec
->NumStrings
){
346 DPRINT("Strings:\n");
347 str
= (WCHAR
*)(((PBYTE
)pRec
)+pRec
->StringOffset
);
348 for(i
= 0; i
< pRec
->NumStrings
; i
++)
350 DPRINT("[%d] %S\n", i
, str
);
351 str
= str
+lstrlenW(str
)+1;
355 DPRINT("Length2=%d\n", *(PDWORD
)(((PBYTE
)pRec
)+pRec
->Length
-4));