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
10 /* INCLUDES *****************************************************************/
14 LIST_ENTRY LogHandleListHead
;
16 /* FUNCTIONS ****************************************************************/
18 DWORD WINAPI
RpcThreadRoutine(LPVOID lpParameter
)
22 InitializeListHead(&LogHandleListHead
);
24 Status
= RpcServerUseProtseqEpW(L
"ncacn_np", 20, L
"\\pipe\\EventLog", NULL
);
25 if (Status
!= RPC_S_OK
)
27 DPRINT("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
31 Status
= RpcServerRegisterIf(eventlog_v0_0_s_ifspec
, NULL
, NULL
);
32 if (Status
!= RPC_S_OK
)
34 DPRINT("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
38 Status
= RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT
, FALSE
);
39 if (Status
!= RPC_S_OK
)
41 DPRINT("RpcServerListen() failed (Status %lx)\n", Status
);
47 PLOGHANDLE
ElfCreateEventLogHandle(LPCWSTR Name
, BOOL Create
)
49 PLOGHANDLE lpLogHandle
;
50 PLOGFILE currentLogFile
= NULL
;
52 PEVENTSOURCE pEventSource
;
54 DPRINT("ElfCreateEventLogHandle(Name: %S)\n", Name
);
56 lpLogHandle
= HeapAlloc(GetProcessHeap(), 0, sizeof(LOGHANDLE
)
57 + ((wcslen(Name
) + 1) * sizeof(WCHAR
)));
60 DPRINT1("Failed to allocate Heap!\n");
64 wcscpy(lpLogHandle
->szName
, Name
);
66 /* Get the number of Log Files the EventLog service found */
67 LogsActive
= LogfListItemCount();
70 DPRINT1("EventLog service reports no log files!\n");
74 /* If Creating, default to the Application Log in case we fail, as documented on MSDN */
77 pEventSource
= GetEventSourceByName(Name
);
78 DPRINT("EventSource: %p\n", pEventSource
);
81 DPRINT("EventSource LogFile: %p\n", pEventSource
->LogFile
);
82 lpLogHandle
->LogFile
= pEventSource
->LogFile
;
86 DPRINT("EventSource LogFile: Application log file\n");
87 lpLogHandle
->LogFile
= LogfListItemByName(L
"Application");
90 DPRINT("LogHandle LogFile: %p\n", lpLogHandle
->LogFile
);
94 lpLogHandle
->LogFile
= NULL
;
96 for (i
= 1; i
<= LogsActive
; i
++)
98 currentLogFile
= LogfListItemByIndex(i
);
100 if (_wcsicmp(Name
, currentLogFile
->LogName
) == 0)
102 lpLogHandle
->LogFile
= LogfListItemByIndex(i
);
103 lpLogHandle
->CurrentRecord
= LogfGetOldestRecord(lpLogHandle
->LogFile
);
108 /* Use the application log if the desired log does not exist */
109 if (lpLogHandle
->LogFile
== NULL
)
111 lpLogHandle
->LogFile
= LogfListItemByName(L
"Application");
112 lpLogHandle
->CurrentRecord
= LogfGetOldestRecord(lpLogHandle
->LogFile
);
116 if (!lpLogHandle
->LogFile
)
119 /* Append log handle */
120 InsertTailList(&LogHandleListHead
, &lpLogHandle
->LogHandleListEntry
);
125 HeapFree(GetProcessHeap(), 0, lpLogHandle
);
130 PLOGHANDLE
ElfGetLogHandleEntryByHandle(IELF_HANDLE EventLogHandle
)
132 PLOGHANDLE lpLogHandle
;
134 if (IsListEmpty(&LogHandleListHead
))
139 lpLogHandle
= CONTAINING_RECORD((PLOGHANDLE
)EventLogHandle
, LOGHANDLE
, LogHandleListEntry
);
144 BOOL
ElfDeleteEventLogHandle(IELF_HANDLE EventLogHandle
)
146 PLOGHANDLE lpLogHandle
= (PLOGHANDLE
)EventLogHandle
;
147 if (!ElfGetLogHandleEntryByHandle(lpLogHandle
))
152 RemoveEntryList(&lpLogHandle
->LogHandleListEntry
);
153 HeapFree(GetProcessHeap(),0,lpLogHandle
);
159 NTSTATUS
ElfrClearELFW(
160 IELF_HANDLE LogHandle
,
161 PRPC_UNICODE_STRING BackupFileName
)
163 PLOGHANDLE lpLogHandle
;
166 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
169 return STATUS_INVALID_HANDLE
;
172 lpLogFile
= lpLogHandle
->LogFile
;
174 if (BackupFileName
->Length
> 0)
176 /* FIXME: Write a backup file */
179 LogfInitializeNew(lpLogFile
);
181 return STATUS_SUCCESS
;
186 NTSTATUS
ElfrBackupELFW(
187 IELF_HANDLE LogHandle
,
188 PRPC_UNICODE_STRING BackupFileName
)
191 return STATUS_NOT_IMPLEMENTED
;
195 NTSTATUS
ElfrCloseEL(
196 IELF_HANDLE
*LogHandle
)
198 if (!ElfDeleteEventLogHandle(*LogHandle
))
200 return STATUS_INVALID_HANDLE
;
203 return STATUS_SUCCESS
;
208 NTSTATUS
ElfrDeregisterEventSource(
209 IELF_HANDLE
*LogHandle
)
211 if (!ElfDeleteEventLogHandle(*LogHandle
))
213 return STATUS_INVALID_HANDLE
;
216 return STATUS_SUCCESS
;
221 NTSTATUS
ElfrNumberOfRecords(
222 IELF_HANDLE LogHandle
,
223 DWORD
*NumberOfRecords
)
225 PLOGHANDLE lpLogHandle
;
228 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
231 return STATUS_INVALID_HANDLE
;
234 lpLogFile
= lpLogHandle
->LogFile
;
236 if (lpLogFile
->Header
.OldestRecordNumber
== 0)
237 *NumberOfRecords
= 0;
239 *NumberOfRecords
= lpLogFile
->Header
.CurrentRecordNumber
-
240 lpLogFile
->Header
.OldestRecordNumber
;
242 return STATUS_SUCCESS
;
247 NTSTATUS
ElfrOldestRecord(
248 IELF_HANDLE LogHandle
,
249 DWORD
*OldestRecordNumber
)
251 PLOGHANDLE lpLogHandle
;
253 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
256 return STATUS_INVALID_HANDLE
;
259 if (!OldestRecordNumber
)
261 return STATUS_INVALID_PARAMETER
;
264 *OldestRecordNumber
= 0;
265 *OldestRecordNumber
= LogfGetOldestRecord(lpLogHandle
->LogFile
);
266 return STATUS_SUCCESS
;
271 NTSTATUS
ElfrChangeNotify(
272 IELF_HANDLE
*LogHandle
,
273 RPC_CLIENT_ID ClientId
,
277 return STATUS_NOT_IMPLEMENTED
;
282 NTSTATUS
ElfrOpenELW(
283 EVENTLOG_HANDLE_W UNCServerName
,
284 PRPC_UNICODE_STRING ModuleName
,
285 PRPC_UNICODE_STRING RegModuleName
,
288 IELF_HANDLE
*LogHandle
)
290 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
291 return STATUS_INVALID_PARAMETER
;
293 /* RegModuleName must be an empty string */
294 if (RegModuleName
->Length
> 0)
295 return STATUS_INVALID_PARAMETER
;
297 /*FIXME: UNCServerName must specify the server */
299 /*FIXME: Must verify that caller has read access */
301 *LogHandle
= ElfCreateEventLogHandle(ModuleName
->Buffer
, FALSE
);
303 if (*LogHandle
== NULL
)
305 return STATUS_INVALID_PARAMETER
;
308 return STATUS_SUCCESS
;
313 NTSTATUS
ElfrRegisterEventSourceW(
314 EVENTLOG_HANDLE_W UNCServerName
,
315 PRPC_UNICODE_STRING ModuleName
,
316 PRPC_UNICODE_STRING RegModuleName
,
319 IELF_HANDLE
*LogHandle
)
321 DPRINT("ElfrRegisterEventSourceW()\n");
323 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
324 return STATUS_INVALID_PARAMETER
;
326 /* RegModuleName must be an empty string */
327 if (RegModuleName
->Length
> 0)
328 return STATUS_INVALID_PARAMETER
;
330 DPRINT("ModuleName: %S\n", ModuleName
->Buffer
);
332 /*FIXME: UNCServerName must specify the server or empty for local */
334 /*FIXME: Must verify that caller has write access */
336 *LogHandle
= ElfCreateEventLogHandle(ModuleName
->Buffer
, TRUE
);
338 return STATUS_SUCCESS
;
343 NTSTATUS
ElfrOpenBELW(
344 EVENTLOG_HANDLE_W UNCServerName
,
345 PRPC_UNICODE_STRING BackupFileName
,
348 IELF_HANDLE
*LogHandle
)
351 return STATUS_NOT_IMPLEMENTED
;
356 NTSTATUS
ElfrReadELW(
357 IELF_HANDLE LogHandle
,
360 RULONG NumberOfBytesToRead
,
362 DWORD
*NumberOfBytesRead
,
363 DWORD
*MinNumberOfBytesNeeded
)
365 PLOGHANDLE lpLogHandle
;
369 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
372 return STATUS_INVALID_HANDLE
;
376 return I_RpcMapWin32Status(ERROR_INVALID_PARAMETER
);
378 /* If sequential read, retrieve the CurrentRecord from this log handle */
379 if (ReadFlags
& EVENTLOG_SEQUENTIAL_READ
)
381 RecordNumber
= lpLogHandle
->CurrentRecord
;
385 RecordNumber
= RecordOffset
;
388 dwError
= LogfReadEvent(lpLogHandle
->LogFile
, ReadFlags
, &RecordNumber
,
389 NumberOfBytesToRead
, Buffer
, NumberOfBytesRead
, MinNumberOfBytesNeeded
);
391 /* Update the handles CurrentRecord if success*/
392 if (dwError
== ERROR_SUCCESS
)
394 lpLogHandle
->CurrentRecord
= RecordNumber
;
397 return I_RpcMapWin32Status(dwError
);
402 NTSTATUS
ElfrReportEventW(
403 IELF_HANDLE LogHandle
,
406 USHORT EventCategory
,
410 PRPC_UNICODE_STRING ComputerName
,
412 PRPC_UNICODE_STRING Strings
[],
420 PLOGHANDLE lpLogHandle
;
423 DWORD dwStringsSize
= 0;
424 DWORD dwUserSidLength
= 0;
425 DWORD dwError
= ERROR_SUCCESS
;
429 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
432 return STATUS_INVALID_HANDLE
;
435 /* Flags must be 0 */
438 return STATUS_INVALID_PARAMETER
;
441 lastRec
= LogfGetCurrentRecord(lpLogHandle
->LogFile
);
443 for (i
= 0; i
< NumStrings
; i
++)
447 case EVENTLOG_SUCCESS
:
448 DPRINT("Success: %wZ\n", Strings
[i
]);
451 case EVENTLOG_ERROR_TYPE
:
452 DPRINT("Error: %wZ\n", Strings
[i
]);
455 case EVENTLOG_WARNING_TYPE
:
456 DPRINT("Warning: %wZ\n", Strings
[i
]);
459 case EVENTLOG_INFORMATION_TYPE
:
460 DPRINT("Info: %wZ\n", Strings
[i
]);
464 DPRINT1("Type %hu: %wZ\n", EventType
, Strings
[i
]);
467 dwStringsSize
+= Strings
[i
]->Length
+ sizeof UNICODE_NULL
;
470 lpStrings
= HeapAlloc(GetProcessHeap(), 0, dwStringsSize
);
473 DPRINT1("Failed to allocate heap\n");
474 return STATUS_NO_MEMORY
;
477 for (i
= 0; i
< NumStrings
; i
++)
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
);
486 dwUserSidLength
= FIELD_OFFSET(SID
, SubAuthority
[UserSID
->SubAuthorityCount
]);
487 LogBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
493 ComputerName
->Buffer
,
501 dwError
= LogfWriteData(lpLogHandle
->LogFile
, recSize
, LogBuffer
);
504 DPRINT1("ERROR WRITING TO EventLog %S\n", lpLogHandle
->LogFile
->FileName
);
507 LogfFreeRecord(LogBuffer
);
509 HeapFree(GetProcessHeap(), 0, lpStrings
);
511 return I_RpcMapWin32Status(dwError
);
516 NTSTATUS
ElfrClearELFA(
517 IELF_HANDLE LogHandle
,
518 PRPC_STRING BackupFileName
)
520 UNICODE_STRING BackupFileNameW
;
523 Status
= RtlAnsiStringToUnicodeString(&BackupFileNameW
,
524 (PANSI_STRING
)BackupFileName
,
526 if (!NT_SUCCESS(Status
))
529 Status
= ElfrClearELFW(LogHandle
,
530 (PRPC_UNICODE_STRING
)&BackupFileNameW
);
532 RtlFreeUnicodeString(&BackupFileNameW
);
539 NTSTATUS
ElfrBackupELFA(
540 IELF_HANDLE LogHandle
,
541 PRPC_STRING BackupFileName
)
544 return STATUS_NOT_IMPLEMENTED
;
549 NTSTATUS
ElfrOpenELA(
550 EVENTLOG_HANDLE_A UNCServerName
,
551 PRPC_STRING ModuleName
,
552 PRPC_STRING RegModuleName
,
555 IELF_HANDLE
*LogHandle
)
557 UNICODE_STRING ModuleNameW
;
560 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
561 return STATUS_INVALID_PARAMETER
;
563 /* RegModuleName must be an empty string */
564 if (RegModuleName
->Length
> 0)
565 return STATUS_INVALID_PARAMETER
;
567 Status
= RtlAnsiStringToUnicodeString(&ModuleNameW
, (PANSI_STRING
)ModuleName
, TRUE
);
568 if (!NT_SUCCESS(Status
))
571 /* FIXME: Must verify that caller has read access */
573 *LogHandle
= ElfCreateEventLogHandle(ModuleNameW
.Buffer
, FALSE
);
575 RtlFreeUnicodeString(&ModuleNameW
);
577 if (*LogHandle
== NULL
)
579 return STATUS_INVALID_PARAMETER
;
582 return STATUS_SUCCESS
;
587 NTSTATUS
ElfrRegisterEventSourceA(
588 EVENTLOG_HANDLE_A UNCServerName
,
589 PRPC_STRING ModuleName
,
590 PRPC_STRING RegModuleName
,
593 IELF_HANDLE
*LogHandle
)
595 UNICODE_STRING ModuleNameW
;
598 Status
= RtlAnsiStringToUnicodeString(&ModuleNameW
,
599 (PANSI_STRING
)ModuleName
,
601 if (!NT_SUCCESS(Status
))
603 DPRINT1("RtlAnsiStringToUnicodeString failed (Status 0x%08lx)\n", Status
);
607 /* RegModuleName must be an empty string */
608 if (RegModuleName
->Length
> 0)
610 RtlFreeUnicodeString(&ModuleNameW
);
611 return STATUS_INVALID_PARAMETER
;
614 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
616 RtlFreeUnicodeString(&ModuleNameW
);
617 return STATUS_INVALID_PARAMETER
;
620 /* FIXME: Must verify that caller has write access */
622 *LogHandle
= ElfCreateEventLogHandle(ModuleNameW
.Buffer
,
625 RtlFreeUnicodeString(&ModuleNameW
);
627 return STATUS_SUCCESS
;
632 NTSTATUS
ElfrOpenBELA(
633 EVENTLOG_HANDLE_A UNCServerName
,
634 PRPC_STRING BackupFileName
,
637 IELF_HANDLE
*LogHandle
)
640 return STATUS_NOT_IMPLEMENTED
;
645 NTSTATUS
ElfrReadELA(
646 IELF_HANDLE LogHandle
,
649 RULONG NumberOfBytesToRead
,
651 DWORD
*NumberOfBytesRead
,
652 DWORD
*MinNumberOfBytesNeeded
)
655 return STATUS_NOT_IMPLEMENTED
;
660 NTSTATUS
ElfrReportEventA(
661 IELF_HANDLE LogHandle
,
664 USHORT EventCategory
,
668 PRPC_STRING ComputerName
,
670 PRPC_STRING Strings
[],
677 return STATUS_NOT_IMPLEMENTED
;
682 NTSTATUS
ElfrRegisterClusterSvc(
683 handle_t BindingHandle
)
686 return STATUS_NOT_IMPLEMENTED
;
691 NTSTATUS
ElfrDeregisterClusterSvc(
692 handle_t BindingHandle
)
695 return STATUS_NOT_IMPLEMENTED
;
700 NTSTATUS
ElfrWriteClusterEvents(
701 handle_t BindingHandle
)
704 return STATUS_NOT_IMPLEMENTED
;
709 NTSTATUS
ElfrGetLogInformation(
710 IELF_HANDLE LogHandle
,
714 DWORD
*pcbBytesNeeded
)
716 NTSTATUS Status
= STATUS_SUCCESS
;
718 /* FIXME: check handle first */
722 case EVENTLOG_FULL_INFO
:
724 LPEVENTLOG_FULL_INFORMATION efi
= (LPEVENTLOG_FULL_INFORMATION
)Buffer
;
726 *pcbBytesNeeded
= sizeof(EVENTLOG_FULL_INFORMATION
);
727 if (cbBufSize
< sizeof(EVENTLOG_FULL_INFORMATION
))
729 return STATUS_BUFFER_TOO_SMALL
;
732 efi
->dwFull
= 0; /* FIXME */
737 Status
= STATUS_INVALID_LEVEL
;
746 NTSTATUS
ElfrFlushEL(
747 IELF_HANDLE LogHandle
)
750 return STATUS_NOT_IMPLEMENTED
;
755 NTSTATUS
ElfrReportEventAndSourceW(
756 IELF_HANDLE LogHandle
,
759 USHORT EventCategory
,
761 PRPC_UNICODE_STRING SourceName
,
764 PRPC_UNICODE_STRING ComputerName
,
766 PRPC_UNICODE_STRING Strings
[],
773 return STATUS_NOT_IMPLEMENTED
;
777 void __RPC_FAR
*__RPC_USER
midl_user_allocate(SIZE_T len
)
779 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
783 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
785 HeapFree(GetProcessHeap(), 0, ptr
);
789 void __RPC_USER
IELF_HANDLE_rundown(IELF_HANDLE LogHandle
)