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
;
359 StringCchCopy(pLogFile
->LogName
,lstrlenW(LogName
) + 1, LogName
);
362 (WCHAR
*) HeapAlloc(MyHeap
,
364 (lstrlenW(FileName
->Buffer
) + 1) * sizeof(WCHAR
));
365 if (pLogFile
->FileName
== NULL
)
367 DPRINT1("Can't allocate heap\n");
368 Status
= STATUS_NO_MEMORY
;
372 StringCchCopy(pLogFile
->FileName
, lstrlenW(FileName
->Buffer
) + 1, FileName
->Buffer
);
374 pLogFile
->OffsetInfo
=
375 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
377 sizeof(EVENT_OFFSET_INFO
) * 64);
378 if (pLogFile
->OffsetInfo
== NULL
)
380 DPRINT1("Can't allocate heap\n");
381 Status
= STATUS_NO_MEMORY
;
385 pLogFile
->OffsetInfoSize
= 64;
387 pLogFile
->Permanent
= Permanent
;
390 Status
= LogfInitializeNew(pLogFile
);
392 Status
= LogfInitializeExisting(pLogFile
, Backup
);
394 if (!NT_SUCCESS(Status
))
397 RtlInitializeResource(&pLogFile
->Lock
);
399 LogfListAddItem(pLogFile
);
402 if (!NT_SUCCESS(Status
))
404 if ((pLogFile
->hFile
!= NULL
) && (pLogFile
->hFile
!= INVALID_HANDLE_VALUE
))
405 CloseHandle(pLogFile
->hFile
);
407 if (pLogFile
->OffsetInfo
)
408 HeapFree(MyHeap
, 0, pLogFile
->OffsetInfo
);
410 if (pLogFile
->FileName
)
411 HeapFree(MyHeap
, 0, pLogFile
->FileName
);
413 if (pLogFile
->LogName
)
414 HeapFree(MyHeap
, 0, pLogFile
->LogName
);
416 HeapFree(MyHeap
, 0, pLogFile
);
428 LogfClose(PLOGFILE LogFile
,
434 if ((ForceClose
== FALSE
) &&
435 (LogFile
->Permanent
== TRUE
))
438 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
440 FlushFileBuffers(LogFile
->hFile
);
441 CloseHandle(LogFile
->hFile
);
442 LogfListRemoveItem(LogFile
);
444 RtlDeleteResource(&LogFile
->Lock
);
446 HeapFree(MyHeap
, 0, LogFile
->LogName
);
447 HeapFree(MyHeap
, 0, LogFile
->FileName
);
448 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
449 HeapFree(MyHeap
, 0, LogFile
);
454 VOID
LogfCloseAll(VOID
)
456 while (!IsListEmpty(&LogFileListHead
))
458 LogfClose(LogfListHead(), TRUE
);
461 DeleteCriticalSection(&LogFileListCs
);
464 VOID
LogfListInitialize(VOID
)
466 InitializeCriticalSection(&LogFileListCs
);
467 InitializeListHead(&LogFileListHead
);
470 PLOGFILE
LogfListHead(VOID
)
472 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
475 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
477 PLIST_ENTRY CurrentEntry
;
478 PLOGFILE Result
= NULL
;
480 EnterCriticalSection(&LogFileListCs
);
482 CurrentEntry
= LogFileListHead
.Flink
;
483 while (CurrentEntry
!= &LogFileListHead
)
485 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
489 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
495 CurrentEntry
= CurrentEntry
->Flink
;
498 LeaveCriticalSection(&LogFileListCs
);
502 /* Index starting from 1 */
503 INT
LogfListItemIndexByName(WCHAR
* Name
)
505 PLIST_ENTRY CurrentEntry
;
509 EnterCriticalSection(&LogFileListCs
);
511 CurrentEntry
= LogFileListHead
.Flink
;
512 while (CurrentEntry
!= &LogFileListHead
)
514 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
518 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
524 CurrentEntry
= CurrentEntry
->Flink
;
528 LeaveCriticalSection(&LogFileListCs
);
532 /* Index starting from 1 */
533 PLOGFILE
LogfListItemByIndex(INT Index
)
535 PLIST_ENTRY CurrentEntry
;
536 PLOGFILE Result
= NULL
;
539 EnterCriticalSection(&LogFileListCs
);
541 CurrentEntry
= LogFileListHead
.Flink
;
542 while (CurrentEntry
!= &LogFileListHead
)
546 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
550 CurrentEntry
= CurrentEntry
->Flink
;
554 LeaveCriticalSection(&LogFileListCs
);
558 INT
LogfListItemCount(VOID
)
560 PLIST_ENTRY CurrentEntry
;
563 EnterCriticalSection(&LogFileListCs
);
565 CurrentEntry
= LogFileListHead
.Flink
;
566 while (CurrentEntry
!= &LogFileListHead
)
568 CurrentEntry
= CurrentEntry
->Flink
;
572 LeaveCriticalSection(&LogFileListCs
);
576 VOID
LogfListAddItem(PLOGFILE Item
)
578 EnterCriticalSection(&LogFileListCs
);
579 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
580 LeaveCriticalSection(&LogFileListCs
);
583 VOID
LogfListRemoveItem(PLOGFILE Item
)
585 EnterCriticalSection(&LogFileListCs
);
586 RemoveEntryList(&Item
->ListEntry
);
587 LeaveCriticalSection(&LogFileListCs
);
591 ReadAnsiLogEntry(HANDLE hFile
,
593 DWORD nNumberOfBytesToRead
,
594 LPDWORD lpNumberOfBytesRead
)
599 UNICODE_STRING StringW
;
604 LPVOID lpUnicodeBuffer
= NULL
;
613 *lpNumberOfBytesRead
= 0;
615 lpUnicodeBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nNumberOfBytesToRead
);
616 if (lpUnicodeBuffer
== NULL
)
618 DPRINT1("Alloc failed!\n");
622 if (!ReadFile(hFile
, lpUnicodeBuffer
, nNumberOfBytesToRead
, &dwRead
, NULL
))
624 DPRINT1("Read failed!\n");
629 Dst
= (PEVENTLOGRECORD
)lpBuffer
;
630 Src
= (PEVENTLOGRECORD
)lpUnicodeBuffer
;
632 Dst
->TimeGenerated
= Src
->TimeGenerated
;
633 Dst
->Reserved
= Src
->Reserved
;
634 Dst
->RecordNumber
= Src
->RecordNumber
;
635 Dst
->TimeWritten
= Src
->TimeWritten
;
636 Dst
->EventID
= Src
->EventID
;
637 Dst
->EventType
= Src
->EventType
;
638 Dst
->EventCategory
= Src
->EventCategory
;
639 Dst
->NumStrings
= Src
->NumStrings
;
640 Dst
->UserSidLength
= Src
->UserSidLength
;
641 Dst
->DataLength
= Src
->DataLength
;
643 SrcPtr
= (LPWSTR
)((DWORD_PTR
)Src
+ sizeof(EVENTLOGRECORD
));
644 DstPtr
= (LPSTR
)((DWORD_PTR
)Dst
+ sizeof(EVENTLOGRECORD
));
646 /* Convert the module name */
647 RtlInitUnicodeString(&StringW
, SrcPtr
);
648 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
649 if (NT_SUCCESS(Status
))
651 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
653 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
655 RtlFreeAnsiString(&StringA
);
658 /* Convert the computer name */
659 if (NT_SUCCESS(Status
))
661 SrcPtr
= (PWSTR
)((DWORD_PTR
)SrcPtr
+ StringW
.MaximumLength
);
663 RtlInitUnicodeString(&StringW
, SrcPtr
);
664 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
665 if (NT_SUCCESS(Status
))
667 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
669 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
671 RtlFreeAnsiString(&StringA
);
675 /* Add the padding and the User SID*/
676 if (NT_SUCCESS(Status
))
678 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
) % sizeof(DWORD
));
679 RtlZeroMemory(DstPtr
, dwPadding
);
681 DstPtr
= (LPSTR
)((DWORD_PTR
)DstPtr
+ dwPadding
);
682 RtlCopyMemory(DstPtr
,
683 (PVOID
)((DWORD_PTR
)Src
+ Src
->UserSidOffset
),
686 Dst
->UserSidOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
690 /* Convert the strings */
691 if (NT_SUCCESS(Status
))
693 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->UserSidLength
);
695 SrcString
= (LPWSTR
)((DWORD_PTR
)Src
+ (DWORD
)Src
->StringOffset
);
696 DstString
= (LPSTR
)DstPtr
;
698 for (i
= 0; i
< Dst
->NumStrings
; i
++)
700 RtlInitUnicodeString(&StringW
, SrcString
);
702 RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
704 RtlCopyMemory(DstString
, StringA
.Buffer
, StringA
.MaximumLength
);
706 SrcString
= (LPWSTR
)((DWORD_PTR
)SrcString
+
707 (DWORD
)StringW
.MaximumLength
);
709 DstString
= (LPSTR
)((DWORD_PTR
)DstString
+
710 (DWORD
)StringA
.MaximumLength
);
712 RtlFreeAnsiString(&StringA
);
715 Dst
->StringOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
718 /* Copy the binary data */
719 DstPtr
= (PVOID
)DstString
;
720 Dst
->DataOffset
= (DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
;
722 RtlCopyMemory(DstPtr
, (PVOID
)((DWORD_PTR
)Src
+ Src
->DataOffset
), Src
->DataLength
);
724 /* Add the padding */
725 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->DataLength
);
726 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
-(DWORD_PTR
)Dst
) % sizeof(DWORD
));
727 RtlZeroMemory(DstPtr
, dwPadding
);
729 dwEntryLength
= (DWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
+ sizeof(DWORD
) - (DWORD_PTR
)Dst
);
731 /* Set the entry length at the end of the entry*/
732 pLength
= (PDWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
);
733 *pLength
= dwEntryLength
;
734 Dst
->Length
= dwEntryLength
;
736 *lpNumberOfBytesRead
= dwEntryLength
;
740 if (lpUnicodeBuffer
!= NULL
)
741 HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer
);
747 DWORD
LogfReadEvent(PLOGFILE LogFile
,
749 DWORD
* RecordNumber
,
756 DWORD dwOffset
, dwRead
, dwRecSize
;
757 DWORD dwBufferUsage
= 0, dwRecNum
;
759 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
760 return ERROR_INVALID_PARAMETER
;
762 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
763 return ERROR_INVALID_PARAMETER
;
765 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
766 return ERROR_INVALID_PARAMETER
;
768 if ((*RecordNumber
==0) && !(EVENTLOG_SEQUENTIAL_READ
))
770 return ERROR_INVALID_PARAMETER
;
773 dwRecNum
= *RecordNumber
;
775 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
780 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
784 RtlReleaseResource(&LogFile
->Lock
);
785 return ERROR_HANDLE_EOF
;
788 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
789 INVALID_SET_FILE_POINTER
)
791 DPRINT1("SetFilePointer() failed!\n");
795 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
797 DPRINT1("ReadFile() failed!\n");
801 if (dwRecSize
> BufSize
)
803 *BytesNeeded
= dwRecSize
;
804 RtlReleaseResource(&LogFile
->Lock
);
805 return ERROR_INSUFFICIENT_BUFFER
;
808 if (SetFilePointer(LogFile
->hFile
,
809 -((LONG
) sizeof(DWORD
)),
811 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
813 DPRINT1("SetFilePointer() failed!\n");
819 if (!ReadAnsiLogEntry(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
))
821 DPRINT1("ReadAnsiLogEntry() failed!\n");
827 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
829 DPRINT1("ReadFile() failed!\n");
834 dwBufferUsage
+= dwRead
;
836 while (dwBufferUsage
<= BufSize
)
838 if (Flags
& EVENTLOG_FORWARDS_READ
)
843 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
847 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
848 INVALID_SET_FILE_POINTER
)
850 DPRINT1("SetFilePointer() failed!\n");
854 if (!ReadFile(LogFile
->hFile
,
860 DPRINT1("ReadFile() failed!\n");
864 if (dwBufferUsage
+ dwRecSize
> BufSize
)
867 if (SetFilePointer(LogFile
->hFile
,
868 -((LONG
) sizeof(DWORD
)),
870 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
872 DPRINT1("SetFilePointer() failed!\n");
878 if (!ReadAnsiLogEntry(LogFile
->hFile
,
879 Buffer
+ dwBufferUsage
,
883 DPRINT1("ReadAnsiLogEntry() failed!\n");
889 if (!ReadFile(LogFile
->hFile
,
890 Buffer
+ dwBufferUsage
,
895 DPRINT1("ReadFile() failed!\n");
900 dwBufferUsage
+= dwRead
;
903 *BytesRead
= dwBufferUsage
;
904 * RecordNumber
= dwRecNum
;
905 RtlReleaseResource(&LogFile
->Lock
);
906 return ERROR_SUCCESS
;
909 DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
910 RtlReleaseResource(&LogFile
->Lock
);
911 return GetLastError();
914 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
920 PEVENTLOGRECORD RecBuf
;
921 LARGE_INTEGER logFileSize
;
929 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
931 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
933 if (!GetFileSizeEx(LogFile
->hFile
, &logFileSize
))
935 RtlReleaseResource(&LogFile
->Lock
);
939 /* If the size of the file is over MaxSize */
940 if ((logFileSize
.QuadPart
+ BufSize
)> LogFile
->Header
.MaxSize
)
942 ULONG OverWriteLength
= 0;
943 WriteOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
944 RecBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(EVENTLOGRECORD
));
945 /* Determine how many records need to be overwritten */
948 DPRINT("EventLogFile has reached maximume size\n");
952 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
953 HeapFree(GetProcessHeap(), 0, RecBuf
);
954 RtlReleaseResource(&LogFile
->Lock
);
958 /* Get the oldest record data */
959 RecOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
961 if (SetFilePointer(LogFile
->hFile
,
964 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
966 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
967 HeapFree(GetProcessHeap(), 0, RecBuf
);
968 RtlReleaseResource(&LogFile
->Lock
);
972 if (!ReadFile(LogFile
->hFile
, RecBuf
, sizeof(EVENTLOGRECORD
), &dwRead
, NULL
))
974 DPRINT1("ReadFile() failed!\n");
975 HeapFree(GetProcessHeap(), 0, RecBuf
);
976 RtlReleaseResource(&LogFile
->Lock
);
980 if (RecBuf
->Reserved
!= LOGFILE_SIGNATURE
)
982 DPRINT1("LogFile corrupt!\n");
983 HeapFree(GetProcessHeap(), 0, RecBuf
);
984 RtlReleaseResource(&LogFile
->Lock
);
988 LogfDeleteOffsetInformation(LogFile
,LogFile
->Header
.OldestRecordNumber
);
990 LogFile
->Header
.OldestRecordNumber
++;
992 OverWriteLength
+= RecBuf
->Length
;
993 /* Check the size of the record as the record adding may be larger */
994 if (OverWriteLength
>= BufSize
)
996 DPRINT("Record will fit. Length %d, BufSize %d\n", OverWriteLength
, BufSize
);
997 LogFile
->Header
.StartOffset
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
1001 HeapFree(GetProcessHeap(), 0, RecBuf
);
1004 WriteOffSet
= LogFile
->Header
.EndOffset
;
1006 if (SetFilePointer(LogFile
->hFile
,
1009 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1011 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1012 RtlReleaseResource(&LogFile
->Lock
);
1016 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
1018 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1019 RtlReleaseResource(&LogFile
->Lock
);
1023 if (!LogfAddOffsetInformation(LogFile
,
1024 LogFile
->Header
.CurrentRecordNumber
,
1027 RtlReleaseResource(&LogFile
->Lock
);
1031 LogFile
->Header
.CurrentRecordNumber
++;
1033 if (WriteOffSet
== LogFile
->Header
.EndOffset
)
1035 LogFile
->Header
.EndOffset
+= dwWritten
;
1037 if (SetFilePointer(LogFile
->hFile
,
1038 LogFile
->Header
.EndOffset
,
1040 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1042 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1043 RtlReleaseResource(&LogFile
->Lock
);
1047 EofRec
.Ones
= 0x11111111;
1048 EofRec
.Twos
= 0x22222222;
1049 EofRec
.Threes
= 0x33333333;
1050 EofRec
.Fours
= 0x44444444;
1051 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1052 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1053 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1054 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1055 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
1056 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
1058 if (!WriteFile(LogFile
->hFile
,
1060 sizeof(EVENTLOGEOF
),
1064 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1065 RtlReleaseResource(&LogFile
->Lock
);
1069 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
1070 INVALID_SET_FILE_POINTER
)
1072 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1073 RtlReleaseResource(&LogFile
->Lock
);
1077 if (!WriteFile(LogFile
->hFile
,
1079 sizeof(EVENTLOGHEADER
),
1083 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
1084 RtlReleaseResource(&LogFile
->Lock
);
1088 if (!FlushFileBuffers(LogFile
->hFile
))
1090 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
1091 RtlReleaseResource(&LogFile
->Lock
);
1095 RtlReleaseResource(&LogFile
->Lock
);
1101 LogfClearFile(PLOGFILE LogFile
,
1102 PUNICODE_STRING BackupFileName
)
1106 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
1108 if (BackupFileName
->Length
> 0)
1110 /* Write a backup file */
1111 Status
= LogfBackupFile(LogFile
,
1113 if (!NT_SUCCESS(Status
))
1115 DPRINT1("LogfBackupFile failed (Status: 0x%08lx)\n", Status
);
1120 Status
= LogfInitializeNew(LogFile
);
1121 if (!NT_SUCCESS(Status
))
1123 DPRINT1("LogfInitializeNew failed (Status: 0x%08lx)\n", Status
);
1126 RtlReleaseResource(&LogFile
->Lock
);
1133 LogfBackupFile(PLOGFILE LogFile
,
1134 PUNICODE_STRING BackupFileName
)
1136 OBJECT_ATTRIBUTES ObjectAttributes
;
1137 IO_STATUS_BLOCK IoStatusBlock
;
1138 EVENTLOGHEADER Header
;
1140 HANDLE FileHandle
= NULL
;
1142 LARGE_INTEGER FileOffset
;
1144 PUCHAR Buffer
= NULL
;
1146 DWORD dwOffset
, dwRead
, dwRecSize
;
1148 DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile
, BackupFileName
);
1150 /* Lock the log file shared */
1151 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
1153 InitializeObjectAttributes(&ObjectAttributes
,
1155 OBJ_CASE_INSENSITIVE
,
1159 Status
= NtCreateFile(&FileHandle
,
1160 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1164 FILE_ATTRIBUTE_NORMAL
,
1167 FILE_WRITE_THROUGH
| FILE_SYNCHRONOUS_IO_NONALERT
,
1170 if (!NT_SUCCESS(Status
))
1172 DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName
, Status
);
1176 /* Initialize the (dirty) log file header */
1177 Header
.HeaderSize
= sizeof(EVENTLOGHEADER
);
1178 Header
.Signature
= LOGFILE_SIGNATURE
;
1179 Header
.MajorVersion
= MAJORVER
;
1180 Header
.MinorVersion
= MINORVER
;
1181 Header
.StartOffset
= sizeof(EVENTLOGHEADER
);
1182 Header
.EndOffset
= sizeof(EVENTLOGHEADER
);
1183 Header
.CurrentRecordNumber
= 1;
1184 Header
.OldestRecordNumber
= 1;
1186 Header
.Flags
= ELF_LOGFILE_HEADER_DIRTY
;
1187 Header
.Retention
= LogFile
->Header
.Retention
;
1188 Header
.EndHeaderSize
= sizeof(EVENTLOGHEADER
);
1190 /* Write the (dirty) log file header */
1191 Status
= NtWriteFile(FileHandle
,
1197 sizeof(EVENTLOGHEADER
),
1200 if (!NT_SUCCESS(Status
))
1202 DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status
);
1206 for (i
= LogFile
->Header
.OldestRecordNumber
; i
< LogFile
->Header
.CurrentRecordNumber
; i
++)
1208 dwOffset
= LogfOffsetByNumber(LogFile
, i
);
1212 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1214 DPRINT1("SetFilePointer() failed!\n");
1218 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
1220 DPRINT1("ReadFile() failed!\n");
1224 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1226 DPRINT1("SetFilePointer() failed!\n");
1230 Buffer
= HeapAlloc(MyHeap
, 0, dwRecSize
);
1233 DPRINT1("HeapAlloc() failed!\n");
1237 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
1239 DPRINT1("ReadFile() failed!\n");
1243 /* Write the event record */
1244 Status
= NtWriteFile(FileHandle
,
1253 if (!NT_SUCCESS(Status
))
1255 DPRINT1("NtWriteFile() failed! (Status: 0x%08lx)\n", Status
);
1259 /* Update the header information */
1260 Header
.EndOffset
+= dwRecSize
;
1262 /* Free the buffer */
1263 HeapFree(MyHeap
, 0, Buffer
);
1267 /* Initialize the EOF record */
1268 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1269 EofRec
.Ones
= 0x11111111;
1270 EofRec
.Twos
= 0x22222222;
1271 EofRec
.Threes
= 0x33333333;
1272 EofRec
.Fours
= 0x44444444;
1273 EofRec
.BeginRecord
= sizeof(EVENTLOGHEADER
);
1274 EofRec
.EndRecord
= Header
.EndOffset
;
1275 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1276 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1277 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1279 /* Write the EOF record */
1280 Status
= NtWriteFile(FileHandle
,
1286 sizeof(EVENTLOGEOF
),
1289 if (!NT_SUCCESS(Status
))
1291 DPRINT1("NtWriteFile() failed!\n");
1295 /* Update the header information */
1296 Header
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1297 Header
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1298 Header
.MaxSize
= Header
.EndOffset
+ sizeof(EVENTLOGEOF
);
1301 /* Write the (clean) log file header */
1302 FileOffset
.QuadPart
= 0;
1303 Status
= NtWriteFile(FileHandle
,
1309 sizeof(EVENTLOGHEADER
),
1312 if (!NT_SUCCESS(Status
))
1314 DPRINT1("NtWriteFile() failed! (Status: 0x%08lx)\n", Status
);
1318 /* Free the buffer */
1320 HeapFree(MyHeap
, 0, Buffer
);
1322 /* Close the backup file */
1323 if (FileHandle
!= NULL
)
1324 NtClose(FileHandle
);
1326 /* Unlock the log file */
1327 RtlReleaseResource(&LogFile
->Lock
);
1333 /* Returns 0 if nothing found. */
1334 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
1338 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
1340 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
1341 return LogFile
->OffsetInfo
[i
].EventOffset
;
1346 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
1348 return LogFile
->Header
.OldestRecordNumber
;
1351 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
1353 return LogFile
->Header
.CurrentRecordNumber
;
1356 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
1360 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
1365 for (i
= 0; i
< LogFile
->OffsetInfoNext
- 1; i
++)
1367 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+ 1].EventNumber
;
1368 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+ 1].EventOffset
;
1370 LogFile
->OffsetInfoNext
--;
1374 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
1376 LPVOID NewOffsetInfo
;
1378 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
1380 NewOffsetInfo
= HeapReAlloc(MyHeap
,
1382 LogFile
->OffsetInfo
,
1383 (LogFile
->OffsetInfoSize
+ 64) *
1384 sizeof(EVENT_OFFSET_INFO
));
1388 DPRINT1("Can't reallocate heap.\n");
1392 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
1393 LogFile
->OffsetInfoSize
+= 64;
1396 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
1397 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
1398 LogFile
->OffsetInfoNext
++;
1403 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
1404 DWORD dwRecordNumber
,
1409 LPCWSTR ComputerName
,
1418 PEVENTLOGRECORD pRec
;
1425 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
1426 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
1428 if (dwRecSize
% 4 != 0)
1429 dwRecSize
+= 4 - (dwRecSize
% 4);
1431 dwRecSize
+= dwSidLength
;
1433 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1435 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1436 str
+= lstrlenW(str
) + 1;
1439 dwRecSize
+= dwDataSize
;
1440 if (dwRecSize
% 4 != 0)
1441 dwRecSize
+= 4 - (dwRecSize
% 4);
1445 Buffer
= HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
1449 DPRINT1("Can't allocate heap!\n");
1453 pRec
= (PEVENTLOGRECORD
) Buffer
;
1454 pRec
->Length
= dwRecSize
;
1455 pRec
->Reserved
= LOGFILE_SIGNATURE
;
1456 pRec
->RecordNumber
= dwRecordNumber
;
1458 GetSystemTime(&SysTime
);
1459 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
1460 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
1462 pRec
->EventID
= dwEventId
;
1463 pRec
->EventType
= wType
;
1464 pRec
->EventCategory
= wCategory
;
1466 pos
= sizeof(EVENTLOGRECORD
);
1468 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
1469 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
1470 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
1471 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
1473 pRec
->UserSidOffset
= pos
;
1476 pos
+= 4 - (pos
% 4);
1480 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1481 pRec
->UserSidLength
= dwSidLength
;
1482 pRec
->UserSidOffset
= pos
;
1486 pRec
->StringOffset
= pos
;
1487 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1489 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1490 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1491 str
+= lstrlenW(str
) + 1;
1493 pRec
->NumStrings
= wNumStrings
;
1495 pRec
->DataOffset
= pos
;
1498 pRec
->DataLength
= dwDataSize
;
1499 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1504 pos
+= 4 - (pos
% 4);
1506 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1508 *lpRecSize
= dwRecSize
;
1514 LogfReportEvent(WORD wType
,
1522 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1523 DWORD dwComputerNameLength
= MAX_COMPUTERNAME_LENGTH
+ 1;
1524 PEVENTSOURCE pEventSource
= NULL
;
1530 if (!GetComputerNameW(szComputerName
, &dwComputerNameLength
))
1532 szComputerName
[0] = 0;
1535 pEventSource
= GetEventSourceByName(L
"EventLog");
1536 if (pEventSource
== NULL
)
1541 lastRec
= LogfGetCurrentRecord(pEventSource
->LogFile
);
1543 logBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
1548 pEventSource
->szName
,
1549 (LPCWSTR
)szComputerName
,
1557 dwError
= LogfWriteData(pEventSource
->LogFile
, recSize
, logBuffer
);
1560 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource
->LogFile
->FileName
);
1563 LogfFreeRecord(logBuffer
);