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 #include <ndk/iofuncs.h>
19 /* GLOBALS ******************************************************************/
21 static LIST_ENTRY LogFileListHead
;
22 static CRITICAL_SECTION LogFileListCs
;
24 /* FUNCTIONS ****************************************************************/
27 LogfInitializeNew(PLOGFILE LogFile
)
32 ZeroMemory(&LogFile
->Header
, sizeof(EVENTLOGHEADER
));
33 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
34 SetEndOfFile(LogFile
->hFile
);
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
,
50 sizeof(EVENTLOGHEADER
),
54 DPRINT1("WriteFile failed:%d!\n", GetLastError());
55 return STATUS_UNSUCCESSFUL
;
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
;
69 if (!WriteFile(LogFile
->hFile
,
75 DPRINT1("WriteFile failed:%d!\n", GetLastError());
76 return STATUS_UNSUCCESSFUL
;
79 if (!FlushFileBuffers(LogFile
->hFile
))
81 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
82 return STATUS_UNSUCCESSFUL
;
85 return STATUS_SUCCESS
;
90 LogfInitializeExisting(PLOGFILE LogFile
, BOOL Backup
)
93 DWORD dwRecordsNumber
= 0;
94 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
96 PEVENTLOGRECORD RecBuf
;
97 BOOL OvewrWrittenRecords
= FALSE
;
99 DPRINT("Initializing LogFile %S\n",LogFile
->LogName
);
101 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
102 INVALID_SET_FILE_POINTER
)
104 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
105 return STATUS_EVENTLOG_FILE_CORRUPT
;
108 if (!ReadFile(LogFile
->hFile
,
110 sizeof(EVENTLOGHEADER
),
114 DPRINT1("ReadFile failed! %d\n", GetLastError());
115 return STATUS_EVENTLOG_FILE_CORRUPT
;
118 if (dwRead
!= sizeof(EVENTLOGHEADER
))
120 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
121 return STATUS_EVENTLOG_FILE_CORRUPT
;
124 if (LogFile
->Header
.HeaderSize
!= sizeof(EVENTLOGHEADER
) ||
125 LogFile
->Header
.EndHeaderSize
!= sizeof(EVENTLOGHEADER
))
127 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
128 return STATUS_EVENTLOG_FILE_CORRUPT
;
131 if (LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
133 DPRINT("EventLog: Invalid signature %x in %S.\n",
134 LogFile
->Header
.Signature
, LogFile
->FileName
);
135 return STATUS_EVENTLOG_FILE_CORRUPT
;
138 if (LogFile
->Header
.EndOffset
> GetFileSize(LogFile
->hFile
, NULL
) + 1)
140 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
141 LogFile
->Header
.EndOffset
, LogFile
->FileName
);
142 return STATUS_EVENTLOG_FILE_CORRUPT
;
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
)
149 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
150 return STATUS_EVENTLOG_FILE_CORRUPT
;
155 dwFilePointer
= SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
);
157 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
159 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
160 return STATUS_EVENTLOG_FILE_CORRUPT
;
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
)))
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
);
171 if (!ReadFile(LogFile
->hFile
,
177 DPRINT1("ReadFile failed! %d\n", GetLastError());
178 return STATUS_EVENTLOG_FILE_CORRUPT
;
181 if (dwRead
!= sizeof(dwRecSize
))
184 if (!ReadFile(LogFile
->hFile
,
190 DPRINT1("ReadFile() failed! %d\n", GetLastError());
191 return STATUS_EVENTLOG_FILE_CORRUPT
;
194 if (dwRead
!= sizeof(dwRecSize
))
197 if (dwRecSign
!= LOGFILE_SIGNATURE
||
198 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
) + 1 ||
199 dwRecSize
< sizeof(EVENTLOGRECORD
))
204 if (SetFilePointer(LogFile
->hFile
,
205 -((LONG
) sizeof(DWORD
) * 2),
207 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
209 DPRINT1("SetFilePointer() failed! %d", GetLastError());
210 return STATUS_EVENTLOG_FILE_CORRUPT
;
213 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
216 DPRINT1("Can't allocate heap!\n");
217 return STATUS_NO_MEMORY
;
220 if (!ReadFile(LogFile
->hFile
, RecBuf
, dwRecSize
, &dwRead
, NULL
))
222 DPRINT1("ReadFile() failed! %d\n", GetLastError());
223 HeapFree(MyHeap
, 0, RecBuf
);
224 return STATUS_EVENTLOG_FILE_CORRUPT
;
227 if (dwRead
!= dwRecSize
)
229 HeapFree(MyHeap
, 0, RecBuf
);
233 /* if OvewrWrittenRecords is TRUE and this record has already been read */
234 if ((OvewrWrittenRecords
== TRUE
) && (RecBuf
->RecordNumber
== LogFile
->Header
.OldestRecordNumber
))
236 HeapFree(MyHeap
, 0, RecBuf
);
240 pdwRecSize2
= (PDWORD
) (((PBYTE
) RecBuf
) + dwRecSize
- 4);
242 if (*pdwRecSize2
!= dwRecSize
)
244 DPRINT1("Invalid RecordSizeEnd of record %d (%x) in %S\n",
245 dwRecordsNumber
, *pdwRecSize2
, LogFile
->LogName
);
246 HeapFree(MyHeap
, 0, RecBuf
);
252 if (!LogfAddOffsetInformation(LogFile
,
253 RecBuf
->RecordNumber
,
256 DPRINT1("LogfAddOffsetInformation() failed!\n");
257 HeapFree(MyHeap
, 0, RecBuf
);
258 return STATUS_EVENTLOG_FILE_CORRUPT
;
261 HeapFree(MyHeap
, 0, RecBuf
);
264 LogFile
->Header
.CurrentRecordNumber
= dwRecordsNumber
+ LogFile
->Header
.OldestRecordNumber
;
265 if (LogFile
->Header
.CurrentRecordNumber
== 0)
266 LogFile
->Header
.CurrentRecordNumber
= 1;
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;
274 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
275 INVALID_SET_FILE_POINTER
)
277 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
278 return STATUS_EVENTLOG_FILE_CORRUPT
;
281 if (!WriteFile(LogFile
->hFile
,
283 sizeof(EVENTLOGHEADER
),
287 DPRINT1("WriteFile failed! %d\n", GetLastError());
288 return STATUS_EVENTLOG_FILE_CORRUPT
;
291 if (!FlushFileBuffers(LogFile
->hFile
))
293 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
294 return STATUS_EVENTLOG_FILE_CORRUPT
;
298 return STATUS_SUCCESS
;
303 LogfCreate(PLOGFILE
*LogFile
,
305 PUNICODE_STRING FileName
,
309 OBJECT_ATTRIBUTES ObjectAttributes
;
310 IO_STATUS_BLOCK IoStatusBlock
;
312 BOOL bCreateNew
= FALSE
;
313 NTSTATUS Status
= STATUS_SUCCESS
;
315 pLogFile
= (LOGFILE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(LOGFILE
));
318 DPRINT1("Can't allocate heap!\n");
319 return STATUS_NO_MEMORY
;
322 InitializeObjectAttributes(&ObjectAttributes
,
324 OBJ_CASE_INSENSITIVE
,
328 Status
= NtCreateFile(&pLogFile
->hFile
,
329 Backup
? (GENERIC_READ
| SYNCHRONIZE
) : (GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
),
333 FILE_ATTRIBUTE_NORMAL
,
335 Backup
? FILE_OPEN
: FILE_OPEN_IF
,
336 FILE_SYNCHRONOUS_IO_NONALERT
,
339 if (!NT_SUCCESS(Status
))
341 DPRINT1("Can't create file %wZ (Status: 0x%08lx)\n", FileName
, Status
);
345 bCreateNew
= (IoStatusBlock
.Information
== FILE_CREATED
) ? TRUE
: FALSE
;
348 (WCHAR
*) HeapAlloc(MyHeap
,
350 (lstrlenW(LogName
) + 1) * sizeof(WCHAR
));
351 if (pLogFile
->LogName
== NULL
)
353 DPRINT1("Can't allocate heap\n");
354 Status
= STATUS_NO_MEMORY
;
358 lstrcpyW(pLogFile
->LogName
, LogName
);
361 (WCHAR
*) HeapAlloc(MyHeap
,
363 (lstrlenW(FileName
->Buffer
) + 1) * sizeof(WCHAR
));
364 if (pLogFile
->FileName
== NULL
)
366 DPRINT1("Can't allocate heap\n");
367 Status
= STATUS_NO_MEMORY
;
371 lstrcpyW(pLogFile
->FileName
, FileName
->Buffer
);
373 pLogFile
->OffsetInfo
=
374 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
376 sizeof(EVENT_OFFSET_INFO
) * 64);
377 if (pLogFile
->OffsetInfo
== NULL
)
379 DPRINT1("Can't allocate heap\n");
380 Status
= STATUS_NO_MEMORY
;
384 pLogFile
->OffsetInfoSize
= 64;
386 pLogFile
->Permanent
= Permanent
;
389 Status
= LogfInitializeNew(pLogFile
);
391 Status
= LogfInitializeExisting(pLogFile
, Backup
);
393 if (!NT_SUCCESS(Status
))
396 RtlInitializeResource(&pLogFile
->Lock
);
398 LogfListAddItem(pLogFile
);
401 if (!NT_SUCCESS(Status
))
403 if ((pLogFile
->hFile
!= NULL
) && (pLogFile
->hFile
!= INVALID_HANDLE_VALUE
))
404 CloseHandle(pLogFile
->hFile
);
406 if (pLogFile
->OffsetInfo
)
407 HeapFree(MyHeap
, 0, pLogFile
->OffsetInfo
);
409 if (pLogFile
->FileName
)
410 HeapFree(MyHeap
, 0, pLogFile
->FileName
);
412 if (pLogFile
->LogName
)
413 HeapFree(MyHeap
, 0, pLogFile
->LogName
);
415 HeapFree(MyHeap
, 0, pLogFile
);
427 LogfClose(PLOGFILE LogFile
,
433 if ((ForceClose
== FALSE
) &&
434 (LogFile
->Permanent
== TRUE
))
437 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
439 FlushFileBuffers(LogFile
->hFile
);
440 CloseHandle(LogFile
->hFile
);
441 LogfListRemoveItem(LogFile
);
443 RtlDeleteResource(&LogFile
->Lock
);
445 HeapFree(MyHeap
, 0, LogFile
->LogName
);
446 HeapFree(MyHeap
, 0, LogFile
->FileName
);
447 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
448 HeapFree(MyHeap
, 0, LogFile
);
453 VOID
LogfCloseAll(VOID
)
455 while (!IsListEmpty(&LogFileListHead
))
457 LogfClose(LogfListHead(), TRUE
);
460 DeleteCriticalSection(&LogFileListCs
);
463 VOID
LogfListInitialize(VOID
)
465 InitializeCriticalSection(&LogFileListCs
);
466 InitializeListHead(&LogFileListHead
);
469 PLOGFILE
LogfListHead(VOID
)
471 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
474 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
476 PLIST_ENTRY CurrentEntry
;
477 PLOGFILE Result
= NULL
;
479 EnterCriticalSection(&LogFileListCs
);
481 CurrentEntry
= LogFileListHead
.Flink
;
482 while (CurrentEntry
!= &LogFileListHead
)
484 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
488 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
494 CurrentEntry
= CurrentEntry
->Flink
;
497 LeaveCriticalSection(&LogFileListCs
);
501 /* Index starting from 1 */
502 INT
LogfListItemIndexByName(WCHAR
* Name
)
504 PLIST_ENTRY CurrentEntry
;
508 EnterCriticalSection(&LogFileListCs
);
510 CurrentEntry
= LogFileListHead
.Flink
;
511 while (CurrentEntry
!= &LogFileListHead
)
513 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
517 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
523 CurrentEntry
= CurrentEntry
->Flink
;
527 LeaveCriticalSection(&LogFileListCs
);
531 /* Index starting from 1 */
532 PLOGFILE
LogfListItemByIndex(INT Index
)
534 PLIST_ENTRY CurrentEntry
;
535 PLOGFILE Result
= NULL
;
538 EnterCriticalSection(&LogFileListCs
);
540 CurrentEntry
= LogFileListHead
.Flink
;
541 while (CurrentEntry
!= &LogFileListHead
)
545 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
549 CurrentEntry
= CurrentEntry
->Flink
;
553 LeaveCriticalSection(&LogFileListCs
);
557 INT
LogfListItemCount(VOID
)
559 PLIST_ENTRY CurrentEntry
;
562 EnterCriticalSection(&LogFileListCs
);
564 CurrentEntry
= LogFileListHead
.Flink
;
565 while (CurrentEntry
!= &LogFileListHead
)
567 CurrentEntry
= CurrentEntry
->Flink
;
571 LeaveCriticalSection(&LogFileListCs
);
575 VOID
LogfListAddItem(PLOGFILE Item
)
577 EnterCriticalSection(&LogFileListCs
);
578 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
579 LeaveCriticalSection(&LogFileListCs
);
582 VOID
LogfListRemoveItem(PLOGFILE Item
)
584 EnterCriticalSection(&LogFileListCs
);
585 RemoveEntryList(&Item
->ListEntry
);
586 LeaveCriticalSection(&LogFileListCs
);
590 ReadAnsiLogEntry(HANDLE hFile
,
592 DWORD nNumberOfBytesToRead
,
593 LPDWORD lpNumberOfBytesRead
)
598 UNICODE_STRING StringW
;
603 LPVOID lpUnicodeBuffer
= NULL
;
612 *lpNumberOfBytesRead
= 0;
614 lpUnicodeBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nNumberOfBytesToRead
);
615 if (lpUnicodeBuffer
== NULL
)
617 DPRINT1("Alloc failed!\n");
621 if (!ReadFile(hFile
, lpUnicodeBuffer
, nNumberOfBytesToRead
, &dwRead
, NULL
))
623 DPRINT1("Read failed!\n");
628 Dst
= (PEVENTLOGRECORD
)lpBuffer
;
629 Src
= (PEVENTLOGRECORD
)lpUnicodeBuffer
;
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
;
642 SrcPtr
= (LPWSTR
)((DWORD_PTR
)Src
+ sizeof(EVENTLOGRECORD
));
643 DstPtr
= (LPSTR
)((DWORD_PTR
)Dst
+ sizeof(EVENTLOGRECORD
));
645 /* Convert the module name */
646 RtlInitUnicodeString(&StringW
, SrcPtr
);
647 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
648 if (NT_SUCCESS(Status
))
650 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
652 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
654 RtlFreeAnsiString(&StringA
);
657 /* Convert the computer name */
658 if (NT_SUCCESS(Status
))
660 SrcPtr
= (PWSTR
)((DWORD_PTR
)SrcPtr
+ StringW
.MaximumLength
);
662 RtlInitUnicodeString(&StringW
, SrcPtr
);
663 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
664 if (NT_SUCCESS(Status
))
666 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
668 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
670 RtlFreeAnsiString(&StringA
);
674 /* Add the padding and the User SID*/
675 if (NT_SUCCESS(Status
))
677 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
) % sizeof(DWORD
));
678 RtlZeroMemory(DstPtr
, dwPadding
);
680 DstPtr
= (LPSTR
)((DWORD_PTR
)DstPtr
+ dwPadding
);
681 RtlCopyMemory(DstPtr
,
682 (PVOID
)((DWORD_PTR
)Src
+ Src
->UserSidOffset
),
685 Dst
->UserSidOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
689 /* Convert the strings */
690 if (NT_SUCCESS(Status
))
692 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->UserSidLength
);
694 SrcString
= (LPWSTR
)((DWORD_PTR
)Src
+ (DWORD
)Src
->StringOffset
);
695 DstString
= (LPSTR
)DstPtr
;
697 for (i
= 0; i
< Dst
->NumStrings
; i
++)
699 RtlInitUnicodeString(&StringW
, SrcString
);
701 RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
703 RtlCopyMemory(DstString
, StringA
.Buffer
, StringA
.MaximumLength
);
705 SrcString
= (LPWSTR
)((DWORD_PTR
)SrcString
+
706 (DWORD
)StringW
.MaximumLength
);
708 DstString
= (LPSTR
)((DWORD_PTR
)DstString
+
709 (DWORD
)StringA
.MaximumLength
);
711 RtlFreeAnsiString(&StringA
);
714 Dst
->StringOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
717 /* Copy the binary data */
718 DstPtr
= (PVOID
)DstString
;
719 Dst
->DataOffset
= (DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
;
721 RtlCopyMemory(DstPtr
, (PVOID
)((DWORD_PTR
)Src
+ Src
->DataOffset
), Src
->DataLength
);
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
);
728 dwEntryLength
= (DWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
+ sizeof(DWORD
) - (DWORD_PTR
)Dst
);
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
;
735 *lpNumberOfBytesRead
= dwEntryLength
;
739 if (lpUnicodeBuffer
!= NULL
)
740 HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer
);
746 DWORD
LogfReadEvent(PLOGFILE LogFile
,
748 DWORD
* RecordNumber
,
755 DWORD dwOffset
, dwRead
, dwRecSize
;
756 DWORD dwBufferUsage
= 0, dwRecNum
;
758 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
759 return ERROR_INVALID_PARAMETER
;
761 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
762 return ERROR_INVALID_PARAMETER
;
764 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
765 return ERROR_INVALID_PARAMETER
;
767 if ((*RecordNumber
==0) && !(EVENTLOG_SEQUENTIAL_READ
))
769 return ERROR_INVALID_PARAMETER
;
772 dwRecNum
= *RecordNumber
;
774 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
779 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
783 RtlReleaseResource(&LogFile
->Lock
);
784 return ERROR_HANDLE_EOF
;
787 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
788 INVALID_SET_FILE_POINTER
)
790 DPRINT1("SetFilePointer() failed!\n");
794 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
796 DPRINT1("ReadFile() failed!\n");
800 if (dwRecSize
> BufSize
)
802 *BytesNeeded
= dwRecSize
;
803 RtlReleaseResource(&LogFile
->Lock
);
804 return ERROR_INSUFFICIENT_BUFFER
;
807 if (SetFilePointer(LogFile
->hFile
,
808 -((LONG
) sizeof(DWORD
)),
810 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
812 DPRINT1("SetFilePointer() failed!\n");
818 if (!ReadAnsiLogEntry(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
))
820 DPRINT1("ReadAnsiLogEntry() failed!\n");
826 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
828 DPRINT1("ReadFile() failed!\n");
833 dwBufferUsage
+= dwRead
;
835 while (dwBufferUsage
<= BufSize
)
837 if (Flags
& EVENTLOG_FORWARDS_READ
)
842 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
846 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
847 INVALID_SET_FILE_POINTER
)
849 DPRINT1("SetFilePointer() failed!\n");
853 if (!ReadFile(LogFile
->hFile
,
859 DPRINT1("ReadFile() failed!\n");
863 if (dwBufferUsage
+ dwRecSize
> BufSize
)
866 if (SetFilePointer(LogFile
->hFile
,
867 -((LONG
) sizeof(DWORD
)),
869 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
871 DPRINT1("SetFilePointer() failed!\n");
877 if (!ReadAnsiLogEntry(LogFile
->hFile
,
878 Buffer
+ dwBufferUsage
,
882 DPRINT1("ReadAnsiLogEntry() failed!\n");
888 if (!ReadFile(LogFile
->hFile
,
889 Buffer
+ dwBufferUsage
,
894 DPRINT1("ReadFile() failed!\n");
899 dwBufferUsage
+= dwRead
;
902 *BytesRead
= dwBufferUsage
;
903 * RecordNumber
= dwRecNum
;
904 RtlReleaseResource(&LogFile
->Lock
);
905 return ERROR_SUCCESS
;
908 DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
909 RtlReleaseResource(&LogFile
->Lock
);
910 return GetLastError();
913 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
919 PEVENTLOGRECORD RecBuf
;
920 LARGE_INTEGER logFileSize
;
928 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
930 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
932 if (!GetFileSizeEx(LogFile
->hFile
, &logFileSize
))
934 RtlReleaseResource(&LogFile
->Lock
);
938 /* If the size of the file is over MaxSize */
939 if ((logFileSize
.QuadPart
+ BufSize
)> LogFile
->Header
.MaxSize
)
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 */
947 DPRINT("EventLogFile has reached maximume size\n");
951 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
952 HeapFree(GetProcessHeap(), 0, RecBuf
);
953 RtlReleaseResource(&LogFile
->Lock
);
957 /* Get the oldest record data */
958 RecOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
960 if (SetFilePointer(LogFile
->hFile
,
963 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
965 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
966 HeapFree(GetProcessHeap(), 0, RecBuf
);
967 RtlReleaseResource(&LogFile
->Lock
);
971 if (!ReadFile(LogFile
->hFile
, RecBuf
, sizeof(EVENTLOGRECORD
), &dwRead
, NULL
))
973 DPRINT1("ReadFile() failed!\n");
974 HeapFree(GetProcessHeap(), 0, RecBuf
);
975 RtlReleaseResource(&LogFile
->Lock
);
979 if (RecBuf
->Reserved
!= LOGFILE_SIGNATURE
)
981 DPRINT1("LogFile corrupt!\n");
982 RtlReleaseResource(&LogFile
->Lock
);
986 LogfDeleteOffsetInformation(LogFile
,LogFile
->Header
.OldestRecordNumber
);
988 LogFile
->Header
.OldestRecordNumber
++;
990 OverWriteLength
+= RecBuf
->Length
;
991 /* Check the size of the record as the record adding may be larger */
992 if (OverWriteLength
>= BufSize
)
994 DPRINT("Record will fit. Length %d, BufSize %d\n", OverWriteLength
, BufSize
);
995 LogFile
->Header
.StartOffset
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
999 HeapFree(GetProcessHeap(), 0, RecBuf
);
1002 WriteOffSet
= LogFile
->Header
.EndOffset
;
1004 if (SetFilePointer(LogFile
->hFile
,
1007 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1009 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1010 RtlReleaseResource(&LogFile
->Lock
);
1014 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
1016 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1017 RtlReleaseResource(&LogFile
->Lock
);
1021 if (!LogfAddOffsetInformation(LogFile
,
1022 LogFile
->Header
.CurrentRecordNumber
,
1025 RtlReleaseResource(&LogFile
->Lock
);
1029 LogFile
->Header
.CurrentRecordNumber
++;
1031 if (WriteOffSet
== LogFile
->Header
.EndOffset
)
1033 LogFile
->Header
.EndOffset
+= dwWritten
;
1035 if (SetFilePointer(LogFile
->hFile
,
1036 LogFile
->Header
.EndOffset
,
1038 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1040 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1041 RtlReleaseResource(&LogFile
->Lock
);
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
;
1056 if (!WriteFile(LogFile
->hFile
,
1058 sizeof(EVENTLOGEOF
),
1062 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1063 RtlReleaseResource(&LogFile
->Lock
);
1067 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
1068 INVALID_SET_FILE_POINTER
)
1070 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1071 RtlReleaseResource(&LogFile
->Lock
);
1075 if (!WriteFile(LogFile
->hFile
,
1077 sizeof(EVENTLOGHEADER
),
1081 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
1082 RtlReleaseResource(&LogFile
->Lock
);
1086 if (!FlushFileBuffers(LogFile
->hFile
))
1088 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
1089 RtlReleaseResource(&LogFile
->Lock
);
1093 RtlReleaseResource(&LogFile
->Lock
);
1099 LogfClearFile(PLOGFILE LogFile
,
1100 PUNICODE_STRING BackupFileName
)
1104 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
1106 if (BackupFileName
->Length
> 0)
1108 /* Write a backup file */
1109 Status
= LogfBackupFile(LogFile
,
1111 if (!NT_SUCCESS(Status
))
1113 DPRINT1("LogfBackupFile failed (Status: 0x%08lx)\n", Status
);
1118 Status
= LogfInitializeNew(LogFile
);
1119 if (!NT_SUCCESS(Status
))
1121 DPRINT1("LogfInitializeNew failed (Status: 0x%08lx)\n", Status
);
1124 RtlReleaseResource(&LogFile
->Lock
);
1131 LogfBackupFile(PLOGFILE LogFile
,
1132 PUNICODE_STRING BackupFileName
)
1134 OBJECT_ATTRIBUTES ObjectAttributes
;
1135 IO_STATUS_BLOCK IoStatusBlock
;
1136 EVENTLOGHEADER Header
;
1138 HANDLE FileHandle
= NULL
;
1140 LARGE_INTEGER FileOffset
;
1142 PUCHAR Buffer
= NULL
;
1144 DWORD dwOffset
, dwRead
, dwRecSize
;
1146 DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile
, BackupFileName
);
1148 /* Lock the log file shared */
1149 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
1151 InitializeObjectAttributes(&ObjectAttributes
,
1153 OBJ_CASE_INSENSITIVE
,
1157 Status
= NtCreateFile(&FileHandle
,
1158 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1162 FILE_ATTRIBUTE_NORMAL
,
1165 FILE_WRITE_THROUGH
| FILE_SYNCHRONOUS_IO_NONALERT
,
1168 if (!NT_SUCCESS(Status
))
1170 DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName
, Status
);
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;
1184 Header
.Flags
= ELF_LOGFILE_HEADER_DIRTY
;
1185 Header
.Retention
= LogFile
->Header
.Retention
;
1186 Header
.EndHeaderSize
= sizeof(EVENTLOGHEADER
);
1188 /* Write the (dirty) log file header */
1189 Status
= NtWriteFile(FileHandle
,
1195 sizeof(EVENTLOGHEADER
),
1198 if (!NT_SUCCESS(Status
))
1200 DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status
);
1204 for (i
= LogFile
->Header
.OldestRecordNumber
; i
< LogFile
->Header
.CurrentRecordNumber
; i
++)
1206 dwOffset
= LogfOffsetByNumber(LogFile
, i
);
1210 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1212 DPRINT1("SetFilePointer() failed!\n");
1216 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
1218 DPRINT1("ReadFile() failed!\n");
1222 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1224 DPRINT1("SetFilePointer() failed!\n");
1228 Buffer
= HeapAlloc(MyHeap
, 0, dwRecSize
);
1231 DPRINT1("HeapAlloc() failed!\n");
1235 if (!ReadFile(LogFile
->hFile
, &Buffer
, dwRecSize
, &dwRead
, NULL
))
1237 DPRINT1("ReadFile() failed!\n");
1241 /* Write the event record */
1242 Status
= NtWriteFile(FileHandle
,
1251 if (!NT_SUCCESS(Status
))
1253 DPRINT1("NtWriteFile() failed!\n");
1257 /* Update the header information */
1258 Header
.EndOffset
+= dwRecSize
;
1260 /* Free the buffer */
1261 HeapFree(MyHeap
, 0, Buffer
);
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
);
1277 /* Write the EOF record */
1278 Status
= NtWriteFile(FileHandle
,
1284 sizeof(EVENTLOGEOF
),
1287 if (!NT_SUCCESS(Status
))
1289 DPRINT1("NtWriteFile() failed!\n");
1293 /* Update the header information */
1294 Header
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1295 Header
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1296 Header
.MaxSize
= Header
.EndOffset
+ sizeof(EVENTLOGEOF
);
1299 /* Write the (clean) log file header */
1300 FileOffset
.QuadPart
= 0;
1301 Status
= NtWriteFile(FileHandle
,
1307 sizeof(EVENTLOGHEADER
),
1310 if (!NT_SUCCESS(Status
))
1312 DPRINT1("NtWriteFile() failed!\n");
1316 /* Free the buffer */
1318 HeapFree(MyHeap
, 0, Buffer
);
1320 /* Close the backup file */
1321 if (FileHandle
!= NULL
)
1322 NtClose(FileHandle
);
1324 /* Unlock the log file */
1325 RtlReleaseResource(&LogFile
->Lock
);
1331 /* Returns 0 if nothing found. */
1332 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
1336 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
1338 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
1339 return LogFile
->OffsetInfo
[i
].EventOffset
;
1344 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
1346 return LogFile
->Header
.OldestRecordNumber
;
1349 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
1351 return LogFile
->Header
.CurrentRecordNumber
;
1354 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
1358 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
1363 for (i
= 0; i
< LogFile
->OffsetInfoNext
- 1; i
++)
1365 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+ 1].EventNumber
;
1366 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+ 1].EventOffset
;
1368 LogFile
->OffsetInfoNext
--;
1372 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
1374 LPVOID NewOffsetInfo
;
1376 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
1378 NewOffsetInfo
= HeapReAlloc(MyHeap
,
1380 LogFile
->OffsetInfo
,
1381 (LogFile
->OffsetInfoSize
+ 64) *
1382 sizeof(EVENT_OFFSET_INFO
));
1386 DPRINT1("Can't reallocate heap.\n");
1390 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
1391 LogFile
->OffsetInfoSize
+= 64;
1394 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
1395 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
1396 LogFile
->OffsetInfoNext
++;
1401 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
1402 DWORD dwRecordNumber
,
1407 LPCWSTR ComputerName
,
1416 PEVENTLOGRECORD pRec
;
1423 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
1424 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
1426 if (dwRecSize
% 4 != 0)
1427 dwRecSize
+= 4 - (dwRecSize
% 4);
1429 dwRecSize
+= dwSidLength
;
1431 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1433 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1434 str
+= lstrlenW(str
) + 1;
1437 dwRecSize
+= dwDataSize
;
1438 if (dwRecSize
% 4 != 0)
1439 dwRecSize
+= 4 - (dwRecSize
% 4);
1443 Buffer
= HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
1447 DPRINT1("Can't allocate heap!\n");
1451 pRec
= (PEVENTLOGRECORD
) Buffer
;
1452 pRec
->Length
= dwRecSize
;
1453 pRec
->Reserved
= LOGFILE_SIGNATURE
;
1454 pRec
->RecordNumber
= dwRecordNumber
;
1456 GetSystemTime(&SysTime
);
1457 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
1458 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
1460 pRec
->EventID
= dwEventId
;
1461 pRec
->EventType
= wType
;
1462 pRec
->EventCategory
= wCategory
;
1464 pos
= sizeof(EVENTLOGRECORD
);
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
);
1471 pRec
->UserSidOffset
= pos
;
1474 pos
+= 4 - (pos
% 4);
1478 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1479 pRec
->UserSidLength
= dwSidLength
;
1480 pRec
->UserSidOffset
= pos
;
1484 pRec
->StringOffset
= pos
;
1485 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1487 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1488 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1489 str
+= lstrlenW(str
) + 1;
1491 pRec
->NumStrings
= wNumStrings
;
1493 pRec
->DataOffset
= pos
;
1496 pRec
->DataLength
= dwDataSize
;
1497 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1502 pos
+= 4 - (pos
% 4);
1504 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1506 *lpRecSize
= dwRecSize
;
1512 LogfReportEvent(WORD wType
,
1520 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1521 DWORD dwComputerNameLength
= MAX_COMPUTERNAME_LENGTH
+ 1;
1522 PEVENTSOURCE pEventSource
= NULL
;
1528 if (!GetComputerNameW(szComputerName
, &dwComputerNameLength
))
1530 szComputerName
[0] = 0;
1533 pEventSource
= GetEventSourceByName(L
"EventLog");
1534 if (pEventSource
== NULL
)
1539 lastRec
= LogfGetCurrentRecord(pEventSource
->LogFile
);
1541 logBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
1546 pEventSource
->szName
,
1547 (LPCWSTR
)szComputerName
,
1555 dwError
= LogfWriteData(pEventSource
->LogFile
, recSize
, logBuffer
);
1558 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource
->LogFile
->FileName
);
1561 LogfFreeRecord(logBuffer
);