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