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 static VOID CALLBACK
ServiceMain(DWORD
, LPWSTR
*);
17 static WCHAR ServiceName
[] = L
"EventLog";
18 static SERVICE_TABLE_ENTRYW ServiceTable
[2] =
20 { ServiceName
, ServiceMain
},
24 SERVICE_STATUS ServiceStatus
;
25 SERVICE_STATUS_HANDLE ServiceStatusHandle
;
27 BOOL onLiveCD
= FALSE
; // On livecd events will go to debug output only
30 /* FUNCTIONS ****************************************************************/
33 UpdateServiceStatus(DWORD dwState
)
35 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
36 ServiceStatus
.dwCurrentState
= dwState
;
37 ServiceStatus
.dwControlsAccepted
= 0;
38 ServiceStatus
.dwWin32ExitCode
= 0;
39 ServiceStatus
.dwServiceSpecificExitCode
= 0;
40 ServiceStatus
.dwCheckPoint
= 0;
42 if (dwState
== SERVICE_START_PENDING
||
43 dwState
== SERVICE_STOP_PENDING
||
44 dwState
== SERVICE_PAUSE_PENDING
||
45 dwState
== SERVICE_CONTINUE_PENDING
)
46 ServiceStatus
.dwWaitHint
= 10000;
48 ServiceStatus
.dwWaitHint
= 0;
50 SetServiceStatus(ServiceStatusHandle
,
55 ServiceControlHandler(DWORD dwControl
,
60 DPRINT("ServiceControlHandler() called\n");
64 case SERVICE_CONTROL_STOP
:
65 DPRINT(" SERVICE_CONTROL_STOP received\n");
66 UpdateServiceStatus(SERVICE_STOPPED
);
69 case SERVICE_CONTROL_PAUSE
:
70 DPRINT(" SERVICE_CONTROL_PAUSE received\n");
71 UpdateServiceStatus(SERVICE_PAUSED
);
74 case SERVICE_CONTROL_CONTINUE
:
75 DPRINT(" SERVICE_CONTROL_CONTINUE received\n");
76 UpdateServiceStatus(SERVICE_RUNNING
);
79 case SERVICE_CONTROL_INTERROGATE
:
80 DPRINT(" SERVICE_CONTROL_INTERROGATE received\n");
81 SetServiceStatus(ServiceStatusHandle
,
85 case SERVICE_CONTROL_SHUTDOWN
:
86 DPRINT(" SERVICE_CONTROL_SHUTDOWN received\n");
87 UpdateServiceStatus(SERVICE_STOPPED
);
91 DPRINT1(" Control %lu received\n");
92 return ERROR_CALL_NOT_IMPLEMENTED
;
102 hThread
= CreateThread(NULL
,
104 (LPTHREAD_START_ROUTINE
)
112 DPRINT("Can't create PortThread\n");
113 return GetLastError();
116 CloseHandle(hThread
);
118 hThread
= CreateThread(NULL
,
120 (LPTHREAD_START_ROUTINE
)
128 DPRINT("Can't create RpcThread\n");
129 return GetLastError();
132 CloseHandle(hThread
);
134 return ERROR_SUCCESS
;
139 ServiceMain(DWORD argc
,
144 UNREFERENCED_PARAMETER(argc
);
145 UNREFERENCED_PARAMETER(argv
);
147 DPRINT("ServiceMain() called\n");
149 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
150 ServiceControlHandler
,
152 if (!ServiceStatusHandle
)
154 dwError
= GetLastError();
155 DPRINT1("RegisterServiceCtrlHandlerW() failed! (Error %lu)\n", dwError
);
159 UpdateServiceStatus(SERVICE_START_PENDING
);
161 dwError
= ServiceInit();
162 if (dwError
!= ERROR_SUCCESS
)
164 DPRINT("Service stopped (dwError: %lu\n", dwError
);
165 UpdateServiceStatus(SERVICE_START_PENDING
);
169 DPRINT("Service started\n");
170 UpdateServiceStatus(SERVICE_RUNNING
);
172 LogfReportEvent(EVENTLOG_INFORMATION_TYPE
,
174 EVENT_EventlogStarted
);
177 DPRINT("ServiceMain() done\n");
181 PLOGFILE
LoadLogFile(HKEY hKey
, WCHAR
* LogName
)
183 DWORD MaxValueLen
, ValueLen
, Type
, ExpandedLen
;
184 WCHAR
*Buf
= NULL
, *Expanded
= NULL
;
188 DPRINT("LoadLogFile: %S\n", LogName
);
190 RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
191 NULL
, NULL
, &MaxValueLen
, NULL
, NULL
);
193 Buf
= HeapAlloc(MyHeap
, 0, MaxValueLen
);
196 DPRINT1("Can't allocate heap!\n");
200 ValueLen
= MaxValueLen
;
202 Result
= RegQueryValueEx(hKey
,
208 if (Result
!= ERROR_SUCCESS
)
210 DPRINT1("RegQueryValueEx failed: %d\n", GetLastError());
211 HeapFree(MyHeap
, 0, Buf
);
215 if (Type
!= REG_EXPAND_SZ
&& Type
!= REG_SZ
)
217 DPRINT1("%S\\File - value of wrong type %x.\n", LogName
, Type
);
218 HeapFree(MyHeap
, 0, Buf
);
222 ExpandedLen
= ExpandEnvironmentStrings(Buf
, NULL
, 0);
223 Expanded
= HeapAlloc(MyHeap
, 0, ExpandedLen
* sizeof(WCHAR
));
226 DPRINT1("Can't allocate heap!\n");
227 HeapFree(MyHeap
, 0, Buf
);
231 ExpandEnvironmentStrings(Buf
, Expanded
, ExpandedLen
);
233 DPRINT("%S -> %S\n", Buf
, Expanded
);
235 pLogf
= LogfCreate(LogName
, Expanded
);
239 DPRINT1("Failed to create %S!\n", Expanded
);
242 HeapFree(MyHeap
, 0, Buf
);
243 HeapFree(MyHeap
, 0, Expanded
);
247 BOOL
LoadLogFiles(HKEY eventlogKey
)
250 DWORD MaxLognameLen
, LognameLen
;
255 RegQueryInfoKey(eventlogKey
,
256 NULL
, NULL
, NULL
, NULL
,
258 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
262 Buf
= HeapAlloc(MyHeap
, 0, MaxLognameLen
* sizeof(WCHAR
));
266 DPRINT1("Error: can't allocate heap!\n");
271 LognameLen
= MaxLognameLen
;
273 while (RegEnumKeyEx(eventlogKey
,
277 NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
283 result
= RegOpenKeyEx(eventlogKey
, Buf
, 0, KEY_ALL_ACCESS
, &SubKey
);
284 if (result
!= ERROR_SUCCESS
)
286 DPRINT1("Failed to open %S key.\n", Buf
);
287 HeapFree(MyHeap
, 0, Buf
);
291 pLogFile
= LoadLogFile(SubKey
, Buf
);
292 if (pLogFile
!= NULL
)
294 DPRINT("Loaded %S\n", Buf
);
295 LoadEventSources(SubKey
, pLogFile
);
299 DPRINT1("Failed to load %S\n", Buf
);
303 LognameLen
= MaxLognameLen
;
307 HeapFree(MyHeap
, 0, Buf
);
313 WCHAR LogPath
[MAX_PATH
];
318 LogfListInitialize();
319 InitEventSourceList();
321 MyHeap
= HeapCreate(0, 1024 * 256, 0);
325 DPRINT1("FATAL ERROR, can't create heap.\n");
330 GetWindowsDirectory(LogPath
, MAX_PATH
);
332 if (GetDriveType(LogPath
) == DRIVE_CDROM
)
334 DPRINT("LiveCD detected\n");
339 result
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
340 L
"SYSTEM\\CurrentControlSet\\Services\\EventLog",
345 if (result
!= ERROR_SUCCESS
)
347 DPRINT1("Fatal error: can't open eventlog registry key.\n");
352 LoadLogFiles(elogKey
);
355 StartServiceCtrlDispatcher(ServiceTable
);
366 VOID
EventTimeToSystemTime(DWORD EventTime
, SYSTEMTIME
* pSystemTime
)
368 SYSTEMTIME st1970
= { 1970, 1, 0, 1, 0, 0, 0, 0 };
376 uUCT
.ft
.dwHighDateTime
= 0;
377 uUCT
.ft
.dwLowDateTime
= EventTime
;
378 SystemTimeToFileTime(&st1970
, &u1970
.ft
);
379 uUCT
.ll
= uUCT
.ll
* 10000000 + u1970
.ll
;
380 FileTimeToLocalFileTime(&uUCT
.ft
, &ftLocal
);
381 FileTimeToSystemTime(&ftLocal
, pSystemTime
);
384 VOID
SystemTimeToEventTime(SYSTEMTIME
* pSystemTime
, DWORD
* pEventTime
)
386 SYSTEMTIME st1970
= { 1970, 1, 0, 1, 0, 0, 0, 0 };
393 SystemTimeToFileTime(pSystemTime
, &Time
.ft
);
394 SystemTimeToFileTime(&st1970
, &u1970
.ft
);
395 *pEventTime
= (Time
.ll
- u1970
.ll
) / 10000000;
398 VOID
PRINT_HEADER(PEVENTLOGHEADER header
)
400 DPRINT("HeaderSize = %d\n", header
->HeaderSize
);
401 DPRINT("Signature = 0x%x\n", header
->Signature
);
402 DPRINT("MajorVersion = %d\n", header
->MajorVersion
);
403 DPRINT("MinorVersion = %d\n", header
->MinorVersion
);
404 DPRINT("StartOffset = %d\n", header
->StartOffset
);
405 DPRINT("EndOffset = 0x%x\n", header
->EndOffset
);
406 DPRINT("CurrentRecordNumber = %d\n", header
->CurrentRecordNumber
);
407 DPRINT("OldestRecordNumber = %d\n", header
->OldestRecordNumber
);
408 DPRINT("MaxSize = 0x%x\n", header
->MaxSize
);
409 DPRINT("Retention = 0x%x\n", header
->Retention
);
410 DPRINT("EndHeaderSize = %d\n", header
->EndHeaderSize
);
412 if (header
->Flags
& ELF_LOGFILE_HEADER_DIRTY
) DPRINT("ELF_LOGFILE_HEADER_DIRTY");
413 if (header
->Flags
& ELF_LOGFILE_HEADER_WRAP
) DPRINT("| ELF_LOGFILE_HEADER_WRAP ");
414 if (header
->Flags
& ELF_LOGGFILE_LOGFULL_WRITTEN
) DPRINT("| ELF_LOGGFILE_LOGFULL_WRITTEN ");
415 if (header
->Flags
& ELF_LOGFILE_ARCHIVE_SET
) DPRINT("| ELF_LOGFILE_ARCHIVE_SET ");
419 VOID
PRINT_RECORD(PEVENTLOGRECORD pRec
)
425 DPRINT("Length = %d\n", pRec
->Length
);
426 DPRINT("Reserved = 0x%x\n", pRec
->Reserved
);
427 DPRINT("RecordNumber = %d\n", pRec
->RecordNumber
);
429 EventTimeToSystemTime(pRec
->TimeGenerated
, &time
);
430 DPRINT("TimeGenerated = %d.%d.%d %d:%d:%d\n",
431 time
.wDay
, time
.wMonth
, time
.wYear
,
432 time
.wHour
, time
.wMinute
, time
.wSecond
);
434 EventTimeToSystemTime(pRec
->TimeWritten
, &time
);
435 DPRINT("TimeWritten = %d.%d.%d %d:%d:%d\n",
436 time
.wDay
, time
.wMonth
, time
.wYear
,
437 time
.wHour
, time
.wMinute
, time
.wSecond
);
439 DPRINT("EventID = %d\n", pRec
->EventID
);
441 switch (pRec
->EventType
)
443 case EVENTLOG_ERROR_TYPE
:
444 DPRINT("EventType = EVENTLOG_ERROR_TYPE\n");
446 case EVENTLOG_WARNING_TYPE
:
447 DPRINT("EventType = EVENTLOG_WARNING_TYPE\n");
449 case EVENTLOG_INFORMATION_TYPE
:
450 DPRINT("EventType = EVENTLOG_INFORMATION_TYPE\n");
452 case EVENTLOG_AUDIT_SUCCESS
:
453 DPRINT("EventType = EVENTLOG_AUDIT_SUCCESS\n");
455 case EVENTLOG_AUDIT_FAILURE
:
456 DPRINT("EventType = EVENTLOG_AUDIT_FAILURE\n");
459 DPRINT("EventType = %d\n", pRec
->EventType
);
462 DPRINT("NumStrings = %d\n", pRec
->NumStrings
);
463 DPRINT("EventCategory = %d\n", pRec
->EventCategory
);
464 DPRINT("ReservedFlags = 0x%x\n", pRec
->ReservedFlags
);
465 DPRINT("ClosingRecordNumber = %d\n", pRec
->ClosingRecordNumber
);
466 DPRINT("StringOffset = %d\n", pRec
->StringOffset
);
467 DPRINT("UserSidLength = %d\n", pRec
->UserSidLength
);
468 DPRINT("UserSidOffset = %d\n", pRec
->UserSidOffset
);
469 DPRINT("DataLength = %d\n", pRec
->DataLength
);
470 DPRINT("DataOffset = %d\n", pRec
->DataOffset
);
472 DPRINT("SourceName: %S\n", (WCHAR
*) (((PBYTE
) pRec
) + sizeof(EVENTLOGRECORD
)));
474 i
= (lstrlenW((WCHAR
*) (((PBYTE
) pRec
) + sizeof(EVENTLOGRECORD
))) + 1) *
477 DPRINT("ComputerName: %S\n", (WCHAR
*) (((PBYTE
) pRec
) + sizeof(EVENTLOGRECORD
) + i
));
479 if (pRec
->StringOffset
< pRec
->Length
&& pRec
->NumStrings
)
481 DPRINT("Strings:\n");
482 str
= (WCHAR
*) (((PBYTE
) pRec
) + pRec
->StringOffset
);
483 for (i
= 0; i
< pRec
->NumStrings
; i
++)
485 DPRINT("[%d] %S\n", i
, str
);
486 str
= str
+ lstrlenW(str
) + 1;
490 DPRINT("Length2 = %d\n", *(PDWORD
) (((PBYTE
) pRec
) + pRec
->Length
- 4));