[EVENTLOG]
[reactos.git] / reactos / base / services / eventlog / file.c
1 /*
2 * PROJECT: ReactOS kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: services/eventlog/file.c
5 * PURPOSE: Event logging service
6 * COPYRIGHT: Copyright 2005 Saveliy Tretiakov
7 Michael Martin
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "eventlog.h"
13
14 /* GLOBALS ******************************************************************/
15
16 static LIST_ENTRY LogFileListHead;
17 static CRITICAL_SECTION LogFileListCs;
18
19 /* FUNCTIONS ****************************************************************/
20
21 BOOL LogfInitializeNew(PLOGFILE LogFile)
22 {
23 DWORD dwWritten;
24 EVENTLOGEOF EofRec;
25
26 ZeroMemory(&LogFile->Header, sizeof(EVENTLOGHEADER));
27 SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN);
28 SetEndOfFile(LogFile->hFile);
29
30 LogFile->Header.HeaderSize = sizeof(EVENTLOGHEADER);
31 LogFile->Header.EndHeaderSize = sizeof(EVENTLOGHEADER);
32 LogFile->Header.StartOffset = sizeof(EVENTLOGHEADER);
33 LogFile->Header.EndOffset = sizeof(EVENTLOGHEADER);
34 LogFile->Header.MajorVersion = MAJORVER;
35 LogFile->Header.MinorVersion = MINORVER;
36 LogFile->Header.CurrentRecordNumber = 1;
37 LogFile->Header.OldestRecordNumber = 1;
38 /* FIXME: Read MaxSize from registry for this LogFile.
39 But for now limit EventLog size to just under 5K. */
40 LogFile->Header.MaxSize = 5000;
41 LogFile->Header.Signature = LOGFILE_SIGNATURE;
42 if (!WriteFile(LogFile->hFile,
43 &LogFile->Header,
44 sizeof(EVENTLOGHEADER),
45 &dwWritten,
46 NULL))
47 {
48 DPRINT1("WriteFile failed:%d!\n", GetLastError());
49 return FALSE;
50 }
51
52 EofRec.Ones = 0x11111111;
53 EofRec.Twos = 0x22222222;
54 EofRec.Threes = 0x33333333;
55 EofRec.Fours = 0x44444444;
56 EofRec.RecordSizeBeginning = sizeof(EVENTLOGEOF);
57 EofRec.RecordSizeEnd = sizeof(EVENTLOGEOF);
58 EofRec.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
59 EofRec.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
60 EofRec.BeginRecord = LogFile->Header.StartOffset;
61 EofRec.EndRecord = LogFile->Header.EndOffset;
62
63 if (!WriteFile(LogFile->hFile,
64 &EofRec,
65 sizeof(EVENTLOGEOF),
66 &dwWritten,
67 NULL))
68 {
69 DPRINT1("WriteFile failed:%d!\n", GetLastError());
70 return FALSE;
71 }
72
73 if (!FlushFileBuffers(LogFile->hFile))
74 {
75 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
76 return FALSE;
77 }
78
79 return TRUE;
80 }
81
82 BOOL LogfInitializeExisting(PLOGFILE LogFile)
83 {
84 DWORD dwRead;
85 DWORD dwRecordsNumber = 0;
86 DWORD dwRecSize, dwRecSign, dwFilePointer;
87 PDWORD pdwRecSize2;
88 PEVENTLOGRECORD RecBuf;
89 BOOL OvewrWrittenRecords = FALSE;
90
91 DPRINT("Initializing LogFile %S\n",LogFile->LogName);
92
93 if (SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
94 INVALID_SET_FILE_POINTER)
95 {
96 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
97 return FALSE;
98 }
99
100 if (!ReadFile(LogFile->hFile,
101 &LogFile->Header,
102 sizeof(EVENTLOGHEADER),
103 &dwRead,
104 NULL))
105 {
106 DPRINT1("ReadFile failed! %d\n", GetLastError());
107 return FALSE;
108 }
109
110 if (dwRead != sizeof(EVENTLOGHEADER))
111 {
112 DPRINT("EventLog: Invalid file %S.\n", LogFile->FileName);
113 return LogfInitializeNew(LogFile);
114 }
115
116 if (LogFile->Header.HeaderSize != sizeof(EVENTLOGHEADER) ||
117 LogFile->Header.EndHeaderSize != sizeof(EVENTLOGHEADER))
118 {
119 DPRINT("EventLog: Invalid header size in %S.\n", LogFile->FileName);
120 return LogfInitializeNew(LogFile);
121 }
122
123 if (LogFile->Header.Signature != LOGFILE_SIGNATURE)
124 {
125 DPRINT("EventLog: Invalid signature %x in %S.\n",
126 LogFile->Header.Signature, LogFile->FileName);
127 return LogfInitializeNew(LogFile);
128 }
129
130 if (LogFile->Header.EndOffset > GetFileSize(LogFile->hFile, NULL) + 1)
131 {
132 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
133 LogFile->Header.EndOffset, LogFile->FileName);
134 return LogfInitializeNew(LogFile);
135 }
136
137 /* Set the read location to the oldest record */
138 dwFilePointer = SetFilePointer(LogFile->hFile, LogFile->Header.StartOffset, NULL, FILE_BEGIN);
139 if (dwFilePointer == INVALID_SET_FILE_POINTER)
140 {
141 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
142 return FALSE;
143 }
144
145 for (;;)
146 {
147 dwFilePointer = SetFilePointer(LogFile->hFile, 0, NULL, FILE_CURRENT);
148
149 if (dwFilePointer == INVALID_SET_FILE_POINTER)
150 {
151 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
152 return FALSE;
153 }
154
155 /* If the EVENTLOGEOF info has been reached and the oldest record was not immediately after the Header */
156 if ((dwFilePointer == LogFile->Header.EndOffset) && (LogFile->Header.StartOffset != sizeof(EVENTLOGHEADER)))
157 {
158 OvewrWrittenRecords = TRUE;
159 /* The file has records that overwrote old ones so read them */
160 dwFilePointer = SetFilePointer(LogFile->hFile, sizeof(EVENTLOGHEADER), NULL, FILE_BEGIN);
161 }
162
163 if (!ReadFile(LogFile->hFile,
164 &dwRecSize,
165 sizeof(dwRecSize),
166 &dwRead,
167 NULL))
168 {
169 DPRINT1("ReadFile failed! %d\n", GetLastError());
170 return FALSE;
171 }
172
173 if (dwRead != sizeof(dwRecSize))
174 break;
175
176 if (!ReadFile(LogFile->hFile,
177 &dwRecSign,
178 sizeof(dwRecSign),
179 &dwRead,
180 NULL))
181 {
182 DPRINT1("ReadFile() failed! %d\n", GetLastError());
183 return FALSE;
184 }
185
186 if (dwRead != sizeof(dwRecSize))
187 break;
188
189 if (dwRecSign != LOGFILE_SIGNATURE ||
190 dwRecSize + dwFilePointer > GetFileSize(LogFile->hFile, NULL) + 1 ||
191 dwRecSize < sizeof(EVENTLOGRECORD))
192 {
193 break;
194 }
195
196 if (SetFilePointer(LogFile->hFile,
197 -((LONG) sizeof(DWORD) * 2),
198 NULL,
199 FILE_CURRENT) == INVALID_SET_FILE_POINTER)
200 {
201 DPRINT1("SetFilePointer() failed! %d", GetLastError());
202 return FALSE;
203 }
204
205 RecBuf = (PEVENTLOGRECORD) HeapAlloc(MyHeap, 0, dwRecSize);
206
207 if (!RecBuf)
208 {
209 DPRINT1("Can't allocate heap!\n");
210 return FALSE;
211 }
212
213 if (!ReadFile(LogFile->hFile, RecBuf, dwRecSize, &dwRead, NULL))
214 {
215 DPRINT1("ReadFile() failed! %d\n", GetLastError());
216 HeapFree(MyHeap, 0, RecBuf);
217 return FALSE;
218 }
219
220 if (dwRead != dwRecSize)
221 {
222 HeapFree(MyHeap, 0, RecBuf);
223 break;
224 }
225
226 /* if OvewrWrittenRecords is TRUE and this record has already been read */
227 if ((OvewrWrittenRecords == TRUE) && (RecBuf->RecordNumber == LogFile->Header.OldestRecordNumber))
228 {
229 HeapFree(MyHeap, 0, RecBuf);
230 break;
231 }
232
233 pdwRecSize2 = (PDWORD) (((PBYTE) RecBuf) + dwRecSize - 4);
234
235 if (*pdwRecSize2 != dwRecSize)
236 {
237 DPRINT1("Invalid RecordSizeEnd of record %d (%x) in %S\n",
238 dwRecordsNumber, *pdwRecSize2, LogFile->LogName);
239 HeapFree(MyHeap, 0, RecBuf);
240 break;
241 }
242
243 dwRecordsNumber++;
244
245 if (!LogfAddOffsetInformation(LogFile,
246 RecBuf->RecordNumber,
247 dwFilePointer))
248 {
249 DPRINT1("LogfAddOffsetInformation() failed!\n");
250 HeapFree(MyHeap, 0, RecBuf);
251 return FALSE;
252 }
253
254 HeapFree(MyHeap, 0, RecBuf);
255 }
256
257 LogFile->Header.CurrentRecordNumber = dwRecordsNumber + LogFile->Header.OldestRecordNumber;
258 if (LogFile->Header.CurrentRecordNumber == 0)
259 LogFile->Header.CurrentRecordNumber = 1;
260
261 /* FIXME: Read MaxSize from registry for this LogFile.
262 But for now limit EventLog size to just under 5K. */
263 LogFile->Header.MaxSize = 5000;
264
265 if (SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
266 INVALID_SET_FILE_POINTER)
267 {
268 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
269 return FALSE;
270 }
271
272 if (!WriteFile(LogFile->hFile,
273 &LogFile->Header,
274 sizeof(EVENTLOGHEADER),
275 &dwRead,
276 NULL))
277 {
278 DPRINT1("WriteFile failed! %d\n", GetLastError());
279 return FALSE;
280 }
281
282 if (!FlushFileBuffers(LogFile->hFile))
283 {
284 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
285 return FALSE;
286 }
287
288 return TRUE;
289 }
290
291 PLOGFILE LogfCreate(WCHAR * LogName, WCHAR * FileName)
292 {
293 PLOGFILE LogFile;
294 BOOL bResult, bCreateNew = FALSE;
295
296 LogFile = (LOGFILE *) HeapAlloc(MyHeap, HEAP_ZERO_MEMORY, sizeof(LOGFILE));
297 if (!LogFile)
298 {
299 DPRINT1("Can't allocate heap!\n");
300 return NULL;
301 }
302
303 LogFile->hFile = CreateFile(FileName,
304 GENERIC_READ | GENERIC_WRITE,
305 FILE_SHARE_READ,
306 NULL,
307 OPEN_ALWAYS,
308 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
309 NULL);
310
311 if (LogFile->hFile == INVALID_HANDLE_VALUE)
312 {
313 DPRINT1("Can't create file %S.\n", FileName);
314 HeapFree(MyHeap, 0, LogFile);
315 return NULL;
316 }
317
318 bCreateNew = (GetLastError() == ERROR_ALREADY_EXISTS) ? FALSE : TRUE;
319
320 LogFile->LogName =
321 (WCHAR *) HeapAlloc(MyHeap,
322 HEAP_ZERO_MEMORY,
323 (lstrlenW(LogName) + 1) * sizeof(WCHAR));
324
325 if (LogFile->LogName)
326 lstrcpyW(LogFile->LogName, LogName);
327 else
328 {
329 DPRINT1("Can't allocate heap\n");
330 HeapFree(MyHeap, 0, LogFile);
331 return NULL;
332 }
333
334 LogFile->FileName =
335 (WCHAR *) HeapAlloc(MyHeap,
336 HEAP_ZERO_MEMORY,
337 (lstrlenW(FileName) + 1) * sizeof(WCHAR));
338
339 if (LogFile->FileName)
340 lstrcpyW(LogFile->FileName, FileName);
341 else
342 {
343 DPRINT1("Can't allocate heap\n");
344 goto fail;
345 }
346
347 LogFile->OffsetInfo =
348 (PEVENT_OFFSET_INFO) HeapAlloc(MyHeap,
349 HEAP_ZERO_MEMORY,
350 sizeof(EVENT_OFFSET_INFO) * 64);
351
352 if (!LogFile->OffsetInfo)
353 {
354 DPRINT1("Can't allocate heap\n");
355 goto fail;
356 }
357
358 LogFile->OffsetInfoSize = 64;
359
360 if (bCreateNew)
361 bResult = LogfInitializeNew(LogFile);
362 else
363 bResult = LogfInitializeExisting(LogFile);
364
365 if (!bResult)
366 goto fail;
367
368 RtlInitializeResource(&LogFile->Lock);
369
370 LogfListAddItem(LogFile);
371 return LogFile;
372
373 fail:
374 if (LogFile)
375 {
376 if (LogFile->OffsetInfo)
377 HeapFree(MyHeap, 0, LogFile->OffsetInfo);
378
379 if (LogFile->FileName)
380 HeapFree(MyHeap, 0, LogFile->FileName);
381
382 if (LogFile->LogName)
383 HeapFree(MyHeap, 0, LogFile->LogName);
384
385 HeapFree(MyHeap, 0, LogFile);
386 }
387
388 return NULL;
389 }
390
391 VOID LogfClose(PLOGFILE LogFile)
392 {
393 if (LogFile == NULL)
394 return;
395
396 RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
397
398 FlushFileBuffers(LogFile->hFile);
399 CloseHandle(LogFile->hFile);
400 LogfListRemoveItem(LogFile);
401
402 RtlDeleteResource(&LogFile->Lock);
403
404 HeapFree(MyHeap, 0, LogFile->LogName);
405 HeapFree(MyHeap, 0, LogFile->FileName);
406 HeapFree(MyHeap, 0, LogFile->OffsetInfo);
407 HeapFree(MyHeap, 0, LogFile);
408
409 return;
410 }
411
412 VOID LogfCloseAll(VOID)
413 {
414 while (!IsListEmpty(&LogFileListHead))
415 {
416 LogfClose(LogfListHead());
417 }
418
419 DeleteCriticalSection(&LogFileListCs);
420 }
421
422 VOID LogfListInitialize(VOID)
423 {
424 InitializeCriticalSection(&LogFileListCs);
425 InitializeListHead(&LogFileListHead);
426 }
427
428 PLOGFILE LogfListHead(VOID)
429 {
430 return CONTAINING_RECORD(LogFileListHead.Flink, LOGFILE, ListEntry);
431 }
432
433 PLOGFILE LogfListItemByName(WCHAR * Name)
434 {
435 PLIST_ENTRY CurrentEntry;
436 PLOGFILE Result = NULL;
437
438 EnterCriticalSection(&LogFileListCs);
439
440 CurrentEntry = LogFileListHead.Flink;
441 while (CurrentEntry != &LogFileListHead)
442 {
443 PLOGFILE Item = CONTAINING_RECORD(CurrentEntry,
444 LOGFILE,
445 ListEntry);
446
447 if (Item->LogName && !lstrcmpi(Item->LogName, Name))
448 {
449 Result = Item;
450 break;
451 }
452
453 CurrentEntry = CurrentEntry->Flink;
454 }
455
456 LeaveCriticalSection(&LogFileListCs);
457 return Result;
458 }
459
460 /* Index starting from 1 */
461 INT LogfListItemIndexByName(WCHAR * Name)
462 {
463 PLIST_ENTRY CurrentEntry;
464 INT Result = 0;
465 INT i = 1;
466
467 EnterCriticalSection(&LogFileListCs);
468
469 CurrentEntry = LogFileListHead.Flink;
470 while (CurrentEntry != &LogFileListHead)
471 {
472 PLOGFILE Item = CONTAINING_RECORD(CurrentEntry,
473 LOGFILE,
474 ListEntry);
475
476 if (Item->LogName && !lstrcmpi(Item->LogName, Name))
477 {
478 Result = i;
479 break;
480 }
481
482 CurrentEntry = CurrentEntry->Flink;
483 i++;
484 }
485
486 LeaveCriticalSection(&LogFileListCs);
487 return Result;
488 }
489
490 /* Index starting from 1 */
491 PLOGFILE LogfListItemByIndex(INT Index)
492 {
493 PLIST_ENTRY CurrentEntry;
494 PLOGFILE Result = NULL;
495 INT i = 1;
496
497 EnterCriticalSection(&LogFileListCs);
498
499 CurrentEntry = LogFileListHead.Flink;
500 while (CurrentEntry != &LogFileListHead)
501 {
502 if (i == Index)
503 {
504 Result = CONTAINING_RECORD(CurrentEntry, LOGFILE, ListEntry);
505 break;
506 }
507
508 CurrentEntry = CurrentEntry->Flink;
509 i++;
510 }
511
512 LeaveCriticalSection(&LogFileListCs);
513 return Result;
514 }
515
516 INT LogfListItemCount(VOID)
517 {
518 PLIST_ENTRY CurrentEntry;
519 INT i = 0;
520
521 EnterCriticalSection(&LogFileListCs);
522
523 CurrentEntry = LogFileListHead.Flink;
524 while (CurrentEntry != &LogFileListHead)
525 {
526 CurrentEntry = CurrentEntry->Flink;
527 i++;
528 }
529
530 LeaveCriticalSection(&LogFileListCs);
531 return i;
532 }
533
534 VOID LogfListAddItem(PLOGFILE Item)
535 {
536 EnterCriticalSection(&LogFileListCs);
537 InsertTailList(&LogFileListHead, &Item->ListEntry);
538 LeaveCriticalSection(&LogFileListCs);
539 }
540
541 VOID LogfListRemoveItem(PLOGFILE Item)
542 {
543 EnterCriticalSection(&LogFileListCs);
544 RemoveEntryList(&Item->ListEntry);
545 LeaveCriticalSection(&LogFileListCs);
546 }
547
548 static BOOL
549 ReadAnsiLogEntry(HANDLE hFile,
550 LPVOID lpBuffer,
551 DWORD nNumberOfBytesToRead,
552 LPDWORD lpNumberOfBytesRead)
553 {
554 PEVENTLOGRECORD Dst;
555 PEVENTLOGRECORD Src;
556 ANSI_STRING StringA;
557 UNICODE_STRING StringW;
558 LPWSTR SrcPtr;
559 LPSTR DstPtr;
560 LPWSTR SrcString;
561 LPSTR DstString;
562 LPVOID lpUnicodeBuffer = NULL;
563 DWORD dwRead = 0;
564 DWORD i;
565 DWORD dwPadding;
566 DWORD dwEntryLength;
567 PDWORD pLength;
568 NTSTATUS Status;
569 BOOL ret = TRUE;
570
571 *lpNumberOfBytesRead = 0;
572
573 lpUnicodeBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nNumberOfBytesToRead);
574 if (lpUnicodeBuffer == NULL)
575 {
576 DPRINT1("Alloc failed!\n");
577 return FALSE;
578 }
579
580 if (!ReadFile(hFile, lpUnicodeBuffer, nNumberOfBytesToRead, &dwRead, NULL))
581 {
582 DPRINT1("Read failed!\n");
583 ret = FALSE;
584 goto done;
585 }
586
587 Dst = (PEVENTLOGRECORD)lpBuffer;
588 Src = (PEVENTLOGRECORD)lpUnicodeBuffer;
589
590 Dst->TimeGenerated = Src->TimeGenerated;
591 Dst->Reserved = Src->Reserved;
592 Dst->RecordNumber = Src->RecordNumber;
593 Dst->TimeWritten = Src->TimeWritten;
594 Dst->EventID = Src->EventID;
595 Dst->EventType = Src->EventType;
596 Dst->EventCategory = Src->EventCategory;
597 Dst->NumStrings = Src->NumStrings;
598 Dst->UserSidLength = Src->UserSidLength;
599 Dst->DataLength = Src->DataLength;
600
601 SrcPtr = (LPWSTR)((DWORD_PTR)Src + sizeof(EVENTLOGRECORD));
602 DstPtr = (LPSTR)((DWORD_PTR)Dst + sizeof(EVENTLOGRECORD));
603
604 /* Convert the module name */
605 RtlInitUnicodeString(&StringW, SrcPtr);
606 Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
607 if (NT_SUCCESS(Status))
608 {
609 RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength);
610
611 DstPtr = (PVOID)((DWORD_PTR)DstPtr + StringA.MaximumLength);
612
613 RtlFreeAnsiString(&StringA);
614 }
615
616 /* Convert the computer name */
617 if (NT_SUCCESS(Status))
618 {
619 SrcPtr = (PWSTR)((DWORD_PTR)SrcPtr + StringW.MaximumLength);
620
621 RtlInitUnicodeString(&StringW, SrcPtr);
622 Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
623 if (NT_SUCCESS(Status))
624 {
625 RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength);
626
627 DstPtr = (PVOID)((DWORD_PTR)DstPtr + StringA.MaximumLength);
628
629 RtlFreeAnsiString(&StringA);
630 }
631 }
632
633 /* Add the padding and the User SID*/
634 if (NT_SUCCESS(Status))
635 {
636 dwPadding = sizeof(DWORD) - (((DWORD_PTR)DstPtr - (DWORD_PTR)Dst) % sizeof(DWORD));
637 RtlZeroMemory(DstPtr, dwPadding);
638
639 DstPtr = (LPSTR)((DWORD_PTR)DstPtr + dwPadding);
640 RtlCopyMemory(DstPtr,
641 (PVOID)((DWORD_PTR)Src + Src->UserSidOffset),
642 Src->UserSidLength);
643
644 Dst->UserSidOffset = (DWORD)((DWORD_PTR)DstPtr - (DWORD_PTR)Dst);
645 }
646
647
648 /* Convert the strings */
649 if (NT_SUCCESS(Status))
650 {
651 DstPtr = (PVOID)((DWORD_PTR)DstPtr + Src->UserSidLength);
652
653 SrcString = (LPWSTR)((DWORD_PTR)Src + (DWORD)Src->StringOffset);
654 DstString = (LPSTR)DstPtr;
655
656 for (i = 0; i < Dst->NumStrings; i++)
657 {
658 RtlInitUnicodeString(&StringW, SrcString);
659
660 RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE);
661
662 RtlCopyMemory(DstString, StringA.Buffer, StringA.MaximumLength);
663
664 SrcString = (LPWSTR)((DWORD_PTR)SrcString +
665 (DWORD)StringW.MaximumLength);
666
667 DstString = (LPSTR)((DWORD_PTR)DstString +
668 (DWORD)StringA.MaximumLength);
669
670 RtlFreeAnsiString(&StringA);
671 }
672
673 Dst->StringOffset = (DWORD)((DWORD_PTR)DstPtr - (DWORD_PTR)Dst);
674
675
676 /* Copy the binary data */
677 DstPtr = (PVOID)DstString;
678 Dst->DataOffset = (DWORD_PTR)DstPtr - (DWORD_PTR)Dst;
679
680 RtlCopyMemory(DstPtr, (PVOID)((DWORD_PTR)Src + Src->DataOffset), Src->DataLength);
681
682 /* Add the padding */
683 DstPtr = (PVOID)((DWORD_PTR)DstPtr + Src->DataLength);
684 dwPadding = sizeof(DWORD) - (((DWORD_PTR)DstPtr-(DWORD_PTR)Dst) % sizeof(DWORD));
685 RtlZeroMemory(DstPtr, dwPadding);
686
687 dwEntryLength = (DWORD)((DWORD_PTR)DstPtr + dwPadding + sizeof(DWORD) - (DWORD_PTR)Dst);
688
689 /* Set the entry length at the end of the entry*/
690 pLength = (PDWORD)((DWORD_PTR)DstPtr + dwPadding);
691 *pLength = dwEntryLength;
692 Dst->Length = dwEntryLength;
693
694 *lpNumberOfBytesRead = dwEntryLength;
695 }
696
697 done:
698 if (lpUnicodeBuffer != NULL)
699 HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer);
700
701 return ret;
702 }
703
704
705 DWORD LogfReadEvent(PLOGFILE LogFile,
706 DWORD Flags,
707 DWORD * RecordNumber,
708 DWORD BufSize,
709 PBYTE Buffer,
710 DWORD * BytesRead,
711 DWORD * BytesNeeded,
712 BOOL Ansi)
713 {
714 DWORD dwOffset, dwRead, dwRecSize;
715 DWORD dwBufferUsage = 0, dwRecNum;
716
717 if (Flags & EVENTLOG_FORWARDS_READ && Flags & EVENTLOG_BACKWARDS_READ)
718 return ERROR_INVALID_PARAMETER;
719
720 if (!(Flags & EVENTLOG_FORWARDS_READ) && !(Flags & EVENTLOG_BACKWARDS_READ))
721 return ERROR_INVALID_PARAMETER;
722
723 if (!Buffer || !BytesRead || !BytesNeeded)
724 return ERROR_INVALID_PARAMETER;
725
726 if ((*RecordNumber==0) && !(EVENTLOG_SEQUENTIAL_READ))
727 {
728 return ERROR_INVALID_PARAMETER;
729 }
730
731 dwRecNum = *RecordNumber;
732
733 RtlAcquireResourceShared(&LogFile->Lock, TRUE);
734
735 *BytesRead = 0;
736 *BytesNeeded = 0;
737
738 dwOffset = LogfOffsetByNumber(LogFile, dwRecNum);
739
740 if (!dwOffset)
741 {
742 RtlReleaseResource(&LogFile->Lock);
743 return ERROR_HANDLE_EOF;
744 }
745
746 if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) ==
747 INVALID_SET_FILE_POINTER)
748 {
749 DPRINT1("SetFilePointer() failed!\n");
750 goto Done;
751 }
752
753 if (!ReadFile(LogFile->hFile, &dwRecSize, sizeof(DWORD), &dwRead, NULL))
754 {
755 DPRINT1("ReadFile() failed!\n");
756 goto Done;
757 }
758
759 if (dwRecSize > BufSize)
760 {
761 *BytesNeeded = dwRecSize;
762 RtlReleaseResource(&LogFile->Lock);
763 return ERROR_INSUFFICIENT_BUFFER;
764 }
765
766 if (SetFilePointer(LogFile->hFile,
767 -((LONG) sizeof(DWORD)),
768 NULL,
769 FILE_CURRENT) == INVALID_SET_FILE_POINTER)
770 {
771 DPRINT1("SetFilePointer() failed!\n");
772 goto Done;
773 }
774
775 if (Ansi == TRUE)
776 {
777 if (!ReadAnsiLogEntry(LogFile->hFile, Buffer, dwRecSize, &dwRead))
778 {
779 DPRINT1("ReadAnsiLogEntry() failed!\n");
780 goto Done;
781 }
782 }
783 else
784 {
785 if (!ReadFile(LogFile->hFile, Buffer, dwRecSize, &dwRead, NULL))
786 {
787 DPRINT1("ReadFile() failed!\n");
788 goto Done;
789 }
790 }
791
792 dwBufferUsage += dwRead;
793
794 while (dwBufferUsage <= BufSize)
795 {
796 if (Flags & EVENTLOG_FORWARDS_READ)
797 dwRecNum++;
798 else
799 dwRecNum--;
800
801 dwOffset = LogfOffsetByNumber(LogFile, dwRecNum);
802 if (!dwOffset)
803 break;
804
805 if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) ==
806 INVALID_SET_FILE_POINTER)
807 {
808 DPRINT1("SetFilePointer() failed!\n");
809 goto Done;
810 }
811
812 if (!ReadFile(LogFile->hFile,
813 &dwRecSize,
814 sizeof(DWORD),
815 &dwRead,
816 NULL))
817 {
818 DPRINT1("ReadFile() failed!\n");
819 goto Done;
820 }
821
822 if (dwBufferUsage + dwRecSize > BufSize)
823 break;
824
825 if (SetFilePointer(LogFile->hFile,
826 -((LONG) sizeof(DWORD)),
827 NULL,
828 FILE_CURRENT) == INVALID_SET_FILE_POINTER)
829 {
830 DPRINT1("SetFilePointer() failed!\n");
831 goto Done;
832 }
833
834 if (Ansi == TRUE)
835 {
836 if (!ReadAnsiLogEntry(LogFile->hFile,
837 Buffer + dwBufferUsage,
838 dwRecSize,
839 &dwRead))
840 {
841 DPRINT1("ReadAnsiLogEntry() failed!\n");
842 goto Done;
843 }
844 }
845 else
846 {
847 if (!ReadFile(LogFile->hFile,
848 Buffer + dwBufferUsage,
849 dwRecSize,
850 &dwRead,
851 NULL))
852 {
853 DPRINT1("ReadFile() failed!\n");
854 goto Done;
855 }
856 }
857
858 dwBufferUsage += dwRead;
859 }
860
861 *BytesRead = dwBufferUsage;
862 * RecordNumber = dwRecNum;
863 RtlReleaseResource(&LogFile->Lock);
864 return ERROR_SUCCESS;
865
866 Done:
867 DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
868 RtlReleaseResource(&LogFile->Lock);
869 return GetLastError();
870 }
871
872 BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
873 {
874 DWORD dwWritten;
875 DWORD dwRead;
876 SYSTEMTIME st;
877 EVENTLOGEOF EofRec;
878 PEVENTLOGRECORD RecBuf;
879 LARGE_INTEGER logFileSize;
880 ULONG RecOffSet;
881 ULONG WriteOffSet;
882
883 if (!Buffer)
884 return FALSE;
885
886 GetSystemTime(&st);
887 SystemTimeToEventTime(&st, &((PEVENTLOGRECORD) Buffer)->TimeWritten);
888
889 RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
890
891 if (!GetFileSizeEx(LogFile->hFile, &logFileSize))
892 {
893 RtlReleaseResource(&LogFile->Lock);
894 return FALSE;
895 }
896
897 /* If the size of the file is over MaxSize */
898 if ((logFileSize.QuadPart + BufSize)> LogFile->Header.MaxSize)
899 {
900 ULONG OverWriteLength = 0;
901 WriteOffSet = LogfOffsetByNumber(LogFile, LogFile->Header.OldestRecordNumber);
902 RecBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(EVENTLOGRECORD));
903 /* Determine how many records need to be overwritten */
904 while (TRUE)
905 {
906 DPRINT("EventLogFile has reached maximume size\n");
907
908 if (!RecBuf)
909 {
910 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
911 HeapFree(GetProcessHeap(), 0, RecBuf);
912 RtlReleaseResource(&LogFile->Lock);
913 return FALSE;
914 }
915
916 /* Get the oldest record data */
917 RecOffSet = LogfOffsetByNumber(LogFile, LogFile->Header.OldestRecordNumber);
918
919 if (SetFilePointer(LogFile->hFile,
920 RecOffSet,
921 NULL,
922 FILE_BEGIN) == INVALID_SET_FILE_POINTER)
923 {
924 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
925 HeapFree(GetProcessHeap(), 0, RecBuf);
926 RtlReleaseResource(&LogFile->Lock);
927 return FALSE;
928 }
929
930 if (!ReadFile(LogFile->hFile, RecBuf, sizeof(EVENTLOGRECORD), &dwRead, NULL))
931 {
932 DPRINT1("ReadFile() failed!\n");
933 HeapFree(GetProcessHeap(), 0, RecBuf);
934 RtlReleaseResource(&LogFile->Lock);
935 return FALSE;
936 }
937
938 if (RecBuf->Reserved != LOGFILE_SIGNATURE)
939 {
940 DPRINT1("LogFile corrupt!\n");
941 RtlReleaseResource(&LogFile->Lock);
942 return FALSE;
943 }
944
945 LogfDeleteOffsetInformation(LogFile,LogFile->Header.OldestRecordNumber);
946
947 LogFile->Header.OldestRecordNumber++;
948
949 OverWriteLength += RecBuf->Length;
950 /* Check the size of the record as the record adding may be larger */
951 if (OverWriteLength >= BufSize)
952 {
953 DPRINT("Record will fit. Lenght %d, BufSize %d\n", OverWriteLength, BufSize);
954 LogFile->Header.StartOffset = LogfOffsetByNumber(LogFile, LogFile->Header.OldestRecordNumber);
955 break;
956 }
957 }
958 HeapFree(GetProcessHeap(), 0, RecBuf);
959 }
960 else
961 WriteOffSet = LogFile->Header.EndOffset;
962
963 if (SetFilePointer(LogFile->hFile,
964 WriteOffSet,
965 NULL,
966 FILE_BEGIN) == INVALID_SET_FILE_POINTER)
967 {
968 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
969 RtlReleaseResource(&LogFile->Lock);
970 return FALSE;
971 }
972
973 if (!WriteFile(LogFile->hFile, Buffer, BufSize, &dwWritten, NULL))
974 {
975 DPRINT1("WriteFile() failed! %d\n", GetLastError());
976 RtlReleaseResource(&LogFile->Lock);
977 return FALSE;
978 }
979
980 if (!LogfAddOffsetInformation(LogFile,
981 LogFile->Header.CurrentRecordNumber,
982 WriteOffSet))
983 {
984 RtlReleaseResource(&LogFile->Lock);
985 return FALSE;
986 }
987
988 LogFile->Header.CurrentRecordNumber++;
989
990 if (WriteOffSet == LogFile->Header.EndOffset)
991 {
992 LogFile->Header.EndOffset += dwWritten;
993 }
994 if (SetFilePointer(LogFile->hFile,
995 LogFile->Header.EndOffset,
996 NULL,
997 FILE_BEGIN) == INVALID_SET_FILE_POINTER)
998 {
999 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1000 RtlReleaseResource(&LogFile->Lock);
1001 return FALSE;
1002 }
1003
1004 EofRec.Ones = 0x11111111;
1005 EofRec.Twos = 0x22222222;
1006 EofRec.Threes = 0x33333333;
1007 EofRec.Fours = 0x44444444;
1008 EofRec.RecordSizeBeginning = sizeof(EVENTLOGEOF);
1009 EofRec.RecordSizeEnd = sizeof(EVENTLOGEOF);
1010 EofRec.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
1011 EofRec.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
1012 EofRec.BeginRecord = LogFile->Header.StartOffset;
1013 EofRec.EndRecord = LogFile->Header.EndOffset;
1014
1015 if (!WriteFile(LogFile->hFile,
1016 &EofRec,
1017 sizeof(EVENTLOGEOF),
1018 &dwWritten,
1019 NULL))
1020 {
1021 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1022 RtlReleaseResource(&LogFile->Lock);
1023 return FALSE;
1024 }
1025
1026 if (SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
1027 INVALID_SET_FILE_POINTER)
1028 {
1029 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1030 RtlReleaseResource(&LogFile->Lock);
1031 return FALSE;
1032 }
1033
1034 if (!WriteFile(LogFile->hFile,
1035 &LogFile->Header,
1036 sizeof(EVENTLOGHEADER),
1037 &dwWritten,
1038 NULL))
1039 {
1040 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
1041 RtlReleaseResource(&LogFile->Lock);
1042 return FALSE;
1043 }
1044
1045 if (!FlushFileBuffers(LogFile->hFile))
1046 {
1047 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
1048 RtlReleaseResource(&LogFile->Lock);
1049 return FALSE;
1050 }
1051
1052 RtlReleaseResource(&LogFile->Lock);
1053 return TRUE;
1054 }
1055
1056
1057 NTSTATUS
1058 LogfClearFile(PLOGFILE LogFile,
1059 PUNICODE_STRING BackupFileName)
1060 {
1061 RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
1062
1063 if (BackupFileName->Length > 0)
1064 {
1065 /* FIXME: Write a backup file */
1066 }
1067
1068 LogfInitializeNew(LogFile);
1069
1070 RtlReleaseResource(&LogFile->Lock);
1071
1072 return STATUS_SUCCESS;
1073 }
1074
1075
1076 NTSTATUS
1077 LogfBackupFile(PLOGFILE LogFile,
1078 PUNICODE_STRING BackupFileName)
1079 {
1080 OBJECT_ATTRIBUTES ObjectAttributes;
1081 IO_STATUS_BLOCK IoStatusBlock;
1082 EVENTLOGHEADER Header;
1083 EVENTLOGEOF EofRec;
1084 HANDLE FileHandle = NULL;
1085 ULONG i;
1086 LARGE_INTEGER FileOffset;
1087 NTSTATUS Status;
1088 PUCHAR Buffer = NULL;
1089
1090 DWORD dwOffset, dwRead, dwRecSize;
1091
1092 DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile, BackupFileName);
1093
1094 /* Lock the log file shared */
1095 RtlAcquireResourceShared(&LogFile->Lock, TRUE);
1096
1097 InitializeObjectAttributes(&ObjectAttributes,
1098 BackupFileName,
1099 OBJ_CASE_INSENSITIVE,
1100 NULL,
1101 NULL);
1102
1103 Status = NtCreateFile(&FileHandle,
1104 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
1105 &ObjectAttributes,
1106 &IoStatusBlock,
1107 NULL,
1108 FILE_ATTRIBUTE_NORMAL,
1109 FILE_SHARE_READ,
1110 FILE_CREATE,
1111 FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
1112 NULL,
1113 0);
1114 if (!NT_SUCCESS(Status))
1115 {
1116 DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName, Status);
1117 goto Done;
1118 }
1119
1120 /* Initialize the (dirty) log file header */
1121 Header.HeaderSize = sizeof(EVENTLOGHEADER);
1122 Header.Signature = LOGFILE_SIGNATURE;
1123 Header.MajorVersion = MAJORVER;
1124 Header.MinorVersion = MINORVER;
1125 Header.StartOffset = sizeof(EVENTLOGHEADER);
1126 Header.EndOffset = sizeof(EVENTLOGHEADER);
1127 Header.CurrentRecordNumber = 1;
1128 Header.OldestRecordNumber = 1;
1129 Header.MaxSize = 0;
1130 Header.Flags = ELF_LOGFILE_HEADER_DIRTY;
1131 Header.Retention = LogFile->Header.Retention;
1132 Header.EndHeaderSize = sizeof(EVENTLOGHEADER);
1133
1134 /* Write the (dirty) log file header */
1135 Status = NtWriteFile(FileHandle,
1136 NULL,
1137 NULL,
1138 NULL,
1139 &IoStatusBlock,
1140 &Header,
1141 sizeof(EVENTLOGHEADER),
1142 NULL,
1143 NULL);
1144 if (!NT_SUCCESS(Status))
1145 {
1146 DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status);
1147 goto Done;
1148 }
1149
1150 for (i = LogFile->Header.OldestRecordNumber; i < LogFile->Header.CurrentRecordNumber; i++)
1151 {
1152 dwOffset = LogfOffsetByNumber(LogFile, i);
1153 if (dwOffset == 0)
1154 break;
1155
1156 if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
1157 {
1158 DPRINT1("SetFilePointer() failed!\n");
1159 goto Done;
1160 }
1161
1162 if (!ReadFile(LogFile->hFile, &dwRecSize, sizeof(DWORD), &dwRead, NULL))
1163 {
1164 DPRINT1("ReadFile() failed!\n");
1165 goto Done;
1166 }
1167
1168 if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
1169 {
1170 DPRINT1("SetFilePointer() failed!\n");
1171 goto Done;
1172 }
1173
1174 Buffer = HeapAlloc(MyHeap, 0, dwRecSize);
1175 if (Buffer == NULL)
1176 {
1177 DPRINT1("HeapAlloc() failed!\n");
1178 goto Done;
1179 }
1180
1181 if (!ReadFile(LogFile->hFile, &Buffer, dwRecSize, &dwRead, NULL))
1182 {
1183 DPRINT1("ReadFile() failed!\n");
1184 goto Done;
1185 }
1186
1187 /* Write the event record */
1188 Status = NtWriteFile(FileHandle,
1189 NULL,
1190 NULL,
1191 NULL,
1192 &IoStatusBlock,
1193 Buffer,
1194 dwRecSize,
1195 NULL,
1196 NULL);
1197 if (!NT_SUCCESS(Status))
1198 {
1199 DPRINT1("NtWriteFile() failed!\n");
1200 goto Done;
1201 }
1202
1203 /* Update the header information */
1204 Header.EndOffset += dwRecSize;
1205
1206 /* Free the buffer */
1207 HeapFree(MyHeap, 0, Buffer);
1208 Buffer = NULL;
1209 }
1210
1211 /* Initialize the EOF record */
1212 EofRec.RecordSizeBeginning = sizeof(EVENTLOGEOF);
1213 EofRec.Ones = 0x11111111;
1214 EofRec.Twos = 0x22222222;
1215 EofRec.Threes = 0x33333333;
1216 EofRec.Fours = 0x44444444;
1217 EofRec.BeginRecord = sizeof(EVENTLOGHEADER);
1218 EofRec.EndRecord = Header.EndOffset;
1219 EofRec.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
1220 EofRec.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
1221 EofRec.RecordSizeEnd = sizeof(EVENTLOGEOF);
1222
1223 /* Write the EOF record */
1224 Status = NtWriteFile(FileHandle,
1225 NULL,
1226 NULL,
1227 NULL,
1228 &IoStatusBlock,
1229 &EofRec,
1230 sizeof(EVENTLOGEOF),
1231 NULL,
1232 NULL);
1233 if (!NT_SUCCESS(Status))
1234 {
1235 DPRINT1("NtWriteFile() failed!\n");
1236 goto Done;
1237 }
1238
1239 /* Update the header information */
1240 Header.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
1241 Header.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
1242 Header.MaxSize = Header.EndOffset + sizeof(EVENTLOGEOF);
1243 Header.Flags = 0;
1244
1245 /* Write the (clean) log file header */
1246 FileOffset.QuadPart = 0;
1247 Status = NtWriteFile(FileHandle,
1248 NULL,
1249 NULL,
1250 NULL,
1251 &IoStatusBlock,
1252 &Header,
1253 sizeof(EVENTLOGHEADER),
1254 &FileOffset,
1255 NULL);
1256 if (!NT_SUCCESS(Status))
1257 {
1258 DPRINT1("NtWriteFile() failed!\n");
1259 }
1260
1261 Done:
1262 /* Free the buffer */
1263 if (Buffer != NULL)
1264 HeapFree(MyHeap, 0, Buffer);
1265
1266 /* Close the backup file */
1267 if (FileHandle != NULL)
1268 NtClose(FileHandle);
1269
1270 /* Unlock the log file */
1271 RtlReleaseResource(&LogFile->Lock);
1272
1273 return Status;
1274 }
1275
1276
1277 /* Returns 0 if nothing found. */
1278 ULONG LogfOffsetByNumber(PLOGFILE LogFile, DWORD RecordNumber)
1279 {
1280 DWORD i;
1281
1282 for (i = 0; i < LogFile->OffsetInfoNext; i++)
1283 {
1284 if (LogFile->OffsetInfo[i].EventNumber == RecordNumber)
1285 return LogFile->OffsetInfo[i].EventOffset;
1286 }
1287 return 0;
1288 }
1289
1290 DWORD LogfGetOldestRecord(PLOGFILE LogFile)
1291 {
1292 return LogFile->Header.OldestRecordNumber;
1293 }
1294
1295 DWORD LogfGetCurrentRecord(PLOGFILE LogFile)
1296 {
1297 return LogFile->Header.CurrentRecordNumber;
1298 }
1299
1300 BOOL LogfDeleteOffsetInformation(PLOGFILE LogFile, ULONG ulNumber)
1301 {
1302 DWORD i;
1303
1304 if (ulNumber != LogFile->OffsetInfo[0].EventNumber)
1305 {
1306 return FALSE;
1307 }
1308
1309 for (i = 0; i < LogFile->OffsetInfoNext - 1; i++)
1310 {
1311 LogFile->OffsetInfo[i].EventNumber = LogFile->OffsetInfo[i + 1].EventNumber;
1312 LogFile->OffsetInfo[i].EventOffset = LogFile->OffsetInfo[i + 1].EventOffset;
1313 }
1314 LogFile->OffsetInfoNext--;
1315 return TRUE;
1316 }
1317
1318 BOOL LogfAddOffsetInformation(PLOGFILE LogFile, ULONG ulNumber, ULONG ulOffset)
1319 {
1320 LPVOID NewOffsetInfo;
1321
1322 if (LogFile->OffsetInfoNext == LogFile->OffsetInfoSize)
1323 {
1324 NewOffsetInfo = HeapReAlloc(MyHeap,
1325 HEAP_ZERO_MEMORY,
1326 LogFile->OffsetInfo,
1327 (LogFile->OffsetInfoSize + 64) *
1328 sizeof(EVENT_OFFSET_INFO));
1329
1330 if (!NewOffsetInfo)
1331 {
1332 DPRINT1("Can't reallocate heap.\n");
1333 return FALSE;
1334 }
1335
1336 LogFile->OffsetInfo = (PEVENT_OFFSET_INFO) NewOffsetInfo;
1337 LogFile->OffsetInfoSize += 64;
1338 }
1339
1340 LogFile->OffsetInfo[LogFile->OffsetInfoNext].EventNumber = ulNumber;
1341 LogFile->OffsetInfo[LogFile->OffsetInfoNext].EventOffset = ulOffset;
1342 LogFile->OffsetInfoNext++;
1343
1344 return TRUE;
1345 }
1346
1347 PBYTE LogfAllocAndBuildNewRecord(LPDWORD lpRecSize,
1348 DWORD dwRecordNumber,
1349 WORD wType,
1350 WORD wCategory,
1351 DWORD dwEventId,
1352 LPCWSTR SourceName,
1353 LPCWSTR ComputerName,
1354 DWORD dwSidLength,
1355 PSID lpUserSid,
1356 WORD wNumStrings,
1357 WCHAR * lpStrings,
1358 DWORD dwDataSize,
1359 LPVOID lpRawData)
1360 {
1361 DWORD dwRecSize;
1362 PEVENTLOGRECORD pRec;
1363 SYSTEMTIME SysTime;
1364 WCHAR *str;
1365 UINT i, pos;
1366 PBYTE Buffer;
1367
1368 dwRecSize =
1369 sizeof(EVENTLOGRECORD) + (lstrlenW(ComputerName) +
1370 lstrlenW(SourceName) + 2) * sizeof(WCHAR);
1371
1372 if (dwRecSize % 4 != 0)
1373 dwRecSize += 4 - (dwRecSize % 4);
1374
1375 dwRecSize += dwSidLength;
1376
1377 for (i = 0, str = lpStrings; i < wNumStrings; i++)
1378 {
1379 dwRecSize += (lstrlenW(str) + 1) * sizeof(WCHAR);
1380 str += lstrlenW(str) + 1;
1381 }
1382
1383 dwRecSize += dwDataSize;
1384 if (dwRecSize % 4 != 0)
1385 dwRecSize += 4 - (dwRecSize % 4);
1386
1387 dwRecSize += 4;
1388
1389 Buffer = HeapAlloc(MyHeap, HEAP_ZERO_MEMORY, dwRecSize);
1390
1391 if (!Buffer)
1392 {
1393 DPRINT1("Can't allocate heap!\n");
1394 return NULL;
1395 }
1396
1397 pRec = (PEVENTLOGRECORD) Buffer;
1398 pRec->Length = dwRecSize;
1399 pRec->Reserved = LOGFILE_SIGNATURE;
1400 pRec->RecordNumber = dwRecordNumber;
1401
1402 GetSystemTime(&SysTime);
1403 SystemTimeToEventTime(&SysTime, &pRec->TimeGenerated);
1404 SystemTimeToEventTime(&SysTime, &pRec->TimeWritten);
1405
1406 pRec->EventID = dwEventId;
1407 pRec->EventType = wType;
1408 pRec->EventCategory = wCategory;
1409
1410 pos = sizeof(EVENTLOGRECORD);
1411
1412 lstrcpyW((WCHAR *) (Buffer + pos), SourceName);
1413 pos += (lstrlenW(SourceName) + 1) * sizeof(WCHAR);
1414 lstrcpyW((WCHAR *) (Buffer + pos), ComputerName);
1415 pos += (lstrlenW(ComputerName) + 1) * sizeof(WCHAR);
1416
1417 pRec->UserSidOffset = pos;
1418
1419 if (pos % 4 != 0)
1420 pos += 4 - (pos % 4);
1421
1422 if (dwSidLength)
1423 {
1424 CopyMemory(Buffer + pos, lpUserSid, dwSidLength);
1425 pRec->UserSidLength = dwSidLength;
1426 pRec->UserSidOffset = pos;
1427 pos += dwSidLength;
1428 }
1429
1430 pRec->StringOffset = pos;
1431 for (i = 0, str = lpStrings; i < wNumStrings; i++)
1432 {
1433 lstrcpyW((WCHAR *) (Buffer + pos), str);
1434 pos += (lstrlenW(str) + 1) * sizeof(WCHAR);
1435 str += lstrlenW(str) + 1;
1436 }
1437 pRec->NumStrings = wNumStrings;
1438
1439 pRec->DataOffset = pos;
1440 if (dwDataSize)
1441 {
1442 pRec->DataLength = dwDataSize;
1443 CopyMemory(Buffer + pos, lpRawData, dwDataSize);
1444 pos += dwDataSize;
1445 }
1446
1447 if (pos % 4 != 0)
1448 pos += 4 - (pos % 4);
1449
1450 *((PDWORD) (Buffer + pos)) = dwRecSize;
1451
1452 *lpRecSize = dwRecSize;
1453 return Buffer;
1454 }
1455
1456
1457 VOID
1458 LogfReportEvent(WORD wType,
1459 WORD wCategory,
1460 DWORD dwEventId,
1461 WORD wNumStrings,
1462 WCHAR *lpStrings,
1463 DWORD dwDataSize,
1464 LPVOID lpRawData)
1465 {
1466 WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
1467 DWORD dwComputerNameLength = MAX_COMPUTERNAME_LENGTH + 1;
1468 PEVENTSOURCE pEventSource = NULL;
1469 PBYTE logBuffer;
1470 DWORD lastRec;
1471 DWORD recSize;
1472 DWORD dwError;
1473
1474 if (!GetComputerNameW(szComputerName, &dwComputerNameLength))
1475 {
1476 szComputerName[0] = 0;
1477 }
1478
1479 pEventSource = GetEventSourceByName(L"EventLog");
1480 if (pEventSource == NULL)
1481 {
1482 return;
1483 }
1484
1485 lastRec = LogfGetCurrentRecord(pEventSource->LogFile);
1486
1487 logBuffer = LogfAllocAndBuildNewRecord(&recSize,
1488 lastRec,
1489 wType,
1490 wCategory,
1491 dwEventId,
1492 pEventSource->szName,
1493 (LPCWSTR)szComputerName,
1494 0,
1495 NULL,
1496 wNumStrings,
1497 lpStrings,
1498 dwDataSize,
1499 lpRawData);
1500
1501 dwError = LogfWriteData(pEventSource->LogFile, recSize, logBuffer);
1502 if (!dwError)
1503 {
1504 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource->LogFile->FileName);
1505 }
1506
1507 LogfFreeRecord(logBuffer);
1508 }