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());
291 PLOGFILE
LogfCreate(WCHAR
* LogName
, WCHAR
* FileName
)
294 BOOL bResult
, bCreateNew
= FALSE
;
296 LogFile
= (LOGFILE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(LOGFILE
));
299 DPRINT1("Can't allocate heap!\n");
303 LogFile
->hFile
= CreateFile(FileName
,
304 GENERIC_READ
| GENERIC_WRITE
,
308 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
311 if (LogFile
->hFile
== INVALID_HANDLE_VALUE
)
313 DPRINT1("Can't create file %S.\n", FileName
);
314 HeapFree(MyHeap
, 0, LogFile
);
318 bCreateNew
= (GetLastError() == ERROR_ALREADY_EXISTS
) ? FALSE
: TRUE
;
321 (WCHAR
*) HeapAlloc(MyHeap
,
323 (lstrlenW(LogName
) + 1) * sizeof(WCHAR
));
325 if (LogFile
->LogName
)
326 lstrcpyW(LogFile
->LogName
, LogName
);
329 DPRINT1("Can't allocate heap\n");
330 HeapFree(MyHeap
, 0, LogFile
);
335 (WCHAR
*) HeapAlloc(MyHeap
,
337 (lstrlenW(FileName
) + 1) * sizeof(WCHAR
));
339 if (LogFile
->FileName
)
340 lstrcpyW(LogFile
->FileName
, FileName
);
343 DPRINT1("Can't allocate heap\n");
347 LogFile
->OffsetInfo
=
348 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
350 sizeof(EVENT_OFFSET_INFO
) * 64);
352 if (!LogFile
->OffsetInfo
)
354 DPRINT1("Can't allocate heap\n");
358 LogFile
->OffsetInfoSize
= 64;
361 bResult
= LogfInitializeNew(LogFile
);
363 bResult
= LogfInitializeExisting(LogFile
);
368 RtlInitializeResource(&LogFile
->Lock
);
370 LogfListAddItem(LogFile
);
376 if (LogFile
->OffsetInfo
)
377 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
379 if (LogFile
->FileName
)
380 HeapFree(MyHeap
, 0, LogFile
->FileName
);
382 if (LogFile
->LogName
)
383 HeapFree(MyHeap
, 0, LogFile
->LogName
);
385 HeapFree(MyHeap
, 0, LogFile
);
391 VOID
LogfClose(PLOGFILE LogFile
)
396 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
398 FlushFileBuffers(LogFile
->hFile
);
399 CloseHandle(LogFile
->hFile
);
400 LogfListRemoveItem(LogFile
);
402 RtlDeleteResource(&LogFile
->Lock
);
404 HeapFree(MyHeap
, 0, LogFile
->LogName
);
405 HeapFree(MyHeap
, 0, LogFile
->FileName
);
406 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
407 HeapFree(MyHeap
, 0, LogFile
);
412 VOID
LogfCloseAll(VOID
)
414 while (!IsListEmpty(&LogFileListHead
))
416 LogfClose(LogfListHead());
419 DeleteCriticalSection(&LogFileListCs
);
422 VOID
LogfListInitialize(VOID
)
424 InitializeCriticalSection(&LogFileListCs
);
425 InitializeListHead(&LogFileListHead
);
428 PLOGFILE
LogfListHead(VOID
)
430 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
433 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
435 PLIST_ENTRY CurrentEntry
;
436 PLOGFILE Result
= NULL
;
438 EnterCriticalSection(&LogFileListCs
);
440 CurrentEntry
= LogFileListHead
.Flink
;
441 while (CurrentEntry
!= &LogFileListHead
)
443 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
447 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
453 CurrentEntry
= CurrentEntry
->Flink
;
456 LeaveCriticalSection(&LogFileListCs
);
460 /* Index starting from 1 */
461 INT
LogfListItemIndexByName(WCHAR
* Name
)
463 PLIST_ENTRY CurrentEntry
;
467 EnterCriticalSection(&LogFileListCs
);
469 CurrentEntry
= LogFileListHead
.Flink
;
470 while (CurrentEntry
!= &LogFileListHead
)
472 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
476 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
482 CurrentEntry
= CurrentEntry
->Flink
;
486 LeaveCriticalSection(&LogFileListCs
);
490 /* Index starting from 1 */
491 PLOGFILE
LogfListItemByIndex(INT Index
)
493 PLIST_ENTRY CurrentEntry
;
494 PLOGFILE Result
= NULL
;
497 EnterCriticalSection(&LogFileListCs
);
499 CurrentEntry
= LogFileListHead
.Flink
;
500 while (CurrentEntry
!= &LogFileListHead
)
504 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
508 CurrentEntry
= CurrentEntry
->Flink
;
512 LeaveCriticalSection(&LogFileListCs
);
516 INT
LogfListItemCount(VOID
)
518 PLIST_ENTRY CurrentEntry
;
521 EnterCriticalSection(&LogFileListCs
);
523 CurrentEntry
= LogFileListHead
.Flink
;
524 while (CurrentEntry
!= &LogFileListHead
)
526 CurrentEntry
= CurrentEntry
->Flink
;
530 LeaveCriticalSection(&LogFileListCs
);
534 VOID
LogfListAddItem(PLOGFILE Item
)
536 EnterCriticalSection(&LogFileListCs
);
537 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
538 LeaveCriticalSection(&LogFileListCs
);
541 VOID
LogfListRemoveItem(PLOGFILE Item
)
543 EnterCriticalSection(&LogFileListCs
);
544 RemoveEntryList(&Item
->ListEntry
);
545 LeaveCriticalSection(&LogFileListCs
);
549 ReadAnsiLogEntry(HANDLE hFile
,
551 DWORD nNumberOfBytesToRead
,
552 LPDWORD lpNumberOfBytesRead
)
557 UNICODE_STRING StringW
;
562 LPVOID lpUnicodeBuffer
= NULL
;
571 *lpNumberOfBytesRead
= 0;
573 lpUnicodeBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nNumberOfBytesToRead
);
574 if (lpUnicodeBuffer
== NULL
)
576 DPRINT1("Alloc failed!\n");
580 if (!ReadFile(hFile
, lpUnicodeBuffer
, nNumberOfBytesToRead
, &dwRead
, NULL
))
582 DPRINT1("Read failed!\n");
587 Dst
= (PEVENTLOGRECORD
)lpBuffer
;
588 Src
= (PEVENTLOGRECORD
)lpUnicodeBuffer
;
590 Dst
->TimeGenerated
= Src
->TimeGenerated
;
591 Dst
->Reserved
= Src
->Reserved
;
592 Dst
->RecordNumber
= Src
->RecordNumber
;
593 Dst
->TimeWritten
= Src
->TimeWritten
;
594 Dst
->EventID
= Src
->EventID
;
595 Dst
->EventType
= Src
->EventType
;
596 Dst
->EventCategory
= Src
->EventCategory
;
597 Dst
->NumStrings
= Src
->NumStrings
;
598 Dst
->UserSidLength
= Src
->UserSidLength
;
599 Dst
->DataLength
= Src
->DataLength
;
601 SrcPtr
= (LPWSTR
)((DWORD_PTR
)Src
+ sizeof(EVENTLOGRECORD
));
602 DstPtr
= (LPSTR
)((DWORD_PTR
)Dst
+ sizeof(EVENTLOGRECORD
));
604 /* Convert the module name */
605 RtlInitUnicodeString(&StringW
, SrcPtr
);
606 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
607 if (NT_SUCCESS(Status
))
609 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
611 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
613 RtlFreeAnsiString(&StringA
);
616 /* Convert the computer name */
617 if (NT_SUCCESS(Status
))
619 SrcPtr
= (PWSTR
)((DWORD_PTR
)SrcPtr
+ StringW
.MaximumLength
);
621 RtlInitUnicodeString(&StringW
, SrcPtr
);
622 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
623 if (NT_SUCCESS(Status
))
625 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
627 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
629 RtlFreeAnsiString(&StringA
);
633 /* Add the padding and the User SID*/
634 if (NT_SUCCESS(Status
))
636 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
) % sizeof(DWORD
));
637 RtlZeroMemory(DstPtr
, dwPadding
);
639 DstPtr
= (LPSTR
)((DWORD_PTR
)DstPtr
+ dwPadding
);
640 RtlCopyMemory(DstPtr
,
641 (PVOID
)((DWORD_PTR
)Src
+ Src
->UserSidOffset
),
644 Dst
->UserSidOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
648 /* Convert the strings */
649 if (NT_SUCCESS(Status
))
651 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->UserSidLength
);
653 SrcString
= (LPWSTR
)((DWORD_PTR
)Src
+ (DWORD
)Src
->StringOffset
);
654 DstString
= (LPSTR
)DstPtr
;
656 for (i
= 0; i
< Dst
->NumStrings
; i
++)
658 RtlInitUnicodeString(&StringW
, SrcString
);
660 RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
662 RtlCopyMemory(DstString
, StringA
.Buffer
, StringA
.MaximumLength
);
664 SrcString
= (LPWSTR
)((DWORD_PTR
)SrcString
+
665 (DWORD
)StringW
.MaximumLength
);
667 DstString
= (LPSTR
)((DWORD_PTR
)DstString
+
668 (DWORD
)StringA
.MaximumLength
);
670 RtlFreeAnsiString(&StringA
);
673 Dst
->StringOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
676 /* Copy the binary data */
677 DstPtr
= (PVOID
)DstString
;
678 Dst
->DataOffset
= (DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
;
680 RtlCopyMemory(DstPtr
, (PVOID
)((DWORD_PTR
)Src
+ Src
->DataOffset
), Src
->DataLength
);
682 /* Add the padding */
683 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->DataLength
);
684 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
-(DWORD_PTR
)Dst
) % sizeof(DWORD
));
685 RtlZeroMemory(DstPtr
, dwPadding
);
687 dwEntryLength
= (DWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
+ sizeof(DWORD
) - (DWORD_PTR
)Dst
);
689 /* Set the entry length at the end of the entry*/
690 pLength
= (PDWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
);
691 *pLength
= dwEntryLength
;
692 Dst
->Length
= dwEntryLength
;
694 *lpNumberOfBytesRead
= dwEntryLength
;
698 if (lpUnicodeBuffer
!= NULL
)
699 HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer
);
705 DWORD
LogfReadEvent(PLOGFILE LogFile
,
707 DWORD
* RecordNumber
,
714 DWORD dwOffset
, dwRead
, dwRecSize
;
715 DWORD dwBufferUsage
= 0, dwRecNum
;
717 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
718 return ERROR_INVALID_PARAMETER
;
720 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
721 return ERROR_INVALID_PARAMETER
;
723 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
724 return ERROR_INVALID_PARAMETER
;
726 if ((*RecordNumber
==0) && !(EVENTLOG_SEQUENTIAL_READ
))
728 return ERROR_INVALID_PARAMETER
;
731 dwRecNum
= *RecordNumber
;
733 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
738 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
742 RtlReleaseResource(&LogFile
->Lock
);
743 return ERROR_HANDLE_EOF
;
746 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
747 INVALID_SET_FILE_POINTER
)
749 DPRINT1("SetFilePointer() failed!\n");
753 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
755 DPRINT1("ReadFile() failed!\n");
759 if (dwRecSize
> BufSize
)
761 *BytesNeeded
= dwRecSize
;
762 RtlReleaseResource(&LogFile
->Lock
);
763 return ERROR_INSUFFICIENT_BUFFER
;
766 if (SetFilePointer(LogFile
->hFile
,
767 -((LONG
) sizeof(DWORD
)),
769 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
771 DPRINT1("SetFilePointer() failed!\n");
777 if (!ReadAnsiLogEntry(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
))
779 DPRINT1("ReadAnsiLogEntry() failed!\n");
785 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
787 DPRINT1("ReadFile() failed!\n");
792 dwBufferUsage
+= dwRead
;
794 while (dwBufferUsage
<= BufSize
)
796 if (Flags
& EVENTLOG_FORWARDS_READ
)
801 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
805 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
806 INVALID_SET_FILE_POINTER
)
808 DPRINT1("SetFilePointer() failed!\n");
812 if (!ReadFile(LogFile
->hFile
,
818 DPRINT1("ReadFile() failed!\n");
822 if (dwBufferUsage
+ dwRecSize
> BufSize
)
825 if (SetFilePointer(LogFile
->hFile
,
826 -((LONG
) sizeof(DWORD
)),
828 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
830 DPRINT1("SetFilePointer() failed!\n");
836 if (!ReadAnsiLogEntry(LogFile
->hFile
,
837 Buffer
+ dwBufferUsage
,
841 DPRINT1("ReadAnsiLogEntry() failed!\n");
847 if (!ReadFile(LogFile
->hFile
,
848 Buffer
+ dwBufferUsage
,
853 DPRINT1("ReadFile() failed!\n");
858 dwBufferUsage
+= dwRead
;
861 *BytesRead
= dwBufferUsage
;
862 * RecordNumber
= dwRecNum
;
863 RtlReleaseResource(&LogFile
->Lock
);
864 return ERROR_SUCCESS
;
867 DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
868 RtlReleaseResource(&LogFile
->Lock
);
869 return GetLastError();
872 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
878 PEVENTLOGRECORD RecBuf
;
879 LARGE_INTEGER logFileSize
;
887 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
889 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
891 if (!GetFileSizeEx(LogFile
->hFile
, &logFileSize
))
893 RtlReleaseResource(&LogFile
->Lock
);
897 /* If the size of the file is over MaxSize */
898 if ((logFileSize
.QuadPart
+ BufSize
)> LogFile
->Header
.MaxSize
)
900 ULONG OverWriteLength
= 0;
901 WriteOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
902 RecBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(EVENTLOGRECORD
));
903 /* Determine how many records need to be overwritten */
906 DPRINT("EventLogFile has reached maximume size\n");
910 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
911 HeapFree(GetProcessHeap(), 0, RecBuf
);
912 RtlReleaseResource(&LogFile
->Lock
);
916 /* Get the oldest record data */
917 RecOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
919 if (SetFilePointer(LogFile
->hFile
,
922 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
924 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
925 HeapFree(GetProcessHeap(), 0, RecBuf
);
926 RtlReleaseResource(&LogFile
->Lock
);
930 if (!ReadFile(LogFile
->hFile
, RecBuf
, sizeof(EVENTLOGRECORD
), &dwRead
, NULL
))
932 DPRINT1("ReadFile() failed!\n");
933 HeapFree(GetProcessHeap(), 0, RecBuf
);
934 RtlReleaseResource(&LogFile
->Lock
);
938 if (RecBuf
->Reserved
!= LOGFILE_SIGNATURE
)
940 DPRINT1("LogFile corrupt!\n");
941 RtlReleaseResource(&LogFile
->Lock
);
945 LogfDeleteOffsetInformation(LogFile
,LogFile
->Header
.OldestRecordNumber
);
947 LogFile
->Header
.OldestRecordNumber
++;
949 OverWriteLength
+= RecBuf
->Length
;
950 /* Check the size of the record as the record adding may be larger */
951 if (OverWriteLength
>= BufSize
)
953 DPRINT("Record will fit. Lenght %d, BufSize %d\n", OverWriteLength
, BufSize
);
954 LogFile
->Header
.StartOffset
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
958 HeapFree(GetProcessHeap(), 0, RecBuf
);
961 WriteOffSet
= LogFile
->Header
.EndOffset
;
963 if (SetFilePointer(LogFile
->hFile
,
966 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
968 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
969 RtlReleaseResource(&LogFile
->Lock
);
973 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
975 DPRINT1("WriteFile() failed! %d\n", GetLastError());
976 RtlReleaseResource(&LogFile
->Lock
);
980 if (!LogfAddOffsetInformation(LogFile
,
981 LogFile
->Header
.CurrentRecordNumber
,
984 RtlReleaseResource(&LogFile
->Lock
);
988 LogFile
->Header
.CurrentRecordNumber
++;
990 if (WriteOffSet
== LogFile
->Header
.EndOffset
)
992 LogFile
->Header
.EndOffset
+= dwWritten
;
994 if (SetFilePointer(LogFile
->hFile
,
995 LogFile
->Header
.EndOffset
,
997 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
999 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1000 RtlReleaseResource(&LogFile
->Lock
);
1004 EofRec
.Ones
= 0x11111111;
1005 EofRec
.Twos
= 0x22222222;
1006 EofRec
.Threes
= 0x33333333;
1007 EofRec
.Fours
= 0x44444444;
1008 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1009 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1010 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1011 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1012 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
1013 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
1015 if (!WriteFile(LogFile
->hFile
,
1017 sizeof(EVENTLOGEOF
),
1021 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1022 RtlReleaseResource(&LogFile
->Lock
);
1026 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
1027 INVALID_SET_FILE_POINTER
)
1029 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1030 RtlReleaseResource(&LogFile
->Lock
);
1034 if (!WriteFile(LogFile
->hFile
,
1036 sizeof(EVENTLOGHEADER
),
1040 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
1041 RtlReleaseResource(&LogFile
->Lock
);
1045 if (!FlushFileBuffers(LogFile
->hFile
))
1047 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
1048 RtlReleaseResource(&LogFile
->Lock
);
1052 RtlReleaseResource(&LogFile
->Lock
);
1058 LogfClearFile(PLOGFILE LogFile
,
1059 PUNICODE_STRING BackupFileName
)
1061 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
1063 if (BackupFileName
->Length
> 0)
1065 /* FIXME: Write a backup file */
1068 LogfInitializeNew(LogFile
);
1070 RtlReleaseResource(&LogFile
->Lock
);
1072 return STATUS_SUCCESS
;
1077 LogfBackupFile(PLOGFILE LogFile
,
1078 PUNICODE_STRING BackupFileName
)
1080 // RtlAcquireResourceShared(&LogFile->Lock, TRUE);
1082 /* FIXME: Write a backup file */
1084 // RtlReleaseResource(&LogFile->Lock);
1086 return STATUS_NOT_IMPLEMENTED
;
1090 /* Returns 0 if nothing found. */
1091 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
1095 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
1097 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
1098 return LogFile
->OffsetInfo
[i
].EventOffset
;
1103 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
1105 return LogFile
->Header
.OldestRecordNumber
;
1108 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
1110 return LogFile
->Header
.CurrentRecordNumber
;
1113 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
1117 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
1122 for (i
= 0; i
< LogFile
->OffsetInfoNext
- 1; i
++)
1124 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+ 1].EventNumber
;
1125 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+ 1].EventOffset
;
1127 LogFile
->OffsetInfoNext
--;
1131 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
1133 LPVOID NewOffsetInfo
;
1135 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
1137 NewOffsetInfo
= HeapReAlloc(MyHeap
,
1139 LogFile
->OffsetInfo
,
1140 (LogFile
->OffsetInfoSize
+ 64) *
1141 sizeof(EVENT_OFFSET_INFO
));
1145 DPRINT1("Can't reallocate heap.\n");
1149 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
1150 LogFile
->OffsetInfoSize
+= 64;
1153 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
1154 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
1155 LogFile
->OffsetInfoNext
++;
1160 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
1161 DWORD dwRecordNumber
,
1166 LPCWSTR ComputerName
,
1175 PEVENTLOGRECORD pRec
;
1182 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
1183 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
1185 if (dwRecSize
% 4 != 0)
1186 dwRecSize
+= 4 - (dwRecSize
% 4);
1188 dwRecSize
+= dwSidLength
;
1190 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1192 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1193 str
+= lstrlenW(str
) + 1;
1196 dwRecSize
+= dwDataSize
;
1197 if (dwRecSize
% 4 != 0)
1198 dwRecSize
+= 4 - (dwRecSize
% 4);
1202 Buffer
= HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
1206 DPRINT1("Can't allocate heap!\n");
1210 pRec
= (PEVENTLOGRECORD
) Buffer
;
1211 pRec
->Length
= dwRecSize
;
1212 pRec
->Reserved
= LOGFILE_SIGNATURE
;
1213 pRec
->RecordNumber
= dwRecordNumber
;
1215 GetSystemTime(&SysTime
);
1216 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
1217 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
1219 pRec
->EventID
= dwEventId
;
1220 pRec
->EventType
= wType
;
1221 pRec
->EventCategory
= wCategory
;
1223 pos
= sizeof(EVENTLOGRECORD
);
1225 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
1226 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
1227 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
1228 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
1230 pRec
->UserSidOffset
= pos
;
1233 pos
+= 4 - (pos
% 4);
1237 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1238 pRec
->UserSidLength
= dwSidLength
;
1239 pRec
->UserSidOffset
= pos
;
1243 pRec
->StringOffset
= pos
;
1244 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1246 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1247 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1248 str
+= lstrlenW(str
) + 1;
1250 pRec
->NumStrings
= wNumStrings
;
1252 pRec
->DataOffset
= pos
;
1255 pRec
->DataLength
= dwDataSize
;
1256 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1261 pos
+= 4 - (pos
% 4);
1263 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1265 *lpRecSize
= dwRecSize
;
1271 LogfReportEvent(WORD wType
,
1279 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1280 DWORD dwComputerNameLength
= MAX_COMPUTERNAME_LENGTH
+ 1;
1281 PEVENTSOURCE pEventSource
= NULL
;
1287 if (!GetComputerNameW(szComputerName
, &dwComputerNameLength
))
1289 szComputerName
[0] = 0;
1292 pEventSource
= GetEventSourceByName(L
"EventLog");
1293 if (pEventSource
== NULL
)
1298 lastRec
= LogfGetCurrentRecord(pEventSource
->LogFile
);
1300 logBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
1305 pEventSource
->szName
,
1306 (LPCWSTR
)szComputerName
,
1314 dwError
= LogfWriteData(pEventSource
->LogFile
, recSize
, logBuffer
);
1317 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource
->LogFile
->FileName
);
1320 LogfFreeRecord(logBuffer
);