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
)
1102 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
1104 if (BackupFileName
->Length
> 0)
1106 /* FIXME: Write a backup file */
1109 LogfInitializeNew(LogFile
);
1111 RtlReleaseResource(&LogFile
->Lock
);
1113 return STATUS_SUCCESS
;
1118 LogfBackupFile(PLOGFILE LogFile
,
1119 PUNICODE_STRING BackupFileName
)
1121 OBJECT_ATTRIBUTES ObjectAttributes
;
1122 IO_STATUS_BLOCK IoStatusBlock
;
1123 EVENTLOGHEADER Header
;
1125 HANDLE FileHandle
= NULL
;
1127 LARGE_INTEGER FileOffset
;
1129 PUCHAR Buffer
= NULL
;
1131 DWORD dwOffset
, dwRead
, dwRecSize
;
1133 DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile
, BackupFileName
);
1135 /* Lock the log file shared */
1136 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
1138 InitializeObjectAttributes(&ObjectAttributes
,
1140 OBJ_CASE_INSENSITIVE
,
1144 Status
= NtCreateFile(&FileHandle
,
1145 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1149 FILE_ATTRIBUTE_NORMAL
,
1152 FILE_WRITE_THROUGH
| FILE_SYNCHRONOUS_IO_NONALERT
,
1155 if (!NT_SUCCESS(Status
))
1157 DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName
, Status
);
1161 /* Initialize the (dirty) log file header */
1162 Header
.HeaderSize
= sizeof(EVENTLOGHEADER
);
1163 Header
.Signature
= LOGFILE_SIGNATURE
;
1164 Header
.MajorVersion
= MAJORVER
;
1165 Header
.MinorVersion
= MINORVER
;
1166 Header
.StartOffset
= sizeof(EVENTLOGHEADER
);
1167 Header
.EndOffset
= sizeof(EVENTLOGHEADER
);
1168 Header
.CurrentRecordNumber
= 1;
1169 Header
.OldestRecordNumber
= 1;
1171 Header
.Flags
= ELF_LOGFILE_HEADER_DIRTY
;
1172 Header
.Retention
= LogFile
->Header
.Retention
;
1173 Header
.EndHeaderSize
= sizeof(EVENTLOGHEADER
);
1175 /* Write the (dirty) log file header */
1176 Status
= NtWriteFile(FileHandle
,
1182 sizeof(EVENTLOGHEADER
),
1185 if (!NT_SUCCESS(Status
))
1187 DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status
);
1191 for (i
= LogFile
->Header
.OldestRecordNumber
; i
< LogFile
->Header
.CurrentRecordNumber
; i
++)
1193 dwOffset
= LogfOffsetByNumber(LogFile
, i
);
1197 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1199 DPRINT1("SetFilePointer() failed!\n");
1203 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
1205 DPRINT1("ReadFile() failed!\n");
1209 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1211 DPRINT1("SetFilePointer() failed!\n");
1215 Buffer
= HeapAlloc(MyHeap
, 0, dwRecSize
);
1218 DPRINT1("HeapAlloc() failed!\n");
1222 if (!ReadFile(LogFile
->hFile
, &Buffer
, dwRecSize
, &dwRead
, NULL
))
1224 DPRINT1("ReadFile() failed!\n");
1228 /* Write the event record */
1229 Status
= NtWriteFile(FileHandle
,
1238 if (!NT_SUCCESS(Status
))
1240 DPRINT1("NtWriteFile() failed!\n");
1244 /* Update the header information */
1245 Header
.EndOffset
+= dwRecSize
;
1247 /* Free the buffer */
1248 HeapFree(MyHeap
, 0, Buffer
);
1252 /* Initialize the EOF record */
1253 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1254 EofRec
.Ones
= 0x11111111;
1255 EofRec
.Twos
= 0x22222222;
1256 EofRec
.Threes
= 0x33333333;
1257 EofRec
.Fours
= 0x44444444;
1258 EofRec
.BeginRecord
= sizeof(EVENTLOGHEADER
);
1259 EofRec
.EndRecord
= Header
.EndOffset
;
1260 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1261 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1262 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1264 /* Write the EOF record */
1265 Status
= NtWriteFile(FileHandle
,
1271 sizeof(EVENTLOGEOF
),
1274 if (!NT_SUCCESS(Status
))
1276 DPRINT1("NtWriteFile() failed!\n");
1280 /* Update the header information */
1281 Header
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1282 Header
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1283 Header
.MaxSize
= Header
.EndOffset
+ sizeof(EVENTLOGEOF
);
1286 /* Write the (clean) log file header */
1287 FileOffset
.QuadPart
= 0;
1288 Status
= NtWriteFile(FileHandle
,
1294 sizeof(EVENTLOGHEADER
),
1297 if (!NT_SUCCESS(Status
))
1299 DPRINT1("NtWriteFile() failed!\n");
1303 /* Free the buffer */
1305 HeapFree(MyHeap
, 0, Buffer
);
1307 /* Close the backup file */
1308 if (FileHandle
!= NULL
)
1309 NtClose(FileHandle
);
1311 /* Unlock the log file */
1312 RtlReleaseResource(&LogFile
->Lock
);
1318 /* Returns 0 if nothing found. */
1319 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
1323 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
1325 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
1326 return LogFile
->OffsetInfo
[i
].EventOffset
;
1331 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
1333 return LogFile
->Header
.OldestRecordNumber
;
1336 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
1338 return LogFile
->Header
.CurrentRecordNumber
;
1341 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
1345 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
1350 for (i
= 0; i
< LogFile
->OffsetInfoNext
- 1; i
++)
1352 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+ 1].EventNumber
;
1353 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+ 1].EventOffset
;
1355 LogFile
->OffsetInfoNext
--;
1359 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
1361 LPVOID NewOffsetInfo
;
1363 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
1365 NewOffsetInfo
= HeapReAlloc(MyHeap
,
1367 LogFile
->OffsetInfo
,
1368 (LogFile
->OffsetInfoSize
+ 64) *
1369 sizeof(EVENT_OFFSET_INFO
));
1373 DPRINT1("Can't reallocate heap.\n");
1377 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
1378 LogFile
->OffsetInfoSize
+= 64;
1381 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
1382 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
1383 LogFile
->OffsetInfoNext
++;
1388 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
1389 DWORD dwRecordNumber
,
1394 LPCWSTR ComputerName
,
1403 PEVENTLOGRECORD pRec
;
1410 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
1411 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
1413 if (dwRecSize
% 4 != 0)
1414 dwRecSize
+= 4 - (dwRecSize
% 4);
1416 dwRecSize
+= dwSidLength
;
1418 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1420 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1421 str
+= lstrlenW(str
) + 1;
1424 dwRecSize
+= dwDataSize
;
1425 if (dwRecSize
% 4 != 0)
1426 dwRecSize
+= 4 - (dwRecSize
% 4);
1430 Buffer
= HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
1434 DPRINT1("Can't allocate heap!\n");
1438 pRec
= (PEVENTLOGRECORD
) Buffer
;
1439 pRec
->Length
= dwRecSize
;
1440 pRec
->Reserved
= LOGFILE_SIGNATURE
;
1441 pRec
->RecordNumber
= dwRecordNumber
;
1443 GetSystemTime(&SysTime
);
1444 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
1445 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
1447 pRec
->EventID
= dwEventId
;
1448 pRec
->EventType
= wType
;
1449 pRec
->EventCategory
= wCategory
;
1451 pos
= sizeof(EVENTLOGRECORD
);
1453 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
1454 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
1455 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
1456 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
1458 pRec
->UserSidOffset
= pos
;
1461 pos
+= 4 - (pos
% 4);
1465 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1466 pRec
->UserSidLength
= dwSidLength
;
1467 pRec
->UserSidOffset
= pos
;
1471 pRec
->StringOffset
= pos
;
1472 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1474 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1475 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1476 str
+= lstrlenW(str
) + 1;
1478 pRec
->NumStrings
= wNumStrings
;
1480 pRec
->DataOffset
= pos
;
1483 pRec
->DataLength
= dwDataSize
;
1484 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1489 pos
+= 4 - (pos
% 4);
1491 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1493 *lpRecSize
= dwRecSize
;
1499 LogfReportEvent(WORD wType
,
1507 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1508 DWORD dwComputerNameLength
= MAX_COMPUTERNAME_LENGTH
+ 1;
1509 PEVENTSOURCE pEventSource
= NULL
;
1515 if (!GetComputerNameW(szComputerName
, &dwComputerNameLength
))
1517 szComputerName
[0] = 0;
1520 pEventSource
= GetEventSourceByName(L
"EventLog");
1521 if (pEventSource
== NULL
)
1526 lastRec
= LogfGetCurrentRecord(pEventSource
->LogFile
);
1528 logBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
1533 pEventSource
->szName
,
1534 (LPCWSTR
)szComputerName
,
1542 dwError
= LogfWriteData(pEventSource
->LogFile
, recSize
, logBuffer
);
1545 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource
->LogFile
->FileName
);
1548 LogfFreeRecord(logBuffer
);