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 HeapFree(GetProcessHeap(), 0, RecBuf
);
983 RtlReleaseResource(&LogFile
->Lock
);
987 LogfDeleteOffsetInformation(LogFile
,LogFile
->Header
.OldestRecordNumber
);
989 LogFile
->Header
.OldestRecordNumber
++;
991 OverWriteLength
+= RecBuf
->Length
;
992 /* Check the size of the record as the record adding may be larger */
993 if (OverWriteLength
>= BufSize
)
995 DPRINT("Record will fit. Length %d, BufSize %d\n", OverWriteLength
, BufSize
);
996 LogFile
->Header
.StartOffset
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
1000 HeapFree(GetProcessHeap(), 0, RecBuf
);
1003 WriteOffSet
= LogFile
->Header
.EndOffset
;
1005 if (SetFilePointer(LogFile
->hFile
,
1008 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1010 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1011 RtlReleaseResource(&LogFile
->Lock
);
1015 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
1017 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1018 RtlReleaseResource(&LogFile
->Lock
);
1022 if (!LogfAddOffsetInformation(LogFile
,
1023 LogFile
->Header
.CurrentRecordNumber
,
1026 RtlReleaseResource(&LogFile
->Lock
);
1030 LogFile
->Header
.CurrentRecordNumber
++;
1032 if (WriteOffSet
== LogFile
->Header
.EndOffset
)
1034 LogFile
->Header
.EndOffset
+= dwWritten
;
1036 if (SetFilePointer(LogFile
->hFile
,
1037 LogFile
->Header
.EndOffset
,
1039 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1041 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1042 RtlReleaseResource(&LogFile
->Lock
);
1046 EofRec
.Ones
= 0x11111111;
1047 EofRec
.Twos
= 0x22222222;
1048 EofRec
.Threes
= 0x33333333;
1049 EofRec
.Fours
= 0x44444444;
1050 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1051 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1052 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1053 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1054 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
1055 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
1057 if (!WriteFile(LogFile
->hFile
,
1059 sizeof(EVENTLOGEOF
),
1063 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1064 RtlReleaseResource(&LogFile
->Lock
);
1068 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
1069 INVALID_SET_FILE_POINTER
)
1071 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1072 RtlReleaseResource(&LogFile
->Lock
);
1076 if (!WriteFile(LogFile
->hFile
,
1078 sizeof(EVENTLOGHEADER
),
1082 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
1083 RtlReleaseResource(&LogFile
->Lock
);
1087 if (!FlushFileBuffers(LogFile
->hFile
))
1089 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
1090 RtlReleaseResource(&LogFile
->Lock
);
1094 RtlReleaseResource(&LogFile
->Lock
);
1100 LogfClearFile(PLOGFILE LogFile
,
1101 PUNICODE_STRING BackupFileName
)
1105 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
1107 if (BackupFileName
->Length
> 0)
1109 /* Write a backup file */
1110 Status
= LogfBackupFile(LogFile
,
1112 if (!NT_SUCCESS(Status
))
1114 DPRINT1("LogfBackupFile failed (Status: 0x%08lx)\n", Status
);
1119 Status
= LogfInitializeNew(LogFile
);
1120 if (!NT_SUCCESS(Status
))
1122 DPRINT1("LogfInitializeNew failed (Status: 0x%08lx)\n", Status
);
1125 RtlReleaseResource(&LogFile
->Lock
);
1132 LogfBackupFile(PLOGFILE LogFile
,
1133 PUNICODE_STRING BackupFileName
)
1135 OBJECT_ATTRIBUTES ObjectAttributes
;
1136 IO_STATUS_BLOCK IoStatusBlock
;
1137 EVENTLOGHEADER Header
;
1139 HANDLE FileHandle
= NULL
;
1141 LARGE_INTEGER FileOffset
;
1143 PUCHAR Buffer
= NULL
;
1145 DWORD dwOffset
, dwRead
, dwRecSize
;
1147 DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile
, BackupFileName
);
1149 /* Lock the log file shared */
1150 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
1152 InitializeObjectAttributes(&ObjectAttributes
,
1154 OBJ_CASE_INSENSITIVE
,
1158 Status
= NtCreateFile(&FileHandle
,
1159 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1163 FILE_ATTRIBUTE_NORMAL
,
1166 FILE_WRITE_THROUGH
| FILE_SYNCHRONOUS_IO_NONALERT
,
1169 if (!NT_SUCCESS(Status
))
1171 DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName
, Status
);
1175 /* Initialize the (dirty) log file header */
1176 Header
.HeaderSize
= sizeof(EVENTLOGHEADER
);
1177 Header
.Signature
= LOGFILE_SIGNATURE
;
1178 Header
.MajorVersion
= MAJORVER
;
1179 Header
.MinorVersion
= MINORVER
;
1180 Header
.StartOffset
= sizeof(EVENTLOGHEADER
);
1181 Header
.EndOffset
= sizeof(EVENTLOGHEADER
);
1182 Header
.CurrentRecordNumber
= 1;
1183 Header
.OldestRecordNumber
= 1;
1185 Header
.Flags
= ELF_LOGFILE_HEADER_DIRTY
;
1186 Header
.Retention
= LogFile
->Header
.Retention
;
1187 Header
.EndHeaderSize
= sizeof(EVENTLOGHEADER
);
1189 /* Write the (dirty) log file header */
1190 Status
= NtWriteFile(FileHandle
,
1196 sizeof(EVENTLOGHEADER
),
1199 if (!NT_SUCCESS(Status
))
1201 DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status
);
1205 for (i
= LogFile
->Header
.OldestRecordNumber
; i
< LogFile
->Header
.CurrentRecordNumber
; i
++)
1207 dwOffset
= LogfOffsetByNumber(LogFile
, i
);
1211 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1213 DPRINT1("SetFilePointer() failed!\n");
1217 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
1219 DPRINT1("ReadFile() failed!\n");
1223 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1225 DPRINT1("SetFilePointer() failed!\n");
1229 Buffer
= HeapAlloc(MyHeap
, 0, dwRecSize
);
1232 DPRINT1("HeapAlloc() failed!\n");
1236 if (!ReadFile(LogFile
->hFile
, &Buffer
, dwRecSize
, &dwRead
, NULL
))
1238 DPRINT1("ReadFile() failed!\n");
1242 /* Write the event record */
1243 Status
= NtWriteFile(FileHandle
,
1252 if (!NT_SUCCESS(Status
))
1254 DPRINT1("NtWriteFile() failed!\n");
1258 /* Update the header information */
1259 Header
.EndOffset
+= dwRecSize
;
1261 /* Free the buffer */
1262 HeapFree(MyHeap
, 0, Buffer
);
1266 /* Initialize the EOF record */
1267 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1268 EofRec
.Ones
= 0x11111111;
1269 EofRec
.Twos
= 0x22222222;
1270 EofRec
.Threes
= 0x33333333;
1271 EofRec
.Fours
= 0x44444444;
1272 EofRec
.BeginRecord
= sizeof(EVENTLOGHEADER
);
1273 EofRec
.EndRecord
= Header
.EndOffset
;
1274 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1275 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1276 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1278 /* Write the EOF record */
1279 Status
= NtWriteFile(FileHandle
,
1285 sizeof(EVENTLOGEOF
),
1288 if (!NT_SUCCESS(Status
))
1290 DPRINT1("NtWriteFile() failed!\n");
1294 /* Update the header information */
1295 Header
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1296 Header
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1297 Header
.MaxSize
= Header
.EndOffset
+ sizeof(EVENTLOGEOF
);
1300 /* Write the (clean) log file header */
1301 FileOffset
.QuadPart
= 0;
1302 Status
= NtWriteFile(FileHandle
,
1308 sizeof(EVENTLOGHEADER
),
1311 if (!NT_SUCCESS(Status
))
1313 DPRINT1("NtWriteFile() failed!\n");
1317 /* Free the buffer */
1319 HeapFree(MyHeap
, 0, Buffer
);
1321 /* Close the backup file */
1322 if (FileHandle
!= NULL
)
1323 NtClose(FileHandle
);
1325 /* Unlock the log file */
1326 RtlReleaseResource(&LogFile
->Lock
);
1332 /* Returns 0 if nothing found. */
1333 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
1337 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
1339 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
1340 return LogFile
->OffsetInfo
[i
].EventOffset
;
1345 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
1347 return LogFile
->Header
.OldestRecordNumber
;
1350 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
1352 return LogFile
->Header
.CurrentRecordNumber
;
1355 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
1359 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
1364 for (i
= 0; i
< LogFile
->OffsetInfoNext
- 1; i
++)
1366 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+ 1].EventNumber
;
1367 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+ 1].EventOffset
;
1369 LogFile
->OffsetInfoNext
--;
1373 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
1375 LPVOID NewOffsetInfo
;
1377 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
1379 NewOffsetInfo
= HeapReAlloc(MyHeap
,
1381 LogFile
->OffsetInfo
,
1382 (LogFile
->OffsetInfoSize
+ 64) *
1383 sizeof(EVENT_OFFSET_INFO
));
1387 DPRINT1("Can't reallocate heap.\n");
1391 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
1392 LogFile
->OffsetInfoSize
+= 64;
1395 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
1396 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
1397 LogFile
->OffsetInfoNext
++;
1402 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
1403 DWORD dwRecordNumber
,
1408 LPCWSTR ComputerName
,
1417 PEVENTLOGRECORD pRec
;
1424 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
1425 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
1427 if (dwRecSize
% 4 != 0)
1428 dwRecSize
+= 4 - (dwRecSize
% 4);
1430 dwRecSize
+= dwSidLength
;
1432 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1434 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1435 str
+= lstrlenW(str
) + 1;
1438 dwRecSize
+= dwDataSize
;
1439 if (dwRecSize
% 4 != 0)
1440 dwRecSize
+= 4 - (dwRecSize
% 4);
1444 Buffer
= HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
1448 DPRINT1("Can't allocate heap!\n");
1452 pRec
= (PEVENTLOGRECORD
) Buffer
;
1453 pRec
->Length
= dwRecSize
;
1454 pRec
->Reserved
= LOGFILE_SIGNATURE
;
1455 pRec
->RecordNumber
= dwRecordNumber
;
1457 GetSystemTime(&SysTime
);
1458 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
1459 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
1461 pRec
->EventID
= dwEventId
;
1462 pRec
->EventType
= wType
;
1463 pRec
->EventCategory
= wCategory
;
1465 pos
= sizeof(EVENTLOGRECORD
);
1467 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
1468 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
1469 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
1470 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
1472 pRec
->UserSidOffset
= pos
;
1475 pos
+= 4 - (pos
% 4);
1479 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1480 pRec
->UserSidLength
= dwSidLength
;
1481 pRec
->UserSidOffset
= pos
;
1485 pRec
->StringOffset
= pos
;
1486 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1488 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1489 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1490 str
+= lstrlenW(str
) + 1;
1492 pRec
->NumStrings
= wNumStrings
;
1494 pRec
->DataOffset
= pos
;
1497 pRec
->DataLength
= dwDataSize
;
1498 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1503 pos
+= 4 - (pos
% 4);
1505 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1507 *lpRecSize
= dwRecSize
;
1513 LogfReportEvent(WORD wType
,
1521 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1522 DWORD dwComputerNameLength
= MAX_COMPUTERNAME_LENGTH
+ 1;
1523 PEVENTSOURCE pEventSource
= NULL
;
1529 if (!GetComputerNameW(szComputerName
, &dwComputerNameLength
))
1531 szComputerName
[0] = 0;
1534 pEventSource
= GetEventSourceByName(L
"EventLog");
1535 if (pEventSource
== NULL
)
1540 lastRec
= LogfGetCurrentRecord(pEventSource
->LogFile
);
1542 logBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
1547 pEventSource
->szName
,
1548 (LPCWSTR
)szComputerName
,
1556 dwError
= LogfWriteData(pEventSource
->LogFile
, recSize
, logBuffer
);
1559 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource
->LogFile
->FileName
);
1562 LogfFreeRecord(logBuffer
);