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
11 PLOGFILE LogListHead
= NULL
;
12 CRITICAL_SECTION LogListCs
;
15 BOOL
LogfInitializeNew(PLOGFILE LogFile
)
20 ZeroMemory(&LogFile
->Header
, sizeof(FILE_HEADER
));
21 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
22 SetEndOfFile(LogFile
->hFile
);
24 LogFile
->Header
.SizeOfHeader
= sizeof(FILE_HEADER
);
25 LogFile
->Header
.SizeOfHeader2
= sizeof(FILE_HEADER
);
26 LogFile
->Header
.FirstRecordOffset
= sizeof(FILE_HEADER
);
27 LogFile
->Header
.EofOffset
= sizeof(FILE_HEADER
);
28 LogFile
->Header
.MajorVersion
= MAJORVER
;
29 LogFile
->Header
.MinorVersion
= MINORVER
;
30 LogFile
->Header
.NextRecord
= 1;
32 LogFile
->Header
.Signature
= LOGFILE_SIGNATURE
;
33 if(!WriteFile(LogFile
->hFile
,
39 DPRINT1("WriteFile failed:%d!\n", GetLastError());
43 EofRec
.Ones
= 0x11111111;
44 EofRec
.Twos
= 0x22222222;
45 EofRec
.Threes
= 0x33333333;
46 EofRec
.Fours
= 0x44444444;
47 EofRec
.Size1
= sizeof(EOF_RECORD
);
48 EofRec
.Size2
= sizeof(EOF_RECORD
);
49 EofRec
.NextRecordNumber
= LogFile
->Header
.NextRecord
;
50 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecord
;
51 EofRec
.StartOffset
= LogFile
->Header
.FirstRecordOffset
;
52 EofRec
.EndOffset
= LogFile
->Header
.EofOffset
;
54 if(!WriteFile(LogFile
->hFile
,
60 DPRINT1("WriteFile failed:%d!\n", GetLastError());
64 if(!FlushFileBuffers(LogFile
->hFile
))
66 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
73 BOOL
LogfInitializeExisting(PLOGFILE LogFile
)
76 DWORD dwRecordsNumber
= 0;
77 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
79 PEVENTLOGRECORD RecBuf
;
81 if(SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
82 INVALID_SET_FILE_POINTER
)
84 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
88 if(!ReadFile(LogFile
->hFile
,
93 DPRINT1("ReadFile failed! %d\n", GetLastError());
97 if(dwRead
!= sizeof(FILE_HEADER
))
99 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
100 return LogfInitializeNew(LogFile
);
103 if(LogFile
->Header
.SizeOfHeader
!= sizeof(FILE_HEADER
) ||
104 LogFile
->Header
.SizeOfHeader2
!= sizeof(FILE_HEADER
))
106 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
107 return LogfInitializeNew(LogFile
);
110 if(LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
112 DPRINT("EventLog: Invalid signature %x in %S.\n",
113 LogFile
->Header
.Signature
,
115 return LogfInitializeNew(LogFile
);
118 if(LogFile
->Header
.EofOffset
> GetFileSize(LogFile
->hFile
, NULL
)+1)
120 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
121 LogFile
->Header
.EofOffset
,
123 return LogfInitializeNew(LogFile
);
128 dwFilePointer
= SetFilePointer(LogFile
->hFile
,
133 if(dwFilePointer
== INVALID_SET_FILE_POINTER
)
135 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
139 if(!ReadFile(LogFile
->hFile
,
145 DPRINT1("ReadFile failed! %d\n", GetLastError());
149 if(dwRead
!= sizeof(dwRecSize
))
152 if(!ReadFile(LogFile
->hFile
,
158 DPRINT1("ReadFile() failed! %d\n", GetLastError());
162 if(dwRead
!= sizeof(dwRecSize
))
165 if(dwRecSign
!= LOGFILE_SIGNATURE
||
166 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
)+1 ||
167 dwRecSize
< sizeof(EVENTLOGRECORD
))
172 if(SetFilePointer(LogFile
->hFile
,
173 -((LONG
)sizeof(DWORD
)*2),
175 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
177 DPRINT1("SetFilePointer() failed! %d", GetLastError());
181 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
185 DPRINT1("Can't allocate heap!\n");
189 if(!ReadFile(LogFile
->hFile
,
195 DPRINT1("ReadFile() failed! %d\n", GetLastError());
196 HeapFree(MyHeap
, 0, RecBuf
);
200 if(dwRead
!= dwRecSize
)
202 HeapFree(MyHeap
, 0, RecBuf
);
206 pdwRecSize2
= (PDWORD
)(((PBYTE
)RecBuf
)+dwRecSize
-4);
207 if(*pdwRecSize2
!= dwRecSize
)
209 DPRINT1("Invalid size2 of record %d (%x) in %s\n",
213 HeapFree(MyHeap
, 0, RecBuf
);
219 if(!LogfAddOffsetInformation(LogFile
, RecBuf
->RecordNumber
, dwFilePointer
))
221 DPRINT1("LogfAddOffsetInformation() failed!\n");
222 HeapFree(MyHeap
, 0, RecBuf
);
226 HeapFree(MyHeap
, 0, RecBuf
);
229 LogFile
->Header
.NextRecord
= dwRecordsNumber
+1;
230 LogFile
->Header
.OldestRecord
= dwRecordsNumber
? 1 : 0; //FIXME
232 if(!SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
) ==
233 INVALID_SET_FILE_POINTER
)
235 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
239 if(!WriteFile(LogFile
->hFile
,
245 DPRINT1("WriteFile failed! %d\n", GetLastError());
249 if(!FlushFileBuffers(LogFile
->hFile
))
251 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
258 PLOGFILE
LogfCreate(WCHAR
*LogName
,
262 BOOL bResult
, bCreateNew
= FALSE
;
264 LogFile
= (LOGFILE
*) HeapAlloc(MyHeap
,
269 DPRINT1("Can't allocate heap!\n");
273 LogFile
->hFile
= CreateFile(FileName
,
274 GENERIC_READ
| GENERIC_WRITE
,
278 FILE_ATTRIBUTE_NORMAL
|
279 FILE_FLAG_RANDOM_ACCESS
,
282 if(LogFile
->hFile
== INVALID_HANDLE_VALUE
)
284 DPRINT1("Can't create file %S.\n", FileName
);
285 HeapFree(MyHeap
, 0, LogFile
);
289 bCreateNew
= (GetLastError() == ERROR_ALREADY_EXISTS
) ? FALSE
: TRUE
;
291 LogFile
->LogName
= (WCHAR
*) HeapAlloc(MyHeap
,
293 (lstrlenW(LogName
)+1)*sizeof(WCHAR
));
295 if(LogFile
->LogName
) lstrcpyW(LogFile
->LogName
, LogName
);
298 DPRINT1("Can't allocate heap\n");
299 HeapFree(MyHeap
, 0, LogFile
);
303 LogFile
->FileName
= (WCHAR
*) HeapAlloc(MyHeap
,
305 (lstrlenW(FileName
)+1)*sizeof(WCHAR
));
307 if(LogFile
->FileName
) lstrcpyW(LogFile
->FileName
, FileName
);
310 DPRINT1("Can't allocate heap\n");
314 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
)
315 HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(EVENT_OFFSET_INFO
)*64);
317 if(!LogFile
->OffsetInfo
)
319 DPRINT1("Can't allocate heap\n");
323 LogFile
->OffsetInfoSize
= 64;
326 bResult
= LogfInitializeNew(LogFile
);
327 else bResult
= LogfInitializeExisting(LogFile
);
329 if(!bResult
) goto fail
;
331 InitializeCriticalSection(&LogFile
->cs
);
332 LogfListAddItem(LogFile
);
338 if(LogFile
->OffsetInfo
) HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
339 if(LogFile
->FileName
) HeapFree(MyHeap
, 0, LogFile
->FileName
);
340 if(LogFile
->LogName
) HeapFree(MyHeap
, 0, LogFile
->LogName
);
341 HeapFree(MyHeap
, 0, LogFile
);
346 VOID
LogfClose(PLOGFILE LogFile
)
351 EnterCriticalSection(&LogFile
->cs
);
353 FlushFileBuffers(LogFile
->hFile
);
354 CloseHandle(LogFile
->hFile
);
356 LogfListRemoveItem(LogFile
);
357 DeleteCriticalSection(&LogFile
->cs
);
359 HeapFree(MyHeap
, 0, LogFile
->LogName
);
360 HeapFree(MyHeap
, 0, LogFile
->FileName
);
361 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
362 HeapFree(MyHeap
, 0, LogFile
);
367 PLOGFILE
LogfListItemByName(WCHAR
*Name
)
369 PLOGFILE Item
, Ret
= NULL
;
371 EnterCriticalSection(&LogListCs
);
373 for(Item
= LogListHead
; Item
; Item
= (PLOGFILE
)Item
->Next
)
374 if(Item
->LogName
&& lstrcmpi(Item
->LogName
, Name
)==0)
380 LeaveCriticalSection(&LogListCs
);
384 /* index starting from 1 */
385 INT
LogfListItemIndexByName(WCHAR
*Name
)
390 EnterCriticalSection(&LogListCs
);
392 for(Item
= LogListHead
; Item
; i
++, Item
= (PLOGFILE
)Item
->Next
)
393 if(Item
->LogName
&& lstrcmpi(Item
->LogName
, Name
)==0)
399 LeaveCriticalSection(&LogListCs
);
403 /* index starting from 1 */
404 PLOGFILE
LogfListItemByIndex(INT Index
)
407 PLOGFILE Item
= LogListHead
;
409 EnterCriticalSection(&LogListCs
);
410 for(; Item
&& i
<Index
; Item
= (PLOGFILE
)Item
->Next
, i
++);
411 LeaveCriticalSection(&LogListCs
);
416 INT
LogfListItemCount()
418 PLOGFILE Item
= LogListHead
;
421 EnterCriticalSection(&LogListCs
);
425 Item
= (PLOGFILE
) Item
->Next
;
427 LeaveCriticalSection(&LogListCs
);
432 VOID
LogfListAddItem(PLOGFILE Item
)
434 EnterCriticalSection(&LogListCs
);
438 PLOGFILE List
= LogListHead
;
441 List
= (PLOGFILE
)List
->Next
;
443 Item
->Prev
= (PVOID
)List
;
454 LeaveCriticalSection(&LogListCs
);
457 VOID
LogfListRemoveItem(PLOGFILE Item
)
459 PLOGFILE prev
= (PLOGFILE
)Item
->Prev
;
460 PLOGFILE next
= (PLOGFILE
)Item
->Next
;
462 EnterCriticalSection(&LogListCs
);
474 else if(prev
) prev
->Next
= NULL
;
475 else LogListHead
= NULL
;
477 LeaveCriticalSection(&LogListCs
);
481 BOOL
LogfReadEvent(PLOGFILE LogFile
,
489 DWORD dwOffset
, dwRead
, dwRecSize
;
490 DWORD dwBufferUsage
= 0, dwRecNum
;
492 if(Flags
& EVENTLOG_FORWARDS_READ
&&
493 Flags
& EVENTLOG_BACKWARDS_READ
)
498 if(!(Flags
& EVENTLOG_FORWARDS_READ
) &&
499 !(Flags
& EVENTLOG_BACKWARDS_READ
))
504 if(!Buffer
|| !BytesRead
|| !BytesNeeded
)
509 dwRecNum
= RecordNumber
;
510 EnterCriticalSection(&LogFile
->cs
);
511 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
515 LeaveCriticalSection(&LogFile
->cs
);
519 if(SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
)
520 == INVALID_SET_FILE_POINTER
)
522 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
523 LeaveCriticalSection(&LogFile
->cs
);
527 if(!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
529 DPRINT1("ReadFile() failed! %d\n", GetLastError());
530 LeaveCriticalSection(&LogFile
->cs
);
534 if(dwRecSize
> BufSize
)
537 *BytesNeeded
= dwRecSize
;
538 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
539 LeaveCriticalSection(&LogFile
->cs
);
543 if(SetFilePointer(LogFile
->hFile
,
544 -((LONG
)sizeof(DWORD
)),
546 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
548 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
549 LeaveCriticalSection(&LogFile
->cs
);
553 if(!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
555 DPRINT1("ReadFile() failed! %d\n", GetLastError());
556 LeaveCriticalSection(&LogFile
->cs
);
560 dwBufferUsage
+=dwRead
;
562 while(dwBufferUsage
<BufSize
)
564 if(Flags
& EVENTLOG_FORWARDS_READ
)
568 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
571 if(SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
)
572 == INVALID_SET_FILE_POINTER
)
574 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
575 LeaveCriticalSection(&LogFile
->cs
);
579 if(!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
581 DPRINT1("ReadFile() failed! %d\n", GetLastError());
582 LeaveCriticalSection(&LogFile
->cs
);
586 if(dwBufferUsage
+dwRecSize
>BufSize
)break;
588 if(SetFilePointer(LogFile
->hFile
,
589 -((LONG
)sizeof(DWORD
)),
591 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
593 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
594 LeaveCriticalSection(&LogFile
->cs
);
598 if(!ReadFile(LogFile
->hFile
,
599 Buffer
+dwBufferUsage
,
604 DPRINT1("ReadFile() failed! %d\n", GetLastError());
605 LeaveCriticalSection(&LogFile
->cs
);
609 dwBufferUsage
+=dwRead
;
612 *BytesRead
= dwBufferUsage
;
613 LeaveCriticalSection(&LogFile
->cs
);
617 BOOL
LogfWriteData(PLOGFILE LogFile
,
631 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
)Buffer
)->TimeWritten
);
633 EnterCriticalSection(&LogFile
->cs
);
635 if(SetFilePointer(LogFile
->hFile
,
636 LogFile
->Header
.EofOffset
,
637 NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
639 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
640 LeaveCriticalSection(&LogFile
->cs
);
644 if(!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
646 DPRINT1("WriteFile() failed! %d\n", GetLastError());
647 LeaveCriticalSection(&LogFile
->cs
);
651 if(!LogfAddOffsetInformation(LogFile
,
652 LogFile
->Header
.NextRecord
,
653 LogFile
->Header
.EofOffset
))
655 LeaveCriticalSection(&LogFile
->cs
);
659 LogFile
->Header
.NextRecord
++;
660 LogFile
->Header
.EofOffset
+= dwWritten
;
662 if(LogFile
->Header
.OldestRecord
== 0)
663 LogFile
->Header
.OldestRecord
= 1;
665 EofRec
.Ones
= 0x11111111;
666 EofRec
.Twos
= 0x22222222;
667 EofRec
.Threes
= 0x33333333;
668 EofRec
.Fours
= 0x44444444;
669 EofRec
.Size1
= sizeof(EOF_RECORD
);
670 EofRec
.Size2
= sizeof(EOF_RECORD
);
671 EofRec
.NextRecordNumber
= LogFile
->Header
.NextRecord
;
672 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecord
;
673 EofRec
.StartOffset
= LogFile
->Header
.FirstRecordOffset
;
674 EofRec
.EndOffset
= LogFile
->Header
.EofOffset
;
676 if(!WriteFile(LogFile
->hFile
,
681 DPRINT1("WriteFile() failed! %d\n", GetLastError());
682 LeaveCriticalSection(&LogFile
->cs
);
686 if(SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
)
687 == INVALID_SET_FILE_POINTER
)
689 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
690 LeaveCriticalSection(&LogFile
->cs
);
694 if(!WriteFile(LogFile
->hFile
,
700 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
701 LeaveCriticalSection(&LogFile
->cs
);
705 if(!FlushFileBuffers(LogFile
->hFile
))
707 LeaveCriticalSection(&LogFile
->cs
);
708 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
712 LeaveCriticalSection(&LogFile
->cs
);
716 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
,
718 /* Returns 0 if nothing found. */
721 for(i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
722 if(LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
723 return LogFile
->OffsetInfo
[i
].EventOffset
;
727 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
729 return LogFile
->Header
.OldestRecord
;
732 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
,
736 LPVOID NewOffsetInfo
;
738 if(LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
740 NewOffsetInfo
= HeapReAlloc(MyHeap
,
743 (LogFile
->OffsetInfoSize
+64)*
744 sizeof(EVENT_OFFSET_INFO
));
747 DPRINT1("Can't reallocate heap.\n");
751 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
)NewOffsetInfo
;
752 LogFile
->OffsetInfoSize
+=64;
755 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
756 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
757 LogFile
->OffsetInfoNext
++;
762 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
763 DWORD dwRecordNumber
,
768 LPCWSTR ComputerName
,
777 PEVENTLOGRECORD pRec
;
780 UINT i
, pos
, nStrings
;
783 dwRecSize
= sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
784 lstrlenW(SourceName
) + 2)*sizeof(WCHAR
);
786 if(dwRecSize
% 4 != 0) dwRecSize
+= 4 - (dwRecSize
% 4);
787 dwRecSize
+= dwSidLength
;
789 for(i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
791 dwRecSize
+= (lstrlenW(str
)+1)*sizeof(WCHAR
);
792 str
+= lstrlenW(str
)+1;
795 dwRecSize
+= dwDataSize
;
796 if(dwRecSize
% 4 != 0) dwRecSize
+= 4 - (dwRecSize
% 4);
799 Buffer
= (BYTE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
802 DPRINT1("Can't allocate heap!\n");
806 pRec
= (PEVENTLOGRECORD
)Buffer
;
807 pRec
->Length
= dwRecSize
;
808 pRec
->Reserved
= LOGFILE_SIGNATURE
;
809 pRec
->RecordNumber
= dwRecordNumber
;
811 GetSystemTime(&SysTime
);
812 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
813 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
815 pRec
->EventID
= dwEventId
;
816 pRec
->EventType
= wType
;
817 pRec
->NumStrings
= wNumStrings
;
818 pRec
->EventCategory
= wCategory
;
820 pos
= sizeof(EVENTLOGRECORD
);
822 lstrcpyW((WCHAR
*)(Buffer
+pos
), SourceName
);
823 pos
+=(lstrlenW(SourceName
)+1)*sizeof(WCHAR
);
824 lstrcpyW((WCHAR
*)(Buffer
+pos
), ComputerName
);
825 pos
+=(lstrlenW(ComputerName
)+1)*sizeof(WCHAR
);
827 pRec
->UserSidOffset
= pos
;
830 if(pos
% 4 != 0) pos
+= 4 - (pos
% 4);
831 CopyMemory(Buffer
+pos
, lpUserSid
, dwSidLength
);
832 pRec
->UserSidLength
= dwSidLength
;
833 pRec
->UserSidOffset
= pos
;
837 pRec
->StringOffset
= pos
;
838 for(i
= 0, str
= lpStrings
, nStrings
= 0; i
< wNumStrings
; i
++)
840 lstrcpyW((WCHAR
*)(Buffer
+pos
), str
);
841 pos
+= (lstrlenW(str
)+1)*sizeof(WCHAR
);
842 str
+= lstrlenW(str
)+1;
845 pRec
->NumStrings
= nStrings
;
847 pRec
->DataOffset
= pos
;
850 pRec
->DataLength
= dwDataSize
;
851 CopyMemory(Buffer
+pos
, lpRawData
, dwDataSize
);
855 if(pos
% 4 != 0) pos
+= 4 - (pos
% 4);
856 *((PDWORD
)(Buffer
+pos
)) = dwRecSize
;
858 *lpRecSize
= dwRecSize
;
862 void __inline
LogfFreeRecord(LPVOID Rec
)
864 HeapFree(MyHeap
, 0, Rec
);