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 LogFile
->Header
.OldestRecordNumber
= 1;
38 /* FIXME: Read MaxSize from registry for this LogFile.
39 But for now limit EventLog size to just under 5K. */
40 LogFile
->Header
.MaxSize
= 5000;
41 LogFile
->Header
.Signature
= LOGFILE_SIGNATURE
;
42 if (!WriteFile(LogFile
->hFile
,
44 sizeof(EVENTLOGHEADER
),
48 DPRINT1("WriteFile failed:%d!\n", GetLastError());
52 EofRec
.Ones
= 0x11111111;
53 EofRec
.Twos
= 0x22222222;
54 EofRec
.Threes
= 0x33333333;
55 EofRec
.Fours
= 0x44444444;
56 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
57 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
58 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
59 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
60 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
61 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
63 if (!WriteFile(LogFile
->hFile
,
69 DPRINT1("WriteFile failed:%d!\n", GetLastError());
73 if (!FlushFileBuffers(LogFile
->hFile
))
75 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
82 BOOL
LogfInitializeExisting(PLOGFILE LogFile
)
85 DWORD dwRecordsNumber
= 0;
86 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
88 PEVENTLOGRECORD RecBuf
;
89 BOOL OvewrWrittenRecords
= FALSE
;
91 DPRINT("Initializing LogFile %S\n",LogFile
->LogName
);
93 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
94 INVALID_SET_FILE_POINTER
)
96 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
100 if (!ReadFile(LogFile
->hFile
,
102 sizeof(EVENTLOGHEADER
),
106 DPRINT1("ReadFile failed! %d\n", GetLastError());
110 if (dwRead
!= sizeof(EVENTLOGHEADER
))
112 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
113 return LogfInitializeNew(LogFile
);
116 if (LogFile
->Header
.HeaderSize
!= sizeof(EVENTLOGHEADER
) ||
117 LogFile
->Header
.EndHeaderSize
!= sizeof(EVENTLOGHEADER
))
119 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
120 return LogfInitializeNew(LogFile
);
123 if (LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
125 DPRINT("EventLog: Invalid signature %x in %S.\n",
126 LogFile
->Header
.Signature
, LogFile
->FileName
);
127 return LogfInitializeNew(LogFile
);
130 if (LogFile
->Header
.EndOffset
> GetFileSize(LogFile
->hFile
, NULL
) + 1)
132 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
133 LogFile
->Header
.EndOffset
, LogFile
->FileName
);
134 return LogfInitializeNew(LogFile
);
137 /* Set the read location to the oldest record */
138 dwFilePointer
= SetFilePointer(LogFile
->hFile
, LogFile
->Header
.StartOffset
, NULL
, FILE_BEGIN
);
139 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
141 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
147 dwFilePointer
= SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
);
149 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
151 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
155 /* If the EVENTLOGEOF info has been reached and the oldest record was not immediately after the Header */
156 if ((dwFilePointer
== LogFile
->Header
.EndOffset
) && (LogFile
->Header
.StartOffset
!= sizeof(EVENTLOGHEADER
)))
158 OvewrWrittenRecords
= TRUE
;
159 /* The file has records that overwrote old ones so read them */
160 dwFilePointer
= SetFilePointer(LogFile
->hFile
, sizeof(EVENTLOGHEADER
), NULL
, FILE_BEGIN
);
163 if (!ReadFile(LogFile
->hFile
,
169 DPRINT1("ReadFile failed! %d\n", GetLastError());
173 if (dwRead
!= sizeof(dwRecSize
))
176 if (!ReadFile(LogFile
->hFile
,
182 DPRINT1("ReadFile() failed! %d\n", GetLastError());
186 if (dwRead
!= sizeof(dwRecSize
))
189 if (dwRecSign
!= LOGFILE_SIGNATURE
||
190 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
) + 1 ||
191 dwRecSize
< sizeof(EVENTLOGRECORD
))
196 if (SetFilePointer(LogFile
->hFile
,
197 -((LONG
) sizeof(DWORD
) * 2),
199 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
201 DPRINT1("SetFilePointer() failed! %d", GetLastError());
205 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
209 DPRINT1("Can't allocate heap!\n");
213 if (!ReadFile(LogFile
->hFile
, RecBuf
, dwRecSize
, &dwRead
, NULL
))
215 DPRINT1("ReadFile() failed! %d\n", GetLastError());
216 HeapFree(MyHeap
, 0, RecBuf
);
220 if (dwRead
!= dwRecSize
)
222 HeapFree(MyHeap
, 0, RecBuf
);
226 /* if OvewrWrittenRecords is TRUE and this record has already been read */
227 if ((OvewrWrittenRecords
== TRUE
) && (RecBuf
->RecordNumber
== LogFile
->Header
.OldestRecordNumber
))
229 HeapFree(MyHeap
, 0, RecBuf
);
233 pdwRecSize2
= (PDWORD
) (((PBYTE
) RecBuf
) + dwRecSize
- 4);
235 if (*pdwRecSize2
!= dwRecSize
)
237 DPRINT1("Invalid RecordSizeEnd of record %d (%x) in %S\n",
238 dwRecordsNumber
, *pdwRecSize2
, LogFile
->LogName
);
239 HeapFree(MyHeap
, 0, RecBuf
);
245 if (!LogfAddOffsetInformation(LogFile
,
246 RecBuf
->RecordNumber
,
249 DPRINT1("LogfAddOffsetInformation() failed!\n");
250 HeapFree(MyHeap
, 0, RecBuf
);
254 HeapFree(MyHeap
, 0, RecBuf
);
257 LogFile
->Header
.CurrentRecordNumber
= dwRecordsNumber
+ LogFile
->Header
.OldestRecordNumber
;
258 if (LogFile
->Header
.CurrentRecordNumber
== 0)
259 LogFile
->Header
.CurrentRecordNumber
= 1;
261 /* FIXME: Read MaxSize from registry for this LogFile.
262 But for now limit EventLog size to just under 5K. */
263 LogFile
->Header
.MaxSize
= 5000;
265 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
266 INVALID_SET_FILE_POINTER
)
268 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
272 if (!WriteFile(LogFile
->hFile
,
274 sizeof(EVENTLOGHEADER
),
278 DPRINT1("WriteFile failed! %d\n", GetLastError());
282 if (!FlushFileBuffers(LogFile
->hFile
))
284 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
293 LogfCreate(PLOGFILE
*LogFile
,
295 PUNICODE_STRING FileName
,
299 OBJECT_ATTRIBUTES ObjectAttributes
;
300 IO_STATUS_BLOCK IoStatusBlock
;
302 BOOL bResult
, bCreateNew
= FALSE
;
303 NTSTATUS Status
= STATUS_SUCCESS
;
305 pLogFile
= (LOGFILE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(LOGFILE
));
308 DPRINT1("Can't allocate heap!\n");
309 return STATUS_NO_MEMORY
;
312 InitializeObjectAttributes(&ObjectAttributes
,
314 OBJ_CASE_INSENSITIVE
,
318 Status
= NtCreateFile(&pLogFile
->hFile
,
319 Backup
? (GENERIC_READ
| SYNCHRONIZE
) : (GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
),
323 FILE_ATTRIBUTE_NORMAL
,
325 Backup
? FILE_OPEN
: FILE_OPEN_IF
,
326 FILE_SYNCHRONOUS_IO_NONALERT
,
329 if (!NT_SUCCESS(Status
))
331 DPRINT1("Can't create file %wZ (Status: 0x%08lx)\n", FileName
, Status
);
335 bCreateNew
= (IoStatusBlock
.Information
== FILE_CREATED
) ? TRUE
: FALSE
;
338 (WCHAR
*) HeapAlloc(MyHeap
,
340 (lstrlenW(LogName
) + 1) * sizeof(WCHAR
));
341 if (pLogFile
->LogName
== NULL
)
343 DPRINT1("Can't allocate heap\n");
344 Status
= STATUS_NO_MEMORY
;
348 lstrcpyW(pLogFile
->LogName
, LogName
);
351 (WCHAR
*) HeapAlloc(MyHeap
,
353 (lstrlenW(FileName
->Buffer
) + 1) * sizeof(WCHAR
));
354 if (pLogFile
->FileName
== NULL
)
356 DPRINT1("Can't allocate heap\n");
357 Status
= STATUS_NO_MEMORY
;
361 lstrcpyW(pLogFile
->FileName
, FileName
->Buffer
);
363 pLogFile
->OffsetInfo
=
364 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
366 sizeof(EVENT_OFFSET_INFO
) * 64);
367 if (pLogFile
->OffsetInfo
== NULL
)
369 DPRINT1("Can't allocate heap\n");
370 Status
= STATUS_NO_MEMORY
;
374 pLogFile
->OffsetInfoSize
= 64;
376 pLogFile
->Permanent
= Permanent
;
379 bResult
= LogfInitializeNew(pLogFile
);
381 bResult
= LogfInitializeExisting(pLogFile
);
385 Status
= STATUS_UNSUCCESSFUL
;
389 RtlInitializeResource(&pLogFile
->Lock
);
391 LogfListAddItem(pLogFile
);
394 if (!NT_SUCCESS(Status
))
396 if ((pLogFile
->hFile
!= NULL
) && (pLogFile
->hFile
!= INVALID_HANDLE_VALUE
))
397 CloseHandle(pLogFile
->hFile
);
399 if (pLogFile
->OffsetInfo
)
400 HeapFree(MyHeap
, 0, pLogFile
->OffsetInfo
);
402 if (pLogFile
->FileName
)
403 HeapFree(MyHeap
, 0, pLogFile
->FileName
);
405 if (pLogFile
->LogName
)
406 HeapFree(MyHeap
, 0, pLogFile
->LogName
);
408 HeapFree(MyHeap
, 0, pLogFile
);
419 LogfClose(PLOGFILE LogFile
,
425 if ((ForceClose
== FALSE
) &&
426 (LogFile
->Permanent
== TRUE
))
429 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
431 FlushFileBuffers(LogFile
->hFile
);
432 CloseHandle(LogFile
->hFile
);
433 LogfListRemoveItem(LogFile
);
435 RtlDeleteResource(&LogFile
->Lock
);
437 HeapFree(MyHeap
, 0, LogFile
->LogName
);
438 HeapFree(MyHeap
, 0, LogFile
->FileName
);
439 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
440 HeapFree(MyHeap
, 0, LogFile
);
445 VOID
LogfCloseAll(VOID
)
447 while (!IsListEmpty(&LogFileListHead
))
449 LogfClose(LogfListHead(), TRUE
);
452 DeleteCriticalSection(&LogFileListCs
);
455 VOID
LogfListInitialize(VOID
)
457 InitializeCriticalSection(&LogFileListCs
);
458 InitializeListHead(&LogFileListHead
);
461 PLOGFILE
LogfListHead(VOID
)
463 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
466 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
468 PLIST_ENTRY CurrentEntry
;
469 PLOGFILE Result
= NULL
;
471 EnterCriticalSection(&LogFileListCs
);
473 CurrentEntry
= LogFileListHead
.Flink
;
474 while (CurrentEntry
!= &LogFileListHead
)
476 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
480 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
486 CurrentEntry
= CurrentEntry
->Flink
;
489 LeaveCriticalSection(&LogFileListCs
);
493 /* Index starting from 1 */
494 INT
LogfListItemIndexByName(WCHAR
* Name
)
496 PLIST_ENTRY CurrentEntry
;
500 EnterCriticalSection(&LogFileListCs
);
502 CurrentEntry
= LogFileListHead
.Flink
;
503 while (CurrentEntry
!= &LogFileListHead
)
505 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
509 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
515 CurrentEntry
= CurrentEntry
->Flink
;
519 LeaveCriticalSection(&LogFileListCs
);
523 /* Index starting from 1 */
524 PLOGFILE
LogfListItemByIndex(INT Index
)
526 PLIST_ENTRY CurrentEntry
;
527 PLOGFILE Result
= NULL
;
530 EnterCriticalSection(&LogFileListCs
);
532 CurrentEntry
= LogFileListHead
.Flink
;
533 while (CurrentEntry
!= &LogFileListHead
)
537 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
541 CurrentEntry
= CurrentEntry
->Flink
;
545 LeaveCriticalSection(&LogFileListCs
);
549 INT
LogfListItemCount(VOID
)
551 PLIST_ENTRY CurrentEntry
;
554 EnterCriticalSection(&LogFileListCs
);
556 CurrentEntry
= LogFileListHead
.Flink
;
557 while (CurrentEntry
!= &LogFileListHead
)
559 CurrentEntry
= CurrentEntry
->Flink
;
563 LeaveCriticalSection(&LogFileListCs
);
567 VOID
LogfListAddItem(PLOGFILE Item
)
569 EnterCriticalSection(&LogFileListCs
);
570 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
571 LeaveCriticalSection(&LogFileListCs
);
574 VOID
LogfListRemoveItem(PLOGFILE Item
)
576 EnterCriticalSection(&LogFileListCs
);
577 RemoveEntryList(&Item
->ListEntry
);
578 LeaveCriticalSection(&LogFileListCs
);
582 ReadAnsiLogEntry(HANDLE hFile
,
584 DWORD nNumberOfBytesToRead
,
585 LPDWORD lpNumberOfBytesRead
)
590 UNICODE_STRING StringW
;
595 LPVOID lpUnicodeBuffer
= NULL
;
604 *lpNumberOfBytesRead
= 0;
606 lpUnicodeBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nNumberOfBytesToRead
);
607 if (lpUnicodeBuffer
== NULL
)
609 DPRINT1("Alloc failed!\n");
613 if (!ReadFile(hFile
, lpUnicodeBuffer
, nNumberOfBytesToRead
, &dwRead
, NULL
))
615 DPRINT1("Read failed!\n");
620 Dst
= (PEVENTLOGRECORD
)lpBuffer
;
621 Src
= (PEVENTLOGRECORD
)lpUnicodeBuffer
;
623 Dst
->TimeGenerated
= Src
->TimeGenerated
;
624 Dst
->Reserved
= Src
->Reserved
;
625 Dst
->RecordNumber
= Src
->RecordNumber
;
626 Dst
->TimeWritten
= Src
->TimeWritten
;
627 Dst
->EventID
= Src
->EventID
;
628 Dst
->EventType
= Src
->EventType
;
629 Dst
->EventCategory
= Src
->EventCategory
;
630 Dst
->NumStrings
= Src
->NumStrings
;
631 Dst
->UserSidLength
= Src
->UserSidLength
;
632 Dst
->DataLength
= Src
->DataLength
;
634 SrcPtr
= (LPWSTR
)((DWORD_PTR
)Src
+ sizeof(EVENTLOGRECORD
));
635 DstPtr
= (LPSTR
)((DWORD_PTR
)Dst
+ sizeof(EVENTLOGRECORD
));
637 /* Convert the module name */
638 RtlInitUnicodeString(&StringW
, SrcPtr
);
639 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
640 if (NT_SUCCESS(Status
))
642 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
644 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
646 RtlFreeAnsiString(&StringA
);
649 /* Convert the computer name */
650 if (NT_SUCCESS(Status
))
652 SrcPtr
= (PWSTR
)((DWORD_PTR
)SrcPtr
+ StringW
.MaximumLength
);
654 RtlInitUnicodeString(&StringW
, SrcPtr
);
655 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
656 if (NT_SUCCESS(Status
))
658 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
660 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
662 RtlFreeAnsiString(&StringA
);
666 /* Add the padding and the User SID*/
667 if (NT_SUCCESS(Status
))
669 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
) % sizeof(DWORD
));
670 RtlZeroMemory(DstPtr
, dwPadding
);
672 DstPtr
= (LPSTR
)((DWORD_PTR
)DstPtr
+ dwPadding
);
673 RtlCopyMemory(DstPtr
,
674 (PVOID
)((DWORD_PTR
)Src
+ Src
->UserSidOffset
),
677 Dst
->UserSidOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
681 /* Convert the strings */
682 if (NT_SUCCESS(Status
))
684 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->UserSidLength
);
686 SrcString
= (LPWSTR
)((DWORD_PTR
)Src
+ (DWORD
)Src
->StringOffset
);
687 DstString
= (LPSTR
)DstPtr
;
689 for (i
= 0; i
< Dst
->NumStrings
; i
++)
691 RtlInitUnicodeString(&StringW
, SrcString
);
693 RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
695 RtlCopyMemory(DstString
, StringA
.Buffer
, StringA
.MaximumLength
);
697 SrcString
= (LPWSTR
)((DWORD_PTR
)SrcString
+
698 (DWORD
)StringW
.MaximumLength
);
700 DstString
= (LPSTR
)((DWORD_PTR
)DstString
+
701 (DWORD
)StringA
.MaximumLength
);
703 RtlFreeAnsiString(&StringA
);
706 Dst
->StringOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
709 /* Copy the binary data */
710 DstPtr
= (PVOID
)DstString
;
711 Dst
->DataOffset
= (DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
;
713 RtlCopyMemory(DstPtr
, (PVOID
)((DWORD_PTR
)Src
+ Src
->DataOffset
), Src
->DataLength
);
715 /* Add the padding */
716 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->DataLength
);
717 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
-(DWORD_PTR
)Dst
) % sizeof(DWORD
));
718 RtlZeroMemory(DstPtr
, dwPadding
);
720 dwEntryLength
= (DWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
+ sizeof(DWORD
) - (DWORD_PTR
)Dst
);
722 /* Set the entry length at the end of the entry*/
723 pLength
= (PDWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
);
724 *pLength
= dwEntryLength
;
725 Dst
->Length
= dwEntryLength
;
727 *lpNumberOfBytesRead
= dwEntryLength
;
731 if (lpUnicodeBuffer
!= NULL
)
732 HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer
);
738 DWORD
LogfReadEvent(PLOGFILE LogFile
,
740 DWORD
* RecordNumber
,
747 DWORD dwOffset
, dwRead
, dwRecSize
;
748 DWORD dwBufferUsage
= 0, dwRecNum
;
750 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
751 return ERROR_INVALID_PARAMETER
;
753 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
754 return ERROR_INVALID_PARAMETER
;
756 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
757 return ERROR_INVALID_PARAMETER
;
759 if ((*RecordNumber
==0) && !(EVENTLOG_SEQUENTIAL_READ
))
761 return ERROR_INVALID_PARAMETER
;
764 dwRecNum
= *RecordNumber
;
766 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
771 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
775 RtlReleaseResource(&LogFile
->Lock
);
776 return ERROR_HANDLE_EOF
;
779 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
780 INVALID_SET_FILE_POINTER
)
782 DPRINT1("SetFilePointer() failed!\n");
786 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
788 DPRINT1("ReadFile() failed!\n");
792 if (dwRecSize
> BufSize
)
794 *BytesNeeded
= dwRecSize
;
795 RtlReleaseResource(&LogFile
->Lock
);
796 return ERROR_INSUFFICIENT_BUFFER
;
799 if (SetFilePointer(LogFile
->hFile
,
800 -((LONG
) sizeof(DWORD
)),
802 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
804 DPRINT1("SetFilePointer() failed!\n");
810 if (!ReadAnsiLogEntry(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
))
812 DPRINT1("ReadAnsiLogEntry() failed!\n");
818 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
820 DPRINT1("ReadFile() failed!\n");
825 dwBufferUsage
+= dwRead
;
827 while (dwBufferUsage
<= BufSize
)
829 if (Flags
& EVENTLOG_FORWARDS_READ
)
834 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
838 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
839 INVALID_SET_FILE_POINTER
)
841 DPRINT1("SetFilePointer() failed!\n");
845 if (!ReadFile(LogFile
->hFile
,
851 DPRINT1("ReadFile() failed!\n");
855 if (dwBufferUsage
+ dwRecSize
> BufSize
)
858 if (SetFilePointer(LogFile
->hFile
,
859 -((LONG
) sizeof(DWORD
)),
861 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
863 DPRINT1("SetFilePointer() failed!\n");
869 if (!ReadAnsiLogEntry(LogFile
->hFile
,
870 Buffer
+ dwBufferUsage
,
874 DPRINT1("ReadAnsiLogEntry() failed!\n");
880 if (!ReadFile(LogFile
->hFile
,
881 Buffer
+ dwBufferUsage
,
886 DPRINT1("ReadFile() failed!\n");
891 dwBufferUsage
+= dwRead
;
894 *BytesRead
= dwBufferUsage
;
895 * RecordNumber
= dwRecNum
;
896 RtlReleaseResource(&LogFile
->Lock
);
897 return ERROR_SUCCESS
;
900 DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
901 RtlReleaseResource(&LogFile
->Lock
);
902 return GetLastError();
905 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
911 PEVENTLOGRECORD RecBuf
;
912 LARGE_INTEGER logFileSize
;
920 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
922 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
924 if (!GetFileSizeEx(LogFile
->hFile
, &logFileSize
))
926 RtlReleaseResource(&LogFile
->Lock
);
930 /* If the size of the file is over MaxSize */
931 if ((logFileSize
.QuadPart
+ BufSize
)> LogFile
->Header
.MaxSize
)
933 ULONG OverWriteLength
= 0;
934 WriteOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
935 RecBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(EVENTLOGRECORD
));
936 /* Determine how many records need to be overwritten */
939 DPRINT("EventLogFile has reached maximume size\n");
943 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
944 HeapFree(GetProcessHeap(), 0, RecBuf
);
945 RtlReleaseResource(&LogFile
->Lock
);
949 /* Get the oldest record data */
950 RecOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
952 if (SetFilePointer(LogFile
->hFile
,
955 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
957 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
958 HeapFree(GetProcessHeap(), 0, RecBuf
);
959 RtlReleaseResource(&LogFile
->Lock
);
963 if (!ReadFile(LogFile
->hFile
, RecBuf
, sizeof(EVENTLOGRECORD
), &dwRead
, NULL
))
965 DPRINT1("ReadFile() failed!\n");
966 HeapFree(GetProcessHeap(), 0, RecBuf
);
967 RtlReleaseResource(&LogFile
->Lock
);
971 if (RecBuf
->Reserved
!= LOGFILE_SIGNATURE
)
973 DPRINT1("LogFile corrupt!\n");
974 RtlReleaseResource(&LogFile
->Lock
);
978 LogfDeleteOffsetInformation(LogFile
,LogFile
->Header
.OldestRecordNumber
);
980 LogFile
->Header
.OldestRecordNumber
++;
982 OverWriteLength
+= RecBuf
->Length
;
983 /* Check the size of the record as the record adding may be larger */
984 if (OverWriteLength
>= BufSize
)
986 DPRINT("Record will fit. Lenght %d, BufSize %d\n", OverWriteLength
, BufSize
);
987 LogFile
->Header
.StartOffset
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
991 HeapFree(GetProcessHeap(), 0, RecBuf
);
994 WriteOffSet
= LogFile
->Header
.EndOffset
;
996 if (SetFilePointer(LogFile
->hFile
,
999 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1001 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1002 RtlReleaseResource(&LogFile
->Lock
);
1006 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
1008 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1009 RtlReleaseResource(&LogFile
->Lock
);
1013 if (!LogfAddOffsetInformation(LogFile
,
1014 LogFile
->Header
.CurrentRecordNumber
,
1017 RtlReleaseResource(&LogFile
->Lock
);
1021 LogFile
->Header
.CurrentRecordNumber
++;
1023 if (WriteOffSet
== LogFile
->Header
.EndOffset
)
1025 LogFile
->Header
.EndOffset
+= dwWritten
;
1027 if (SetFilePointer(LogFile
->hFile
,
1028 LogFile
->Header
.EndOffset
,
1030 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1032 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1033 RtlReleaseResource(&LogFile
->Lock
);
1037 EofRec
.Ones
= 0x11111111;
1038 EofRec
.Twos
= 0x22222222;
1039 EofRec
.Threes
= 0x33333333;
1040 EofRec
.Fours
= 0x44444444;
1041 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1042 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1043 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1044 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1045 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
1046 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
1048 if (!WriteFile(LogFile
->hFile
,
1050 sizeof(EVENTLOGEOF
),
1054 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1055 RtlReleaseResource(&LogFile
->Lock
);
1059 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
1060 INVALID_SET_FILE_POINTER
)
1062 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1063 RtlReleaseResource(&LogFile
->Lock
);
1067 if (!WriteFile(LogFile
->hFile
,
1069 sizeof(EVENTLOGHEADER
),
1073 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
1074 RtlReleaseResource(&LogFile
->Lock
);
1078 if (!FlushFileBuffers(LogFile
->hFile
))
1080 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
1081 RtlReleaseResource(&LogFile
->Lock
);
1085 RtlReleaseResource(&LogFile
->Lock
);
1091 LogfClearFile(PLOGFILE LogFile
,
1092 PUNICODE_STRING BackupFileName
)
1094 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
1096 if (BackupFileName
->Length
> 0)
1098 /* FIXME: Write a backup file */
1101 LogfInitializeNew(LogFile
);
1103 RtlReleaseResource(&LogFile
->Lock
);
1105 return STATUS_SUCCESS
;
1110 LogfBackupFile(PLOGFILE LogFile
,
1111 PUNICODE_STRING BackupFileName
)
1113 OBJECT_ATTRIBUTES ObjectAttributes
;
1114 IO_STATUS_BLOCK IoStatusBlock
;
1115 EVENTLOGHEADER Header
;
1117 HANDLE FileHandle
= NULL
;
1119 LARGE_INTEGER FileOffset
;
1121 PUCHAR Buffer
= NULL
;
1123 DWORD dwOffset
, dwRead
, dwRecSize
;
1125 DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile
, BackupFileName
);
1127 /* Lock the log file shared */
1128 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
1130 InitializeObjectAttributes(&ObjectAttributes
,
1132 OBJ_CASE_INSENSITIVE
,
1136 Status
= NtCreateFile(&FileHandle
,
1137 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1141 FILE_ATTRIBUTE_NORMAL
,
1144 FILE_WRITE_THROUGH
| FILE_SYNCHRONOUS_IO_NONALERT
,
1147 if (!NT_SUCCESS(Status
))
1149 DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName
, Status
);
1153 /* Initialize the (dirty) log file header */
1154 Header
.HeaderSize
= sizeof(EVENTLOGHEADER
);
1155 Header
.Signature
= LOGFILE_SIGNATURE
;
1156 Header
.MajorVersion
= MAJORVER
;
1157 Header
.MinorVersion
= MINORVER
;
1158 Header
.StartOffset
= sizeof(EVENTLOGHEADER
);
1159 Header
.EndOffset
= sizeof(EVENTLOGHEADER
);
1160 Header
.CurrentRecordNumber
= 1;
1161 Header
.OldestRecordNumber
= 1;
1163 Header
.Flags
= ELF_LOGFILE_HEADER_DIRTY
;
1164 Header
.Retention
= LogFile
->Header
.Retention
;
1165 Header
.EndHeaderSize
= sizeof(EVENTLOGHEADER
);
1167 /* Write the (dirty) log file header */
1168 Status
= NtWriteFile(FileHandle
,
1174 sizeof(EVENTLOGHEADER
),
1177 if (!NT_SUCCESS(Status
))
1179 DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status
);
1183 for (i
= LogFile
->Header
.OldestRecordNumber
; i
< LogFile
->Header
.CurrentRecordNumber
; i
++)
1185 dwOffset
= LogfOffsetByNumber(LogFile
, i
);
1189 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1191 DPRINT1("SetFilePointer() failed!\n");
1195 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
1197 DPRINT1("ReadFile() failed!\n");
1201 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1203 DPRINT1("SetFilePointer() failed!\n");
1207 Buffer
= HeapAlloc(MyHeap
, 0, dwRecSize
);
1210 DPRINT1("HeapAlloc() failed!\n");
1214 if (!ReadFile(LogFile
->hFile
, &Buffer
, dwRecSize
, &dwRead
, NULL
))
1216 DPRINT1("ReadFile() failed!\n");
1220 /* Write the event record */
1221 Status
= NtWriteFile(FileHandle
,
1230 if (!NT_SUCCESS(Status
))
1232 DPRINT1("NtWriteFile() failed!\n");
1236 /* Update the header information */
1237 Header
.EndOffset
+= dwRecSize
;
1239 /* Free the buffer */
1240 HeapFree(MyHeap
, 0, Buffer
);
1244 /* Initialize the EOF record */
1245 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1246 EofRec
.Ones
= 0x11111111;
1247 EofRec
.Twos
= 0x22222222;
1248 EofRec
.Threes
= 0x33333333;
1249 EofRec
.Fours
= 0x44444444;
1250 EofRec
.BeginRecord
= sizeof(EVENTLOGHEADER
);
1251 EofRec
.EndRecord
= Header
.EndOffset
;
1252 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1253 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1254 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1256 /* Write the EOF record */
1257 Status
= NtWriteFile(FileHandle
,
1263 sizeof(EVENTLOGEOF
),
1266 if (!NT_SUCCESS(Status
))
1268 DPRINT1("NtWriteFile() failed!\n");
1272 /* Update the header information */
1273 Header
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1274 Header
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1275 Header
.MaxSize
= Header
.EndOffset
+ sizeof(EVENTLOGEOF
);
1278 /* Write the (clean) log file header */
1279 FileOffset
.QuadPart
= 0;
1280 Status
= NtWriteFile(FileHandle
,
1286 sizeof(EVENTLOGHEADER
),
1289 if (!NT_SUCCESS(Status
))
1291 DPRINT1("NtWriteFile() failed!\n");
1295 /* Free the buffer */
1297 HeapFree(MyHeap
, 0, Buffer
);
1299 /* Close the backup file */
1300 if (FileHandle
!= NULL
)
1301 NtClose(FileHandle
);
1303 /* Unlock the log file */
1304 RtlReleaseResource(&LogFile
->Lock
);
1310 /* Returns 0 if nothing found. */
1311 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
1315 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
1317 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
1318 return LogFile
->OffsetInfo
[i
].EventOffset
;
1323 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
1325 return LogFile
->Header
.OldestRecordNumber
;
1328 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
1330 return LogFile
->Header
.CurrentRecordNumber
;
1333 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
1337 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
1342 for (i
= 0; i
< LogFile
->OffsetInfoNext
- 1; i
++)
1344 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+ 1].EventNumber
;
1345 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+ 1].EventOffset
;
1347 LogFile
->OffsetInfoNext
--;
1351 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
1353 LPVOID NewOffsetInfo
;
1355 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
1357 NewOffsetInfo
= HeapReAlloc(MyHeap
,
1359 LogFile
->OffsetInfo
,
1360 (LogFile
->OffsetInfoSize
+ 64) *
1361 sizeof(EVENT_OFFSET_INFO
));
1365 DPRINT1("Can't reallocate heap.\n");
1369 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
1370 LogFile
->OffsetInfoSize
+= 64;
1373 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
1374 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
1375 LogFile
->OffsetInfoNext
++;
1380 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
1381 DWORD dwRecordNumber
,
1386 LPCWSTR ComputerName
,
1395 PEVENTLOGRECORD pRec
;
1402 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
1403 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
1405 if (dwRecSize
% 4 != 0)
1406 dwRecSize
+= 4 - (dwRecSize
% 4);
1408 dwRecSize
+= dwSidLength
;
1410 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1412 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1413 str
+= lstrlenW(str
) + 1;
1416 dwRecSize
+= dwDataSize
;
1417 if (dwRecSize
% 4 != 0)
1418 dwRecSize
+= 4 - (dwRecSize
% 4);
1422 Buffer
= HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
1426 DPRINT1("Can't allocate heap!\n");
1430 pRec
= (PEVENTLOGRECORD
) Buffer
;
1431 pRec
->Length
= dwRecSize
;
1432 pRec
->Reserved
= LOGFILE_SIGNATURE
;
1433 pRec
->RecordNumber
= dwRecordNumber
;
1435 GetSystemTime(&SysTime
);
1436 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
1437 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
1439 pRec
->EventID
= dwEventId
;
1440 pRec
->EventType
= wType
;
1441 pRec
->EventCategory
= wCategory
;
1443 pos
= sizeof(EVENTLOGRECORD
);
1445 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
1446 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
1447 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
1448 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
1450 pRec
->UserSidOffset
= pos
;
1453 pos
+= 4 - (pos
% 4);
1457 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1458 pRec
->UserSidLength
= dwSidLength
;
1459 pRec
->UserSidOffset
= pos
;
1463 pRec
->StringOffset
= pos
;
1464 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1466 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1467 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1468 str
+= lstrlenW(str
) + 1;
1470 pRec
->NumStrings
= wNumStrings
;
1472 pRec
->DataOffset
= pos
;
1475 pRec
->DataLength
= dwDataSize
;
1476 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1481 pos
+= 4 - (pos
% 4);
1483 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1485 *lpRecSize
= dwRecSize
;
1491 LogfReportEvent(WORD wType
,
1499 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1500 DWORD dwComputerNameLength
= MAX_COMPUTERNAME_LENGTH
+ 1;
1501 PEVENTSOURCE pEventSource
= NULL
;
1507 if (!GetComputerNameW(szComputerName
, &dwComputerNameLength
))
1509 szComputerName
[0] = 0;
1512 pEventSource
= GetEventSourceByName(L
"EventLog");
1513 if (pEventSource
== NULL
)
1518 lastRec
= LogfGetCurrentRecord(pEventSource
->LogFile
);
1520 logBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
1525 pEventSource
->szName
,
1526 (LPCWSTR
)szComputerName
,
1534 dwError
= LogfWriteData(pEventSource
->LogFile
, recSize
, logBuffer
);
1537 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource
->LogFile
->FileName
);
1540 LogfFreeRecord(logBuffer
);