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