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
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS ******************************************************************/
16 static LIST_ENTRY LogFileListHead
;
17 static CRITICAL_SECTION LogFileListCs
;
19 /* FUNCTIONS ****************************************************************/
21 BOOL
LogfInitializeNew(PLOGFILE LogFile
)
26 ZeroMemory(&LogFile
->Header
, sizeof(EVENTLOGHEADER
));
27 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
28 SetEndOfFile(LogFile
->hFile
);
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 /* FIXME: Read MaxSize from registry for this LogFile.
38 But for now limit EventLog size to just under 5K. */
39 LogFile
->Header
.MaxSize
= 5000;
40 LogFile
->Header
.Signature
= LOGFILE_SIGNATURE
;
41 if (!WriteFile(LogFile
->hFile
,
43 sizeof(EVENTLOGHEADER
),
47 DPRINT1("WriteFile failed:%d!\n", GetLastError());
51 EofRec
.Ones
= 0x11111111;
52 EofRec
.Twos
= 0x22222222;
53 EofRec
.Threes
= 0x33333333;
54 EofRec
.Fours
= 0x44444444;
55 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
56 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
57 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
58 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
59 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
60 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
62 if (!WriteFile(LogFile
->hFile
,
68 DPRINT1("WriteFile failed:%d!\n", GetLastError());
72 if (!FlushFileBuffers(LogFile
->hFile
))
74 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
81 BOOL
LogfInitializeExisting(PLOGFILE LogFile
)
84 DWORD dwRecordsNumber
= 0;
85 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
87 PEVENTLOGRECORD RecBuf
;
88 BOOL OvewrWrittenRecords
= FALSE
;
90 DPRINT("Initializing LogFile %S\n",LogFile
->LogName
);
92 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
93 INVALID_SET_FILE_POINTER
)
95 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
99 if (!ReadFile(LogFile
->hFile
,
101 sizeof(EVENTLOGHEADER
),
105 DPRINT1("ReadFile failed! %d\n", GetLastError());
109 if (dwRead
!= sizeof(EVENTLOGHEADER
))
111 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
112 return LogfInitializeNew(LogFile
);
115 if (LogFile
->Header
.HeaderSize
!= sizeof(EVENTLOGHEADER
) ||
116 LogFile
->Header
.EndHeaderSize
!= sizeof(EVENTLOGHEADER
))
118 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
119 return LogfInitializeNew(LogFile
);
122 if (LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
124 DPRINT("EventLog: Invalid signature %x in %S.\n",
125 LogFile
->Header
.Signature
, LogFile
->FileName
);
126 return LogfInitializeNew(LogFile
);
129 if (LogFile
->Header
.EndOffset
> GetFileSize(LogFile
->hFile
, NULL
) + 1)
131 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
132 LogFile
->Header
.EndOffset
, LogFile
->FileName
);
133 return LogfInitializeNew(LogFile
);
136 /* Set the read location to the oldest record */
137 dwFilePointer
= SetFilePointer(LogFile
->hFile
, LogFile
->Header
.StartOffset
, NULL
, FILE_BEGIN
);
138 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
140 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
146 dwFilePointer
= SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
);
148 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
150 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
154 /* If the EVENTLOGEOF info has been reached and the oldest record was not immediately after the Header */
155 if ((dwFilePointer
== LogFile
->Header
.EndOffset
) && (LogFile
->Header
.StartOffset
!= sizeof(EVENTLOGHEADER
)))
157 OvewrWrittenRecords
= TRUE
;
158 /* The file has records that overwrote old ones so read them */
159 dwFilePointer
= SetFilePointer(LogFile
->hFile
, sizeof(EVENTLOGHEADER
), NULL
, FILE_BEGIN
);
162 if (!ReadFile(LogFile
->hFile
,
168 DPRINT1("ReadFile failed! %d\n", GetLastError());
172 if (dwRead
!= sizeof(dwRecSize
))
175 if (!ReadFile(LogFile
->hFile
,
181 DPRINT1("ReadFile() failed! %d\n", GetLastError());
185 if (dwRead
!= sizeof(dwRecSize
))
188 if (dwRecSign
!= LOGFILE_SIGNATURE
||
189 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
) + 1 ||
190 dwRecSize
< sizeof(EVENTLOGRECORD
))
195 if (SetFilePointer(LogFile
->hFile
,
196 -((LONG
) sizeof(DWORD
) * 2),
198 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
200 DPRINT1("SetFilePointer() failed! %d", GetLastError());
204 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
208 DPRINT1("Can't allocate heap!\n");
212 if (!ReadFile(LogFile
->hFile
, RecBuf
, dwRecSize
, &dwRead
, NULL
))
214 DPRINT1("ReadFile() failed! %d\n", GetLastError());
215 HeapFree(MyHeap
, 0, RecBuf
);
219 if (dwRead
!= dwRecSize
)
221 HeapFree(MyHeap
, 0, RecBuf
);
225 /* if OvewrWrittenRecords is TRUE and this record has already been read */
226 if ((OvewrWrittenRecords
== TRUE
) && (RecBuf
->RecordNumber
== LogFile
->Header
.OldestRecordNumber
))
228 HeapFree(MyHeap
, 0, RecBuf
);
232 pdwRecSize2
= (PDWORD
) (((PBYTE
) RecBuf
) + dwRecSize
- 4);
234 if (*pdwRecSize2
!= dwRecSize
)
236 DPRINT1("Invalid RecordSizeEnd of record %d (%x) in %S\n",
237 dwRecordsNumber
, *pdwRecSize2
, LogFile
->LogName
);
238 HeapFree(MyHeap
, 0, RecBuf
);
244 if (!LogfAddOffsetInformation(LogFile
,
245 RecBuf
->RecordNumber
,
248 DPRINT1("LogfAddOffsetInformation() failed!\n");
249 HeapFree(MyHeap
, 0, RecBuf
);
253 HeapFree(MyHeap
, 0, RecBuf
);
256 LogFile
->Header
.CurrentRecordNumber
= dwRecordsNumber
+ LogFile
->Header
.OldestRecordNumber
;
257 if (LogFile
->Header
.CurrentRecordNumber
== 0)
258 LogFile
->Header
.CurrentRecordNumber
= 1;
260 /* FIXME: Read MaxSize from registry for this LogFile.
261 But for now limit EventLog size to just under 5K. */
262 LogFile
->Header
.MaxSize
= 5000;
264 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
265 INVALID_SET_FILE_POINTER
)
267 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
271 if (!WriteFile(LogFile
->hFile
,
273 sizeof(EVENTLOGHEADER
),
277 DPRINT1("WriteFile failed! %d\n", GetLastError());
281 if (!FlushFileBuffers(LogFile
->hFile
))
283 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
290 PLOGFILE
LogfCreate(WCHAR
* LogName
, WCHAR
* FileName
)
293 BOOL bResult
, bCreateNew
= FALSE
;
295 LogFile
= (LOGFILE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(LOGFILE
));
298 DPRINT1("Can't allocate heap!\n");
302 LogFile
->hFile
= CreateFile(FileName
,
303 GENERIC_READ
| GENERIC_WRITE
,
307 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
310 if (LogFile
->hFile
== INVALID_HANDLE_VALUE
)
312 DPRINT1("Can't create file %S.\n", FileName
);
313 HeapFree(MyHeap
, 0, LogFile
);
317 bCreateNew
= (GetLastError() == ERROR_ALREADY_EXISTS
) ? FALSE
: TRUE
;
320 (WCHAR
*) HeapAlloc(MyHeap
,
322 (lstrlenW(LogName
) + 1) * sizeof(WCHAR
));
324 if (LogFile
->LogName
)
325 lstrcpyW(LogFile
->LogName
, LogName
);
328 DPRINT1("Can't allocate heap\n");
329 HeapFree(MyHeap
, 0, LogFile
);
334 (WCHAR
*) HeapAlloc(MyHeap
,
336 (lstrlenW(FileName
) + 1) * sizeof(WCHAR
));
338 if (LogFile
->FileName
)
339 lstrcpyW(LogFile
->FileName
, FileName
);
342 DPRINT1("Can't allocate heap\n");
346 LogFile
->OffsetInfo
=
347 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
349 sizeof(EVENT_OFFSET_INFO
) * 64);
351 if (!LogFile
->OffsetInfo
)
353 DPRINT1("Can't allocate heap\n");
357 LogFile
->OffsetInfoSize
= 64;
360 bResult
= LogfInitializeNew(LogFile
);
362 bResult
= LogfInitializeExisting(LogFile
);
367 InitializeCriticalSection(&LogFile
->cs
);
368 LogfListAddItem(LogFile
);
374 if (LogFile
->OffsetInfo
)
375 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
377 if (LogFile
->FileName
)
378 HeapFree(MyHeap
, 0, LogFile
->FileName
);
380 if (LogFile
->LogName
)
381 HeapFree(MyHeap
, 0, LogFile
->LogName
);
383 HeapFree(MyHeap
, 0, LogFile
);
389 VOID
LogfClose(PLOGFILE LogFile
)
394 EnterCriticalSection(&LogFile
->cs
);
396 FlushFileBuffers(LogFile
->hFile
);
397 CloseHandle(LogFile
->hFile
);
398 LogfListRemoveItem(LogFile
);
400 DeleteCriticalSection(&LogFile
->cs
);
402 HeapFree(MyHeap
, 0, LogFile
->LogName
);
403 HeapFree(MyHeap
, 0, LogFile
->FileName
);
404 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
405 HeapFree(MyHeap
, 0, LogFile
);
410 VOID
LogfCloseAll(VOID
)
412 while (!IsListEmpty(&LogFileListHead
))
414 LogfClose(LogfListHead());
417 DeleteCriticalSection(&LogFileListCs
);
420 VOID
LogfListInitialize(VOID
)
422 InitializeCriticalSection(&LogFileListCs
);
423 InitializeListHead(&LogFileListHead
);
426 PLOGFILE
LogfListHead(VOID
)
428 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
431 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
433 PLIST_ENTRY CurrentEntry
;
434 PLOGFILE Result
= NULL
;
436 EnterCriticalSection(&LogFileListCs
);
438 CurrentEntry
= LogFileListHead
.Flink
;
439 while (CurrentEntry
!= &LogFileListHead
)
441 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
445 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
451 CurrentEntry
= CurrentEntry
->Flink
;
454 LeaveCriticalSection(&LogFileListCs
);
458 /* Index starting from 1 */
459 INT
LogfListItemIndexByName(WCHAR
* Name
)
461 PLIST_ENTRY CurrentEntry
;
465 EnterCriticalSection(&LogFileListCs
);
467 CurrentEntry
= LogFileListHead
.Flink
;
468 while (CurrentEntry
!= &LogFileListHead
)
470 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
474 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
480 CurrentEntry
= CurrentEntry
->Flink
;
484 LeaveCriticalSection(&LogFileListCs
);
488 /* Index starting from 1 */
489 PLOGFILE
LogfListItemByIndex(INT Index
)
491 PLIST_ENTRY CurrentEntry
;
492 PLOGFILE Result
= NULL
;
495 EnterCriticalSection(&LogFileListCs
);
497 CurrentEntry
= LogFileListHead
.Flink
;
498 while (CurrentEntry
!= &LogFileListHead
)
502 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
506 CurrentEntry
= CurrentEntry
->Flink
;
510 LeaveCriticalSection(&LogFileListCs
);
514 INT
LogfListItemCount(VOID
)
516 PLIST_ENTRY CurrentEntry
;
519 EnterCriticalSection(&LogFileListCs
);
521 CurrentEntry
= LogFileListHead
.Flink
;
522 while (CurrentEntry
!= &LogFileListHead
)
524 CurrentEntry
= CurrentEntry
->Flink
;
528 LeaveCriticalSection(&LogFileListCs
);
532 VOID
LogfListAddItem(PLOGFILE Item
)
534 EnterCriticalSection(&LogFileListCs
);
535 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
536 LeaveCriticalSection(&LogFileListCs
);
539 VOID
LogfListRemoveItem(PLOGFILE Item
)
541 EnterCriticalSection(&LogFileListCs
);
542 RemoveEntryList(&Item
->ListEntry
);
543 LeaveCriticalSection(&LogFileListCs
);
547 ReadAnsiLogEntry(HANDLE hFile
,
549 DWORD nNumberOfBytesToRead
,
550 LPDWORD lpNumberOfBytesRead
)
555 UNICODE_STRING StringW
;
560 LPVOID lpUnicodeBuffer
= NULL
;
569 *lpNumberOfBytesRead
= 0;
571 lpUnicodeBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nNumberOfBytesToRead
);
572 if (lpUnicodeBuffer
== NULL
)
574 DPRINT1("Alloc failed!\n");
578 if (!ReadFile(hFile
, lpUnicodeBuffer
, nNumberOfBytesToRead
, &dwRead
, NULL
))
580 DPRINT1("Read failed!\n");
585 Dst
= (PEVENTLOGRECORD
)lpBuffer
;
586 Src
= (PEVENTLOGRECORD
)lpUnicodeBuffer
;
588 Dst
->TimeGenerated
= Src
->TimeGenerated
;
589 Dst
->Reserved
= Src
->Reserved
;
590 Dst
->RecordNumber
= Src
->RecordNumber
;
591 Dst
->TimeWritten
= Src
->TimeWritten
;
592 Dst
->EventID
= Src
->EventID
;
593 Dst
->EventType
= Src
->EventType
;
594 Dst
->EventCategory
= Src
->EventCategory
;
595 Dst
->NumStrings
= Src
->NumStrings
;
596 Dst
->UserSidLength
= Src
->UserSidLength
;
597 Dst
->DataLength
= Src
->DataLength
;
599 SrcPtr
= (LPWSTR
)((DWORD_PTR
)Src
+ sizeof(EVENTLOGRECORD
));
600 DstPtr
= (LPSTR
)((DWORD_PTR
)Dst
+ sizeof(EVENTLOGRECORD
));
602 /* Convert the module name */
603 RtlInitUnicodeString(&StringW
, SrcPtr
);
604 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
605 if (NT_SUCCESS(Status
))
607 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
609 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
611 RtlFreeAnsiString(&StringA
);
614 /* Convert the computer name */
615 if (NT_SUCCESS(Status
))
617 SrcPtr
= (PWSTR
)((DWORD_PTR
)SrcPtr
+ StringW
.MaximumLength
);
619 RtlInitUnicodeString(&StringW
, SrcPtr
);
620 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
621 if (NT_SUCCESS(Status
))
623 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
625 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
627 RtlFreeAnsiString(&StringA
);
631 /* Add the padding and the User SID*/
632 if (NT_SUCCESS(Status
))
634 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
) % sizeof(DWORD
));
635 RtlZeroMemory(DstPtr
, dwPadding
);
637 DstPtr
= (LPSTR
)((DWORD_PTR
)DstPtr
+ dwPadding
);
638 RtlCopyMemory(DstPtr
,
639 (PVOID
)((DWORD_PTR
)Src
+ Src
->UserSidOffset
),
642 Dst
->UserSidOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
646 /* Convert the strings */
647 if (NT_SUCCESS(Status
))
649 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->UserSidLength
);
651 SrcString
= (LPWSTR
)((DWORD_PTR
)Src
+ (DWORD
)Src
->StringOffset
);
652 DstString
= (LPSTR
)DstPtr
;
654 for (i
= 0; i
< Dst
->NumStrings
; i
++)
656 RtlInitUnicodeString(&StringW
, SrcString
);
658 RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
660 RtlCopyMemory(DstString
, StringA
.Buffer
, StringA
.MaximumLength
);
662 SrcString
= (LPWSTR
)((DWORD_PTR
)SrcString
+
663 (DWORD
)StringW
.MaximumLength
);
665 DstString
= (LPSTR
)((DWORD_PTR
)DstString
+
666 (DWORD
)StringA
.MaximumLength
);
668 RtlFreeAnsiString(&StringA
);
671 Dst
->StringOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
674 /* Copy the binary data */
675 DstPtr
= (PVOID
)DstString
;
676 Dst
->DataOffset
= (DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
;
678 RtlCopyMemory(DstPtr
, (PVOID
)((DWORD_PTR
)Src
+ Src
->DataOffset
), Src
->DataLength
);
680 /* Add the padding */
681 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->DataLength
);
682 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
-(DWORD_PTR
)Dst
) % sizeof(DWORD
));
683 RtlZeroMemory(DstPtr
, dwPadding
);
685 dwEntryLength
= (DWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
+ sizeof(DWORD
) - (DWORD_PTR
)Dst
);
687 /* Set the entry length at the end of the entry*/
688 pLength
= (PDWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
);
689 *pLength
= dwEntryLength
;
690 Dst
->Length
= dwEntryLength
;
692 *lpNumberOfBytesRead
= dwEntryLength
;
696 if (lpUnicodeBuffer
!= NULL
)
697 HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer
);
703 DWORD
LogfReadEvent(PLOGFILE LogFile
,
705 DWORD
* RecordNumber
,
712 DWORD dwOffset
, dwRead
, dwRecSize
;
713 DWORD dwBufferUsage
= 0, dwRecNum
;
715 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
716 return ERROR_INVALID_PARAMETER
;
718 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
719 return ERROR_INVALID_PARAMETER
;
721 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
722 return ERROR_INVALID_PARAMETER
;
724 if ((*RecordNumber
==0) && !(EVENTLOG_SEQUENTIAL_READ
))
726 return ERROR_INVALID_PARAMETER
;
729 dwRecNum
= *RecordNumber
;
730 EnterCriticalSection(&LogFile
->cs
);
735 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
739 LeaveCriticalSection(&LogFile
->cs
);
740 return ERROR_HANDLE_EOF
;
743 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
744 INVALID_SET_FILE_POINTER
)
746 DPRINT1("SetFilePointer() failed!\n");
750 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
752 DPRINT1("ReadFile() failed!\n");
756 if (dwRecSize
> BufSize
)
758 *BytesNeeded
= dwRecSize
;
759 LeaveCriticalSection(&LogFile
->cs
);
760 return ERROR_INSUFFICIENT_BUFFER
;
763 if (SetFilePointer(LogFile
->hFile
,
764 -((LONG
) sizeof(DWORD
)),
766 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
768 DPRINT1("SetFilePointer() failed!\n");
774 if (!ReadAnsiLogEntry(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
))
776 DPRINT1("ReadAnsiLogEntry() failed!\n");
782 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
784 DPRINT1("ReadFile() failed!\n");
789 dwBufferUsage
+= dwRead
;
791 while (dwBufferUsage
<= BufSize
)
793 if (Flags
& EVENTLOG_FORWARDS_READ
)
798 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
802 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
803 INVALID_SET_FILE_POINTER
)
805 DPRINT1("SetFilePointer() failed!\n");
809 if (!ReadFile(LogFile
->hFile
,
815 DPRINT1("ReadFile() failed!\n");
819 if (dwBufferUsage
+ dwRecSize
> BufSize
)
822 if (SetFilePointer(LogFile
->hFile
,
823 -((LONG
) sizeof(DWORD
)),
825 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
827 DPRINT1("SetFilePointer() failed!\n");
833 if (!ReadAnsiLogEntry(LogFile
->hFile
,
834 Buffer
+ dwBufferUsage
,
838 DPRINT1("ReadAnsiLogEntry() failed!\n");
844 if (!ReadFile(LogFile
->hFile
,
845 Buffer
+ dwBufferUsage
,
850 DPRINT1("ReadFile() failed!\n");
855 dwBufferUsage
+= dwRead
;
858 *BytesRead
= dwBufferUsage
;
859 * RecordNumber
= dwRecNum
;
860 LeaveCriticalSection(&LogFile
->cs
);
861 return ERROR_SUCCESS
;
864 DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
865 LeaveCriticalSection(&LogFile
->cs
);
866 return GetLastError();
869 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
874 PEVENTLOGRECORD RecBuf
;
875 LARGE_INTEGER logFileSize
;
876 LARGE_INTEGER SystemTime
;
883 NtQuerySystemTime(&SystemTime
);
884 RtlTimeToSecondsSince1970(&SystemTime
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
886 EnterCriticalSection(&LogFile
->cs
);
888 if (!GetFileSizeEx(LogFile
->hFile
, &logFileSize
))
890 LeaveCriticalSection(&LogFile
->cs
);
894 /* If the size of the file is over MaxSize */
895 if ((logFileSize
.QuadPart
+ BufSize
)> LogFile
->Header
.MaxSize
)
897 ULONG OverWriteLength
= 0;
898 WriteOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
899 RecBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(EVENTLOGRECORD
));
900 /* Determine how many records need to be overwritten */
903 DPRINT("EventLogFile has reached maximume size\n");
907 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
908 HeapFree(GetProcessHeap(), 0, RecBuf
);
909 LeaveCriticalSection(&LogFile
->cs
);
913 /* Get the oldest record data */
914 RecOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
916 if (SetFilePointer(LogFile
->hFile
,
919 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
921 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
922 HeapFree(GetProcessHeap(), 0, RecBuf
);
923 LeaveCriticalSection(&LogFile
->cs
);
927 if (!ReadFile(LogFile
->hFile
, RecBuf
, sizeof(EVENTLOGRECORD
), &dwRead
, NULL
))
929 DPRINT1("ReadFile() failed!\n");
930 HeapFree(GetProcessHeap(), 0, RecBuf
);
931 LeaveCriticalSection(&LogFile
->cs
);
935 if (RecBuf
->Reserved
!= LOGFILE_SIGNATURE
)
937 DPRINT1("LogFile corrupt!\n");
938 LeaveCriticalSection(&LogFile
->cs
);
942 LogfDeleteOffsetInformation(LogFile
,LogFile
->Header
.OldestRecordNumber
);
944 LogFile
->Header
.OldestRecordNumber
++;
946 OverWriteLength
+= RecBuf
->Length
;
947 /* Check the size of the record as the record adding may be larger */
948 if (OverWriteLength
>= BufSize
)
950 DPRINT("Record will fit. Lenght %d, BufSize %d\n", OverWriteLength
, BufSize
);
951 LogFile
->Header
.StartOffset
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
955 HeapFree(GetProcessHeap(), 0, RecBuf
);
958 WriteOffSet
= LogFile
->Header
.EndOffset
;
960 if (SetFilePointer(LogFile
->hFile
,
963 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
965 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
966 LeaveCriticalSection(&LogFile
->cs
);
970 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
972 DPRINT1("WriteFile() failed! %d\n", GetLastError());
973 LeaveCriticalSection(&LogFile
->cs
);
977 if (!LogfAddOffsetInformation(LogFile
,
978 LogFile
->Header
.CurrentRecordNumber
,
981 LeaveCriticalSection(&LogFile
->cs
);
985 LogFile
->Header
.CurrentRecordNumber
++;
987 if (LogFile
->Header
.OldestRecordNumber
== 0)
988 LogFile
->Header
.OldestRecordNumber
= 1;
990 if (WriteOffSet
== LogFile
->Header
.EndOffset
)
992 LogFile
->Header
.EndOffset
+= dwWritten
;
994 if (SetFilePointer(LogFile
->hFile
,
995 LogFile
->Header
.EndOffset
,
997 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
999 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1000 LeaveCriticalSection(&LogFile
->cs
);
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
;
1015 if (!WriteFile(LogFile
->hFile
,
1017 sizeof(EVENTLOGEOF
),
1021 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1022 LeaveCriticalSection(&LogFile
->cs
);
1026 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
1027 INVALID_SET_FILE_POINTER
)
1029 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1030 LeaveCriticalSection(&LogFile
->cs
);
1034 if (!WriteFile(LogFile
->hFile
,
1036 sizeof(EVENTLOGHEADER
),
1040 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
1041 LeaveCriticalSection(&LogFile
->cs
);
1045 if (!FlushFileBuffers(LogFile
->hFile
))
1047 LeaveCriticalSection(&LogFile
->cs
);
1048 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
1052 LeaveCriticalSection(&LogFile
->cs
);
1056 /* Returns 0 if nothing found. */
1057 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
1061 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
1063 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
1064 return LogFile
->OffsetInfo
[i
].EventOffset
;
1069 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
1071 return LogFile
->Header
.OldestRecordNumber
;
1074 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
1076 return LogFile
->Header
.CurrentRecordNumber
;
1079 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
1083 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
1088 for (i
= 0; i
< LogFile
->OffsetInfoNext
- 1; i
++)
1090 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+ 1].EventNumber
;
1091 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+ 1].EventOffset
;
1093 LogFile
->OffsetInfoNext
--;
1097 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
1099 LPVOID NewOffsetInfo
;
1101 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
1103 NewOffsetInfo
= HeapReAlloc(MyHeap
,
1105 LogFile
->OffsetInfo
,
1106 (LogFile
->OffsetInfoSize
+ 64) *
1107 sizeof(EVENT_OFFSET_INFO
));
1111 DPRINT1("Can't reallocate heap.\n");
1115 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
1116 LogFile
->OffsetInfoSize
+= 64;
1119 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
1120 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
1121 LogFile
->OffsetInfoNext
++;
1126 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
1127 DWORD dwRecordNumber
,
1133 LPCWSTR ComputerName
,
1142 PEVENTLOGRECORD pRec
;
1148 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
1149 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
1151 if (dwRecSize
% sizeof(DWORD
) != 0)
1152 dwRecSize
+= sizeof(DWORD
) - (dwRecSize
% sizeof(DWORD
));
1154 dwRecSize
+= dwSidLength
;
1156 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1158 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1159 str
+= lstrlenW(str
) + 1;
1162 dwRecSize
+= dwDataSize
;
1163 if (dwRecSize
% sizeof(DWORD
) != 0)
1164 dwRecSize
+= sizeof(DWORD
) - (dwRecSize
% sizeof(DWORD
));
1166 dwRecSize
+= sizeof(DWORD
);
1168 Buffer
= HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
1172 DPRINT1("Can't allocate heap!\n");
1176 pRec
= (PEVENTLOGRECORD
) Buffer
;
1177 pRec
->Length
= dwRecSize
;
1178 pRec
->Reserved
= LOGFILE_SIGNATURE
;
1179 pRec
->RecordNumber
= dwRecordNumber
;
1181 pRec
->TimeGenerated
= dwTime
;
1182 pRec
->TimeWritten
= dwTime
;
1184 pRec
->EventID
= dwEventId
;
1185 pRec
->EventType
= wType
;
1186 pRec
->EventCategory
= wCategory
;
1188 pos
= sizeof(EVENTLOGRECORD
);
1190 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
1191 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
1192 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
1193 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
1195 pRec
->UserSidOffset
= pos
;
1197 if (pos
% sizeof(DWORD
) != 0)
1198 pos
+= sizeof(DWORD
) - (pos
% sizeof(DWORD
));
1202 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1203 pRec
->UserSidLength
= dwSidLength
;
1204 pRec
->UserSidOffset
= pos
;
1208 pRec
->StringOffset
= pos
;
1209 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1211 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1212 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1213 str
+= lstrlenW(str
) + 1;
1215 pRec
->NumStrings
= wNumStrings
;
1217 pRec
->DataOffset
= pos
;
1220 pRec
->DataLength
= dwDataSize
;
1221 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1225 if (pos
% sizeof(DWORD
) != 0)
1226 pos
+= sizeof(DWORD
) - (pos
% sizeof(DWORD
));
1228 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1230 *lpRecSize
= dwRecSize
;
1236 LogfReportEvent(WORD wType
,
1244 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1245 DWORD dwComputerNameLength
= MAX_COMPUTERNAME_LENGTH
+ 1;
1246 PEVENTSOURCE pEventSource
= NULL
;
1252 LARGE_INTEGER SystemTime
;
1254 if (!GetComputerNameW(szComputerName
, &dwComputerNameLength
))
1256 szComputerName
[0] = 0;
1259 pEventSource
= GetEventSourceByName(L
"EventLog");
1260 if (pEventSource
== NULL
)
1265 NtQuerySystemTime(&SystemTime
);
1266 RtlTimeToSecondsSince1970(&SystemTime
, &dwTime
);
1268 lastRec
= LogfGetCurrentRecord(pEventSource
->LogFile
);
1270 logBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
1276 pEventSource
->szName
,
1277 (LPCWSTR
)szComputerName
,
1285 dwError
= LogfWriteData(pEventSource
->LogFile
, recSize
, logBuffer
);
1288 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource
->LogFile
->FileName
);
1291 LogfFreeRecord(logBuffer
);