Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[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 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 }