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