[CMAKE]
[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 LIST_ENTRY LogHandleListHead;
15
16 /* FUNCTIONS ****************************************************************/
17
18 DWORD WINAPI RpcThreadRoutine(LPVOID lpParameter)
19 {
20 RPC_STATUS Status;
21
22 InitializeListHead(&LogHandleListHead);
23
24 Status = RpcServerUseProtseqEpW(L"ncacn_np", 20, L"\\pipe\\EventLog", NULL);
25 if (Status != RPC_S_OK)
26 {
27 DPRINT("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
28 return 0;
29 }
30
31 Status = RpcServerRegisterIf(eventlog_v0_0_s_ifspec, NULL, NULL);
32 if (Status != RPC_S_OK)
33 {
34 DPRINT("RpcServerRegisterIf() failed (Status %lx)\n", Status);
35 return 0;
36 }
37
38 Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
39 if (Status != RPC_S_OK)
40 {
41 DPRINT("RpcServerListen() failed (Status %lx)\n", Status);
42 }
43
44 return 0;
45 }
46
47 PLOGHANDLE ElfCreateEventLogHandle(LPCWSTR Name, BOOL Create)
48 {
49 PLOGHANDLE lpLogHandle;
50 PLOGFILE currentLogFile = NULL;
51 INT i, LogsActive;
52 PEVENTSOURCE pEventSource;
53
54 DPRINT("ElfCreateEventLogHandle(Name: %S)\n", Name);
55
56 lpLogHandle = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGHANDLE)
57 + ((wcslen(Name) + 1) * sizeof(WCHAR)));
58 if (!lpLogHandle)
59 {
60 DPRINT1("Failed to allocate Heap!\n");
61 return NULL;
62 }
63
64 wcscpy(lpLogHandle->szName, Name);
65
66 /* Get the number of Log Files the EventLog service found */
67 LogsActive = LogfListItemCount();
68 if (LogsActive == 0)
69 {
70 DPRINT1("EventLog service reports no log files!\n");
71 goto Cleanup;
72 }
73
74 /* If Creating, default to the Application Log in case we fail, as documented on MSDN */
75 if (Create == TRUE)
76 {
77 pEventSource = GetEventSourceByName(Name);
78 DPRINT("EventSource: %p\n", pEventSource);
79 if (pEventSource)
80 {
81 DPRINT("EventSource LogFile: %p\n", pEventSource->LogFile);
82 lpLogHandle->LogFile = pEventSource->LogFile;
83 }
84 else
85 {
86 DPRINT("EventSource LogFile: Application log file\n");
87 lpLogHandle->LogFile = LogfListItemByName(L"Application");
88 }
89
90 DPRINT("LogHandle LogFile: %p\n", lpLogHandle->LogFile);
91 }
92 else
93 {
94 lpLogHandle->LogFile = NULL;
95
96 for (i = 1; i <= LogsActive; i++)
97 {
98 currentLogFile = LogfListItemByIndex(i);
99
100 if (_wcsicmp(Name, currentLogFile->LogName) == 0)
101 {
102 lpLogHandle->LogFile = LogfListItemByIndex(i);
103 lpLogHandle->CurrentRecord = LogfGetOldestRecord(lpLogHandle->LogFile);
104 break;
105 }
106 }
107 }
108
109 if (!lpLogHandle->LogFile)
110 goto Cleanup;
111
112 /* Append log handle */
113 InsertTailList(&LogHandleListHead, &lpLogHandle->LogHandleListEntry);
114
115 return lpLogHandle;
116
117 Cleanup:
118 HeapFree(GetProcessHeap(), 0, lpLogHandle);
119
120 return NULL;
121 }
122
123 PLOGHANDLE ElfGetLogHandleEntryByHandle(IELF_HANDLE EventLogHandle)
124 {
125 PLOGHANDLE lpLogHandle;
126
127 if (IsListEmpty(&LogHandleListHead))
128 {
129 return NULL;
130 }
131
132 lpLogHandle = CONTAINING_RECORD((PLOGHANDLE)EventLogHandle, LOGHANDLE, LogHandleListEntry);
133
134 return lpLogHandle;
135 }
136
137 BOOL ElfDeleteEventLogHandle(IELF_HANDLE EventLogHandle)
138 {
139 PLOGHANDLE lpLogHandle = (PLOGHANDLE)EventLogHandle;
140 if (!ElfGetLogHandleEntryByHandle(lpLogHandle))
141 {
142 return FALSE;
143 }
144
145 RemoveEntryList(&lpLogHandle->LogHandleListEntry);
146 HeapFree(GetProcessHeap(),0,lpLogHandle);
147
148 return TRUE;
149 }
150
151 /* Function 0 */
152 NTSTATUS ElfrClearELFW(
153 IELF_HANDLE LogHandle,
154 PRPC_UNICODE_STRING BackupFileName)
155 {
156 UNIMPLEMENTED;
157 return STATUS_NOT_IMPLEMENTED;
158 }
159
160
161 /* Function 1 */
162 NTSTATUS ElfrBackupELFW(
163 IELF_HANDLE LogHandle,
164 PRPC_UNICODE_STRING BackupFileName)
165 {
166 UNIMPLEMENTED;
167 return STATUS_NOT_IMPLEMENTED;
168 }
169
170 /* Function 2 */
171 NTSTATUS ElfrCloseEL(
172 IELF_HANDLE *LogHandle)
173 {
174 if (!ElfDeleteEventLogHandle(*LogHandle))
175 {
176 return STATUS_INVALID_HANDLE;
177 }
178
179 return STATUS_SUCCESS;
180 }
181
182
183 /* Function 3 */
184 NTSTATUS ElfrDeregisterEventSource(
185 IELF_HANDLE *LogHandle)
186 {
187 if (!ElfDeleteEventLogHandle(*LogHandle))
188 {
189 return STATUS_INVALID_HANDLE;
190 }
191
192 return STATUS_SUCCESS;
193 }
194
195
196 /* Function 4 */
197 NTSTATUS ElfrNumberOfRecords(
198 IELF_HANDLE LogHandle,
199 DWORD *NumberOfRecords)
200 {
201 PLOGHANDLE lpLogHandle;
202
203 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
204 if (!lpLogHandle)
205 {
206 return STATUS_INVALID_HANDLE;
207 }
208
209 *NumberOfRecords = lpLogHandle->LogFile->Header.CurrentRecordNumber;
210
211 return STATUS_SUCCESS;
212 }
213
214
215 /* Function 5 */
216 NTSTATUS ElfrOldestRecord(
217 IELF_HANDLE LogHandle,
218 DWORD *OldestRecordNumber)
219 {
220 PLOGHANDLE lpLogHandle;
221
222 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
223 if (!lpLogHandle)
224 {
225 return STATUS_INVALID_HANDLE;
226 }
227
228 if (!OldestRecordNumber)
229 {
230 return STATUS_INVALID_PARAMETER;
231 }
232
233 *OldestRecordNumber = 0;
234 *OldestRecordNumber = LogfGetOldestRecord(lpLogHandle->LogFile);
235 return STATUS_SUCCESS;
236 }
237
238
239 /* Function 6 */
240 NTSTATUS ElfrChangeNotify(
241 IELF_HANDLE *LogHandle,
242 RPC_CLIENT_ID ClientId,
243 DWORD Event)
244 {
245 UNIMPLEMENTED;
246 return STATUS_NOT_IMPLEMENTED;
247 }
248
249
250 /* Function 7 */
251 NTSTATUS ElfrOpenELW(
252 EVENTLOG_HANDLE_W UNCServerName,
253 PRPC_UNICODE_STRING ModuleName,
254 PRPC_UNICODE_STRING RegModuleName,
255 DWORD MajorVersion,
256 DWORD MinorVersion,
257 IELF_HANDLE *LogHandle)
258 {
259 if ((MajorVersion != 1) || (MinorVersion != 1))
260 return STATUS_INVALID_PARAMETER;
261
262 /* RegModuleName must be an empty string */
263 if (RegModuleName->Length > 0)
264 return STATUS_INVALID_PARAMETER;
265
266 /*FIXME: UNCServerName must specify the server */
267
268 /*FIXME: Must verify that caller has read access */
269
270 *LogHandle = ElfCreateEventLogHandle(ModuleName->Buffer, FALSE);
271
272 if (*LogHandle == NULL)
273 {
274 return STATUS_INVALID_PARAMETER;
275 }
276
277 return STATUS_SUCCESS;
278 }
279
280
281 /* Function 8 */
282 NTSTATUS ElfrRegisterEventSourceW(
283 EVENTLOG_HANDLE_W UNCServerName,
284 PRPC_UNICODE_STRING ModuleName,
285 PRPC_UNICODE_STRING RegModuleName,
286 DWORD MajorVersion,
287 DWORD MinorVersion,
288 IELF_HANDLE *LogHandle)
289 {
290 DPRINT1("ElfrRegisterEventSourceW()\n");
291
292 if ((MajorVersion != 1) || (MinorVersion != 1))
293 return STATUS_INVALID_PARAMETER;
294
295 /* RegModuleName must be an empty string */
296 if (RegModuleName->Length > 0)
297 return STATUS_INVALID_PARAMETER;
298
299 DPRINT1("ModuleName: %S\n", ModuleName->Buffer);
300
301 /*FIXME: UNCServerName must specify the server or empty for local */
302
303 /*FIXME: Must verify that caller has write access */
304
305 *LogHandle = ElfCreateEventLogHandle(ModuleName->Buffer, TRUE);
306
307 return STATUS_SUCCESS;
308 }
309
310
311 /* Function 9 */
312 NTSTATUS ElfrOpenBELW(
313 EVENTLOG_HANDLE_W UNCServerName,
314 PRPC_UNICODE_STRING BackupFileName,
315 DWORD MajorVersion,
316 DWORD MinorVersion,
317 IELF_HANDLE *LogHandle)
318 {
319 UNIMPLEMENTED;
320 return STATUS_NOT_IMPLEMENTED;
321 }
322
323
324 /* Function 10 */
325 NTSTATUS ElfrReadELW(
326 IELF_HANDLE LogHandle,
327 DWORD ReadFlags,
328 DWORD RecordOffset,
329 RULONG NumberOfBytesToRead,
330 BYTE *Buffer,
331 DWORD *NumberOfBytesRead,
332 DWORD *MinNumberOfBytesNeeded)
333 {
334 PLOGHANDLE lpLogHandle;
335 DWORD dwError;
336 DWORD RecordNumber;
337
338 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
339 if (!lpLogHandle)
340 {
341 return STATUS_INVALID_HANDLE;
342 }
343
344 if (!Buffer)
345 return I_RpcMapWin32Status(ERROR_INVALID_PARAMETER);
346
347 /* If sequential read, retrieve the CurrentRecord from this log handle */
348 if (ReadFlags & EVENTLOG_SEQUENTIAL_READ)
349 {
350 RecordNumber = lpLogHandle->CurrentRecord;
351 }
352 else
353 {
354 RecordNumber = RecordOffset;
355 }
356
357 dwError = LogfReadEvent(lpLogHandle->LogFile, ReadFlags, &RecordNumber,
358 NumberOfBytesToRead, Buffer, NumberOfBytesRead, MinNumberOfBytesNeeded);
359
360 /* Update the handles CurrentRecord if success*/
361 if (dwError == ERROR_SUCCESS)
362 {
363 lpLogHandle->CurrentRecord = RecordNumber;
364 }
365
366 return I_RpcMapWin32Status(dwError);
367 }
368
369
370 /* Function 11 */
371 NTSTATUS ElfrReportEventW(
372 IELF_HANDLE LogHandle,
373 DWORD Time,
374 USHORT EventType,
375 USHORT EventCategory,
376 DWORD EventID,
377 USHORT NumStrings,
378 DWORD DataSize,
379 PRPC_UNICODE_STRING ComputerName,
380 PRPC_SID UserSID,
381 PRPC_UNICODE_STRING Strings[],
382 BYTE *Data,
383 USHORT Flags,
384 DWORD *RecordNumber,
385 DWORD *TimeWritten)
386 {
387 USHORT i;
388 PBYTE LogBuffer;
389 PLOGHANDLE lpLogHandle;
390 DWORD lastRec;
391 DWORD recSize;
392 DWORD dwStringsSize = 0;
393 DWORD dwError = ERROR_SUCCESS;
394 WCHAR *lpStrings;
395 int pos = 0;
396
397 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
398 if (!lpLogHandle)
399 {
400 return STATUS_INVALID_HANDLE;
401 }
402
403 /* Flags must be 0 */
404 if (Flags)
405 {
406 return STATUS_INVALID_PARAMETER;
407 }
408
409 lastRec = LogfGetCurrentRecord(lpLogHandle->LogFile);
410
411 for (i = 0; i < NumStrings; i++)
412 {
413 switch (EventType)
414 {
415 case EVENTLOG_SUCCESS:
416 DPRINT("Success: %wZ\n", Strings[i]);
417 break;
418
419 case EVENTLOG_ERROR_TYPE:
420 DPRINT("Error: %wZ\n", Strings[i]);
421 break;
422
423 case EVENTLOG_WARNING_TYPE:
424 DPRINT("Warning: %wZ\n", Strings[i]);
425 break;
426
427 case EVENTLOG_INFORMATION_TYPE:
428 DPRINT("Info: %wZ\n", Strings[i]);
429 break;
430
431 default:
432 DPRINT1("Type %hu: %wZ\n", EventType, Strings[i]);
433 break;
434 }
435 dwStringsSize += (wcslen(Strings[i]->Buffer) + 1) * sizeof(WCHAR);
436 }
437
438 lpStrings = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, dwStringsSize * 2);
439 if (!lpStrings)
440 {
441 DPRINT1("Failed to allocate heap\n");
442 return STATUS_NO_MEMORY;
443 }
444
445 for (i = 0; i < NumStrings; i++)
446 {
447 wcscpy((WCHAR*)(lpStrings + pos), Strings[i]->Buffer);
448 pos += (wcslen(Strings[i]->Buffer) + 1) * sizeof(WCHAR);
449 }
450
451 LogBuffer = LogfAllocAndBuildNewRecord(&recSize,
452 lastRec,
453 EventType,
454 EventCategory,
455 EventID,
456 lpLogHandle->szName,
457 ComputerName->Buffer,
458 sizeof(UserSID),
459 &UserSID,
460 NumStrings,
461 (WCHAR*)lpStrings,
462 DataSize,
463 Data);
464
465 dwError = LogfWriteData(lpLogHandle->LogFile, recSize, LogBuffer);
466 if (!dwError)
467 {
468 DPRINT1("ERROR WRITING TO EventLog %S\n", lpLogHandle->LogFile->FileName);
469 }
470
471 LogfFreeRecord(LogBuffer);
472
473 HeapFree(GetProcessHeap(), 0, lpStrings);
474
475 return I_RpcMapWin32Status(dwError);
476 }
477
478
479 /* Function 12 */
480 NTSTATUS ElfrClearELFA(
481 IELF_HANDLE LogHandle,
482 PRPC_STRING BackupFileName)
483 {
484 UNIMPLEMENTED;
485 return STATUS_NOT_IMPLEMENTED;
486 }
487
488
489 /* Function 13 */
490 NTSTATUS ElfrBackupELFA(
491 IELF_HANDLE LogHandle,
492 PRPC_STRING BackupFileName)
493 {
494 UNIMPLEMENTED;
495 return STATUS_NOT_IMPLEMENTED;
496 }
497
498
499 /* Function 14 */
500 NTSTATUS ElfrOpenELA(
501 EVENTLOG_HANDLE_A UNCServerName,
502 PRPC_STRING ModuleName,
503 PRPC_STRING RegModuleName,
504 DWORD MajorVersion,
505 DWORD MinorVersion,
506 IELF_HANDLE *LogHandle)
507 {
508 UNICODE_STRING ModuleNameW;
509
510 if ((MajorVersion != 1) || (MinorVersion != 1))
511 return STATUS_INVALID_PARAMETER;
512
513 /* RegModuleName must be an empty string */
514 if (RegModuleName->Length > 0)
515 return STATUS_INVALID_PARAMETER;
516
517 RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE);
518
519 /* FIXME: Must verify that caller has read access */
520
521 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer, FALSE);
522
523 RtlFreeUnicodeString(&ModuleNameW);
524
525 if (*LogHandle == NULL)
526 {
527 return STATUS_INVALID_PARAMETER;
528 }
529
530 return STATUS_SUCCESS;
531 }
532
533
534 /* Function 15 */
535 NTSTATUS ElfrRegisterEventSourceA(
536 EVENTLOG_HANDLE_A UNCServerName,
537 PRPC_STRING ModuleName,
538 PRPC_STRING RegModuleName,
539 DWORD MajorVersion,
540 DWORD MinorVersion,
541 IELF_HANDLE *LogHandle)
542 {
543 UNICODE_STRING ModuleNameW = { 0, 0, NULL };
544
545 if (ModuleName &&
546 !RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE))
547 {
548 return STATUS_NO_MEMORY;
549 }
550
551 /* RegModuleName must be an empty string */
552 if (RegModuleName->Length > 0)
553 {
554 RtlFreeUnicodeString(&ModuleNameW);
555 return STATUS_INVALID_PARAMETER;
556 }
557
558 if ((MajorVersion != 1) || (MinorVersion != 1))
559 {
560 RtlFreeUnicodeString(&ModuleNameW);
561 return STATUS_INVALID_PARAMETER;
562 }
563
564 /* FIXME: Must verify that caller has write access */
565
566 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer,
567 TRUE);
568
569 RtlFreeUnicodeString(&ModuleNameW);
570
571 return STATUS_SUCCESS;
572 }
573
574
575 /* Function 16 */
576 NTSTATUS ElfrOpenBELA(
577 EVENTLOG_HANDLE_A UNCServerName,
578 PRPC_STRING BackupFileName,
579 DWORD MajorVersion,
580 DWORD MinorVersion,
581 IELF_HANDLE *LogHandle)
582 {
583 UNIMPLEMENTED;
584 return STATUS_NOT_IMPLEMENTED;
585 }
586
587
588 /* Function 17 */
589 NTSTATUS ElfrReadELA(
590 IELF_HANDLE LogHandle,
591 DWORD ReadFlags,
592 DWORD RecordOffset,
593 RULONG NumberOfBytesToRead,
594 BYTE *Buffer,
595 DWORD *NumberOfBytesRead,
596 DWORD *MinNumberOfBytesNeeded)
597 {
598 UNIMPLEMENTED;
599 return STATUS_NOT_IMPLEMENTED;
600 }
601
602
603 /* Function 18 */
604 NTSTATUS ElfrReportEventA(
605 IELF_HANDLE LogHandle,
606 DWORD Time,
607 USHORT EventType,
608 USHORT EventCategory,
609 DWORD EventID,
610 USHORT NumStrings,
611 DWORD DataSize,
612 PRPC_STRING ComputerName,
613 PRPC_SID UserSID,
614 PRPC_STRING Strings[],
615 BYTE *Data,
616 USHORT Flags,
617 DWORD *RecordNumber,
618 DWORD *TimeWritten)
619 {
620 UNIMPLEMENTED;
621 return STATUS_NOT_IMPLEMENTED;
622 }
623
624
625 /* Function 19 */
626 NTSTATUS ElfrRegisterClusterSvc(
627 handle_t BindingHandle)
628 {
629 UNIMPLEMENTED;
630 return STATUS_NOT_IMPLEMENTED;
631 }
632
633
634 /* Function 20 */
635 NTSTATUS ElfrDeregisterClusterSvc(
636 handle_t BindingHandle)
637 {
638 UNIMPLEMENTED;
639 return STATUS_NOT_IMPLEMENTED;
640 }
641
642
643 /* Function 21 */
644 NTSTATUS ElfrWriteClusterEvents(
645 handle_t BindingHandle)
646 {
647 UNIMPLEMENTED;
648 return STATUS_NOT_IMPLEMENTED;
649 }
650
651
652 /* Function 22 */
653 NTSTATUS ElfrGetLogInformation(
654 IELF_HANDLE LogHandle,
655 DWORD InfoLevel,
656 BYTE *Buffer,
657 DWORD cbBufSize,
658 DWORD *pcbBytesNeeded)
659 {
660 NTSTATUS Status = STATUS_SUCCESS;
661
662 /* FIXME: check handle first */
663
664 switch (InfoLevel)
665 {
666 case EVENTLOG_FULL_INFO:
667 {
668 LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer;
669
670 *pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
671 if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION))
672 {
673 return STATUS_BUFFER_TOO_SMALL;
674 }
675
676 efi->dwFull = 0; /* FIXME */
677 }
678 break;
679
680 default:
681 Status = STATUS_INVALID_LEVEL;
682 break;
683 }
684
685 return Status;
686 }
687
688
689 /* Function 23 */
690 NTSTATUS ElfrFlushEL(
691 IELF_HANDLE LogHandle)
692 {
693 UNIMPLEMENTED;
694 return STATUS_NOT_IMPLEMENTED;
695 }
696
697
698 /* Function 24 */
699 NTSTATUS ElfrReportEventAndSourceW(
700 IELF_HANDLE LogHandle,
701 DWORD Time,
702 USHORT EventType,
703 USHORT EventCategory,
704 ULONG EventID,
705 PRPC_UNICODE_STRING SourceName,
706 USHORT NumStrings,
707 DWORD DataSize,
708 PRPC_UNICODE_STRING ComputerName,
709 PRPC_SID UserSID,
710 PRPC_UNICODE_STRING Strings[],
711 BYTE *Data,
712 USHORT Flags,
713 DWORD *RecordNumber,
714 DWORD *TimeWritten)
715 {
716 UNIMPLEMENTED;
717 return STATUS_NOT_IMPLEMENTED;
718 }
719
720
721 void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len)
722 {
723 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
724 }
725
726
727 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
728 {
729 HeapFree(GetProcessHeap(), 0, ptr);
730 }
731
732
733 void __RPC_USER IELF_HANDLE_rundown(IELF_HANDLE LogHandle)
734 {
735 }