1 /* 2 * PROJECT: ReactOS EventLog Service 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/services/eventlog/rpc.c 5 * PURPOSE: RPC Port Interface support 6 * COPYRIGHT: Copyright 2005 Saveliy Tretiakov 7 * Copyright 2008 Michael Martin 8 * Copyright 2010-2011 Eric Kohl 9 */ 10 11 /* INCLUDES *****************************************************************/ 12 13 #include "eventlog.h" 14 15 #define NDEBUG 16 #include <debug.h> 17 18 static LIST_ENTRY LogHandleListHead; 19 static CRITICAL_SECTION LogHandleListCs; 20 21 /* FUNCTIONS ****************************************************************/ 22 23 static NTSTATUS 24 ElfDeleteEventLogHandle(PIELF_HANDLE LogHandle); 25 26 DWORD WINAPI RpcThreadRoutine(LPVOID lpParameter) 27 { 28 RPC_STATUS Status; 29 30 InitializeCriticalSection(&LogHandleListCs); 31 InitializeListHead(&LogHandleListHead); 32 33 Status = RpcServerUseProtseqEpW(L"ncacn_np", 20, L"\\pipe\\EventLog", NULL); 34 if (Status != RPC_S_OK) 35 { 36 DPRINT("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); 37 goto Quit; 38 } 39 40 Status = RpcServerRegisterIf(eventlog_v0_0_s_ifspec, NULL, NULL); 41 if (Status != RPC_S_OK) 42 { 43 DPRINT("RpcServerRegisterIf() failed (Status %lx)\n", Status); 44 goto Quit; 45 } 46 47 Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE); 48 if (Status != RPC_S_OK) 49 { 50 DPRINT("RpcServerListen() failed (Status %lx)\n", Status); 51 } 52 53 EnterCriticalSection(&LogHandleListCs); 54 while (!IsListEmpty(&LogHandleListHead)) 55 { 56 IELF_HANDLE LogHandle = (IELF_HANDLE)CONTAINING_RECORD(LogHandleListHead.Flink, LOGHANDLE, LogHandleListEntry); 57 ElfDeleteEventLogHandle(&LogHandle); 58 } 59 LeaveCriticalSection(&LogHandleListCs); 60 61 Quit: 62 DeleteCriticalSection(&LogHandleListCs); 63 64 return 0; 65 } 66 67 68 static NTSTATUS 69 ElfCreateEventLogHandle(PLOGHANDLE* LogHandle, 70 PUNICODE_STRING LogName, 71 BOOLEAN Create) 72 { 73 NTSTATUS Status = STATUS_SUCCESS; 74 PLOGHANDLE pLogHandle; 75 PLOGFILE currentLogFile = NULL; 76 DWORD i, LogsActive; 77 PEVENTSOURCE pEventSource; 78 79 DPRINT("ElfCreateEventLogHandle(%wZ)\n", LogName); 80 81 *LogHandle = NULL; 82 83 i = (LogName->Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR); 84 pLogHandle = HeapAlloc(GetProcessHeap(), 85 HEAP_ZERO_MEMORY, 86 FIELD_OFFSET(LOGHANDLE, szName[i])); 87 if (!pLogHandle) 88 { 89 DPRINT1("Failed to allocate Heap!\n"); 90 return STATUS_NO_MEMORY; 91 } 92 93 StringCchCopyW(pLogHandle->szName, i, LogName->Buffer); 94 95 /* Get the number of Log Files the EventLog service found */ 96 // NOTE: We could just as well loop only once within the list of logs 97 // and retrieve what the code below that calls LogfListItemByIndex, does!! 98 LogsActive = LogfListItemCount(); 99 if (LogsActive == 0) 100 { 101 DPRINT1("EventLog service reports no log files!\n"); 102 Status = STATUS_UNSUCCESSFUL; 103 goto Done; 104 } 105 106 /* If Creating, default to the Application Log in case we fail, as documented on MSDN */ 107 if (Create) 108 { 109 pEventSource = GetEventSourceByName(LogName->Buffer); 110 DPRINT("EventSource: %p\n", pEventSource); 111 if (pEventSource) 112 { 113 DPRINT("EventSource LogFile: %p\n", pEventSource->LogFile); 114 pLogHandle->LogFile = pEventSource->LogFile; 115 } 116 else 117 { 118 DPRINT("EventSource LogFile: Application log file\n"); 119 pLogHandle->LogFile = LogfListItemByName(L"Application"); 120 } 121 122 DPRINT("LogHandle LogFile: %p\n", pLogHandle->LogFile); 123 } 124 else 125 { 126 pLogHandle->LogFile = NULL; 127 128 for (i = 1; i <= LogsActive; i++) 129 { 130 currentLogFile = LogfListItemByIndex(i); 131 132 if (_wcsicmp(LogName->Buffer, currentLogFile->LogName) == 0) 133 { 134 pLogHandle->LogFile = currentLogFile; 135 break; 136 } 137 } 138 139 /* Use the application log if the desired log does not exist */ 140 if (pLogHandle->LogFile == NULL) 141 { 142 pLogHandle->LogFile = LogfListItemByName(L"Application"); 143 if (pLogHandle->LogFile == NULL) 144 { 145 DPRINT1("Application log is missing!\n"); 146 Status = STATUS_UNSUCCESSFUL; 147 goto Done; 148 } 149 } 150 151 /* Reset the current record */ 152 pLogHandle->CurrentRecord = 0; 153 } 154 155 if (!pLogHandle->LogFile) 156 Status = STATUS_UNSUCCESSFUL; 157 158 Done: 159 if (NT_SUCCESS(Status)) 160 { 161 /* Append log handle */ 162 EnterCriticalSection(&LogHandleListCs); 163 InsertTailList(&LogHandleListHead, &pLogHandle->LogHandleListEntry); 164 LeaveCriticalSection(&LogHandleListCs); 165 *LogHandle = pLogHandle; 166 } 167 else 168 { 169 HeapFree(GetProcessHeap(), 0, pLogHandle); 170 } 171 172 return Status; 173 } 174 175 176 static NTSTATUS 177 ElfCreateBackupLogHandle(PLOGHANDLE* LogHandle, 178 PUNICODE_STRING FileName) 179 { 180 NTSTATUS Status = STATUS_SUCCESS; 181 PLOGHANDLE pLogHandle; 182 183 DPRINT("ElfCreateBackupLogHandle(%wZ)\n", FileName); 184 185 *LogHandle = NULL; 186 187 pLogHandle = HeapAlloc(GetProcessHeap(), 188 HEAP_ZERO_MEMORY, 189 sizeof(LOGHANDLE)); 190 if (pLogHandle == NULL) 191 { 192 DPRINT1("Failed to allocate Heap!\n"); 193 return STATUS_NO_MEMORY; 194 } 195 196 /* Create the log file */ 197 Status = LogfCreate(&pLogHandle->LogFile, 198 NULL, 199 FileName, 200 0, 201 0, 202 FALSE, 203 TRUE); 204 if (!NT_SUCCESS(Status)) 205 { 206 DPRINT1("Failed to create the log file! (Status 0x%08lx)\n", Status); 207 goto Done; 208 } 209 210 /* Set the backup flag */ 211 pLogHandle->Flags |= LOG_HANDLE_BACKUP_FILE; 212 213 /* Reset the current record */ 214 pLogHandle->CurrentRecord = 0; 215 216 Done: 217 if (NT_SUCCESS(Status)) 218 { 219 /* Append log handle */ 220 EnterCriticalSection(&LogHandleListCs); 221 InsertTailList(&LogHandleListHead, &pLogHandle->LogHandleListEntry); 222 LeaveCriticalSection(&LogHandleListCs); 223 *LogHandle = pLogHandle; 224 } 225 else 226 { 227 HeapFree(GetProcessHeap(), 0, pLogHandle); 228 } 229 230 return Status; 231 } 232 233 234 static PLOGHANDLE 235 ElfGetLogHandleEntryByHandle(IELF_HANDLE EventLogHandle) 236 { 237 PLIST_ENTRY CurrentEntry; 238 PLOGHANDLE Handle, pLogHandle = NULL; 239 240 EnterCriticalSection(&LogHandleListCs); 241 242 CurrentEntry = LogHandleListHead.Flink; 243 while (CurrentEntry != &LogHandleListHead) 244 { 245 Handle = CONTAINING_RECORD(CurrentEntry, 246 LOGHANDLE, 247 LogHandleListEntry); 248 CurrentEntry = CurrentEntry->Flink; 249 250 if (Handle == EventLogHandle) 251 { 252 pLogHandle = Handle; 253 break; 254 } 255 } 256 257 LeaveCriticalSection(&LogHandleListCs); 258 259 return pLogHandle; 260 } 261 262 263 static NTSTATUS 264 ElfDeleteEventLogHandle(PIELF_HANDLE LogHandle) 265 { 266 PLOGHANDLE pLogHandle; 267 268 pLogHandle = ElfGetLogHandleEntryByHandle(*LogHandle); 269 if (!pLogHandle) 270 return STATUS_INVALID_HANDLE; 271 272 EnterCriticalSection(&LogHandleListCs); 273 RemoveEntryList(&pLogHandle->LogHandleListEntry); 274 LeaveCriticalSection(&LogHandleListCs); 275 276 LogfClose(pLogHandle->LogFile, FALSE); 277 278 HeapFree(GetProcessHeap(), 0, pLogHandle); 279 280 *LogHandle = NULL; 281 282 return STATUS_SUCCESS; 283 } 284 285 286 /* Function 0 */ 287 NTSTATUS 288 WINAPI 289 ElfrClearELFW( 290 IELF_HANDLE LogHandle, 291 PRPC_UNICODE_STRING BackupFileName) 292 { 293 PLOGHANDLE pLogHandle; 294 295 DPRINT("ElfrClearELFW()\n"); 296 297 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 298 if (!pLogHandle) 299 return STATUS_INVALID_HANDLE; 300 301 /* Fail, if the log file is a backup file */ 302 if (pLogHandle->Flags & LOG_HANDLE_BACKUP_FILE) 303 return STATUS_INVALID_HANDLE; 304 305 return LogfClearFile(pLogHandle->LogFile, 306 (PUNICODE_STRING)BackupFileName); 307 } 308 309 310 /* Function 1 */ 311 NTSTATUS 312 WINAPI 313 ElfrBackupELFW( 314 IELF_HANDLE LogHandle, 315 PRPC_UNICODE_STRING BackupFileName) 316 { 317 PLOGHANDLE pLogHandle; 318 319 DPRINT("ElfrBackupELFW()\n"); 320 321 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 322 if (!pLogHandle) 323 return STATUS_INVALID_HANDLE; 324 325 return LogfBackupFile(pLogHandle->LogFile, 326 (PUNICODE_STRING)BackupFileName); 327 } 328 329 330 /* Function 2 */ 331 NTSTATUS 332 WINAPI 333 ElfrCloseEL( 334 PIELF_HANDLE LogHandle) 335 { 336 return ElfDeleteEventLogHandle(LogHandle); 337 } 338 339 340 /* Function 3 */ 341 NTSTATUS 342 WINAPI 343 ElfrDeregisterEventSource( 344 PIELF_HANDLE LogHandle) 345 { 346 return ElfDeleteEventLogHandle(LogHandle); 347 } 348 349 350 /* Function 4 */ 351 NTSTATUS 352 WINAPI 353 ElfrNumberOfRecords( 354 IELF_HANDLE LogHandle, 355 PULONG NumberOfRecords) 356 { 357 PLOGHANDLE pLogHandle; 358 PLOGFILE pLogFile; 359 ULONG OldestRecordNumber, CurrentRecordNumber; 360 361 DPRINT("ElfrNumberOfRecords()\n"); 362 363 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 364 if (!pLogHandle) 365 return STATUS_INVALID_HANDLE; 366 367 if (!NumberOfRecords) 368 return STATUS_INVALID_PARAMETER; 369 370 pLogFile = pLogHandle->LogFile; 371 372 /* Lock the log file shared */ 373 RtlAcquireResourceShared(&pLogFile->Lock, TRUE); 374 375 OldestRecordNumber = ElfGetOldestRecord(&pLogFile->LogFile); 376 CurrentRecordNumber = ElfGetCurrentRecord(&pLogFile->LogFile); 377 378 /* Unlock the log file */ 379 RtlReleaseResource(&pLogFile->Lock); 380 381 DPRINT("Oldest: %lu Current: %lu\n", 382 OldestRecordNumber, CurrentRecordNumber); 383 384 if (OldestRecordNumber == 0) 385 { 386 /* OldestRecordNumber == 0 when the log is empty */ 387 *NumberOfRecords = 0; 388 } 389 else 390 { 391 /* The log contains events */ 392 *NumberOfRecords = CurrentRecordNumber - OldestRecordNumber; 393 } 394 395 return STATUS_SUCCESS; 396 } 397 398 399 /* Function 5 */ 400 NTSTATUS 401 WINAPI 402 ElfrOldestRecord( 403 IELF_HANDLE LogHandle, 404 PULONG OldestRecordNumber) 405 { 406 PLOGHANDLE pLogHandle; 407 PLOGFILE pLogFile; 408 409 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 410 if (!pLogHandle) 411 return STATUS_INVALID_HANDLE; 412 413 if (!OldestRecordNumber) 414 return STATUS_INVALID_PARAMETER; 415 416 pLogFile = pLogHandle->LogFile; 417 418 /* Lock the log file shared */ 419 RtlAcquireResourceShared(&pLogFile->Lock, TRUE); 420 421 *OldestRecordNumber = ElfGetOldestRecord(&pLogFile->LogFile); 422 423 /* Unlock the log file */ 424 RtlReleaseResource(&pLogFile->Lock); 425 426 return STATUS_SUCCESS; 427 } 428 429 430 /* Function 6 */ 431 NTSTATUS 432 WINAPI 433 ElfrChangeNotify( 434 IELF_HANDLE LogHandle, 435 RPC_CLIENT_ID ClientId, 436 ULONG Event) 437 { 438 UNIMPLEMENTED; 439 return STATUS_NOT_IMPLEMENTED; 440 } 441 442 443 /* Function 7 */ 444 NTSTATUS 445 WINAPI 446 ElfrOpenELW( 447 EVENTLOG_HANDLE_W UNCServerName, 448 PRPC_UNICODE_STRING ModuleName, 449 PRPC_UNICODE_STRING RegModuleName, 450 ULONG MajorVersion, 451 ULONG MinorVersion, 452 PIELF_HANDLE LogHandle) 453 { 454 if ((MajorVersion != 1) || (MinorVersion != 1)) 455 return STATUS_INVALID_PARAMETER; 456 457 /* RegModuleName must be an empty string */ 458 if (RegModuleName->Length > 0) 459 return STATUS_INVALID_PARAMETER; 460 461 /* FIXME: UNCServerName must specify the server */ 462 463 /* FIXME: Must verify that caller has read access */ 464 465 return ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle, 466 (PUNICODE_STRING)ModuleName, 467 FALSE); 468 } 469 470 471 /* Function 8 */ 472 NTSTATUS 473 WINAPI 474 ElfrRegisterEventSourceW( 475 EVENTLOG_HANDLE_W UNCServerName, 476 PRPC_UNICODE_STRING ModuleName, 477 PRPC_UNICODE_STRING RegModuleName, 478 ULONG MajorVersion, 479 ULONG MinorVersion, 480 PIELF_HANDLE LogHandle) 481 { 482 DPRINT("ElfrRegisterEventSourceW()\n"); 483 484 if ((MajorVersion != 1) || (MinorVersion != 1)) 485 return STATUS_INVALID_PARAMETER; 486 487 /* RegModuleName must be an empty string */ 488 if (RegModuleName->Length > 0) 489 return STATUS_INVALID_PARAMETER; 490 491 DPRINT("ModuleName: %wZ\n", ModuleName); 492 493 /* FIXME: UNCServerName must specify the server or empty for local */ 494 495 /* FIXME: Must verify that caller has write access */ 496 497 return ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle, 498 (PUNICODE_STRING)ModuleName, 499 TRUE); 500 } 501 502 503 /* Function 9 */ 504 NTSTATUS 505 WINAPI 506 ElfrOpenBELW( 507 EVENTLOG_HANDLE_W UNCServerName, 508 PRPC_UNICODE_STRING BackupFileName, 509 ULONG MajorVersion, 510 ULONG MinorVersion, 511 PIELF_HANDLE LogHandle) 512 { 513 DPRINT("ElfrOpenBELW(%wZ)\n", BackupFileName); 514 515 if ((MajorVersion != 1) || (MinorVersion != 1)) 516 return STATUS_INVALID_PARAMETER; 517 518 /* FIXME: UNCServerName must specify the server */ 519 520 /* FIXME: Must verify that caller has read access */ 521 522 return ElfCreateBackupLogHandle((PLOGHANDLE*)LogHandle, 523 (PUNICODE_STRING)BackupFileName); 524 } 525 526 527 /* Function 10 */ 528 NTSTATUS 529 WINAPI 530 ElfrReadELW( 531 IELF_HANDLE LogHandle, 532 ULONG ReadFlags, 533 ULONG RecordOffset, 534 RULONG NumberOfBytesToRead, 535 PBYTE Buffer, 536 PULONG NumberOfBytesRead, 537 PULONG MinNumberOfBytesNeeded) 538 { 539 NTSTATUS Status; 540 PLOGHANDLE pLogHandle; 541 ULONG RecordNumber; 542 543 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 544 if (!pLogHandle) 545 return STATUS_INVALID_HANDLE; 546 547 if (!Buffer) 548 return STATUS_INVALID_PARAMETER; 549 550 /* If sequential read, retrieve the CurrentRecord from this log handle */ 551 if (ReadFlags & EVENTLOG_SEQUENTIAL_READ) 552 { 553 RecordNumber = pLogHandle->CurrentRecord; 554 } 555 else // (ReadFlags & EVENTLOG_SEEK_READ) 556 { 557 RecordNumber = RecordOffset; 558 } 559 560 Status = LogfReadEvents(pLogHandle->LogFile, 561 ReadFlags, 562 &RecordNumber, 563 NumberOfBytesToRead, 564 Buffer, 565 NumberOfBytesRead, 566 MinNumberOfBytesNeeded, 567 FALSE); 568 569 /* Update the handle's CurrentRecord if success */ 570 if (NT_SUCCESS(Status)) 571 { 572 pLogHandle->CurrentRecord = RecordNumber; 573 } 574 575 return Status; 576 } 577 578 579 /* Helper function for ElfrReportEventW/A and ElfrReportEventAndSourceW */ 580 NTSTATUS 581 ElfrIntReportEventW( 582 IELF_HANDLE LogHandle, 583 ULONG Time, 584 USHORT EventType, 585 USHORT EventCategory, 586 ULONG EventID, 587 PRPC_UNICODE_STRING SourceName OPTIONAL, 588 USHORT NumStrings, 589 ULONG DataSize, 590 PRPC_UNICODE_STRING ComputerName, 591 PRPC_SID UserSID, 592 PRPC_UNICODE_STRING Strings[], 593 PBYTE Data, 594 USHORT Flags, 595 PULONG RecordNumber, 596 PULONG TimeWritten) 597 { 598 NTSTATUS Status; 599 PLOGHANDLE pLogHandle; 600 UNICODE_STRING LocalSourceName, LocalComputerName; 601 PEVENTLOGRECORD LogBuffer; 602 USHORT i; 603 SIZE_T RecSize; 604 ULONG dwStringsSize = 0; 605 ULONG dwUserSidLength = 0; 606 PWSTR lpStrings, str; 607 608 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 609 if (!pLogHandle) 610 return STATUS_INVALID_HANDLE; 611 612 /* Flags must be 0 */ 613 if (Flags) 614 return STATUS_INVALID_PARAMETER; 615 616 for (i = 0; i < NumStrings; i++) 617 { 618 switch (EventType) 619 { 620 case EVENTLOG_SUCCESS: 621 DPRINT("Success: %wZ\n", Strings[i]); 622 break; 623 624 case EVENTLOG_ERROR_TYPE: 625 DPRINT("Error: %wZ\n", Strings[i]); 626 break; 627 628 case EVENTLOG_WARNING_TYPE: 629 DPRINT("Warning: %wZ\n", Strings[i]); 630 break; 631 632 case EVENTLOG_INFORMATION_TYPE: 633 DPRINT("Info: %wZ\n", Strings[i]); 634 break; 635 636 case EVENTLOG_AUDIT_SUCCESS: 637 DPRINT("Audit Success: %wZ\n", Strings[i]); 638 break; 639 640 case EVENTLOG_AUDIT_FAILURE: 641 DPRINT("Audit Failure: %wZ\n", Strings[i]); 642 break; 643 644 default: 645 DPRINT1("Type %hu: %wZ\n", EventType, Strings[i]); 646 break; 647 } 648 dwStringsSize += Strings[i]->Length + sizeof(UNICODE_NULL); 649 } 650 651 lpStrings = HeapAlloc(GetProcessHeap(), 0, dwStringsSize); 652 if (!lpStrings) 653 { 654 DPRINT1("Failed to allocate heap\n"); 655 return STATUS_NO_MEMORY; 656 } 657 658 str = lpStrings; 659 for (i = 0; i < NumStrings; i++) 660 { 661 RtlCopyMemory(str, Strings[i]->Buffer, Strings[i]->Length); 662 str += Strings[i]->Length / sizeof(WCHAR); 663 *str = UNICODE_NULL; 664 str++; 665 } 666 667 if (UserSID) 668 dwUserSidLength = FIELD_OFFSET(SID, SubAuthority[UserSID->SubAuthorityCount]); 669 670 if (SourceName && SourceName->Buffer) 671 LocalSourceName = *(PUNICODE_STRING)SourceName; 672 else 673 RtlInitUnicodeString(&LocalSourceName, pLogHandle->szName); 674 675 LocalComputerName = *(PUNICODE_STRING)ComputerName; 676 677 LogBuffer = LogfAllocAndBuildNewRecord(&RecSize, 678 Time, 679 EventType, 680 EventCategory, 681 EventID, 682 &LocalSourceName, 683 &LocalComputerName, 684 dwUserSidLength, 685 UserSID, 686 NumStrings, 687 lpStrings, 688 DataSize, 689 Data); 690 if (LogBuffer == NULL) 691 { 692 DPRINT1("LogfAllocAndBuildNewRecord failed!\n"); 693 HeapFree(GetProcessHeap(), 0, lpStrings); 694 return STATUS_NO_MEMORY; 695 } 696 697 Status = LogfWriteRecord(pLogHandle->LogFile, LogBuffer, RecSize); 698 if (!NT_SUCCESS(Status)) 699 { 700 DPRINT1("ERROR writing to event log `%S' (Status 0x%08lx)\n", 701 pLogHandle->LogFile->LogName, Status); 702 } 703 704 if (NT_SUCCESS(Status)) 705 { 706 /* Retrieve the two fields that were set by LogfWriteRecord into the record */ 707 if (RecordNumber) 708 *RecordNumber = LogBuffer->RecordNumber; 709 if (TimeWritten) 710 *TimeWritten = LogBuffer->TimeWritten; 711 } 712 713 LogfFreeRecord(LogBuffer); 714 715 HeapFree(GetProcessHeap(), 0, lpStrings); 716 717 return Status; 718 } 719 720 721 /* Function 11 */ 722 NTSTATUS 723 WINAPI 724 ElfrReportEventW( 725 IELF_HANDLE LogHandle, 726 ULONG Time, 727 USHORT EventType, 728 USHORT EventCategory, 729 ULONG EventID, 730 USHORT NumStrings, 731 ULONG DataSize, 732 PRPC_UNICODE_STRING ComputerName, 733 PRPC_SID UserSID, 734 PRPC_UNICODE_STRING Strings[], 735 PBYTE Data, 736 USHORT Flags, 737 PULONG RecordNumber, 738 PULONG TimeWritten) 739 { 740 /* Call the helper function. The event source is provided via the log handle. */ 741 return ElfrIntReportEventW(LogHandle, 742 Time, 743 EventType, 744 EventCategory, 745 EventID, 746 NULL, 747 NumStrings, 748 DataSize, 749 ComputerName, 750 UserSID, 751 Strings, 752 Data, 753 Flags, 754 RecordNumber, 755 TimeWritten); 756 } 757 758 759 /* Function 12 */ 760 NTSTATUS 761 WINAPI 762 ElfrClearELFA( 763 IELF_HANDLE LogHandle, 764 PRPC_STRING BackupFileName) 765 { 766 NTSTATUS Status; 767 UNICODE_STRING BackupFileNameW; 768 769 Status = RtlAnsiStringToUnicodeString(&BackupFileNameW, 770 (PANSI_STRING)BackupFileName, 771 TRUE); 772 if (!NT_SUCCESS(Status)) 773 return Status; 774 775 Status = ElfrClearELFW(LogHandle, 776 (PRPC_UNICODE_STRING)&BackupFileNameW); 777 778 RtlFreeUnicodeString(&BackupFileNameW); 779 780 return Status; 781 } 782 783 784 /* Function 13 */ 785 NTSTATUS 786 WINAPI 787 ElfrBackupELFA( 788 IELF_HANDLE LogHandle, 789 PRPC_STRING BackupFileName) 790 { 791 NTSTATUS Status; 792 UNICODE_STRING BackupFileNameW; 793 794 Status = RtlAnsiStringToUnicodeString(&BackupFileNameW, 795 (PANSI_STRING)BackupFileName, 796 TRUE); 797 if (!NT_SUCCESS(Status)) 798 return Status; 799 800 Status = ElfrBackupELFW(LogHandle, 801 (PRPC_UNICODE_STRING)&BackupFileNameW); 802 803 RtlFreeUnicodeString(&BackupFileNameW); 804 805 return Status; 806 } 807 808 809 /* Function 14 */ 810 NTSTATUS 811 WINAPI 812 ElfrOpenELA( 813 EVENTLOG_HANDLE_A UNCServerName, 814 PRPC_STRING ModuleName, 815 PRPC_STRING RegModuleName, 816 ULONG MajorVersion, 817 ULONG MinorVersion, 818 PIELF_HANDLE LogHandle) 819 { 820 NTSTATUS Status; 821 UNICODE_STRING ModuleNameW; 822 823 if ((MajorVersion != 1) || (MinorVersion != 1)) 824 return STATUS_INVALID_PARAMETER; 825 826 /* RegModuleName must be an empty string */ 827 if (RegModuleName->Length > 0) 828 return STATUS_INVALID_PARAMETER; 829 830 Status = RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE); 831 if (!NT_SUCCESS(Status)) 832 return Status; 833 834 /* FIXME: Must verify that caller has read access */ 835 836 Status = ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle, 837 &ModuleNameW, 838 FALSE); 839 840 RtlFreeUnicodeString(&ModuleNameW); 841 842 return Status; 843 } 844 845 846 /* Function 15 */ 847 NTSTATUS 848 WINAPI 849 ElfrRegisterEventSourceA( 850 EVENTLOG_HANDLE_A UNCServerName, 851 PRPC_STRING ModuleName, 852 PRPC_STRING RegModuleName, 853 ULONG MajorVersion, 854 ULONG MinorVersion, 855 PIELF_HANDLE LogHandle) 856 { 857 NTSTATUS Status; 858 UNICODE_STRING ModuleNameW; 859 860 Status = RtlAnsiStringToUnicodeString(&ModuleNameW, 861 (PANSI_STRING)ModuleName, 862 TRUE); 863 if (!NT_SUCCESS(Status)) 864 { 865 DPRINT1("RtlAnsiStringToUnicodeString failed (Status 0x%08lx)\n", Status); 866 return Status; 867 } 868 869 /* RegModuleName must be an empty string */ 870 if (RegModuleName->Length > 0) 871 { 872 RtlFreeUnicodeString(&ModuleNameW); 873 return STATUS_INVALID_PARAMETER; 874 } 875 876 if ((MajorVersion != 1) || (MinorVersion != 1)) 877 { 878 RtlFreeUnicodeString(&ModuleNameW); 879 return STATUS_INVALID_PARAMETER; 880 } 881 882 /* FIXME: Must verify that caller has write access */ 883 884 Status = ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle, 885 &ModuleNameW, 886 TRUE); 887 888 RtlFreeUnicodeString(&ModuleNameW); 889 890 return Status; 891 } 892 893 894 /* Function 16 */ 895 NTSTATUS 896 WINAPI 897 ElfrOpenBELA( 898 EVENTLOG_HANDLE_A UNCServerName, 899 PRPC_STRING BackupFileName, 900 ULONG MajorVersion, 901 ULONG MinorVersion, 902 PIELF_HANDLE LogHandle) 903 { 904 NTSTATUS Status; 905 UNICODE_STRING BackupFileNameW; 906 907 DPRINT("ElfrOpenBELA(%Z)\n", BackupFileName); 908 909 Status = RtlAnsiStringToUnicodeString(&BackupFileNameW, 910 (PANSI_STRING)BackupFileName, 911 TRUE); 912 if (!NT_SUCCESS(Status)) 913 { 914 DPRINT1("RtlAnsiStringToUnicodeString failed (Status 0x%08lx)\n", Status); 915 return Status; 916 } 917 918 if ((MajorVersion != 1) || (MinorVersion != 1)) 919 { 920 RtlFreeUnicodeString(&BackupFileNameW); 921 return STATUS_INVALID_PARAMETER; 922 } 923 924 /* FIXME: UNCServerName must specify the server */ 925 926 /* FIXME: Must verify that caller has read access */ 927 928 Status = ElfCreateBackupLogHandle((PLOGHANDLE*)LogHandle, 929 &BackupFileNameW); 930 931 RtlFreeUnicodeString(&BackupFileNameW); 932 933 return Status; 934 } 935 936 937 /* Function 17 */ 938 NTSTATUS 939 WINAPI 940 ElfrReadELA( 941 IELF_HANDLE LogHandle, 942 ULONG ReadFlags, 943 ULONG RecordOffset, 944 RULONG NumberOfBytesToRead, 945 PBYTE Buffer, 946 PULONG NumberOfBytesRead, 947 PULONG MinNumberOfBytesNeeded) 948 { 949 NTSTATUS Status; 950 PLOGHANDLE pLogHandle; 951 ULONG RecordNumber; 952 953 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 954 if (!pLogHandle) 955 return STATUS_INVALID_HANDLE; 956 957 if (!Buffer) 958 return STATUS_INVALID_PARAMETER; 959 960 /* If sequential read, retrieve the CurrentRecord from this log handle */ 961 if (ReadFlags & EVENTLOG_SEQUENTIAL_READ) 962 { 963 RecordNumber = pLogHandle->CurrentRecord; 964 } 965 else // (ReadFlags & EVENTLOG_SEEK_READ) 966 { 967 RecordNumber = RecordOffset; 968 } 969 970 Status = LogfReadEvents(pLogHandle->LogFile, 971 ReadFlags, 972 &RecordNumber, 973 NumberOfBytesToRead, 974 Buffer, 975 NumberOfBytesRead, 976 MinNumberOfBytesNeeded, 977 TRUE); 978 979 /* Update the handle's CurrentRecord if success */ 980 if (NT_SUCCESS(Status)) 981 { 982 pLogHandle->CurrentRecord = RecordNumber; 983 } 984 985 return Status; 986 } 987 988 989 /* Function 18 */ 990 NTSTATUS 991 WINAPI 992 ElfrReportEventA( 993 IELF_HANDLE LogHandle, 994 ULONG Time, 995 USHORT EventType, 996 USHORT EventCategory, 997 ULONG EventID, 998 USHORT NumStrings, 999 ULONG DataSize, 1000 PRPC_STRING ComputerName, 1001 PRPC_SID UserSID, 1002 PRPC_STRING Strings[], 1003 PBYTE Data, 1004 USHORT Flags, 1005 PULONG RecordNumber, 1006 PULONG TimeWritten) 1007 { 1008 NTSTATUS Status = STATUS_SUCCESS; 1009 UNICODE_STRING ComputerNameW; 1010 PUNICODE_STRING *StringsArrayW = NULL; 1011 USHORT i; 1012 1013 DPRINT("ElfrReportEventA(%hu)\n", NumStrings); 1014 1015 #if 0 1016 for (i = 0; i < NumStrings; i++) 1017 { 1018 if (Strings[i] == NULL) 1019 { 1020 DPRINT1("String %hu is null\n", i); 1021 } 1022 else 1023 { 1024 DPRINT1("String %hu: %Z\n", i, Strings[i]); 1025 } 1026 } 1027 #endif 1028 1029 Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING)&ComputerNameW, 1030 (PANSI_STRING)ComputerName, 1031 TRUE); 1032 if (!NT_SUCCESS(Status)) 1033 return Status; 1034 1035 if (NumStrings != 0) 1036 { 1037 StringsArrayW = HeapAlloc(GetProcessHeap(), 1038 HEAP_ZERO_MEMORY, 1039 NumStrings * sizeof(PUNICODE_STRING)); 1040 if (StringsArrayW == NULL) 1041 { 1042 Status = STATUS_NO_MEMORY; 1043 goto Done; 1044 } 1045 1046 for (i = 0; i < NumStrings; i++) 1047 { 1048 if (Strings[i] != NULL) 1049 { 1050 StringsArrayW[i] = HeapAlloc(GetProcessHeap(), 1051 HEAP_ZERO_MEMORY, 1052 sizeof(UNICODE_STRING)); 1053 if (StringsArrayW[i] == NULL) 1054 { 1055 Status = STATUS_NO_MEMORY; 1056 break; 1057 } 1058 1059 Status = RtlAnsiStringToUnicodeString(StringsArrayW[i], 1060 (PANSI_STRING)Strings[i], 1061 TRUE); 1062 } 1063 1064 if (!NT_SUCCESS(Status)) 1065 break; 1066 } 1067 } 1068 1069 if (NT_SUCCESS(Status)) 1070 { 1071 Status = ElfrReportEventW(LogHandle, 1072 Time, 1073 EventType, 1074 EventCategory, 1075 EventID, 1076 NumStrings, 1077 DataSize, 1078 (PRPC_UNICODE_STRING)&ComputerNameW, 1079 UserSID, 1080 (PRPC_UNICODE_STRING*)StringsArrayW, 1081 Data, 1082 Flags, 1083 RecordNumber, 1084 TimeWritten); 1085 } 1086 1087 Done: 1088 if (StringsArrayW != NULL) 1089 { 1090 for (i = 0; i < NumStrings; i++) 1091 { 1092 if ((StringsArrayW[i] != NULL) && (StringsArrayW[i]->Buffer)) 1093 { 1094 RtlFreeUnicodeString(StringsArrayW[i]); 1095 HeapFree(GetProcessHeap(), 0, StringsArrayW[i]); 1096 } 1097 } 1098 1099 HeapFree(GetProcessHeap(), 0, StringsArrayW); 1100 } 1101 1102 RtlFreeUnicodeString(&ComputerNameW); 1103 1104 return Status; 1105 } 1106 1107 1108 /* Function 19 */ 1109 NTSTATUS 1110 WINAPI 1111 ElfrRegisterClusterSvc( 1112 handle_t BindingHandle) 1113 { 1114 UNIMPLEMENTED; 1115 return STATUS_NOT_IMPLEMENTED; 1116 } 1117 1118 1119 /* Function 20 */ 1120 NTSTATUS 1121 WINAPI 1122 ElfrDeregisterClusterSvc( 1123 handle_t BindingHandle) 1124 { 1125 UNIMPLEMENTED; 1126 return STATUS_NOT_IMPLEMENTED; 1127 } 1128 1129 1130 /* Function 21 */ 1131 NTSTATUS 1132 WINAPI 1133 ElfrWriteClusterEvents( 1134 handle_t BindingHandle) 1135 { 1136 UNIMPLEMENTED; 1137 return STATUS_NOT_IMPLEMENTED; 1138 } 1139 1140 1141 /* Function 22 */ 1142 NTSTATUS 1143 WINAPI 1144 ElfrGetLogInformation( 1145 IELF_HANDLE LogHandle, 1146 ULONG InfoLevel, 1147 PBYTE Buffer, 1148 ULONG cbBufSize, 1149 PULONG pcbBytesNeeded) 1150 { 1151 NTSTATUS Status = STATUS_SUCCESS; 1152 PLOGHANDLE pLogHandle; 1153 PLOGFILE pLogFile; 1154 1155 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 1156 if (!pLogHandle) 1157 return STATUS_INVALID_HANDLE; 1158 1159 pLogFile = pLogHandle->LogFile; 1160 1161 /* Lock the log file shared */ 1162 RtlAcquireResourceShared(&pLogFile->Lock, TRUE); 1163 1164 switch (InfoLevel) 1165 { 1166 case EVENTLOG_FULL_INFO: 1167 { 1168 LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer; 1169 1170 *pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION); 1171 if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION)) 1172 { 1173 Status = STATUS_BUFFER_TOO_SMALL; 1174 break; 1175 } 1176 1177 efi->dwFull = !!(ElfGetFlags(&pLogFile->LogFile) & ELF_LOGFILE_LOGFULL_WRITTEN); 1178 break; 1179 } 1180 1181 default: 1182 Status = STATUS_INVALID_LEVEL; 1183 break; 1184 } 1185 1186 /* Unlock the log file */ 1187 RtlReleaseResource(&pLogFile->Lock); 1188 1189 return Status; 1190 } 1191 1192 1193 /* Function 23 */ 1194 NTSTATUS 1195 WINAPI 1196 ElfrFlushEL( 1197 IELF_HANDLE LogHandle) 1198 { 1199 NTSTATUS Status; 1200 PLOGHANDLE pLogHandle; 1201 PLOGFILE pLogFile; 1202 1203 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 1204 if (!pLogHandle) 1205 return STATUS_INVALID_HANDLE; 1206 1207 pLogFile = pLogHandle->LogFile; 1208 1209 /* Lock the log file exclusive */ 1210 RtlAcquireResourceExclusive(&pLogFile->Lock, TRUE); 1211 1212 Status = ElfFlushFile(&pLogFile->LogFile); 1213 1214 /* Unlock the log file */ 1215 RtlReleaseResource(&pLogFile->Lock); 1216 1217 return Status; 1218 } 1219 1220 1221 /* Function 24 */ 1222 NTSTATUS 1223 WINAPI 1224 ElfrReportEventAndSourceW( 1225 IELF_HANDLE LogHandle, 1226 ULONG Time, 1227 USHORT EventType, 1228 USHORT EventCategory, 1229 ULONG EventID, 1230 PRPC_UNICODE_STRING SourceName, 1231 USHORT NumStrings, 1232 ULONG DataSize, 1233 PRPC_UNICODE_STRING ComputerName, 1234 PRPC_SID UserSID, 1235 PRPC_UNICODE_STRING Strings[], 1236 PBYTE Data, 1237 USHORT Flags, 1238 PULONG RecordNumber, 1239 PULONG TimeWritten) 1240 { 1241 /* Call the helper function. The event source is specified by the caller. */ 1242 return ElfrIntReportEventW(LogHandle, 1243 Time, 1244 EventType, 1245 EventCategory, 1246 EventID, 1247 SourceName, 1248 NumStrings, 1249 DataSize, 1250 ComputerName, 1251 UserSID, 1252 Strings, 1253 Data, 1254 Flags, 1255 RecordNumber, 1256 TimeWritten); 1257 } 1258 1259 1260 void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len) 1261 { 1262 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 1263 } 1264 1265 1266 void __RPC_USER midl_user_free(void __RPC_FAR * ptr) 1267 { 1268 HeapFree(GetProcessHeap(), 0, ptr); 1269 } 1270 1271 1272 void __RPC_USER IELF_HANDLE_rundown(IELF_HANDLE LogHandle) 1273 { 1274 /* Close the handle */ 1275 ElfDeleteEventLogHandle(&LogHandle); // ElfrCloseEL(&LogHandle); 1276 } 1277