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 ElfrClearELFW( 289 IELF_HANDLE LogHandle, 290 PRPC_UNICODE_STRING BackupFileName) 291 { 292 PLOGHANDLE pLogHandle; 293 294 DPRINT("ElfrClearELFW()\n"); 295 296 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 297 if (!pLogHandle) 298 return STATUS_INVALID_HANDLE; 299 300 /* Fail, if the log file is a backup file */ 301 if (pLogHandle->Flags & LOG_HANDLE_BACKUP_FILE) 302 return STATUS_INVALID_HANDLE; 303 304 return LogfClearFile(pLogHandle->LogFile, 305 (PUNICODE_STRING)BackupFileName); 306 } 307 308 309 /* Function 1 */ 310 NTSTATUS 311 ElfrBackupELFW( 312 IELF_HANDLE LogHandle, 313 PRPC_UNICODE_STRING BackupFileName) 314 { 315 PLOGHANDLE pLogHandle; 316 317 DPRINT("ElfrBackupELFW()\n"); 318 319 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 320 if (!pLogHandle) 321 return STATUS_INVALID_HANDLE; 322 323 return LogfBackupFile(pLogHandle->LogFile, 324 (PUNICODE_STRING)BackupFileName); 325 } 326 327 328 /* Function 2 */ 329 NTSTATUS 330 ElfrCloseEL( 331 PIELF_HANDLE LogHandle) 332 { 333 return ElfDeleteEventLogHandle(LogHandle); 334 } 335 336 337 /* Function 3 */ 338 NTSTATUS 339 ElfrDeregisterEventSource( 340 PIELF_HANDLE LogHandle) 341 { 342 return ElfDeleteEventLogHandle(LogHandle); 343 } 344 345 346 /* Function 4 */ 347 NTSTATUS 348 ElfrNumberOfRecords( 349 IELF_HANDLE LogHandle, 350 PULONG NumberOfRecords) 351 { 352 PLOGHANDLE pLogHandle; 353 PLOGFILE pLogFile; 354 ULONG OldestRecordNumber, CurrentRecordNumber; 355 356 DPRINT("ElfrNumberOfRecords()\n"); 357 358 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 359 if (!pLogHandle) 360 return STATUS_INVALID_HANDLE; 361 362 if (!NumberOfRecords) 363 return STATUS_INVALID_PARAMETER; 364 365 pLogFile = pLogHandle->LogFile; 366 367 /* Lock the log file shared */ 368 RtlAcquireResourceShared(&pLogFile->Lock, TRUE); 369 370 OldestRecordNumber = ElfGetOldestRecord(&pLogFile->LogFile); 371 CurrentRecordNumber = ElfGetCurrentRecord(&pLogFile->LogFile); 372 373 /* Unlock the log file */ 374 RtlReleaseResource(&pLogFile->Lock); 375 376 DPRINT("Oldest: %lu Current: %lu\n", 377 OldestRecordNumber, CurrentRecordNumber); 378 379 if (OldestRecordNumber == 0) 380 { 381 /* OldestRecordNumber == 0 when the log is empty */ 382 *NumberOfRecords = 0; 383 } 384 else 385 { 386 /* The log contains events */ 387 *NumberOfRecords = CurrentRecordNumber - OldestRecordNumber; 388 } 389 390 return STATUS_SUCCESS; 391 } 392 393 394 /* Function 5 */ 395 NTSTATUS 396 ElfrOldestRecord( 397 IELF_HANDLE LogHandle, 398 PULONG OldestRecordNumber) 399 { 400 PLOGHANDLE pLogHandle; 401 PLOGFILE pLogFile; 402 403 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 404 if (!pLogHandle) 405 return STATUS_INVALID_HANDLE; 406 407 if (!OldestRecordNumber) 408 return STATUS_INVALID_PARAMETER; 409 410 pLogFile = pLogHandle->LogFile; 411 412 /* Lock the log file shared */ 413 RtlAcquireResourceShared(&pLogFile->Lock, TRUE); 414 415 *OldestRecordNumber = ElfGetOldestRecord(&pLogFile->LogFile); 416 417 /* Unlock the log file */ 418 RtlReleaseResource(&pLogFile->Lock); 419 420 return STATUS_SUCCESS; 421 } 422 423 424 /* Function 6 */ 425 NTSTATUS 426 ElfrChangeNotify( 427 IELF_HANDLE LogHandle, 428 RPC_CLIENT_ID ClientId, 429 ULONG Event) 430 { 431 UNIMPLEMENTED; 432 return STATUS_NOT_IMPLEMENTED; 433 } 434 435 436 /* Function 7 */ 437 NTSTATUS 438 ElfrOpenELW( 439 EVENTLOG_HANDLE_W UNCServerName, 440 PRPC_UNICODE_STRING ModuleName, 441 PRPC_UNICODE_STRING RegModuleName, 442 ULONG MajorVersion, 443 ULONG MinorVersion, 444 PIELF_HANDLE LogHandle) 445 { 446 if ((MajorVersion != 1) || (MinorVersion != 1)) 447 return STATUS_INVALID_PARAMETER; 448 449 /* RegModuleName must be an empty string */ 450 if (RegModuleName->Length > 0) 451 return STATUS_INVALID_PARAMETER; 452 453 /* FIXME: UNCServerName must specify the server */ 454 455 /* FIXME: Must verify that caller has read access */ 456 457 return ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle, 458 (PUNICODE_STRING)ModuleName, 459 FALSE); 460 } 461 462 463 /* Function 8 */ 464 NTSTATUS 465 ElfrRegisterEventSourceW( 466 EVENTLOG_HANDLE_W UNCServerName, 467 PRPC_UNICODE_STRING ModuleName, 468 PRPC_UNICODE_STRING RegModuleName, 469 ULONG MajorVersion, 470 ULONG MinorVersion, 471 PIELF_HANDLE LogHandle) 472 { 473 DPRINT("ElfrRegisterEventSourceW()\n"); 474 475 if ((MajorVersion != 1) || (MinorVersion != 1)) 476 return STATUS_INVALID_PARAMETER; 477 478 /* RegModuleName must be an empty string */ 479 if (RegModuleName->Length > 0) 480 return STATUS_INVALID_PARAMETER; 481 482 DPRINT("ModuleName: %wZ\n", ModuleName); 483 484 /* FIXME: UNCServerName must specify the server or empty for local */ 485 486 /* FIXME: Must verify that caller has write access */ 487 488 return ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle, 489 (PUNICODE_STRING)ModuleName, 490 TRUE); 491 } 492 493 494 /* Function 9 */ 495 NTSTATUS 496 ElfrOpenBELW( 497 EVENTLOG_HANDLE_W UNCServerName, 498 PRPC_UNICODE_STRING BackupFileName, 499 ULONG MajorVersion, 500 ULONG MinorVersion, 501 PIELF_HANDLE LogHandle) 502 { 503 DPRINT("ElfrOpenBELW(%wZ)\n", BackupFileName); 504 505 if ((MajorVersion != 1) || (MinorVersion != 1)) 506 return STATUS_INVALID_PARAMETER; 507 508 /* FIXME: UNCServerName must specify the server */ 509 510 /* FIXME: Must verify that caller has read access */ 511 512 return ElfCreateBackupLogHandle((PLOGHANDLE*)LogHandle, 513 (PUNICODE_STRING)BackupFileName); 514 } 515 516 517 /* Function 10 */ 518 NTSTATUS 519 ElfrReadELW( 520 IELF_HANDLE LogHandle, 521 ULONG ReadFlags, 522 ULONG RecordOffset, 523 RULONG NumberOfBytesToRead, 524 PBYTE Buffer, 525 PULONG NumberOfBytesRead, 526 PULONG MinNumberOfBytesNeeded) 527 { 528 NTSTATUS Status; 529 PLOGHANDLE pLogHandle; 530 ULONG RecordNumber; 531 532 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 533 if (!pLogHandle) 534 return STATUS_INVALID_HANDLE; 535 536 if (!Buffer) 537 return STATUS_INVALID_PARAMETER; 538 539 /* If sequential read, retrieve the CurrentRecord from this log handle */ 540 if (ReadFlags & EVENTLOG_SEQUENTIAL_READ) 541 { 542 RecordNumber = pLogHandle->CurrentRecord; 543 } 544 else // (ReadFlags & EVENTLOG_SEEK_READ) 545 { 546 RecordNumber = RecordOffset; 547 } 548 549 Status = LogfReadEvents(pLogHandle->LogFile, 550 ReadFlags, 551 &RecordNumber, 552 NumberOfBytesToRead, 553 Buffer, 554 NumberOfBytesRead, 555 MinNumberOfBytesNeeded, 556 FALSE); 557 558 /* Update the handle's CurrentRecord if success */ 559 if (NT_SUCCESS(Status)) 560 { 561 pLogHandle->CurrentRecord = RecordNumber; 562 } 563 564 return Status; 565 } 566 567 568 /* Helper function for ElfrReportEventW/A and ElfrReportEventAndSourceW */ 569 NTSTATUS 570 ElfrIntReportEventW( 571 IELF_HANDLE LogHandle, 572 ULONG Time, 573 USHORT EventType, 574 USHORT EventCategory, 575 ULONG EventID, 576 PRPC_UNICODE_STRING SourceName OPTIONAL, 577 USHORT NumStrings, 578 ULONG DataSize, 579 PRPC_UNICODE_STRING ComputerName, 580 PRPC_SID UserSID, 581 PRPC_UNICODE_STRING Strings[], 582 PBYTE Data, 583 USHORT Flags, 584 PULONG RecordNumber, 585 PULONG TimeWritten) 586 { 587 NTSTATUS Status; 588 PLOGHANDLE pLogHandle; 589 UNICODE_STRING LocalSourceName, LocalComputerName; 590 PEVENTLOGRECORD LogBuffer; 591 USHORT i; 592 SIZE_T RecSize; 593 ULONG dwStringsSize = 0; 594 ULONG dwUserSidLength = 0; 595 PWSTR lpStrings, str; 596 597 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 598 if (!pLogHandle) 599 return STATUS_INVALID_HANDLE; 600 601 /* Flags must be 0 */ 602 if (Flags) 603 return STATUS_INVALID_PARAMETER; 604 605 for (i = 0; i < NumStrings; i++) 606 { 607 switch (EventType) 608 { 609 case EVENTLOG_SUCCESS: 610 DPRINT("Success: %wZ\n", Strings[i]); 611 break; 612 613 case EVENTLOG_ERROR_TYPE: 614 DPRINT("Error: %wZ\n", Strings[i]); 615 break; 616 617 case EVENTLOG_WARNING_TYPE: 618 DPRINT("Warning: %wZ\n", Strings[i]); 619 break; 620 621 case EVENTLOG_INFORMATION_TYPE: 622 DPRINT("Info: %wZ\n", Strings[i]); 623 break; 624 625 case EVENTLOG_AUDIT_SUCCESS: 626 DPRINT("Audit Success: %wZ\n", Strings[i]); 627 break; 628 629 case EVENTLOG_AUDIT_FAILURE: 630 DPRINT("Audit Failure: %wZ\n", Strings[i]); 631 break; 632 633 default: 634 DPRINT1("Type %hu: %wZ\n", EventType, Strings[i]); 635 break; 636 } 637 dwStringsSize += Strings[i]->Length + sizeof(UNICODE_NULL); 638 } 639 640 lpStrings = HeapAlloc(GetProcessHeap(), 0, dwStringsSize); 641 if (!lpStrings) 642 { 643 DPRINT1("Failed to allocate heap\n"); 644 return STATUS_NO_MEMORY; 645 } 646 647 str = lpStrings; 648 for (i = 0; i < NumStrings; i++) 649 { 650 RtlCopyMemory(str, Strings[i]->Buffer, Strings[i]->Length); 651 str += Strings[i]->Length / sizeof(WCHAR); 652 *str = UNICODE_NULL; 653 str++; 654 } 655 656 if (UserSID) 657 dwUserSidLength = FIELD_OFFSET(SID, SubAuthority[UserSID->SubAuthorityCount]); 658 659 if (SourceName && SourceName->Buffer) 660 LocalSourceName = *(PUNICODE_STRING)SourceName; 661 else 662 RtlInitUnicodeString(&LocalSourceName, pLogHandle->szName); 663 664 LocalComputerName = *(PUNICODE_STRING)ComputerName; 665 666 LogBuffer = LogfAllocAndBuildNewRecord(&RecSize, 667 Time, 668 EventType, 669 EventCategory, 670 EventID, 671 &LocalSourceName, 672 &LocalComputerName, 673 dwUserSidLength, 674 UserSID, 675 NumStrings, 676 lpStrings, 677 DataSize, 678 Data); 679 if (LogBuffer == NULL) 680 { 681 DPRINT1("LogfAllocAndBuildNewRecord failed!\n"); 682 HeapFree(GetProcessHeap(), 0, lpStrings); 683 return STATUS_NO_MEMORY; 684 } 685 686 Status = LogfWriteRecord(pLogHandle->LogFile, LogBuffer, RecSize); 687 if (!NT_SUCCESS(Status)) 688 { 689 DPRINT1("ERROR writing to event log `%S' (Status 0x%08lx)\n", 690 pLogHandle->LogFile->LogName, Status); 691 } 692 693 if (NT_SUCCESS(Status)) 694 { 695 /* Retrieve the two fields that were set by LogfWriteRecord into the record */ 696 if (RecordNumber) 697 *RecordNumber = LogBuffer->RecordNumber; 698 if (TimeWritten) 699 *TimeWritten = LogBuffer->TimeWritten; 700 } 701 702 LogfFreeRecord(LogBuffer); 703 704 HeapFree(GetProcessHeap(), 0, lpStrings); 705 706 return Status; 707 } 708 709 710 /* Function 11 */ 711 NTSTATUS 712 ElfrReportEventW( 713 IELF_HANDLE LogHandle, 714 ULONG Time, 715 USHORT EventType, 716 USHORT EventCategory, 717 ULONG EventID, 718 USHORT NumStrings, 719 ULONG DataSize, 720 PRPC_UNICODE_STRING ComputerName, 721 PRPC_SID UserSID, 722 PRPC_UNICODE_STRING Strings[], 723 PBYTE Data, 724 USHORT Flags, 725 PULONG RecordNumber, 726 PULONG TimeWritten) 727 { 728 /* Call the helper function. The event source is provided via the log handle. */ 729 return ElfrIntReportEventW(LogHandle, 730 Time, 731 EventType, 732 EventCategory, 733 EventID, 734 NULL, 735 NumStrings, 736 DataSize, 737 ComputerName, 738 UserSID, 739 Strings, 740 Data, 741 Flags, 742 RecordNumber, 743 TimeWritten); 744 } 745 746 747 /* Function 12 */ 748 NTSTATUS 749 ElfrClearELFA( 750 IELF_HANDLE LogHandle, 751 PRPC_STRING BackupFileName) 752 { 753 NTSTATUS Status; 754 UNICODE_STRING BackupFileNameW; 755 756 Status = RtlAnsiStringToUnicodeString(&BackupFileNameW, 757 (PANSI_STRING)BackupFileName, 758 TRUE); 759 if (!NT_SUCCESS(Status)) 760 return Status; 761 762 Status = ElfrClearELFW(LogHandle, 763 (PRPC_UNICODE_STRING)&BackupFileNameW); 764 765 RtlFreeUnicodeString(&BackupFileNameW); 766 767 return Status; 768 } 769 770 771 /* Function 13 */ 772 NTSTATUS 773 ElfrBackupELFA( 774 IELF_HANDLE LogHandle, 775 PRPC_STRING BackupFileName) 776 { 777 NTSTATUS Status; 778 UNICODE_STRING BackupFileNameW; 779 780 Status = RtlAnsiStringToUnicodeString(&BackupFileNameW, 781 (PANSI_STRING)BackupFileName, 782 TRUE); 783 if (!NT_SUCCESS(Status)) 784 return Status; 785 786 Status = ElfrBackupELFW(LogHandle, 787 (PRPC_UNICODE_STRING)&BackupFileNameW); 788 789 RtlFreeUnicodeString(&BackupFileNameW); 790 791 return Status; 792 } 793 794 795 /* Function 14 */ 796 NTSTATUS 797 ElfrOpenELA( 798 EVENTLOG_HANDLE_A UNCServerName, 799 PRPC_STRING ModuleName, 800 PRPC_STRING RegModuleName, 801 ULONG MajorVersion, 802 ULONG MinorVersion, 803 PIELF_HANDLE LogHandle) 804 { 805 NTSTATUS Status; 806 UNICODE_STRING ModuleNameW; 807 808 if ((MajorVersion != 1) || (MinorVersion != 1)) 809 return STATUS_INVALID_PARAMETER; 810 811 /* RegModuleName must be an empty string */ 812 if (RegModuleName->Length > 0) 813 return STATUS_INVALID_PARAMETER; 814 815 Status = RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE); 816 if (!NT_SUCCESS(Status)) 817 return Status; 818 819 /* FIXME: Must verify that caller has read access */ 820 821 Status = ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle, 822 &ModuleNameW, 823 FALSE); 824 825 RtlFreeUnicodeString(&ModuleNameW); 826 827 return Status; 828 } 829 830 831 /* Function 15 */ 832 NTSTATUS 833 ElfrRegisterEventSourceA( 834 EVENTLOG_HANDLE_A UNCServerName, 835 PRPC_STRING ModuleName, 836 PRPC_STRING RegModuleName, 837 ULONG MajorVersion, 838 ULONG MinorVersion, 839 PIELF_HANDLE LogHandle) 840 { 841 NTSTATUS Status; 842 UNICODE_STRING ModuleNameW; 843 844 Status = RtlAnsiStringToUnicodeString(&ModuleNameW, 845 (PANSI_STRING)ModuleName, 846 TRUE); 847 if (!NT_SUCCESS(Status)) 848 { 849 DPRINT1("RtlAnsiStringToUnicodeString failed (Status 0x%08lx)\n", Status); 850 return Status; 851 } 852 853 /* RegModuleName must be an empty string */ 854 if (RegModuleName->Length > 0) 855 { 856 RtlFreeUnicodeString(&ModuleNameW); 857 return STATUS_INVALID_PARAMETER; 858 } 859 860 if ((MajorVersion != 1) || (MinorVersion != 1)) 861 { 862 RtlFreeUnicodeString(&ModuleNameW); 863 return STATUS_INVALID_PARAMETER; 864 } 865 866 /* FIXME: Must verify that caller has write access */ 867 868 Status = ElfCreateEventLogHandle((PLOGHANDLE*)LogHandle, 869 &ModuleNameW, 870 TRUE); 871 872 RtlFreeUnicodeString(&ModuleNameW); 873 874 return Status; 875 } 876 877 878 /* Function 16 */ 879 NTSTATUS 880 ElfrOpenBELA( 881 EVENTLOG_HANDLE_A UNCServerName, 882 PRPC_STRING BackupFileName, 883 ULONG MajorVersion, 884 ULONG MinorVersion, 885 PIELF_HANDLE LogHandle) 886 { 887 NTSTATUS Status; 888 UNICODE_STRING BackupFileNameW; 889 890 DPRINT("ElfrOpenBELA(%Z)\n", BackupFileName); 891 892 Status = RtlAnsiStringToUnicodeString(&BackupFileNameW, 893 (PANSI_STRING)BackupFileName, 894 TRUE); 895 if (!NT_SUCCESS(Status)) 896 { 897 DPRINT1("RtlAnsiStringToUnicodeString failed (Status 0x%08lx)\n", Status); 898 return Status; 899 } 900 901 if ((MajorVersion != 1) || (MinorVersion != 1)) 902 { 903 RtlFreeUnicodeString(&BackupFileNameW); 904 return STATUS_INVALID_PARAMETER; 905 } 906 907 /* FIXME: UNCServerName must specify the server */ 908 909 /* FIXME: Must verify that caller has read access */ 910 911 Status = ElfCreateBackupLogHandle((PLOGHANDLE*)LogHandle, 912 &BackupFileNameW); 913 914 RtlFreeUnicodeString(&BackupFileNameW); 915 916 return Status; 917 } 918 919 920 /* Function 17 */ 921 NTSTATUS 922 ElfrReadELA( 923 IELF_HANDLE LogHandle, 924 ULONG ReadFlags, 925 ULONG RecordOffset, 926 RULONG NumberOfBytesToRead, 927 PBYTE Buffer, 928 PULONG NumberOfBytesRead, 929 PULONG MinNumberOfBytesNeeded) 930 { 931 NTSTATUS Status; 932 PLOGHANDLE pLogHandle; 933 ULONG RecordNumber; 934 935 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 936 if (!pLogHandle) 937 return STATUS_INVALID_HANDLE; 938 939 if (!Buffer) 940 return STATUS_INVALID_PARAMETER; 941 942 /* If sequential read, retrieve the CurrentRecord from this log handle */ 943 if (ReadFlags & EVENTLOG_SEQUENTIAL_READ) 944 { 945 RecordNumber = pLogHandle->CurrentRecord; 946 } 947 else // (ReadFlags & EVENTLOG_SEEK_READ) 948 { 949 RecordNumber = RecordOffset; 950 } 951 952 Status = LogfReadEvents(pLogHandle->LogFile, 953 ReadFlags, 954 &RecordNumber, 955 NumberOfBytesToRead, 956 Buffer, 957 NumberOfBytesRead, 958 MinNumberOfBytesNeeded, 959 TRUE); 960 961 /* Update the handle's CurrentRecord if success */ 962 if (NT_SUCCESS(Status)) 963 { 964 pLogHandle->CurrentRecord = RecordNumber; 965 } 966 967 return Status; 968 } 969 970 971 /* Function 18 */ 972 NTSTATUS 973 ElfrReportEventA( 974 IELF_HANDLE LogHandle, 975 ULONG Time, 976 USHORT EventType, 977 USHORT EventCategory, 978 ULONG EventID, 979 USHORT NumStrings, 980 ULONG DataSize, 981 PRPC_STRING ComputerName, 982 PRPC_SID UserSID, 983 PRPC_STRING Strings[], 984 PBYTE Data, 985 USHORT Flags, 986 PULONG RecordNumber, 987 PULONG TimeWritten) 988 { 989 NTSTATUS Status = STATUS_SUCCESS; 990 UNICODE_STRING ComputerNameW; 991 PUNICODE_STRING *StringsArrayW = NULL; 992 USHORT i; 993 994 DPRINT("ElfrReportEventA(%hu)\n", NumStrings); 995 996 #if 0 997 for (i = 0; i < NumStrings; i++) 998 { 999 if (Strings[i] == NULL) 1000 { 1001 DPRINT1("String %hu is null\n", i); 1002 } 1003 else 1004 { 1005 DPRINT1("String %hu: %Z\n", i, Strings[i]); 1006 } 1007 } 1008 #endif 1009 1010 Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING)&ComputerNameW, 1011 (PANSI_STRING)ComputerName, 1012 TRUE); 1013 if (!NT_SUCCESS(Status)) 1014 return Status; 1015 1016 if (NumStrings != 0) 1017 { 1018 StringsArrayW = HeapAlloc(GetProcessHeap(), 1019 HEAP_ZERO_MEMORY, 1020 NumStrings * sizeof(PUNICODE_STRING)); 1021 if (StringsArrayW == NULL) 1022 { 1023 Status = STATUS_NO_MEMORY; 1024 goto Done; 1025 } 1026 1027 for (i = 0; i < NumStrings; i++) 1028 { 1029 if (Strings[i] != NULL) 1030 { 1031 StringsArrayW[i] = HeapAlloc(GetProcessHeap(), 1032 HEAP_ZERO_MEMORY, 1033 sizeof(UNICODE_STRING)); 1034 if (StringsArrayW[i] == NULL) 1035 { 1036 Status = STATUS_NO_MEMORY; 1037 break; 1038 } 1039 1040 Status = RtlAnsiStringToUnicodeString(StringsArrayW[i], 1041 (PANSI_STRING)Strings[i], 1042 TRUE); 1043 } 1044 1045 if (!NT_SUCCESS(Status)) 1046 break; 1047 } 1048 } 1049 1050 if (NT_SUCCESS(Status)) 1051 { 1052 Status = ElfrReportEventW(LogHandle, 1053 Time, 1054 EventType, 1055 EventCategory, 1056 EventID, 1057 NumStrings, 1058 DataSize, 1059 (PRPC_UNICODE_STRING)&ComputerNameW, 1060 UserSID, 1061 (PRPC_UNICODE_STRING*)StringsArrayW, 1062 Data, 1063 Flags, 1064 RecordNumber, 1065 TimeWritten); 1066 } 1067 1068 Done: 1069 if (StringsArrayW != NULL) 1070 { 1071 for (i = 0; i < NumStrings; i++) 1072 { 1073 if ((StringsArrayW[i] != NULL) && (StringsArrayW[i]->Buffer)) 1074 { 1075 RtlFreeUnicodeString(StringsArrayW[i]); 1076 HeapFree(GetProcessHeap(), 0, StringsArrayW[i]); 1077 } 1078 } 1079 1080 HeapFree(GetProcessHeap(), 0, StringsArrayW); 1081 } 1082 1083 RtlFreeUnicodeString(&ComputerNameW); 1084 1085 return Status; 1086 } 1087 1088 1089 /* Function 19 */ 1090 NTSTATUS 1091 ElfrRegisterClusterSvc( 1092 handle_t BindingHandle) 1093 { 1094 UNIMPLEMENTED; 1095 return STATUS_NOT_IMPLEMENTED; 1096 } 1097 1098 1099 /* Function 20 */ 1100 NTSTATUS 1101 ElfrDeregisterClusterSvc( 1102 handle_t BindingHandle) 1103 { 1104 UNIMPLEMENTED; 1105 return STATUS_NOT_IMPLEMENTED; 1106 } 1107 1108 1109 /* Function 21 */ 1110 NTSTATUS 1111 ElfrWriteClusterEvents( 1112 handle_t BindingHandle) 1113 { 1114 UNIMPLEMENTED; 1115 return STATUS_NOT_IMPLEMENTED; 1116 } 1117 1118 1119 /* Function 22 */ 1120 NTSTATUS 1121 ElfrGetLogInformation( 1122 IELF_HANDLE LogHandle, 1123 ULONG InfoLevel, 1124 PBYTE Buffer, 1125 ULONG cbBufSize, 1126 PULONG pcbBytesNeeded) 1127 { 1128 NTSTATUS Status = STATUS_SUCCESS; 1129 PLOGHANDLE pLogHandle; 1130 PLOGFILE pLogFile; 1131 1132 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 1133 if (!pLogHandle) 1134 return STATUS_INVALID_HANDLE; 1135 1136 pLogFile = pLogHandle->LogFile; 1137 1138 /* Lock the log file shared */ 1139 RtlAcquireResourceShared(&pLogFile->Lock, TRUE); 1140 1141 switch (InfoLevel) 1142 { 1143 case EVENTLOG_FULL_INFO: 1144 { 1145 LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer; 1146 1147 *pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION); 1148 if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION)) 1149 { 1150 Status = STATUS_BUFFER_TOO_SMALL; 1151 break; 1152 } 1153 1154 efi->dwFull = !!(ElfGetFlags(&pLogFile->LogFile) & ELF_LOGFILE_LOGFULL_WRITTEN); 1155 break; 1156 } 1157 1158 default: 1159 Status = STATUS_INVALID_LEVEL; 1160 break; 1161 } 1162 1163 /* Unlock the log file */ 1164 RtlReleaseResource(&pLogFile->Lock); 1165 1166 return Status; 1167 } 1168 1169 1170 /* Function 23 */ 1171 NTSTATUS 1172 ElfrFlushEL( 1173 IELF_HANDLE LogHandle) 1174 { 1175 NTSTATUS Status; 1176 PLOGHANDLE pLogHandle; 1177 PLOGFILE pLogFile; 1178 1179 pLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); 1180 if (!pLogHandle) 1181 return STATUS_INVALID_HANDLE; 1182 1183 pLogFile = pLogHandle->LogFile; 1184 1185 /* Lock the log file exclusive */ 1186 RtlAcquireResourceExclusive(&pLogFile->Lock, TRUE); 1187 1188 Status = ElfFlushFile(&pLogFile->LogFile); 1189 1190 /* Unlock the log file */ 1191 RtlReleaseResource(&pLogFile->Lock); 1192 1193 return Status; 1194 } 1195 1196 1197 /* Function 24 */ 1198 NTSTATUS 1199 ElfrReportEventAndSourceW( 1200 IELF_HANDLE LogHandle, 1201 ULONG Time, 1202 USHORT EventType, 1203 USHORT EventCategory, 1204 ULONG EventID, 1205 PRPC_UNICODE_STRING SourceName, 1206 USHORT NumStrings, 1207 ULONG DataSize, 1208 PRPC_UNICODE_STRING ComputerName, 1209 PRPC_SID UserSID, 1210 PRPC_UNICODE_STRING Strings[], 1211 PBYTE Data, 1212 USHORT Flags, 1213 PULONG RecordNumber, 1214 PULONG TimeWritten) 1215 { 1216 /* Call the helper function. The event source is specified by the caller. */ 1217 return ElfrIntReportEventW(LogHandle, 1218 Time, 1219 EventType, 1220 EventCategory, 1221 EventID, 1222 SourceName, 1223 NumStrings, 1224 DataSize, 1225 ComputerName, 1226 UserSID, 1227 Strings, 1228 Data, 1229 Flags, 1230 RecordNumber, 1231 TimeWritten); 1232 } 1233 1234 1235 void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len) 1236 { 1237 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 1238 } 1239 1240 1241 void __RPC_USER midl_user_free(void __RPC_FAR * ptr) 1242 { 1243 HeapFree(GetProcessHeap(), 0, ptr); 1244 } 1245 1246 1247 void __RPC_USER IELF_HANDLE_rundown(IELF_HANDLE LogHandle) 1248 { 1249 /* Close the handle */ 1250 ElfDeleteEventLogHandle(&LogHandle); // ElfrCloseEL(&LogHandle); 1251 } 1252