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