Sync with trunk head.
[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 ModuleNameW;
484
485 if ((MajorVersion != 1) || (MinorVersion != 1))
486 return STATUS_INVALID_PARAMETER;
487
488 /* RegModuleName must be an empty string */
489 if (RegModuleName->Length > 0)
490 return STATUS_INVALID_PARAMETER;
491
492 RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE);
493
494 /* FIXME: Must verify that caller has read access */
495
496 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer, FALSE);
497
498 RtlFreeUnicodeString(&ModuleNameW);
499
500 if (*LogHandle == NULL)
501 {
502 return STATUS_INVALID_PARAMETER;
503 }
504
505 return STATUS_SUCCESS;
506 }
507
508
509 /* Function 15 */
510 NTSTATUS ElfrRegisterEventSourceA(
511 EVENTLOG_HANDLE_A UNCServerName,
512 PRPC_STRING ModuleName,
513 PRPC_STRING RegModuleName,
514 DWORD MajorVersion,
515 DWORD MinorVersion,
516 IELF_HANDLE *LogHandle)
517 {
518 UNICODE_STRING ModuleNameW = { 0, 0, NULL };
519
520 if (ModuleName &&
521 !RtlAnsiStringToUnicodeString(&ModuleNameW, (PANSI_STRING)ModuleName, TRUE))
522 {
523 return STATUS_NO_MEMORY;
524 }
525
526 /* RegModuleName must be an empty string */
527 if (RegModuleName->Length > 0)
528 {
529 RtlFreeUnicodeString(&ModuleNameW);
530 return STATUS_INVALID_PARAMETER;
531 }
532
533 if ((MajorVersion != 1) || (MinorVersion != 1))
534 {
535 RtlFreeUnicodeString(&ModuleNameW);
536 return STATUS_INVALID_PARAMETER;
537 }
538
539 /* FIXME: Must verify that caller has write access */
540
541 *LogHandle = ElfCreateEventLogHandle(ModuleNameW.Buffer,
542 TRUE);
543
544 RtlFreeUnicodeString(&ModuleNameW);
545
546 return STATUS_SUCCESS;
547 }
548
549
550 /* Function 16 */
551 NTSTATUS ElfrOpenBELA(
552 EVENTLOG_HANDLE_A UNCServerName,
553 PRPC_STRING BackupFileName,
554 DWORD MajorVersion,
555 DWORD MinorVersion,
556 IELF_HANDLE *LogHandle)
557 {
558 UNIMPLEMENTED;
559 return STATUS_NOT_IMPLEMENTED;
560 }
561
562
563 /* Function 17 */
564 NTSTATUS ElfrReadELA(
565 IELF_HANDLE LogHandle,
566 DWORD ReadFlags,
567 DWORD RecordOffset,
568 RULONG NumberOfBytesToRead,
569 BYTE *Buffer,
570 DWORD *NumberOfBytesRead,
571 DWORD *MinNumberOfBytesNeeded)
572 {
573 UNIMPLEMENTED;
574 return STATUS_NOT_IMPLEMENTED;
575 }
576
577
578 /* Function 18 */
579 NTSTATUS ElfrReportEventA(
580 IELF_HANDLE LogHandle,
581 DWORD Time,
582 USHORT EventType,
583 USHORT EventCategory,
584 DWORD EventID,
585 USHORT NumStrings,
586 DWORD DataSize,
587 PRPC_STRING ComputerName,
588 PRPC_SID UserSID,
589 PRPC_STRING Strings[],
590 BYTE *Data,
591 USHORT Flags,
592 DWORD *RecordNumber,
593 DWORD *TimeWritten)
594 {
595 UNIMPLEMENTED;
596 return STATUS_NOT_IMPLEMENTED;
597 }
598
599
600 /* Function 19 */
601 NTSTATUS ElfrRegisterClusterSvc(
602 handle_t BindingHandle)
603 {
604 UNIMPLEMENTED;
605 return STATUS_NOT_IMPLEMENTED;
606 }
607
608
609 /* Function 20 */
610 NTSTATUS ElfrDeregisterClusterSvc(
611 handle_t BindingHandle)
612 {
613 UNIMPLEMENTED;
614 return STATUS_NOT_IMPLEMENTED;
615 }
616
617
618 /* Function 21 */
619 NTSTATUS ElfrWriteClusterEvents(
620 handle_t BindingHandle)
621 {
622 UNIMPLEMENTED;
623 return STATUS_NOT_IMPLEMENTED;
624 }
625
626
627 /* Function 22 */
628 NTSTATUS ElfrGetLogInformation(
629 IELF_HANDLE LogHandle,
630 DWORD InfoLevel,
631 BYTE *Buffer,
632 DWORD cbBufSize,
633 DWORD *pcbBytesNeeded)
634 {
635 NTSTATUS Status = STATUS_SUCCESS;
636
637 /* FIXME: check handle first */
638
639 switch (InfoLevel)
640 {
641 case EVENTLOG_FULL_INFO:
642 {
643 LPEVENTLOG_FULL_INFORMATION efi = (LPEVENTLOG_FULL_INFORMATION)Buffer;
644
645 *pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
646 if (cbBufSize < sizeof(EVENTLOG_FULL_INFORMATION))
647 {
648 return STATUS_BUFFER_TOO_SMALL;
649 }
650
651 efi->dwFull = 0; /* FIXME */
652 }
653 break;
654
655 default:
656 Status = STATUS_INVALID_LEVEL;
657 break;
658 }
659
660 return Status;
661 }
662
663
664 /* Function 23 */
665 NTSTATUS ElfrFlushEL(
666 IELF_HANDLE LogHandle)
667 {
668 UNIMPLEMENTED;
669 return STATUS_NOT_IMPLEMENTED;
670 }
671
672
673 /* Function 24 */
674 NTSTATUS ElfrReportEventAndSourceW(
675 IELF_HANDLE LogHandle,
676 DWORD Time,
677 USHORT EventType,
678 USHORT EventCategory,
679 ULONG EventID,
680 PRPC_UNICODE_STRING SourceName,
681 USHORT NumStrings,
682 DWORD DataSize,
683 PRPC_UNICODE_STRING ComputerName,
684 PRPC_SID UserSID,
685 PRPC_UNICODE_STRING Strings[],
686 BYTE *Data,
687 USHORT Flags,
688 DWORD *RecordNumber,
689 DWORD *TimeWritten)
690 {
691 UNIMPLEMENTED;
692 return STATUS_NOT_IMPLEMENTED;
693 }
694
695
696 void __RPC_FAR *__RPC_USER midl_user_allocate(SIZE_T len)
697 {
698 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
699 }
700
701
702 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
703 {
704 HeapFree(GetProcessHeap(), 0, ptr);
705 }
706
707
708 void __RPC_USER IELF_HANDLE_rundown(IELF_HANDLE LogHandle)
709 {
710 }