2 * PROJECT: ReactOS kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: services/eventlog/file.c
5 * PURPOSE: Event logging service
6 * COPYRIGHT: Copyright 2005 Saveliy Tretiakov
10 /* INCLUDES *****************************************************************/
14 #include <ndk/iofuncs.h>
19 /* GLOBALS ******************************************************************/
21 static LIST_ENTRY LogFileListHead
;
22 static CRITICAL_SECTION LogFileListCs
;
24 /* FUNCTIONS ****************************************************************/
27 LogfInitializeNew(PLOGFILE LogFile
,
31 IO_STATUS_BLOCK IoStatusBlock
;
35 ZeroMemory(&LogFile
->Header
, sizeof(EVENTLOGHEADER
));
36 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
37 SetEndOfFile(LogFile
->hFile
);
39 LogFile
->Header
.HeaderSize
= sizeof(EVENTLOGHEADER
);
40 LogFile
->Header
.Signature
= LOGFILE_SIGNATURE
;
41 LogFile
->Header
.MajorVersion
= MAJORVER
;
42 LogFile
->Header
.MinorVersion
= MINORVER
;
43 LogFile
->Header
.StartOffset
= sizeof(EVENTLOGHEADER
);
44 LogFile
->Header
.EndOffset
= sizeof(EVENTLOGHEADER
);
45 LogFile
->Header
.CurrentRecordNumber
= 1;
46 LogFile
->Header
.OldestRecordNumber
= 1;
47 LogFile
->Header
.MaxSize
= ulMaxSize
;
48 LogFile
->Header
.Flags
= 0;
49 LogFile
->Header
.Retention
= ulRetention
;
50 LogFile
->Header
.EndHeaderSize
= sizeof(EVENTLOGHEADER
);
52 Status
= NtWriteFile(LogFile
->hFile
,
58 sizeof(EVENTLOGHEADER
),
61 if (!NT_SUCCESS(Status
))
63 DPRINT1("NtWriteFile failed (Status 0x%08lx)\n", Status
);
67 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
68 EofRec
.Ones
= 0x11111111;
69 EofRec
.Twos
= 0x22222222;
70 EofRec
.Threes
= 0x33333333;
71 EofRec
.Fours
= 0x44444444;
72 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
73 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
74 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
75 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
76 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
78 Status
= NtWriteFile(LogFile
->hFile
,
87 if (!NT_SUCCESS(Status
))
89 DPRINT1("NtWriteFile failed (Status 0x%08lx)\n", Status
);
93 Status
= NtFlushBuffersFile(LogFile
->hFile
,
95 if (!NT_SUCCESS(Status
))
97 DPRINT1("NtFlushBuffersFile failed (Status 0x%08lx)\n", Status
);
101 return STATUS_SUCCESS
;
106 LogfInitializeExisting(PLOGFILE LogFile
,
110 DWORD dwRecordsNumber
= 0;
111 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
113 PEVENTLOGRECORD RecBuf
;
114 BOOL OvewrWrittenRecords
= FALSE
;
116 DPRINT("Initializing LogFile %S\n",LogFile
->LogName
);
118 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
119 INVALID_SET_FILE_POINTER
)
121 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
122 return STATUS_EVENTLOG_FILE_CORRUPT
;
125 if (!ReadFile(LogFile
->hFile
,
127 sizeof(EVENTLOGHEADER
),
131 DPRINT1("ReadFile failed! %d\n", GetLastError());
132 return STATUS_EVENTLOG_FILE_CORRUPT
;
135 if (dwRead
!= sizeof(EVENTLOGHEADER
))
137 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
138 return STATUS_EVENTLOG_FILE_CORRUPT
;
141 if (LogFile
->Header
.HeaderSize
!= sizeof(EVENTLOGHEADER
) ||
142 LogFile
->Header
.EndHeaderSize
!= sizeof(EVENTLOGHEADER
))
144 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
145 return STATUS_EVENTLOG_FILE_CORRUPT
;
148 if (LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
150 DPRINT("EventLog: Invalid signature %x in %S.\n",
151 LogFile
->Header
.Signature
, LogFile
->FileName
);
152 return STATUS_EVENTLOG_FILE_CORRUPT
;
155 if (LogFile
->Header
.EndOffset
> GetFileSize(LogFile
->hFile
, NULL
) + 1)
157 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
158 LogFile
->Header
.EndOffset
, LogFile
->FileName
);
159 return STATUS_EVENTLOG_FILE_CORRUPT
;
162 /* Set the read location to the oldest record */
163 dwFilePointer
= SetFilePointer(LogFile
->hFile
, LogFile
->Header
.StartOffset
, NULL
, FILE_BEGIN
);
164 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
166 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
167 return STATUS_EVENTLOG_FILE_CORRUPT
;
172 dwFilePointer
= SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
);
174 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
176 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
177 return STATUS_EVENTLOG_FILE_CORRUPT
;
180 /* If the EVENTLOGEOF info has been reached and the oldest record was not immediately after the Header */
181 if ((dwFilePointer
== LogFile
->Header
.EndOffset
) && (LogFile
->Header
.StartOffset
!= sizeof(EVENTLOGHEADER
)))
183 OvewrWrittenRecords
= TRUE
;
184 /* The file has records that overwrote old ones so read them */
185 dwFilePointer
= SetFilePointer(LogFile
->hFile
, sizeof(EVENTLOGHEADER
), NULL
, FILE_BEGIN
);
188 if (!ReadFile(LogFile
->hFile
,
194 DPRINT1("ReadFile failed! %d\n", GetLastError());
195 return STATUS_EVENTLOG_FILE_CORRUPT
;
198 if (dwRead
!= sizeof(dwRecSize
))
201 if (!ReadFile(LogFile
->hFile
,
207 DPRINT1("ReadFile() failed! %d\n", GetLastError());
208 return STATUS_EVENTLOG_FILE_CORRUPT
;
211 if (dwRead
!= sizeof(dwRecSize
))
214 if (dwRecSign
!= LOGFILE_SIGNATURE
||
215 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
) + 1 ||
216 dwRecSize
< sizeof(EVENTLOGRECORD
))
221 if (SetFilePointer(LogFile
->hFile
,
222 -((LONG
) sizeof(DWORD
) * 2),
224 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
226 DPRINT1("SetFilePointer() failed! %d", GetLastError());
227 return STATUS_EVENTLOG_FILE_CORRUPT
;
230 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
233 DPRINT1("Can't allocate heap!\n");
234 return STATUS_NO_MEMORY
;
237 if (!ReadFile(LogFile
->hFile
, RecBuf
, dwRecSize
, &dwRead
, NULL
))
239 DPRINT1("ReadFile() failed! %d\n", GetLastError());
240 HeapFree(MyHeap
, 0, RecBuf
);
241 return STATUS_EVENTLOG_FILE_CORRUPT
;
244 if (dwRead
!= dwRecSize
)
246 HeapFree(MyHeap
, 0, RecBuf
);
250 /* if OvewrWrittenRecords is TRUE and this record has already been read */
251 if ((OvewrWrittenRecords
== TRUE
) && (RecBuf
->RecordNumber
== LogFile
->Header
.OldestRecordNumber
))
253 HeapFree(MyHeap
, 0, RecBuf
);
257 pdwRecSize2
= (PDWORD
) (((PBYTE
) RecBuf
) + dwRecSize
- 4);
259 if (*pdwRecSize2
!= dwRecSize
)
261 DPRINT1("Invalid RecordSizeEnd of record %d (%x) in %S\n",
262 dwRecordsNumber
, *pdwRecSize2
, LogFile
->LogName
);
263 HeapFree(MyHeap
, 0, RecBuf
);
269 if (!LogfAddOffsetInformation(LogFile
,
270 RecBuf
->RecordNumber
,
273 DPRINT1("LogfAddOffsetInformation() failed!\n");
274 HeapFree(MyHeap
, 0, RecBuf
);
275 return STATUS_EVENTLOG_FILE_CORRUPT
;
278 HeapFree(MyHeap
, 0, RecBuf
);
281 LogFile
->Header
.CurrentRecordNumber
= dwRecordsNumber
+ LogFile
->Header
.OldestRecordNumber
;
282 if (LogFile
->Header
.CurrentRecordNumber
== 0)
283 LogFile
->Header
.CurrentRecordNumber
= 1;
287 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
288 INVALID_SET_FILE_POINTER
)
290 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
291 return STATUS_EVENTLOG_FILE_CORRUPT
;
294 if (!WriteFile(LogFile
->hFile
,
296 sizeof(EVENTLOGHEADER
),
300 DPRINT1("WriteFile failed! %d\n", GetLastError());
301 return STATUS_EVENTLOG_FILE_CORRUPT
;
304 if (!FlushFileBuffers(LogFile
->hFile
))
306 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
307 return STATUS_EVENTLOG_FILE_CORRUPT
;
311 return STATUS_SUCCESS
;
316 LogfCreate(PLOGFILE
*LogFile
,
318 PUNICODE_STRING FileName
,
324 OBJECT_ATTRIBUTES ObjectAttributes
;
325 IO_STATUS_BLOCK IoStatusBlock
;
327 BOOL bCreateNew
= FALSE
;
328 NTSTATUS Status
= STATUS_SUCCESS
;
330 pLogFile
= (LOGFILE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(LOGFILE
));
333 DPRINT1("Can't allocate heap!\n");
334 return STATUS_NO_MEMORY
;
337 InitializeObjectAttributes(&ObjectAttributes
,
339 OBJ_CASE_INSENSITIVE
,
343 Status
= NtCreateFile(&pLogFile
->hFile
,
344 Backup
? (GENERIC_READ
| SYNCHRONIZE
) : (GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
),
348 FILE_ATTRIBUTE_NORMAL
,
350 Backup
? FILE_OPEN
: FILE_OPEN_IF
,
351 FILE_SYNCHRONOUS_IO_NONALERT
,
354 if (!NT_SUCCESS(Status
))
356 DPRINT1("Can't create file %wZ (Status: 0x%08lx)\n", FileName
, Status
);
360 bCreateNew
= (IoStatusBlock
.Information
== FILE_CREATED
) ? TRUE
: FALSE
;
363 (WCHAR
*) HeapAlloc(MyHeap
,
365 (lstrlenW(LogName
) + 1) * sizeof(WCHAR
));
366 if (pLogFile
->LogName
== NULL
)
368 DPRINT1("Can't allocate heap\n");
369 Status
= STATUS_NO_MEMORY
;
374 StringCchCopy(pLogFile
->LogName
,lstrlenW(LogName
) + 1, LogName
);
377 (WCHAR
*) HeapAlloc(MyHeap
,
379 (lstrlenW(FileName
->Buffer
) + 1) * sizeof(WCHAR
));
380 if (pLogFile
->FileName
== NULL
)
382 DPRINT1("Can't allocate heap\n");
383 Status
= STATUS_NO_MEMORY
;
387 StringCchCopy(pLogFile
->FileName
, lstrlenW(FileName
->Buffer
) + 1, FileName
->Buffer
);
389 pLogFile
->OffsetInfo
=
390 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
392 sizeof(EVENT_OFFSET_INFO
) * 64);
393 if (pLogFile
->OffsetInfo
== NULL
)
395 DPRINT1("Can't allocate heap\n");
396 Status
= STATUS_NO_MEMORY
;
400 pLogFile
->OffsetInfoSize
= 64;
402 pLogFile
->Permanent
= Permanent
;
405 Status
= LogfInitializeNew(pLogFile
, ulMaxSize
, ulRetention
);
407 Status
= LogfInitializeExisting(pLogFile
, Backup
);
409 if (!NT_SUCCESS(Status
))
412 RtlInitializeResource(&pLogFile
->Lock
);
414 LogfListAddItem(pLogFile
);
417 if (!NT_SUCCESS(Status
))
419 if ((pLogFile
->hFile
!= NULL
) && (pLogFile
->hFile
!= INVALID_HANDLE_VALUE
))
420 CloseHandle(pLogFile
->hFile
);
422 if (pLogFile
->OffsetInfo
)
423 HeapFree(MyHeap
, 0, pLogFile
->OffsetInfo
);
425 if (pLogFile
->FileName
)
426 HeapFree(MyHeap
, 0, pLogFile
->FileName
);
428 if (pLogFile
->LogName
)
429 HeapFree(MyHeap
, 0, pLogFile
->LogName
);
431 HeapFree(MyHeap
, 0, pLogFile
);
443 LogfClose(PLOGFILE LogFile
,
449 if ((ForceClose
== FALSE
) &&
450 (LogFile
->Permanent
== TRUE
))
453 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
455 FlushFileBuffers(LogFile
->hFile
);
456 CloseHandle(LogFile
->hFile
);
457 LogfListRemoveItem(LogFile
);
459 RtlDeleteResource(&LogFile
->Lock
);
461 HeapFree(MyHeap
, 0, LogFile
->LogName
);
462 HeapFree(MyHeap
, 0, LogFile
->FileName
);
463 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
464 HeapFree(MyHeap
, 0, LogFile
);
469 VOID
LogfCloseAll(VOID
)
471 while (!IsListEmpty(&LogFileListHead
))
473 LogfClose(LogfListHead(), TRUE
);
476 DeleteCriticalSection(&LogFileListCs
);
479 VOID
LogfListInitialize(VOID
)
481 InitializeCriticalSection(&LogFileListCs
);
482 InitializeListHead(&LogFileListHead
);
485 PLOGFILE
LogfListHead(VOID
)
487 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
490 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
492 PLIST_ENTRY CurrentEntry
;
493 PLOGFILE Result
= NULL
;
495 EnterCriticalSection(&LogFileListCs
);
497 CurrentEntry
= LogFileListHead
.Flink
;
498 while (CurrentEntry
!= &LogFileListHead
)
500 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
504 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
510 CurrentEntry
= CurrentEntry
->Flink
;
513 LeaveCriticalSection(&LogFileListCs
);
517 /* Index starting from 1 */
518 INT
LogfListItemIndexByName(WCHAR
* Name
)
520 PLIST_ENTRY CurrentEntry
;
524 EnterCriticalSection(&LogFileListCs
);
526 CurrentEntry
= LogFileListHead
.Flink
;
527 while (CurrentEntry
!= &LogFileListHead
)
529 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
533 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
539 CurrentEntry
= CurrentEntry
->Flink
;
543 LeaveCriticalSection(&LogFileListCs
);
547 /* Index starting from 1 */
548 PLOGFILE
LogfListItemByIndex(INT Index
)
550 PLIST_ENTRY CurrentEntry
;
551 PLOGFILE Result
= NULL
;
554 EnterCriticalSection(&LogFileListCs
);
556 CurrentEntry
= LogFileListHead
.Flink
;
557 while (CurrentEntry
!= &LogFileListHead
)
561 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
565 CurrentEntry
= CurrentEntry
->Flink
;
569 LeaveCriticalSection(&LogFileListCs
);
573 INT
LogfListItemCount(VOID
)
575 PLIST_ENTRY CurrentEntry
;
578 EnterCriticalSection(&LogFileListCs
);
580 CurrentEntry
= LogFileListHead
.Flink
;
581 while (CurrentEntry
!= &LogFileListHead
)
583 CurrentEntry
= CurrentEntry
->Flink
;
587 LeaveCriticalSection(&LogFileListCs
);
591 VOID
LogfListAddItem(PLOGFILE Item
)
593 EnterCriticalSection(&LogFileListCs
);
594 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
595 LeaveCriticalSection(&LogFileListCs
);
598 VOID
LogfListRemoveItem(PLOGFILE Item
)
600 EnterCriticalSection(&LogFileListCs
);
601 RemoveEntryList(&Item
->ListEntry
);
602 LeaveCriticalSection(&LogFileListCs
);
606 ReadAnsiLogEntry(HANDLE hFile
,
608 DWORD nNumberOfBytesToRead
,
609 LPDWORD lpNumberOfBytesRead
)
614 UNICODE_STRING StringW
;
619 LPVOID lpUnicodeBuffer
= NULL
;
628 *lpNumberOfBytesRead
= 0;
630 lpUnicodeBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nNumberOfBytesToRead
);
631 if (lpUnicodeBuffer
== NULL
)
633 DPRINT1("Alloc failed!\n");
637 if (!ReadFile(hFile
, lpUnicodeBuffer
, nNumberOfBytesToRead
, &dwRead
, NULL
))
639 DPRINT1("Read failed!\n");
644 Dst
= (PEVENTLOGRECORD
)lpBuffer
;
645 Src
= (PEVENTLOGRECORD
)lpUnicodeBuffer
;
647 Dst
->TimeGenerated
= Src
->TimeGenerated
;
648 Dst
->Reserved
= Src
->Reserved
;
649 Dst
->RecordNumber
= Src
->RecordNumber
;
650 Dst
->TimeWritten
= Src
->TimeWritten
;
651 Dst
->EventID
= Src
->EventID
;
652 Dst
->EventType
= Src
->EventType
;
653 Dst
->EventCategory
= Src
->EventCategory
;
654 Dst
->NumStrings
= Src
->NumStrings
;
655 Dst
->UserSidLength
= Src
->UserSidLength
;
656 Dst
->DataLength
= Src
->DataLength
;
658 SrcPtr
= (LPWSTR
)((DWORD_PTR
)Src
+ sizeof(EVENTLOGRECORD
));
659 DstPtr
= (LPSTR
)((DWORD_PTR
)Dst
+ sizeof(EVENTLOGRECORD
));
661 /* Convert the module name */
662 RtlInitUnicodeString(&StringW
, SrcPtr
);
663 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
664 if (NT_SUCCESS(Status
))
666 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
668 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
670 RtlFreeAnsiString(&StringA
);
673 /* Convert the computer name */
674 if (NT_SUCCESS(Status
))
676 SrcPtr
= (PWSTR
)((DWORD_PTR
)SrcPtr
+ StringW
.MaximumLength
);
678 RtlInitUnicodeString(&StringW
, SrcPtr
);
679 Status
= RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
680 if (NT_SUCCESS(Status
))
682 RtlCopyMemory(DstPtr
, StringA
.Buffer
, StringA
.MaximumLength
);
684 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ StringA
.MaximumLength
);
686 RtlFreeAnsiString(&StringA
);
690 /* Add the padding and the User SID*/
691 if (NT_SUCCESS(Status
))
693 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
) % sizeof(DWORD
));
694 RtlZeroMemory(DstPtr
, dwPadding
);
696 DstPtr
= (LPSTR
)((DWORD_PTR
)DstPtr
+ dwPadding
);
697 RtlCopyMemory(DstPtr
,
698 (PVOID
)((DWORD_PTR
)Src
+ Src
->UserSidOffset
),
701 Dst
->UserSidOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
705 /* Convert the strings */
706 if (NT_SUCCESS(Status
))
708 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->UserSidLength
);
710 SrcString
= (LPWSTR
)((DWORD_PTR
)Src
+ (DWORD
)Src
->StringOffset
);
711 DstString
= (LPSTR
)DstPtr
;
713 for (i
= 0; i
< Dst
->NumStrings
; i
++)
715 RtlInitUnicodeString(&StringW
, SrcString
);
717 RtlUnicodeStringToAnsiString(&StringA
, &StringW
, TRUE
);
719 RtlCopyMemory(DstString
, StringA
.Buffer
, StringA
.MaximumLength
);
721 SrcString
= (LPWSTR
)((DWORD_PTR
)SrcString
+
722 (DWORD
)StringW
.MaximumLength
);
724 DstString
= (LPSTR
)((DWORD_PTR
)DstString
+
725 (DWORD
)StringA
.MaximumLength
);
727 RtlFreeAnsiString(&StringA
);
730 Dst
->StringOffset
= (DWORD
)((DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
);
733 /* Copy the binary data */
734 DstPtr
= (PVOID
)DstString
;
735 Dst
->DataOffset
= (DWORD_PTR
)DstPtr
- (DWORD_PTR
)Dst
;
737 RtlCopyMemory(DstPtr
, (PVOID
)((DWORD_PTR
)Src
+ Src
->DataOffset
), Src
->DataLength
);
739 /* Add the padding */
740 DstPtr
= (PVOID
)((DWORD_PTR
)DstPtr
+ Src
->DataLength
);
741 dwPadding
= sizeof(DWORD
) - (((DWORD_PTR
)DstPtr
-(DWORD_PTR
)Dst
) % sizeof(DWORD
));
742 RtlZeroMemory(DstPtr
, dwPadding
);
744 dwEntryLength
= (DWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
+ sizeof(DWORD
) - (DWORD_PTR
)Dst
);
746 /* Set the entry length at the end of the entry*/
747 pLength
= (PDWORD
)((DWORD_PTR
)DstPtr
+ dwPadding
);
748 *pLength
= dwEntryLength
;
749 Dst
->Length
= dwEntryLength
;
751 *lpNumberOfBytesRead
= dwEntryLength
;
755 if (lpUnicodeBuffer
!= NULL
)
756 HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer
);
762 DWORD
LogfReadEvent(PLOGFILE LogFile
,
764 DWORD
* RecordNumber
,
771 DWORD dwOffset
, dwRead
, dwRecSize
;
772 DWORD dwBufferUsage
= 0, dwRecNum
;
774 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
775 return ERROR_INVALID_PARAMETER
;
777 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
778 return ERROR_INVALID_PARAMETER
;
780 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
781 return ERROR_INVALID_PARAMETER
;
783 if ((*RecordNumber
==0) && !(EVENTLOG_SEQUENTIAL_READ
))
785 return ERROR_INVALID_PARAMETER
;
788 dwRecNum
= *RecordNumber
;
790 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
795 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
799 RtlReleaseResource(&LogFile
->Lock
);
800 return ERROR_HANDLE_EOF
;
803 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
804 INVALID_SET_FILE_POINTER
)
806 DPRINT1("SetFilePointer() failed!\n");
810 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
812 DPRINT1("ReadFile() failed!\n");
816 if (dwRecSize
> BufSize
)
818 *BytesNeeded
= dwRecSize
;
819 RtlReleaseResource(&LogFile
->Lock
);
820 return ERROR_INSUFFICIENT_BUFFER
;
823 if (SetFilePointer(LogFile
->hFile
,
824 -((LONG
) sizeof(DWORD
)),
826 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
828 DPRINT1("SetFilePointer() failed!\n");
834 if (!ReadAnsiLogEntry(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
))
836 DPRINT1("ReadAnsiLogEntry() failed!\n");
842 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
844 DPRINT1("ReadFile() failed!\n");
849 dwBufferUsage
+= dwRead
;
851 while (dwBufferUsage
<= BufSize
)
853 if (Flags
& EVENTLOG_FORWARDS_READ
)
858 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
862 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
863 INVALID_SET_FILE_POINTER
)
865 DPRINT1("SetFilePointer() failed!\n");
869 if (!ReadFile(LogFile
->hFile
,
875 DPRINT1("ReadFile() failed!\n");
879 if (dwBufferUsage
+ dwRecSize
> BufSize
)
882 if (SetFilePointer(LogFile
->hFile
,
883 -((LONG
) sizeof(DWORD
)),
885 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
887 DPRINT1("SetFilePointer() failed!\n");
893 if (!ReadAnsiLogEntry(LogFile
->hFile
,
894 Buffer
+ dwBufferUsage
,
898 DPRINT1("ReadAnsiLogEntry() failed!\n");
904 if (!ReadFile(LogFile
->hFile
,
905 Buffer
+ dwBufferUsage
,
910 DPRINT1("ReadFile() failed!\n");
915 dwBufferUsage
+= dwRead
;
918 *BytesRead
= dwBufferUsage
;
919 * RecordNumber
= dwRecNum
;
920 RtlReleaseResource(&LogFile
->Lock
);
921 return ERROR_SUCCESS
;
924 DPRINT1("LogfReadEvent failed with %x\n",GetLastError());
925 RtlReleaseResource(&LogFile
->Lock
);
926 return GetLastError();
929 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
935 PEVENTLOGRECORD RecBuf
;
936 LARGE_INTEGER logFileSize
;
944 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
946 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
948 if (!GetFileSizeEx(LogFile
->hFile
, &logFileSize
))
950 RtlReleaseResource(&LogFile
->Lock
);
954 /* If the size of the file is over MaxSize */
955 if ((logFileSize
.QuadPart
+ BufSize
)> LogFile
->Header
.MaxSize
)
957 ULONG OverWriteLength
= 0;
958 WriteOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
959 RecBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(EVENTLOGRECORD
));
960 /* Determine how many records need to be overwritten */
963 DPRINT("EventLogFile has reached maximume size\n");
967 DPRINT1("Failed to allocate buffer for OldestRecord!\n");
968 HeapFree(GetProcessHeap(), 0, RecBuf
);
969 RtlReleaseResource(&LogFile
->Lock
);
973 /* Get the oldest record data */
974 RecOffSet
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
976 if (SetFilePointer(LogFile
->hFile
,
979 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
981 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
982 HeapFree(GetProcessHeap(), 0, RecBuf
);
983 RtlReleaseResource(&LogFile
->Lock
);
987 if (!ReadFile(LogFile
->hFile
, RecBuf
, sizeof(EVENTLOGRECORD
), &dwRead
, NULL
))
989 DPRINT1("ReadFile() failed!\n");
990 HeapFree(GetProcessHeap(), 0, RecBuf
);
991 RtlReleaseResource(&LogFile
->Lock
);
995 if (RecBuf
->Reserved
!= LOGFILE_SIGNATURE
)
997 DPRINT1("LogFile corrupt!\n");
998 HeapFree(GetProcessHeap(), 0, RecBuf
);
999 RtlReleaseResource(&LogFile
->Lock
);
1003 LogfDeleteOffsetInformation(LogFile
,LogFile
->Header
.OldestRecordNumber
);
1005 LogFile
->Header
.OldestRecordNumber
++;
1007 OverWriteLength
+= RecBuf
->Length
;
1008 /* Check the size of the record as the record adding may be larger */
1009 if (OverWriteLength
>= BufSize
)
1011 DPRINT("Record will fit. Length %d, BufSize %d\n", OverWriteLength
, BufSize
);
1012 LogFile
->Header
.StartOffset
= LogfOffsetByNumber(LogFile
, LogFile
->Header
.OldestRecordNumber
);
1016 HeapFree(GetProcessHeap(), 0, RecBuf
);
1019 WriteOffSet
= LogFile
->Header
.EndOffset
;
1021 if (SetFilePointer(LogFile
->hFile
,
1024 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1026 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1027 RtlReleaseResource(&LogFile
->Lock
);
1031 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
1033 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1034 RtlReleaseResource(&LogFile
->Lock
);
1038 if (!LogfAddOffsetInformation(LogFile
,
1039 LogFile
->Header
.CurrentRecordNumber
,
1042 RtlReleaseResource(&LogFile
->Lock
);
1046 LogFile
->Header
.CurrentRecordNumber
++;
1048 if (WriteOffSet
== LogFile
->Header
.EndOffset
)
1050 LogFile
->Header
.EndOffset
+= dwWritten
;
1052 if (SetFilePointer(LogFile
->hFile
,
1053 LogFile
->Header
.EndOffset
,
1055 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1057 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1058 RtlReleaseResource(&LogFile
->Lock
);
1062 EofRec
.Ones
= 0x11111111;
1063 EofRec
.Twos
= 0x22222222;
1064 EofRec
.Threes
= 0x33333333;
1065 EofRec
.Fours
= 0x44444444;
1066 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1067 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1068 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1069 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1070 EofRec
.BeginRecord
= LogFile
->Header
.StartOffset
;
1071 EofRec
.EndRecord
= LogFile
->Header
.EndOffset
;
1073 if (!WriteFile(LogFile
->hFile
,
1075 sizeof(EVENTLOGEOF
),
1079 DPRINT1("WriteFile() failed! %d\n", GetLastError());
1080 RtlReleaseResource(&LogFile
->Lock
);
1084 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
1085 INVALID_SET_FILE_POINTER
)
1087 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
1088 RtlReleaseResource(&LogFile
->Lock
);
1092 if (!WriteFile(LogFile
->hFile
,
1094 sizeof(EVENTLOGHEADER
),
1098 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
1099 RtlReleaseResource(&LogFile
->Lock
);
1103 if (!FlushFileBuffers(LogFile
->hFile
))
1105 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
1106 RtlReleaseResource(&LogFile
->Lock
);
1110 RtlReleaseResource(&LogFile
->Lock
);
1116 LogfClearFile(PLOGFILE LogFile
,
1117 PUNICODE_STRING BackupFileName
)
1121 RtlAcquireResourceExclusive(&LogFile
->Lock
, TRUE
);
1123 if (BackupFileName
->Length
> 0)
1125 /* Write a backup file */
1126 Status
= LogfBackupFile(LogFile
,
1128 if (!NT_SUCCESS(Status
))
1130 DPRINT1("LogfBackupFile failed (Status: 0x%08lx)\n", Status
);
1135 Status
= LogfInitializeNew(LogFile
,
1136 LogFile
->Header
.MaxSize
,
1137 LogFile
->Header
.Retention
);
1138 if (!NT_SUCCESS(Status
))
1140 DPRINT1("LogfInitializeNew failed (Status: 0x%08lx)\n", Status
);
1143 RtlReleaseResource(&LogFile
->Lock
);
1150 LogfBackupFile(PLOGFILE LogFile
,
1151 PUNICODE_STRING BackupFileName
)
1153 OBJECT_ATTRIBUTES ObjectAttributes
;
1154 IO_STATUS_BLOCK IoStatusBlock
;
1155 EVENTLOGHEADER Header
;
1157 HANDLE FileHandle
= NULL
;
1159 LARGE_INTEGER FileOffset
;
1161 PUCHAR Buffer
= NULL
;
1163 DWORD dwOffset
, dwRead
, dwRecSize
;
1165 DPRINT1("LogfBackupFile(%p, %wZ)\n", LogFile
, BackupFileName
);
1167 /* Lock the log file shared */
1168 RtlAcquireResourceShared(&LogFile
->Lock
, TRUE
);
1170 InitializeObjectAttributes(&ObjectAttributes
,
1172 OBJ_CASE_INSENSITIVE
,
1176 Status
= NtCreateFile(&FileHandle
,
1177 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
1181 FILE_ATTRIBUTE_NORMAL
,
1184 FILE_WRITE_THROUGH
| FILE_SYNCHRONOUS_IO_NONALERT
,
1187 if (!NT_SUCCESS(Status
))
1189 DPRINT("Can't create backup file %wZ (Status: 0x%08lx)\n", BackupFileName
, Status
);
1193 /* Initialize the (dirty) log file header */
1194 Header
.HeaderSize
= sizeof(EVENTLOGHEADER
);
1195 Header
.Signature
= LOGFILE_SIGNATURE
;
1196 Header
.MajorVersion
= MAJORVER
;
1197 Header
.MinorVersion
= MINORVER
;
1198 Header
.StartOffset
= sizeof(EVENTLOGHEADER
);
1199 Header
.EndOffset
= sizeof(EVENTLOGHEADER
);
1200 Header
.CurrentRecordNumber
= 1;
1201 Header
.OldestRecordNumber
= 1;
1202 Header
.MaxSize
= LogFile
->Header
.MaxSize
;
1203 Header
.Flags
= ELF_LOGFILE_HEADER_DIRTY
;
1204 Header
.Retention
= LogFile
->Header
.Retention
;
1205 Header
.EndHeaderSize
= sizeof(EVENTLOGHEADER
);
1207 /* Write the (dirty) log file header */
1208 Status
= NtWriteFile(FileHandle
,
1214 sizeof(EVENTLOGHEADER
),
1217 if (!NT_SUCCESS(Status
))
1219 DPRINT1("Failed to write the log file header (Status: 0x%08lx)\n", Status
);
1223 for (i
= LogFile
->Header
.OldestRecordNumber
; i
< LogFile
->Header
.CurrentRecordNumber
; i
++)
1225 dwOffset
= LogfOffsetByNumber(LogFile
, i
);
1229 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1231 DPRINT1("SetFilePointer() failed!\n");
1235 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
1237 DPRINT1("ReadFile() failed!\n");
1241 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
1243 DPRINT1("SetFilePointer() failed!\n");
1247 Buffer
= HeapAlloc(MyHeap
, 0, dwRecSize
);
1250 DPRINT1("HeapAlloc() failed!\n");
1254 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
1256 DPRINT1("ReadFile() failed!\n");
1260 /* Write the event record */
1261 Status
= NtWriteFile(FileHandle
,
1270 if (!NT_SUCCESS(Status
))
1272 DPRINT1("NtWriteFile() failed! (Status: 0x%08lx)\n", Status
);
1276 /* Update the header information */
1277 Header
.EndOffset
+= dwRecSize
;
1279 /* Free the buffer */
1280 HeapFree(MyHeap
, 0, Buffer
);
1284 /* Initialize the EOF record */
1285 EofRec
.RecordSizeBeginning
= sizeof(EVENTLOGEOF
);
1286 EofRec
.Ones
= 0x11111111;
1287 EofRec
.Twos
= 0x22222222;
1288 EofRec
.Threes
= 0x33333333;
1289 EofRec
.Fours
= 0x44444444;
1290 EofRec
.BeginRecord
= sizeof(EVENTLOGHEADER
);
1291 EofRec
.EndRecord
= Header
.EndOffset
;
1292 EofRec
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1293 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1294 EofRec
.RecordSizeEnd
= sizeof(EVENTLOGEOF
);
1296 /* Write the EOF record */
1297 Status
= NtWriteFile(FileHandle
,
1303 sizeof(EVENTLOGEOF
),
1306 if (!NT_SUCCESS(Status
))
1308 DPRINT1("NtWriteFile() failed!\n");
1312 /* Update the header information */
1313 Header
.CurrentRecordNumber
= LogFile
->Header
.CurrentRecordNumber
;
1314 Header
.OldestRecordNumber
= LogFile
->Header
.OldestRecordNumber
;
1315 Header
.MaxSize
= Header
.EndOffset
+ sizeof(EVENTLOGEOF
);
1318 /* Write the (clean) log file header */
1319 FileOffset
.QuadPart
= 0;
1320 Status
= NtWriteFile(FileHandle
,
1326 sizeof(EVENTLOGHEADER
),
1329 if (!NT_SUCCESS(Status
))
1331 DPRINT1("NtWriteFile() failed! (Status: 0x%08lx)\n", Status
);
1335 /* Free the buffer */
1337 HeapFree(MyHeap
, 0, Buffer
);
1339 /* Close the backup file */
1340 if (FileHandle
!= NULL
)
1341 NtClose(FileHandle
);
1343 /* Unlock the log file */
1344 RtlReleaseResource(&LogFile
->Lock
);
1350 /* Returns 0 if nothing found. */
1351 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
1355 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
1357 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
1358 return LogFile
->OffsetInfo
[i
].EventOffset
;
1363 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
1365 return LogFile
->Header
.OldestRecordNumber
;
1368 DWORD
LogfGetCurrentRecord(PLOGFILE LogFile
)
1370 return LogFile
->Header
.CurrentRecordNumber
;
1373 BOOL
LogfDeleteOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
)
1377 if (ulNumber
!= LogFile
->OffsetInfo
[0].EventNumber
)
1382 for (i
= 0; i
< LogFile
->OffsetInfoNext
- 1; i
++)
1384 LogFile
->OffsetInfo
[i
].EventNumber
= LogFile
->OffsetInfo
[i
+ 1].EventNumber
;
1385 LogFile
->OffsetInfo
[i
].EventOffset
= LogFile
->OffsetInfo
[i
+ 1].EventOffset
;
1387 LogFile
->OffsetInfoNext
--;
1391 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
1393 LPVOID NewOffsetInfo
;
1395 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
1397 NewOffsetInfo
= HeapReAlloc(MyHeap
,
1399 LogFile
->OffsetInfo
,
1400 (LogFile
->OffsetInfoSize
+ 64) *
1401 sizeof(EVENT_OFFSET_INFO
));
1405 DPRINT1("Can't reallocate heap.\n");
1409 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
1410 LogFile
->OffsetInfoSize
+= 64;
1413 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
1414 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
1415 LogFile
->OffsetInfoNext
++;
1420 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
1421 DWORD dwRecordNumber
,
1426 LPCWSTR ComputerName
,
1435 PEVENTLOGRECORD pRec
;
1442 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
1443 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
1445 if (dwRecSize
% 4 != 0)
1446 dwRecSize
+= 4 - (dwRecSize
% 4);
1448 dwRecSize
+= dwSidLength
;
1450 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1452 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1453 str
+= lstrlenW(str
) + 1;
1456 dwRecSize
+= dwDataSize
;
1457 if (dwRecSize
% 4 != 0)
1458 dwRecSize
+= 4 - (dwRecSize
% 4);
1462 Buffer
= HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
1466 DPRINT1("Can't allocate heap!\n");
1470 pRec
= (PEVENTLOGRECORD
) Buffer
;
1471 pRec
->Length
= dwRecSize
;
1472 pRec
->Reserved
= LOGFILE_SIGNATURE
;
1473 pRec
->RecordNumber
= dwRecordNumber
;
1475 GetSystemTime(&SysTime
);
1476 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
1477 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
1479 pRec
->EventID
= dwEventId
;
1480 pRec
->EventType
= wType
;
1481 pRec
->EventCategory
= wCategory
;
1483 pos
= sizeof(EVENTLOGRECORD
);
1485 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
1486 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
1487 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
1488 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
1490 pRec
->UserSidOffset
= pos
;
1493 pos
+= 4 - (pos
% 4);
1497 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
1498 pRec
->UserSidLength
= dwSidLength
;
1499 pRec
->UserSidOffset
= pos
;
1503 pRec
->StringOffset
= pos
;
1504 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
1506 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
1507 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1508 str
+= lstrlenW(str
) + 1;
1510 pRec
->NumStrings
= wNumStrings
;
1512 pRec
->DataOffset
= pos
;
1515 pRec
->DataLength
= dwDataSize
;
1516 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
1521 pos
+= 4 - (pos
% 4);
1523 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
1525 *lpRecSize
= dwRecSize
;
1531 LogfReportEvent(WORD wType
,
1539 WCHAR szComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1540 DWORD dwComputerNameLength
= MAX_COMPUTERNAME_LENGTH
+ 1;
1541 PEVENTSOURCE pEventSource
= NULL
;
1547 if (!GetComputerNameW(szComputerName
, &dwComputerNameLength
))
1549 szComputerName
[0] = 0;
1552 pEventSource
= GetEventSourceByName(L
"EventLog");
1553 if (pEventSource
== NULL
)
1558 lastRec
= LogfGetCurrentRecord(pEventSource
->LogFile
);
1560 logBuffer
= LogfAllocAndBuildNewRecord(&recSize
,
1565 pEventSource
->szName
,
1566 (LPCWSTR
)szComputerName
,
1574 dwError
= LogfWriteData(pEventSource
->LogFile
, recSize
, logBuffer
);
1577 DPRINT1("ERROR WRITING TO EventLog %S\n", pEventSource
->LogFile
->FileName
);
1580 LogfFreeRecord(logBuffer
);