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
9 /* INCLUDES *****************************************************************/
13 /* GLOBALS ******************************************************************/
15 static LIST_ENTRY LogFileListHead
;
16 static CRITICAL_SECTION LogFileListCs
;
19 /* FUNCTIONS ****************************************************************/
21 BOOL
LogfInitializeNew(PLOGFILE LogFile
)
26 ZeroMemory(&LogFile
->Header
, sizeof(FILE_HEADER
));
27 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
28 SetEndOfFile(LogFile
->hFile
);
30 LogFile
->Header
.SizeOfHeader
= sizeof(FILE_HEADER
);
31 LogFile
->Header
.SizeOfHeader2
= sizeof(FILE_HEADER
);
32 LogFile
->Header
.FirstRecordOffset
= sizeof(FILE_HEADER
);
33 LogFile
->Header
.EofOffset
= sizeof(FILE_HEADER
);
34 LogFile
->Header
.MajorVersion
= MAJORVER
;
35 LogFile
->Header
.MinorVersion
= MINORVER
;
36 LogFile
->Header
.NextRecord
= 1;
38 LogFile
->Header
.Signature
= LOGFILE_SIGNATURE
;
39 if (!WriteFile(LogFile
->hFile
,
45 DPRINT1("WriteFile failed:%d!\n", GetLastError());
49 EofRec
.Ones
= 0x11111111;
50 EofRec
.Twos
= 0x22222222;
51 EofRec
.Threes
= 0x33333333;
52 EofRec
.Fours
= 0x44444444;
53 EofRec
.Size1
= sizeof(EOF_RECORD
);
54 EofRec
.Size2
= sizeof(EOF_RECORD
);
55 EofRec
.NextRecordNumber
= LogFile
->Header
.NextRecord
;
56 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecord
;
57 EofRec
.StartOffset
= LogFile
->Header
.FirstRecordOffset
;
58 EofRec
.EndOffset
= LogFile
->Header
.EofOffset
;
60 if (!WriteFile(LogFile
->hFile
,
66 DPRINT1("WriteFile failed:%d!\n", GetLastError());
70 if (!FlushFileBuffers(LogFile
->hFile
))
72 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
79 BOOL
LogfInitializeExisting(PLOGFILE LogFile
)
82 DWORD dwRecordsNumber
= 0;
83 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
85 PEVENTLOGRECORD RecBuf
;
87 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
88 INVALID_SET_FILE_POINTER
)
90 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
94 if (!ReadFile(LogFile
->hFile
,
100 DPRINT1("ReadFile failed! %d\n", GetLastError());
104 if (dwRead
!= sizeof(FILE_HEADER
))
106 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
107 return LogfInitializeNew(LogFile
);
110 if (LogFile
->Header
.SizeOfHeader
!= sizeof(FILE_HEADER
) ||
111 LogFile
->Header
.SizeOfHeader2
!= sizeof(FILE_HEADER
))
113 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
114 return LogfInitializeNew(LogFile
);
117 if (LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
119 DPRINT("EventLog: Invalid signature %x in %S.\n",
120 LogFile
->Header
.Signature
, LogFile
->FileName
);
121 return LogfInitializeNew(LogFile
);
124 if (LogFile
->Header
.EofOffset
> GetFileSize(LogFile
->hFile
, NULL
) + 1)
126 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
127 LogFile
->Header
.EofOffset
, LogFile
->FileName
);
128 return LogfInitializeNew(LogFile
);
133 dwFilePointer
= SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
);
135 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
137 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
141 if (!ReadFile(LogFile
->hFile
,
147 DPRINT1("ReadFile failed! %d\n", GetLastError());
151 if (dwRead
!= sizeof(dwRecSize
))
154 if (!ReadFile(LogFile
->hFile
,
160 DPRINT1("ReadFile() failed! %d\n", GetLastError());
164 if (dwRead
!= sizeof(dwRecSize
))
167 if (dwRecSign
!= LOGFILE_SIGNATURE
||
168 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
) + 1 ||
169 dwRecSize
< sizeof(EVENTLOGRECORD
))
174 if (SetFilePointer(LogFile
->hFile
,
175 -((LONG
) sizeof(DWORD
) * 2),
177 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
179 DPRINT1("SetFilePointer() failed! %d", GetLastError());
183 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
187 DPRINT1("Can't allocate heap!\n");
191 if (!ReadFile(LogFile
->hFile
, RecBuf
, dwRecSize
, &dwRead
, NULL
))
193 DPRINT1("ReadFile() failed! %d\n", GetLastError());
194 HeapFree(MyHeap
, 0, RecBuf
);
198 if (dwRead
!= dwRecSize
)
200 HeapFree(MyHeap
, 0, RecBuf
);
204 pdwRecSize2
= (PDWORD
) (((PBYTE
) RecBuf
) + dwRecSize
- 4);
206 if (*pdwRecSize2
!= dwRecSize
)
208 DPRINT1("Invalid size2 of record %d (%x) in %S\n",
209 dwRecordsNumber
, *pdwRecSize2
, LogFile
->LogName
);
210 HeapFree(MyHeap
, 0, RecBuf
);
216 if (!LogfAddOffsetInformation(LogFile
,
217 RecBuf
->RecordNumber
,
220 DPRINT1("LogfAddOffsetInformation() failed!\n");
221 HeapFree(MyHeap
, 0, RecBuf
);
225 HeapFree(MyHeap
, 0, RecBuf
);
228 LogFile
->Header
.NextRecord
= dwRecordsNumber
+ 1;
229 LogFile
->Header
.OldestRecord
= dwRecordsNumber
? 1 : 0; // FIXME
231 if (!SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
) ==
232 INVALID_SET_FILE_POINTER
)
234 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
238 if (!WriteFile(LogFile
->hFile
,
244 DPRINT1("WriteFile failed! %d\n", GetLastError());
248 if (!FlushFileBuffers(LogFile
->hFile
))
250 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
257 PLOGFILE
LogfCreate(WCHAR
* LogName
, WCHAR
* FileName
)
260 BOOL bResult
, bCreateNew
= FALSE
;
262 LogFile
= (LOGFILE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(LOGFILE
));
265 DPRINT1("Can't allocate heap!\n");
269 LogFile
->hFile
= CreateFile(FileName
,
270 GENERIC_READ
| GENERIC_WRITE
,
274 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
277 if (LogFile
->hFile
== INVALID_HANDLE_VALUE
)
279 DPRINT1("Can't create file %S.\n", FileName
);
280 HeapFree(MyHeap
, 0, LogFile
);
284 bCreateNew
= (GetLastError() == ERROR_ALREADY_EXISTS
) ? FALSE
: TRUE
;
287 (WCHAR
*) HeapAlloc(MyHeap
,
289 (lstrlenW(LogName
) + 1) * sizeof(WCHAR
));
291 if (LogFile
->LogName
)
292 lstrcpyW(LogFile
->LogName
, LogName
);
295 DPRINT1("Can't allocate heap\n");
296 HeapFree(MyHeap
, 0, LogFile
);
301 (WCHAR
*) HeapAlloc(MyHeap
,
303 (lstrlenW(FileName
) + 1) * sizeof(WCHAR
));
305 if (LogFile
->FileName
)
306 lstrcpyW(LogFile
->FileName
, FileName
);
309 DPRINT1("Can't allocate heap\n");
313 LogFile
->OffsetInfo
=
314 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
316 sizeof(EVENT_OFFSET_INFO
) * 64);
318 if (!LogFile
->OffsetInfo
)
320 DPRINT1("Can't allocate heap\n");
324 LogFile
->OffsetInfoSize
= 64;
327 bResult
= LogfInitializeNew(LogFile
);
329 bResult
= LogfInitializeExisting(LogFile
);
334 InitializeCriticalSection(&LogFile
->cs
);
335 LogfListAddItem(LogFile
);
341 if (LogFile
->OffsetInfo
)
342 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
344 if (LogFile
->FileName
)
345 HeapFree(MyHeap
, 0, LogFile
->FileName
);
347 if (LogFile
->LogName
)
348 HeapFree(MyHeap
, 0, LogFile
->LogName
);
350 HeapFree(MyHeap
, 0, LogFile
);
356 VOID
LogfClose(PLOGFILE LogFile
)
361 EnterCriticalSection(&LogFile
->cs
);
363 FlushFileBuffers(LogFile
->hFile
);
364 CloseHandle(LogFile
->hFile
);
365 LogfListRemoveItem(LogFile
);
367 DeleteCriticalSection(&LogFile
->cs
);
369 HeapFree(MyHeap
, 0, LogFile
->LogName
);
370 HeapFree(MyHeap
, 0, LogFile
->FileName
);
371 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
372 HeapFree(MyHeap
, 0, LogFile
);
377 VOID
LogfCloseAll(VOID
)
379 while (!IsListEmpty(&LogFileListHead
))
381 LogfClose(LogfListHead());
384 DeleteCriticalSection(&LogFileListCs
);
387 VOID
LogfListInitialize(VOID
)
389 InitializeCriticalSection(&LogFileListCs
);
390 InitializeListHead(&LogFileListHead
);
393 PLOGFILE
LogfListHead(VOID
)
395 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
398 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
400 PLIST_ENTRY CurrentEntry
;
401 PLOGFILE Result
= NULL
;
403 EnterCriticalSection(&LogFileListCs
);
405 CurrentEntry
= LogFileListHead
.Flink
;
406 while (CurrentEntry
!= &LogFileListHead
)
408 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
412 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
418 CurrentEntry
= CurrentEntry
->Flink
;
421 LeaveCriticalSection(&LogFileListCs
);
425 /* Index starting from 1 */
426 INT
LogfListItemIndexByName(WCHAR
* Name
)
428 PLIST_ENTRY CurrentEntry
;
432 EnterCriticalSection(&LogFileListCs
);
434 CurrentEntry
= LogFileListHead
.Flink
;
435 while (CurrentEntry
!= &LogFileListHead
)
437 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
441 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
447 CurrentEntry
= CurrentEntry
->Flink
;
451 LeaveCriticalSection(&LogFileListCs
);
455 /* Index starting from 1 */
456 PLOGFILE
LogfListItemByIndex(INT Index
)
458 PLIST_ENTRY CurrentEntry
;
459 PLOGFILE Result
= NULL
;
462 EnterCriticalSection(&LogFileListCs
);
464 CurrentEntry
= LogFileListHead
.Flink
;
465 while (CurrentEntry
!= &LogFileListHead
)
469 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
473 CurrentEntry
= CurrentEntry
->Flink
;
477 LeaveCriticalSection(&LogFileListCs
);
481 INT
LogfListItemCount()
483 PLIST_ENTRY CurrentEntry
;
486 EnterCriticalSection(&LogFileListCs
);
488 CurrentEntry
= LogFileListHead
.Flink
;
489 while (CurrentEntry
!= &LogFileListHead
)
491 CurrentEntry
= CurrentEntry
->Flink
;
495 LeaveCriticalSection(&LogFileListCs
);
499 VOID
LogfListAddItem(PLOGFILE Item
)
501 EnterCriticalSection(&LogFileListCs
);
502 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
503 LeaveCriticalSection(&LogFileListCs
);
506 VOID
LogfListRemoveItem(PLOGFILE Item
)
508 EnterCriticalSection(&LogFileListCs
);
509 RemoveEntryList(&Item
->ListEntry
);
510 LeaveCriticalSection(&LogFileListCs
);
513 BOOL
LogfReadEvent(PLOGFILE LogFile
,
521 DWORD dwOffset
, dwRead
, dwRecSize
;
522 DWORD dwBufferUsage
= 0, dwRecNum
;
524 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
527 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
530 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
533 dwRecNum
= RecordNumber
;
534 EnterCriticalSection(&LogFile
->cs
);
535 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
539 LeaveCriticalSection(&LogFile
->cs
);
543 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
544 INVALID_SET_FILE_POINTER
)
546 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
547 LeaveCriticalSection(&LogFile
->cs
);
551 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
553 DPRINT1("ReadFile() failed! %d\n", GetLastError());
554 LeaveCriticalSection(&LogFile
->cs
);
558 if (dwRecSize
> BufSize
)
561 *BytesNeeded
= dwRecSize
;
562 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
563 LeaveCriticalSection(&LogFile
->cs
);
567 if (SetFilePointer(LogFile
->hFile
,
568 -((LONG
) sizeof(DWORD
)),
570 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
572 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
573 LeaveCriticalSection(&LogFile
->cs
);
577 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
579 DPRINT1("ReadFile() failed! %d\n", GetLastError());
580 LeaveCriticalSection(&LogFile
->cs
);
584 dwBufferUsage
+= dwRead
;
586 while (dwBufferUsage
< BufSize
)
588 if (Flags
& EVENTLOG_FORWARDS_READ
)
593 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
597 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
598 INVALID_SET_FILE_POINTER
)
600 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
601 LeaveCriticalSection(&LogFile
->cs
);
605 if (!ReadFile(LogFile
->hFile
,
611 DPRINT1("ReadFile() failed! %d\n", GetLastError());
612 LeaveCriticalSection(&LogFile
->cs
);
616 if (dwBufferUsage
+ dwRecSize
> BufSize
)
619 if (SetFilePointer(LogFile
->hFile
,
620 -((LONG
) sizeof(DWORD
)),
622 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
624 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
625 LeaveCriticalSection(&LogFile
->cs
);
629 if (!ReadFile(LogFile
->hFile
,
630 Buffer
+ dwBufferUsage
,
635 DPRINT1("ReadFile() failed! %d\n", GetLastError());
636 LeaveCriticalSection(&LogFile
->cs
);
640 dwBufferUsage
+= dwRead
;
643 *BytesRead
= dwBufferUsage
;
644 LeaveCriticalSection(&LogFile
->cs
);
648 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
658 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
660 EnterCriticalSection(&LogFile
->cs
);
662 if (SetFilePointer(LogFile
->hFile
,
663 LogFile
->Header
.EofOffset
,
665 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
667 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
668 LeaveCriticalSection(&LogFile
->cs
);
672 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
674 DPRINT1("WriteFile() failed! %d\n", GetLastError());
675 LeaveCriticalSection(&LogFile
->cs
);
679 if (!LogfAddOffsetInformation(LogFile
,
680 LogFile
->Header
.NextRecord
,
681 LogFile
->Header
.EofOffset
))
683 LeaveCriticalSection(&LogFile
->cs
);
687 LogFile
->Header
.NextRecord
++;
688 LogFile
->Header
.EofOffset
+= dwWritten
;
690 if (LogFile
->Header
.OldestRecord
== 0)
691 LogFile
->Header
.OldestRecord
= 1;
693 EofRec
.Ones
= 0x11111111;
694 EofRec
.Twos
= 0x22222222;
695 EofRec
.Threes
= 0x33333333;
696 EofRec
.Fours
= 0x44444444;
697 EofRec
.Size1
= sizeof(EOF_RECORD
);
698 EofRec
.Size2
= sizeof(EOF_RECORD
);
699 EofRec
.NextRecordNumber
= LogFile
->Header
.NextRecord
;
700 EofRec
.OldestRecordNumber
= LogFile
->Header
.OldestRecord
;
701 EofRec
.StartOffset
= LogFile
->Header
.FirstRecordOffset
;
702 EofRec
.EndOffset
= LogFile
->Header
.EofOffset
;
704 if (!WriteFile(LogFile
->hFile
,
710 DPRINT1("WriteFile() failed! %d\n", GetLastError());
711 LeaveCriticalSection(&LogFile
->cs
);
715 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
716 INVALID_SET_FILE_POINTER
)
718 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
719 LeaveCriticalSection(&LogFile
->cs
);
723 if (!WriteFile(LogFile
->hFile
,
729 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
730 LeaveCriticalSection(&LogFile
->cs
);
734 if (!FlushFileBuffers(LogFile
->hFile
))
736 LeaveCriticalSection(&LogFile
->cs
);
737 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
741 LeaveCriticalSection(&LogFile
->cs
);
745 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
747 /* Returns 0 if nothing found. */
751 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
753 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
754 return LogFile
->OffsetInfo
[i
].EventOffset
;
759 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
761 return LogFile
->Header
.OldestRecord
;
764 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
766 LPVOID NewOffsetInfo
;
768 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
770 NewOffsetInfo
= HeapReAlloc(MyHeap
,
773 (LogFile
->OffsetInfoSize
+ 64) *
774 sizeof(EVENT_OFFSET_INFO
));
778 DPRINT1("Can't reallocate heap.\n");
782 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
783 LogFile
->OffsetInfoSize
+= 64;
786 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
787 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
788 LogFile
->OffsetInfoNext
++;
793 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
794 DWORD dwRecordNumber
,
799 LPCWSTR ComputerName
,
808 PEVENTLOGRECORD pRec
;
811 UINT i
, pos
, nStrings
;
815 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
816 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
818 if (dwRecSize
% 4 != 0)
819 dwRecSize
+= 4 - (dwRecSize
% 4);
821 dwRecSize
+= dwSidLength
;
823 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
825 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
826 str
+= lstrlenW(str
) + 1;
829 dwRecSize
+= dwDataSize
;
830 if (dwRecSize
% 4 != 0)
831 dwRecSize
+= 4 - (dwRecSize
% 4);
835 Buffer
= (BYTE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
839 DPRINT1("Can't allocate heap!\n");
843 pRec
= (PEVENTLOGRECORD
) Buffer
;
844 pRec
->Length
= dwRecSize
;
845 pRec
->Reserved
= LOGFILE_SIGNATURE
;
846 pRec
->RecordNumber
= dwRecordNumber
;
848 GetSystemTime(&SysTime
);
849 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
850 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
852 pRec
->EventID
= dwEventId
;
853 pRec
->EventType
= wType
;
854 pRec
->NumStrings
= wNumStrings
;
855 pRec
->EventCategory
= wCategory
;
857 pos
= sizeof(EVENTLOGRECORD
);
859 lstrcpyW((WCHAR
*) (Buffer
+ pos
), SourceName
);
860 pos
+= (lstrlenW(SourceName
) + 1) * sizeof(WCHAR
);
861 lstrcpyW((WCHAR
*) (Buffer
+ pos
), ComputerName
);
862 pos
+= (lstrlenW(ComputerName
) + 1) * sizeof(WCHAR
);
864 pRec
->UserSidOffset
= pos
;
868 pos
+= 4 - (pos
% 4);
869 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
870 pRec
->UserSidLength
= dwSidLength
;
871 pRec
->UserSidOffset
= pos
;
875 pRec
->StringOffset
= pos
;
876 for (i
= 0, str
= lpStrings
, nStrings
= 0; i
< wNumStrings
; i
++)
878 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
879 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
880 str
+= lstrlenW(str
) + 1;
883 pRec
->NumStrings
= nStrings
;
885 pRec
->DataOffset
= pos
;
888 pRec
->DataLength
= dwDataSize
;
889 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
894 pos
+= 4 - (pos
% 4);
896 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
898 *lpRecSize
= dwRecSize
;
902 __inline
void LogfFreeRecord(LPVOID Rec
)
904 HeapFree(MyHeap
, 0, Rec
);