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
;
53 lpLogHandle
= HeapAlloc(GetProcessHeap(), 0, sizeof(LOGHANDLE
)
54 + ((wcslen(Name
) + 1) * sizeof(WCHAR
)));
57 DPRINT1("Failed to allocate Heap!\n");
61 wcscpy(lpLogHandle
->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 lpLogHandle
->LogFile
= LogfListItemByName(L
"Application");
75 lpLogHandle
->LogFile
= NULL
;
77 for (i
= 1; i
<= LogsActive
; i
++)
79 currentLogFile
= LogfListItemByIndex(i
);
81 if (_wcsicmp(Name
, currentLogFile
->LogName
) == 0)
83 lpLogHandle
->LogFile
= LogfListItemByIndex(i
);
84 lpLogHandle
->CurrentRecord
= LogfGetOldestRecord(lpLogHandle
->LogFile
);
89 if (!lpLogHandle
->LogFile
)
92 /* Append log handle */
93 InsertTailList(&LogHandleListHead
, &lpLogHandle
->LogHandleListEntry
);
98 HeapFree(GetProcessHeap(), 0, lpLogHandle
);
103 PLOGHANDLE
ElfGetLogHandleEntryByHandle(IELF_HANDLE EventLogHandle
)
105 PLOGHANDLE lpLogHandle
;
107 if (IsListEmpty(&LogHandleListHead
))
112 lpLogHandle
= CONTAINING_RECORD((PLOGHANDLE
)EventLogHandle
, LOGHANDLE
, LogHandleListEntry
);
117 BOOL
ElfDeleteEventLogHandle(IELF_HANDLE EventLogHandle
)
119 PLOGHANDLE lpLogHandle
= (PLOGHANDLE
)EventLogHandle
;
120 if (!ElfGetLogHandleEntryByHandle(lpLogHandle
))
125 RemoveEntryList(&lpLogHandle
->LogHandleListEntry
);
126 HeapFree(GetProcessHeap(),0,lpLogHandle
);
132 NTSTATUS
ElfrClearELFW(
133 IELF_HANDLE LogHandle
,
134 PRPC_UNICODE_STRING BackupFileName
)
137 return STATUS_NOT_IMPLEMENTED
;
142 NTSTATUS
ElfrBackupELFW(
143 IELF_HANDLE LogHandle
,
144 PRPC_UNICODE_STRING BackupFileName
)
147 return STATUS_NOT_IMPLEMENTED
;
151 NTSTATUS
ElfrCloseEL(
152 IELF_HANDLE
*LogHandle
)
154 if (!ElfDeleteEventLogHandle(*LogHandle
))
156 return STATUS_INVALID_HANDLE
;
159 return STATUS_SUCCESS
;
164 NTSTATUS
ElfrDeregisterEventSource(
165 IELF_HANDLE
*LogHandle
)
167 if (!ElfDeleteEventLogHandle(*LogHandle
))
169 return STATUS_INVALID_HANDLE
;
172 return STATUS_SUCCESS
;
177 NTSTATUS
ElfrNumberOfRecords(
178 IELF_HANDLE LogHandle
,
179 DWORD
*NumberOfRecords
)
181 PLOGHANDLE lpLogHandle
;
183 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
186 return STATUS_INVALID_HANDLE
;
189 *NumberOfRecords
= lpLogHandle
->LogFile
->Header
.CurrentRecordNumber
;
191 return STATUS_SUCCESS
;
196 NTSTATUS
ElfrOldestRecord(
197 IELF_HANDLE LogHandle
,
198 DWORD
*OldestRecordNumber
)
200 PLOGHANDLE lpLogHandle
;
202 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
205 return STATUS_INVALID_HANDLE
;
208 if (!OldestRecordNumber
)
210 return STATUS_INVALID_PARAMETER
;
213 *OldestRecordNumber
= 0;
214 *OldestRecordNumber
= LogfGetOldestRecord(lpLogHandle
->LogFile
);
215 return STATUS_SUCCESS
;
220 NTSTATUS
ElfrChangeNotify(
221 IELF_HANDLE
*LogHandle
,
222 RPC_CLIENT_ID ClientId
,
226 return STATUS_NOT_IMPLEMENTED
;
231 NTSTATUS
ElfrOpenELW(
232 EVENTLOG_HANDLE_W UNCServerName
,
233 PRPC_UNICODE_STRING ModuleName
,
234 PRPC_UNICODE_STRING RegModuleName
,
237 IELF_HANDLE
*LogHandle
)
239 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
240 return STATUS_INVALID_PARAMETER
;
242 /* RegModuleName must be an empty string */
243 if (RegModuleName
->Length
> 0)
244 return STATUS_INVALID_PARAMETER
;
246 /*FIXME: UNCServerName must specify the server */
248 /*FIXME: Must verify that caller has read access */
250 *LogHandle
= ElfCreateEventLogHandle(ModuleName
->Buffer
, FALSE
);
252 if (*LogHandle
== NULL
)
254 return STATUS_INVALID_PARAMETER
;
257 return STATUS_SUCCESS
;
262 NTSTATUS
ElfrRegisterEventSourceW(
263 EVENTLOG_HANDLE_W UNCServerName
,
264 PRPC_UNICODE_STRING ModuleName
,
265 PRPC_UNICODE_STRING RegModuleName
,
268 IELF_HANDLE
*LogHandle
)
270 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
271 return STATUS_INVALID_PARAMETER
;
273 /* RegModuleName must be an empty string */
274 if (RegModuleName
->Length
> 0)
275 return STATUS_INVALID_PARAMETER
;
277 /*FIXME: UNCServerName must specify the server or empty for local */
279 /*FIXME: Must verify that caller has write access */
281 *LogHandle
= ElfCreateEventLogHandle(ModuleName
->Buffer
, TRUE
);
283 return STATUS_SUCCESS
;
288 NTSTATUS
ElfrOpenBELW(
289 EVENTLOG_HANDLE_W UNCServerName
,
290 PRPC_UNICODE_STRING BackupFileName
,
293 IELF_HANDLE
*LogHandle
)
296 return STATUS_NOT_IMPLEMENTED
;
301 NTSTATUS
ElfrReadELW(
302 IELF_HANDLE LogHandle
,
305 RULONG NumberOfBytesToRead
,
307 DWORD
*NumberOfBytesRead
,
308 DWORD
*MinNumberOfBytesNeeded
)
310 PLOGHANDLE lpLogHandle
;
314 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
317 return STATUS_INVALID_HANDLE
;
321 return I_RpcMapWin32Status(ERROR_INVALID_PARAMETER
);
323 /* If sequential read, retrieve the CurrentRecord from this log handle */
324 if (ReadFlags
& EVENTLOG_SEQUENTIAL_READ
)
326 RecordNumber
= lpLogHandle
->CurrentRecord
;
330 RecordNumber
= RecordOffset
;
333 dwError
= LogfReadEvent(lpLogHandle
->LogFile
, ReadFlags
, &RecordNumber
,
334 NumberOfBytesToRead
, Buffer
, NumberOfBytesRead
, MinNumberOfBytesNeeded
);
336 /* Update the handles CurrentRecord if success*/
337 if (dwError
== ERROR_SUCCESS
)
339 lpLogHandle
->CurrentRecord
= RecordNumber
;
342 return I_RpcMapWin32Status(dwError
);
347 NTSTATUS
ElfrReportEventW(
348 IELF_HANDLE LogHandle
,
351 USHORT EventCategory
,
355 PRPC_UNICODE_STRING ComputerName
,
357 PRPC_UNICODE_STRING Strings
[],
365 PLOGHANDLE lpLogHandle
;
368 DWORD dwStringsSize
= 0;
369 DWORD dwError
= ERROR_SUCCESS
;
373 lpLogHandle
= ElfGetLogHandleEntryByHandle(LogHandle
);
376 return STATUS_INVALID_HANDLE
;
379 /* Flags must be 0 */
382 return STATUS_INVALID_PARAMETER
;
385 lastRec
= LogfGetCurrentRecord(lpLogHandle
->LogFile
);
387 for (i
= 0; i
< NumStrings
; i
++)
391 case EVENTLOG_SUCCESS
:
392 DPRINT("Success: %wZ\n", Strings
[i
]);
395 case EVENTLOG_ERROR_TYPE
:
396 DPRINT("Error: %wZ\n", Strings
[i
]);
399 case EVENTLOG_WARNING_TYPE
:
400 DPRINT("Warning: %wZ\n", Strings
[i
]);
403 case EVENTLOG_INFORMATION_TYPE
:
404 DPRINT("Info: %wZ\n", Strings
[i
]);
408 DPRINT1("Type %hu: %wZ\n", EventType
, Strings
[i
]);
411 dwStringsSize
+= (wcslen(Strings
[i
]->Buffer
) + 1) * sizeof(WCHAR
);
414 lpStrings
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
, dwStringsSize
* 2);
417 DPRINT1("Failed to allocate heap\n");
418 return STATUS_NO_MEMORY
;
421 for (i
= 0; i
< NumStrings
; i
++)
423 wcscpy((WCHAR
*)(lpStrings
+ pos
), Strings
[i
]->Buffer
);
424 pos
+= (wcslen(Strings
[i
]->Buffer
) + 1) * sizeof(WCHAR
);
427 LogBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
433 ComputerName
->Buffer
,
441 dwError
= LogfWriteData(lpLogHandle
->LogFile
, recSize
, LogBuffer
);
444 DPRINT1("ERROR WRITING TO EventLog %S\n", lpLogHandle
->LogFile
->FileName
);
447 LogfFreeRecord(LogBuffer
);
449 HeapFree(GetProcessHeap(), 0, lpStrings
);
451 return I_RpcMapWin32Status(dwError
);
456 NTSTATUS
ElfrClearELFA(
457 IELF_HANDLE LogHandle
,
458 PRPC_STRING BackupFileName
)
461 return STATUS_NOT_IMPLEMENTED
;
466 NTSTATUS
ElfrBackupELFA(
467 IELF_HANDLE LogHandle
,
468 PRPC_STRING BackupFileName
)
471 return STATUS_NOT_IMPLEMENTED
;
476 NTSTATUS
ElfrOpenELA(
477 EVENTLOG_HANDLE_A UNCServerName
,
478 PRPC_STRING ModuleName
,
479 PRPC_STRING RegModuleName
,
482 IELF_HANDLE
*LogHandle
)
484 UNICODE_STRING ModuleNameW
;
486 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
487 return STATUS_INVALID_PARAMETER
;
489 /* RegModuleName must be an empty string */
490 if (RegModuleName
->Length
> 0)
491 return STATUS_INVALID_PARAMETER
;
493 RtlAnsiStringToUnicodeString(&ModuleNameW
, (PANSI_STRING
)ModuleName
, TRUE
);
495 /* FIXME: Must verify that caller has read access */
497 *LogHandle
= ElfCreateEventLogHandle(ModuleNameW
.Buffer
, FALSE
);
499 RtlFreeUnicodeString(&ModuleNameW
);
501 if (*LogHandle
== NULL
)
503 return STATUS_INVALID_PARAMETER
;
506 return STATUS_SUCCESS
;
511 NTSTATUS
ElfrRegisterEventSourceA(
512 EVENTLOG_HANDLE_A UNCServerName
,
513 PRPC_STRING ModuleName
,
514 PRPC_STRING RegModuleName
,
517 IELF_HANDLE
*LogHandle
)
519 UNICODE_STRING ModuleNameW
= { 0, 0, NULL
};
522 !RtlAnsiStringToUnicodeString(&ModuleNameW
, (PANSI_STRING
)ModuleName
, TRUE
))
524 return STATUS_NO_MEMORY
;
527 /* RegModuleName must be an empty string */
528 if (RegModuleName
->Length
> 0)
530 RtlFreeUnicodeString(&ModuleNameW
);
531 return STATUS_INVALID_PARAMETER
;
534 if ((MajorVersion
!= 1) || (MinorVersion
!= 1))
536 RtlFreeUnicodeString(&ModuleNameW
);
537 return STATUS_INVALID_PARAMETER
;
540 /* FIXME: Must verify that caller has write access */
542 *LogHandle
= ElfCreateEventLogHandle(ModuleNameW
.Buffer
,
545 RtlFreeUnicodeString(&ModuleNameW
);
547 return STATUS_SUCCESS
;
552 NTSTATUS
ElfrOpenBELA(
553 EVENTLOG_HANDLE_A UNCServerName
,
554 PRPC_STRING BackupFileName
,
557 IELF_HANDLE
*LogHandle
)
560 return STATUS_NOT_IMPLEMENTED
;
565 NTSTATUS
ElfrReadELA(
566 IELF_HANDLE LogHandle
,
569 RULONG NumberOfBytesToRead
,
571 DWORD
*NumberOfBytesRead
,
572 DWORD
*MinNumberOfBytesNeeded
)
575 return STATUS_NOT_IMPLEMENTED
;
580 NTSTATUS
ElfrReportEventA(
581 IELF_HANDLE LogHandle
,
584 USHORT EventCategory
,
588 PRPC_STRING ComputerName
,
590 PRPC_STRING Strings
[],
597 return STATUS_NOT_IMPLEMENTED
;
602 NTSTATUS
ElfrRegisterClusterSvc(
603 handle_t BindingHandle
)
606 return STATUS_NOT_IMPLEMENTED
;
611 NTSTATUS
ElfrDeregisterClusterSvc(
612 handle_t BindingHandle
)
615 return STATUS_NOT_IMPLEMENTED
;
620 NTSTATUS
ElfrWriteClusterEvents(
621 handle_t BindingHandle
)
624 return STATUS_NOT_IMPLEMENTED
;
629 NTSTATUS
ElfrGetLogInformation(
630 IELF_HANDLE LogHandle
,
634 DWORD
*pcbBytesNeeded
)
636 NTSTATUS Status
= STATUS_SUCCESS
;
638 /* FIXME: check handle first */
642 case EVENTLOG_FULL_INFO
:
644 LPEVENTLOG_FULL_INFORMATION efi
= (LPEVENTLOG_FULL_INFORMATION
)Buffer
;
646 *pcbBytesNeeded
= sizeof(EVENTLOG_FULL_INFORMATION
);
647 if (cbBufSize
< sizeof(EVENTLOG_FULL_INFORMATION
))
649 return STATUS_BUFFER_TOO_SMALL
;
652 efi
->dwFull
= 0; /* FIXME */
657 Status
= STATUS_INVALID_LEVEL
;
666 NTSTATUS
ElfrFlushEL(
667 IELF_HANDLE LogHandle
)
670 return STATUS_NOT_IMPLEMENTED
;
675 NTSTATUS
ElfrReportEventAndSourceW(
676 IELF_HANDLE LogHandle
,
679 USHORT EventCategory
,
681 PRPC_UNICODE_STRING SourceName
,
684 PRPC_UNICODE_STRING ComputerName
,
686 PRPC_UNICODE_STRING Strings
[],
693 return STATUS_NOT_IMPLEMENTED
;
697 void __RPC_FAR
*__RPC_USER
midl_user_allocate(SIZE_T len
)
699 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
703 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
705 HeapFree(GetProcessHeap(), 0, ptr
);
709 void __RPC_USER
IELF_HANDLE_rundown(IELF_HANDLE LogHandle
)