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 /* FIXME: Read MaxSize from registry for this LogFile.
38 But for now limit EventLog size to just under 5K. */
39 LogFile
->Header
.MaxSize
= 5000;
40 LogFile
->Header
.Signature
= LOGFILE_SIGNATURE
;
41 if (!WriteFile(LogFile
->hFile
,
43 sizeof(EVENTLOGHEADER
),
47 DPRINT1("WriteFile failed:%d!\n", GetLastError());
51 EofRec
.Ones
= 0x11111111;
52 EofRec
.Twos
= 0x22222222;
53 EofRec
.Threes
= 0x33333333;
54 EofRec
.Fours
= 0x44444444;
55 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
56 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
57 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
58 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
59 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
60 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
62 if (!WriteFile(LogFile
->hFile
,
68 DPRINT1("WriteFile failed:%d!\n", GetLastError());
72 if (!FlushFileBuffers(LogFile
->hFile
))
74 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
81 BOOL
LogfInitializeExisting(PLOGFILE LogFile
)
84 DWORD dwRecordsNumber
= 0;
85 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
87 PEVENTLOGRECORD RecBuf
;
88 BOOL OvewrWrittenRecords
= FALSE
;
90 DPRINT("Initializing LogFile %S\n",LogFile
->LogName
);
92 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
93 INVALID_SET_FILE_POINTER
)
95 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
99 if (!ReadFile(LogFile
->hFile
,
101 sizeof(EVENTLOGHEADER
),
105 DPRINT1("ReadFile failed! %d\n", GetLastError());
109 if (dwRead
!= sizeof(EVENTLOGHEADER
))
111 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
112 return LogfInitializeNew(LogFile
);
115 if (LogFile
->Header
.HeaderSize
!= sizeof(EVENTLOGHEADER
) ||
116 LogFile
->Header
.EndHeaderSize
!= sizeof(EVENTLOGHEADER
))
118 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
119 return LogfInitializeNew(LogFile
);
122 if (LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
124 DPRINT("EventLog: Invalid signature %x in %S.\n",
125 LogFile
->Header
.Signature
, LogFile
->FileName
);
126 return LogfInitializeNew(LogFile
);
129 if (LogFile
->Header
.EndOffset
> GetFileSize(LogFile
->hFile
, NULL
) + 1)
131 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
132 LogFile
->Header
.EndOffset
, LogFile
->FileName
);
133 return LogfInitializeNew(LogFile
);
136 /* Set the read location to the oldest record */
137 dwFilePointer
= SetFilePointer(LogFile
->hFile
, LogFile
->Header
.StartOffset
, NULL
, FILE_BEGIN
);
138 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
140 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
146 dwFilePointer
= SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
);
148 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
150 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
154 /* If the EVENTLOGEOF info has been reached and the oldest record was not immediately after the Header */
155 if ((dwFilePointer
== LogFile
->Header
.EndOffset
) && (LogFile
->Header
.StartOffset
!= sizeof(EVENTLOGHEADER
)))
157 OvewrWrittenRecords
= TRUE
;
158 /* The file has records that overwrote old ones so read them */
159 dwFilePointer
= SetFilePointer(LogFile
->hFile
, sizeof(EVENTLOGHEADER
), NULL
, FILE_BEGIN
);
162 if (!ReadFile(LogFile
->hFile
,
168 DPRINT1("ReadFile failed! %d\n", GetLastError());
172 if (dwRead
!= sizeof(dwRecSize
))
175 if (!ReadFile(LogFile
->hFile
,
181 DPRINT1("ReadFile() failed! %d\n", GetLastError());
185 if (dwRead
!= sizeof(dwRecSize
))
188 if (dwRecSign
!= LOGFILE_SIGNATURE
||
189 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
) + 1 ||
190 dwRecSize
< sizeof(EVENTLOGRECORD
))
195 if (SetFilePointer(LogFile
->hFile
,
196 -((LONG
) sizeof(DWORD
) * 2),
198 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
200 DPRINT1("SetFilePointer() failed! %d", GetLastError());
204 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
208 DPRINT1("Can't allocate heap!\n");
212 if (!ReadFile(LogFile
->hFile
, RecBuf
, dwRecSize
, &dwRead
, NULL
))
214 DPRINT1("ReadFile() failed! %d\n", GetLastError());
215 HeapFree(MyHeap
, 0, RecBuf
);
219 if (dwRead
!= dwRecSize
)
221 HeapFree(MyHeap
, 0, RecBuf
);
225 /* if OvewrWrittenRecords is TRUE and this record has already been read */
226 if ((OvewrWrittenRecords
== TRUE
) && (RecBuf
->RecordNumber
== LogFile
->Header
.OldestRecordNumber
))
228 HeapFree(MyHeap
, 0, RecBuf
);
232 pdwRecSize2
= (PDWORD
) (((PBYTE
) RecBuf
) + dwRecSize
- 4);
234 if (*pdwRecSize2
!= dwRecSize
)
236 DPRINT1("Invalid RecordSizeEnd of record %d (%x) in %S\n",
237 dwRecordsNumber
, *pdwRecSize2
, LogFile
->LogName
);
238 HeapFree(MyHeap
, 0, RecBuf
);
244 if (!LogfAddOffsetInformation(LogFile
,
245 RecBuf
->RecordNumber
,
248 DPRINT1("LogfAddOffsetInformation() failed!\n");
249 HeapFree(MyHeap
, 0, RecBuf
);
253 HeapFree(MyHeap
, 0, RecBuf
);
256 LogFile
->Header
.CurrentRecordNumber
= dwRecordsNumber
+ LogFile
->Header
.OldestRecordNumber
;
257 if (LogFile
->Header
.CurrentRecordNumber
== 0)
258 LogFile
->Header
.CurrentRecordNumber
= 1;
260 /* FIXME: Read MaxSize from registry for this LogFile.
261 But for now limit EventLog size to just under 5K. */
262 LogFile
->Header
.MaxSize
= 5000;
264 if (!SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
265 INVALID_SET_FILE_POINTER
)
267 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
271 if (!WriteFile(LogFile
->hFile
,
273 sizeof(EVENTLOGHEADER
),
277 DPRINT1("WriteFile failed! %d\n", GetLastError());
281 if (!FlushFileBuffers(LogFile
->hFile
))
283 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
290 PLOGFILE
LogfCreate(WCHAR
* LogName
, WCHAR
* FileName
)
293 BOOL bResult
, bCreateNew
= FALSE
;
295 LogFile
= (LOGFILE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(LOGFILE
));
298 DPRINT1("Can't allocate heap!\n");
302 LogFile
->hFile
= CreateFile(FileName
,
303 GENERIC_READ
| GENERIC_WRITE
,
307 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
310 if (LogFile
->hFile
== INVALID_HANDLE_VALUE
)
312 DPRINT1("Can't create file %S.\n", FileName
);
313 HeapFree(MyHeap
, 0, LogFile
);
317 bCreateNew
= (GetLastError() == ERROR_ALREADY_EXISTS
) ? FALSE
: TRUE
;
320 (WCHAR
*) HeapAlloc(MyHeap
,
322 (lstrlenW(LogName
) + 1) * sizeof(WCHAR
));
324 if (LogFile
->LogName
)
325 lstrcpyW(LogFile
->LogName
, LogName
);
328 DPRINT1("Can't allocate heap\n");
329 HeapFree(MyHeap
, 0, LogFile
);
334 (WCHAR
*) HeapAlloc(MyHeap
,
336 (lstrlenW(FileName
) + 1) * sizeof(WCHAR
));
338 if (LogFile
->FileName
)
339 lstrcpyW(LogFile
->FileName
, FileName
);
342 DPRINT1("Can't allocate heap\n");
346 LogFile
->OffsetInfo
=
347 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
349 sizeof(EVENT_OFFSET_INFO
) * 64);
351 if (!LogFile
->OffsetInfo
)
353 DPRINT1("Can't allocate heap\n");
357 LogFile
->OffsetInfoSize
= 64;
360 bResult
= LogfInitializeNew(LogFile
);
362 bResult
= LogfInitializeExisting(LogFile
);
367 InitializeCriticalSection(&LogFile
->cs
);
368 LogfListAddItem(LogFile
);
374 if (LogFile
->OffsetInfo
)
375 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
377 if (LogFile
->FileName
)
378 HeapFree(MyHeap
, 0, LogFile
->FileName
);
380 if (LogFile
->LogName
)
381 HeapFree(MyHeap
, 0, LogFile
->LogName
);
383 HeapFree(MyHeap
, 0, LogFile
);
389 VOID
LogfClose(PLOGFILE LogFile
)
394 EnterCriticalSection(&LogFile
->cs
);
396 FlushFileBuffers(LogFile
->hFile
);
397 CloseHandle(LogFile
->hFile
);
398 LogfListRemoveItem(LogFile
);
400 DeleteCriticalSection(&LogFile
->cs
);
402 HeapFree(MyHeap
, 0, LogFile
->LogName
);
403 HeapFree(MyHeap
, 0, LogFile
->FileName
);
404 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
405 HeapFree(MyHeap
, 0, LogFile
);
410 VOID
LogfCloseAll(VOID
)
412 while (!IsListEmpty(&LogFileListHead
))
414 LogfClose(LogfListHead());
417 DeleteCriticalSection(&LogFileListCs
);
420 VOID
LogfListInitialize(VOID
)
422 InitializeCriticalSection(&LogFileListCs
);
423 InitializeListHead(&LogFileListHead
);
426 PLOGFILE
LogfListHead(VOID
)
428 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
431 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
433 PLIST_ENTRY CurrentEntry
;
434 PLOGFILE Result
= NULL
;
436 EnterCriticalSection(&LogFileListCs
);
438 CurrentEntry
= LogFileListHead
.Flink
;
439 while (CurrentEntry
!= &LogFileListHead
)
441 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
445 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
451 CurrentEntry
= CurrentEntry
->Flink
;
454 LeaveCriticalSection(&LogFileListCs
);
458 /* Index starting from 1 */
459 INT
LogfListItemIndexByName(WCHAR
* Name
)
461 PLIST_ENTRY CurrentEntry
;
465 EnterCriticalSection(&LogFileListCs
);
467 CurrentEntry
= LogFileListHead
.Flink
;
468 while (CurrentEntry
!= &LogFileListHead
)
470 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
474 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
480 CurrentEntry
= CurrentEntry
->Flink
;
484 LeaveCriticalSection(&LogFileListCs
);
488 /* Index starting from 1 */
489 PLOGFILE
LogfListItemByIndex(INT Index
)
491 PLIST_ENTRY CurrentEntry
;
492 PLOGFILE Result
= NULL
;
495 EnterCriticalSection(&LogFileListCs
);
497 CurrentEntry
= LogFileListHead
.Flink
;
498 while (CurrentEntry
!= &LogFileListHead
)
502 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
506 CurrentEntry
= CurrentEntry
->Flink
;
510 LeaveCriticalSection(&LogFileListCs
);
514 INT
LogfListItemCount()
516 PLIST_ENTRY CurrentEntry
;
519 EnterCriticalSection(&LogFileListCs
);
521 CurrentEntry
= LogFileListHead
.Flink
;
522 while (CurrentEntry
!= &LogFileListHead
)
524 CurrentEntry
= CurrentEntry
->Flink
;
528 LeaveCriticalSection(&LogFileListCs
);
532 VOID
LogfListAddItem(PLOGFILE Item
)
534 EnterCriticalSection(&LogFileListCs
);
535 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
536 LeaveCriticalSection(&LogFileListCs
);
539 VOID
LogfListRemoveItem(PLOGFILE Item
)
541 EnterCriticalSection(&LogFileListCs
);
542 RemoveEntryList(&Item
->ListEntry
);
543 LeaveCriticalSection(&LogFileListCs
);
546 DWORD
LogfReadEvent(PLOGFILE LogFile
,
548 DWORD
* RecordNumber
,
554 DWORD dwOffset
, dwRead
, dwRecSize
;
555 DWORD dwBufferUsage
= 0, dwRecNum
;
557 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
558 return ERROR_INVALID_PARAMETER
;
560 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
561 return ERROR_INVALID_PARAMETER
;
563 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
564 return ERROR_INVALID_PARAMETER
;
566 if ((*RecordNumber
==0) && !(EVENTLOG_SEQUENTIAL_READ
))
568 return ERROR_INVALID_PARAMETER
;
571 dwRecNum
= *RecordNumber
;
572 EnterCriticalSection(&LogFile
->cs
);
577 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
581 LeaveCriticalSection(&LogFile
->cs
);
582 return ERROR_HANDLE_EOF
;
585 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
586 INVALID_SET_FILE_POINTER
)
588 DPRINT1("SetFilePointer() failed!\n");
592 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
594 DPRINT1("ReadFile() failed!\n");
598 if (dwRecSize
> BufSize
)
600 *BytesNeeded
= dwRecSize
;
601 LeaveCriticalSection(&LogFile
->cs
);
602 return ERROR_INSUFFICIENT_BUFFER
;
605 if (SetFilePointer(LogFile
->hFile
,
606 -((LONG
) sizeof(DWORD
)),
608 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
610 DPRINT1("SetFilePointer() failed!\n");
614 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
616 DPRINT1("ReadFile() failed!\n");
620 dwBufferUsage
+= dwRead
;
622 while (dwBufferUsage
<= BufSize
)
624 if (Flags
& EVENTLOG_FORWARDS_READ
)
629 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
633 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
634 INVALID_SET_FILE_POINTER
)
636 DPRINT1("SetFilePointer() failed!\n");
640 if (!ReadFile(LogFile
->hFile
,
646 DPRINT1("ReadFile() failed!\n");
650 if (dwBufferUsage
+ dwRecSize
> BufSize
)
653 if (SetFilePointer(LogFile
->hFile
,
654 -((LONG
) sizeof(DWORD
)),
656 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
658 DPRINT1("SetFilePointer() failed!\n");
662 if (!ReadFile(LogFile
->hFile
,
663 Buffer
+ dwBufferUsage
,
668 DPRINT1("ReadFile() failed!\n");
672 dwBufferUsage
+= dwRead
;
675 *BytesRead
= dwBufferUsage
;
676 * RecordNumber
= dwRecNum
;
677 LeaveCriticalSection(&LogFile
->cs
);
678 return ERROR_SUCCESS
;
681 DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
682 LeaveCriticalSection(&LogFile
->cs
);
683 return GetLastError();
686 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
692 PEVENTLOGRECORD RecBuf
;
693 LARGE_INTEGER logFileSize
;
701 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
703 EnterCriticalSection(&LogFile
->cs
);
705 if (!GetFileSizeEx(LogFile
->hFile
, &logFileSize
))
707 LeaveCriticalSection(&LogFile
->cs
);
711 /* If the size of the file is over MaxSize */
712 if ((logFileSize
.QuadPart
+ BufSize
)> LogFile
->Header
.MaxSize
)
714 ULONG OverWriteLength
= 0;
715 WriteOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
716 RecBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(EVENTLOGRECORD
));
717 /* Determine how many records need to be overwritten */
720 DPRINT("EventLogFile has reached maximume size\n");
724 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
725 HeapFree(GetProcessHeap(), 0, RecBuf
);
726 LeaveCriticalSection(&LogFile
->cs
);
730 /* Get the oldest record data */
731 RecOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
733 if (SetFilePointer(LogFile
->hFile
,
736 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
738 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
739 HeapFree(GetProcessHeap(), 0, RecBuf
);
740 LeaveCriticalSection(&LogFile
->cs
);
744 if (!ReadFile(LogFile
->hFile
, RecBuf
, sizeof(EVENTLOGRECORD
), &dwRead
, NULL
))
746 DPRINT1("ReadFile() failed!\n");
747 HeapFree(GetProcessHeap(), 0, RecBuf
);
748 LeaveCriticalSection(&LogFile
->cs
);
752 if (RecBuf
->Reserved
!= LOGFILE_SIGNATURE
)
754 DPRINT1("LogFile corrupt!\n");
755 LeaveCriticalSection(&LogFile
->cs
);
759 LogfDeleteOffsetInformation(LogFile
,LogFile
->Header
.OldestRecordNumber
);
761 LogFile
->Header
.OldestRecordNumber
++;
763 OverWriteLength
+= RecBuf
->Length
;
764 /* Check the size of the record as the record adding may be larger */
765 if (OverWriteLength
>= BufSize
)
767 DPRINT("Record will fit. Lenght %d, BufSize %d\n", OverWriteLength
, BufSize
);
768 LogFile
->Header
.StartOffset
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
772 HeapFree(GetProcessHeap(), 0, RecBuf
);
775 WriteOffSet
= LogFile
->Header
.EndOffset
;
777 if (SetFilePointer(LogFile
->hFile
,
780 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
782 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
783 LeaveCriticalSection(&LogFile
->cs
);
787 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
789 DPRINT1("WriteFile() failed! %d\n", GetLastError());
790 LeaveCriticalSection(&LogFile
->cs
);
794 if (!LogfAddOffsetInformation(LogFile
,
795 LogFile
->Header
.CurrentRecordNumber
,
798 LeaveCriticalSection(&LogFile
->cs
);
802 LogFile
->Header
.CurrentRecordNumber
++;
804 if (LogFile
->Header
.OldestRecordNumber
== 0)
805 LogFile
->Header
.OldestRecordNumber
= 1;
807 if (WriteOffSet
== LogFile
->Header
.EndOffset
)
809 LogFile
->Header
.EndOffset
+= dwWritten
;
811 if (SetFilePointer(LogFile
->hFile
,
812 LogFile
->Header
.EndOffset
,
814 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
816 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
817 LeaveCriticalSection(&LogFile
->cs
);
821 EofRec
.Ones
= 0x11111111;
822 EofRec
.Twos
= 0x22222222;
823 EofRec
.Threes
= 0x33333333;
824 EofRec
.Fours
= 0x44444444;
825 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
826 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
827 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
828 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
829 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
830 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
832 if (!WriteFile(LogFile
->hFile
,
838 DPRINT1("WriteFile() failed! %d\n", GetLastError());
839 LeaveCriticalSection(&LogFile
->cs
);
843 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
844 INVALID_SET_FILE_POINTER
)
846 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
847 LeaveCriticalSection(&LogFile
->cs
);
851 if (!WriteFile(LogFile
->hFile
,
853 sizeof(EVENTLOGHEADER
),
857 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
858 LeaveCriticalSection(&LogFile
->cs
);
862 if (!FlushFileBuffers(LogFile
->hFile
))
864 LeaveCriticalSection(&LogFile
->cs
);
865 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
869 LeaveCriticalSection(&LogFile
->cs
);
873 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
875 /* Returns 0 if nothing found. */
879 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
881 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
882 return LogFile
->OffsetInfo
[i
].EventOffset
;
887 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
889 return LogFile
->Header
.OldestRecordNumber
;
892 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
894 return LogFile
->Header
.CurrentRecordNumber
;
897 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
901 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
906 for (i
=0;i
<LogFile
->OffsetInfoNext
-1; i
++)
908 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+1].EventNumber
;
909 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+1].EventOffset
;
911 LogFile
->OffsetInfoNext
--;
915 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
917 LPVOID NewOffsetInfo
;
919 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
921 NewOffsetInfo
= HeapReAlloc(MyHeap
,
924 (LogFile
->OffsetInfoSize
+ 64) *
925 sizeof(EVENT_OFFSET_INFO
));
929 DPRINT1("Can't reallocate heap.\n");
933 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
934 LogFile
->OffsetInfoSize
+= 64;
937 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
938 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
939 LogFile
->OffsetInfoNext
++;
944 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
945 DWORD dwRecordNumber
,
950 LPCWSTR ComputerName
,
959 PEVENTLOGRECORD pRec
;
962 UINT i
, pos
, nStrings
;
966 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
967 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
969 if (dwRecSize
% 4 != 0)
970 dwRecSize
+= 4 - (dwRecSize
% 4);
972 dwRecSize
+= dwSidLength
;
974 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
976 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
977 str
+= lstrlenW(str
) + 1;
980 dwRecSize
+= dwDataSize
;
981 if (dwRecSize
% 4 != 0)
982 dwRecSize
+= 4 - (dwRecSize
% 4);
986 Buffer
= (BYTE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
990 DPRINT1("Can't allocate heap!\n");
994 pRec
= (PEVENTLOGRECORD
) Buffer
;
995 pRec
->Length
= dwRecSize
;
996 pRec
->Reserved
= LOGFILE_SIGNATURE
;
997 pRec
->RecordNumber
= dwRecordNumber
;
999 GetSystemTime(&SysTime
);
1000 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
1001 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
1003 pRec
->EventID
= dwEventId
;
1004 pRec
->EventType
= wType
;
1005 pRec
->NumStrings
= wNumStrings
;
1006 pRec
->EventCategory
= wCategory
;
1008 pos
= sizeof(EVENTLOGRECORD
);
1010 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
1011 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
1012 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
1013 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
1015 pRec
->UserSidOffset
= pos
;
1019 pos
+= 4 - (pos
% 4);
1020 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1021 pRec
->UserSidLength
= dwSidLength
;
1022 pRec
->UserSidOffset
= pos
;
1026 pRec
->StringOffset
= pos
;
1027 for (i
= 0, str
= lpStrings
, nStrings
= 0; i
< wNumStrings
; i
++)
1029 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1030 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1031 str
+= lstrlenW(str
) + 1;
1034 pRec
->NumStrings
= nStrings
;
1036 pRec
->DataOffset
= pos
;
1039 pRec
->DataLength
= dwDataSize
;
1040 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1045 pos
+= 4 - (pos
% 4);
1047 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1049 *lpRecSize
= dwRecSize
;