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