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