[TFTPD] Fix compilation, and use the #define MAX_SERVERS where needed instead of...
[reactos.git] / 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 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 }