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