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