advapi32/tests: Fix a test failure with Wow64.
[wine] / dlls / advapi32 / tests / eventlog.c
1 /*
2  * Unit tests for Event Logging functions
3  *
4  * Copyright (c) 2009 Paul Vriens
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "winnt.h"
27 #include "winreg.h"
28 #include "sddl.h"
29
30 #include "wine/test.h"
31
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);
36
37 static void init_function_pointers(void)
38 {
39     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
40     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
41
42     pCreateWellKnownSid = (void*)GetProcAddress(hadvapi32, "CreateWellKnownSid");
43     pGetEventLogInformation = (void*)GetProcAddress(hadvapi32, "GetEventLogInformation");
44
45     pWow64DisableWow64FsRedirection = (void*)GetProcAddress(hkernel32, "Wow64DisableWow64FsRedirection");
46     pWow64RevertWow64FsRedirection = (void*)GetProcAddress(hkernel32, "Wow64RevertWow64FsRedirection");
47 }
48
49 static void create_backup(const char *filename)
50 {
51     HANDLE handle;
52
53     DeleteFileA(filename);
54     handle = OpenEventLogA(NULL, "Application");
55     BackupEventLogA(handle, filename);
56     CloseEventLog(handle);
57
58     todo_wine
59     ok(GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n");
60 }
61
62 static void test_open_close(void)
63 {
64     HANDLE handle;
65     BOOL ret;
66
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());
73
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());
78
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());
83
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());
90
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);
99     todo_wine
100     {
101     ok(!ret, "Expected failure\n");
102     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
103     }
104
105     /* Empty servername should be read as local server */
106     handle = OpenEventLogA("", "Application");
107     ok(handle != NULL, "Expected a handle\n");
108     CloseEventLog(handle);
109
110     handle = OpenEventLogA(NULL, "Application");
111     ok(handle != NULL, "Expected a handle\n");
112     CloseEventLog(handle);
113 }
114
115 static void test_info(void)
116 {
117     HANDLE handle;
118     BOOL ret;
119     DWORD needed;
120     EVENTLOG_FULL_INFORMATION efi;
121
122     if (!pGetEventLogInformation)
123     {
124         /* NT4 */
125         win_skip("GetEventLogInformation is not available\n");
126         return;
127     }
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());
132
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());
137
138     handle = OpenEventLogA(NULL, "Application");
139
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());
144
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());
149
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());
154
155     SetLastError(0xdeadbeef);
156     needed = 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");
163
164     /* Not that we care, but on success last error is set to ERROR_IO_PENDING */
165     efi.dwFull = 0xdeadbeef;
166     needed *= 2;
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);
171
172     CloseEventLog(handle);
173 }
174
175 static void test_count(void)
176 {
177     HANDLE handle;
178     BOOL ret;
179     DWORD count;
180     const char backup[] = "backup.evt";
181
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());
186
187     SetLastError(0xdeadbeef);
188     count = 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");
193
194     handle = OpenEventLogA(NULL, "Application");
195
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());
200
201     count = 0xdeadbeef;
202     ret = GetNumberOfEventLogRecords(handle, &count);
203     ok(ret, "Expected success\n");
204     ok(count != 0xdeadbeef, "Expected the number of records\n");
205
206     CloseEventLog(handle);
207
208     /* Make a backup eventlog to work with */
209     create_backup(backup);
210
211     handle = OpenBackupEventLogA(NULL, backup);
212     todo_wine
213     ok(handle != NULL, "Expected a handle\n");
214
215     /* Does GetNumberOfEventLogRecords work with backup eventlogs? */
216     count = 0xdeadbeef;
217     ret = GetNumberOfEventLogRecords(handle, &count);
218     todo_wine
219     {
220     ok(ret, "Expected success\n");
221     ok(count != 0xdeadbeef, "Expected the number of records\n");
222     }
223
224     CloseEventLog(handle);
225     DeleteFileA(backup);
226 }
227
228 static void test_oldest(void)
229 {
230     HANDLE handle;
231     BOOL ret;
232     DWORD oldest;
233     const char backup[] = "backup.evt";
234
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());
239
240     SetLastError(0xdeadbeef);
241     oldest = 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");
246
247     handle = OpenEventLogA(NULL, "Application");
248
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());
253
254     oldest = 0xdeadbeef;
255     ret = GetOldestEventLogRecord(handle, &oldest);
256     ok(ret, "Expected success\n");
257     ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n");
258
259     CloseEventLog(handle);
260
261     /* Make a backup eventlog to work with */
262     create_backup(backup);
263
264     handle = OpenBackupEventLogA(NULL, backup);
265     todo_wine
266     ok(handle != NULL, "Expected a handle\n");
267
268     /* Does GetOldestEventLogRecord work with backup eventlogs? */
269     oldest = 0xdeadbeef;
270     ret = GetOldestEventLogRecord(handle, &oldest);
271     todo_wine
272     {
273     ok(ret, "Expected success\n");
274     ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n");
275     }
276
277     CloseEventLog(handle);
278     DeleteFileA(backup);
279 }
280
281 static void test_backup(void)
282 {
283     HANDLE handle;
284     BOOL ret;
285     const char backup[] = "backup.evt";
286     const char backup2[] = "backup2.evt";
287
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());
292
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");
297
298     handle = OpenEventLogA(NULL, "Application");
299
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());
304
305     ret = BackupEventLogA(handle, backup);
306     ok(ret, "Expected success\n");
307     todo_wine
308     ok(GetFileAttributesA(backup) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n");
309
310     /* Try to overwrite */
311     SetLastError(0xdeadbeef);
312     ret = BackupEventLogA(handle, backup);
313     todo_wine
314     {
315     ok(!ret, "Expected failure\n");
316     ok(GetLastError() == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
317     }
318
319     CloseEventLog(handle);
320
321     /* Can we make a backup of a backup? */
322     handle = OpenBackupEventLogA(NULL, backup);
323     todo_wine
324     ok(handle != NULL, "Expected a handle\n");
325
326     ret = BackupEventLogA(handle, backup2);
327     todo_wine
328     {
329     ok(ret, "Expected success\n");
330     ok(GetFileAttributesA(backup2) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n");
331     }
332
333     CloseEventLog(handle);
334     DeleteFileA(backup);
335     DeleteFileA(backup2);
336 }
337
338 static void test_read(void)
339 {
340     HANDLE handle;
341     BOOL ret;
342     DWORD count, toread, read, needed;
343     void *buf;
344
345     SetLastError(0xdeadbeef);
346     ret = ReadEventLogA(NULL, 0, 0, NULL, 0, NULL, NULL);
347     ok(!ret, "Expected failure\n");
348     todo_wine
349     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
350
351     read = 0xdeadbeef;
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");
356     todo_wine
357     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
358
359     needed = 0xdeadbeef;
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");
364     todo_wine
365     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
366
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");
371     todo_wine
372     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
373
374     SetLastError(0xdeadbeef);
375     ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, NULL, 0, NULL, NULL);
376     ok(!ret, "Expected failure\n");
377     todo_wine
378     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
379
380     SetLastError(0xdeadbeef);
381     ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, NULL, 0, &read, &needed);
382     ok(!ret, "Expected failure\n");
383     todo_wine
384     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
385
386     buf = NULL;
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");
391     todo_wine
392     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
393
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");
399     todo_wine
400     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
401     HeapFree(GetProcessHeap(), 0, buf);
402
403     handle = OpenEventLogA(NULL, "Application");
404
405     /* Show that we need the proper dwFlags with a (for the rest) proper call */
406     buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD));
407
408     SetLastError(0xdeadbeef);
409     ret = ReadEventLogA(handle, 0, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
410     ok(!ret, "Expected failure\n");
411     todo_wine
412     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
413
414     SetLastError(0xdeadbeef);
415     ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
416     ok(!ret, "Expected failure\n");
417     todo_wine
418     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
419
420     SetLastError(0xdeadbeef);
421     ret = ReadEventLogA(handle, EVENTLOG_SEEK_READ, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
422     ok(!ret, "Expected failure\n");
423     todo_wine
424     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
425
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");
430     todo_wine
431     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
432
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");
437     todo_wine
438     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
439
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");
444     todo_wine
445     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
446
447     HeapFree(GetProcessHeap(), 0, buf);
448
449     /* First check if there are any records (in practice only on Wine: FIXME) */
450     count = 0;
451     GetNumberOfEventLogRecords(handle, &count);
452     if (!count)
453     {
454         skip("No records in the 'Application' log\n");
455         CloseEventLog(handle);
456         return;
457     }
458
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());
469
470     /* Read the first record */
471     toread = needed;
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");
477     ok(read == toread ||
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);
482
483     CloseEventLog(handle);
484 }
485
486 static void test_openbackup(void)
487 {
488     HANDLE handle, handle2, file;
489     DWORD written;
490     const char backup[] = "backup.evt";
491     const char text[] = "Just some text";
492
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());
497
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());
502
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());
507
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());
514
515     /* Make a backup eventlog to work with */
516     create_backup(backup);
517
518     /* FIXME: Wine stops here */
519     if (GetFileAttributesA(backup) == INVALID_FILE_ATTRIBUTES)
520     {
521         skip("We don't have a backup eventlog to work with\n");
522         return;
523     }
524
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());
531
532     /* Empty servername should be read as local server */
533     handle = OpenBackupEventLogA("", backup);
534     ok(handle != NULL, "Expected a handle\n");
535     CloseEventLog(handle);
536
537     handle = OpenBackupEventLogA(NULL, backup);
538     ok(handle != NULL, "Expected a handle\n");
539
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);
545
546     CloseEventLog(handle);
547     DeleteFileA(backup);
548
549     /* Is there any content checking done? */
550     file = CreateFileA(backup, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
551     CloseHandle(file);
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);
559     DeleteFileA(backup);
560
561     file = CreateFileA(backup, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
562     WriteFile(file, text, sizeof(text), &written, NULL);
563     CloseHandle(file);
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);
569     DeleteFileA(backup);
570 }
571
572 static void test_clear(void)
573 {
574     HANDLE handle;
575     BOOL ret;
576     const char backup[] = "backup.evt";
577     const char backup2[] = "backup2.evt";
578
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());
583
584     /* Make a backup eventlog to work with */
585     create_backup(backup);
586
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());
591
592     handle = OpenBackupEventLogA(NULL, backup);
593     todo_wine
594     ok(handle != NULL, "Expected a handle\n");
595
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.
602      */
603     ok(GetLastError() == ERROR_INVALID_HANDLE ||
604        GetLastError() == ERROR_ACCESS_DENIED, /* Vista+ */
605        "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
606
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");
613
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());
618
619     CloseEventLog(handle);
620     todo_wine
621     ok(DeleteFileA(backup), "Could not delete the backup file\n");
622 }
623
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" };
627
628 static BOOL create_new_eventlog(void)
629 {
630     HKEY key, eventkey;
631     BOOL bret = FALSE;
632     LONG lret;
633     int i;
634
635     /* First create our eventlog */
636     lret = RegOpenKeyA(HKEY_LOCAL_MACHINE, eventlogsvc, &key);
637      /* FIXME: Wine stops here */
638     if (lret != ERROR_SUCCESS)
639     {
640         skip("Could not open the EventLog service registry key\n");
641         return FALSE;
642     }
643     lret = RegCreateKeyA(key, eventlogname, &eventkey);
644     if (lret != ERROR_SUCCESS)
645     {
646         skip("Could not create the eventlog '%s' registry key\n", eventlogname);
647         goto cleanup;
648     }
649
650     /* Create some event sources, the registry value 'Sources' is updated automatically */
651     for (i = 0; i < sizeof(eventsources)/sizeof(eventsources[0]); i++)
652     {
653         HKEY srckey;
654
655         lret = RegCreateKeyA(eventkey, eventsources[i], &srckey);
656         if (lret != ERROR_SUCCESS)
657         {
658             skip("Could not create the eventsource '%s' registry key\n", eventsources[i]);
659             goto cleanup;
660         }
661         RegFlushKey(srckey);
662         RegCloseKey(srckey);
663     }
664
665     bret = TRUE;
666
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
669      * not updated.
670      */
671     RegFlushKey(eventkey);
672 cleanup:
673     RegCloseKey(eventkey);
674     RegCloseKey(key);
675
676     return bret;
677 }
678
679 static const char *one_string[] = { "First string" };
680 static const char *two_strings[] = { "First string", "Second string" };
681 static const struct
682 {
683     const char  *evt_src;
684     WORD         evt_type;
685     WORD         evt_cat;
686     DWORD        evt_id;
687     BOOL         evt_sid;
688     WORD         evt_numstrings;
689     const char **evt_strings;
690 } read_write [] =
691 {
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 }
702 };
703
704 static void test_readwrite(void)
705 {
706     HANDLE handle;
707     PSID user;
708     DWORD sidsize, count;
709     BOOL ret, sidavailable;
710     BOOL on_vista = FALSE; /* Used to indicate Vista or higher */
711     int i;
712     char localcomputer[MAX_COMPUTERNAME_LENGTH + 1];
713     DWORD len = sizeof(localcomputer);
714
715     if (pCreateWellKnownSid)
716     {
717         sidsize = SECURITY_MAX_SID_SIZE;
718         user = HeapAlloc(GetProcessHeap(), 0, sidsize);
719         SetLastError(0xdeadbeef);
720         pCreateWellKnownSid(WinInteractiveSid, NULL, user, &sidsize);
721         sidavailable = TRUE;
722     }
723     else
724     {
725         win_skip("Skipping some SID related tests\n");
726         sidavailable = FALSE;
727         user = NULL;
728     }
729
730     GetComputerNameA(localcomputer, &len);
731
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.
734      */
735     handle = OpenEventLogA(NULL, eventlogname);
736
737     SetLastError(0xdeadbeef);
738     ret = ReportEvent(handle, 0x20, 0, 0, NULL, 0, 0, NULL, NULL);
739     if (!ret && GetLastError() == ERROR_CRC)
740     {
741         win_skip("Win7 fails when using incorrect event types\n");
742         ret = ReportEvent(handle, 0, 0, 0, NULL, 0, 0, NULL, NULL);
743     }
744     ok(ret, "Expected success : %d\n", GetLastError());
745
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
749      * had one event.
750      */
751     ClearEventLogA(handle, NULL);
752     CloseEventLog(handle);
753
754     /* Write a bunch of events while using different event sources */
755     for (i = 0; i < sizeof(read_write)/sizeof(read_write[0]); i++)
756     {
757         DWORD oldest;
758         BOOL run_sidtests = read_write[i].evt_sid & sidavailable;
759
760         /* We don't need to use RegisterEventSource to report events */
761         if (i % 2)
762             handle = OpenEventLogA(NULL, read_write[i].evt_src);
763         else
764             handle = RegisterEventSourceA(NULL, read_write[i].evt_src);
765         ok(handle != NULL, "Expected a handle\n");
766
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);
771
772         count = 0xdeadbeef;
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);
776
777         oldest = 0xdeadbeef;
778         ret = GetOldestEventLogRecord(handle, &oldest);
779         ok(ret, "Expected success\n");
780         ok(oldest == 1 ||
781            oldest == 2, /* Vista+ */
782            "Expected oldest to be 1 or 2, got %d\n", oldest);
783         if (oldest == 2)
784             on_vista = TRUE;
785
786         if (i % 2)
787             ret = CloseEventLog(handle);
788         else
789             ret = DeregisterEventSource(handle);
790         ok(ret, "Expected success : %d\n", GetLastError());
791     }
792
793     handle = OpenEventLogA(NULL, eventlogname);
794     count = 0xdeadbeef;
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);
799
800     if (count == 0)
801     {
802         skip("No events were written to the eventlog\n");
803         return;
804     }
805
806     /* Report only once */
807     if (on_vista)
808         skip("There is no DWORD alignment for UserSid on Vista or higher\n");
809
810     /* Read all events from our created eventlog, one by one */
811     handle = OpenEventLogA(NULL, eventlogname);
812     i = 0;
813     for (;;)
814     {
815         void *buf;
816         DWORD read, needed;
817         EVENTLOGRECORD *record;
818         char *sourcename, *computername;
819         int k;
820         char *ptr;
821         BOOL run_sidtests = read_write[i].evt_sid & sidavailable;
822
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)
828         {
829             HeapFree(GetProcessHeap(), 0, buf);
830             break;
831         }
832         ok(!ret, "Expected failure\n");
833         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
834            "Expected ERROR_INVALID_PARAMETER, got %d\n",GetLastError());
835
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());
840
841         record = (EVENTLOGRECORD *)buf;
842
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);
858
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);
862
863         computername = (char *)((BYTE *)buf + sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1);
864         ok(!lstrcmpiA(computername, localcomputer), "Expected '%s', got '%s'\n",
865            localcomputer, computername);
866
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
870          * anyway.
871          */
872
873         if (!on_vista)
874         {
875             DWORD calculated_sidoffset = sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1 + lstrlenA(computername) + 1;
876
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");
880
881             ok((((UINT_PTR)buf + record->UserSidOffset) % sizeof(DWORD)) == 0, "Expected DWORD alignment\n");
882         }
883
884         if (run_sidtests)
885         {
886             ok(record->UserSidLength == sidsize, "Expected %d, got %d\n", sidsize, record->UserSidLength);
887         }
888         else
889         {
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);
892         }
893
894         ok(record->DataLength == 0, "Expected 0, got %d\n", record->DataLength);
895
896         ptr = (char *)((BYTE *)buf + record->StringOffset);
897         for (k = 0; k < record->NumStrings; k++)
898         {
899             ok(!lstrcmpA(ptr, two_strings[k]), "Expected '%s', got '%s'\n", two_strings[k], ptr);
900             ptr += lstrlenA(ptr) + 1;
901         }
902
903         ok(record->Length == *(DWORD *)((BYTE *)buf + record->Length - sizeof(DWORD)),
904            "Expected the closing DWORD to contain the length of the record\n");
905
906         HeapFree(GetProcessHeap(), 0, buf);
907         i++;
908     }
909     CloseEventLog(handle);
910
911     HeapFree(GetProcessHeap(), 0, user);
912
913     /* Test clearing a real eventlog */
914     handle = OpenEventLogA(NULL, eventlogname);
915
916     SetLastError(0xdeadbeef);
917     ret = ClearEventLogA(handle, NULL);
918     ok(ret, "Expected success\n");
919
920     count = 0xdeadbeef;
921     ret = GetNumberOfEventLogRecords(handle, &count);
922     ok(ret, "Expected success\n");
923     ok(count == 0, "Expected an empty eventlog, got %d records\n", count);
924
925     CloseEventLog(handle);
926 }
927
928 /* Before Vista:
929  *
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.
934  *
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.
938  *
939  * NT4 and higher:
940  *
941  * The eventlog file itself is also automatically created, even before we
942  * start writing events.
943  */
944 static char eventlogfile[MAX_PATH];
945 static void test_autocreation(void)
946 {
947     HKEY key, eventkey;
948     DWORD type, size;
949     LONG ret;
950     int i;
951     char *p;
952     char sources[sizeof(eventsources)];
953     char sysdir[MAX_PATH];
954     void *redir = 0;
955
956     RegOpenKeyA(HKEY_LOCAL_MACHINE, eventlogsvc, &key);
957     RegOpenKeyA(key, eventlogname, &eventkey);
958
959     size = sizeof(sources);
960     sources[0] = 0;
961     ret = RegQueryValueExA(eventkey, "Sources", NULL, &type, (LPBYTE)sources, &size);
962     if (ret == ERROR_SUCCESS)
963     {
964         char sources_verify[sizeof(eventsources)];
965
966         ok(type == REG_MULTI_SZ, "Expected a REG_MULTI_SZ, got %d\n", type);
967
968         /* Build the expected string */
969         memset(sources_verify, 0, sizeof(sources_verify));
970         p = sources_verify;
971         for (i = sizeof(eventsources)/sizeof(eventsources[0]); i > 0; i--)
972         {
973             lstrcpyA(p, eventsources[i - 1]);
974             p += (lstrlenA(eventsources[i - 1]) + 1);
975         }
976         lstrcpyA(p, eventlogname);
977
978         ok(!memcmp(sources, sources_verify, size), "Expected a correct 'Sources' value\n");
979     }
980
981     RegCloseKey(eventkey);
982     RegCloseKey(key);
983
984     /* The directory that holds the eventlog files could be redirected */
985     if (pWow64DisableWow64FsRedirection)
986         pWow64DisableWow64FsRedirection(&redir);
987
988     /* On Windows we also automatically get an eventlog file */
989     GetSystemDirectoryA(sysdir, sizeof(sysdir));
990
991     /* NT4 - W2K3 */
992     lstrcpyA(eventlogfile, sysdir);
993     lstrcatA(eventlogfile, "\\config\\");
994     lstrcatA(eventlogfile, eventlogname);
995     lstrcatA(eventlogfile, ".evt");
996
997     if (GetFileAttributesA(eventlogfile) == INVALID_FILE_ATTRIBUTES)
998     {
999         /* Vista+ */
1000         lstrcpyA(eventlogfile, sysdir);
1001         lstrcatA(eventlogfile, "\\winevt\\Logs\\");
1002         lstrcatA(eventlogfile, eventlogname);
1003         lstrcatA(eventlogfile, ".evtx");
1004     }
1005
1006     ok(GetFileAttributesA(eventlogfile) != INVALID_FILE_ATTRIBUTES,
1007        "Expected an eventlog file\n");
1008
1009     if (pWow64RevertWow64FsRedirection)
1010         pWow64RevertWow64FsRedirection(redir);
1011 }
1012
1013 static void cleanup_eventlog(void)
1014 {
1015     BOOL bret;
1016     LONG lret;
1017     HKEY key;
1018     int i;
1019     char winesvc[MAX_PATH];
1020
1021     /* Delete the registry tree */
1022     lstrcpyA(winesvc, eventlogsvc);
1023     lstrcatA(winesvc, "\\");
1024     lstrcatA(winesvc, eventlogname);
1025
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");
1030     RegCloseKey(key);
1031     lret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, winesvc);
1032     todo_wine
1033     ok(lret == ERROR_SUCCESS, "Could not delete the registry tree : %d\n", lret);
1034
1035     /* A handle to the eventlog is locked by services.exe. We can only
1036      * delete the eventlog file after reboot.
1037      */
1038     bret = MoveFileExA(eventlogfile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
1039     todo_wine
1040     ok(bret, "Expected MoveFileEx to succeed: %d\n", GetLastError());
1041 }
1042
1043 START_TEST(eventlog)
1044 {
1045     SetLastError(0xdeadbeef);
1046     CloseEventLog(NULL);
1047     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1048     {
1049         win_skip("Event log functions are not implemented\n");
1050         return;
1051     }
1052
1053     init_function_pointers();
1054
1055     /* Parameters only */
1056     test_open_close();
1057     test_info();
1058     test_count();
1059     test_oldest();
1060     test_backup();
1061     test_openbackup();
1062     test_read();
1063     test_clear();
1064
1065     /* Functional tests */
1066     if (create_new_eventlog())
1067     {
1068         test_readwrite();
1069         test_autocreation();
1070     }
1071     cleanup_eventlog();
1072 }