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