advapi32/tests: Add tests for reading and writing to a real eventlog.
[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
35 static void init_function_pointers(void)
36 {
37     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
38
39     pCreateWellKnownSid = (void*)GetProcAddress(hadvapi32, "CreateWellKnownSid");
40     pGetEventLogInformation = (void*)GetProcAddress(hadvapi32, "GetEventLogInformation");
41 }
42
43 static void create_backup(const char *filename)
44 {
45     HANDLE handle;
46
47     DeleteFileA(filename);
48     handle = OpenEventLogA(NULL, "Application");
49     BackupEventLogA(handle, filename);
50     CloseEventLog(handle);
51
52     todo_wine
53     ok(GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n");
54 }
55
56 static void test_open_close(void)
57 {
58     HANDLE handle;
59     BOOL ret;
60
61     SetLastError(0xdeadbeef);
62     ret = CloseEventLog(NULL);
63     ok(!ret, "Expected failure\n");
64     ok(GetLastError() == ERROR_INVALID_HANDLE ||
65        GetLastError() == ERROR_NOACCESS, /* W2K */
66        "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
67
68     SetLastError(0xdeadbeef);
69     handle = OpenEventLogA(NULL, NULL);
70     ok(handle == NULL, "Didn't expect a handle\n");
71     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
72
73     SetLastError(0xdeadbeef);
74     handle = OpenEventLogA("IDontExist", NULL);
75     ok(handle == NULL, "Didn't expect a handle\n");
76     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
77
78     SetLastError(0xdeadbeef);
79     handle = OpenEventLogA("IDontExist", "deadbeef");
80     ok(handle == NULL, "Didn't expect a handle\n");
81     ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
82        GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista and Win7 */
83        "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError());
84
85     /* This one opens the Application log */
86     handle = OpenEventLogA(NULL, "deadbeef");
87     ok(handle != NULL, "Expected a handle\n");
88     ret = CloseEventLog(handle);
89     ok(ret, "Expected success\n");
90     /* Close a second time */
91     SetLastError(0xdeadbeef);
92     ret = CloseEventLog(handle);
93     todo_wine
94     {
95     ok(!ret, "Expected failure\n");
96     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
97     }
98
99     /* Empty servername should be read as local server */
100     handle = OpenEventLogA("", "Application");
101     ok(handle != NULL, "Expected a handle\n");
102     CloseEventLog(handle);
103
104     handle = OpenEventLogA(NULL, "Application");
105     ok(handle != NULL, "Expected a handle\n");
106     CloseEventLog(handle);
107 }
108
109 static void test_info(void)
110 {
111     HANDLE handle;
112     BOOL ret;
113     DWORD needed;
114     EVENTLOG_FULL_INFORMATION efi;
115
116     if (!pGetEventLogInformation)
117     {
118         /* NT4 */
119         win_skip("GetEventLogInformation is not available\n");
120         return;
121     }
122     SetLastError(0xdeadbeef);
123     ret = pGetEventLogInformation(NULL, 1, NULL, 0, NULL);
124     ok(!ret, "Expected failure\n");
125     ok(GetLastError() == ERROR_INVALID_LEVEL, "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
126
127     SetLastError(0xdeadbeef);
128     ret = pGetEventLogInformation(NULL, EVENTLOG_FULL_INFO, NULL, 0, NULL);
129     ok(!ret, "Expected failure\n");
130     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
131
132     handle = OpenEventLogA(NULL, "Application");
133
134     SetLastError(0xdeadbeef);
135     ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, NULL, 0, NULL);
136     ok(!ret, "Expected failure\n");
137     ok(GetLastError() == RPC_X_NULL_REF_POINTER, "Expected RPC_X_NULL_REF_POINTER, got %d\n", GetLastError());
138
139     SetLastError(0xdeadbeef);
140     ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, NULL, 0, &needed);
141     ok(!ret, "Expected failure\n");
142     ok(GetLastError() == RPC_X_NULL_REF_POINTER, "Expected RPC_X_NULL_REF_POINTER, got %d\n", GetLastError());
143
144     SetLastError(0xdeadbeef);
145     ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, (LPVOID)&efi, 0, NULL);
146     ok(!ret, "Expected failure\n");
147     ok(GetLastError() == RPC_X_NULL_REF_POINTER, "Expected RPC_X_NULL_REF_POINTER, got %d\n", GetLastError());
148
149     SetLastError(0xdeadbeef);
150     needed = 0xdeadbeef;
151     efi.dwFull = 0xdeadbeef;
152     ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, (LPVOID)&efi, 0, &needed);
153     ok(!ret, "Expected failure\n");
154     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
155     ok(needed == sizeof(EVENTLOG_FULL_INFORMATION), "Expected sizeof(EVENTLOG_FULL_INFORMATION), got %d\n", needed);
156     ok(efi.dwFull == 0xdeadbeef, "Expected no change to the dwFull member\n");
157
158     /* Not that we care, but on success last error is set to ERROR_IO_PENDING */
159     efi.dwFull = 0xdeadbeef;
160     needed *= 2;
161     ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, (LPVOID)&efi, needed, &needed);
162     ok(ret, "Expected success\n");
163     ok(needed == sizeof(EVENTLOG_FULL_INFORMATION), "Expected sizeof(EVENTLOG_FULL_INFORMATION), got %d\n", needed);
164     ok(efi.dwFull == 0 || efi.dwFull == 1, "Expected 0 (not full) or 1 (full), got %d\n", efi.dwFull);
165
166     CloseEventLog(handle);
167 }
168
169 static void test_count(void)
170 {
171     HANDLE handle;
172     BOOL ret;
173     DWORD count;
174     const char backup[] = "backup.evt";
175
176     SetLastError(0xdeadbeef);
177     ret = GetNumberOfEventLogRecords(NULL, NULL);
178     ok(!ret, "Expected failure\n");
179     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
180
181     SetLastError(0xdeadbeef);
182     count = 0xdeadbeef;
183     ret = GetNumberOfEventLogRecords(NULL, &count);
184     ok(!ret, "Expected failure\n");
185     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
186     ok(count == 0xdeadbeef, "Expected count to stay unchanged\n");
187
188     handle = OpenEventLogA(NULL, "Application");
189
190     SetLastError(0xdeadbeef);
191     ret = GetNumberOfEventLogRecords(handle, NULL);
192     ok(!ret, "Expected failure\n");
193     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
194
195     count = 0xdeadbeef;
196     ret = GetNumberOfEventLogRecords(handle, &count);
197     ok(ret, "Expected success\n");
198     ok(count != 0xdeadbeef, "Expected the number of records\n");
199
200     CloseEventLog(handle);
201
202     /* Make a backup eventlog to work with */
203     create_backup(backup);
204
205     handle = OpenBackupEventLogA(NULL, backup);
206     todo_wine
207     ok(handle != NULL, "Expected a handle\n");
208
209     /* Does GetNumberOfEventLogRecords work with backup eventlogs? */
210     count = 0xdeadbeef;
211     ret = GetNumberOfEventLogRecords(handle, &count);
212     todo_wine
213     {
214     ok(ret, "Expected success\n");
215     ok(count != 0xdeadbeef, "Expected the number of records\n");
216     }
217
218     CloseEventLog(handle);
219     DeleteFileA(backup);
220 }
221
222 static void test_oldest(void)
223 {
224     HANDLE handle;
225     BOOL ret;
226     DWORD oldest;
227     const char backup[] = "backup.evt";
228
229     SetLastError(0xdeadbeef);
230     ret = GetOldestEventLogRecord(NULL, NULL);
231     ok(!ret, "Expected failure\n");
232     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
233
234     SetLastError(0xdeadbeef);
235     oldest = 0xdeadbeef;
236     ret = GetOldestEventLogRecord(NULL, &oldest);
237     ok(!ret, "Expected failure\n");
238     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
239     ok(oldest == 0xdeadbeef, "Expected oldest to stay unchanged\n");
240
241     handle = OpenEventLogA(NULL, "Application");
242
243     SetLastError(0xdeadbeef);
244     ret = GetOldestEventLogRecord(handle, NULL);
245     ok(!ret, "Expected failure\n");
246     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
247
248     oldest = 0xdeadbeef;
249     ret = GetOldestEventLogRecord(handle, &oldest);
250     ok(ret, "Expected success\n");
251     ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n");
252
253     CloseEventLog(handle);
254
255     /* Make a backup eventlog to work with */
256     create_backup(backup);
257
258     handle = OpenBackupEventLogA(NULL, backup);
259     todo_wine
260     ok(handle != NULL, "Expected a handle\n");
261
262     /* Does GetOldestEventLogRecord work with backup eventlogs? */
263     oldest = 0xdeadbeef;
264     ret = GetOldestEventLogRecord(handle, &oldest);
265     todo_wine
266     {
267     ok(ret, "Expected success\n");
268     ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n");
269     }
270
271     CloseEventLog(handle);
272     DeleteFileA(backup);
273 }
274
275 static void test_backup(void)
276 {
277     HANDLE handle;
278     BOOL ret;
279     const char backup[] = "backup.evt";
280     const char backup2[] = "backup2.evt";
281
282     SetLastError(0xdeadbeef);
283     ret = BackupEventLogA(NULL, NULL);
284     ok(!ret, "Expected failure\n");
285     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
286
287     SetLastError(0xdeadbeef);
288     ret = BackupEventLogA(NULL, backup);
289     ok(!ret, "Expected failure\n");
290     ok(GetFileAttributesA(backup) == INVALID_FILE_ATTRIBUTES, "Expected no backup file\n");
291
292     handle = OpenEventLogA(NULL, "Application");
293
294     SetLastError(0xdeadbeef);
295     ret = BackupEventLogA(handle, NULL);
296     ok(!ret, "Expected failure\n");
297     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
298
299     ret = BackupEventLogA(handle, backup);
300     ok(ret, "Expected success\n");
301     todo_wine
302     ok(GetFileAttributesA(backup) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n");
303
304     /* Try to overwrite */
305     SetLastError(0xdeadbeef);
306     ret = BackupEventLogA(handle, backup);
307     todo_wine
308     {
309     ok(!ret, "Expected failure\n");
310     ok(GetLastError() == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError());
311     }
312
313     CloseEventLog(handle);
314
315     /* Can we make a backup of a backup? */
316     handle = OpenBackupEventLogA(NULL, backup);
317     todo_wine
318     ok(handle != NULL, "Expected a handle\n");
319
320     ret = BackupEventLogA(handle, backup2);
321     todo_wine
322     {
323     ok(ret, "Expected success\n");
324     ok(GetFileAttributesA(backup2) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n");
325     }
326
327     CloseEventLog(handle);
328     DeleteFileA(backup);
329     DeleteFileA(backup2);
330 }
331
332 static void test_read(void)
333 {
334     HANDLE handle;
335     BOOL ret;
336     DWORD count, toread, read, needed;
337     void *buf;
338
339     SetLastError(0xdeadbeef);
340     ret = ReadEventLogA(NULL, 0, 0, NULL, 0, NULL, NULL);
341     ok(!ret, "Expected failure\n");
342     todo_wine
343     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
344
345     read = 0xdeadbeef;
346     SetLastError(0xdeadbeef);
347     ret = ReadEventLogA(NULL, 0, 0, NULL, 0, &read, NULL);
348     ok(!ret, "Expected failure\n");
349     ok(read == 0xdeadbeef, "Expected 'read' parameter to remain unchanged\n");
350     todo_wine
351     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
352
353     needed = 0xdeadbeef;
354     SetLastError(0xdeadbeef);
355     ret = ReadEventLogA(NULL, 0, 0, NULL, 0, NULL, &needed);
356     ok(!ret, "Expected failure\n");
357     ok(needed == 0xdeadbeef, "Expected 'needed' parameter to remain unchanged\n");
358     todo_wine
359     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
360
361     /* 'read' and 'needed' are only filled when the needed buffer size is passed back or when the call succeeds */
362     SetLastError(0xdeadbeef);
363     ret = ReadEventLogA(NULL, 0, 0, NULL, 0, &read, &needed);
364     ok(!ret, "Expected failure\n");
365     todo_wine
366     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
367
368     SetLastError(0xdeadbeef);
369     ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, NULL, 0, NULL, NULL);
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, &read, &needed);
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     buf = NULL;
381     SetLastError(0xdeadbeef);
382     ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
383                         0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
384     ok(!ret, "Expected failure\n");
385     todo_wine
386     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
387
388     buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD));
389     SetLastError(0xdeadbeef);
390     ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
391                         0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
392     ok(!ret, "Expected failure\n");
393     todo_wine
394     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
395     HeapFree(GetProcessHeap(), 0, buf);
396
397     handle = OpenEventLogA(NULL, "Application");
398
399     /* Show that we need the proper dwFlags with a (for the rest) proper call */
400     buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD));
401
402     SetLastError(0xdeadbeef);
403     ret = ReadEventLogA(handle, 0, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
404     ok(!ret, "Expected failure\n");
405     todo_wine
406     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
407
408     SetLastError(0xdeadbeef);
409     ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ, 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_SEEK_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_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ,
422                         0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
423     ok(!ret, "Expected failure\n");
424     todo_wine
425     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
426
427     SetLastError(0xdeadbeef);
428     ret = ReadEventLogA(handle, EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ,
429                         0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
430     ok(!ret, "Expected failure\n");
431     todo_wine
432     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
433
434     SetLastError(0xdeadbeef);
435     ret = ReadEventLogA(handle, EVENTLOG_SEEK_READ | EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
436                         0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
437     ok(!ret, "Expected failure\n");
438     todo_wine
439     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
440
441     HeapFree(GetProcessHeap(), 0, buf);
442
443     /* First check if there are any records (in practice only on Wine: FIXME) */
444     count = 0;
445     GetNumberOfEventLogRecords(handle, &count);
446     if (!count)
447     {
448         skip("No records in the 'Application' log\n");
449         CloseEventLog(handle);
450         return;
451     }
452
453     /* Get the buffer size for the first record */
454     buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD));
455     read = needed = 0xdeadbeef;
456     SetLastError(0xdeadbeef);
457     ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
458                         0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
459     ok(!ret, "Expected failure\n");
460     ok(read == 0, "Expected no bytes read\n");
461     ok(needed > sizeof(EVENTLOGRECORD), "Expected the needed buffersize to be bigger than sizeof(EVENTLOGRECORD)\n");
462     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
463
464     /* Read the first record */
465     toread = needed;
466     buf = HeapReAlloc(GetProcessHeap(), 0, buf, toread);
467     read = needed = 0xdeadbeef;
468     SetLastError(0xdeadbeef);
469     ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, buf, toread, &read, &needed);
470     ok(ret, "Expected success\n");
471     ok(read == toread ||
472        broken(read < toread), /* NT4 wants a buffer size way bigger than just 1 record */
473        "Expected the requested size to be read\n");
474     ok(needed == 0, "Expected no extra bytes to be read\n");
475     HeapFree(GetProcessHeap(), 0, buf);
476
477     CloseEventLog(handle);
478 }
479
480 static void test_openbackup(void)
481 {
482     HANDLE handle, handle2, file;
483     DWORD written;
484     const char backup[] = "backup.evt";
485     const char text[] = "Just some text";
486
487     SetLastError(0xdeadbeef);
488     handle = OpenBackupEventLogA(NULL, NULL);
489     ok(handle == NULL, "Didn't expect a handle\n");
490     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
491
492     SetLastError(0xdeadbeef);
493     handle = OpenBackupEventLogA(NULL, "idontexist.evt");
494     ok(handle == NULL, "Didn't expect a handle\n");
495     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
496
497     SetLastError(0xdeadbeef);
498     handle = OpenBackupEventLogA("IDontExist", NULL);
499     ok(handle == NULL, "Didn't expect a handle\n");
500     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
501
502     SetLastError(0xdeadbeef);
503     handle = OpenBackupEventLogA("IDontExist", "idontexist.evt");
504     ok(handle == NULL, "Didn't expect a handle\n");
505     ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
506        GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista and Win7 */
507        "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError());
508
509     /* Make a backup eventlog to work with */
510     create_backup(backup);
511
512     /* FIXME: Wine stops here */
513     if (GetFileAttributesA(backup) == INVALID_FILE_ATTRIBUTES)
514     {
515         skip("We don't have a backup eventlog to work with\n");
516         return;
517     }
518
519     SetLastError(0xdeadbeef);
520     handle = OpenBackupEventLogA("IDontExist", backup);
521     ok(handle == NULL, "Didn't expect a handle\n");
522     ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
523        GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista and Win7 */
524        "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError());
525
526     /* Empty servername should be read as local server */
527     handle = OpenBackupEventLogA("", backup);
528     ok(handle != NULL, "Expected a handle\n");
529     CloseEventLog(handle);
530
531     handle = OpenBackupEventLogA(NULL, backup);
532     ok(handle != NULL, "Expected a handle\n");
533
534     /* Can we open that same backup eventlog more than once? */
535     handle2 = OpenBackupEventLogA(NULL, backup);
536     ok(handle2 != NULL, "Expected a handle\n");
537     ok(handle2 != handle, "Didn't expect the same handle\n");
538     CloseEventLog(handle2);
539
540     CloseEventLog(handle);
541     DeleteFileA(backup);
542
543     /* Is there any content checking done? */
544     file = CreateFileA(backup, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
545     CloseHandle(file);
546     SetLastError(0xdeadbeef);
547     handle = OpenBackupEventLogA(NULL, backup);
548     ok(handle == NULL, "Didn't expect a handle\n");
549     ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY ||
550        GetLastError() == ERROR_EVENTLOG_FILE_CORRUPT, /* Vista and Win7 */
551        "Expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
552     CloseEventLog(handle);
553     DeleteFileA(backup);
554
555     file = CreateFileA(backup, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
556     WriteFile(file, text, sizeof(text), &written, NULL);
557     CloseHandle(file);
558     SetLastError(0xdeadbeef);
559     handle = OpenBackupEventLogA(NULL, backup);
560     ok(handle == NULL, "Didn't expect a handle\n");
561     ok(GetLastError() == ERROR_EVENTLOG_FILE_CORRUPT, "Expected ERROR_EVENTLOG_FILE_CORRUPT, got %d\n", GetLastError());
562     CloseEventLog(handle);
563     DeleteFileA(backup);
564 }
565
566 static void test_clear(void)
567 {
568     HANDLE handle;
569     BOOL ret;
570     const char backup[] = "backup.evt";
571     const char backup2[] = "backup2.evt";
572
573     SetLastError(0xdeadbeef);
574     ret = ClearEventLogA(NULL, NULL);
575     ok(!ret, "Expected failure\n");
576     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
577
578     /* Make a backup eventlog to work with */
579     create_backup(backup);
580
581     SetLastError(0xdeadbeef);
582     ret = ClearEventLogA(NULL, backup);
583     ok(!ret, "Expected failure\n");
584     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
585
586     handle = OpenBackupEventLogA(NULL, backup);
587     todo_wine
588     ok(handle != NULL, "Expected a handle\n");
589
590     /* A real eventlog would fail with ERROR_ALREADY_EXISTS */
591     SetLastError(0xdeadbeef);
592     ret = ClearEventLogA(handle, backup);
593     ok(!ret, "Expected failure\n");
594     /* The eventlog service runs under an account that doesn't have the necessary
595      * permissions on the users home directory on a default Vista+ system.
596      */
597     ok(GetLastError() == ERROR_INVALID_HANDLE ||
598        GetLastError() == ERROR_ACCESS_DENIED, /* Vista+ */
599        "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
600
601     /* Show that ClearEventLog only works for real eventlogs. */
602     SetLastError(0xdeadbeef);
603     ret = ClearEventLogA(handle, backup2);
604     ok(!ret, "Expected failure\n");
605     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
606     ok(GetFileAttributesA(backup2) == INVALID_FILE_ATTRIBUTES, "Expected no backup file\n");
607
608     SetLastError(0xdeadbeef);
609     ret = ClearEventLogA(handle, NULL);
610     ok(!ret, "Expected failure\n");
611     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
612
613     CloseEventLog(handle);
614     todo_wine
615     ok(DeleteFileA(backup), "Could not delete the backup file\n");
616 }
617
618 static const char eventlogsvc[] = "SYSTEM\\CurrentControlSet\\Services\\Eventlog";
619 static const char eventlogname[] = "Wine";
620 static const char eventsources[][11] = { "WineSrc", "WineSrc1", "WineSrc20", "WineSrc300" };
621
622 static BOOL create_new_eventlog(void)
623 {
624     HKEY key, eventkey;
625     BOOL bret = FALSE;
626     LONG lret;
627     int i;
628
629     /* First create our eventlog */
630     lret = RegOpenKeyA(HKEY_LOCAL_MACHINE, eventlogsvc, &key);
631      /* FIXME: Wine stops here */
632     if (lret != ERROR_SUCCESS)
633     {
634         skip("Could not open the EventLog service registry key\n");
635         return FALSE;
636     }
637     lret = RegCreateKeyA(key, eventlogname, &eventkey);
638     if (lret != ERROR_SUCCESS)
639     {
640         skip("Could not create the eventlog '%s' registry key\n", eventlogname);
641         goto cleanup;
642     }
643
644     /* Create some event sources, the registry value 'Sources' is updated automatically */
645     for (i = 0; i < sizeof(eventsources)/sizeof(eventsources[0]); i++)
646     {
647         HKEY srckey;
648
649         lret = RegCreateKeyA(eventkey, eventsources[i], &srckey);
650         if (lret != ERROR_SUCCESS)
651         {
652             skip("Could not create the eventsource '%s' registry key\n", eventsources[i]);
653             goto cleanup;
654         }
655         RegFlushKey(srckey);
656         RegCloseKey(srckey);
657     }
658
659     bret = TRUE;
660
661     /* The flushing of the registry (here and above) gives us some assurance
662      * that we are not to quickly writing events as 'Sources' could still be
663      * not updated.
664      */
665     RegFlushKey(eventkey);
666 cleanup:
667     RegCloseKey(eventkey);
668     RegCloseKey(key);
669
670     return bret;
671 }
672
673 static const char *one_string[] = { "First string" };
674 static const char *two_strings[] = { "First string", "Second string" };
675 static const struct
676 {
677     const char  *evt_src;
678     WORD         evt_type;
679     WORD         evt_cat;
680     DWORD        evt_id;
681     BOOL         evt_sid;
682     WORD         evt_numstrings;
683     const char **evt_strings;
684 } read_write [] =
685 {
686     { eventlogname,    EVENTLOG_INFORMATION_TYPE, 1, 1,  FALSE, 1, one_string },
687     { eventsources[0], EVENTLOG_WARNING_TYPE,     1, 2,  FALSE, 0, NULL },
688     { eventsources[1], EVENTLOG_AUDIT_FAILURE,    1, 3,  FALSE, 2, two_strings },
689     { eventsources[2], EVENTLOG_ERROR_TYPE,       1, 4,  FALSE, 0, NULL },
690     { eventsources[3], EVENTLOG_WARNING_TYPE,     1, 5,  FALSE, 1, one_string },
691     { eventlogname,    EVENTLOG_SUCCESS,          2, 6,  TRUE,  2, two_strings },
692     { eventsources[0], EVENTLOG_AUDIT_FAILURE,    2, 7,  TRUE,  0, NULL },
693     { eventsources[1], EVENTLOG_AUDIT_SUCCESS,    2, 8,  TRUE,  2, two_strings },
694     { eventsources[2], EVENTLOG_WARNING_TYPE,     2, 9,  TRUE,  0, NULL },
695     { eventsources[3], EVENTLOG_ERROR_TYPE,       2, 10, TRUE,  1, one_string }
696 };
697
698 static void test_readwrite(void)
699 {
700     HANDLE handle;
701     PSID user;
702     DWORD sidsize, count;
703     BOOL ret, sidavailable;
704     BOOL on_vista = FALSE; /* Used to indicate Vista or higher */
705     int i;
706     char localcomputer[MAX_COMPUTERNAME_LENGTH + 1];
707     DWORD len = sizeof(localcomputer);
708
709     if (pCreateWellKnownSid)
710     {
711         sidsize = SECURITY_MAX_SID_SIZE;
712         user = HeapAlloc(GetProcessHeap(), 0, sidsize);
713         SetLastError(0xdeadbeef);
714         pCreateWellKnownSid(WinInteractiveSid, NULL, user, &sidsize);
715         sidavailable = TRUE;
716     }
717     else
718     {
719         win_skip("Skipping some SID related tests\n");
720         sidavailable = FALSE;
721         user = NULL;
722     }
723
724     GetComputerNameA(localcomputer, &len);
725
726     /* Write an event with an incorrect event type. This will fail on Windows 7
727      * but succeed on all others, hence it's not part of the struct.
728      */
729     handle = OpenEventLogA(NULL, eventlogname);
730
731     SetLastError(0xdeadbeef);
732     ret = ReportEvent(handle, 0x20, 0, 0, NULL, 0, 0, NULL, NULL);
733     if (!ret && GetLastError() == ERROR_CRC)
734     {
735         win_skip("Win7 fails when using incorrect event types\n");
736         ret = ReportEvent(handle, 0, 0, 0, NULL, 0, 0, NULL, NULL);
737     }
738     ok(ret, "Expected success : %d\n", GetLastError());
739
740     /* This will clear the eventlog. The record numbering for new
741      * events however differs on Vista+. Before Vista the first
742      * event would be numbered 1, on Vista+ it's now 2 as we already
743      * had one event.
744      */
745     ClearEventLogA(handle, NULL);
746     CloseEventLog(handle);
747
748     /* Write a bunch of events while using different event sources */
749     for (i = 0; i < sizeof(read_write)/sizeof(read_write[0]); i++)
750     {
751         DWORD oldest;
752         BOOL run_sidtests = read_write[i].evt_sid & sidavailable;
753
754         /* We don't need to use RegisterEventSource to report events */
755         if (i % 2)
756             handle = OpenEventLogA(NULL, read_write[i].evt_src);
757         else
758             handle = RegisterEventSourceA(NULL, read_write[i].evt_src);
759         ok(handle != NULL, "Expected a handle\n");
760
761         SetLastError(0xdeadbeef);
762         ret = ReportEvent(handle, read_write[i].evt_type, read_write[i].evt_cat,
763                           read_write[i].evt_id, run_sidtests ? user : NULL,
764                           read_write[i].evt_numstrings, 0, read_write[i].evt_strings, NULL);
765
766         count = 0xdeadbeef;
767         ret = GetNumberOfEventLogRecords(handle, &count);
768         ok(ret, "Expected success\n");
769         ok(count == (i + 1), "Expected %d records, got %d\n", i + 1, count);
770
771         oldest = 0xdeadbeef;
772         ret = GetOldestEventLogRecord(handle, &oldest);
773         ok(ret, "Expected success\n");
774         ok(oldest == 1 ||
775            oldest == 2, /* Vista+ */
776            "Expected oldest to be 1 or 2, got %d\n", oldest);
777         if (oldest == 2)
778             on_vista = TRUE;
779
780         if (i % 2)
781             ret = CloseEventLog(handle);
782         else
783             ret = DeregisterEventSource(handle);
784         ok(ret, "Expected success : %d\n", GetLastError());
785     }
786
787     handle = OpenEventLogA(NULL, eventlogname);
788     count = 0xdeadbeef;
789     ret = GetNumberOfEventLogRecords(handle, &count);
790     ok(ret, "Expected success\n");
791     ok(count == i, "Expected %d records, got %d\n", i, count);
792     CloseEventLog(handle);
793
794     if (count == 0)
795     {
796         skip("No events were written to the eventlog\n");
797         return;
798     }
799
800     /* Report only once */
801     if (on_vista)
802         skip("There is no DWORD alignment for UserSid on Vista or higher\n");
803
804     /* Read all events from our created eventlog, one by one */
805     handle = OpenEventLogA(NULL, eventlogname);
806     i = 0;
807     for (;;)
808     {
809         void *buf;
810         DWORD read, needed;
811         EVENTLOGRECORD *record;
812         char *sourcename, *computername;
813         int k;
814         char *ptr;
815         BOOL run_sidtests = read_write[i].evt_sid & sidavailable;
816
817         buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD));
818         SetLastError(0xdeadbeef);
819         ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
820                             0, buf, sizeof(EVENTLOGRECORD), &read, &needed);
821         if (!ret && GetLastError() == ERROR_HANDLE_EOF)
822         {
823             HeapFree(GetProcessHeap(), 0, buf);
824             break;
825         }
826         ok(!ret, "Expected failure\n");
827         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
828            "Expected ERROR_INVALID_PARAMETER, got %d\n",GetLastError());
829
830         buf = HeapReAlloc(GetProcessHeap(), 0, buf, needed);
831         ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
832                             0, buf, needed, &read, &needed);
833         ok(ret, "Expected success: %d\n", GetLastError());
834
835         record = (EVENTLOGRECORD *)buf;
836
837         ok(record->Length == read,
838            "Expected %d, got %d\n", read, record->Length);
839         ok(record->Reserved == 0x654c664c,
840            "Expected 0x654c664c, got %d\n", record->Reserved);
841         ok(record->RecordNumber == i + 1 ||
842            (on_vista && (record->RecordNumber == i + 2)),
843            "Expected %d or %d, got %d\n", i + 1, i + 2, record->RecordNumber);
844         ok(record->EventID == read_write[i].evt_id,
845            "Expected %d, got %d\n", read_write[i].evt_id, record->EventID);
846         ok(record->EventType == read_write[i].evt_type,
847            "Expected %d, got %d\n", read_write[i].evt_type, record->EventType);
848         ok(record->NumStrings == read_write[i].evt_numstrings,
849            "Expected %d, got %d\n", read_write[i].evt_numstrings, record->NumStrings);
850         ok(record->EventCategory == read_write[i].evt_cat,
851            "Expected %d, got %d\n", read_write[i].evt_cat, record->EventCategory);
852
853         sourcename = (char *)((BYTE *)buf + sizeof(EVENTLOGRECORD));
854         ok(!lstrcmpA(sourcename, read_write[i].evt_src), "Expected '%s', got '%s'\n",
855            read_write[i].evt_src, sourcename);
856
857         computername = (char *)((BYTE *)buf + sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1);
858         ok(!lstrcmpiA(computername, localcomputer), "Expected '%s', got '%s'\n",
859            localcomputer, computername);
860
861         /* Before Vista, UserSid was aligned on a DWORD boundary. Next to that if
862          * no padding was actually required a 0 DWORD was still used for padding. No
863          * application should be relying on the padding as we are working with offsets
864          * anyway.
865          */
866
867         if (!on_vista)
868         {
869             DWORD calculated_sidoffset = sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1 + lstrlenA(computername) + 1;
870
871             /* We are already DWORD aligned, there should still be some padding */
872             if ((((UINT_PTR)buf + calculated_sidoffset) % sizeof(DWORD)) == 0)
873                 ok(*(DWORD_PTR *)((BYTE *)buf + calculated_sidoffset) == 0, "Expected 0\n");
874
875             ok((((UINT_PTR)buf + record->UserSidOffset) % sizeof(DWORD)) == 0, "Expected DWORD alignment\n");
876         }
877
878         if (run_sidtests)
879         {
880             ok(record->UserSidLength == sidsize, "Expected %d, got %d\n", sidsize, record->UserSidLength);
881         }
882         else
883         {
884             ok(record->StringOffset == record->UserSidOffset, "Expected offsets to be the same\n");
885             ok(record->UserSidLength == 0, "Expected 0, got %d\n", record->UserSidLength);
886         }
887
888         ok(record->DataLength == 0, "Expected 0, got %d\n", record->DataLength);
889
890         ptr = (char *)((BYTE *)buf + record->StringOffset);
891         for (k = 0; k < record->NumStrings; k++)
892         {
893             ok(!lstrcmpA(ptr, two_strings[k]), "Expected '%s', got '%s'\n", two_strings[k], ptr);
894             ptr += lstrlenA(ptr) + 1;
895         }
896
897         ok(record->Length == *(DWORD_PTR *)((BYTE *)buf + record->Length - sizeof(DWORD)),
898            "Expected the closing DWORD to contain the length of the record\n");
899
900         HeapFree(GetProcessHeap(), 0, buf);
901         i++;
902     }
903     CloseEventLog(handle);
904
905     HeapFree(GetProcessHeap(), 0, user);
906
907     /* Test clearing a real eventlog */
908     handle = OpenEventLogA(NULL, eventlogname);
909
910     SetLastError(0xdeadbeef);
911     ret = ClearEventLogA(handle, NULL);
912     ok(ret, "Expected success\n");
913
914     count = 0xdeadbeef;
915     ret = GetNumberOfEventLogRecords(handle, &count);
916     ok(ret, "Expected success\n");
917     ok(count == 0, "Expected an empty eventlog, got %d records\n", count);
918
919     CloseEventLog(handle);
920 }
921
922 /* Before Vista:
923  *
924  * Creating an eventlog on Windows (via the registry) automatically leads
925  * to creation of a REG_MULTI_SZ named 'Sources'. This value lists all the
926  * potential event sources for this eventlog. 'Sources' is automatically
927  * updated when a new key (aka event source) is created.
928  *
929  * Although the updating of registry keys is almost instantaneously, we
930  * check it after some other tests to assure we are not querying the
931  * registry or file system to quickly.
932  *
933  * NT4 and higher:
934  *
935  * The eventlog file itself is also automatically created, even before we
936  * start writing events.
937  */
938 static char eventlogfile[MAX_PATH];
939 static void test_autocreation(void)
940 {
941     HKEY key, eventkey;
942     DWORD type, size;
943     LONG ret;
944     int i;
945     char *p;
946     char sources[sizeof(eventsources)];
947     char sysdir[MAX_PATH];
948
949     RegOpenKeyA(HKEY_LOCAL_MACHINE, eventlogsvc, &key);
950     RegOpenKeyA(key, eventlogname, &eventkey);
951
952     size = sizeof(sources);
953     sources[0] = 0;
954     ret = RegQueryValueExA(eventkey, "Sources", NULL, &type, (LPBYTE)sources, &size);
955     if (ret == ERROR_SUCCESS)
956     {
957         char sources_verify[sizeof(eventsources)];
958
959         ok(type == REG_MULTI_SZ, "Expected a REG_MULTI_SZ, got %d\n", type);
960
961         /* Build the expected string */
962         memset(sources_verify, 0, sizeof(sources_verify));
963         p = sources_verify;
964         for (i = sizeof(eventsources)/sizeof(eventsources[0]); i > 0; i--)
965         {
966             lstrcpyA(p, eventsources[i - 1]);
967             p += (lstrlenA(eventsources[i - 1]) + 1);
968         }
969         lstrcpyA(p, eventlogname);
970
971         ok(!memcmp(sources, sources_verify, size), "Expected a correct 'Sources' value\n");
972     }
973
974     RegCloseKey(eventkey);
975     RegCloseKey(key);
976
977     /* On Windows we also automatically get an eventlog file */
978     GetSystemDirectoryA(sysdir, sizeof(sysdir));
979
980     /* NT4 - W2K3 */
981     lstrcpyA(eventlogfile, sysdir);
982     lstrcatA(eventlogfile, "\\config\\");
983     lstrcatA(eventlogfile, eventlogname);
984     lstrcatA(eventlogfile, ".evt");
985
986     if (GetFileAttributesA(eventlogfile) == INVALID_FILE_ATTRIBUTES)
987     {
988         /* Vista+ */
989         lstrcpyA(eventlogfile, sysdir);
990         lstrcatA(eventlogfile, "\\winevt\\Logs\\");
991         lstrcatA(eventlogfile, eventlogname);
992         lstrcatA(eventlogfile, ".evtx");
993     }
994
995     ok(GetFileAttributesA(eventlogfile) != INVALID_FILE_ATTRIBUTES,
996        "Expected an eventlog file\n");
997 }
998
999 static void cleanup_eventlog(void)
1000 {
1001     BOOL bret;
1002     LONG lret;
1003     HKEY key;
1004     int i;
1005     char winesvc[MAX_PATH];
1006
1007     /* Delete the registry tree */
1008     lstrcpyA(winesvc, eventlogsvc);
1009     lstrcatA(winesvc, "\\");
1010     lstrcatA(winesvc, eventlogname);
1011
1012     RegOpenKeyA(HKEY_LOCAL_MACHINE, winesvc, &key);
1013     for (i = 0; i < sizeof(eventsources)/sizeof(eventsources[0]); i++)
1014         RegDeleteKeyA(key, eventsources[i]);
1015     RegDeleteValueA(key, "Sources");
1016     RegCloseKey(key);
1017     lret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, winesvc);
1018     todo_wine
1019     ok(lret == ERROR_SUCCESS, "Could not delete the registry tree : %d\n", lret);
1020
1021     /* A handle to the eventlog is locked by services.exe. We can only
1022      * delete the eventlog file after reboot.
1023      */
1024     bret = MoveFileExA(eventlogfile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
1025     todo_wine
1026     ok(bret, "Expected MoveFileEx to succeed: %d\n", GetLastError());
1027 }
1028
1029 START_TEST(eventlog)
1030 {
1031     SetLastError(0xdeadbeef);
1032     CloseEventLog(NULL);
1033     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1034     {
1035         win_skip("Event log functions are not implemented\n");
1036         return;
1037     }
1038
1039     init_function_pointers();
1040
1041     /* Parameters only */
1042     test_open_close();
1043     test_info();
1044     test_count();
1045     test_oldest();
1046     test_backup();
1047     test_openbackup();
1048     test_read();
1049     test_clear();
1050
1051     /* Functional tests */
1052     if (create_new_eventlog())
1053     {
1054         test_readwrite();
1055         test_autocreation();
1056     }
1057     cleanup_eventlog();
1058 }