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
)
164 return STATUS_NOT_IMPLEMENTED
;
169 NTSTATUS
ElfrBackupELFW(
170 IELF_HANDLE LogHandle
,
171 PRPC_UNICODE_STRING BackupFileName
)
174 return STATUS_NOT_IMPLEMENTED
;
178 NTSTATUS
ElfrCloseEL(
179 IELF_HANDLE
*LogHandle
)
181 if (!ElfDeleteEventLogHandle(*LogHandle
))
183 return STATUS_INVALID_HANDLE
;
186 return STATUS_SUCCESS
;
191 NTSTATUS
ElfrDeregisterEventSource(
192 IELF_HANDLE
*LogHandle
)
194 if (!ElfDeleteEventLogHandle(*LogHandle
))
196 return STATUS_INVALID_HANDLE
;
199 return STATUS_SUCCESS
;
204 NTSTATUS
ElfrNumberOfRecords(
205 IELF_HANDLE LogHandle
,
206 DWORD
*NumberOfRecords
)
208 PLOGHANDLE lpLogHandle
;
211 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
214 return STATUS_INVALID_HANDLE
;
217 lpLogFile
= lpLogHandle
->LogFile
;
219 if (lpLogFile
->Header
.OldestRecordNumber
== 0)
220 *NumberOfRecords
= 0;
222 *NumberOfRecords
= lpLogFile
->Header
.CurrentRecordNumber
-
223 lpLogFile
->Header
.OldestRecordNumber
;
225 return STATUS_SUCCESS
;
230 NTSTATUS
ElfrOldestRecord(
231 IELF_HANDLE LogHandle
,
232 DWORD
*OldestRecordNumber
)
234 PLOGHANDLE lpLogHandle
;
236 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
239 return STATUS_INVALID_HANDLE
;
242 if (!OldestRecordNumber
)
244 return STATUS_INVALID_PARAMETER
;
247 *OldestRecordNumber
= 0;
248 *OldestRecordNumber
= LogfGetOldestRecord(lpLogHandle
->LogFile
);
249 return STATUS_SUCCESS
;
254 NTSTATUS
ElfrChangeNotify(
255 IELF_HANDLE
*LogHandle
,
256 RPC_CLIENT_ID ClientId
,
260 return STATUS_NOT_IMPLEMENTED
;
265 NTSTATUS
ElfrOpenELW(
266 EVENTLOG_HANDLE_W UNCServerName
,
267 PRPC_UNICODE_STRING ModuleName
,
268 PRPC_UNICODE_STRING RegModuleName
,
271 IELF_HANDLE
*LogHandle
)
273 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
274 return STATUS_INVALID_PARAMETER
;
276 /* RegModuleName must be an empty string */
277 if (RegModuleName
->Length
> 0)
278 return STATUS_INVALID_PARAMETER
;
280 /*FIXME: UNCServerName must specify the server */
282 /*FIXME: Must verify that caller has read access */
284 *LogHandle
= ElfCreateEventLogHandle(ModuleName
->Buffer
, FALSE
);
286 if (*LogHandle
== NULL
)
288 return STATUS_INVALID_PARAMETER
;
291 return STATUS_SUCCESS
;
296 NTSTATUS
ElfrRegisterEventSourceW(
297 EVENTLOG_HANDLE_W UNCServerName
,
298 PRPC_UNICODE_STRING ModuleName
,
299 PRPC_UNICODE_STRING RegModuleName
,
302 IELF_HANDLE
*LogHandle
)
304 DPRINT1("ElfrRegisterEventSourceW()\n");
306 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
307 return STATUS_INVALID_PARAMETER
;
309 /* RegModuleName must be an empty string */
310 if (RegModuleName
->Length
> 0)
311 return STATUS_INVALID_PARAMETER
;
313 DPRINT1("ModuleName: %S\n", ModuleName
->Buffer
);
315 /*FIXME: UNCServerName must specify the server or empty for local */
317 /*FIXME: Must verify that caller has write access */
319 *LogHandle
= ElfCreateEventLogHandle(ModuleName
->Buffer
, TRUE
);
321 return STATUS_SUCCESS
;
326 NTSTATUS
ElfrOpenBELW(
327 EVENTLOG_HANDLE_W UNCServerName
,
328 PRPC_UNICODE_STRING BackupFileName
,
331 IELF_HANDLE
*LogHandle
)
334 return STATUS_NOT_IMPLEMENTED
;
339 NTSTATUS
ElfrReadELW(
340 IELF_HANDLE LogHandle
,
343 RULONG NumberOfBytesToRead
,
345 DWORD
*NumberOfBytesRead
,
346 DWORD
*MinNumberOfBytesNeeded
)
348 PLOGHANDLE lpLogHandle
;
352 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
355 return STATUS_INVALID_HANDLE
;
359 return I_RpcMapWin32Status(ERROR_INVALID_PARAMETER
);
361 /* If sequential read, retrieve the CurrentRecord from this log handle */
362 if (ReadFlags
& EVENTLOG_SEQUENTIAL_READ
)
364 RecordNumber
= lpLogHandle
->CurrentRecord
;
368 RecordNumber
= RecordOffset
;
371 dwError
= LogfReadEvent(lpLogHandle
->LogFile
, ReadFlags
, &RecordNumber
,
372 NumberOfBytesToRead
, Buffer
, NumberOfBytesRead
, MinNumberOfBytesNeeded
);
374 /* Update the handles CurrentRecord if success*/
375 if (dwError
== ERROR_SUCCESS
)
377 lpLogHandle
->CurrentRecord
= RecordNumber
;
380 return I_RpcMapWin32Status(dwError
);
385 NTSTATUS
ElfrReportEventW(
386 IELF_HANDLE LogHandle
,
389 USHORT EventCategory
,
393 PRPC_UNICODE_STRING ComputerName
,
395 PRPC_UNICODE_STRING Strings
[],
403 PLOGHANDLE lpLogHandle
;
406 DWORD dwStringsSize
= 0;
407 DWORD dwUserSidLength
= 0;
408 DWORD dwError
= ERROR_SUCCESS
;
412 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
415 return STATUS_INVALID_HANDLE
;
418 /* Flags must be 0 */
421 return STATUS_INVALID_PARAMETER
;
424 lastRec
= LogfGetCurrentRecord(lpLogHandle
->LogFile
);
426 for (i
= 0; i
< NumStrings
; i
++)
430 case EVENTLOG_SUCCESS
:
431 DPRINT("Success: %wZ\n", Strings
[i
]);
434 case EVENTLOG_ERROR_TYPE
:
435 DPRINT("Error: %wZ\n", Strings
[i
]);
438 case EVENTLOG_WARNING_TYPE
:
439 DPRINT("Warning: %wZ\n", Strings
[i
]);
442 case EVENTLOG_INFORMATION_TYPE
:
443 DPRINT("Info: %wZ\n", Strings
[i
]);
447 DPRINT1("Type %hu: %wZ\n", EventType
, Strings
[i
]);
450 dwStringsSize
+= Strings
[i
]->Length
+ sizeof UNICODE_NULL
;
453 lpStrings
= HeapAlloc(GetProcessHeap(), 0, dwStringsSize
);
456 DPRINT1("Failed to allocate heap\n");
457 return STATUS_NO_MEMORY
;
460 for (i
= 0; i
< NumStrings
; i
++)
462 CopyMemory(lpStrings
+ pos
, Strings
[i
]->Buffer
, Strings
[i
]->Length
);
463 pos
+= Strings
[i
]->Length
/ sizeof(WCHAR
);
464 lpStrings
[pos
] = UNICODE_NULL
;
465 pos
+= sizeof UNICODE_NULL
/ sizeof(WCHAR
);
469 dwUserSidLength
= FIELD_OFFSET(SID
, SubAuthority
[UserSID
->SubAuthorityCount
]);
470 LogBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
476 ComputerName
->Buffer
,
484 dwError
= LogfWriteData(lpLogHandle
->LogFile
, recSize
, LogBuffer
);
487 DPRINT1("ERROR WRITING TO EventLog %S\n", lpLogHandle
->LogFile
->FileName
);
490 LogfFreeRecord(LogBuffer
);
492 HeapFree(GetProcessHeap(), 0, lpStrings
);
494 return I_RpcMapWin32Status(dwError
);
499 NTSTATUS
ElfrClearELFA(
500 IELF_HANDLE LogHandle
,
501 PRPC_STRING BackupFileName
)
504 return STATUS_NOT_IMPLEMENTED
;
509 NTSTATUS
ElfrBackupELFA(
510 IELF_HANDLE LogHandle
,
511 PRPC_STRING BackupFileName
)
514 return STATUS_NOT_IMPLEMENTED
;
519 NTSTATUS
ElfrOpenELA(
520 EVENTLOG_HANDLE_A UNCServerName
,
521 PRPC_STRING ModuleName
,
522 PRPC_STRING RegModuleName
,
525 IELF_HANDLE
*LogHandle
)
527 UNICODE_STRING ModuleNameW
;
529 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
530 return STATUS_INVALID_PARAMETER
;
532 /* RegModuleName must be an empty string */
533 if (RegModuleName
->Length
> 0)
534 return STATUS_INVALID_PARAMETER
;
536 RtlAnsiStringToUnicodeString(&ModuleNameW
, (PANSI_STRING
)ModuleName
, TRUE
);
538 /* FIXME: Must verify that caller has read access */
540 *LogHandle
= ElfCreateEventLogHandle(ModuleNameW
.Buffer
, FALSE
);
542 RtlFreeUnicodeString(&ModuleNameW
);
544 if (*LogHandle
== NULL
)
546 return STATUS_INVALID_PARAMETER
;
549 return STATUS_SUCCESS
;
554 NTSTATUS
ElfrRegisterEventSourceA(
555 EVENTLOG_HANDLE_A UNCServerName
,
556 PRPC_STRING ModuleName
,
557 PRPC_STRING RegModuleName
,
560 IELF_HANDLE
*LogHandle
)
562 UNICODE_STRING ModuleNameW
= { 0, 0, NULL
};
565 !RtlAnsiStringToUnicodeString(&ModuleNameW
, (PANSI_STRING
)ModuleName
, TRUE
))
567 return STATUS_NO_MEMORY
;
570 /* RegModuleName must be an empty string */
571 if (RegModuleName
->Length
> 0)
573 RtlFreeUnicodeString(&ModuleNameW
);
574 return STATUS_INVALID_PARAMETER
;
577 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
579 RtlFreeUnicodeString(&ModuleNameW
);
580 return STATUS_INVALID_PARAMETER
;
583 /* FIXME: Must verify that caller has write access */
585 *LogHandle
= ElfCreateEventLogHandle(ModuleNameW
.Buffer
,
588 RtlFreeUnicodeString(&ModuleNameW
);
590 return STATUS_SUCCESS
;
595 NTSTATUS
ElfrOpenBELA(
596 EVENTLOG_HANDLE_A UNCServerName
,
597 PRPC_STRING BackupFileName
,
600 IELF_HANDLE
*LogHandle
)
603 return STATUS_NOT_IMPLEMENTED
;
608 NTSTATUS
ElfrReadELA(
609 IELF_HANDLE LogHandle
,
612 RULONG NumberOfBytesToRead
,
614 DWORD
*NumberOfBytesRead
,
615 DWORD
*MinNumberOfBytesNeeded
)
618 return STATUS_NOT_IMPLEMENTED
;
623 NTSTATUS
ElfrReportEventA(
624 IELF_HANDLE LogHandle
,
627 USHORT EventCategory
,
631 PRPC_STRING ComputerName
,
633 PRPC_STRING Strings
[],
640 return STATUS_NOT_IMPLEMENTED
;
645 NTSTATUS
ElfrRegisterClusterSvc(
646 handle_t BindingHandle
)
649 return STATUS_NOT_IMPLEMENTED
;
654 NTSTATUS
ElfrDeregisterClusterSvc(
655 handle_t BindingHandle
)
658 return STATUS_NOT_IMPLEMENTED
;
663 NTSTATUS
ElfrWriteClusterEvents(
664 handle_t BindingHandle
)
667 return STATUS_NOT_IMPLEMENTED
;
672 NTSTATUS
ElfrGetLogInformation(
673 IELF_HANDLE LogHandle
,
677 DWORD
*pcbBytesNeeded
)
679 NTSTATUS Status
= STATUS_SUCCESS
;
681 /* FIXME: check handle first */
685 case EVENTLOG_FULL_INFO
:
687 LPEVENTLOG_FULL_INFORMATION efi
= (LPEVENTLOG_FULL_INFORMATION
)Buffer
;
689 *pcbBytesNeeded
= sizeof(EVENTLOG_FULL_INFORMATION
);
690 if (cbBufSize
< sizeof(EVENTLOG_FULL_INFORMATION
))
692 return STATUS_BUFFER_TOO_SMALL
;
695 efi
->dwFull
= 0; /* FIXME */
700 Status
= STATUS_INVALID_LEVEL
;
709 NTSTATUS
ElfrFlushEL(
710 IELF_HANDLE LogHandle
)
713 return STATUS_NOT_IMPLEMENTED
;
718 NTSTATUS
ElfrReportEventAndSourceW(
719 IELF_HANDLE LogHandle
,
722 USHORT EventCategory
,
724 PRPC_UNICODE_STRING SourceName
,
727 PRPC_UNICODE_STRING ComputerName
,
729 PRPC_UNICODE_STRING Strings
[],
736 return STATUS_NOT_IMPLEMENTED
;
740 void __RPC_FAR
*__RPC_USER
midl_user_allocate(SIZE_T len
)
742 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
746 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
748 HeapFree(GetProcessHeap(), 0, ptr
);
752 void __RPC_USER
IELF_HANDLE_rundown(IELF_HANDLE LogHandle
)