From 13478a6cb084bfae0eb74e3a8828356794d8200b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 14 Aug 2016 19:15:54 +0000 Subject: [PATCH] [ROSTESTS]: Add an interactive test that tests some parts of the event log service. CORE-11843 CORE-11838 svn path=/trunk/; revision=72225 --- rostests/win32/CMakeLists.txt | 1 + rostests/win32/advapi32/CMakeLists.txt | 1 + .../win32/advapi32/eventlog/CMakeLists.txt | 21 + rostests/win32/advapi32/eventlog/EvtLogTest.c | 468 ++++++++++++++++++ .../advapi32/eventlog/MyEventProvider.mc | 102 ++++ 5 files changed, 593 insertions(+) create mode 100644 rostests/win32/advapi32/CMakeLists.txt create mode 100644 rostests/win32/advapi32/eventlog/CMakeLists.txt create mode 100644 rostests/win32/advapi32/eventlog/EvtLogTest.c create mode 100644 rostests/win32/advapi32/eventlog/MyEventProvider.mc diff --git a/rostests/win32/CMakeLists.txt b/rostests/win32/CMakeLists.txt index 512f6adae6c..73e15e25a0e 100644 --- a/rostests/win32/CMakeLists.txt +++ b/rostests/win32/CMakeLists.txt @@ -1,2 +1,3 @@ +add_subdirectory(advapi32) add_subdirectory(kernel32) add_subdirectory(user32) diff --git a/rostests/win32/advapi32/CMakeLists.txt b/rostests/win32/advapi32/CMakeLists.txt new file mode 100644 index 00000000000..218c3495410 --- /dev/null +++ b/rostests/win32/advapi32/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(eventlog) diff --git a/rostests/win32/advapi32/eventlog/CMakeLists.txt b/rostests/win32/advapi32/eventlog/CMakeLists.txt new file mode 100644 index 00000000000..0c078720e50 --- /dev/null +++ b/rostests/win32/advapi32/eventlog/CMakeLists.txt @@ -0,0 +1,21 @@ +## Original MSVC commands: +## mc -U MyEventProvider.mc +## rc /fo $(IntDir)MyEventProvider.res MyEventProvider.rc +## link /dll /noentry /SUBSYSTEM:CONSOLE",5.0" /out:$(SolutionDir)$(Configuration)\MyEventProvider.dll $(IntDir)MyEventProvider.res + +## add_message_headers(UNICODE MyEventProvider.mc) + +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/MyEventProvider.rc ${CMAKE_CURRENT_BINARY_DIR}/MyEventProvider.h + COMMAND ${CMAKE_MC_COMPILER} -U ${CMAKE_CURRENT_SOURCE_DIR}/MyEventProvider.mc -r ${CMAKE_CURRENT_BINARY_DIR}/ + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/MyEventProvider.mc) + +add_library(MyEventProvider SHARED ${CMAKE_CURRENT_BINARY_DIR}/MyEventProvider.rc) +set_module_type(MyEventProvider win32dll UNICODE ENTRYPOINT 0) +add_cd_file(TARGET MyEventProvider DESTINATION reactos/bin FOR all) + +add_executable(evtlogtest EvtLogTest.c) +add_dependencies(evtlogtest MyEventProvider) +set_module_type(evtlogtest win32cui UNICODE) +add_importlibs(evtlogtest advapi32 msvcrt kernel32) +add_cd_file(TARGET evtlogtest DESTINATION reactos/bin FOR all) diff --git a/rostests/win32/advapi32/eventlog/EvtLogTest.c b/rostests/win32/advapi32/eventlog/EvtLogTest.c new file mode 100644 index 00000000000..e498c31ba01 --- /dev/null +++ b/rostests/win32/advapi32/eventlog/EvtLogTest.c @@ -0,0 +1,468 @@ +/* + * PROJECT: ReactOS Tests + * LICENSE: GPL - See COPYING in the top level directory + * FILE: rostests/win32/advapi32/eventlog/EvtLogTest.c + * PURPOSE: Interactively test some EventLog service APIs and its behaviour. + * PROGRAMMER: Hermes Belusca-Maito + */ + +#include +#include + +#define WIN32_LEAN_AND_MEAN +#include + +#include "MyEventProvider.h" + +#define PROVIDER_NAME L"MyEventProvider" + +BOOL CreateEventLog(LPCWSTR EventLogName, + UINT MaxSize, + UINT SourcesCount, + LPCWSTR EventLogSources[]) +{ + BOOL Success = FALSE; + LONG lRet; + HKEY hKey = NULL, hEventKey = NULL, hSrcKey = NULL; + UINT i; + // WCHAR evtFile[] = L"D:\\myfile.evtx"; + + wprintf(L"Creating log %s of MaxSize 0x%x with %d sources...", EventLogName, MaxSize, SourcesCount); + + lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Services\\Eventlog", + 0, KEY_CREATE_SUB_KEY, + &hKey); + if (lRet != ERROR_SUCCESS) + goto Quit; + + /* + * At this precise moment, EventLog detects we create a new log registry key + * and therefore creates for us the log file in System32\config (<= Win2k3) + * or in System32\winevt\Logs (>= Vista). + */ + lRet = RegCreateKeyExW(hKey, + EventLogName, + 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_CREATE_SUB_KEY | KEY_SET_VALUE, NULL, + &hEventKey, NULL); + if (lRet != ERROR_SUCCESS) + goto Quit; + + RegSetValueExW(hEventKey, L"MaxSize", 0, REG_DWORD, + (LPBYTE)&MaxSize, sizeof(MaxSize)); + + i = 0; + RegSetValueExW(hEventKey, L"Retention", 0, REG_DWORD, + (LPBYTE)&i, sizeof(i)); + +#if 0 + /* + * Set the flag that will allow EventLog to use an alternative log file name. + * If this flag is not set, EventLog will not care about the "File" value. + * When the flag is set, EventLog monitors for the "File" value, which can be + * changed at run-time, in which case a new event log file is created. + */ + i = 1; + RegSetValueExW(hEventKey, L"Flags", 0, REG_DWORD, + (LPBYTE)&i, sizeof(i)); + + RegSetValueExW(hEventKey, L"File", 0, REG_EXPAND_SZ, + (LPBYTE)evtFile, sizeof(evtFile)); +#endif + + for (i = 0; i < SourcesCount; i++) + { + lRet = RegCreateKeyExW(hEventKey, + EventLogSources[i], + 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_QUERY_VALUE, NULL, + &hSrcKey, NULL); + RegFlushKey(hSrcKey); + RegCloseKey(hSrcKey); + } + + RegFlushKey(hEventKey); + + Success = TRUE; + +Quit: + if (Success) + wprintf(L"Success\n"); + else + wprintf(L"Failure\n"); + + if (hEventKey) + RegCloseKey(hEventKey); + + if (hKey) + RegCloseKey(hKey); + + return Success; +} + +BOOL RemoveEventLog(LPCWSTR EventLogName) +{ + BOOL Success = FALSE; + LONG lRet; + HKEY hKey, hEventKey; + DWORD MaxKeyNameLen, KeyNameLen; + LPWSTR Buf = NULL; + + wprintf(L"Deleting log %s...", EventLogName); + + lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Services\\Eventlog", + 0, KEY_CREATE_SUB_KEY, + &hKey); + if (lRet != ERROR_SUCCESS) + goto Quit; + + lRet = RegOpenKeyExW(hKey, + EventLogName, + 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, + &hEventKey); + if (lRet != ERROR_SUCCESS) + goto Quit; + + lRet = RegQueryInfoKeyW(hEventKey, + NULL, NULL, NULL, NULL, + &MaxKeyNameLen, + NULL, NULL, NULL, NULL, NULL, NULL); + if (lRet != ERROR_SUCCESS) + goto Quit; + + MaxKeyNameLen++; + + Buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, MaxKeyNameLen * sizeof(WCHAR)); + if (!Buf) + goto Quit; + + KeyNameLen = MaxKeyNameLen; + while (RegEnumKeyExW(hEventKey, + 0, + Buf, + &KeyNameLen, + NULL, NULL, NULL, NULL) == ERROR_SUCCESS) + { + RegDeleteKeyW(hEventKey, Buf); + KeyNameLen = MaxKeyNameLen; + } + + RegFlushKey(hEventKey); + + HeapFree(GetProcessHeap(), 0, Buf); + + Success = TRUE; + +Quit: + if (Success) + { + RegCloseKey(hEventKey); + RegDeleteKeyW(hKey, EventLogName); + + wprintf(L"Success\n"); + } + else + { + if (hEventKey) + RegCloseKey(hEventKey); + + wprintf(L"Failure\n"); + } + + if (hKey) + RegCloseKey(hKey); + + return Success; +} + +VOID TestEventsGeneration(VOID) +{ + BOOL Success = FALSE; + LPCWSTR EvtLog = L"MyLog"; + LPCWSTR Sources[] = {L"Source1", L"Source2"}; + HANDLE hEventLog; + ULONG MaxSize = max(0x30 + 0x28 + 0x200, 0x010000); + + /* Create the test event log */ + if (!CreateEventLog(EvtLog, MaxSize, ARRAYSIZE(Sources), Sources)) + return; + + wprintf(L"Press any key to continue...\n"); + _getch(); + + /* To report events we can either use a handle got from OpenEventLog or from RegisterEventSource! */ + hEventLog = OpenEventLogW(NULL, EvtLog); + wprintf(L"OpenEventLogW(NULL, EvtLog = %s) ", EvtLog); + if (hEventLog) + { + LPCWSTR String = L"Event from OpenEventLog handle with EvtLog"; + + wprintf(L"succeeded\n"); + Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 1, 0, &String, NULL); + if (!Success) + wprintf(L" Failed to report event\n"); + } + else + { + wprintf(L"failed\n"); + } + CloseEventLog(hEventLog); + + /* This call should fail (where we use a source name for OpenEventLog) */ + hEventLog = OpenEventLogW(NULL, L"Source1"); + wprintf(L"OpenEventLogW(NULL, Source = %s) ", L"Source1"); + if (hEventLog) + { + LPCWSTR String = L"Event from OpenEventLog handle with Source"; + + wprintf(L"succeeded\n"); + Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 1, 0, &String, NULL); + if (!Success) + wprintf(L" Failed to report event\n"); + } + else + { + wprintf(L"failed\n"); + } + CloseEventLog(hEventLog); + + /* Now use RegisterEventSource */ + hEventLog = RegisterEventSourceW(NULL, EvtLog); + wprintf(L"RegisterEventSourceW(NULL, EvtLog = %s) ", EvtLog); + if (hEventLog) + { + LPCWSTR String = L"Event from RegisterEventSource handle with EvtLog"; + + wprintf(L"succeeded\n"); + Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 1, 0, &String, NULL); + if (!Success) + wprintf(L" Failed to report event\n"); + } + else + { + wprintf(L"failed\n"); + } + DeregisterEventSource(hEventLog); + + /* Now use RegisterEventSource */ + hEventLog = RegisterEventSourceW(NULL, L"Source1"); + wprintf(L"RegisterEventSourceW(NULL, Source = %s) ", L"Source1"); + if (hEventLog) + { + LPCWSTR String = L"Event from RegisterEventSource handle with Source"; + + wprintf(L"succeeded\n"); + Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 1, 0, &String, NULL); + if (!Success) + wprintf(L" Failed to report event\n"); + } + else + { + wprintf(L"failed\n"); + } + DeregisterEventSource(hEventLog); + + /* Now fill the log with one big event */ + hEventLog = OpenEventLogW(NULL, EvtLog); + wprintf(L"OpenEventLogW(NULL, EvtLog = %s) ", EvtLog); + if (hEventLog) + { + // LPWSTR String = L"Big event"; + PVOID Data; + + wprintf(L"succeeded\n"); + + // MaxSize -= (0x30 + 0x28 + 0x300 + 0x40); + MaxSize = 0xFC80 - sizeof(EVENTLOGRECORD); // With a StartOffset of 0x14, that should allow seeing the effect of splitting the EOF record in half... + Data = HeapAlloc(GetProcessHeap(), 0, MaxSize); + if (Data) + { + RtlFillMemory(Data, MaxSize, 0xCA); + Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 0 /* 1 */, MaxSize, NULL /* &String */, Data); + if (!Success) + wprintf(L" Failed to report event\n"); + + HeapFree(GetProcessHeap(), 0, Data); + } + } + else + { + wprintf(L"failed\n"); + } + CloseEventLog(hEventLog); + + wprintf(L"Press any key to continue...\n"); + _getch(); + + /* Delete the test event log */ + RemoveEventLog(EvtLog); +} + +/* + * This code was adapted from the MSDN article "Reporting Events" at: + * https://msdn.microsoft.com/en-us/library/windows/desktop/aa363680(v=vs.85).aspx + */ +VOID TestMyEventProvider(VOID) +{ + LONG lRet; + HKEY hKey = NULL, hSourceKey = NULL; + DWORD dwData; + // WCHAR DllPath[] = L"C:\\Users\\ReactOS\\Desktop\\EvtLogTest\\Debug\\" PROVIDER_NAME L".dll"; + WCHAR DllPath[] = L"C:\\" PROVIDER_NAME L".dll"; + + wprintf(L"Testing \"" PROVIDER_NAME L"\" in 'Application' log..."); + + lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application", + 0, KEY_CREATE_SUB_KEY, + &hKey); + if (lRet != ERROR_SUCCESS) + goto Quit; + + lRet = RegCreateKeyExW(hKey, + PROVIDER_NAME, + 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_CREATE_SUB_KEY | KEY_SET_VALUE, NULL, + &hSourceKey, NULL); + if (lRet != ERROR_SUCCESS) + goto Quit; + + dwData = 3; + RegSetValueExW(hSourceKey, L"CategoryCount", 0, REG_DWORD, + (LPBYTE)&dwData, sizeof(dwData)); + + dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; + RegSetValueExW(hSourceKey, L"TypesSupported", 0, REG_DWORD, + (LPBYTE)&dwData, sizeof(dwData)); + + RegSetValueExW(hSourceKey, L"CategoryMessageFile", 0, REG_SZ, + (LPBYTE)DllPath, sizeof(DllPath)); + + RegSetValueExW(hSourceKey, L"EventMessageFile", 0, REG_SZ, + (LPBYTE)DllPath, sizeof(DllPath)); + + RegSetValueExW(hSourceKey, L"ParameterMessageFile", 0, REG_SZ, + (LPBYTE)DllPath, sizeof(DllPath)); + + RegFlushKey(hSourceKey); + + { + CONST LPWSTR pBadCommand = L"The command that was not valid"; + CONST LPWSTR pFilename = L"c:\\folder\\file.ext"; + CONST LPWSTR pNumberOfRetries = L"3"; + CONST LPWSTR pSuccessfulRetries = L"0"; + CONST LPWSTR pQuarts = L"8"; + CONST LPWSTR pGallons = L"2"; + + HANDLE hEventLog = NULL; + LPWSTR pInsertStrings[2] = {NULL, NULL}; + DWORD dwEventDataSize = 0; + + // The source name (provider) must exist as a subkey of Application. + hEventLog = RegisterEventSourceW(NULL, PROVIDER_NAME); + if (NULL == hEventLog) + { + wprintf(L"RegisterEventSource failed with 0x%x.\n", GetLastError()); + goto cleanup; + } + + // This event includes user-defined data as part of the event. + // The event message does not use insert strings. + dwEventDataSize = ((DWORD)wcslen(pBadCommand) + 1) * sizeof(WCHAR); + if (!ReportEventW(hEventLog, EVENTLOG_ERROR_TYPE, UI_CATEGORY, MSG_INVALID_COMMAND, NULL, 0, dwEventDataSize, NULL, pBadCommand)) + { + wprintf(L"ReportEvent failed with 0x%x for event 0x%x.\n", GetLastError(), MSG_INVALID_COMMAND); + goto cleanup; + } + + // This event uses insert strings. + pInsertStrings[0] = pFilename; + if (!ReportEventW(hEventLog, EVENTLOG_ERROR_TYPE, DATABASE_CATEGORY, MSG_BAD_FILE_CONTENTS, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL)) + { + wprintf(L"ReportEvent failed with 0x%x for event 0x%x.\n", GetLastError(), MSG_BAD_FILE_CONTENTS); + goto cleanup; + } + + // This event uses insert strings. + pInsertStrings[0] = pNumberOfRetries; + pInsertStrings[1] = pSuccessfulRetries; + if (!ReportEventW(hEventLog, EVENTLOG_WARNING_TYPE, NETWORK_CATEGORY, MSG_RETRIES, NULL, 2, 0, (LPCWSTR*)pInsertStrings, NULL)) + { + wprintf(L"ReportEvent failed with 0x%x for event 0x%x.\n", GetLastError(), MSG_RETRIES); + goto cleanup; + } + + // This event uses insert strings. + pInsertStrings[0] = pQuarts; + pInsertStrings[1] = pGallons; + if (!ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, UI_CATEGORY, MSG_COMPUTE_CONVERSION, NULL, 2, 0, (LPCWSTR*)pInsertStrings, NULL)) + { + wprintf(L"ReportEvent failed with 0x%x for event 0x%x.\n", GetLastError(), MSG_COMPUTE_CONVERSION); + goto cleanup; + } + + wprintf(L"All events successfully reported.\n"); + +cleanup: + + if (hEventLog) + DeregisterEventSource(hEventLog); + + } + +Quit: + // RegDeleteKeyW(hKey, PROVIDER_NAME); + + if (hKey) + RegCloseKey(hKey); +} + +int wmain(int argc, WCHAR* argv[]) +{ + UINT Choice = 0; + + wprintf(L"\n" + L"EventLog API interactive tester for ReactOS\n" + L"===========================================\n" + L"\n"); + +ChoiceMenu: + do + { + wprintf(L"What do you want to do:\n" + L"1) Test events generation.\n" + L"2) Test customized event provider.\n" + L"\n" + L"0) Quit the program.\n" + L"(Enter the right number, or 0 to quit): "); + wscanf(L"%lu", &Choice); + wprintf(L"\n\n"); + } while ((Choice != 0) && (Choice != 1) && (Choice != 2)); + + switch (Choice) + { + case 0: + goto Quit; + break; + + case 1: + TestEventsGeneration(); + break; + + case 2: + TestMyEventProvider(); + break; + + default: + break; + } + wprintf(L"\n\n\n\n"); + goto ChoiceMenu; + +Quit: + wprintf(L"Press any key to quit...\n"); + _getch(); + return 0; +} diff --git a/rostests/win32/advapi32/eventlog/MyEventProvider.mc b/rostests/win32/advapi32/eventlog/MyEventProvider.mc new file mode 100644 index 00000000000..4ddb4e6a4d7 --- /dev/null +++ b/rostests/win32/advapi32/eventlog/MyEventProvider.mc @@ -0,0 +1,102 @@ +; // MyEventProvider.mc + +; // This is the header section. + + +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR + ) + + +FacilityNames=(System=0x0:FACILITY_SYSTEM + Runtime=0x2:FACILITY_RUNTIME + Stubs=0x3:FACILITY_STUBS + Io=0x4:FACILITY_IO_ERROR_CODE + ) + +LanguageNames=(English=0x409:MSG00409) + + +; // The following are the categories of events. + +MessageIdTypedef=WORD + +MessageId=0x1 +SymbolicName=NETWORK_CATEGORY +Language=English +Network Events +. + +MessageId=0x2 +SymbolicName=DATABASE_CATEGORY +Language=English +Database Events +. + +MessageId=0x3 +SymbolicName=UI_CATEGORY +Language=English +UI Events +. + + +; // The following are the message definitions. + +MessageIdTypedef=DWORD + +MessageId=0x100 +Severity=Error +Facility=Runtime +SymbolicName=MSG_INVALID_COMMAND +Language=English +The command is not valid. +. + + +MessageId=0x101 +Severity=Error +Facility=System +SymbolicName=MSG_BAD_FILE_CONTENTS +Language=English +File %1 contains content that is not valid. +. + +MessageId=0x102 +Severity=Warning +Facility=System +SymbolicName=MSG_RETRIES +Language=English +There have been %1 retries with %2 success! Disconnect from +the server and try again later. +. + +MessageId=0x103 +Severity=Informational +Facility=System +SymbolicName=MSG_COMPUTE_CONVERSION +Language=English +%1 %%4096 = %2 %%4097. +. + + +; // The following are the parameter strings */ + + +MessageId=0x1000 +Severity=Success +Facility=System +SymbolicName=QUARTS_UNITS +Language=English +quarts%0 +. + +MessageId=0x1001 +Severity=Success +Facility=System +SymbolicName=GALLONS_UNITS +Language=English +gallons%0 +. +