* Sync with recent trunk (r52637).
[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 PLOGFILE lpLogFile;
203
204 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
205 if (!lpLogHandle)
206 {
207 return STATUS_INVALID_HANDLE;
208 }
209
210 lpLogFile = lpLogHandle->LogFile;
211
212 if (lpLogFile->Header.OldestRecordNumber == 0)
213 *NumberOfRecords = 0;
214 else
215 *NumberOfRecords = lpLogFile->Header.CurrentRecordNumber -
216 lpLogFile->Header.OldestRecordNumber;
217
218 return STATUS_SUCCESS;
219 }
220
221
222 /* Function 5 */
223 NTSTATUS ElfrOldestRecord(
224 IELF_HANDLE LogHandle,
225 DWORD *OldestRecordNumber)
226 {
227 PLOGHANDLE lpLogHandle;
228
229 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
230 if (!lpLogHandle)
231 {
232 return STATUS_INVALID_HANDLE;
233 }
234
235 if (!OldestRecordNumber)
236 {
237 return STATUS_INVALID_PARAMETER;
238 }
239
240 *OldestRecordNumber = 0;
241 *OldestRecordNumber = LogfGetOldestRecord(lpLogHandle->LogFile);
242 return STATUS_SUCCESS;
243 }
244
245
246 /* Function 6 */
247 NTSTATUS ElfrChangeNotify(
248 IELF_HANDLE *LogHandle,
249 RPC_CLIENT_ID ClientId,
250 DWORD Event)
251 {
252 UNIMPLEMENTED;
253 return STATUS_NOT_IMPLEMENTED;
254 }
255
256
257 /* Function 7 */
258 NTSTATUS ElfrOpenELW(
259 EVENTLOG_HANDLE_W UNCServerName,
260 PRPC_UNICODE_STRING ModuleName,
261 PRPC_UNICODE_STRING RegModuleName,
262 DWORD MajorVersion,
263 DWORD MinorVersion,
264 IELF_HANDLE *LogHandle)
265 {
266 if ((MajorVersion != 1) || (MinorVersion != 1))
267 return STATUS_INVALID_PARAMETER;
268
269 /* RegModuleName must be an empty string */
270 if (RegModuleName->Length > 0)
271 return STATUS_INVALID_PARAMETER;
272
273 /*FIXME: UNCServerName must specify the server */
274
275 /*FIXME: Must verify that caller has read access */
276
277 *LogHandle = ElfCreateEventLogHandle(ModuleName->Buffer, FALSE);
278
279 if (*LogHandle == NULL)
280 {
281 return STATUS_INVALID_PARAMETER;
282 }
283
284 return STATUS_SUCCESS;
285 }
286
287
288 /* Function 8 */
289 NTSTATUS ElfrRegisterEventSourceW(
290 EVENTLOG_HANDLE_W UNCServerName,
291 PRPC_UNICODE_STRING ModuleName,
292 PRPC_UNICODE_STRING RegModuleName,
293 DWORD MajorVersion,
294 DWORD MinorVersion,
295 IELF_HANDLE *LogHandle)
296 {
297 DPRINT1("ElfrRegisterEventSourceW()\n");
298
299 if ((MajorVersion != 1) || (MinorVersion != 1))
300 return STATUS_INVALID_PARAMETER;
301
302 /* RegModuleName must be an empty string */
303 if (RegModuleName->Length > 0)
304 return STATUS_INVALID_PARAMETER;
305
306 DPRINT1("ModuleName: %S\n", ModuleName->Buffer);
307
308 /*FIXME: UNCServerName must specify the server or empty for local */
309
310 /*FIXME: Must verify that caller has write access */
311
312 *LogHandle = ElfCreateEventLogHandle(ModuleName->Buffer, TRUE);
313
314 return STATUS_SUCCESS;
315 }
316
317
318 /* Function 9 */
319 NTSTATUS ElfrOpenBELW(
320 EVENTLOG_HANDLE_W UNCServerName,
321 PRPC_UNICODE_STRING BackupFileName,
322 DWORD MajorVersion,
323 DWORD MinorVersion,
324 IELF_HANDLE *LogHandle)
325 {
326 UNIMPLEMENTED;
327 return STATUS_NOT_IMPLEMENTED;
328 }
329
330
331 /* Function 10 */
332 NTSTATUS ElfrReadELW(
333 IELF_HANDLE LogHandle,
334 DWORD ReadFlags,
335 DWORD RecordOffset,
336 RULONG NumberOfBytesToRead,
337 BYTE *Buffer,
338 DWORD *NumberOfBytesRead,
339 DWORD *MinNumberOfBytesNeeded)
340 {
341 PLOGHANDLE lpLogHandle;
342 DWORD dwError;
343 DWORD RecordNumber;
344
345 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
346 if (!lpLogHandle)
347 {
348 return STATUS_INVALID_HANDLE;
349 }
350
351 if (!Buffer)
352 return I_RpcMapWin32Status(ERROR_INVALID_PARAMETER);
353
354 /* If sequential read, retrieve the CurrentRecord from this log handle */
355 if (ReadFlags & EVENTLOG_SEQUENTIAL_READ)
356 {
357 RecordNumber = lpLogHandle->CurrentRecord;
358 }
359 else
360 {
361 RecordNumber = RecordOffset;
362 }
363
364 dwError = LogfReadEvent(lpLogHandle->LogFile, ReadFlags, &RecordNumber,
365 NumberOfBytesToRead, Buffer, NumberOfBytesRead, MinNumberOfBytesNeeded);
366
367 /* Update the handles CurrentRecord if success*/
368 if (dwError == ERROR_SUCCESS)
369 {
370 lpLogHandle->CurrentRecord = RecordNumber;
371 }
372
373 return I_RpcMapWin32Status(dwError);
374 }
375
376
377 /* Function 11 */
378 NTSTATUS ElfrReportEventW(
379 IELF_HANDLE LogHandle,
380 DWORD Time,
381 USHORT EventType,
382 USHORT EventCategory,
383 DWORD EventID,
384 USHORT NumStrings,
385 DWORD DataSize,
386 PRPC_UNICODE_STRING ComputerName,
387 PRPC_SID UserSID,
388 PRPC_UNICODE_STRING Strings[],
389 BYTE *Data,
390 USHORT Flags,
391 DWORD *RecordNumber,
392 DWORD *TimeWritten)
393 {
394 USHORT i;
395 PBYTE LogBuffer;
396 PLOGHANDLE lpLogHandle;
397 DWORD lastRec;
398 DWORD recSize;
399 DWORD dwStringsSize = 0;
400 DWORD dwError = ERROR_SUCCESS;
401 WCHAR *lpStrings;
402 int pos = 0;
403
404 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
405 if (!lpLogHandle)
406 {
407 return STATUS_INVALID_HANDLE;
408 }
409
410 /* Flags must be 0 */
411 if (Flags)
412 {
413 return STATUS_INVALID_PARAMETER;
414 }
415
416 lastRec = LogfGetCurrentRecord(lpLogHandle->LogFile);
417
418 for (i = 0; i < NumStrings; i++)
419 {
420 switch (EventType)
421 {
422 case EVENTLOG_SUCCESS:
423 DPRINT("Success: %wZ\n", Strings[i]);
424 break;
425
426 case EVENTLOG_ERROR_TYPE:
427 DPRINT("Error: %wZ\n", Strings[i]);
428 break;
429
430 case EVENTLOG_WARNING_TYPE:
431 DPRINT("Warning: %wZ\n", Strings[i]);
432 break;
433
434 case EVENTLOG_INFORMATION_TYPE:
435 DPRINT("Info: %wZ\n", Strings[i]);
436 break;
437
438 default:
439 DPRINT1("Type %hu: %wZ\n", EventType, Strings[i]);
440 break;
441 }
442 dwStringsSize += (wcslen(Strings[i]->Buffer) + 1) * sizeof(WCHAR);
443 }
444
445 lpStrings = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, dwStringsSize * 2);
446 if (!lpStrings)
447 {
448 DPRINT1("Failed to allocate heap\n");
449 return STATUS_NO_MEMORY;
450 }
451
452 for (i = 0; i < NumStrings; i++)
453 {
454 wcscpy((WCHAR*)(lpStrings + pos), Strings[i]->Buffer);
455 pos += (wcslen(Strings[i]->Buffer) + 1) * sizeof(WCHAR);
456 }
457
458 LogBuffer = LogfAllocAndBuildNewRecord(&recSize,
459 lastRec,
460 EventType,
461 EventCategory,
462 EventID,
463 lpLogHandle->szName,
464 ComputerName->Buffer,
465 sizeof(UserSID),
466 &UserSID,
467 NumStrings,
468 (WCHAR*)lpStrings,
469 DataSize,
470 Data);
471
472 dwError = LogfWriteData(lpLogHandle->LogFile, recSize, LogBuffer);
473 if (!dwError)
474 {
475 DPRINT1("ERROR WRITING TO EventLog %S\n", lpLogHandle->LogFile->FileName);
476 }
477
478 LogfFreeRecord(LogBuffer);
479
480 HeapFree(GetProcessHeap(), 0, lpStrings);
481
482 return I_RpcMapWin32Status(dwError);
483 }
484
485
486 /* Function 12 */
487 NTSTATUS ElfrClearELFA(
488 IELF_HANDLE LogHandle,
489 PRPC_STRING BackupFileName)
490 {
491 UNIMPLEMENTED;
492 return STATUS_NOT_IMPLEMENTED;
493 }
494
495
496 /* Function 13 */
497 NTSTATUS ElfrBackupELFA(
498 IELF_HANDLE LogHandle,
499 PRPC_STRING BackupFileName)
500 {
501 UNIMPLEMENTED;
502 return STATUS_NOT_IMPLEMENTED;
503 }
504
505
506 /* Function 14 */
507 NTSTATUS ElfrOpenELA(
508 EVENTLOG_HANDLE_A UNCServerName,
509 PRPC_STRING ModuleName,
510 PRPC_STRING RegModuleName,
511 DWORD MajorVersion,
512 DWORD MinorVersion,
513 IELF_HANDLE *LogHandle)
514 {
515 UNICODE_STRING ModuleNameW;
516
517 if ((MajorVersion != 1) || (MinorVersion != 1))
518 return STATUS_INVALID_PARAMETER;
519
520 /* RegModuleName must be an empty string */
521 if (RegModuleName->Length > 0)
522 return STATUS_INVALID_PARAMETER;
523
524 RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE);
525
526 /* FIXME: Must verify that caller has read access */
527
528 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer, FALSE);
529
530 RtlFreeUnicodeString(&ModuleNameW);
531
532 if (*LogHandle == NULL)
533 {
534 return STATUS_INVALID_PARAMETER;
535 }
536
537 return STATUS_SUCCESS;
538 }
539
540
541 /* Function 15 */
542 NTSTATUS ElfrRegisterEventSourceA(
543 EVENTLOG_HANDLE_A UNCServerName,
544 PRPC_STRING ModuleName,
545 PRPC_STRING RegModuleName,
546 DWORD MajorVersion,
547 DWORD MinorVersion,
548 IELF_HANDLE *LogHandle)
549 {
550 UNICODE_STRING ModuleNameW = { 0, 0, NULL };
551
552 if (ModuleName &&
553 !RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE))
554 {
555 return STATUS_NO_MEMORY;
556 }
557
558 /* RegModuleName must be an empty string */
559 if (RegModuleName->Length > 0)
560 {
561 RtlFreeUnicodeString(&ModuleNameW);
562 return STATUS_INVALID_PARAMETER;
563 }
564
565 if ((MajorVersion != 1) || (MinorVersion != 1))
566 {
567 RtlFreeUnicodeString(&ModuleNameW);
568 return STATUS_INVALID_PARAMETER;
569 }
570
571 /* FIXME: Must verify that caller has write access */
572
573 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer,
574 TRUE);
575
576 RtlFreeUnicodeString(&ModuleNameW);
577
578 return STATUS_SUCCESS;
579 }
580
581
582 /* Function 16 */
583 NTSTATUS ElfrOpenBELA(
584 EVENTLOG_HANDLE_A UNCServerName,
585 PRPC_STRING BackupFileName,
586 DWORD MajorVersion,
587 DWORD MinorVersion,
588 IELF_HANDLE *LogHandle)
589 {
590 UNIMPLEMENTED;
591 return STATUS_NOT_IMPLEMENTED;
592 }
593
594
595 /* Function 17 */
596 NTSTATUS ElfrReadELA(
597 IELF_HANDLE LogHandle,
598 DWORD ReadFlags,
599 DWORD RecordOffset,
600 RULONG NumberOfBytesToRead,
601 BYTE *Buffer,
602 DWORD *NumberOfBytesRead,
603 DWORD *MinNumberOfBytesNeeded)
604 {
605 UNIMPLEMENTED;
606 return STATUS_NOT_IMPLEMENTED;
607 }
608
609
610 /* Function 18 */
611 NTSTATUS ElfrReportEventA(
612 IELF_HANDLE LogHandle,
613 DWORD Time,
614 USHORT EventType,
615 USHORT EventCategory,
616 DWORD EventID,
617 USHORT NumStrings,
618 DWORD DataSize,
619 PRPC_STRING ComputerName,
620 PRPC_SID UserSID,
621 PRPC_STRING Strings[],
622 BYTE *Data,
623 USHORT Flags,
624 DWORD *RecordNumber,
625 DWORD *TimeWritten)
626 {
627 UNIMPLEMENTED;
628 return STATUS_NOT_IMPLEMENTED;
629 }
630
631
632 /* Function 19 */
633 NTSTATUS ElfrRegisterClusterSvc(
634 handle_t BindingHandle)
635 {
636 UNIMPLEMENTED;
637 return STATUS_NOT_IMPLEMENTED;
638 }
639
640
641 /* Function 20 */
642 NTSTATUS ElfrDeregisterClusterSvc(
643 handle_t BindingHandle)
644 {
645 UNIMPLEMENTED;
646 return STATUS_NOT_IMPLEMENTED;
647 }
648
649
650 /* Function 21 */
651 NTSTATUS ElfrWriteClusterEvents(
652 handle_t BindingHandle)
653 {
654 UNIMPLEMENTED;
655 return STATUS_NOT_IMPLEMENTED;
656 }
657
658
659 /* Function 22 */
660 NTSTATUS ElfrGetLogInformation(
661 IELF_HANDLE LogHandle,
662 DWORD InfoLevel,
663 BYTE *Buffer,
664 DWORD cbBufSize,
665 DWORD *pcbBytesNeeded)
666 {
667 NTSTATUS Status = STATUS_SUCCESS;
668
669 /* FIXME: check handle first */
670
671 switch (InfoLevel)
672 {
673 case EVENTLOG_FULL_INFO:
674 {
675 LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer;
676
677 *pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
678 if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION))
679 {
680 return STATUS_BUFFER_TOO_SMALL;
681 }
682
683 efi->dwFull = 0; /* FIXME */
684 }
685 break;
686
687 default:
688 Status = STATUS_INVALID_LEVEL;
689 break;
690 }
691
692 return Status;
693 }
694
695
696 /* Function 23 */
697 NTSTATUS ElfrFlushEL(
698 IELF_HANDLE LogHandle)
699 {
700 UNIMPLEMENTED;
701 return STATUS_NOT_IMPLEMENTED;
702 }
703
704
705 /* Function 24 */
706 NTSTATUS ElfrReportEventAndSourceW(
707 IELF_HANDLE LogHandle,
708 DWORD Time,
709 USHORT EventType,
710 USHORT EventCategory,
711 ULONG EventID,
712 PRPC_UNICODE_STRING SourceName,
713 USHORT NumStrings,
714 DWORD DataSize,
715 PRPC_UNICODE_STRING ComputerName,
716 PRPC_SID UserSID,
717 PRPC_UNICODE_STRING Strings[],
718 BYTE *Data,
719 USHORT Flags,
720 DWORD *RecordNumber,
721 DWORD *TimeWritten)
722 {
723 UNIMPLEMENTED;
724 return STATUS_NOT_IMPLEMENTED;
725 }
726
727
728 void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len)
729 {
730 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
731 }
732
733
734 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
735 {
736 HeapFree(GetProcessHeap(), 0, ptr);
737 }
738
739
740 void __RPC_USER IELF_HANDLE_rundown(IELF_HANDLE LogHandle)
741 {
742 }