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