2 * Unit tests for Event Logging functions
4 * Copyright (c) 2009 Paul Vriens
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/test.h"
32 static BOOL (WINAPI *pCreateWellKnownSid)(WELL_KNOWN_SID_TYPE,PSID,PSID,DWORD*);
33 static BOOL (WINAPI *pGetEventLogInformation)(HANDLE,DWORD,LPVOID,DWORD,LPDWORD);
34 static BOOL (WINAPI *pWow64DisableWow64FsRedirection)(PVOID *);
35 static BOOL (WINAPI *pWow64RevertWow64FsRedirection)(PVOID);
37 static void init_function_pointers(void)
39 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
40 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
42 pCreateWellKnownSid = (void*)GetProcAddress(hadvapi32, "CreateWellKnownSid");
43 pGetEventLogInformation = (void*)GetProcAddress(hadvapi32, "GetEventLogInformation");
45 pWow64DisableWow64FsRedirection = (void*)GetProcAddress(hkernel32, "Wow64DisableWow64FsRedirection");
46 pWow64RevertWow64FsRedirection = (void*)GetProcAddress(hkernel32, "Wow64RevertWow64FsRedirection");
49 static void create_backup(const char *filename)
53 DeleteFileA(filename);
54 handle = OpenEventLogA(NULL, "Application");
55 BackupEventLogA(handle, filename);
56 CloseEventLog(handle);
59 ok(GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n");
62 static void test_open_close(void)
67 SetLastError(0xdeadbeef);
68 ret = CloseEventLog(NULL);
69 ok(!ret, "Expected failure\n");
70 ok(GetLastError() == ERROR_INVALID_HANDLE ||
71 GetLastError() == ERROR_NOACCESS, /* W2K */
72 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
74 SetLastError(0xdeadbeef);
75 handle = OpenEventLogA(NULL, NULL);
76 ok(handle == NULL, "Didn't expect a handle\n");
77 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
79 SetLastError(0xdeadbeef);
80 handle = OpenEventLogA("IDontExist", NULL);
81 ok(handle == NULL, "Didn't expect a handle\n");
82 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
84 SetLastError(0xdeadbeef);
85 handle = OpenEventLogA("IDontExist", "deadbeef");
86 ok(handle == NULL, "Didn't expect a handle\n");
87 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
88 GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista and Win7 */
89 "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError());
91 /* This one opens the Application log */
92 handle = OpenEventLogA(NULL, "deadbeef");
93 ok(handle != NULL, "Expected a handle\n");
94 ret = CloseEventLog(handle);
95 ok(ret, "Expected success\n");
96 /* Close a second time */
97 SetLastError(0xdeadbeef);
98 ret = CloseEventLog(handle);
101 ok(!ret, "Expected failure\n");
102 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
105 /* Empty servername should be read as local server */
106 handle = OpenEventLogA("", "Application");
107 ok(handle != NULL, "Expected a handle\n");
108 CloseEventLog(handle);
110 handle = OpenEventLogA(NULL, "Application");
111 ok(handle != NULL, "Expected a handle\n");
112 CloseEventLog(handle);
115 static void test_info(void)
120 EVENTLOG_FULL_INFORMATION efi;
122 if (!pGetEventLogInformation)
125 win_skip("GetEventLogInformation is not available\n");
128 SetLastError(0xdeadbeef);
129 ret = pGetEventLogInformation(NULL, 1, NULL, 0, NULL);
130 ok(!ret, "Expected failure\n");
131 ok(GetLastError() == ERROR_INVALID_LEVEL, "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
133 SetLastError(0xdeadbeef);
134 ret = pGetEventLogInformation(NULL, EVENTLOG_FULL_INFO, NULL, 0, NULL);
135 ok(!ret, "Expected failure\n");
136 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
138 handle = OpenEventLogA(NULL, "Application");
140 SetLastError(0xdeadbeef);
141 ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, NULL, 0, NULL);
142 ok(!ret, "Expected failure\n");
143 ok(GetLastError() == RPC_X_NULL_REF_POINTER, "Expected RPC_X_NULL_REF_POINTER, got %d\n", GetLastError());
145 SetLastError(0xdeadbeef);
146 ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, NULL, 0, &needed);
147 ok(!ret, "Expected failure\n");
148 ok(GetLastError() == RPC_X_NULL_REF_POINTER, "Expected RPC_X_NULL_REF_POINTER, got %d\n", GetLastError());
150 SetLastError(0xdeadbeef);
151 ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, (LPVOID)&efi, 0, NULL);
152 ok(!ret, "Expected failure\n");
153 ok(GetLastError() == RPC_X_NULL_REF_POINTER, "Expected RPC_X_NULL_REF_POINTER, got %d\n", GetLastError());
155 SetLastError(0xdeadbeef);
157 efi.dwFull = 0xdeadbeef;
158 ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, (LPVOID)&efi, 0, &needed);
159 ok(!ret, "Expected failure\n");
160 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
161 ok(needed == sizeof(EVENTLOG_FULL_INFORMATION), "Expected sizeof(EVENTLOG_FULL_INFORMATION), got %d\n", needed);
162 ok(efi.dwFull == 0xdeadbeef, "Expected no change to the dwFull member\n");
164 /* Not that we care, but on success last error is set to ERROR_IO_PENDING */
165 efi.dwFull = 0xdeadbeef;
167 ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, (LPVOID)&efi, needed, &needed);
168 ok(ret, "Expected success\n");
169 ok(needed == sizeof(EVENTLOG_FULL_INFORMATION), "Expected sizeof(EVENTLOG_FULL_INFORMATION), got %d\n", needed);
170 ok(efi.dwFull == 0 || efi.dwFull == 1, "Expected 0 (not full) or 1 (full), got %d\n", efi.dwFull);
172 CloseEventLog(handle);
175 static void test_count(void)
180 const char backup[] = "backup.evt";
182 SetLastError(0xdeadbeef);
183 ret = GetNumberOfEventLogRecords(NULL, NULL);
184 ok(!ret, "Expected failure\n");
185 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
187 SetLastError(0xdeadbeef);
189 ret = GetNumberOfEventLogRecords(NULL, &count);
190 ok(!ret, "Expected failure\n");
191 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
192 ok(count == 0xdeadbeef, "Expected count to stay unchanged\n");
194 handle = OpenEventLogA(NULL, "Application");
196 SetLastError(0xdeadbeef);
197 ret = GetNumberOfEventLogRecords(handle, NULL);
198 ok(!ret, "Expected failure\n");
199 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
202 ret = GetNumberOfEventLogRecords(handle, &count);
203 ok(ret, "Expected success\n");
204 ok(count != 0xdeadbeef, "Expected the number of records\n");
206 CloseEventLog(handle);
208 /* Make a backup eventlog to work with */
209 create_backup(backup);
211 handle = OpenBackupEventLogA(NULL, backup);
213 ok(handle != NULL, "Expected a handle\n");
215 /* Does GetNumberOfEventLogRecords work with backup eventlogs? */
217 ret = GetNumberOfEventLogRecords(handle, &count);
220 ok(ret, "Expected success\n");
221 ok(count != 0xdeadbeef, "Expected the number of records\n");
224 CloseEventLog(handle);
228 static void test_oldest(void)
233 const char backup[] = "backup.evt";
235 SetLastError(0xdeadbeef);
236 ret = GetOldestEventLogRecord(NULL, NULL);
237 ok(!ret, "Expected failure\n");
238 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
240 SetLastError(0xdeadbeef);
242 ret = GetOldestEventLogRecord(NULL, &oldest);
243 ok(!ret, "Expected failure\n");
244 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
245 ok(oldest == 0xdeadbeef, "Expected oldest to stay unchanged\n");
247 handle = OpenEventLogA(NULL, "Application");
249 SetLastError(0xdeadbeef);
250 ret = GetOldestEventLogRecord(handle, NULL);
251 ok(!ret, "Expected failure\n");
252 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
255 ret = GetOldestEventLogRecord(handle, &oldest);
256 ok(ret, "Expected success\n");
257 ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n");
259 CloseEventLog(handle);
261 /* Make a backup eventlog to work with */
262 create_backup(backup);
264 handle = OpenBackupEventLogA(NULL, backup);
266 ok(handle != NULL, "Expected a handle\n");
268 /* Does GetOldestEventLogRecord work with backup eventlogs? */
270 ret = GetOldestEventLogRecord(handle, &oldest);
273 ok(ret, "Expected success\n");
274 ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n");
277 CloseEventLog(handle);
281 static void test_backup(void)
285 const char backup[] = "backup.evt";
286 const char backup2[] = "backup2.evt";
288 SetLastError(0xdeadbeef);
289 ret = BackupEventLogA(NULL, NULL);
290 ok(!ret, "Expected failure\n");
291 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
293 SetLastError(0xdeadbeef);
294 ret = BackupEventLogA(NULL, backup);
295 ok(!ret, "Expected failure\n");
296 ok(GetFileAttributesA(backup) == INVALID_FILE_ATTRIBUTES, "Expected no backup file\n");
298 handle = OpenEventLogA(NULL, "Application");
300 SetLastError(0xdeadbeef);
301 ret = BackupEventLogA(handle, NULL);
302 ok(!ret, "Expected failure\n");
303 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
305 ret = BackupEventLogA(handle, backup);
306 ok(ret, "Expected success\n");
308 ok(GetFileAttributesA(backup) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n");
310 /* Try to overwrite */
311 SetLastError(0xdeadbeef);
312 ret = BackupEventLogA(handle, backup);
315 ok(!ret, "Expected failure\n");
316 ok(GetLastError() == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
319 CloseEventLog(handle);
321 /* Can we make a backup of a backup? */
322 handle = OpenBackupEventLogA(NULL, backup);
324 ok(handle != NULL, "Expected a handle\n");
326 ret = BackupEventLogA(handle, backup2);
329 ok(ret, "Expected success\n");
330 ok(GetFileAttributesA(backup2) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n");
333 CloseEventLog(handle);
335 DeleteFileA(backup2);
338 static void test_read(void)
342 DWORD count, toread, read, needed;
345 SetLastError(0xdeadbeef);
346 ret = ReadEventLogA(NULL, 0, 0, NULL, 0, NULL, NULL);
347 ok(!ret, "Expected failure\n");
349 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
352 SetLastError(0xdeadbeef);
353 ret = ReadEventLogA(NULL, 0, 0, NULL, 0, &read, NULL);
354 ok(!ret, "Expected failure\n");
355 ok(read == 0xdeadbeef, "Expected 'read' parameter to remain unchanged\n");
357 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
360 SetLastError(0xdeadbeef);
361 ret = ReadEventLogA(NULL, 0, 0, NULL, 0, NULL, &needed);
362 ok(!ret, "Expected failure\n");
363 ok(needed == 0xdeadbeef, "Expected 'needed' parameter to remain unchanged\n");
365 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
367 /* 'read' and 'needed' are only filled when the needed buffer size is passed back or when the call succeeds */
368 SetLastError(0xdeadbeef);
369 ret = ReadEventLogA(NULL, 0, 0, NULL, 0, &read, &needed);
370 ok(!ret, "Expected failure\n");
372 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
374 SetLastError(0xdeadbeef);
375 ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, NULL, 0, NULL, NULL);
376 ok(!ret, "Expected failure\n");
378 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
380 SetLastError(0xdeadbeef);
381 ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, NULL, 0, &read, &needed);
382 ok(!ret, "Expected failure\n");
384 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
387 SetLastError(0xdeadbeef);
388 ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
389 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
390 ok(!ret, "Expected failure\n");
392 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
394 buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD));
395 SetLastError(0xdeadbeef);
396 ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
397 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
398 ok(!ret, "Expected failure\n");
400 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
401 HeapFree(GetProcessHeap(), 0, buf);
403 handle = OpenEventLogA(NULL, "Application");
405 /* Show that we need the proper dwFlags with a (for the rest) proper call */
406 buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD));
408 SetLastError(0xdeadbeef);
409 ret = ReadEventLogA(handle, 0, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
410 ok(!ret, "Expected failure\n");
412 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
414 SetLastError(0xdeadbeef);
415 ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
416 ok(!ret, "Expected failure\n");
418 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
420 SetLastError(0xdeadbeef);
421 ret = ReadEventLogA(handle, EVENTLOG_SEEK_READ, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
422 ok(!ret, "Expected failure\n");
424 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
426 SetLastError(0xdeadbeef);
427 ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ,
428 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
429 ok(!ret, "Expected failure\n");
431 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
433 SetLastError(0xdeadbeef);
434 ret = ReadEventLogA(handle, EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ,
435 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
436 ok(!ret, "Expected failure\n");
438 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
440 SetLastError(0xdeadbeef);
441 ret = ReadEventLogA(handle, EVENTLOG_SEEK_READ | EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
442 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
443 ok(!ret, "Expected failure\n");
445 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
447 HeapFree(GetProcessHeap(), 0, buf);
449 /* First check if there are any records (in practice only on Wine: FIXME) */
451 GetNumberOfEventLogRecords(handle, &count);
454 skip("No records in the 'Application' log\n");
455 CloseEventLog(handle);
459 /* Get the buffer size for the first record */
460 buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD));
461 read = needed = 0xdeadbeef;
462 SetLastError(0xdeadbeef);
463 ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
464 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
465 ok(!ret, "Expected failure\n");
466 ok(read == 0, "Expected no bytes read\n");
467 ok(needed > sizeof(EVENTLOGRECORD), "Expected the needed buffersize to be bigger than sizeof(EVENTLOGRECORD)\n");
468 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
470 /* Read the first record */
472 buf = HeapReAlloc(GetProcessHeap(), 0, buf, toread);
473 read = needed = 0xdeadbeef;
474 SetLastError(0xdeadbeef);
475 ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, buf, toread, &read, &needed);
476 ok(ret, "Expected success\n");
478 broken(read < toread), /* NT4 wants a buffer size way bigger than just 1 record */
479 "Expected the requested size to be read\n");
480 ok(needed == 0, "Expected no extra bytes to be read\n");
481 HeapFree(GetProcessHeap(), 0, buf);
483 CloseEventLog(handle);
486 static void test_openbackup(void)
488 HANDLE handle, handle2, file;
490 const char backup[] = "backup.evt";
491 const char text[] = "Just some text";
493 SetLastError(0xdeadbeef);
494 handle = OpenBackupEventLogA(NULL, NULL);
495 ok(handle == NULL, "Didn't expect a handle\n");
496 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
498 SetLastError(0xdeadbeef);
499 handle = OpenBackupEventLogA(NULL, "idontexist.evt");
500 ok(handle == NULL, "Didn't expect a handle\n");
501 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
503 SetLastError(0xdeadbeef);
504 handle = OpenBackupEventLogA("IDontExist", NULL);
505 ok(handle == NULL, "Didn't expect a handle\n");
506 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
508 SetLastError(0xdeadbeef);
509 handle = OpenBackupEventLogA("IDontExist", "idontexist.evt");
510 ok(handle == NULL, "Didn't expect a handle\n");
511 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
512 GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista and Win7 */
513 "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError());
515 /* Make a backup eventlog to work with */
516 create_backup(backup);
518 /* FIXME: Wine stops here */
519 if (GetFileAttributesA(backup) == INVALID_FILE_ATTRIBUTES)
521 skip("We don't have a backup eventlog to work with\n");
525 SetLastError(0xdeadbeef);
526 handle = OpenBackupEventLogA("IDontExist", backup);
527 ok(handle == NULL, "Didn't expect a handle\n");
528 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
529 GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista and Win7 */
530 "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError());
532 /* Empty servername should be read as local server */
533 handle = OpenBackupEventLogA("", backup);
534 ok(handle != NULL, "Expected a handle\n");
535 CloseEventLog(handle);
537 handle = OpenBackupEventLogA(NULL, backup);
538 ok(handle != NULL, "Expected a handle\n");
540 /* Can we open that same backup eventlog more than once? */
541 handle2 = OpenBackupEventLogA(NULL, backup);
542 ok(handle2 != NULL, "Expected a handle\n");
543 ok(handle2 != handle, "Didn't expect the same handle\n");
544 CloseEventLog(handle2);
546 CloseEventLog(handle);
549 /* Is there any content checking done? */
550 file = CreateFileA(backup, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
552 SetLastError(0xdeadbeef);
553 handle = OpenBackupEventLogA(NULL, backup);
554 ok(handle == NULL, "Didn't expect a handle\n");
555 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY ||
556 GetLastError() == ERROR_EVENTLOG_FILE_CORRUPT, /* Vista and Win7 */
557 "Expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
558 CloseEventLog(handle);
561 file = CreateFileA(backup, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
562 WriteFile(file, text, sizeof(text), &written, NULL);
564 SetLastError(0xdeadbeef);
565 handle = OpenBackupEventLogA(NULL, backup);
566 ok(handle == NULL, "Didn't expect a handle\n");
567 ok(GetLastError() == ERROR_EVENTLOG_FILE_CORRUPT, "Expected ERROR_EVENTLOG_FILE_CORRUPT, got %d\n", GetLastError());
568 CloseEventLog(handle);
572 static void test_clear(void)
576 const char backup[] = "backup.evt";
577 const char backup2[] = "backup2.evt";
579 SetLastError(0xdeadbeef);
580 ret = ClearEventLogA(NULL, NULL);
581 ok(!ret, "Expected failure\n");
582 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
584 /* Make a backup eventlog to work with */
585 create_backup(backup);
587 SetLastError(0xdeadbeef);
588 ret = ClearEventLogA(NULL, backup);
589 ok(!ret, "Expected failure\n");
590 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
592 handle = OpenBackupEventLogA(NULL, backup);
594 ok(handle != NULL, "Expected a handle\n");
596 /* A real eventlog would fail with ERROR_ALREADY_EXISTS */
597 SetLastError(0xdeadbeef);
598 ret = ClearEventLogA(handle, backup);
599 ok(!ret, "Expected failure\n");
600 /* The eventlog service runs under an account that doesn't have the necessary
601 * permissions on the users home directory on a default Vista+ system.
603 ok(GetLastError() == ERROR_INVALID_HANDLE ||
604 GetLastError() == ERROR_ACCESS_DENIED, /* Vista+ */
605 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
607 /* Show that ClearEventLog only works for real eventlogs. */
608 SetLastError(0xdeadbeef);
609 ret = ClearEventLogA(handle, backup2);
610 ok(!ret, "Expected failure\n");
611 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
612 ok(GetFileAttributesA(backup2) == INVALID_FILE_ATTRIBUTES, "Expected no backup file\n");
614 SetLastError(0xdeadbeef);
615 ret = ClearEventLogA(handle, NULL);
616 ok(!ret, "Expected failure\n");
617 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
619 CloseEventLog(handle);
621 ok(DeleteFileA(backup), "Could not delete the backup file\n");
624 static const char eventlogsvc[] = "SYSTEM\\CurrentControlSet\\Services\\Eventlog";
625 static const char eventlogname[] = "Wine";
626 static const char eventsources[][11] = { "WineSrc", "WineSrc1", "WineSrc20", "WineSrc300" };
628 static BOOL create_new_eventlog(void)
635 /* First create our eventlog */
636 lret = RegOpenKeyA(HKEY_LOCAL_MACHINE, eventlogsvc, &key);
637 /* FIXME: Wine stops here */
638 if (lret != ERROR_SUCCESS)
640 skip("Could not open the EventLog service registry key\n");
643 lret = RegCreateKeyA(key, eventlogname, &eventkey);
644 if (lret != ERROR_SUCCESS)
646 skip("Could not create the eventlog '%s' registry key\n", eventlogname);
650 /* Create some event sources, the registry value 'Sources' is updated automatically */
651 for (i = 0; i < sizeof(eventsources)/sizeof(eventsources[0]); i++)
655 lret = RegCreateKeyA(eventkey, eventsources[i], &srckey);
656 if (lret != ERROR_SUCCESS)
658 skip("Could not create the eventsource '%s' registry key\n", eventsources[i]);
667 /* The flushing of the registry (here and above) gives us some assurance
668 * that we are not to quickly writing events as 'Sources' could still be
671 RegFlushKey(eventkey);
673 RegCloseKey(eventkey);
679 static const char *one_string[] = { "First string" };
680 static const char *two_strings[] = { "First string", "Second string" };
689 const char **evt_strings;
692 { eventlogname, EVENTLOG_INFORMATION_TYPE, 1, 1, FALSE, 1, one_string },
693 { eventsources[0], EVENTLOG_WARNING_TYPE, 1, 2, FALSE, 0, NULL },
694 { eventsources[1], EVENTLOG_AUDIT_FAILURE, 1, 3, FALSE, 2, two_strings },
695 { eventsources[2], EVENTLOG_ERROR_TYPE, 1, 4, FALSE, 0, NULL },
696 { eventsources[3], EVENTLOG_WARNING_TYPE, 1, 5, FALSE, 1, one_string },
697 { eventlogname, EVENTLOG_SUCCESS, 2, 6, TRUE, 2, two_strings },
698 { eventsources[0], EVENTLOG_AUDIT_FAILURE, 2, 7, TRUE, 0, NULL },
699 { eventsources[1], EVENTLOG_AUDIT_SUCCESS, 2, 8, TRUE, 2, two_strings },
700 { eventsources[2], EVENTLOG_WARNING_TYPE, 2, 9, TRUE, 0, NULL },
701 { eventsources[3], EVENTLOG_ERROR_TYPE, 2, 10, TRUE, 1, one_string }
704 static void test_readwrite(void)
708 DWORD sidsize, count;
709 BOOL ret, sidavailable;
710 BOOL on_vista = FALSE; /* Used to indicate Vista or higher */
712 char localcomputer[MAX_COMPUTERNAME_LENGTH + 1];
713 DWORD len = sizeof(localcomputer);
715 if (pCreateWellKnownSid)
717 sidsize = SECURITY_MAX_SID_SIZE;
718 user = HeapAlloc(GetProcessHeap(), 0, sidsize);
719 SetLastError(0xdeadbeef);
720 pCreateWellKnownSid(WinInteractiveSid, NULL, user, &sidsize);
725 win_skip("Skipping some SID related tests\n");
726 sidavailable = FALSE;
730 GetComputerNameA(localcomputer, &len);
732 /* Write an event with an incorrect event type. This will fail on Windows 7
733 * but succeed on all others, hence it's not part of the struct.
735 handle = OpenEventLogA(NULL, eventlogname);
737 SetLastError(0xdeadbeef);
738 ret = ReportEvent(handle, 0x20, 0, 0, NULL, 0, 0, NULL, NULL);
739 if (!ret && GetLastError() == ERROR_CRC)
741 win_skip("Win7 fails when using incorrect event types\n");
742 ret = ReportEvent(handle, 0, 0, 0, NULL, 0, 0, NULL, NULL);
744 ok(ret, "Expected success : %d\n", GetLastError());
746 /* This will clear the eventlog. The record numbering for new
747 * events however differs on Vista+. Before Vista the first
748 * event would be numbered 1, on Vista+ it's now 2 as we already
751 ClearEventLogA(handle, NULL);
752 CloseEventLog(handle);
754 /* Write a bunch of events while using different event sources */
755 for (i = 0; i < sizeof(read_write)/sizeof(read_write[0]); i++)
758 BOOL run_sidtests = read_write[i].evt_sid & sidavailable;
760 /* We don't need to use RegisterEventSource to report events */
762 handle = OpenEventLogA(NULL, read_write[i].evt_src);
764 handle = RegisterEventSourceA(NULL, read_write[i].evt_src);
765 ok(handle != NULL, "Expected a handle\n");
767 SetLastError(0xdeadbeef);
768 ret = ReportEvent(handle, read_write[i].evt_type, read_write[i].evt_cat,
769 read_write[i].evt_id, run_sidtests ? user : NULL,
770 read_write[i].evt_numstrings, 0, read_write[i].evt_strings, NULL);
773 ret = GetNumberOfEventLogRecords(handle, &count);
774 ok(ret, "Expected success\n");
775 ok(count == (i + 1), "Expected %d records, got %d\n", i + 1, count);
778 ret = GetOldestEventLogRecord(handle, &oldest);
779 ok(ret, "Expected success\n");
781 oldest == 2, /* Vista+ */
782 "Expected oldest to be 1 or 2, got %d\n", oldest);
787 ret = CloseEventLog(handle);
789 ret = DeregisterEventSource(handle);
790 ok(ret, "Expected success : %d\n", GetLastError());
793 handle = OpenEventLogA(NULL, eventlogname);
795 ret = GetNumberOfEventLogRecords(handle, &count);
796 ok(ret, "Expected success\n");
797 ok(count == i, "Expected %d records, got %d\n", i, count);
798 CloseEventLog(handle);
802 skip("No events were written to the eventlog\n");
806 /* Report only once */
808 skip("There is no DWORD alignment for UserSid on Vista or higher\n");
810 /* Read all events from our created eventlog, one by one */
811 handle = OpenEventLogA(NULL, eventlogname);
817 EVENTLOGRECORD *record;
818 char *sourcename, *computername;
821 BOOL run_sidtests = read_write[i].evt_sid & sidavailable;
823 buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD));
824 SetLastError(0xdeadbeef);
825 ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
826 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
827 if (!ret && GetLastError() == ERROR_HANDLE_EOF)
829 HeapFree(GetProcessHeap(), 0, buf);
832 ok(!ret, "Expected failure\n");
833 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
834 "Expected ERROR_INVALID_PARAMETER, got %d\n",GetLastError());
836 buf = HeapReAlloc(GetProcessHeap(), 0, buf, needed);
837 ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
838 0, buf, needed, &read, &needed);
839 ok(ret, "Expected success: %d\n", GetLastError());
841 record = (EVENTLOGRECORD *)buf;
843 ok(record->Length == read,
844 "Expected %d, got %d\n", read, record->Length);
845 ok(record->Reserved == 0x654c664c,
846 "Expected 0x654c664c, got %d\n", record->Reserved);
847 ok(record->RecordNumber == i + 1 ||
848 (on_vista && (record->RecordNumber == i + 2)),
849 "Expected %d or %d, got %d\n", i + 1, i + 2, record->RecordNumber);
850 ok(record->EventID == read_write[i].evt_id,
851 "Expected %d, got %d\n", read_write[i].evt_id, record->EventID);
852 ok(record->EventType == read_write[i].evt_type,
853 "Expected %d, got %d\n", read_write[i].evt_type, record->EventType);
854 ok(record->NumStrings == read_write[i].evt_numstrings,
855 "Expected %d, got %d\n", read_write[i].evt_numstrings, record->NumStrings);
856 ok(record->EventCategory == read_write[i].evt_cat,
857 "Expected %d, got %d\n", read_write[i].evt_cat, record->EventCategory);
859 sourcename = (char *)((BYTE *)buf + sizeof(EVENTLOGRECORD));
860 ok(!lstrcmpA(sourcename, read_write[i].evt_src), "Expected '%s', got '%s'\n",
861 read_write[i].evt_src, sourcename);
863 computername = (char *)((BYTE *)buf + sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1);
864 ok(!lstrcmpiA(computername, localcomputer), "Expected '%s', got '%s'\n",
865 localcomputer, computername);
867 /* Before Vista, UserSid was aligned on a DWORD boundary. Next to that if
868 * no padding was actually required a 0 DWORD was still used for padding. No
869 * application should be relying on the padding as we are working with offsets
875 DWORD calculated_sidoffset = sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1 + lstrlenA(computername) + 1;
877 /* We are already DWORD aligned, there should still be some padding */
878 if ((((UINT_PTR)buf + calculated_sidoffset) % sizeof(DWORD)) == 0)
879 ok(*(DWORD *)((BYTE *)buf + calculated_sidoffset) == 0, "Expected 0\n");
881 ok((((UINT_PTR)buf + record->UserSidOffset) % sizeof(DWORD)) == 0, "Expected DWORD alignment\n");
886 ok(record->UserSidLength == sidsize, "Expected %d, got %d\n", sidsize, record->UserSidLength);
890 ok(record->StringOffset == record->UserSidOffset, "Expected offsets to be the same\n");
891 ok(record->UserSidLength == 0, "Expected 0, got %d\n", record->UserSidLength);
894 ok(record->DataLength == 0, "Expected 0, got %d\n", record->DataLength);
896 ptr = (char *)((BYTE *)buf + record->StringOffset);
897 for (k = 0; k < record->NumStrings; k++)
899 ok(!lstrcmpA(ptr, two_strings[k]), "Expected '%s', got '%s'\n", two_strings[k], ptr);
900 ptr += lstrlenA(ptr) + 1;
903 ok(record->Length == *(DWORD *)((BYTE *)buf + record->Length - sizeof(DWORD)),
904 "Expected the closing DWORD to contain the length of the record\n");
906 HeapFree(GetProcessHeap(), 0, buf);
909 CloseEventLog(handle);
911 HeapFree(GetProcessHeap(), 0, user);
913 /* Test clearing a real eventlog */
914 handle = OpenEventLogA(NULL, eventlogname);
916 SetLastError(0xdeadbeef);
917 ret = ClearEventLogA(handle, NULL);
918 ok(ret, "Expected success\n");
921 ret = GetNumberOfEventLogRecords(handle, &count);
922 ok(ret, "Expected success\n");
923 ok(count == 0, "Expected an empty eventlog, got %d records\n", count);
925 CloseEventLog(handle);
930 * Creating an eventlog on Windows (via the registry) automatically leads
931 * to creation of a REG_MULTI_SZ named 'Sources'. This value lists all the
932 * potential event sources for this eventlog. 'Sources' is automatically
933 * updated when a new key (aka event source) is created.
935 * Although the updating of registry keys is almost instantaneously, we
936 * check it after some other tests to assure we are not querying the
937 * registry or file system to quickly.
941 * The eventlog file itself is also automatically created, even before we
942 * start writing events.
944 static char eventlogfile[MAX_PATH];
945 static void test_autocreation(void)
952 char sources[sizeof(eventsources)];
953 char sysdir[MAX_PATH];
956 RegOpenKeyA(HKEY_LOCAL_MACHINE, eventlogsvc, &key);
957 RegOpenKeyA(key, eventlogname, &eventkey);
959 size = sizeof(sources);
961 ret = RegQueryValueExA(eventkey, "Sources", NULL, &type, (LPBYTE)sources, &size);
962 if (ret == ERROR_SUCCESS)
964 char sources_verify[sizeof(eventsources)];
966 ok(type == REG_MULTI_SZ, "Expected a REG_MULTI_SZ, got %d\n", type);
968 /* Build the expected string */
969 memset(sources_verify, 0, sizeof(sources_verify));
971 for (i = sizeof(eventsources)/sizeof(eventsources[0]); i > 0; i--)
973 lstrcpyA(p, eventsources[i - 1]);
974 p += (lstrlenA(eventsources[i - 1]) + 1);
976 lstrcpyA(p, eventlogname);
978 ok(!memcmp(sources, sources_verify, size), "Expected a correct 'Sources' value\n");
981 RegCloseKey(eventkey);
984 /* The directory that holds the eventlog files could be redirected */
985 if (pWow64DisableWow64FsRedirection)
986 pWow64DisableWow64FsRedirection(&redir);
988 /* On Windows we also automatically get an eventlog file */
989 GetSystemDirectoryA(sysdir, sizeof(sysdir));
992 lstrcpyA(eventlogfile, sysdir);
993 lstrcatA(eventlogfile, "\\config\\");
994 lstrcatA(eventlogfile, eventlogname);
995 lstrcatA(eventlogfile, ".evt");
997 if (GetFileAttributesA(eventlogfile) == INVALID_FILE_ATTRIBUTES)
1000 lstrcpyA(eventlogfile, sysdir);
1001 lstrcatA(eventlogfile, "\\winevt\\Logs\\");
1002 lstrcatA(eventlogfile, eventlogname);
1003 lstrcatA(eventlogfile, ".evtx");
1006 ok(GetFileAttributesA(eventlogfile) != INVALID_FILE_ATTRIBUTES,
1007 "Expected an eventlog file\n");
1009 if (pWow64RevertWow64FsRedirection)
1010 pWow64RevertWow64FsRedirection(redir);
1013 static void cleanup_eventlog(void)
1019 char winesvc[MAX_PATH];
1021 /* Delete the registry tree */
1022 lstrcpyA(winesvc, eventlogsvc);
1023 lstrcatA(winesvc, "\\");
1024 lstrcatA(winesvc, eventlogname);
1026 RegOpenKeyA(HKEY_LOCAL_MACHINE, winesvc, &key);
1027 for (i = 0; i < sizeof(eventsources)/sizeof(eventsources[0]); i++)
1028 RegDeleteKeyA(key, eventsources[i]);
1029 RegDeleteValueA(key, "Sources");
1031 lret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, winesvc);
1033 ok(lret == ERROR_SUCCESS, "Could not delete the registry tree : %d\n", lret);
1035 /* A handle to the eventlog is locked by services.exe. We can only
1036 * delete the eventlog file after reboot.
1038 bret = MoveFileExA(eventlogfile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
1040 ok(bret, "Expected MoveFileEx to succeed: %d\n", GetLastError());
1043 START_TEST(eventlog)
1045 SetLastError(0xdeadbeef);
1046 CloseEventLog(NULL);
1047 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1049 win_skip("Event log functions are not implemented\n");
1053 init_function_pointers();
1055 /* Parameters only */
1065 /* Functional tests */
1066 if (create_new_eventlog())
1069 test_autocreation();