Put inline functions into header files.
[reactos.git] / reactos / base / services / eventlog / file.c
1 /*
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
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include "eventlog.h"
12
13 /* GLOBALS ******************************************************************/
14
15 static LIST_ENTRY LogFileListHead;
16 static CRITICAL_SECTION LogFileListCs;
17
18 /* FUNCTIONS ****************************************************************/
19
20 BOOL LogfInitializeNew(PLOGFILE LogFile)
21 {
22 DWORD dwWritten;
23 EOF_RECORD EofRec;
24
25 ZeroMemory(&LogFile->Header, sizeof(FILE_HEADER));
26 SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN);
27 SetEndOfFile(LogFile->hFile);
28
29 LogFile->Header.SizeOfHeader = sizeof(FILE_HEADER);
30 LogFile->Header.SizeOfHeader2 = sizeof(FILE_HEADER);
31 LogFile->Header.FirstRecordOffset = sizeof(FILE_HEADER);
32 LogFile->Header.EofOffset = sizeof(FILE_HEADER);
33 LogFile->Header.MajorVersion = MAJORVER;
34 LogFile->Header.MinorVersion = MINORVER;
35 LogFile->Header.NextRecord = 1;
36
37 LogFile->Header.Signature = LOGFILE_SIGNATURE;
38 if (!WriteFile(LogFile->hFile,
39 &LogFile->Header,
40 sizeof(FILE_HEADER),
41 &dwWritten,
42 NULL))
43 {
44 DPRINT1("WriteFile failed:%d!\n", GetLastError());
45 return FALSE;
46 }
47
48 EofRec.Ones = 0x11111111;
49 EofRec.Twos = 0x22222222;
50 EofRec.Threes = 0x33333333;
51 EofRec.Fours = 0x44444444;
52 EofRec.Size1 = sizeof(EOF_RECORD);
53 EofRec.Size2 = sizeof(EOF_RECORD);
54 EofRec.NextRecordNumber = LogFile->Header.NextRecord;
55 EofRec.OldestRecordNumber = LogFile->Header.OldestRecord;
56 EofRec.StartOffset = LogFile->Header.FirstRecordOffset;
57 EofRec.EndOffset = LogFile->Header.EofOffset;
58
59 if (!WriteFile(LogFile->hFile,
60 &EofRec,
61 sizeof(EOF_RECORD),
62 &dwWritten,
63 NULL))
64 {
65 DPRINT1("WriteFile failed:%d!\n", GetLastError());
66 return FALSE;
67 }
68
69 if (!FlushFileBuffers(LogFile->hFile))
70 {
71 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
72 return FALSE;
73 }
74
75 return TRUE;
76 }
77
78 BOOL LogfInitializeExisting(PLOGFILE LogFile)
79 {
80 DWORD dwRead;
81 DWORD dwRecordsNumber = 0;
82 DWORD dwRecSize, dwRecSign, dwFilePointer;
83 PDWORD pdwRecSize2;
84 PEVENTLOGRECORD RecBuf;
85
86 if (SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
87 INVALID_SET_FILE_POINTER)
88 {
89 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
90 return FALSE;
91 }
92
93 if (!ReadFile(LogFile->hFile,
94 &LogFile->Header,
95 sizeof(FILE_HEADER),
96 &dwRead,
97 NULL))
98 {
99 DPRINT1("ReadFile failed! %d\n", GetLastError());
100 return FALSE;
101 }
102
103 if (dwRead != sizeof(FILE_HEADER))
104 {
105 DPRINT("EventLog: Invalid file %S.\n", LogFile->FileName);
106 return LogfInitializeNew(LogFile);
107 }
108
109 if (LogFile->Header.SizeOfHeader != sizeof(FILE_HEADER) ||
110 LogFile->Header.SizeOfHeader2 != sizeof(FILE_HEADER))
111 {
112 DPRINT("EventLog: Invalid header size in %S.\n", LogFile->FileName);
113 return LogfInitializeNew(LogFile);
114 }
115
116 if (LogFile->Header.Signature != LOGFILE_SIGNATURE)
117 {
118 DPRINT("EventLog: Invalid signature %x in %S.\n",
119 LogFile->Header.Signature, LogFile->FileName);
120 return LogfInitializeNew(LogFile);
121 }
122
123 if (LogFile->Header.EofOffset > GetFileSize(LogFile->hFile, NULL) + 1)
124 {
125 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
126 LogFile->Header.EofOffset, LogFile->FileName);
127 return LogfInitializeNew(LogFile);
128 }
129
130 for (;;)
131 {
132 dwFilePointer = SetFilePointer(LogFile->hFile, 0, NULL, FILE_CURRENT);
133
134 if (dwFilePointer == INVALID_SET_FILE_POINTER)
135 {
136 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
137 return FALSE;
138 }
139
140 if (!ReadFile(LogFile->hFile,
141 &dwRecSize,
142 sizeof(dwRecSize),
143 &dwRead,
144 NULL))
145 {
146 DPRINT1("ReadFile failed! %d\n", GetLastError());
147 return FALSE;
148 }
149
150 if (dwRead != sizeof(dwRecSize))
151 break;
152
153 if (!ReadFile(LogFile->hFile,
154 &dwRecSign,
155 sizeof(dwRecSign),
156 &dwRead,
157 NULL))
158 {
159 DPRINT1("ReadFile() failed! %d\n", GetLastError());
160 return FALSE;
161 }
162
163 if (dwRead != sizeof(dwRecSize))
164 break;
165
166 if (dwRecSign != LOGFILE_SIGNATURE ||
167 dwRecSize + dwFilePointer > GetFileSize(LogFile->hFile, NULL) + 1 ||
168 dwRecSize < sizeof(EVENTLOGRECORD))
169 {
170 break;
171 }
172
173 if (SetFilePointer(LogFile->hFile,
174 -((LONG) sizeof(DWORD) * 2),
175 NULL,
176 FILE_CURRENT) == INVALID_SET_FILE_POINTER)
177 {
178 DPRINT1("SetFilePointer() failed! %d", GetLastError());
179 return FALSE;
180 }
181
182 RecBuf = (PEVENTLOGRECORD) HeapAlloc(MyHeap, 0, dwRecSize);
183
184 if (!RecBuf)
185 {
186 DPRINT1("Can't allocate heap!\n");
187 return FALSE;
188 }
189
190 if (!ReadFile(LogFile->hFile, RecBuf, dwRecSize, &dwRead, NULL))
191 {
192 DPRINT1("ReadFile() failed! %d\n", GetLastError());
193 HeapFree(MyHeap, 0, RecBuf);
194 return FALSE;
195 }
196
197 if (dwRead != dwRecSize)
198 {
199 HeapFree(MyHeap, 0, RecBuf);
200 break;
201 }
202
203 pdwRecSize2 = (PDWORD) (((PBYTE) RecBuf) + dwRecSize - 4);
204
205 if (*pdwRecSize2 != dwRecSize)
206 {
207 DPRINT1("Invalid size2 of record %d (%x) in %S\n",
208 dwRecordsNumber, *pdwRecSize2, LogFile->LogName);
209 HeapFree(MyHeap, 0, RecBuf);
210 break;
211 }
212
213 dwRecordsNumber++;
214
215 if (!LogfAddOffsetInformation(LogFile,
216 RecBuf->RecordNumber,
217 dwFilePointer))
218 {
219 DPRINT1("LogfAddOffsetInformation() failed!\n");
220 HeapFree(MyHeap, 0, RecBuf);
221 return FALSE;
222 }
223
224 HeapFree(MyHeap, 0, RecBuf);
225 } // for(;;)
226
227 LogFile->Header.NextRecord = dwRecordsNumber + 1;
228 LogFile->Header.OldestRecord = dwRecordsNumber ? 1 : 0; // FIXME
229
230 if (!SetFilePointer(LogFile->hFile, 0, NULL, FILE_CURRENT) ==
231 INVALID_SET_FILE_POINTER)
232 {
233 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
234 return FALSE;
235 }
236
237 if (!WriteFile(LogFile->hFile,
238 &LogFile->Header,
239 sizeof(FILE_HEADER),
240 &dwRead,
241 NULL))
242 {
243 DPRINT1("WriteFile failed! %d\n", GetLastError());
244 return FALSE;
245 }
246
247 if (!FlushFileBuffers(LogFile->hFile))
248 {
249 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
250 return FALSE;
251 }
252
253 return TRUE;
254 }
255
256 PLOGFILE LogfCreate(WCHAR * LogName, WCHAR * FileName)
257 {
258 PLOGFILE LogFile;
259 BOOL bResult, bCreateNew = FALSE;
260
261 LogFile = (LOGFILE *) HeapAlloc(MyHeap, HEAP_ZERO_MEMORY, sizeof(LOGFILE));
262 if (!LogFile)
263 {
264 DPRINT1("Can't allocate heap!\n");
265 return NULL;
266 }
267
268 LogFile->hFile = CreateFile(FileName,
269 GENERIC_READ | GENERIC_WRITE,
270 FILE_SHARE_READ,
271 NULL,
272 OPEN_ALWAYS,
273 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
274 NULL);
275
276 if (LogFile->hFile == INVALID_HANDLE_VALUE)
277 {
278 DPRINT1("Can't create file %S.\n", FileName);
279 HeapFree(MyHeap, 0, LogFile);
280 return NULL;
281 }
282
283 bCreateNew = (GetLastError() == ERROR_ALREADY_EXISTS) ? FALSE : TRUE;
284
285 LogFile->LogName =
286 (WCHAR *) HeapAlloc(MyHeap,
287 HEAP_ZERO_MEMORY,
288 (lstrlenW(LogName) + 1) * sizeof(WCHAR));
289
290 if (LogFile->LogName)
291 lstrcpyW(LogFile->LogName, LogName);
292 else
293 {
294 DPRINT1("Can't allocate heap\n");
295 HeapFree(MyHeap, 0, LogFile);
296 return NULL;
297 }
298
299 LogFile->FileName =
300 (WCHAR *) HeapAlloc(MyHeap,
301 HEAP_ZERO_MEMORY,
302 (lstrlenW(FileName) + 1) * sizeof(WCHAR));
303
304 if (LogFile->FileName)
305 lstrcpyW(LogFile->FileName, FileName);
306 else
307 {
308 DPRINT1("Can't allocate heap\n");
309 goto fail;
310 }
311
312 LogFile->OffsetInfo =
313 (PEVENT_OFFSET_INFO) HeapAlloc(MyHeap,
314 HEAP_ZERO_MEMORY,
315 sizeof(EVENT_OFFSET_INFO) * 64);
316
317 if (!LogFile->OffsetInfo)
318 {
319 DPRINT1("Can't allocate heap\n");
320 goto fail;
321 }
322
323 LogFile->OffsetInfoSize = 64;
324
325 if (bCreateNew)
326 bResult = LogfInitializeNew(LogFile);
327 else
328 bResult = LogfInitializeExisting(LogFile);
329
330 if (!bResult)
331 goto fail;
332
333 InitializeCriticalSection(&LogFile->cs);
334 LogfListAddItem(LogFile);
335 return LogFile;
336
337 fail:
338 if (LogFile)
339 {
340 if (LogFile->OffsetInfo)
341 HeapFree(MyHeap, 0, LogFile->OffsetInfo);
342
343 if (LogFile->FileName)
344 HeapFree(MyHeap, 0, LogFile->FileName);
345
346 if (LogFile->LogName)
347 HeapFree(MyHeap, 0, LogFile->LogName);
348
349 HeapFree(MyHeap, 0, LogFile);
350 }
351
352 return NULL;
353 }
354
355 VOID LogfClose(PLOGFILE LogFile)
356 {
357 if (LogFile == NULL)
358 return;
359
360 EnterCriticalSection(&LogFile->cs);
361
362 FlushFileBuffers(LogFile->hFile);
363 CloseHandle(LogFile->hFile);
364 LogfListRemoveItem(LogFile);
365
366 DeleteCriticalSection(&LogFile->cs);
367
368 HeapFree(MyHeap, 0, LogFile->LogName);
369 HeapFree(MyHeap, 0, LogFile->FileName);
370 HeapFree(MyHeap, 0, LogFile->OffsetInfo);
371 HeapFree(MyHeap, 0, LogFile);
372
373 return;
374 }
375
376 VOID LogfCloseAll(VOID)
377 {
378 while (!IsListEmpty(&LogFileListHead))
379 {
380 LogfClose(LogfListHead());
381 }
382
383 DeleteCriticalSection(&LogFileListCs);
384 }
385
386 VOID LogfListInitialize(VOID)
387 {
388 InitializeCriticalSection(&LogFileListCs);
389 InitializeListHead(&LogFileListHead);
390 }
391
392 PLOGFILE LogfListHead(VOID)
393 {
394 return CONTAINING_RECORD(LogFileListHead.Flink, LOGFILE, ListEntry);
395 }
396
397 PLOGFILE LogfListItemByName(WCHAR * Name)
398 {
399 PLIST_ENTRY CurrentEntry;
400 PLOGFILE Result = NULL;
401
402 EnterCriticalSection(&LogFileListCs);
403
404 CurrentEntry = LogFileListHead.Flink;
405 while (CurrentEntry != &LogFileListHead)
406 {
407 PLOGFILE Item = CONTAINING_RECORD(CurrentEntry,
408 LOGFILE,
409 ListEntry);
410
411 if (Item->LogName && !lstrcmpi(Item->LogName, Name))
412 {
413 Result = Item;
414 break;
415 }
416
417 CurrentEntry = CurrentEntry->Flink;
418 }
419
420 LeaveCriticalSection(&LogFileListCs);
421 return Result;
422 }
423
424 /* Index starting from 1 */
425 INT LogfListItemIndexByName(WCHAR * Name)
426 {
427 PLIST_ENTRY CurrentEntry;
428 INT Result = 0;
429 INT i = 1;
430
431 EnterCriticalSection(&LogFileListCs);
432
433 CurrentEntry = LogFileListHead.Flink;
434 while (CurrentEntry != &LogFileListHead)
435 {
436 PLOGFILE Item = CONTAINING_RECORD(CurrentEntry,
437 LOGFILE,
438 ListEntry);
439
440 if (Item->LogName && !lstrcmpi(Item->LogName, Name))
441 {
442 Result = i;
443 break;
444 }
445
446 CurrentEntry = CurrentEntry->Flink;
447 i++;
448 }
449
450 LeaveCriticalSection(&LogFileListCs);
451 return Result;
452 }
453
454 /* Index starting from 1 */
455 PLOGFILE LogfListItemByIndex(INT Index)
456 {
457 PLIST_ENTRY CurrentEntry;
458 PLOGFILE Result = NULL;
459 INT i = 1;
460
461 EnterCriticalSection(&LogFileListCs);
462
463 CurrentEntry = LogFileListHead.Flink;
464 while (CurrentEntry != &LogFileListHead)
465 {
466 if (i == Index)
467 {
468 Result = CONTAINING_RECORD(CurrentEntry, LOGFILE, ListEntry);
469 break;
470 }
471
472 CurrentEntry = CurrentEntry->Flink;
473 i++;
474 }
475
476 LeaveCriticalSection(&LogFileListCs);
477 return Result;
478 }
479
480 INT LogfListItemCount()
481 {
482 PLIST_ENTRY CurrentEntry;
483 INT i = 0;
484
485 EnterCriticalSection(&LogFileListCs);
486
487 CurrentEntry = LogFileListHead.Flink;
488 while (CurrentEntry != &LogFileListHead)
489 {
490 CurrentEntry = CurrentEntry->Flink;
491 i++;
492 }
493
494 LeaveCriticalSection(&LogFileListCs);
495 return i;
496 }
497
498 VOID LogfListAddItem(PLOGFILE Item)
499 {
500 EnterCriticalSection(&LogFileListCs);
501 InsertTailList(&LogFileListHead, &Item->ListEntry);
502 LeaveCriticalSection(&LogFileListCs);
503 }
504
505 VOID LogfListRemoveItem(PLOGFILE Item)
506 {
507 EnterCriticalSection(&LogFileListCs);
508 RemoveEntryList(&Item->ListEntry);
509 LeaveCriticalSection(&LogFileListCs);
510 }
511
512 BOOL LogfReadEvent(PLOGFILE LogFile,
513 DWORD Flags,
514 DWORD RecordNumber,
515 DWORD BufSize,
516 PBYTE Buffer,
517 DWORD * BytesRead,
518 DWORD * BytesNeeded)
519 {
520 DWORD dwOffset, dwRead, dwRecSize;
521 DWORD dwBufferUsage = 0, dwRecNum;
522
523 if (Flags & EVENTLOG_FORWARDS_READ && Flags & EVENTLOG_BACKWARDS_READ)
524 return FALSE;
525
526 if (!(Flags & EVENTLOG_FORWARDS_READ) && !(Flags & EVENTLOG_BACKWARDS_READ))
527 return FALSE;
528
529 if (!Buffer || !BytesRead || !BytesNeeded)
530 return FALSE;
531
532 dwRecNum = RecordNumber;
533 EnterCriticalSection(&LogFile->cs);
534 dwOffset = LogfOffsetByNumber(LogFile, dwRecNum);
535
536 if (!dwOffset)
537 {
538 LeaveCriticalSection(&LogFile->cs);
539 return FALSE;
540 }
541
542 if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) ==
543 INVALID_SET_FILE_POINTER)
544 {
545 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
546 LeaveCriticalSection(&LogFile->cs);
547 return FALSE;
548 }
549
550 if (!ReadFile(LogFile->hFile, &dwRecSize, sizeof(DWORD), &dwRead, NULL))
551 {
552 DPRINT1("ReadFile() failed! %d\n", GetLastError());
553 LeaveCriticalSection(&LogFile->cs);
554 return FALSE;
555 }
556
557 if (dwRecSize > BufSize)
558 {
559 *BytesRead = 0;
560 *BytesNeeded = dwRecSize;
561 SetLastError(ERROR_INSUFFICIENT_BUFFER);
562 LeaveCriticalSection(&LogFile->cs);
563 return FALSE;
564 }
565
566 if (SetFilePointer(LogFile->hFile,
567 -((LONG) sizeof(DWORD)),
568 NULL,
569 FILE_CURRENT) == INVALID_SET_FILE_POINTER)
570 {
571 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
572 LeaveCriticalSection(&LogFile->cs);
573 return FALSE;
574 }
575
576 if (!ReadFile(LogFile->hFile, Buffer, dwRecSize, &dwRead, NULL))
577 {
578 DPRINT1("ReadFile() failed! %d\n", GetLastError());
579 LeaveCriticalSection(&LogFile->cs);
580 return FALSE;
581 }
582
583 dwBufferUsage += dwRead;
584
585 while (dwBufferUsage < BufSize)
586 {
587 if (Flags & EVENTLOG_FORWARDS_READ)
588 dwRecNum++;
589 else
590 dwRecNum--;
591
592 dwOffset = LogfOffsetByNumber(LogFile, dwRecNum);
593 if (!dwOffset)
594 break;
595
596 if (SetFilePointer(LogFile->hFile, dwOffset, NULL, FILE_BEGIN) ==
597 INVALID_SET_FILE_POINTER)
598 {
599 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
600 LeaveCriticalSection(&LogFile->cs);
601 return FALSE;
602 }
603
604 if (!ReadFile(LogFile->hFile,
605 &dwRecSize,
606 sizeof(DWORD),
607 &dwRead,
608 NULL))
609 {
610 DPRINT1("ReadFile() failed! %d\n", GetLastError());
611 LeaveCriticalSection(&LogFile->cs);
612 return FALSE;
613 }
614
615 if (dwBufferUsage + dwRecSize > BufSize)
616 break;
617
618 if (SetFilePointer(LogFile->hFile,
619 -((LONG) sizeof(DWORD)),
620 NULL,
621 FILE_CURRENT) == INVALID_SET_FILE_POINTER)
622 {
623 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
624 LeaveCriticalSection(&LogFile->cs);
625 return FALSE;
626 }
627
628 if (!ReadFile(LogFile->hFile,
629 Buffer + dwBufferUsage,
630 dwRecSize,
631 &dwRead,
632 NULL))
633 {
634 DPRINT1("ReadFile() failed! %d\n", GetLastError());
635 LeaveCriticalSection(&LogFile->cs);
636 return FALSE;
637 }
638
639 dwBufferUsage += dwRead;
640 }
641
642 *BytesRead = dwBufferUsage;
643 LeaveCriticalSection(&LogFile->cs);
644 return TRUE;
645 }
646
647 BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer)
648 {
649 DWORD dwWritten;
650 SYSTEMTIME st;
651 EOF_RECORD EofRec;
652
653 if (!Buffer)
654 return FALSE;
655
656 GetSystemTime(&st);
657 SystemTimeToEventTime(&st, &((PEVENTLOGRECORD) Buffer)->TimeWritten);
658
659 EnterCriticalSection(&LogFile->cs);
660
661 if (SetFilePointer(LogFile->hFile,
662 LogFile->Header.EofOffset,
663 NULL,
664 FILE_BEGIN) == INVALID_SET_FILE_POINTER)
665 {
666 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
667 LeaveCriticalSection(&LogFile->cs);
668 return FALSE;
669 }
670
671 if (!WriteFile(LogFile->hFile, Buffer, BufSize, &dwWritten, NULL))
672 {
673 DPRINT1("WriteFile() failed! %d\n", GetLastError());
674 LeaveCriticalSection(&LogFile->cs);
675 return FALSE;
676 }
677
678 if (!LogfAddOffsetInformation(LogFile,
679 LogFile->Header.NextRecord,
680 LogFile->Header.EofOffset))
681 {
682 LeaveCriticalSection(&LogFile->cs);
683 return FALSE;
684 }
685
686 LogFile->Header.NextRecord++;
687 LogFile->Header.EofOffset += dwWritten;
688
689 if (LogFile->Header.OldestRecord == 0)
690 LogFile->Header.OldestRecord = 1;
691
692 EofRec.Ones = 0x11111111;
693 EofRec.Twos = 0x22222222;
694 EofRec.Threes = 0x33333333;
695 EofRec.Fours = 0x44444444;
696 EofRec.Size1 = sizeof(EOF_RECORD);
697 EofRec.Size2 = sizeof(EOF_RECORD);
698 EofRec.NextRecordNumber = LogFile->Header.NextRecord;
699 EofRec.OldestRecordNumber = LogFile->Header.OldestRecord;
700 EofRec.StartOffset = LogFile->Header.FirstRecordOffset;
701 EofRec.EndOffset = LogFile->Header.EofOffset;
702
703 if (!WriteFile(LogFile->hFile,
704 &EofRec,
705 sizeof(EOF_RECORD),
706 &dwWritten,
707 NULL))
708 {
709 DPRINT1("WriteFile() failed! %d\n", GetLastError());
710 LeaveCriticalSection(&LogFile->cs);
711 return FALSE;
712 }
713
714 if (SetFilePointer(LogFile->hFile, 0, NULL, FILE_BEGIN) ==
715 INVALID_SET_FILE_POINTER)
716 {
717 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
718 LeaveCriticalSection(&LogFile->cs);
719 return FALSE;
720 }
721
722 if (!WriteFile(LogFile->hFile,
723 &LogFile->Header,
724 sizeof(FILE_HEADER),
725 &dwWritten,
726 NULL))
727 {
728 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
729 LeaveCriticalSection(&LogFile->cs);
730 return FALSE;
731 }
732
733 if (!FlushFileBuffers(LogFile->hFile))
734 {
735 LeaveCriticalSection(&LogFile->cs);
736 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
737 return FALSE;
738 }
739
740 LeaveCriticalSection(&LogFile->cs);
741 return TRUE;
742 }
743
744 ULONG LogfOffsetByNumber(PLOGFILE LogFile, DWORD RecordNumber)
745
746 /* Returns 0 if nothing found. */
747 {
748 DWORD i;
749
750 for (i = 0; i < LogFile->OffsetInfoNext; i++)
751 {
752 if (LogFile->OffsetInfo[i].EventNumber == RecordNumber)
753 return LogFile->OffsetInfo[i].EventOffset;
754 }
755 return 0;
756 }
757
758 DWORD LogfGetOldestRecord(PLOGFILE LogFile)
759 {
760 return LogFile->Header.OldestRecord;
761 }
762
763 BOOL LogfAddOffsetInformation(PLOGFILE LogFile, ULONG ulNumber, ULONG ulOffset)
764 {
765 LPVOID NewOffsetInfo;
766
767 if (LogFile->OffsetInfoNext == LogFile->OffsetInfoSize)
768 {
769 NewOffsetInfo = HeapReAlloc(MyHeap,
770 HEAP_ZERO_MEMORY,
771 LogFile->OffsetInfo,
772 (LogFile->OffsetInfoSize + 64) *
773 sizeof(EVENT_OFFSET_INFO));
774
775 if (!NewOffsetInfo)
776 {
777 DPRINT1("Can't reallocate heap.\n");
778 return FALSE;
779 }
780
781 LogFile->OffsetInfo = (PEVENT_OFFSET_INFO) NewOffsetInfo;
782 LogFile->OffsetInfoSize += 64;
783 }
784
785 LogFile->OffsetInfo[LogFile->OffsetInfoNext].EventNumber = ulNumber;
786 LogFile->OffsetInfo[LogFile->OffsetInfoNext].EventOffset = ulOffset;
787 LogFile->OffsetInfoNext++;
788
789 return TRUE;
790 }
791
792 PBYTE LogfAllocAndBuildNewRecord(LPDWORD lpRecSize,
793 DWORD dwRecordNumber,
794 WORD wType,
795 WORD wCategory,
796 DWORD dwEventId,
797 LPCWSTR SourceName,
798 LPCWSTR ComputerName,
799 DWORD dwSidLength,
800 PSID lpUserSid,
801 WORD wNumStrings,
802 WCHAR * lpStrings,
803 DWORD dwDataSize,
804 LPVOID lpRawData)
805 {
806 DWORD dwRecSize;
807 PEVENTLOGRECORD pRec;
808 SYSTEMTIME SysTime;
809 WCHAR *str;
810 UINT i, pos, nStrings;
811 PBYTE Buffer;
812
813 dwRecSize =
814 sizeof(EVENTLOGRECORD) + (lstrlenW(ComputerName) +
815 lstrlenW(SourceName) + 2) * sizeof(WCHAR);
816
817 if (dwRecSize % 4 != 0)
818 dwRecSize += 4 - (dwRecSize % 4);
819
820 dwRecSize += dwSidLength;
821
822 for (i = 0, str = lpStrings; i < wNumStrings; i++)
823 {
824 dwRecSize += (lstrlenW(str) + 1) * sizeof(WCHAR);
825 str += lstrlenW(str) + 1;
826 }
827
828 dwRecSize += dwDataSize;
829 if (dwRecSize % 4 != 0)
830 dwRecSize += 4 - (dwRecSize % 4);
831
832 dwRecSize += 4;
833
834 Buffer = (BYTE *) HeapAlloc(MyHeap, HEAP_ZERO_MEMORY, dwRecSize);
835
836 if (!Buffer)
837 {
838 DPRINT1("Can't allocate heap!\n");
839 return NULL;
840 }
841
842 pRec = (PEVENTLOGRECORD) Buffer;
843 pRec->Length = dwRecSize;
844 pRec->Reserved = LOGFILE_SIGNATURE;
845 pRec->RecordNumber = dwRecordNumber;
846
847 GetSystemTime(&SysTime);
848 SystemTimeToEventTime(&SysTime, &pRec->TimeGenerated);
849 SystemTimeToEventTime(&SysTime, &pRec->TimeWritten);
850
851 pRec->EventID = dwEventId;
852 pRec->EventType = wType;
853 pRec->NumStrings = wNumStrings;
854 pRec->EventCategory = wCategory;
855
856 pos = sizeof(EVENTLOGRECORD);
857
858 lstrcpyW((WCHAR *) (Buffer + pos), SourceName);
859 pos += (lstrlenW(SourceName) + 1) * sizeof(WCHAR);
860 lstrcpyW((WCHAR *) (Buffer + pos), ComputerName);
861 pos += (lstrlenW(ComputerName) + 1) * sizeof(WCHAR);
862
863 pRec->UserSidOffset = pos;
864 if (dwSidLength)
865 {
866 if (pos % 4 != 0)
867 pos += 4 - (pos % 4);
868 CopyMemory(Buffer + pos, lpUserSid, dwSidLength);
869 pRec->UserSidLength = dwSidLength;
870 pRec->UserSidOffset = pos;
871 pos += dwSidLength;
872 }
873
874 pRec->StringOffset = pos;
875 for (i = 0, str = lpStrings, nStrings = 0; i < wNumStrings; i++)
876 {
877 lstrcpyW((WCHAR *) (Buffer + pos), str);
878 pos += (lstrlenW(str) + 1) * sizeof(WCHAR);
879 str += lstrlenW(str) + 1;
880 nStrings++;
881 }
882 pRec->NumStrings = nStrings;
883
884 pRec->DataOffset = pos;
885 if (dwDataSize)
886 {
887 pRec->DataLength = dwDataSize;
888 CopyMemory(Buffer + pos, lpRawData, dwDataSize);
889 pos += dwDataSize;
890 }
891
892 if (pos % 4 != 0)
893 pos += 4 - (pos % 4);
894
895 *((PDWORD) (Buffer + pos)) = dwRecSize;
896
897 *lpRecSize = dwRecSize;
898 return Buffer;
899 }