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