* Sync up to trunk HEAD (r62502).
[reactos.git] / 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 NTSTATUS Status;
1103
1104 RtlAcquireResourceExclusive(&LogFile->Lock, TRUE);
1105
1106 if (BackupFileName->Length > 0)
1107 {
1108 /* Write a backup file */
1109 Status = LogfBackupFile(LogFile,
1110 BackupFileName);
1111 if (!NT_SUCCESS(Status))
1112 {
1113 DPRINT1("LogfBackupFile failed (Status: 0x%08lx)\n", Status);
1114 return Status;
1115 }
1116 }
1117
1118 Status = LogfInitializeNew(LogFile);
1119 if (!NT_SUCCESS(Status))
1120 {
1121 DPRINT1("LogfInitializeNew failed (Status: 0x%08lx)\n", Status);
1122 }
1123
1124 RtlReleaseResource(&LogFile->Lock);
1125
1126 return Status;
1127 }
1128
1129
1130 NTSTATUS
1131 LogfBackupFile(PLOGFILE LogFile,
1132 PUNICODE_STRING BackupFileName)
1133 {
1134 OBJECT_ATTRIBUTES ObjectAttributes;
1135 IO_STATUS_BLOCK IoStatusBlock;
1136 EVENTLOGHEADER Header;
1137 EVENTLOGEOF EofRec;
1138 HANDLE FileHandle = NULL;
1139 ULONG i;
1140 LARGE_INTEGER FileOffset;
1141 NTSTATUS Status;
1142 PUCHAR Buffer = NULL;
1143
1144 DWORD dwOffset, dwRead, dwRecSize;
1145
1146 DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile, BackupFileName);
1147
1148 /* Lock the log file shared */
1149 RtlAcquireResourceShared(&LogFile->Lock, TRUE);
1150
1151 InitializeObjectAttributes(&ObjectAttributes,
1152 BackupFileName,
1153 OBJ_CASE_INSENSITIVE,
1154 NULL,
1155 NULL);
1156
1157 Status = NtCreateFile(&FileHandle,
1158 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
1159 &ObjectAttributes,
1160 &IoStatusBlock,
1161 NULL,
1162 FILE_ATTRIBUTE_NORMAL,
1163 FILE_SHARE_READ,
1164 FILE_CREATE,
1165 FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
1166 NULL,
1167 0);
1168 if (!NT_SUCCESS(Status))
1169 {
1170 DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName, Status);
1171 goto Done;
1172 }
1173
1174 /* Initialize the (dirty) log file header */
1175 Header.HeaderSize = sizeof(EVENTLOGHEADER);
1176 Header.Signature = LOGFILE_SIGNATURE;
1177 Header.MajorVersion = MAJORVER;
1178 Header.MinorVersion = MINORVER;
1179 Header.StartOffset = sizeof(EVENTLOGHEADER);
1180 Header.EndOffset = sizeof(EVENTLOGHEADER);
1181 Header.CurrentRecordNumber = 1;
1182 Header.OldestRecordNumber = 1;
1183 Header.MaxSize = 0;
1184 Header.Flags = ELF_LOGFILE_HEADER_DIRTY;
1185 Header.Retention = LogFile->Header.Retention;
1186 Header.EndHeaderSize = sizeof(EVENTLOGHEADER);
1187
1188 /* Write the (dirty) log file header */
1189 Status = NtWriteFile(FileHandle,
1190 NULL,
1191 NULL,
1192 NULL,
1193 &IoStatusBlock,
1194 &Header,
1195 sizeof(EVENTLOGHEADER),
1196 NULL,
1197 NULL);
1198 if (!NT_SUCCESS(Status))
1199 {
1200 DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status);
1201 goto Done;
1202 }
1203
1204 for (i = LogFile->Header.OldestRecordNumber; i < LogFile->Header.CurrentRecordNumber; i++)
1205 {
1206 dwOffset = LogfOffsetByNumber(LogFile, i);
1207 if (dwOffset == 0)
1208 break;
1209
1210 if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
1211 {
1212 DPRINT1("SetFilePointer() failed!\n");
1213 goto Done;
1214 }
1215
1216 if (!ReadFile(LogFile->hFile, &dwRecSize, sizeof(DWORD), &dwRead, NULL))
1217 {
1218 DPRINT1("ReadFile() failed!\n");
1219 goto Done;
1220 }
1221
1222 if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
1223 {
1224 DPRINT1("SetFilePointer() failed!\n");
1225 goto Done;
1226 }
1227
1228 Buffer = HeapAlloc(MyHeap, 0, dwRecSize);
1229 if (Buffer == NULL)
1230 {
1231 DPRINT1("HeapAlloc() failed!\n");
1232 goto Done;
1233 }
1234
1235 if (!ReadFile(LogFile->hFile, &Buffer, dwRecSize, &dwRead, NULL))
1236 {
1237 DPRINT1("ReadFile() failed!\n");
1238 goto Done;
1239 }
1240
1241 /* Write the event record */
1242 Status = NtWriteFile(FileHandle,
1243 NULL,
1244 NULL,
1245 NULL,
1246 &IoStatusBlock,
1247 Buffer,
1248 dwRecSize,
1249 NULL,
1250 NULL);
1251 if (!NT_SUCCESS(Status))
1252 {
1253 DPRINT1("NtWriteFile() failed!\n");
1254 goto Done;
1255 }
1256
1257 /* Update the header information */
1258 Header.EndOffset += dwRecSize;
1259
1260 /* Free the buffer */
1261 HeapFree(MyHeap, 0, Buffer);
1262 Buffer = NULL;
1263 }
1264
1265 /* Initialize the EOF record */
1266 EofRec.RecordSizeBeginning = sizeof(EVENTLOGEOF);
1267 EofRec.Ones = 0x11111111;
1268 EofRec.Twos = 0x22222222;
1269 EofRec.Threes = 0x33333333;
1270 EofRec.Fours = 0x44444444;
1271 EofRec.BeginRecord = sizeof(EVENTLOGHEADER);
1272 EofRec.EndRecord = Header.EndOffset;
1273 EofRec.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
1274 EofRec.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
1275 EofRec.RecordSizeEnd = sizeof(EVENTLOGEOF);
1276
1277 /* Write the EOF record */
1278 Status = NtWriteFile(FileHandle,
1279 NULL,
1280 NULL,
1281 NULL,
1282 &IoStatusBlock,
1283 &EofRec,
1284 sizeof(EVENTLOGEOF),
1285 NULL,
1286 NULL);
1287 if (!NT_SUCCESS(Status))
1288 {
1289 DPRINT1("NtWriteFile() failed!\n");
1290 goto Done;
1291 }
1292
1293 /* Update the header information */
1294 Header.CurrentRecordNumber = LogFile->Header.CurrentRecordNumber;
1295 Header.OldestRecordNumber = LogFile->Header.OldestRecordNumber;
1296 Header.MaxSize = Header.EndOffset + sizeof(EVENTLOGEOF);
1297 Header.Flags = 0;
1298
1299 /* Write the (clean) log file header */
1300 FileOffset.QuadPart = 0;
1301 Status = NtWriteFile(FileHandle,
1302 NULL,
1303 NULL,
1304 NULL,
1305 &IoStatusBlock,
1306 &Header,
1307 sizeof(EVENTLOGHEADER),
1308 &FileOffset,
1309 NULL);
1310 if (!NT_SUCCESS(Status))
1311 {
1312 DPRINT1("NtWriteFile() failed!\n");
1313 }
1314
1315 Done:
1316 /* Free the buffer */
1317 if (Buffer != NULL)
1318 HeapFree(MyHeap, 0, Buffer);
1319
1320 /* Close the backup file */
1321 if (FileHandle != NULL)
1322 NtClose(FileHandle);
1323
1324 /* Unlock the log file */
1325 RtlReleaseResource(&LogFile->Lock);
1326
1327 return Status;
1328 }
1329
1330
1331 /* Returns 0 if nothing found. */
1332 ULONG LogfOffsetByNumber(PLOGFILE LogFile, DWORD RecordNumber)
1333 {
1334 DWORD i;
1335
1336 for (i = 0; i < LogFile->OffsetInfoNext; i++)
1337 {
1338 if (LogFile->OffsetInfo[i].EventNumber == RecordNumber)
1339 return LogFile->OffsetInfo[i].EventOffset;
1340 }
1341 return 0;
1342 }
1343
1344 DWORD LogfGetOldestRecord(PLOGFILE LogFile)
1345 {
1346 return LogFile->Header.OldestRecordNumber;
1347 }
1348
1349 DWORD LogfGetCurrentRecord(PLOGFILE LogFile)
1350 {
1351 return LogFile->Header.CurrentRecordNumber;
1352 }
1353
1354 BOOL LogfDeleteOffsetInformation(PLOGFILE LogFile, ULONG ulNumber)
1355 {
1356 DWORD i;
1357
1358 if (ulNumber != LogFile->OffsetInfo[0].EventNumber)
1359 {
1360 return FALSE;
1361 }
1362
1363 for (i = 0; i < LogFile->OffsetInfoNext - 1; i++)
1364 {
1365 LogFile->OffsetInfo[i].EventNumber = LogFile->OffsetInfo[i + 1].EventNumber;
1366 LogFile->OffsetInfo[i].EventOffset = LogFile->OffsetInfo[i + 1].EventOffset;
1367 }
1368 LogFile->OffsetInfoNext--;
1369 return TRUE;
1370 }
1371
1372 BOOL LogfAddOffsetInformation(PLOGFILE LogFile, ULONG ulNumber, ULONG ulOffset)
1373 {
1374 LPVOID NewOffsetInfo;
1375
1376 if (LogFile->OffsetInfoNext == LogFile->OffsetInfoSize)
1377 {
1378 NewOffsetInfo = HeapReAlloc(MyHeap,
1379 HEAP_ZERO_MEMORY,
1380 LogFile->OffsetInfo,
1381 (LogFile->OffsetInfoSize + 64) *
1382 sizeof(EVENT_OFFSET_INFO));
1383
1384 if (!NewOffsetInfo)
1385 {
1386 DPRINT1("Can't reallocate heap.\n");
1387 return FALSE;
1388 }
1389
1390 LogFile->OffsetInfo = (PEVENT_OFFSET_INFO) NewOffsetInfo;
1391 LogFile->OffsetInfoSize += 64;
1392 }
1393
1394 LogFile->OffsetInfo[LogFile->OffsetInfoNext].EventNumber = ulNumber;
1395 LogFile->OffsetInfo[LogFile->OffsetInfoNext].EventOffset = ulOffset;
1396 LogFile->OffsetInfoNext++;
1397
1398 return TRUE;
1399 }
1400
1401 PBYTE LogfAllocAndBuildNewRecord(LPDWORD lpRecSize,
1402 DWORD dwRecordNumber,
1403 WORD wType,
1404 WORD wCategory,
1405 DWORD dwEventId,
1406 LPCWSTR SourceName,
1407 LPCWSTR ComputerName,
1408 DWORD dwSidLength,
1409 PSID lpUserSid,
1410 WORD wNumStrings,
1411 WCHAR * lpStrings,
1412 DWORD dwDataSize,
1413 LPVOID lpRawData)
1414 {
1415 DWORD dwRecSize;
1416 PEVENTLOGRECORD pRec;
1417 SYSTEMTIME SysTime;
1418 WCHAR *str;
1419 UINT i, pos;
1420 PBYTE Buffer;
1421
1422 dwRecSize =
1423 sizeof(EVENTLOGRECORD) + (lstrlenW(ComputerName) +
1424 lstrlenW(SourceName) + 2) * sizeof(WCHAR);
1425
1426 if (dwRecSize % 4 != 0)
1427 dwRecSize += 4 - (dwRecSize % 4);
1428
1429 dwRecSize += dwSidLength;
1430
1431 for (i = 0, str = lpStrings; i < wNumStrings; i++)
1432 {
1433 dwRecSize += (lstrlenW(str) + 1) * sizeof(WCHAR);
1434 str += lstrlenW(str) + 1;
1435 }
1436
1437 dwRecSize += dwDataSize;
1438 if (dwRecSize % 4 != 0)
1439 dwRecSize += 4 - (dwRecSize % 4);
1440
1441 dwRecSize += 4;
1442
1443 Buffer = HeapAlloc(MyHeap, HEAP_ZERO_MEMORY, dwRecSize);
1444
1445 if (!Buffer)
1446 {
1447 DPRINT1("Can't allocate heap!\n");
1448 return NULL;
1449 }
1450
1451 pRec = (PEVENTLOGRECORD) Buffer;
1452 pRec->Length = dwRecSize;
1453 pRec->Reserved = LOGFILE_SIGNATURE;
1454 pRec->RecordNumber = dwRecordNumber;
1455
1456 GetSystemTime(&SysTime);
1457 SystemTimeToEventTime(&SysTime, &pRec->TimeGenerated);
1458 SystemTimeToEventTime(&SysTime, &pRec->TimeWritten);
1459
1460 pRec->EventID = dwEventId;
1461 pRec->EventType = wType;
1462 pRec->EventCategory = wCategory;
1463
1464 pos = sizeof(EVENTLOGRECORD);
1465
1466 lstrcpyW((WCHAR *) (Buffer + pos), SourceName);
1467 pos += (lstrlenW(SourceName) + 1) * sizeof(WCHAR);
1468 lstrcpyW((WCHAR *) (Buffer + pos), ComputerName);
1469 pos += (lstrlenW(ComputerName) + 1) * sizeof(WCHAR);
1470
1471 pRec->UserSidOffset = pos;
1472
1473 if (pos % 4 != 0)
1474 pos += 4 - (pos % 4);
1475
1476 if (dwSidLength)
1477 {
1478 CopyMemory(Buffer + pos, lpUserSid, dwSidLength);
1479 pRec->UserSidLength = dwSidLength;
1480 pRec->UserSidOffset = pos;
1481 pos += dwSidLength;
1482 }
1483
1484 pRec->StringOffset = pos;
1485 for (i = 0, str = lpStrings; i < wNumStrings; i++)
1486 {
1487 lstrcpyW((WCHAR *) (Buffer + pos), str);
1488 pos += (lstrlenW(str) + 1) * sizeof(WCHAR);
1489 str += lstrlenW(str) + 1;
1490 }
1491 pRec->NumStrings = wNumStrings;
1492
1493 pRec->DataOffset = pos;
1494 if (dwDataSize)
1495 {
1496 pRec->DataLength = dwDataSize;
1497 CopyMemory(Buffer + pos, lpRawData, dwDataSize);
1498 pos += dwDataSize;
1499 }
1500
1501 if (pos % 4 != 0)
1502 pos += 4 - (pos % 4);
1503
1504 *((PDWORD) (Buffer + pos)) = dwRecSize;
1505
1506 *lpRecSize = dwRecSize;
1507 return Buffer;
1508 }
1509
1510
1511 VOID
1512 LogfReportEvent(WORD wType,
1513 WORD wCategory,
1514 DWORD dwEventId,
1515 WORD wNumStrings,
1516 WCHAR *lpStrings,
1517 DWORD dwDataSize,
1518 LPVOID lpRawData)
1519 {
1520 WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
1521 DWORD dwComputerNameLength = MAX_COMPUTERNAME_LENGTH + 1;
1522 PEVENTSOURCE pEventSource = NULL;
1523 PBYTE logBuffer;
1524 DWORD lastRec;
1525 DWORD recSize;
1526 DWORD dwError;
1527
1528 if (!GetComputerNameW(szComputerName, &dwComputerNameLength))
1529 {
1530 szComputerName[0] = 0;
1531 }
1532
1533 pEventSource = GetEventSourceByName(L"EventLog");
1534 if (pEventSource == NULL)
1535 {
1536 return;
1537 }
1538
1539 lastRec = LogfGetCurrentRecord(pEventSource->LogFile);
1540
1541 logBuffer = LogfAllocAndBuildNewRecord(&recSize,
1542 lastRec,
1543 wType,
1544 wCategory,
1545 dwEventId,
1546 pEventSource->szName,
1547 (LPCWSTR)szComputerName,
1548 0,
1549 NULL,
1550 wNumStrings,
1551 lpStrings,
1552 dwDataSize,
1553 lpRawData);
1554
1555 dwError = LogfWriteData(pEventSource->LogFile, recSize, logBuffer);
1556 if (!dwError)
1557 {
1558 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource->LogFile->FileName);
1559 }
1560
1561 LogfFreeRecord(logBuffer);
1562 }