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