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 EventSourceListHead
;
16 /* FUNCTIONS ****************************************************************/
18 DWORD WINAPI
RpcThreadRoutine(LPVOID lpParameter
)
22 InitializeListHead(&EventSourceListHead
);
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 PEVENTSOURCE
ElfCreateEventLogHandle(LPCWSTR Name
, BOOL Create
)
49 PEVENTSOURCE lpEventSource
;
50 PLOGFILE currentLogFile
= NULL
;
53 lpEventSource
= HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTSOURCE
)
54 + ((wcslen(Name
) + 1) * sizeof(WCHAR
)));
57 DPRINT1("Failed to allocate Heap!\n");
61 wcscpy(lpEventSource
->szName
, Name
);
63 /* Get the number of Log Files the EventLog service found */
64 LogsActive
= LogfListItemCount();
67 DPRINT1("EventLog service reports no log files!\n");
71 /* If Creating, default to the Application Log in case we fail, as documented on MSDN */
73 lpEventSource
->LogFile
= LogfListItemByName(L
"Application");
75 lpEventSource
->LogFile
= NULL
;
77 for (i
= 1; i
<= LogsActive
; i
++)
79 currentLogFile
= LogfListItemByIndex(i
);
81 if (_wcsicmp(Name
, currentLogFile
->LogName
) == 0)
83 lpEventSource
->LogFile
= LogfListItemByIndex(i
);
84 lpEventSource
->CurrentRecord
= LogfGetOldestRecord(lpEventSource
->LogFile
);
89 if (!lpEventSource
->LogFile
)
92 /* Append service record */
93 InsertTailList(&EventSourceListHead
, &lpEventSource
->EventSourceListEntry
);
98 HeapFree(GetProcessHeap(), 0, lpEventSource
);
103 PEVENTSOURCE
ElfGetEventLogSourceEntryByHandle(IELF_HANDLE EventLogHandle
)
105 PEVENTSOURCE CurrentEventSource
;
107 if (IsListEmpty(&EventSourceListHead
))
111 CurrentEventSource
= CONTAINING_RECORD((PEVENTSOURCE
)EventLogHandle
, EVENTSOURCE
, EventSourceListEntry
);
113 return CurrentEventSource
;
116 BOOL
ElfDeleteEventLogHandle(IELF_HANDLE EventLogHandle
)
118 PEVENTSOURCE lpEventSource
= (PEVENTSOURCE
)EventLogHandle
;
119 if (!ElfGetEventLogSourceEntryByHandle(lpEventSource
))
124 RemoveEntryList(&lpEventSource
->EventSourceListEntry
);
125 HeapFree(GetProcessHeap(),0,lpEventSource
);
131 NTSTATUS
ElfrClearELFW(
132 IELF_HANDLE LogHandle
,
133 PRPC_UNICODE_STRING BackupFileName
)
136 return STATUS_NOT_IMPLEMENTED
;
141 NTSTATUS
ElfrBackupELFW(
142 IELF_HANDLE LogHandle
,
143 PRPC_UNICODE_STRING BackupFileName
)
146 return STATUS_NOT_IMPLEMENTED
;
150 NTSTATUS
ElfrCloseEL(
151 IELF_HANDLE
*LogHandle
)
153 if (!ElfDeleteEventLogHandle(*LogHandle
))
155 return STATUS_INVALID_HANDLE
;
158 return STATUS_SUCCESS
;
163 NTSTATUS
ElfrDeregisterEventSource(
164 IELF_HANDLE
*LogHandle
)
166 if (!ElfDeleteEventLogHandle(*LogHandle
))
168 return STATUS_INVALID_HANDLE
;
171 return STATUS_SUCCESS
;
176 NTSTATUS
ElfrNumberOfRecords(
177 IELF_HANDLE LogHandle
,
178 DWORD
*NumberOfRecords
)
180 PEVENTSOURCE lpEventSource
;
182 lpEventSource
= ElfGetEventLogSourceEntryByHandle(LogHandle
);
185 return STATUS_INVALID_HANDLE
;
188 *NumberOfRecords
= lpEventSource
->LogFile
->Header
.CurrentRecordNumber
;
190 return STATUS_SUCCESS
;
195 NTSTATUS
ElfrOldestRecord(
196 IELF_HANDLE LogHandle
,
197 DWORD
*OldestRecordNumber
)
199 PEVENTSOURCE lpEventSource
;
201 lpEventSource
= ElfGetEventLogSourceEntryByHandle(LogHandle
);
204 return STATUS_INVALID_HANDLE
;
207 if (!OldestRecordNumber
)
209 return STATUS_INVALID_PARAMETER
;
212 *OldestRecordNumber
= 0;
213 *OldestRecordNumber
= LogfGetOldestRecord(lpEventSource
->LogFile
);
214 return STATUS_SUCCESS
;
219 NTSTATUS
ElfrChangeNotify(
220 IELF_HANDLE
*LogHandle
,
221 RPC_CLIENT_ID ClientId
,
225 return STATUS_NOT_IMPLEMENTED
;
230 NTSTATUS
ElfrOpenELW(
231 EVENTLOG_HANDLE_W UNCServerName
,
232 PRPC_UNICODE_STRING ModuleName
,
233 PRPC_UNICODE_STRING RegModuleName
,
236 IELF_HANDLE
*LogHandle
)
238 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
239 return STATUS_INVALID_PARAMETER
;
241 /* RegModuleName must be an empty string */
242 if (RegModuleName
->Length
> 0)
243 return STATUS_INVALID_PARAMETER
;
245 /*FIXME: UNCServerName must specify the server */
247 /*FIXME: Must verify that caller has read access */
249 *LogHandle
= ElfCreateEventLogHandle(ModuleName
->Buffer
, FALSE
);
251 if (*LogHandle
== NULL
)
253 return STATUS_INVALID_PARAMETER
;
256 return STATUS_SUCCESS
;
261 NTSTATUS
ElfrRegisterEventSourceW(
262 EVENTLOG_HANDLE_W UNCServerName
,
263 PRPC_UNICODE_STRING ModuleName
,
264 PRPC_UNICODE_STRING RegModuleName
,
267 IELF_HANDLE
*LogHandle
)
269 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
270 return STATUS_INVALID_PARAMETER
;
272 /* RegModuleName must be an empty string */
273 if (RegModuleName
->Length
> 0)
274 return STATUS_INVALID_PARAMETER
;
276 /*FIXME: UNCServerName must specify the server or empty for local */
278 /*FIXME: Must verify that caller has write access */
280 *LogHandle
= ElfCreateEventLogHandle(ModuleName
->Buffer
, TRUE
);
282 return STATUS_SUCCESS
;
287 NTSTATUS
ElfrOpenBELW(
288 EVENTLOG_HANDLE_W UNCServerName
,
289 PRPC_UNICODE_STRING BackupFileName
,
292 IELF_HANDLE
*LogHandle
)
295 return STATUS_NOT_IMPLEMENTED
;
300 NTSTATUS
ElfrReadELW(
301 IELF_HANDLE LogHandle
,
304 RULONG NumberOfBytesToRead
,
306 DWORD
*NumberOfBytesRead
,
307 DWORD
*MinNumberOfBytesNeeded
)
309 PEVENTSOURCE lpEventSource
;
313 lpEventSource
= ElfGetEventLogSourceEntryByHandle(LogHandle
);
316 return STATUS_INVALID_HANDLE
;
320 return I_RpcMapWin32Status(ERROR_INVALID_PARAMETER
);
322 /* If sequential read, retrieve the CurrentRecord from this log handle */
323 if (ReadFlags
& EVENTLOG_SEQUENTIAL_READ
)
325 RecordNumber
= lpEventSource
->CurrentRecord
;
329 RecordNumber
= RecordOffset
;
332 dwError
= LogfReadEvent(lpEventSource
->LogFile
, ReadFlags
, &RecordNumber
,
333 NumberOfBytesToRead
, Buffer
, NumberOfBytesRead
, MinNumberOfBytesNeeded
);
335 /* Update the handles CurrentRecord if success*/
336 if (dwError
== ERROR_SUCCESS
)
338 lpEventSource
->CurrentRecord
= RecordNumber
;
341 return I_RpcMapWin32Status(dwError
);
346 NTSTATUS
ElfrReportEventW(
347 IELF_HANDLE LogHandle
,
350 USHORT EventCategory
,
354 PRPC_UNICODE_STRING ComputerName
,
356 PRPC_UNICODE_STRING Strings
[],
364 PEVENTSOURCE lpEventSource
;
367 DWORD dwStringsSize
= 0;
368 DWORD dwError
= ERROR_SUCCESS
;
372 lpEventSource
= ElfGetEventLogSourceEntryByHandle(LogHandle
);
375 return STATUS_INVALID_HANDLE
;
378 /* Flags must be 0 */
381 return STATUS_INVALID_PARAMETER
;
384 lastRec
= LogfGetCurrentRecord(lpEventSource
->LogFile
);
386 for (i
= 0; i
< NumStrings
; i
++)
390 case EVENTLOG_SUCCESS
:
391 DPRINT("Success: %wZ\n", Strings
[i
]);
394 case EVENTLOG_ERROR_TYPE
:
395 DPRINT("Error: %wZ\n", Strings
[i
]);
398 case EVENTLOG_WARNING_TYPE
:
399 DPRINT("Warning: %wZ\n", Strings
[i
]);
402 case EVENTLOG_INFORMATION_TYPE
:
403 DPRINT("Info: %wZ\n", Strings
[i
]);
407 DPRINT1("Type %hu: %wZ\n", EventType
, Strings
[i
]);
410 dwStringsSize
+= (wcslen(Strings
[i
]->Buffer
) + 1) * sizeof(WCHAR
);
413 lpStrings
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
, dwStringsSize
* 2);
416 DPRINT1("Failed to allocate heap\n");
417 return STATUS_NO_MEMORY
;
420 for (i
= 0; i
< NumStrings
; i
++)
422 wcscpy((WCHAR
*)(lpStrings
+ pos
), Strings
[i
]->Buffer
);
423 pos
+= (wcslen(Strings
[i
]->Buffer
) + 1) * sizeof(WCHAR
);
426 LogBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
431 lpEventSource
->szName
,
432 ComputerName
->Buffer
,
440 dwError
= LogfWriteData(lpEventSource
->LogFile
, recSize
, LogBuffer
);
443 DPRINT1("ERROR WRITING TO EventLog %S\n",lpEventSource
->LogFile
->FileName
);
446 LogfFreeRecord(LogBuffer
);
448 HeapFree(GetProcessHeap(), 0, lpStrings
);
450 return I_RpcMapWin32Status(dwError
);
455 NTSTATUS
ElfrClearELFA(
456 IELF_HANDLE LogHandle
,
457 PRPC_STRING BackupFileName
)
460 return STATUS_NOT_IMPLEMENTED
;
465 NTSTATUS
ElfrBackupELFA(
466 IELF_HANDLE LogHandle
,
467 PRPC_STRING BackupFileName
)
470 return STATUS_NOT_IMPLEMENTED
;
475 NTSTATUS
ElfrOpenELA(
476 EVENTLOG_HANDLE_A UNCServerName
,
477 PRPC_STRING ModuleName
,
478 PRPC_STRING RegModuleName
,
481 IELF_HANDLE
*LogHandle
)
483 UNICODE_STRING ModuleNameW
;
485 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
486 return STATUS_INVALID_PARAMETER
;
488 /* RegModuleName must be an empty string */
489 if (RegModuleName
->Length
> 0)
490 return STATUS_INVALID_PARAMETER
;
492 RtlAnsiStringToUnicodeString(&ModuleNameW
, (PANSI_STRING
)ModuleName
, TRUE
);
494 /* FIXME: Must verify that caller has read access */
496 *LogHandle
= ElfCreateEventLogHandle(ModuleNameW
.Buffer
, FALSE
);
498 RtlFreeUnicodeString(&ModuleNameW
);
500 if (*LogHandle
== NULL
)
502 return STATUS_INVALID_PARAMETER
;
505 return STATUS_SUCCESS
;
510 NTSTATUS
ElfrRegisterEventSourceA(
511 EVENTLOG_HANDLE_A UNCServerName
,
512 PRPC_STRING ModuleName
,
513 PRPC_STRING RegModuleName
,
516 IELF_HANDLE
*LogHandle
)
518 UNICODE_STRING ModuleNameW
= { 0, 0, NULL
};
521 !RtlAnsiStringToUnicodeString(&ModuleNameW
, (PANSI_STRING
)ModuleName
, TRUE
))
523 return STATUS_NO_MEMORY
;
526 /* RegModuleName must be an empty string */
527 if (RegModuleName
->Length
> 0)
529 RtlFreeUnicodeString(&ModuleNameW
);
530 return STATUS_INVALID_PARAMETER
;
533 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
535 RtlFreeUnicodeString(&ModuleNameW
);
536 return STATUS_INVALID_PARAMETER
;
539 /* FIXME: Must verify that caller has write access */
541 *LogHandle
= ElfCreateEventLogHandle(ModuleNameW
.Buffer
,
544 RtlFreeUnicodeString(&ModuleNameW
);
546 return STATUS_SUCCESS
;
551 NTSTATUS
ElfrOpenBELA(
552 EVENTLOG_HANDLE_A UNCServerName
,
553 PRPC_STRING BackupFileName
,
556 IELF_HANDLE
*LogHandle
)
559 return STATUS_NOT_IMPLEMENTED
;
564 NTSTATUS
ElfrReadELA(
565 IELF_HANDLE LogHandle
,
568 RULONG NumberOfBytesToRead
,
570 DWORD
*NumberOfBytesRead
,
571 DWORD
*MinNumberOfBytesNeeded
)
574 return STATUS_NOT_IMPLEMENTED
;
579 NTSTATUS
ElfrReportEventA(
580 IELF_HANDLE LogHandle
,
583 USHORT EventCategory
,
587 PRPC_STRING ComputerName
,
589 PRPC_STRING Strings
[],
596 return STATUS_NOT_IMPLEMENTED
;
601 NTSTATUS
ElfrRegisterClusterSvc(
602 handle_t BindingHandle
)
605 return STATUS_NOT_IMPLEMENTED
;
610 NTSTATUS
ElfrDeregisterClusterSvc(
611 handle_t BindingHandle
)
614 return STATUS_NOT_IMPLEMENTED
;
619 NTSTATUS
ElfrWriteClusterEvents(
620 handle_t BindingHandle
)
623 return STATUS_NOT_IMPLEMENTED
;
628 NTSTATUS
ElfrGetLogInformation(
629 IELF_HANDLE LogHandle
,
633 DWORD
*pcbBytesNeeded
)
635 NTSTATUS Status
= STATUS_SUCCESS
;
637 /* FIXME: check handle first */
641 case EVENTLOG_FULL_INFO
:
643 LPEVENTLOG_FULL_INFORMATION efi
= (LPEVENTLOG_FULL_INFORMATION
)Buffer
;
645 *pcbBytesNeeded
= sizeof(EVENTLOG_FULL_INFORMATION
);
646 if (cbBufSize
< sizeof(EVENTLOG_FULL_INFORMATION
))
648 return STATUS_BUFFER_TOO_SMALL
;
651 efi
->dwFull
= 0; /* FIXME */
656 Status
= STATUS_INVALID_LEVEL
;
665 NTSTATUS
ElfrFlushEL(
666 IELF_HANDLE LogHandle
)
669 return STATUS_NOT_IMPLEMENTED
;
674 NTSTATUS
ElfrReportEventAndSourceW(
675 IELF_HANDLE LogHandle
,
678 USHORT EventCategory
,
680 PRPC_UNICODE_STRING SourceName
,
683 PRPC_UNICODE_STRING ComputerName
,
685 PRPC_UNICODE_STRING Strings
[],
692 return STATUS_NOT_IMPLEMENTED
;
696 void __RPC_FAR
*__RPC_USER
midl_user_allocate(SIZE_T len
)
698 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
702 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
704 HeapFree(GetProcessHeap(), 0, ptr
);
708 void __RPC_USER
IELF_HANDLE_rundown(IELF_HANDLE LogHandle
)