915e35d53b7a41ebe10c8ed4571b39b4d0a09dd4
[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 default:
478 DPRINT1("Type %hu: %wZ\n", EventType, Strings[i]);
479 break;
480 }
481 dwStringsSize += Strings[i]->Length + sizeof UNICODE_NULL;
482 }
483
484 lpStrings = HeapAlloc(GetProcessHeap(), 0, dwStringsSize);
485 if (!lpStrings)
486 {
487 DPRINT1("Failed to allocate heap\n");
488 return STATUS_NO_MEMORY;
489 }
490
491 for (i = 0; i < NumStrings; i++)
492 {
493 CopyMemory(lpStrings + pos, Strings[i]->Buffer, Strings[i]->Length);
494 pos += Strings[i]->Length / sizeof(WCHAR);
495 lpStrings[pos] = UNICODE_NULL;
496 pos += sizeof UNICODE_NULL / sizeof(WCHAR);
497 }
498
499 if (UserSID)
500 dwUserSidLength = FIELD_OFFSET(SID, SubAuthority[UserSID->SubAuthorityCount]);
501 LogBuffer = LogfAllocAndBuildNewRecord(&recSize,
502 lastRec,
503 EventType,
504 EventCategory,
505 EventID,
506 lpLogHandle->szName,
507 ComputerName->Buffer,
508 dwUserSidLength,
509 UserSID,
510 NumStrings,
511 lpStrings,
512 DataSize,
513 Data);
514
515 dwError = LogfWriteData(lpLogHandle->LogFile, recSize, LogBuffer);
516 if (!dwError)
517 {
518 DPRINT1("ERROR WRITING TO EventLog %S\n", lpLogHandle->LogFile->FileName);
519 }
520
521 LogfFreeRecord(LogBuffer);
522
523 HeapFree(GetProcessHeap(), 0, lpStrings);
524
525 return I_RpcMapWin32Status(dwError);
526 }
527
528
529 /* Function 12 */
530 NTSTATUS ElfrClearELFA(
531 IELF_HANDLE LogHandle,
532 PRPC_STRING BackupFileName)
533 {
534 UNICODE_STRING BackupFileNameW;
535 NTSTATUS Status;
536
537 Status = RtlAnsiStringToUnicodeString(&BackupFileNameW,
538 (PANSI_STRING)BackupFileName,
539 TRUE);
540 if (!NT_SUCCESS(Status))
541 return Status;
542
543 Status = ElfrClearELFW(LogHandle,
544 (PRPC_UNICODE_STRING)&BackupFileNameW);
545
546 RtlFreeUnicodeString(&BackupFileNameW);
547
548 return Status;
549 }
550
551
552 /* Function 13 */
553 NTSTATUS ElfrBackupELFA(
554 IELF_HANDLE LogHandle,
555 PRPC_STRING BackupFileName)
556 {
557 UNICODE_STRING BackupFileNameW;
558 NTSTATUS Status;
559
560 Status = RtlAnsiStringToUnicodeString(&BackupFileNameW,
561 (PANSI_STRING)BackupFileName,
562 TRUE);
563 if (!NT_SUCCESS(Status))
564 return Status;
565
566 Status = ElfrBackupELFW(LogHandle,
567 (PRPC_UNICODE_STRING)&BackupFileNameW);
568
569 RtlFreeUnicodeString(&BackupFileNameW);
570
571 return Status;
572 }
573
574
575 /* Function 14 */
576 NTSTATUS ElfrOpenELA(
577 EVENTLOG_HANDLE_A UNCServerName,
578 PRPC_STRING ModuleName,
579 PRPC_STRING RegModuleName,
580 DWORD MajorVersion,
581 DWORD MinorVersion,
582 IELF_HANDLE *LogHandle)
583 {
584 UNICODE_STRING ModuleNameW;
585 NTSTATUS Status;
586
587 if ((MajorVersion != 1) || (MinorVersion != 1))
588 return STATUS_INVALID_PARAMETER;
589
590 /* RegModuleName must be an empty string */
591 if (RegModuleName->Length > 0)
592 return STATUS_INVALID_PARAMETER;
593
594 Status = RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE);
595 if (!NT_SUCCESS(Status))
596 return Status;
597
598 /* FIXME: Must verify that caller has read access */
599
600 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer, FALSE);
601
602 RtlFreeUnicodeString(&ModuleNameW);
603
604 if (*LogHandle == NULL)
605 {
606 return STATUS_INVALID_PARAMETER;
607 }
608
609 return STATUS_SUCCESS;
610 }
611
612
613 /* Function 15 */
614 NTSTATUS ElfrRegisterEventSourceA(
615 EVENTLOG_HANDLE_A UNCServerName,
616 PRPC_STRING ModuleName,
617 PRPC_STRING RegModuleName,
618 DWORD MajorVersion,
619 DWORD MinorVersion,
620 IELF_HANDLE *LogHandle)
621 {
622 UNICODE_STRING ModuleNameW;
623 NTSTATUS Status;
624
625 Status = RtlAnsiStringToUnicodeString(&ModuleNameW,
626 (PANSI_STRING)ModuleName,
627 TRUE);
628 if (!NT_SUCCESS(Status))
629 {
630 DPRINT1("RtlAnsiStringToUnicodeString failed (Status 0x%08lx)\n", Status);
631 return Status;
632 }
633
634 /* RegModuleName must be an empty string */
635 if (RegModuleName->Length > 0)
636 {
637 RtlFreeUnicodeString(&ModuleNameW);
638 return STATUS_INVALID_PARAMETER;
639 }
640
641 if ((MajorVersion != 1) || (MinorVersion != 1))
642 {
643 RtlFreeUnicodeString(&ModuleNameW);
644 return STATUS_INVALID_PARAMETER;
645 }
646
647 /* FIXME: Must verify that caller has write access */
648
649 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer,
650 TRUE);
651
652 RtlFreeUnicodeString(&ModuleNameW);
653
654 return STATUS_SUCCESS;
655 }
656
657
658 /* Function 16 */
659 NTSTATUS ElfrOpenBELA(
660 EVENTLOG_HANDLE_A UNCServerName,
661 PRPC_STRING BackupFileName,
662 DWORD MajorVersion,
663 DWORD MinorVersion,
664 IELF_HANDLE *LogHandle)
665 {
666 UNIMPLEMENTED;
667 return STATUS_NOT_IMPLEMENTED;
668 }
669
670
671 /* Function 17 */
672 NTSTATUS ElfrReadELA(
673 IELF_HANDLE LogHandle,
674 DWORD ReadFlags,
675 DWORD RecordOffset,
676 RULONG NumberOfBytesToRead,
677 BYTE *Buffer,
678 DWORD *NumberOfBytesRead,
679 DWORD *MinNumberOfBytesNeeded)
680 {
681 PLOGHANDLE lpLogHandle;
682 DWORD dwError;
683 DWORD RecordNumber;
684
685 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
686 if (!lpLogHandle)
687 {
688 return STATUS_INVALID_HANDLE;
689 }
690
691 if (!Buffer)
692 return STATUS_INVALID_PARAMETER;
693
694 /* If sequential read, retrieve the CurrentRecord from this log handle */
695 if (ReadFlags & EVENTLOG_SEQUENTIAL_READ)
696 {
697 RecordNumber = lpLogHandle->CurrentRecord;
698 }
699 else
700 {
701 RecordNumber = RecordOffset;
702 }
703
704 dwError = LogfReadEvent(lpLogHandle->LogFile,
705 ReadFlags,
706 &RecordNumber,
707 NumberOfBytesToRead,
708 Buffer,
709 NumberOfBytesRead,
710 MinNumberOfBytesNeeded,
711 TRUE);
712
713 /* Update the handles CurrentRecord if success*/
714 if (dwError == ERROR_SUCCESS)
715 {
716 lpLogHandle->CurrentRecord = RecordNumber;
717 }
718
719 /* HACK!!! */
720 if (dwError == ERROR_HANDLE_EOF)
721 return STATUS_END_OF_FILE;
722
723 return I_RpcMapWin32Status(dwError);
724 }
725
726
727 /* Function 18 */
728 NTSTATUS ElfrReportEventA(
729 IELF_HANDLE LogHandle,
730 DWORD Time,
731 USHORT EventType,
732 USHORT EventCategory,
733 DWORD EventID,
734 USHORT NumStrings,
735 DWORD DataSize,
736 PRPC_STRING ComputerName,
737 PRPC_SID UserSID,
738 PRPC_STRING Strings[],
739 BYTE *Data,
740 USHORT Flags,
741 DWORD *RecordNumber,
742 DWORD *TimeWritten)
743 {
744 UNICODE_STRING ComputerNameW;
745 PUNICODE_STRING *StringsArrayW = NULL;
746 NTSTATUS Status = STATUS_SUCCESS;
747 USHORT i;
748
749 DPRINT("ElfrReportEventA(%hu)\n", NumStrings);
750
751 #if 0
752 for (i = 0; i < NumStrings; i++)
753 {
754 if (Strings[i] == NULL)
755 {
756 DPRINT1("String %hu is null\n", i);
757 }
758 else
759 {
760 DPRINT1("String %hu: %Z\n", i, Strings[i]);
761 }
762 }
763 #endif
764
765 Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING)&ComputerNameW,
766 (PANSI_STRING)ComputerName,
767 TRUE);
768 if (!NT_SUCCESS(Status))
769 return Status;
770
771 if (NumStrings != 0)
772 {
773 StringsArrayW = HeapAlloc(MyHeap,
774 HEAP_ZERO_MEMORY,
775 NumStrings * sizeof (PUNICODE_STRING));
776 if (StringsArrayW == NULL)
777 {
778 Status = STATUS_NO_MEMORY;
779 goto Done;
780 }
781
782 for (i = 0; i < NumStrings; i++)
783 {
784 if (Strings[i] != NULL)
785 {
786 StringsArrayW[i] = HeapAlloc(MyHeap,
787 HEAP_ZERO_MEMORY,
788 sizeof(UNICODE_STRING));
789 if (StringsArrayW[i] == NULL)
790 {
791 Status = STATUS_NO_MEMORY;
792 break;
793 }
794
795 Status = RtlAnsiStringToUnicodeString(StringsArrayW[i],
796 (PANSI_STRING)Strings[i],
797 TRUE);
798 }
799
800 if (!NT_SUCCESS(Status))
801 break;
802 }
803 }
804
805 if (NT_SUCCESS(Status))
806 {
807 Status = ElfrReportEventW(LogHandle,
808 Time,
809 EventType,
810 EventCategory,
811 EventID,
812 NumStrings,
813 DataSize,
814 (PRPC_UNICODE_STRING)&ComputerNameW,
815 UserSID,
816 (PRPC_UNICODE_STRING*)StringsArrayW,
817 Data,
818 Flags,
819 RecordNumber,
820 TimeWritten);
821 }
822
823 Done:
824 for (i = 0; i < NumStrings; i++)
825 {
826 if (StringsArrayW[i] != NULL)
827 {
828 if (StringsArrayW[i]->Buffer)
829 {
830 RtlFreeUnicodeString(StringsArrayW[i]);
831 HeapFree(MyHeap, 0, StringsArrayW[i]);
832 }
833 }
834 }
835
836 if (StringsArrayW != NULL)
837 HeapFree(MyHeap, 0, StringsArrayW);
838
839 RtlFreeUnicodeString(&ComputerNameW);
840
841 return Status;
842 }
843
844
845 /* Function 19 */
846 NTSTATUS ElfrRegisterClusterSvc(
847 handle_t BindingHandle)
848 {
849 UNIMPLEMENTED;
850 return STATUS_NOT_IMPLEMENTED;
851 }
852
853
854 /* Function 20 */
855 NTSTATUS ElfrDeregisterClusterSvc(
856 handle_t BindingHandle)
857 {
858 UNIMPLEMENTED;
859 return STATUS_NOT_IMPLEMENTED;
860 }
861
862
863 /* Function 21 */
864 NTSTATUS ElfrWriteClusterEvents(
865 handle_t BindingHandle)
866 {
867 UNIMPLEMENTED;
868 return STATUS_NOT_IMPLEMENTED;
869 }
870
871
872 /* Function 22 */
873 NTSTATUS ElfrGetLogInformation(
874 IELF_HANDLE LogHandle,
875 DWORD InfoLevel,
876 BYTE *Buffer,
877 DWORD cbBufSize,
878 DWORD *pcbBytesNeeded)
879 {
880 NTSTATUS Status = STATUS_SUCCESS;
881
882 /* FIXME: check handle first */
883
884 switch (InfoLevel)
885 {
886 case EVENTLOG_FULL_INFO:
887 {
888 LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer;
889
890 *pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
891 if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION))
892 {
893 return STATUS_BUFFER_TOO_SMALL;
894 }
895
896 efi->dwFull = 0; /* FIXME */
897 }
898 break;
899
900 default:
901 Status = STATUS_INVALID_LEVEL;
902 break;
903 }
904
905 return Status;
906 }
907
908
909 /* Function 23 */
910 NTSTATUS ElfrFlushEL(
911 IELF_HANDLE LogHandle)
912 {
913 UNIMPLEMENTED;
914 return STATUS_NOT_IMPLEMENTED;
915 }
916
917
918 /* Function 24 */
919 NTSTATUS ElfrReportEventAndSourceW(
920 IELF_HANDLE LogHandle,
921 DWORD Time,
922 USHORT EventType,
923 USHORT EventCategory,
924 ULONG EventID,
925 PRPC_UNICODE_STRING SourceName,
926 USHORT NumStrings,
927 DWORD DataSize,
928 PRPC_UNICODE_STRING ComputerName,
929 PRPC_SID UserSID,
930 PRPC_UNICODE_STRING Strings[],
931 BYTE *Data,
932 USHORT Flags,
933 DWORD *RecordNumber,
934 DWORD *TimeWritten)
935 {
936 UNIMPLEMENTED;
937 return STATUS_NOT_IMPLEMENTED;
938 }
939
940
941 void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len)
942 {
943 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
944 }
945
946
947 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
948 {
949 HeapFree(GetProcessHeap(), 0, ptr);
950 }
951
952
953 void __RPC_USER IELF_HANDLE_rundown(IELF_HANDLE LogHandle)
954 {
955 }