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 ****************************************************************/
21 BOOL
LogfInitializeNew(PLOGFILE LogFile
)
26 ZeroMemory(&LogFile
->Header
, sizeof(EVENTLOGHEADER
));
27 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
28 SetEndOfFile(LogFile
->hFile
);
30 LogFile
->Header
.HeaderSize
= sizeof(EVENTLOGHEADER
);
31 LogFile
->Header
.EndHeaderSize
= sizeof(EVENTLOGHEADER
);
32 LogFile
->Header
.StartOffset
= sizeof(EVENTLOGHEADER
);
33 LogFile
->Header
.EndOffset
= sizeof(EVENTLOGHEADER
);
34 LogFile
->Header
.MajorVersion
= MAJORVER
;
35 LogFile
->Header
.MinorVersion
= MINORVER
;
36 LogFile
->Header
.CurrentRecordNumber
= 1;
37 LogFile
->Header
.OldestRecordNumber
= 1;
38 /* FIXME: Read MaxSize from registry for this LogFile.
39 But for now limit EventLog size to just under 5K. */
40 LogFile
->Header
.MaxSize
= 5000;
41 LogFile
->Header
.Signature
= LOGFILE_SIGNATURE
;
42 if (!WriteFile(LogFile
->hFile
,
44 sizeof(EVENTLOGHEADER
),
48 DPRINT1("WriteFile failed:%d!\n", GetLastError());
52 EofRec
.Ones
= 0x11111111;
53 EofRec
.Twos
= 0x22222222;
54 EofRec
.Threes
= 0x33333333;
55 EofRec
.Fours
= 0x44444444;
56 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
57 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
58 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
59 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
60 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
61 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
63 if (!WriteFile(LogFile
->hFile
,
69 DPRINT1("WriteFile failed:%d!\n", GetLastError());
73 if (!FlushFileBuffers(LogFile
->hFile
))
75 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
82 BOOL
LogfInitializeExisting(PLOGFILE LogFile
)
85 DWORD dwRecordsNumber
= 0;
86 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
88 PEVENTLOGRECORD RecBuf
;
89 BOOL OvewrWrittenRecords
= FALSE
;
91 DPRINT("Initializing LogFile %S\n",LogFile
->LogName
);
93 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
94 INVALID_SET_FILE_POINTER
)
96 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
100 if (!ReadFile(LogFile
->hFile
,
102 sizeof(EVENTLOGHEADER
),
106 DPRINT1("ReadFile failed! %d\n", GetLastError());
110 if (dwRead
!= sizeof(EVENTLOGHEADER
))
112 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
113 return LogfInitializeNew(LogFile
);
116 if (LogFile
->Header
.HeaderSize
!= sizeof(EVENTLOGHEADER
) ||
117 LogFile
->Header
.EndHeaderSize
!= sizeof(EVENTLOGHEADER
))
119 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
120 return LogfInitializeNew(LogFile
);
123 if (LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
125 DPRINT("EventLog: Invalid signature %x in %S.\n",
126 LogFile
->Header
.Signature
, LogFile
->FileName
);
127 return LogfInitializeNew(LogFile
);
130 if (LogFile
->Header
.EndOffset
> GetFileSize(LogFile
->hFile
, NULL
) + 1)
132 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
133 LogFile
->Header
.EndOffset
, LogFile
->FileName
);
134 return LogfInitializeNew(LogFile
);
137 /* Set the read location to the oldest record */
138 dwFilePointer
= SetFilePointer(LogFile
->hFile
, LogFile
->Header
.StartOffset
, NULL
, FILE_BEGIN
);
139 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
141 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
147 dwFilePointer
= SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
);
149 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
151 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
155 /* If the EVENTLOGEOF info has been reached and the oldest record was not immediately after the Header */
156 if ((dwFilePointer
== LogFile
->Header
.EndOffset
) && (LogFile
->Header
.StartOffset
!= sizeof(EVENTLOGHEADER
)))
158 OvewrWrittenRecords
= TRUE
;
159 /* The file has records that overwrote old ones so read them */
160 dwFilePointer
= SetFilePointer(LogFile
->hFile
, sizeof(EVENTLOGHEADER
), NULL
, FILE_BEGIN
);
163 if (!ReadFile(LogFile
->hFile
,
169 DPRINT1("ReadFile failed! %d\n", GetLastError());
173 if (dwRead
!= sizeof(dwRecSize
))
176 if (!ReadFile(LogFile
->hFile
,
182 DPRINT1("ReadFile() failed! %d\n", GetLastError());
186 if (dwRead
!= sizeof(dwRecSize
))
189 if (dwRecSign
!= LOGFILE_SIGNATURE
||
190 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
) + 1 ||
191 dwRecSize
< sizeof(EVENTLOGRECORD
))
196 if (SetFilePointer(LogFile
->hFile
,
197 -((LONG
) sizeof(DWORD
) * 2),
199 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
201 DPRINT1("SetFilePointer() failed! %d", GetLastError());
205 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
209 DPRINT1("Can't allocate heap!\n");
213 if (!ReadFile(LogFile
->hFile
, RecBuf
, dwRecSize
, &dwRead
, NULL
))
215 DPRINT1("ReadFile() failed! %d\n", GetLastError());
216 HeapFree(MyHeap
, 0, RecBuf
);
220 if (dwRead
!= dwRecSize
)
222 HeapFree(MyHeap
, 0, RecBuf
);
226 /* if OvewrWrittenRecords is TRUE and this record has already been read */
227 if ((OvewrWrittenRecords
== TRUE
) && (RecBuf
->RecordNumber
== LogFile
->Header
.OldestRecordNumber
))
229 HeapFree(MyHeap
, 0, RecBuf
);
233 pdwRecSize2
= (PDWORD
) (((PBYTE
) RecBuf
) + dwRecSize
- 4);
235 if (*pdwRecSize2
!= dwRecSize
)
237 DPRINT1("Invalid RecordSizeEnd of record %d (%x) in %S\n",
238 dwRecordsNumber
, *pdwRecSize2
, LogFile
->LogName
);
239 HeapFree(MyHeap
, 0, RecBuf
);
245 if (!LogfAddOffsetInformation(LogFile
,
246 RecBuf
->RecordNumber
,
249 DPRINT1("LogfAddOffsetInformation() failed!\n");
250 HeapFree(MyHeap
, 0, RecBuf
);
254 HeapFree(MyHeap
, 0, RecBuf
);
257 LogFile
->Header
.CurrentRecordNumber
= dwRecordsNumber
+ LogFile
->Header
.OldestRecordNumber
;
258 if (LogFile
->Header
.CurrentRecordNumber
== 0)
259 LogFile
->Header
.CurrentRecordNumber
= 1;
261 /* FIXME: Read MaxSize from registry for this LogFile.
262 But for now limit EventLog size to just under 5K. */
263 LogFile
->Header
.MaxSize
= 5000;
265 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
266 INVALID_SET_FILE_POINTER
)
268 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
272 if (!WriteFile(LogFile
->hFile
,
274 sizeof(EVENTLOGHEADER
),
278 DPRINT1("WriteFile failed! %d\n", GetLastError());
282 if (!FlushFileBuffers(LogFile
->hFile
))
284 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
293 LogfCreate(PLOGFILE
*LogFile
,
295 PUNICODE_STRING FileName
)
297 OBJECT_ATTRIBUTES ObjectAttributes
;
298 IO_STATUS_BLOCK IoStatusBlock
;
300 BOOL bResult
, bCreateNew
= FALSE
;
301 NTSTATUS Status
= STATUS_SUCCESS
;
303 pLogFile
= (LOGFILE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(LOGFILE
));
306 DPRINT1("Can't allocate heap!\n");
307 return STATUS_NO_MEMORY
;
310 InitializeObjectAttributes(&ObjectAttributes
,
312 OBJ_CASE_INSENSITIVE
,
316 Status
= NtCreateFile(&pLogFile
->hFile
,
317 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
321 FILE_ATTRIBUTE_NORMAL
,
324 FILE_SYNCHRONOUS_IO_NONALERT
,
327 if (!NT_SUCCESS(Status
))
329 DPRINT1("Can't create file %wZ (Status: 0x%08lx)\n", FileName
, Status
);
333 bCreateNew
= (IoStatusBlock
.Information
== FILE_CREATED
) ? TRUE
: FALSE
;
336 (WCHAR
*) HeapAlloc(MyHeap
,
338 (lstrlenW(LogName
) + 1) * sizeof(WCHAR
));
339 if (pLogFile
->LogName
== NULL
)
341 DPRINT1("Can't allocate heap\n");
342 Status
= STATUS_NO_MEMORY
;
346 lstrcpyW(pLogFile
->LogName
, LogName
);
349 (WCHAR
*) HeapAlloc(MyHeap
,
351 (lstrlenW(FileName
->Buffer
) + 1) * sizeof(WCHAR
));
352 if (pLogFile
->FileName
== NULL
)
354 DPRINT1("Can't allocate heap\n");
355 Status
= STATUS_NO_MEMORY
;
359 lstrcpyW(pLogFile
->FileName
, FileName
->Buffer
);
361 pLogFile
->OffsetInfo
=
362 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
364 sizeof(EVENT_OFFSET_INFO
) * 64);
365 if (pLogFile
->OffsetInfo
== NULL
)
367 DPRINT1("Can't allocate heap\n");
368 Status
= STATUS_NO_MEMORY
;
372 pLogFile
->OffsetInfoSize
= 64;
375 bResult
= LogfInitializeNew(pLogFile
);
377 bResult
= LogfInitializeExisting(pLogFile
);
381 Status
= STATUS_UNSUCCESSFUL
;
385 RtlInitializeResource(&pLogFile
->Lock
);
387 LogfListAddItem(pLogFile
);
390 if (!NT_SUCCESS(Status
))
392 if ((pLogFile
->hFile
!= NULL
) && (pLogFile
->hFile
!= INVALID_HANDLE_VALUE
))
393 CloseHandle(pLogFile
->hFile
);
395 if (pLogFile
->OffsetInfo
)
396 HeapFree(MyHeap
, 0, pLogFile
->OffsetInfo
);
398 if (pLogFile
->FileName
)
399 HeapFree(MyHeap
, 0, pLogFile
->FileName
);
401 if (pLogFile
->LogName
)
402 HeapFree(MyHeap
, 0, pLogFile
->LogName
);
404 HeapFree(MyHeap
, 0, pLogFile
);
414 VOID
LogfClose(PLOGFILE LogFile
)
419 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
421 FlushFileBuffers(LogFile
->hFile
);
422 CloseHandle(LogFile
->hFile
);
423 LogfListRemoveItem(LogFile
);
425 RtlDeleteResource(&LogFile
->Lock
);
427 HeapFree(MyHeap
, 0, LogFile
->LogName
);
428 HeapFree(MyHeap
, 0, LogFile
->FileName
);
429 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
430 HeapFree(MyHeap
, 0, LogFile
);
435 VOID
LogfCloseAll(VOID
)
437 while (!IsListEmpty(&LogFileListHead
))
439 LogfClose(LogfListHead());
442 DeleteCriticalSection(&LogFileListCs
);
445 VOID
LogfListInitialize(VOID
)
447 InitializeCriticalSection(&LogFileListCs
);
448 InitializeListHead(&LogFileListHead
);
451 PLOGFILE
LogfListHead(VOID
)
453 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
456 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
458 PLIST_ENTRY CurrentEntry
;
459 PLOGFILE Result
= NULL
;
461 EnterCriticalSection(&LogFileListCs
);
463 CurrentEntry
= LogFileListHead
.Flink
;
464 while (CurrentEntry
!= &LogFileListHead
)
466 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
470 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
476 CurrentEntry
= CurrentEntry
->Flink
;
479 LeaveCriticalSection(&LogFileListCs
);
483 /* Index starting from 1 */
484 INT
LogfListItemIndexByName(WCHAR
* Name
)
486 PLIST_ENTRY CurrentEntry
;
490 EnterCriticalSection(&LogFileListCs
);
492 CurrentEntry
= LogFileListHead
.Flink
;
493 while (CurrentEntry
!= &LogFileListHead
)
495 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
499 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
505 CurrentEntry
= CurrentEntry
->Flink
;
509 LeaveCriticalSection(&LogFileListCs
);
513 /* Index starting from 1 */
514 PLOGFILE
LogfListItemByIndex(INT Index
)
516 PLIST_ENTRY CurrentEntry
;
517 PLOGFILE Result
= NULL
;
520 EnterCriticalSection(&LogFileListCs
);
522 CurrentEntry
= LogFileListHead
.Flink
;
523 while (CurrentEntry
!= &LogFileListHead
)
527 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
531 CurrentEntry
= CurrentEntry
->Flink
;
535 LeaveCriticalSection(&LogFileListCs
);
539 INT
LogfListItemCount(VOID
)
541 PLIST_ENTRY CurrentEntry
;
544 EnterCriticalSection(&LogFileListCs
);
546 CurrentEntry
= LogFileListHead
.Flink
;
547 while (CurrentEntry
!= &LogFileListHead
)
549 CurrentEntry
= CurrentEntry
->Flink
;
553 LeaveCriticalSection(&LogFileListCs
);
557 VOID
LogfListAddItem(PLOGFILE Item
)
559 EnterCriticalSection(&LogFileListCs
);
560 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
561 LeaveCriticalSection(&LogFileListCs
);
564 VOID
LogfListRemoveItem(PLOGFILE Item
)
566 EnterCriticalSection(&LogFileListCs
);
567 RemoveEntryList(&Item
->ListEntry
);
568 LeaveCriticalSection(&LogFileListCs
);
572 ReadAnsiLogEntry(HANDLE hFile
,
574 DWORD nNumberOfBytesToRead
,
575 LPDWORD lpNumberOfBytesRead
)
580 UNICODE_STRING StringW
;
585 LPVOID lpUnicodeBuffer
= NULL
;
594 *lpNumberOfBytesRead
= 0;
596 lpUnicodeBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nNumberOfBytesToRead
);
597 if (lpUnicodeBuffer
== NULL
)
599 DPRINT1("Alloc failed!\n");
603 if (!ReadFile(hFile
, lpUnicodeBuffer
, nNumberOfBytesToRead
, &dwRead
, NULL
))
605 DPRINT1("Read failed!\n");
610 Dst
= (PEVENTLOGRECORD
)lpBuffer
;
611 Src
= (PEVENTLOGRECORD
)lpUnicodeBuffer
;
613 Dst
->TimeGenerated
= Src
->TimeGenerated
;
614 Dst
->Reserved
= Src
->Reserved
;
615 Dst
->RecordNumber
= Src
->RecordNumber
;
616 Dst
->TimeWritten
= Src
->TimeWritten
;
617 Dst
->EventID
= Src
->EventID
;
618 Dst
->EventType
= Src
->EventType
;
619 Dst
->EventCategory
= Src
->EventCategory
;
620 Dst
->NumStrings
= Src
->NumStrings
;
621 Dst
->UserSidLength
= Src
->UserSidLength
;
622 Dst
->DataLength
= Src
->DataLength
;
624 SrcPtr
= (LPWSTR
)((DWORD_PTR
)Src
+ sizeof(EVENTLOGRECORD
));
625 DstPtr
= (LPSTR
)((DWORD_PTR
)Dst
+ sizeof(EVENTLOGRECORD
));
627 /* Convert the module name */
628 RtlInitUnicodeString(&StringW
, SrcPtr
);
629 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
630 if (NT_SUCCESS(Status
))
632 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
634 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
636 RtlFreeAnsiString(&StringA
);
639 /* Convert the computer name */
640 if (NT_SUCCESS(Status
))
642 SrcPtr
= (PWSTR
)((DWORD_PTR
)SrcPtr
+ StringW
.MaximumLength
);
644 RtlInitUnicodeString(&StringW
, SrcPtr
);
645 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
646 if (NT_SUCCESS(Status
))
648 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
650 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
652 RtlFreeAnsiString(&StringA
);
656 /* Add the padding and the User SID*/
657 if (NT_SUCCESS(Status
))
659 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
) % sizeof(DWORD
));
660 RtlZeroMemory(DstPtr
, dwPadding
);
662 DstPtr
= (LPSTR
)((DWORD_PTR
)DstPtr
+ dwPadding
);
663 RtlCopyMemory(DstPtr
,
664 (PVOID
)((DWORD_PTR
)Src
+ Src
->UserSidOffset
),
667 Dst
->UserSidOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
671 /* Convert the strings */
672 if (NT_SUCCESS(Status
))
674 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->UserSidLength
);
676 SrcString
= (LPWSTR
)((DWORD_PTR
)Src
+ (DWORD
)Src
->StringOffset
);
677 DstString
= (LPSTR
)DstPtr
;
679 for (i
= 0; i
< Dst
->NumStrings
; i
++)
681 RtlInitUnicodeString(&StringW
, SrcString
);
683 RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
685 RtlCopyMemory(DstString
, StringA
.Buffer
, StringA
.MaximumLength
);
687 SrcString
= (LPWSTR
)((DWORD_PTR
)SrcString
+
688 (DWORD
)StringW
.MaximumLength
);
690 DstString
= (LPSTR
)((DWORD_PTR
)DstString
+
691 (DWORD
)StringA
.MaximumLength
);
693 RtlFreeAnsiString(&StringA
);
696 Dst
->StringOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
699 /* Copy the binary data */
700 DstPtr
= (PVOID
)DstString
;
701 Dst
->DataOffset
= (DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
;
703 RtlCopyMemory(DstPtr
, (PVOID
)((DWORD_PTR
)Src
+ Src
->DataOffset
), Src
->DataLength
);
705 /* Add the padding */
706 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->DataLength
);
707 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
-(DWORD_PTR
)Dst
) % sizeof(DWORD
));
708 RtlZeroMemory(DstPtr
, dwPadding
);
710 dwEntryLength
= (DWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
+ sizeof(DWORD
) - (DWORD_PTR
)Dst
);
712 /* Set the entry length at the end of the entry*/
713 pLength
= (PDWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
);
714 *pLength
= dwEntryLength
;
715 Dst
->Length
= dwEntryLength
;
717 *lpNumberOfBytesRead
= dwEntryLength
;
721 if (lpUnicodeBuffer
!= NULL
)
722 HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer
);
728 DWORD
LogfReadEvent(PLOGFILE LogFile
,
730 DWORD
* RecordNumber
,
737 DWORD dwOffset
, dwRead
, dwRecSize
;
738 DWORD dwBufferUsage
= 0, dwRecNum
;
740 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
741 return ERROR_INVALID_PARAMETER
;
743 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
744 return ERROR_INVALID_PARAMETER
;
746 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
747 return ERROR_INVALID_PARAMETER
;
749 if ((*RecordNumber
==0) && !(EVENTLOG_SEQUENTIAL_READ
))
751 return ERROR_INVALID_PARAMETER
;
754 dwRecNum
= *RecordNumber
;
756 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
761 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
765 RtlReleaseResource(&LogFile
->Lock
);
766 return ERROR_HANDLE_EOF
;
769 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
770 INVALID_SET_FILE_POINTER
)
772 DPRINT1("SetFilePointer() failed!\n");
776 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
778 DPRINT1("ReadFile() failed!\n");
782 if (dwRecSize
> BufSize
)
784 *BytesNeeded
= dwRecSize
;
785 RtlReleaseResource(&LogFile
->Lock
);
786 return ERROR_INSUFFICIENT_BUFFER
;
789 if (SetFilePointer(LogFile
->hFile
,
790 -((LONG
) sizeof(DWORD
)),
792 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
794 DPRINT1("SetFilePointer() failed!\n");
800 if (!ReadAnsiLogEntry(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
))
802 DPRINT1("ReadAnsiLogEntry() failed!\n");
808 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
810 DPRINT1("ReadFile() failed!\n");
815 dwBufferUsage
+= dwRead
;
817 while (dwBufferUsage
<= BufSize
)
819 if (Flags
& EVENTLOG_FORWARDS_READ
)
824 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
828 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
829 INVALID_SET_FILE_POINTER
)
831 DPRINT1("SetFilePointer() failed!\n");
835 if (!ReadFile(LogFile
->hFile
,
841 DPRINT1("ReadFile() failed!\n");
845 if (dwBufferUsage
+ dwRecSize
> BufSize
)
848 if (SetFilePointer(LogFile
->hFile
,
849 -((LONG
) sizeof(DWORD
)),
851 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
853 DPRINT1("SetFilePointer() failed!\n");
859 if (!ReadAnsiLogEntry(LogFile
->hFile
,
860 Buffer
+ dwBufferUsage
,
864 DPRINT1("ReadAnsiLogEntry() failed!\n");
870 if (!ReadFile(LogFile
->hFile
,
871 Buffer
+ dwBufferUsage
,
876 DPRINT1("ReadFile() failed!\n");
881 dwBufferUsage
+= dwRead
;
884 *BytesRead
= dwBufferUsage
;
885 * RecordNumber
= dwRecNum
;
886 RtlReleaseResource(&LogFile
->Lock
);
887 return ERROR_SUCCESS
;
890 DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
891 RtlReleaseResource(&LogFile
->Lock
);
892 return GetLastError();
895 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
901 PEVENTLOGRECORD RecBuf
;
902 LARGE_INTEGER logFileSize
;
910 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
912 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
914 if (!GetFileSizeEx(LogFile
->hFile
, &logFileSize
))
916 RtlReleaseResource(&LogFile
->Lock
);
920 /* If the size of the file is over MaxSize */
921 if ((logFileSize
.QuadPart
+ BufSize
)> LogFile
->Header
.MaxSize
)
923 ULONG OverWriteLength
= 0;
924 WriteOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
925 RecBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(EVENTLOGRECORD
));
926 /* Determine how many records need to be overwritten */
929 DPRINT("EventLogFile has reached maximume size\n");
933 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
934 HeapFree(GetProcessHeap(), 0, RecBuf
);
935 RtlReleaseResource(&LogFile
->Lock
);
939 /* Get the oldest record data */
940 RecOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
942 if (SetFilePointer(LogFile
->hFile
,
945 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
947 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
948 HeapFree(GetProcessHeap(), 0, RecBuf
);
949 RtlReleaseResource(&LogFile
->Lock
);
953 if (!ReadFile(LogFile
->hFile
, RecBuf
, sizeof(EVENTLOGRECORD
), &dwRead
, NULL
))
955 DPRINT1("ReadFile() failed!\n");
956 HeapFree(GetProcessHeap(), 0, RecBuf
);
957 RtlReleaseResource(&LogFile
->Lock
);
961 if (RecBuf
->Reserved
!= LOGFILE_SIGNATURE
)
963 DPRINT1("LogFile corrupt!\n");
964 RtlReleaseResource(&LogFile
->Lock
);
968 LogfDeleteOffsetInformation(LogFile
,LogFile
->Header
.OldestRecordNumber
);
970 LogFile
->Header
.OldestRecordNumber
++;
972 OverWriteLength
+= RecBuf
->Length
;
973 /* Check the size of the record as the record adding may be larger */
974 if (OverWriteLength
>= BufSize
)
976 DPRINT("Record will fit. Lenght %d, BufSize %d\n", OverWriteLength
, BufSize
);
977 LogFile
->Header
.StartOffset
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
981 HeapFree(GetProcessHeap(), 0, RecBuf
);
984 WriteOffSet
= LogFile
->Header
.EndOffset
;
986 if (SetFilePointer(LogFile
->hFile
,
989 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
991 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
992 RtlReleaseResource(&LogFile
->Lock
);
996 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
998 DPRINT1("WriteFile() failed! %d\n", GetLastError());
999 RtlReleaseResource(&LogFile
->Lock
);
1003 if (!LogfAddOffsetInformation(LogFile
,
1004 LogFile
->Header
.CurrentRecordNumber
,
1007 RtlReleaseResource(&LogFile
->Lock
);
1011 LogFile
->Header
.CurrentRecordNumber
++;
1013 if (WriteOffSet
== LogFile
->Header
.EndOffset
)
1015 LogFile
->Header
.EndOffset
+= dwWritten
;
1017 if (SetFilePointer(LogFile
->hFile
,
1018 LogFile
->Header
.EndOffset
,
1020 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1022 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1023 RtlReleaseResource(&LogFile
->Lock
);
1027 EofRec
.Ones
= 0x11111111;
1028 EofRec
.Twos
= 0x22222222;
1029 EofRec
.Threes
= 0x33333333;
1030 EofRec
.Fours
= 0x44444444;
1031 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1032 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1033 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1034 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1035 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
1036 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
1038 if (!WriteFile(LogFile
->hFile
,
1040 sizeof(EVENTLOGEOF
),
1044 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1045 RtlReleaseResource(&LogFile
->Lock
);
1049 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
1050 INVALID_SET_FILE_POINTER
)
1052 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1053 RtlReleaseResource(&LogFile
->Lock
);
1057 if (!WriteFile(LogFile
->hFile
,
1059 sizeof(EVENTLOGHEADER
),
1063 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
1064 RtlReleaseResource(&LogFile
->Lock
);
1068 if (!FlushFileBuffers(LogFile
->hFile
))
1070 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
1071 RtlReleaseResource(&LogFile
->Lock
);
1075 RtlReleaseResource(&LogFile
->Lock
);
1081 LogfClearFile(PLOGFILE LogFile
,
1082 PUNICODE_STRING BackupFileName
)
1084 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
1086 if (BackupFileName
->Length
> 0)
1088 /* FIXME: Write a backup file */
1091 LogfInitializeNew(LogFile
);
1093 RtlReleaseResource(&LogFile
->Lock
);
1095 return STATUS_SUCCESS
;
1100 LogfBackupFile(PLOGFILE LogFile
,
1101 PUNICODE_STRING BackupFileName
)
1103 OBJECT_ATTRIBUTES ObjectAttributes
;
1104 IO_STATUS_BLOCK IoStatusBlock
;
1105 EVENTLOGHEADER Header
;
1107 HANDLE FileHandle
= NULL
;
1109 LARGE_INTEGER FileOffset
;
1111 PUCHAR Buffer
= NULL
;
1113 DWORD dwOffset
, dwRead
, dwRecSize
;
1115 DPRINT("LogfBackupFile(%p, %wZ)\n", LogFile
, BackupFileName
);
1117 /* Lock the log file shared */
1118 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
1120 InitializeObjectAttributes(&ObjectAttributes
,
1122 OBJ_CASE_INSENSITIVE
,
1126 Status
= NtCreateFile(&FileHandle
,
1127 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1131 FILE_ATTRIBUTE_NORMAL
,
1134 FILE_WRITE_THROUGH
| FILE_SYNCHRONOUS_IO_NONALERT
,
1137 if (!NT_SUCCESS(Status
))
1139 DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName
, Status
);
1143 /* Initialize the (dirty) log file header */
1144 Header
.HeaderSize
= sizeof(EVENTLOGHEADER
);
1145 Header
.Signature
= LOGFILE_SIGNATURE
;
1146 Header
.MajorVersion
= MAJORVER
;
1147 Header
.MinorVersion
= MINORVER
;
1148 Header
.StartOffset
= sizeof(EVENTLOGHEADER
);
1149 Header
.EndOffset
= sizeof(EVENTLOGHEADER
);
1150 Header
.CurrentRecordNumber
= 1;
1151 Header
.OldestRecordNumber
= 1;
1153 Header
.Flags
= ELF_LOGFILE_HEADER_DIRTY
;
1154 Header
.Retention
= LogFile
->Header
.Retention
;
1155 Header
.EndHeaderSize
= sizeof(EVENTLOGHEADER
);
1157 /* Write the (dirty) log file header */
1158 Status
= NtWriteFile(FileHandle
,
1164 sizeof(EVENTLOGHEADER
),
1167 if (!NT_SUCCESS(Status
))
1169 DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status
);
1173 for (i
= LogFile
->Header
.OldestRecordNumber
; i
< LogFile
->Header
.CurrentRecordNumber
; i
++)
1175 dwOffset
= LogfOffsetByNumber(LogFile
, i
);
1179 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1181 DPRINT1("SetFilePointer() failed!\n");
1185 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
1187 DPRINT1("ReadFile() failed!\n");
1191 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1193 DPRINT1("SetFilePointer() failed!\n");
1197 Buffer
= HeapAlloc(MyHeap
, 0, dwRecSize
);
1200 DPRINT1("HeapAlloc() failed!\n");
1204 if (!ReadFile(LogFile
->hFile
, &Buffer
, dwRecSize
, &dwRead
, NULL
))
1206 DPRINT1("ReadFile() failed!\n");
1210 /* Write the event record */
1211 Status
= NtWriteFile(FileHandle
,
1220 if (!NT_SUCCESS(Status
))
1222 DPRINT1("NtWriteFile() failed!\n");
1226 /* Update the header information */
1227 Header
.EndOffset
+= dwRecSize
;
1229 /* Free the buffer */
1230 HeapFree(MyHeap
, 0, Buffer
);
1234 /* Initialize the EOF record */
1235 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1236 EofRec
.Ones
= 0x11111111;
1237 EofRec
.Twos
= 0x22222222;
1238 EofRec
.Threes
= 0x33333333;
1239 EofRec
.Fours
= 0x44444444;
1240 EofRec
.BeginRecord
= sizeof(EVENTLOGHEADER
);
1241 EofRec
.EndRecord
= Header
.EndOffset
;
1242 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1243 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1244 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1246 /* Write the EOF record */
1247 Status
= NtWriteFile(FileHandle
,
1253 sizeof(EVENTLOGEOF
),
1256 if (!NT_SUCCESS(Status
))
1258 DPRINT1("NtWriteFile() failed!\n");
1262 /* Update the header information */
1263 Header
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1264 Header
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1265 Header
.MaxSize
= Header
.EndOffset
+ sizeof(EVENTLOGEOF
);
1268 /* Write the (clean) log file header */
1269 FileOffset
.QuadPart
= 0;
1270 Status
= NtWriteFile(FileHandle
,
1276 sizeof(EVENTLOGHEADER
),
1279 if (!NT_SUCCESS(Status
))
1281 DPRINT1("NtWriteFile() failed!\n");
1285 /* Free the buffer */
1287 HeapFree(MyHeap
, 0, Buffer
);
1289 /* Close the backup file */
1290 if (FileHandle
!= NULL
)
1291 NtClose(FileHandle
);
1293 /* Unlock the log file */
1294 RtlReleaseResource(&LogFile
->Lock
);
1300 /* Returns 0 if nothing found. */
1301 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
1305 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
1307 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
1308 return LogFile
->OffsetInfo
[i
].EventOffset
;
1313 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
1315 return LogFile
->Header
.OldestRecordNumber
;
1318 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
1320 return LogFile
->Header
.CurrentRecordNumber
;
1323 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
1327 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
1332 for (i
= 0; i
< LogFile
->OffsetInfoNext
- 1; i
++)
1334 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+ 1].EventNumber
;
1335 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+ 1].EventOffset
;
1337 LogFile
->OffsetInfoNext
--;
1341 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
1343 LPVOID NewOffsetInfo
;
1345 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
1347 NewOffsetInfo
= HeapReAlloc(MyHeap
,
1349 LogFile
->OffsetInfo
,
1350 (LogFile
->OffsetInfoSize
+ 64) *
1351 sizeof(EVENT_OFFSET_INFO
));
1355 DPRINT1("Can't reallocate heap.\n");
1359 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
1360 LogFile
->OffsetInfoSize
+= 64;
1363 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
1364 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
1365 LogFile
->OffsetInfoNext
++;
1370 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
1371 DWORD dwRecordNumber
,
1376 LPCWSTR ComputerName
,
1385 PEVENTLOGRECORD pRec
;
1392 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
1393 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
1395 if (dwRecSize
% 4 != 0)
1396 dwRecSize
+= 4 - (dwRecSize
% 4);
1398 dwRecSize
+= dwSidLength
;
1400 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1402 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1403 str
+= lstrlenW(str
) + 1;
1406 dwRecSize
+= dwDataSize
;
1407 if (dwRecSize
% 4 != 0)
1408 dwRecSize
+= 4 - (dwRecSize
% 4);
1412 Buffer
= HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
1416 DPRINT1("Can't allocate heap!\n");
1420 pRec
= (PEVENTLOGRECORD
) Buffer
;
1421 pRec
->Length
= dwRecSize
;
1422 pRec
->Reserved
= LOGFILE_SIGNATURE
;
1423 pRec
->RecordNumber
= dwRecordNumber
;
1425 GetSystemTime(&SysTime
);
1426 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
1427 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
1429 pRec
->EventID
= dwEventId
;
1430 pRec
->EventType
= wType
;
1431 pRec
->EventCategory
= wCategory
;
1433 pos
= sizeof(EVENTLOGRECORD
);
1435 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
1436 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
1437 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
1438 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
1440 pRec
->UserSidOffset
= pos
;
1443 pos
+= 4 - (pos
% 4);
1447 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1448 pRec
->UserSidLength
= dwSidLength
;
1449 pRec
->UserSidOffset
= pos
;
1453 pRec
->StringOffset
= pos
;
1454 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1456 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1457 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1458 str
+= lstrlenW(str
) + 1;
1460 pRec
->NumStrings
= wNumStrings
;
1462 pRec
->DataOffset
= pos
;
1465 pRec
->DataLength
= dwDataSize
;
1466 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1471 pos
+= 4 - (pos
% 4);
1473 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1475 *lpRecSize
= dwRecSize
;
1481 LogfReportEvent(WORD wType
,
1489 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1490 DWORD dwComputerNameLength
= MAX_COMPUTERNAME_LENGTH
+ 1;
1491 PEVENTSOURCE pEventSource
= NULL
;
1497 if (!GetComputerNameW(szComputerName
, &dwComputerNameLength
))
1499 szComputerName
[0] = 0;
1502 pEventSource
= GetEventSourceByName(L
"EventLog");
1503 if (pEventSource
== NULL
)
1508 lastRec
= LogfGetCurrentRecord(pEventSource
->LogFile
);
1510 logBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
1515 pEventSource
->szName
,
1516 (LPCWSTR
)szComputerName
,
1524 dwError
= LogfWriteData(pEventSource
->LogFile
, recSize
, logBuffer
);
1527 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource
->LogFile
->FileName
);
1530 LogfFreeRecord(logBuffer
);