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