2 * COPYRIGHT: See COPYING in the top level directory
4 * FILE: services/eventlog/file.c
5 * PURPOSE: Event logging service
6 * PROGRAMMER: Saveliy Tretiakov (saveliyt@mail.ru)
11 PLOGFILE _LogListHead
= NULL
;
14 BOOL
LogfInitializeNew(PLOGFILE LogFile
)
19 ZeroMemory(&LogFile
->Header
, sizeof(FILE_HEADER
));
20 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
21 SetEndOfFile(LogFile
->hFile
);
23 LogFile
->Header
.SizeOfHeader
= sizeof(FILE_HEADER
);
24 LogFile
->Header
.SizeOfHeader2
= sizeof(FILE_HEADER
);
25 LogFile
->Header
.FirstRecordOffset
= sizeof(FILE_HEADER
);
26 LogFile
->Header
.EofOffset
= sizeof(FILE_HEADER
);
27 LogFile
->Header
.MajorVersion
= MAJORVER
;
28 LogFile
->Header
.MinorVersion
= MINORVER
;
29 LogFile
->Header
.NextRecord
= 1;
31 LogFile
->Header
.Signature
= LOGFILE_SIGNATURE
;
32 WriteFile(LogFile
->hFile
,
38 EofRec
.Ones
= 0x11111111;
39 EofRec
.Twos
= 0x22222222;
40 EofRec
.Threes
= 0x33333333;
41 EofRec
.Fours
= 0x44444444;
42 EofRec
.Size1
= sizeof(EOF_RECORD
);
43 EofRec
.Size2
= sizeof(EOF_RECORD
);
44 EofRec
.NextRecordNumber
= LogFile
->Header
.NextRecord
;
45 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecord
;
46 EofRec
.StartOffset
= LogFile
->Header
.FirstRecordOffset
;
47 EofRec
.EndOffset
= LogFile
->Header
.EofOffset
;
49 WriteFile(LogFile
->hFile
, &EofRec
, sizeof(EOF_RECORD
), &dwWritten
, NULL
);
51 FlushFileBuffers(LogFile
->hFile
);
56 BOOL
LogfInitializeExisting(PLOGFILE LogFile
)
59 DWORD dwRecordsNumber
= 0;
60 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
62 PEVENTLOGRECORD RecBuf
;
64 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
65 ReadFile(LogFile
->hFile
,
70 if(dwRead
!= sizeof(FILE_HEADER
))
72 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
73 return LogfInitializeNew(LogFile
);
76 if(LogFile
->Header
.SizeOfHeader
!= sizeof(FILE_HEADER
) ||
77 LogFile
->Header
.SizeOfHeader2
!= sizeof(FILE_HEADER
))
79 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
80 return LogfInitializeNew(LogFile
);
83 if(LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
85 DPRINT("EventLog: Invalid signature %x in %S.\n",
86 LogFile
->Header
.Signature
,
88 return LogfInitializeNew(LogFile
);
91 if(LogFile
->Header
.EofOffset
> GetFileSize(LogFile
->hFile
, NULL
)+1)
93 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
94 LogFile
->Header
.EofOffset
,
96 return LogfInitializeNew(LogFile
);
101 dwFilePointer
= SetFilePointer(LogFile
->hFile
,
106 ReadFile(LogFile
->hFile
,
112 if(dwRead
!= sizeof(dwRecSize
))
115 ReadFile(LogFile
->hFile
,
121 if(dwRead
!= sizeof(dwRecSize
))
124 if(dwRecSign
!= LOGFILE_SIGNATURE
||
125 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
)+1 ||
126 dwRecSize
< sizeof(EVENTLOGRECORD
))
131 SetFilePointer(LogFile
->hFile
, -((LONG
)sizeof(DWORD
)*2), NULL
, FILE_CURRENT
);
132 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
133 ReadFile(LogFile
->hFile
,
139 if(dwRead
!= dwRecSize
)
141 HeapFree(MyHeap
, 0, RecBuf
);
145 pdwRecSize2
= (PDWORD
)(((PBYTE
)RecBuf
)+dwRecSize
-4);
146 if(*pdwRecSize2
!= dwRecSize
)
148 DPRINT("EventLog: Invalid size2 of record %d (%x) in %s\n",
152 HeapFree(MyHeap
, 0, RecBuf
);
158 if(!LogfAddOffsetInformation(LogFile
, RecBuf
->RecordNumber
, dwFilePointer
))
160 HeapFree(MyHeap
, 0, RecBuf
);
164 HeapFree(MyHeap
, 0, RecBuf
);
167 LogFile
->Header
.NextRecord
= dwRecordsNumber
+1;
168 LogFile
->Header
.OldestRecord
= dwRecordsNumber
? 1 : 0; //FIXME
170 SetFilePointer(LogFile
->hFile
, 0, 0, FILE_CURRENT
);
171 WriteFile(LogFile
->hFile
,
176 FlushFileBuffers(LogFile
->hFile
);
181 PLOGFILE
LogfCreate(WCHAR
*LogName
,
185 BOOL bResult
, bCreateNew
= FALSE
;
187 LogFile
= HeapAlloc(MyHeap
,
192 DbgPrint("EventLog: Can't allocate heap\n");
196 LogFile
->hFile
= CreateFile(FileName
,
197 GENERIC_READ
| GENERIC_WRITE
,
201 FILE_ATTRIBUTE_NORMAL
|
202 FILE_FLAG_RANDOM_ACCESS
,
205 if(LogFile
->hFile
== INVALID_HANDLE_VALUE
)
207 DbgPrint("EventLog: Can't open file %S.\n", FileName
);
208 HeapFree(MyHeap
, 0, LogFile
);
212 bCreateNew
= GetLastError() == ERROR_ALREADY_EXISTS
? FALSE
: TRUE
;
214 LogFile
->LogName
= HeapAlloc(MyHeap
,
216 (lstrlenW(LogName
)+1)*sizeof(WCHAR
));
218 lstrcpyW(LogFile
->LogName
, LogName
);
221 DPRINT("EventLog: Can't allocate heap\n");
222 HeapFree(MyHeap
, 0, LogFile
);
226 LogFile
->FileName
= HeapAlloc(MyHeap
,
228 (lstrlenW(FileName
)+1)*sizeof(WCHAR
));
229 if(LogFile
->FileName
)
230 lstrcpyW(LogFile
->FileName
, FileName
);
233 DPRINT("EventLog: Can't allocate heap\n");
234 HeapFree(MyHeap
, 0, LogFile
->LogName
);
235 HeapFree(MyHeap
, 0, LogFile
);
240 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
)
243 sizeof(EVENT_OFFSET_INFO
)*64);
245 if(!LogFile
->OffsetInfo
)
247 DPRINT("EventLog: Can't allocate heap\n");
248 HeapFree(MyHeap
, 0, LogFile
->FileName
);
249 HeapFree(MyHeap
, 0, LogFile
->LogName
);
250 HeapFree(MyHeap
, 0, LogFile
);
254 LogFile
->OffsetInfoSize
= 64;
257 bResult
= LogfInitializeNew(LogFile
);
258 else bResult
= LogfInitializeExisting(LogFile
);
262 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
263 HeapFree(MyHeap
, 0, LogFile
->FileName
);
264 HeapFree(MyHeap
, 0, LogFile
->LogName
);
265 HeapFree(MyHeap
, 0, LogFile
);
269 InitializeCriticalSection(&LogFile
->cs
);
270 LogfListAddItem(LogFile
);
274 VOID
LogfClose(PLOGFILE LogFile
)
279 EnterCriticalSection(&LogFile
->cs
);
281 FlushFileBuffers(LogFile
->hFile
);
282 CloseHandle(LogFile
->hFile
);
284 LogfListRemoveItem(LogFile
);
285 DeleteCriticalSection(&LogFile
->cs
);
287 HeapFree(MyHeap
, 0, LogFile
->LogName
);
288 HeapFree(MyHeap
, 0, LogFile
->FileName
);
289 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
290 HeapFree(MyHeap
, 0, LogFile
);
295 PLOGFILE
LogfListHead()
300 PLOGFILE
LogfListItemByName(WCHAR
*Name
)
303 Item
= LogfListHead();
306 if(Item
->LogName
&& lstrcmpW(Item
->LogName
, Name
)==0)
308 Item
= (PLOGFILE
)Item
->Next
;
313 PLOGFILE
LogfListItemByIndex(INT Index
)
317 Item
= LogfListHead();
323 Item
= (PLOGFILE
)Item
->Next
;
328 INT
LogfListItemCount()
330 PLOGFILE Item
= NULL
;
332 Item
= LogfListHead();
338 Item
= (PLOGFILE
) Item
->Next
;
345 VOID
LogfListAddItem(PLOGFILE Item
)
349 List
= LogfListHead();
354 List
= (PLOGFILE
)List
->Next
;
355 Item
->Prev
= (PVOID
)List
;
357 InterlockedExchange((PLONG
)&List
->Next
, (LONG
)Item
);
362 InterlockedExchange((PLONG
)&_LogListHead
, (LONG
)Item
);
366 VOID
LogfListRemoveItem(PLOGFILE Item
)
370 InterlockedExchange((PLONG
)&((PLOGFILE
)Item
->Prev
)->Next
,
374 InterlockedExchange((PLONG
)&_LogListHead
, (LONG
)Item
->Next
);
378 BOOL
LogfReadEvent(PLOGFILE LogFile
,
386 DWORD dwOffset
, dwRead
, dwRecSize
;
387 DWORD dwBufferUsage
= 0, dwRecNum
;
389 if(Flags
& EVENTLOG_FORWARDS_READ
&&
390 Flags
& EVENTLOG_BACKWARDS_READ
)
395 if(!(Flags
& EVENTLOG_FORWARDS_READ
) &&
396 !(Flags
& EVENTLOG_BACKWARDS_READ
))
401 if(!Buffer
|| !BytesRead
|| !BytesNeeded
)
406 dwRecNum
= RecordNumber
;
407 EnterCriticalSection(&LogFile
->cs
);
408 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
412 LeaveCriticalSection(&LogFile
->cs
);
416 SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
);
417 ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
);
418 if(dwRecSize
> BufSize
)
421 *BytesNeeded
= dwRecSize
;
422 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
423 LeaveCriticalSection(&LogFile
->cs
);
427 SetFilePointer(LogFile
->hFile
,
428 -((LONG
)sizeof(DWORD
)),
432 ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
);
433 dwBufferUsage
+=dwRead
;
435 while(dwBufferUsage
<BufSize
)
437 if(Flags
& EVENTLOG_FORWARDS_READ
)
441 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
444 SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
);
445 ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
);
446 if(dwBufferUsage
+dwRecSize
>BufSize
)break;
448 SetFilePointer(LogFile
->hFile
,
449 -((LONG
)sizeof(DWORD
)),
453 ReadFile(LogFile
->hFile
,
454 Buffer
+dwBufferUsage
,
459 dwBufferUsage
+=dwRead
;
462 *BytesRead
= dwBufferUsage
;
463 LeaveCriticalSection(&LogFile
->cs
);
467 BOOL
LogfWriteData(PLOGFILE LogFile
,
482 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
)Buffer
)->TimeWritten
);
484 EnterCriticalSection(&LogFile
->cs
);
486 SetFilePointer(LogFile
->hFile
, LogFile
->Header
.EofOffset
, NULL
, FILE_BEGIN
);
487 WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
);
489 if(BufSize
!= dwWritten
)
491 LeaveCriticalSection(&LogFile
->cs
);
495 if(!LogfAddOffsetInformation(LogFile
,
496 LogFile
->Header
.NextRecord
,
497 LogFile
->Header
.EofOffset
))
499 LeaveCriticalSection(&LogFile
->cs
);
503 LogFile
->Header
.NextRecord
++;
504 LogFile
->Header
.EofOffset
+= dwWritten
;
506 if(LogFile
->Header
.OldestRecord
== 0)
507 LogFile
->Header
.OldestRecord
= 1;
509 EofRec
.Ones
= 0x11111111;
510 EofRec
.Twos
= 0x22222222;
511 EofRec
.Threes
= 0x33333333;
512 EofRec
.Fours
= 0x44444444;
513 EofRec
.Size1
= sizeof(EOF_RECORD
);
514 EofRec
.Size2
= sizeof(EOF_RECORD
);
515 EofRec
.NextRecordNumber
= LogFile
->Header
.NextRecord
;
516 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecord
;
517 EofRec
.StartOffset
= LogFile
->Header
.FirstRecordOffset
;
518 EofRec
.EndOffset
= LogFile
->Header
.EofOffset
;
520 WriteFile(LogFile
->hFile
, &EofRec
, sizeof(EOF_RECORD
), &dwWritten
, NULL
);
522 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
523 bResult
= WriteFile(LogFile
->hFile
,
531 DPRINT("WriteFile failed! LastError = %d\n", GetLastError());
532 LeaveCriticalSection(&LogFile
->cs
);
536 if(!FlushFileBuffers(LogFile
->hFile
))
537 DPRINT("FlushFileBuffers() failed!\n");
539 LeaveCriticalSection(&LogFile
->cs
);
543 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
,
545 /* Returns NULL if nothing found. */
548 for(i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
549 if(LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
550 return LogFile
->OffsetInfo
[i
].EventOffset
;
554 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
556 return LogFile
->Header
.OldestRecord
;
559 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
,
563 LPVOID NewOffsetInfo
;
565 if(LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
567 NewOffsetInfo
= HeapReAlloc(MyHeap
,
570 (LogFile
->OffsetInfoSize
+64)*
571 sizeof(EVENT_OFFSET_INFO
));
574 DbgPrint("EventLog: Can't reallocate heap.\n");
578 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
)NewOffsetInfo
;
579 LogFile
->OffsetInfoSize
+=64;
582 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
583 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
584 LogFile
->OffsetInfoNext
++;
589 DWORD
LogfBuildNewRecord(PBYTE Buffer
,
590 DWORD dwRecordNumber
,
595 LPCWSTR ComputerName
,
604 PEVENTLOGRECORD pRec
;
607 UINT i
, pos
, nStrings
;
609 dwRecSize
= sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
610 lstrlenW(SourceName
) + 2)*sizeof(WCHAR
);
612 if(dwRecSize
% 4 != 0) dwRecSize
+= 4 - (dwRecSize
% 4);
613 dwRecSize
+= dwSidLength
;
615 for(i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
617 dwRecSize
+= (lstrlenW(str
)+1)*sizeof(WCHAR
);
618 str
+= lstrlenW(str
)+1;
621 dwRecSize
+= dwDataSize
;
622 if(dwRecSize
% 4 != 0) dwRecSize
+= 4 - (dwRecSize
% 4);
630 ZeroMemory(Buffer
, dwRecSize
);
631 pRec
= (PEVENTLOGRECORD
)Buffer
;
632 pRec
->Length
= dwRecSize
;
633 pRec
->Reserved
= LOGFILE_SIGNATURE
;
634 pRec
->RecordNumber
= dwRecordNumber
;
636 GetSystemTime(&SysTime
);
637 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
638 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
640 pRec
->EventID
= dwEventId
;
641 pRec
->EventType
= wType
;
642 pRec
->NumStrings
= wNumStrings
;
643 pRec
->EventCategory
= wCategory
;
645 pos
= sizeof(EVENTLOGRECORD
);
647 lstrcpyW((WCHAR
*)(Buffer
+pos
), SourceName
);
648 pos
+=(lstrlenW(SourceName
)+1)*sizeof(WCHAR
);
649 lstrcpyW((WCHAR
*)(Buffer
+pos
), ComputerName
);
650 pos
+=(lstrlenW(ComputerName
)+1)*sizeof(WCHAR
);
652 pRec
->UserSidOffset
= pos
;
655 if(pos
% 4 != 0) pos
+= 4 - (pos
% 4);
656 CopyMemory(Buffer
+pos
, lpUserSid
, dwSidLength
);
657 pRec
->UserSidLength
= dwSidLength
;
658 pRec
->UserSidOffset
= pos
;
662 pRec
->StringOffset
= pos
;
663 for(i
= 0, str
= lpStrings
, nStrings
= 0; i
< wNumStrings
; i
++)
665 lstrcpyW((WCHAR
*)(Buffer
+pos
), str
);
666 pos
+= (lstrlenW(str
)+1)*sizeof(WCHAR
);
667 str
+= lstrlenW(str
)+1;
670 pRec
->NumStrings
= nStrings
;
672 pRec
->DataOffset
= pos
;
675 pRec
->DataLength
= dwDataSize
;
676 CopyMemory(Buffer
+pos
, lpRawData
, dwDataSize
);
680 if(pos
% 4 != 0) pos
+= 4 - (pos
% 4);
681 *((PDWORD
)(Buffer
+pos
)) = dwRecSize
;