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