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