[SHIMENG] Fix logging when handling ordinal ordinal functions.
[reactos.git] / rostests / win32 / advapi32 / eventlog / EvtLogTest.c
1 /*
2 * PROJECT: ReactOS Tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: rostests/win32/advapi32/eventlog/EvtLogTest.c
5 * PURPOSE: Interactively test some EventLog service APIs and its behaviour.
6 * PROGRAMMER: Hermes Belusca-Maito
7 */
8
9 #include <stdio.h>
10 #include <conio.h>
11
12 #define WIN32_LEAN_AND_MEAN
13 #include <windows.h>
14
15 #include "MyEventProvider.h"
16
17 #define PROVIDER_NAME L"MyEventProvider"
18
19 BOOL CreateEventLog(LPCWSTR EventLogName,
20 UINT MaxSize,
21 UINT SourcesCount,
22 LPCWSTR EventLogSources[])
23 {
24 BOOL Success = FALSE;
25 LONG lRet;
26 HKEY hKey = NULL, hEventKey = NULL, hSrcKey = NULL;
27 UINT i;
28 // WCHAR evtFile[] = L"D:\\myfile.evtx";
29
30 wprintf(L"Creating log %s of MaxSize 0x%x with %d sources...", EventLogName, MaxSize, SourcesCount);
31
32 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
33 L"SYSTEM\\CurrentControlSet\\Services\\Eventlog",
34 0, KEY_CREATE_SUB_KEY,
35 &hKey);
36 if (lRet != ERROR_SUCCESS)
37 goto Quit;
38
39 /*
40 * At this precise moment, EventLog detects we create a new log registry key
41 * and therefore creates for us the log file in System32\config (<= Win2k3)
42 * or in System32\winevt\Logs (>= Vista).
43 */
44 lRet = RegCreateKeyExW(hKey,
45 EventLogName,
46 0, NULL, REG_OPTION_NON_VOLATILE,
47 KEY_CREATE_SUB_KEY | KEY_SET_VALUE, NULL,
48 &hEventKey, NULL);
49 if (lRet != ERROR_SUCCESS)
50 goto Quit;
51
52 RegSetValueExW(hEventKey, L"MaxSize", 0, REG_DWORD,
53 (LPBYTE)&MaxSize, sizeof(MaxSize));
54
55 i = 0;
56 RegSetValueExW(hEventKey, L"Retention", 0, REG_DWORD,
57 (LPBYTE)&i, sizeof(i));
58
59 #if 0
60 /*
61 * Set the flag that will allow EventLog to use an alternative log file name.
62 * If this flag is not set, EventLog will not care about the "File" value.
63 * When the flag is set, EventLog monitors for the "File" value, which can be
64 * changed at run-time, in which case a new event log file is created.
65 */
66 i = 1;
67 RegSetValueExW(hEventKey, L"Flags", 0, REG_DWORD,
68 (LPBYTE)&i, sizeof(i));
69
70 RegSetValueExW(hEventKey, L"File", 0, REG_EXPAND_SZ,
71 (LPBYTE)evtFile, sizeof(evtFile));
72 #endif
73
74 for (i = 0; i < SourcesCount; i++)
75 {
76 lRet = RegCreateKeyExW(hEventKey,
77 EventLogSources[i],
78 0, NULL, REG_OPTION_NON_VOLATILE,
79 KEY_QUERY_VALUE, NULL,
80 &hSrcKey, NULL);
81 RegFlushKey(hSrcKey);
82 RegCloseKey(hSrcKey);
83 }
84
85 RegFlushKey(hEventKey);
86
87 Success = TRUE;
88
89 Quit:
90 if (Success)
91 wprintf(L"Success\n");
92 else
93 wprintf(L"Failure\n");
94
95 if (hEventKey)
96 RegCloseKey(hEventKey);
97
98 if (hKey)
99 RegCloseKey(hKey);
100
101 return Success;
102 }
103
104 BOOL RemoveEventLog(LPCWSTR EventLogName)
105 {
106 BOOL Success = FALSE;
107 LONG lRet;
108 HKEY hKey, hEventKey;
109 DWORD MaxKeyNameLen, KeyNameLen;
110 LPWSTR Buf = NULL;
111
112 wprintf(L"Deleting log %s...", EventLogName);
113
114 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
115 L"SYSTEM\\CurrentControlSet\\Services\\Eventlog",
116 0, KEY_CREATE_SUB_KEY,
117 &hKey);
118 if (lRet != ERROR_SUCCESS)
119 goto Quit;
120
121 lRet = RegOpenKeyExW(hKey,
122 EventLogName,
123 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
124 &hEventKey);
125 if (lRet != ERROR_SUCCESS)
126 goto Quit;
127
128 lRet = RegQueryInfoKeyW(hEventKey,
129 NULL, NULL, NULL, NULL,
130 &MaxKeyNameLen,
131 NULL, NULL, NULL, NULL, NULL, NULL);
132 if (lRet != ERROR_SUCCESS)
133 goto Quit;
134
135 MaxKeyNameLen++;
136
137 Buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, MaxKeyNameLen * sizeof(WCHAR));
138 if (!Buf)
139 goto Quit;
140
141 KeyNameLen = MaxKeyNameLen;
142 while (RegEnumKeyExW(hEventKey,
143 0,
144 Buf,
145 &KeyNameLen,
146 NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
147 {
148 RegDeleteKeyW(hEventKey, Buf);
149 KeyNameLen = MaxKeyNameLen;
150 }
151
152 RegFlushKey(hEventKey);
153
154 HeapFree(GetProcessHeap(), 0, Buf);
155
156 Success = TRUE;
157
158 Quit:
159 if (Success)
160 {
161 RegCloseKey(hEventKey);
162 RegDeleteKeyW(hKey, EventLogName);
163
164 wprintf(L"Success\n");
165 }
166 else
167 {
168 if (hEventKey)
169 RegCloseKey(hEventKey);
170
171 wprintf(L"Failure\n");
172 }
173
174 if (hKey)
175 RegCloseKey(hKey);
176
177 return Success;
178 }
179
180 VOID TestEventsGeneration(VOID)
181 {
182 BOOL Success = FALSE;
183 LPCWSTR EvtLog = L"MyLog";
184 LPCWSTR Sources[] = {L"Source1", L"Source2"};
185 HANDLE hEventLog;
186 ULONG MaxSize = max(0x30 + 0x28 + 0x200, 0x010000);
187
188 /* Create the test event log */
189 if (!CreateEventLog(EvtLog, MaxSize, ARRAYSIZE(Sources), Sources))
190 return;
191
192 wprintf(L"Press any key to continue...\n");
193 _getch();
194
195 /* To report events we can either use a handle got from OpenEventLog or from RegisterEventSource! */
196 hEventLog = OpenEventLogW(NULL, EvtLog);
197 wprintf(L"OpenEventLogW(NULL, EvtLog = %s) ", EvtLog);
198 if (hEventLog)
199 {
200 LPCWSTR String = L"Event from OpenEventLog handle with EvtLog";
201
202 wprintf(L"succeeded\n");
203 Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 1, 0, &String, NULL);
204 if (!Success)
205 wprintf(L" Failed to report event\n");
206 }
207 else
208 {
209 wprintf(L"failed\n");
210 }
211 CloseEventLog(hEventLog);
212
213 /* This call should fail (where we use a source name for OpenEventLog) */
214 hEventLog = OpenEventLogW(NULL, L"Source1");
215 wprintf(L"OpenEventLogW(NULL, Source = %s) ", L"Source1");
216 if (hEventLog)
217 {
218 LPCWSTR String = L"Event from OpenEventLog handle with Source";
219
220 wprintf(L"succeeded\n");
221 Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 1, 0, &String, NULL);
222 if (!Success)
223 wprintf(L" Failed to report event\n");
224 }
225 else
226 {
227 wprintf(L"failed\n");
228 }
229 CloseEventLog(hEventLog);
230
231 /* Now use RegisterEventSource */
232 hEventLog = RegisterEventSourceW(NULL, EvtLog);
233 wprintf(L"RegisterEventSourceW(NULL, EvtLog = %s) ", EvtLog);
234 if (hEventLog)
235 {
236 LPCWSTR String = L"Event from RegisterEventSource handle with EvtLog";
237
238 wprintf(L"succeeded\n");
239 Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 1, 0, &String, NULL);
240 if (!Success)
241 wprintf(L" Failed to report event\n");
242 }
243 else
244 {
245 wprintf(L"failed\n");
246 }
247 DeregisterEventSource(hEventLog);
248
249 /* Now use RegisterEventSource */
250 hEventLog = RegisterEventSourceW(NULL, L"Source1");
251 wprintf(L"RegisterEventSourceW(NULL, Source = %s) ", L"Source1");
252 if (hEventLog)
253 {
254 LPCWSTR String = L"Event from RegisterEventSource handle with Source";
255
256 wprintf(L"succeeded\n");
257 Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 1, 0, &String, NULL);
258 if (!Success)
259 wprintf(L" Failed to report event\n");
260 }
261 else
262 {
263 wprintf(L"failed\n");
264 }
265 DeregisterEventSource(hEventLog);
266
267 /* Now fill the log with one big event */
268 hEventLog = OpenEventLogW(NULL, EvtLog);
269 wprintf(L"OpenEventLogW(NULL, EvtLog = %s) ", EvtLog);
270 if (hEventLog)
271 {
272 // LPWSTR String = L"Big event";
273 PVOID Data;
274
275 wprintf(L"succeeded\n");
276
277 // MaxSize -= (0x30 + 0x28 + 0x300 + 0x40);
278 MaxSize = 0xFC80 - sizeof(EVENTLOGRECORD); // With a StartOffset of 0x14, that should allow seeing the effect of splitting the EOF record in half...
279 Data = HeapAlloc(GetProcessHeap(), 0, MaxSize);
280 if (Data)
281 {
282 RtlFillMemory(Data, MaxSize, 0xCA);
283 Success = ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, 1, 1, NULL, 0 /* 1 */, MaxSize, NULL /* &String */, Data);
284 if (!Success)
285 wprintf(L" Failed to report event\n");
286
287 HeapFree(GetProcessHeap(), 0, Data);
288 }
289 }
290 else
291 {
292 wprintf(L"failed\n");
293 }
294 CloseEventLog(hEventLog);
295
296 wprintf(L"Press any key to continue...\n");
297 _getch();
298
299 /* Delete the test event log */
300 RemoveEventLog(EvtLog);
301 }
302
303 /*
304 * This code was adapted from the MSDN article "Reporting Events" at:
305 * https://msdn.microsoft.com/en-us/library/windows/desktop/aa363680(v=vs.85).aspx
306 */
307 VOID TestMyEventProvider(VOID)
308 {
309 LONG lRet;
310 HKEY hKey = NULL, hSourceKey = NULL;
311 DWORD dwData;
312 // WCHAR DllPath[] = L"C:\\Users\\ReactOS\\Desktop\\EvtLogTest\\Debug\\" PROVIDER_NAME L".dll";
313 WCHAR DllPath[] = L"C:\\" PROVIDER_NAME L".dll";
314
315 wprintf(L"Testing \"" PROVIDER_NAME L"\" in 'Application' log...");
316
317 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
318 L"SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application",
319 0, KEY_CREATE_SUB_KEY,
320 &hKey);
321 if (lRet != ERROR_SUCCESS)
322 goto Quit;
323
324 lRet = RegCreateKeyExW(hKey,
325 PROVIDER_NAME,
326 0, NULL, REG_OPTION_NON_VOLATILE,
327 KEY_CREATE_SUB_KEY | KEY_SET_VALUE, NULL,
328 &hSourceKey, NULL);
329 if (lRet != ERROR_SUCCESS)
330 goto Quit;
331
332 dwData = 3;
333 RegSetValueExW(hSourceKey, L"CategoryCount", 0, REG_DWORD,
334 (LPBYTE)&dwData, sizeof(dwData));
335
336 dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
337 RegSetValueExW(hSourceKey, L"TypesSupported", 0, REG_DWORD,
338 (LPBYTE)&dwData, sizeof(dwData));
339
340 RegSetValueExW(hSourceKey, L"CategoryMessageFile", 0, REG_SZ,
341 (LPBYTE)DllPath, sizeof(DllPath));
342
343 RegSetValueExW(hSourceKey, L"EventMessageFile", 0, REG_SZ,
344 (LPBYTE)DllPath, sizeof(DllPath));
345
346 RegSetValueExW(hSourceKey, L"ParameterMessageFile", 0, REG_SZ,
347 (LPBYTE)DllPath, sizeof(DllPath));
348
349 RegFlushKey(hSourceKey);
350
351 {
352 CONST LPWSTR pBadCommand = L"The command that was not valid";
353 CONST LPWSTR pFilename = L"c:\\folder\\file.ext";
354 CONST LPWSTR pNumberOfRetries = L"3";
355 CONST LPWSTR pSuccessfulRetries = L"0";
356 CONST LPWSTR pQuarts = L"8";
357 CONST LPWSTR pGallons = L"2";
358
359 HANDLE hEventLog = NULL;
360 LPWSTR pInsertStrings[2] = {NULL, NULL};
361 DWORD dwEventDataSize = 0;
362
363 // The source name (provider) must exist as a subkey of Application.
364 hEventLog = RegisterEventSourceW(NULL, PROVIDER_NAME);
365 if (NULL == hEventLog)
366 {
367 wprintf(L"RegisterEventSource failed with 0x%x.\n", GetLastError());
368 goto cleanup;
369 }
370
371 // This event includes user-defined data as part of the event.
372 // The event message does not use insert strings.
373 dwEventDataSize = ((DWORD)wcslen(pBadCommand) + 1) * sizeof(WCHAR);
374 if (!ReportEventW(hEventLog, EVENTLOG_ERROR_TYPE, UI_CATEGORY, MSG_INVALID_COMMAND, NULL, 0, dwEventDataSize, NULL, pBadCommand))
375 {
376 wprintf(L"ReportEvent failed with 0x%x for event 0x%x.\n", GetLastError(), MSG_INVALID_COMMAND);
377 goto cleanup;
378 }
379
380 // This event uses insert strings.
381 pInsertStrings[0] = pFilename;
382 if (!ReportEventW(hEventLog, EVENTLOG_ERROR_TYPE, DATABASE_CATEGORY, MSG_BAD_FILE_CONTENTS, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL))
383 {
384 wprintf(L"ReportEvent failed with 0x%x for event 0x%x.\n", GetLastError(), MSG_BAD_FILE_CONTENTS);
385 goto cleanup;
386 }
387
388 // This event uses insert strings.
389 pInsertStrings[0] = pNumberOfRetries;
390 pInsertStrings[1] = pSuccessfulRetries;
391 if (!ReportEventW(hEventLog, EVENTLOG_WARNING_TYPE, NETWORK_CATEGORY, MSG_RETRIES, NULL, 2, 0, (LPCWSTR*)pInsertStrings, NULL))
392 {
393 wprintf(L"ReportEvent failed with 0x%x for event 0x%x.\n", GetLastError(), MSG_RETRIES);
394 goto cleanup;
395 }
396
397 // This event uses insert strings.
398 pInsertStrings[0] = pQuarts;
399 pInsertStrings[1] = pGallons;
400 if (!ReportEventW(hEventLog, EVENTLOG_INFORMATION_TYPE, UI_CATEGORY, MSG_COMPUTE_CONVERSION, NULL, 2, 0, (LPCWSTR*)pInsertStrings, NULL))
401 {
402 wprintf(L"ReportEvent failed with 0x%x for event 0x%x.\n", GetLastError(), MSG_COMPUTE_CONVERSION);
403 goto cleanup;
404 }
405
406 wprintf(L"All events successfully reported.\n");
407
408 cleanup:
409
410 if (hEventLog)
411 DeregisterEventSource(hEventLog);
412
413 }
414
415 Quit:
416 // RegDeleteKeyW(hKey, PROVIDER_NAME);
417
418 if (hKey)
419 RegCloseKey(hKey);
420 }
421
422 int wmain(int argc, WCHAR* argv[])
423 {
424 UINT Choice = 0;
425
426 wprintf(L"\n"
427 L"EventLog API interactive tester for ReactOS\n"
428 L"===========================================\n"
429 L"\n");
430
431 ChoiceMenu:
432 do
433 {
434 wprintf(L"What do you want to do:\n"
435 L"1) Test events generation.\n"
436 L"2) Test customized event provider.\n"
437 L"\n"
438 L"0) Quit the program.\n"
439 L"(Enter the right number, or 0 to quit): ");
440 wscanf(L"%lu", &Choice);
441 wprintf(L"\n\n");
442 } while ((Choice != 0) && (Choice != 1) && (Choice != 2));
443
444 switch (Choice)
445 {
446 case 0:
447 goto Quit;
448 break;
449
450 case 1:
451 TestEventsGeneration();
452 break;
453
454 case 2:
455 TestMyEventProvider();
456 break;
457
458 default:
459 break;
460 }
461 wprintf(L"\n\n\n\n");
462 goto ChoiceMenu;
463
464 Quit:
465 wprintf(L"Press any key to quit...\n");
466 _getch();
467 return 0;
468 }