[SHELL32]
[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
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 dwUserSidLength = 0;
401 DWORD dwError = ERROR_SUCCESS;
402 WCHAR *lpStrings;
403 int pos = 0;
404
405 lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle);
406 if (!lpLogHandle)
407 {
408 return STATUS_INVALID_HANDLE;
409 }
410
411 /* Flags must be 0 */
412 if (Flags)
413 {
414 return STATUS_INVALID_PARAMETER;
415 }
416
417 lastRec = LogfGetCurrentRecord(lpLogHandle->LogFile);
418
419 for (i = 0; i < NumStrings; i++)
420 {
421 switch (EventType)
422 {
423 case EVENTLOG_SUCCESS:
424 DPRINT("Success: %wZ\n", Strings[i]);
425 break;
426
427 case EVENTLOG_ERROR_TYPE:
428 DPRINT("Error: %wZ\n", Strings[i]);
429 break;
430
431 case EVENTLOG_WARNING_TYPE:
432 DPRINT("Warning: %wZ\n", Strings[i]);
433 break;
434
435 case EVENTLOG_INFORMATION_TYPE:
436 DPRINT("Info: %wZ\n", Strings[i]);
437 break;
438
439 default:
440 DPRINT1("Type %hu: %wZ\n", EventType, Strings[i]);
441 break;
442 }
443 dwStringsSize += Strings[i]->Length + sizeof UNICODE_NULL;
444 }
445
446 lpStrings = HeapAlloc(GetProcessHeap(), 0, dwStringsSize);
447 if (!lpStrings)
448 {
449 DPRINT1("Failed to allocate heap\n");
450 return STATUS_NO_MEMORY;
451 }
452
453 for (i = 0; i < NumStrings; i++)
454 {
455 CopyMemory(lpStrings + pos, Strings[i]->Buffer, Strings[i]->Length);
456 pos += Strings[i]->Length / sizeof(WCHAR);
457 lpStrings[pos] = UNICODE_NULL;
458 pos += sizeof UNICODE_NULL / sizeof(WCHAR);
459 }
460
461 if (UserSID)
462 dwUserSidLength = FIELD_OFFSET(SID, SubAuthority[UserSID->SubAuthorityCount]);
463 LogBuffer = LogfAllocAndBuildNewRecord(&recSize,
464 lastRec,
465 EventType,
466 EventCategory,
467 EventID,
468 lpLogHandle->szName,
469 ComputerName->Buffer,
470 dwUserSidLength,
471 UserSID,
472 NumStrings,
473 lpStrings,
474 DataSize,
475 Data);
476
477 dwError = LogfWriteData(lpLogHandle->LogFile, recSize, LogBuffer);
478 if (!dwError)
479 {
480 DPRINT1("ERROR WRITING TO EventLog %S\n", lpLogHandle->LogFile->FileName);
481 }
482
483 LogfFreeRecord(LogBuffer);
484
485 HeapFree(GetProcessHeap(), 0, lpStrings);
486
487 return I_RpcMapWin32Status(dwError);
488 }
489
490
491 /* Function 12 */
492 NTSTATUS ElfrClearELFA(
493 IELF_HANDLE LogHandle,
494 PRPC_STRING BackupFileName)
495 {
496 UNIMPLEMENTED;
497 return STATUS_NOT_IMPLEMENTED;
498 }
499
500
501 /* Function 13 */
502 NTSTATUS ElfrBackupELFA(
503 IELF_HANDLE LogHandle,
504 PRPC_STRING BackupFileName)
505 {
506 UNIMPLEMENTED;
507 return STATUS_NOT_IMPLEMENTED;
508 }
509
510
511 /* Function 14 */
512 NTSTATUS ElfrOpenELA(
513 EVENTLOG_HANDLE_A UNCServerName,
514 PRPC_STRING ModuleName,
515 PRPC_STRING RegModuleName,
516 DWORD MajorVersion,
517 DWORD MinorVersion,
518 IELF_HANDLE *LogHandle)
519 {
520 UNICODE_STRING ModuleNameW;
521
522 if ((MajorVersion != 1) || (MinorVersion != 1))
523 return STATUS_INVALID_PARAMETER;
524
525 /* RegModuleName must be an empty string */
526 if (RegModuleName->Length > 0)
527 return STATUS_INVALID_PARAMETER;
528
529 RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE);
530
531 /* FIXME: Must verify that caller has read access */
532
533 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer, FALSE);
534
535 RtlFreeUnicodeString(&ModuleNameW);
536
537 if (*LogHandle == NULL)
538 {
539 return STATUS_INVALID_PARAMETER;
540 }
541
542 return STATUS_SUCCESS;
543 }
544
545
546 /* Function 15 */
547 NTSTATUS ElfrRegisterEventSourceA(
548 EVENTLOG_HANDLE_A UNCServerName,
549 PRPC_STRING ModuleName,
550 PRPC_STRING RegModuleName,
551 DWORD MajorVersion,
552 DWORD MinorVersion,
553 IELF_HANDLE *LogHandle)
554 {
555 UNICODE_STRING ModuleNameW = { 0, 0, NULL };
556
557 if (ModuleName &&
558 !RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE))
559 {
560 return STATUS_NO_MEMORY;
561 }
562
563 /* RegModuleName must be an empty string */
564 if (RegModuleName->Length > 0)
565 {
566 RtlFreeUnicodeString(&ModuleNameW);
567 return STATUS_INVALID_PARAMETER;
568 }
569
570 if ((MajorVersion != 1) || (MinorVersion != 1))
571 {
572 RtlFreeUnicodeString(&ModuleNameW);
573 return STATUS_INVALID_PARAMETER;
574 }
575
576 /* FIXME: Must verify that caller has write access */
577
578 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer,
579 TRUE);
580
581 RtlFreeUnicodeString(&ModuleNameW);
582
583 return STATUS_SUCCESS;
584 }
585
586
587 /* Function 16 */
588 NTSTATUS ElfrOpenBELA(
589 EVENTLOG_HANDLE_A UNCServerName,
590 PRPC_STRING BackupFileName,
591 DWORD MajorVersion,
592 DWORD MinorVersion,
593 IELF_HANDLE *LogHandle)
594 {
595 UNIMPLEMENTED;
596 return STATUS_NOT_IMPLEMENTED;
597 }
598
599
600 /* Function 17 */
601 NTSTATUS ElfrReadELA(
602 IELF_HANDLE LogHandle,
603 DWORD ReadFlags,
604 DWORD RecordOffset,
605 RULONG NumberOfBytesToRead,
606 BYTE *Buffer,
607 DWORD *NumberOfBytesRead,
608 DWORD *MinNumberOfBytesNeeded)
609 {
610 UNIMPLEMENTED;
611 return STATUS_NOT_IMPLEMENTED;
612 }
613
614
615 /* Function 18 */
616 NTSTATUS ElfrReportEventA(
617 IELF_HANDLE LogHandle,
618 DWORD Time,
619 USHORT EventType,
620 USHORT EventCategory,
621 DWORD EventID,
622 USHORT NumStrings,
623 DWORD DataSize,
624 PRPC_STRING ComputerName,
625 PRPC_SID UserSID,
626 PRPC_STRING Strings[],
627 BYTE *Data,
628 USHORT Flags,
629 DWORD *RecordNumber,
630 DWORD *TimeWritten)
631 {
632 UNIMPLEMENTED;
633 return STATUS_NOT_IMPLEMENTED;
634 }
635
636
637 /* Function 19 */
638 NTSTATUS ElfrRegisterClusterSvc(
639 handle_t BindingHandle)
640 {
641 UNIMPLEMENTED;
642 return STATUS_NOT_IMPLEMENTED;
643 }
644
645
646 /* Function 20 */
647 NTSTATUS ElfrDeregisterClusterSvc(
648 handle_t BindingHandle)
649 {
650 UNIMPLEMENTED;
651 return STATUS_NOT_IMPLEMENTED;
652 }
653
654
655 /* Function 21 */
656 NTSTATUS ElfrWriteClusterEvents(
657 handle_t BindingHandle)
658 {
659 UNIMPLEMENTED;
660 return STATUS_NOT_IMPLEMENTED;
661 }
662
663
664 /* Function 22 */
665 NTSTATUS ElfrGetLogInformation(
666 IELF_HANDLE LogHandle,
667 DWORD InfoLevel,
668 BYTE *Buffer,
669 DWORD cbBufSize,
670 DWORD *pcbBytesNeeded)
671 {
672 NTSTATUS Status = STATUS_SUCCESS;
673
674 /* FIXME: check handle first */
675
676 switch (InfoLevel)
677 {
678 case EVENTLOG_FULL_INFO:
679 {
680 LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer;
681
682 *pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
683 if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION))
684 {
685 return STATUS_BUFFER_TOO_SMALL;
686 }
687
688 efi->dwFull = 0; /* FIXME */
689 }
690 break;
691
692 default:
693 Status = STATUS_INVALID_LEVEL;
694 break;
695 }
696
697 return Status;
698 }
699
700
701 /* Function 23 */
702 NTSTATUS ElfrFlushEL(
703 IELF_HANDLE LogHandle)
704 {
705 UNIMPLEMENTED;
706 return STATUS_NOT_IMPLEMENTED;
707 }
708
709
710 /* Function 24 */
711 NTSTATUS ElfrReportEventAndSourceW(
712 IELF_HANDLE LogHandle,
713 DWORD Time,
714 USHORT EventType,
715 USHORT EventCategory,
716 ULONG EventID,
717 PRPC_UNICODE_STRING SourceName,
718 USHORT NumStrings,
719 DWORD DataSize,
720 PRPC_UNICODE_STRING ComputerName,
721 PRPC_SID UserSID,
722 PRPC_UNICODE_STRING Strings[],
723 BYTE *Data,
724 USHORT Flags,
725 DWORD *RecordNumber,
726 DWORD *TimeWritten)
727 {
728 UNIMPLEMENTED;
729 return STATUS_NOT_IMPLEMENTED;
730 }
731
732
733 void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len)
734 {
735 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
736 }
737
738
739 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
740 {
741 HeapFree(GetProcessHeap(), 0, ptr);
742 }
743
744
745 void __RPC_USER IELF_HANDLE_rundown(IELF_HANDLE LogHandle)
746 {
747 }