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