Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621/* * PROJECT: ReactOS EventLog Service * LICENSE: GPL - See COPYING in the top level directory * FILE: base/services/eventlog/eventlog.c * PURPOSE: Event logging service * COPYRIGHT: Copyright 2002 Eric Kohl * Copyright 2005 Saveliy Tretiakov * Hermes Belusca-Maito */
/* INCLUDES *****************************************************************/
#include "eventlog.h"#include <stdio.h>#include <netevent.h>
#define NDEBUG#include <debug.h>
/* GLOBALS ******************************************************************/
static VOID CALLBACK ServiceMain(DWORD, LPWSTR*);static WCHAR ServiceName[] = L"EventLog";static SERVICE_TABLE_ENTRYW ServiceTable[2] ={ { ServiceName, ServiceMain }, { NULL, NULL }};
SERVICE_STATUS ServiceStatus;SERVICE_STATUS_HANDLE ServiceStatusHandle;
BOOL onLiveCD = FALSE; // On LiveCD events will go to debug output only
PEVENTSOURCE EventLogSource = NULL;
/* FUNCTIONS ****************************************************************/
static VOIDUpdateServiceStatus(DWORD dwState){ ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ServiceStatus.dwCurrentState = dwState; ServiceStatus.dwControlsAccepted = 0; ServiceStatus.dwWin32ExitCode = 0; ServiceStatus.dwServiceSpecificExitCode = 0; ServiceStatus.dwCheckPoint = 0;
if (dwState == SERVICE_START_PENDING || dwState == SERVICE_STOP_PENDING || dwState == SERVICE_PAUSE_PENDING || dwState == SERVICE_CONTINUE_PENDING) ServiceStatus.dwWaitHint = 10000; else ServiceStatus.dwWaitHint = 0;
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);}
static DWORD WINAPIServiceControlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext){ DPRINT("ServiceControlHandler() called\n");
switch (dwControl) { case SERVICE_CONTROL_STOP: DPRINT(" SERVICE_CONTROL_STOP received\n");
LogfReportEvent(EVENTLOG_INFORMATION_TYPE, 0, EVENT_EventlogStopped, 0, NULL, 0, NULL);
/* Stop listening to incoming RPC messages */ RpcMgmtStopServerListening(NULL); UpdateServiceStatus(SERVICE_STOPPED); return ERROR_SUCCESS;
case SERVICE_CONTROL_PAUSE: DPRINT(" SERVICE_CONTROL_PAUSE received\n"); UpdateServiceStatus(SERVICE_PAUSED); return ERROR_SUCCESS;
case SERVICE_CONTROL_CONTINUE: DPRINT(" SERVICE_CONTROL_CONTINUE received\n"); UpdateServiceStatus(SERVICE_RUNNING); return ERROR_SUCCESS;
case SERVICE_CONTROL_INTERROGATE: DPRINT(" SERVICE_CONTROL_INTERROGATE received\n"); SetServiceStatus(ServiceStatusHandle, &ServiceStatus); return ERROR_SUCCESS;
case SERVICE_CONTROL_SHUTDOWN: DPRINT(" SERVICE_CONTROL_SHUTDOWN received\n");
LogfReportEvent(EVENTLOG_INFORMATION_TYPE, 0, EVENT_EventlogStopped, 0, NULL, 0, NULL);
UpdateServiceStatus(SERVICE_STOPPED); return ERROR_SUCCESS;
default: DPRINT1(" Control %lu received\n", dwControl); return ERROR_CALL_NOT_IMPLEMENTED; }}
static DWORDServiceInit(VOID){ HANDLE hThread;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PortThreadRoutine, NULL, 0, NULL); if (!hThread) { DPRINT("Cannot create PortThread\n"); return GetLastError(); } else CloseHandle(hThread);
hThread = CreateThread(NULL, 0, RpcThreadRoutine, NULL, 0, NULL);
if (!hThread) { DPRINT("Cannot create RpcThread\n"); return GetLastError(); } else CloseHandle(hThread);
return ERROR_SUCCESS;}
static VOIDReportProductInfoEvent(VOID){ OSVERSIONINFOW versionInfo; WCHAR szBuffer[512]; PWSTR str; size_t cchRemain; HKEY hKey; DWORD dwValueLength; DWORD dwType; LONG lResult = ERROR_SUCCESS;
ZeroMemory(&versionInfo, sizeof(versionInfo)); versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
/* Get version information */ if (!GetVersionExW(&versionInfo)) return;
ZeroMemory(szBuffer, sizeof(szBuffer)); str = szBuffer; cchRemain = ARRAYSIZE(szBuffer);
/* Write the version number into the buffer */ StringCchPrintfExW(str, cchRemain, &str, &cchRemain, 0, L"%lu.%lu", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion); str++; cchRemain++;
/* Write the build number into the buffer */ StringCchPrintfExW(str, cchRemain, &str, &cchRemain, 0, L"%lu", versionInfo.dwBuildNumber); str++; cchRemain++;
/* Write the service pack info into the buffer */ StringCchCopyExW(str, cchRemain, versionInfo.szCSDVersion, &str, &cchRemain, 0); str++; cchRemain++;
/* Read 'CurrentType' from the registry and write it into the buffer */ lResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey); if (lResult == ERROR_SUCCESS) { dwValueLength = cchRemain; lResult = RegQueryValueExW(hKey, L"CurrentType", NULL, &dwType, (LPBYTE)str, &dwValueLength);
RegCloseKey(hKey); }
/* Log the product information */ LogfReportEvent(EVENTLOG_INFORMATION_TYPE, 0, EVENT_EventLogProductInfo, 4, szBuffer, 0, NULL);}
static VOID CALLBACKServiceMain(DWORD argc, LPWSTR* argv){ DWORD dwError;
UNREFERENCED_PARAMETER(argc); UNREFERENCED_PARAMETER(argv);
DPRINT("ServiceMain() called\n");
ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, ServiceControlHandler, NULL); if (!ServiceStatusHandle) { dwError = GetLastError(); DPRINT1("RegisterServiceCtrlHandlerW() failed! (Error %lu)\n", dwError); return; }
UpdateServiceStatus(SERVICE_START_PENDING);
dwError = ServiceInit(); if (dwError != ERROR_SUCCESS) { DPRINT("Service stopped (dwError: %lu\n", dwError); UpdateServiceStatus(SERVICE_START_PENDING); } else { DPRINT("Service started\n"); UpdateServiceStatus(SERVICE_RUNNING);
ReportProductInfoEvent();
LogfReportEvent(EVENTLOG_INFORMATION_TYPE, 0, EVENT_EventlogStarted, 0, NULL, 0, NULL); }
DPRINT("ServiceMain() done\n");}
static PLOGFILELoadLogFile(HKEY hKey, PWSTR LogName){ DWORD MaxValueLen, ValueLen, Type, ExpandedLen; PWSTR Buf = NULL, Expanded = NULL; LONG Result; PLOGFILE pLogf = NULL; UNICODE_STRING FileName; ULONG ulMaxSize, ulRetention; NTSTATUS Status;
DPRINT("LoadLogFile: `%S'\n", LogName);
Result = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxValueLen, NULL, NULL); if (Result != ERROR_SUCCESS) { DPRINT1("RegQueryInfoKeyW failed: %lu\n", Result); return NULL; }
MaxValueLen = ROUND_DOWN(MaxValueLen, sizeof(WCHAR)); Buf = HeapAlloc(GetProcessHeap(), 0, MaxValueLen); if (!Buf) { DPRINT1("Cannot allocate heap!\n"); return NULL; }
ValueLen = MaxValueLen; Result = RegQueryValueExW(hKey, L"File", NULL, &Type, (LPBYTE)Buf, &ValueLen); /* * If we failed, because the registry value was inexistent * or the value type was incorrect, create a new "File" value * that holds the default event log path. */ if ((Result != ERROR_SUCCESS) || (Type != REG_EXPAND_SZ && Type != REG_SZ)) { MaxValueLen = (wcslen(L"%SystemRoot%\\System32\\Config\\") + wcslen(LogName) + wcslen(L".evt") + 1) * sizeof(WCHAR);
Expanded = HeapReAlloc(GetProcessHeap(), 0, Buf, MaxValueLen); if (!Expanded) { DPRINT1("Cannot reallocate heap!\n"); HeapFree(GetProcessHeap(), 0, Buf); return NULL; } Buf = Expanded;
StringCbCopyW(Buf, MaxValueLen, L"%SystemRoot%\\System32\\Config\\"); StringCbCatW(Buf, MaxValueLen, LogName); StringCbCatW(Buf, MaxValueLen, L".evt");
ValueLen = MaxValueLen; Result = RegSetValueExW(hKey, L"File", 0, REG_EXPAND_SZ, (LPBYTE)Buf, ValueLen); if (Result != ERROR_SUCCESS) { DPRINT1("RegSetValueExW failed: %lu\n", Result); HeapFree(GetProcessHeap(), 0, Buf); return NULL; } }
ExpandedLen = ExpandEnvironmentStringsW(Buf, NULL, 0); Expanded = HeapAlloc(GetProcessHeap(), 0, ExpandedLen * sizeof(WCHAR)); if (!Expanded) { DPRINT1("Cannot allocate heap!\n"); HeapFree(GetProcessHeap(), 0, Buf); return NULL; }
ExpandEnvironmentStringsW(Buf, Expanded, ExpandedLen);
if (!RtlDosPathNameToNtPathName_U(Expanded, &FileName, NULL, NULL)) { DPRINT1("Cannot convert path!\n"); HeapFree(GetProcessHeap(), 0, Expanded); HeapFree(GetProcessHeap(), 0, Buf); return NULL; }
DPRINT("%S -> %S\n", Buf, Expanded);
ValueLen = sizeof(ulMaxSize); Result = RegQueryValueExW(hKey, L"MaxSize", NULL, &Type, (LPBYTE)&ulMaxSize, &ValueLen); if ((Result != ERROR_SUCCESS) || (Type != REG_DWORD)) { ulMaxSize = 512 * 1024; /* 512 kBytes */
Result = RegSetValueExW(hKey, L"MaxSize", 0, REG_DWORD, (LPBYTE)&ulMaxSize, sizeof(ulMaxSize)); }
ValueLen = sizeof(ulRetention); Result = RegQueryValueExW(hKey, L"Retention", NULL, &Type, (LPBYTE)&ulRetention, &ValueLen); if ((Result != ERROR_SUCCESS) || (Type != REG_DWORD)) { /* On Windows 2003 it is 604800 (secs) == 7 days */ ulRetention = 0;
Result = RegSetValueExW(hKey, L"Retention", 0, REG_DWORD, (LPBYTE)&ulRetention, sizeof(ulRetention)); }
// TODO: Add, or use, default values for "AutoBackupLogFiles" (REG_DWORD) // and "CustomSD" (REG_SZ).
Status = LogfCreate(&pLogf, LogName, &FileName, ulMaxSize, ulRetention, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to create %S! (Status %08lx)\n", Expanded, Status); }
HeapFree(GetProcessHeap(), 0, Expanded); HeapFree(GetProcessHeap(), 0, Buf); return pLogf;}
static BOOLLoadLogFiles(HKEY eventlogKey){ LONG Result; DWORD MaxLognameLen, LognameLen; DWORD dwIndex; PWSTR Buf = NULL; PLOGFILE pLogFile;
Result = RegQueryInfoKeyW(eventlogKey, NULL, NULL, NULL, NULL, &MaxLognameLen, NULL, NULL, NULL, NULL, NULL, NULL); if (Result != ERROR_SUCCESS) { DPRINT1("RegQueryInfoKeyW failed: %lu\n", Result); return FALSE; }
MaxLognameLen++;
Buf = HeapAlloc(GetProcessHeap(), 0, MaxLognameLen * sizeof(WCHAR)); if (!Buf) { DPRINT1("Error: cannot allocate heap!\n"); return FALSE; }
LognameLen = MaxLognameLen; dwIndex = 0; while (RegEnumKeyExW(eventlogKey, dwIndex, Buf, &LognameLen, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { HKEY SubKey;
DPRINT("%S\n", Buf);
Result = RegOpenKeyExW(eventlogKey, Buf, 0, KEY_ALL_ACCESS, &SubKey); if (Result != ERROR_SUCCESS) { DPRINT1("Failed to open %S key.\n", Buf); HeapFree(GetProcessHeap(), 0, Buf); return FALSE; }
pLogFile = LoadLogFile(SubKey, Buf); if (pLogFile != NULL) { DPRINT("Loaded %S\n", Buf); LoadEventSources(SubKey, pLogFile); } else { DPRINT1("Failed to load %S\n", Buf); }
RegCloseKey(SubKey);
LognameLen = MaxLognameLen; dwIndex++; }
HeapFree(GetProcessHeap(), 0, Buf); return TRUE;}
int wmain(int argc, WCHAR* argv[]){ INT RetCode = 0; LONG Result; HKEY elogKey; WCHAR LogPath[MAX_PATH];
LogfListInitialize(); InitEventSourceList();
GetSystemWindowsDirectoryW(LogPath, ARRAYSIZE(LogPath));
if (GetDriveTypeW(LogPath) == DRIVE_CDROM) { DPRINT("LiveCD detected\n"); onLiveCD = TRUE; } else { Result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\EventLog", 0, KEY_ALL_ACCESS, &elogKey); if (Result != ERROR_SUCCESS) { DPRINT1("Fatal error: cannot open eventlog registry key.\n"); RetCode = 1; goto bye_bye; }
LoadLogFiles(elogKey); }
EventLogSource = GetEventSourceByName(L"EventLog"); if (!EventLogSource) { DPRINT1("The 'EventLog' source is unavailable. The EventLog service will not be able to log its own events.\n"); }
StartServiceCtrlDispatcher(ServiceTable);
bye_bye: LogfCloseAll();
return RetCode;}
VOID PRINT_RECORD(PEVENTLOGRECORD pRec){ UINT i; PWSTR str; LARGE_INTEGER SystemTime; TIME_FIELDS Time;
DPRINT1("PRINT_RECORD(0x%p)\n", pRec);
DbgPrint("Length = %lu\n", pRec->Length); DbgPrint("Reserved = 0x%x\n", pRec->Reserved); DbgPrint("RecordNumber = %lu\n", pRec->RecordNumber);
RtlSecondsSince1970ToTime(pRec->TimeGenerated, &SystemTime); RtlTimeToTimeFields(&SystemTime, &Time); DbgPrint("TimeGenerated = %hu.%hu.%hu %hu:%hu:%hu\n", Time.Day, Time.Month, Time.Year, Time.Hour, Time.Minute, Time.Second);
RtlSecondsSince1970ToTime(pRec->TimeWritten, &SystemTime); RtlTimeToTimeFields(&SystemTime, &Time); DbgPrint("TimeWritten = %hu.%hu.%hu %hu:%hu:%hu\n", Time.Day, Time.Month, Time.Year, Time.Hour, Time.Minute, Time.Second);
DbgPrint("EventID = %lu\n", pRec->EventID);
switch (pRec->EventType) { case EVENTLOG_ERROR_TYPE: DbgPrint("EventType = EVENTLOG_ERROR_TYPE\n"); break; case EVENTLOG_WARNING_TYPE: DbgPrint("EventType = EVENTLOG_WARNING_TYPE\n"); break; case EVENTLOG_INFORMATION_TYPE: DbgPrint("EventType = EVENTLOG_INFORMATION_TYPE\n"); break; case EVENTLOG_AUDIT_SUCCESS: DbgPrint("EventType = EVENTLOG_AUDIT_SUCCESS\n"); break; case EVENTLOG_AUDIT_FAILURE: DbgPrint("EventType = EVENTLOG_AUDIT_FAILURE\n"); break; default: DbgPrint("EventType = %hu\n", pRec->EventType); }
DbgPrint("NumStrings = %hu\n", pRec->NumStrings); DbgPrint("EventCategory = %hu\n", pRec->EventCategory); DbgPrint("ReservedFlags = 0x%x\n", pRec->ReservedFlags); DbgPrint("ClosingRecordNumber = %lu\n", pRec->ClosingRecordNumber); DbgPrint("StringOffset = %lu\n", pRec->StringOffset); DbgPrint("UserSidLength = %lu\n", pRec->UserSidLength); DbgPrint("UserSidOffset = %lu\n", pRec->UserSidOffset); DbgPrint("DataLength = %lu\n", pRec->DataLength); DbgPrint("DataOffset = %lu\n", pRec->DataOffset);
i = sizeof(EVENTLOGRECORD); DbgPrint("SourceName: %S\n", (PWSTR)((ULONG_PTR)pRec + i));
i += (wcslen((PWSTR)((ULONG_PTR)pRec + i)) + 1) * sizeof(WCHAR); DbgPrint("ComputerName: %S\n", (PWSTR)((ULONG_PTR)pRec + i));
if (pRec->StringOffset < pRec->Length && pRec->NumStrings) { DbgPrint("Strings:\n"); str = (PWSTR)((ULONG_PTR)pRec + pRec->StringOffset); for (i = 0; i < pRec->NumStrings; i++) { DbgPrint("[%u] %S\n", i, str); str += wcslen(str) + 1; } }
DbgPrint("Length2 = %lu\n", *(PULONG)((ULONG_PTR)pRec + pRec->Length - 4));}