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
;
18 /* FUNCTIONS ****************************************************************/
20 BOOL
LogfInitializeNew(PLOGFILE LogFile
)
25 ZeroMemory(&LogFile
->Header
, sizeof(FILE_HEADER
));
26 SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
);
27 SetEndOfFile(LogFile
->hFile
);
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;
37 LogFile
->Header
.Signature
= LOGFILE_SIGNATURE
;
38 if (!WriteFile(LogFile
->hFile
,
44 DPRINT1("WriteFile failed:%d!\n", GetLastError());
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
;
59 if (!WriteFile(LogFile
->hFile
,
65 DPRINT1("WriteFile failed:%d!\n", GetLastError());
69 if (!FlushFileBuffers(LogFile
->hFile
))
71 DPRINT1("FlushFileBuffers failed:%d!\n", GetLastError());
78 BOOL
LogfInitializeExisting(PLOGFILE LogFile
)
81 DWORD dwRecordsNumber
= 0;
82 DWORD dwRecSize
, dwRecSign
, dwFilePointer
;
84 PEVENTLOGRECORD RecBuf
;
86 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
87 INVALID_SET_FILE_POINTER
)
89 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
93 if (!ReadFile(LogFile
->hFile
,
99 DPRINT1("ReadFile failed! %d\n", GetLastError());
103 if (dwRead
!= sizeof(FILE_HEADER
))
105 DPRINT("EventLog: Invalid file %S.\n", LogFile
->FileName
);
106 return LogfInitializeNew(LogFile
);
109 if (LogFile
->Header
.SizeOfHeader
!= sizeof(FILE_HEADER
) ||
110 LogFile
->Header
.SizeOfHeader2
!= sizeof(FILE_HEADER
))
112 DPRINT("EventLog: Invalid header size in %S.\n", LogFile
->FileName
);
113 return LogfInitializeNew(LogFile
);
116 if (LogFile
->Header
.Signature
!= LOGFILE_SIGNATURE
)
118 DPRINT("EventLog: Invalid signature %x in %S.\n",
119 LogFile
->Header
.Signature
, LogFile
->FileName
);
120 return LogfInitializeNew(LogFile
);
123 if (LogFile
->Header
.EofOffset
> GetFileSize(LogFile
->hFile
, NULL
) + 1)
125 DPRINT("EventLog: Invalid eof offset %x in %S.\n",
126 LogFile
->Header
.EofOffset
, LogFile
->FileName
);
127 return LogfInitializeNew(LogFile
);
132 dwFilePointer
= SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
);
134 if (dwFilePointer
== INVALID_SET_FILE_POINTER
)
136 DPRINT1("SetFilePointer failed! %d\n", GetLastError());
140 if (!ReadFile(LogFile
->hFile
,
146 DPRINT1("ReadFile failed! %d\n", GetLastError());
150 if (dwRead
!= sizeof(dwRecSize
))
153 if (!ReadFile(LogFile
->hFile
,
159 DPRINT1("ReadFile() failed! %d\n", GetLastError());
163 if (dwRead
!= sizeof(dwRecSize
))
166 if (dwRecSign
!= LOGFILE_SIGNATURE
||
167 dwRecSize
+ dwFilePointer
> GetFileSize(LogFile
->hFile
, NULL
) + 1 ||
168 dwRecSize
< sizeof(EVENTLOGRECORD
))
173 if (SetFilePointer(LogFile
->hFile
,
174 -((LONG
) sizeof(DWORD
) * 2),
176 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
178 DPRINT1("SetFilePointer() failed! %d", GetLastError());
182 RecBuf
= (PEVENTLOGRECORD
) HeapAlloc(MyHeap
, 0, dwRecSize
);
186 DPRINT1("Can't allocate heap!\n");
190 if (!ReadFile(LogFile
->hFile
, RecBuf
, dwRecSize
, &dwRead
, NULL
))
192 DPRINT1("ReadFile() failed! %d\n", GetLastError());
193 HeapFree(MyHeap
, 0, RecBuf
);
197 if (dwRead
!= dwRecSize
)
199 HeapFree(MyHeap
, 0, RecBuf
);
203 pdwRecSize2
= (PDWORD
) (((PBYTE
) RecBuf
) + dwRecSize
- 4);
205 if (*pdwRecSize2
!= dwRecSize
)
207 DPRINT1("Invalid size2 of record %d (%x) in %S\n",
208 dwRecordsNumber
, *pdwRecSize2
, LogFile
->LogName
);
209 HeapFree(MyHeap
, 0, RecBuf
);
215 if (!LogfAddOffsetInformation(LogFile
,
216 RecBuf
->RecordNumber
,
219 DPRINT1("LogfAddOffsetInformation() failed!\n");
220 HeapFree(MyHeap
, 0, RecBuf
);
224 HeapFree(MyHeap
, 0, RecBuf
);
227 LogFile
->Header
.NextRecord
= dwRecordsNumber
+ 1;
228 LogFile
->Header
.OldestRecord
= dwRecordsNumber
? 1 : 0; // FIXME
230 if (!SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_CURRENT
) ==
231 INVALID_SET_FILE_POINTER
)
233 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
237 if (!WriteFile(LogFile
->hFile
,
243 DPRINT1("WriteFile failed! %d\n", GetLastError());
247 if (!FlushFileBuffers(LogFile
->hFile
))
249 DPRINT1("FlushFileBuffers failed! %d\n", GetLastError());
256 PLOGFILE
LogfCreate(WCHAR
* LogName
, WCHAR
* FileName
)
259 BOOL bResult
, bCreateNew
= FALSE
;
261 LogFile
= (LOGFILE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, sizeof(LOGFILE
));
264 DPRINT1("Can't allocate heap!\n");
268 LogFile
->hFile
= CreateFile(FileName
,
269 GENERIC_READ
| GENERIC_WRITE
,
273 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
276 if (LogFile
->hFile
== INVALID_HANDLE_VALUE
)
278 DPRINT1("Can't create file %S.\n", FileName
);
279 HeapFree(MyHeap
, 0, LogFile
);
283 bCreateNew
= (GetLastError() == ERROR_ALREADY_EXISTS
) ? FALSE
: TRUE
;
286 (WCHAR
*) HeapAlloc(MyHeap
,
288 (lstrlenW(LogName
) + 1) * sizeof(WCHAR
));
290 if (LogFile
->LogName
)
291 lstrcpyW(LogFile
->LogName
, LogName
);
294 DPRINT1("Can't allocate heap\n");
295 HeapFree(MyHeap
, 0, LogFile
);
300 (WCHAR
*) HeapAlloc(MyHeap
,
302 (lstrlenW(FileName
) + 1) * sizeof(WCHAR
));
304 if (LogFile
->FileName
)
305 lstrcpyW(LogFile
->FileName
, FileName
);
308 DPRINT1("Can't allocate heap\n");
312 LogFile
->OffsetInfo
=
313 (PEVENT_OFFSET_INFO
) HeapAlloc(MyHeap
,
315 sizeof(EVENT_OFFSET_INFO
) * 64);
317 if (!LogFile
->OffsetInfo
)
319 DPRINT1("Can't allocate heap\n");
323 LogFile
->OffsetInfoSize
= 64;
326 bResult
= LogfInitializeNew(LogFile
);
328 bResult
= LogfInitializeExisting(LogFile
);
333 InitializeCriticalSection(&LogFile
->cs
);
334 LogfListAddItem(LogFile
);
340 if (LogFile
->OffsetInfo
)
341 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
343 if (LogFile
->FileName
)
344 HeapFree(MyHeap
, 0, LogFile
->FileName
);
346 if (LogFile
->LogName
)
347 HeapFree(MyHeap
, 0, LogFile
->LogName
);
349 HeapFree(MyHeap
, 0, LogFile
);
355 VOID
LogfClose(PLOGFILE LogFile
)
360 EnterCriticalSection(&LogFile
->cs
);
362 FlushFileBuffers(LogFile
->hFile
);
363 CloseHandle(LogFile
->hFile
);
364 LogfListRemoveItem(LogFile
);
366 DeleteCriticalSection(&LogFile
->cs
);
368 HeapFree(MyHeap
, 0, LogFile
->LogName
);
369 HeapFree(MyHeap
, 0, LogFile
->FileName
);
370 HeapFree(MyHeap
, 0, LogFile
->OffsetInfo
);
371 HeapFree(MyHeap
, 0, LogFile
);
376 VOID
LogfCloseAll(VOID
)
378 while (!IsListEmpty(&LogFileListHead
))
380 LogfClose(LogfListHead());
383 DeleteCriticalSection(&LogFileListCs
);
386 VOID
LogfListInitialize(VOID
)
388 InitializeCriticalSection(&LogFileListCs
);
389 InitializeListHead(&LogFileListHead
);
392 PLOGFILE
LogfListHead(VOID
)
394 return CONTAINING_RECORD(LogFileListHead
.Flink
, LOGFILE
, ListEntry
);
397 PLOGFILE
LogfListItemByName(WCHAR
* Name
)
399 PLIST_ENTRY CurrentEntry
;
400 PLOGFILE Result
= NULL
;
402 EnterCriticalSection(&LogFileListCs
);
404 CurrentEntry
= LogFileListHead
.Flink
;
405 while (CurrentEntry
!= &LogFileListHead
)
407 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
411 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
417 CurrentEntry
= CurrentEntry
->Flink
;
420 LeaveCriticalSection(&LogFileListCs
);
424 /* Index starting from 1 */
425 INT
LogfListItemIndexByName(WCHAR
* Name
)
427 PLIST_ENTRY CurrentEntry
;
431 EnterCriticalSection(&LogFileListCs
);
433 CurrentEntry
= LogFileListHead
.Flink
;
434 while (CurrentEntry
!= &LogFileListHead
)
436 PLOGFILE Item
= CONTAINING_RECORD(CurrentEntry
,
440 if (Item
->LogName
&& !lstrcmpi(Item
->LogName
, Name
))
446 CurrentEntry
= CurrentEntry
->Flink
;
450 LeaveCriticalSection(&LogFileListCs
);
454 /* Index starting from 1 */
455 PLOGFILE
LogfListItemByIndex(INT Index
)
457 PLIST_ENTRY CurrentEntry
;
458 PLOGFILE Result
= NULL
;
461 EnterCriticalSection(&LogFileListCs
);
463 CurrentEntry
= LogFileListHead
.Flink
;
464 while (CurrentEntry
!= &LogFileListHead
)
468 Result
= CONTAINING_RECORD(CurrentEntry
, LOGFILE
, ListEntry
);
472 CurrentEntry
= CurrentEntry
->Flink
;
476 LeaveCriticalSection(&LogFileListCs
);
480 INT
LogfListItemCount()
482 PLIST_ENTRY CurrentEntry
;
485 EnterCriticalSection(&LogFileListCs
);
487 CurrentEntry
= LogFileListHead
.Flink
;
488 while (CurrentEntry
!= &LogFileListHead
)
490 CurrentEntry
= CurrentEntry
->Flink
;
494 LeaveCriticalSection(&LogFileListCs
);
498 VOID
LogfListAddItem(PLOGFILE Item
)
500 EnterCriticalSection(&LogFileListCs
);
501 InsertTailList(&LogFileListHead
, &Item
->ListEntry
);
502 LeaveCriticalSection(&LogFileListCs
);
505 VOID
LogfListRemoveItem(PLOGFILE Item
)
507 EnterCriticalSection(&LogFileListCs
);
508 RemoveEntryList(&Item
->ListEntry
);
509 LeaveCriticalSection(&LogFileListCs
);
512 BOOL
LogfReadEvent(PLOGFILE LogFile
,
520 DWORD dwOffset
, dwRead
, dwRecSize
;
521 DWORD dwBufferUsage
= 0, dwRecNum
;
523 if (Flags
& EVENTLOG_FORWARDS_READ
&& Flags
& EVENTLOG_BACKWARDS_READ
)
526 if (!(Flags
& EVENTLOG_FORWARDS_READ
) && !(Flags
& EVENTLOG_BACKWARDS_READ
))
529 if (!Buffer
|| !BytesRead
|| !BytesNeeded
)
532 dwRecNum
= RecordNumber
;
533 EnterCriticalSection(&LogFile
->cs
);
534 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
538 LeaveCriticalSection(&LogFile
->cs
);
542 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
543 INVALID_SET_FILE_POINTER
)
545 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
546 LeaveCriticalSection(&LogFile
->cs
);
550 if (!ReadFile(LogFile
->hFile
, &dwRecSize
, sizeof(DWORD
), &dwRead
, NULL
))
552 DPRINT1("ReadFile() failed! %d\n", GetLastError());
553 LeaveCriticalSection(&LogFile
->cs
);
557 if (dwRecSize
> BufSize
)
560 *BytesNeeded
= dwRecSize
;
561 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
562 LeaveCriticalSection(&LogFile
->cs
);
566 if (SetFilePointer(LogFile
->hFile
,
567 -((LONG
) sizeof(DWORD
)),
569 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
571 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
572 LeaveCriticalSection(&LogFile
->cs
);
576 if (!ReadFile(LogFile
->hFile
, Buffer
, dwRecSize
, &dwRead
, NULL
))
578 DPRINT1("ReadFile() failed! %d\n", GetLastError());
579 LeaveCriticalSection(&LogFile
->cs
);
583 dwBufferUsage
+= dwRead
;
585 while (dwBufferUsage
< BufSize
)
587 if (Flags
& EVENTLOG_FORWARDS_READ
)
592 dwOffset
= LogfOffsetByNumber(LogFile
, dwRecNum
);
596 if (SetFilePointer(LogFile
->hFile
, dwOffset
, NULL
, FILE_BEGIN
) ==
597 INVALID_SET_FILE_POINTER
)
599 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
600 LeaveCriticalSection(&LogFile
->cs
);
604 if (!ReadFile(LogFile
->hFile
,
610 DPRINT1("ReadFile() failed! %d\n", GetLastError());
611 LeaveCriticalSection(&LogFile
->cs
);
615 if (dwBufferUsage
+ dwRecSize
> BufSize
)
618 if (SetFilePointer(LogFile
->hFile
,
619 -((LONG
) sizeof(DWORD
)),
621 FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
623 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
624 LeaveCriticalSection(&LogFile
->cs
);
628 if (!ReadFile(LogFile
->hFile
,
629 Buffer
+ dwBufferUsage
,
634 DPRINT1("ReadFile() failed! %d\n", GetLastError());
635 LeaveCriticalSection(&LogFile
->cs
);
639 dwBufferUsage
+= dwRead
;
642 *BytesRead
= dwBufferUsage
;
643 LeaveCriticalSection(&LogFile
->cs
);
647 BOOL
LogfWriteData(PLOGFILE LogFile
, DWORD BufSize
, PBYTE Buffer
)
657 SystemTimeToEventTime(&st
, &((PEVENTLOGRECORD
) Buffer
)->TimeWritten
);
659 EnterCriticalSection(&LogFile
->cs
);
661 if (SetFilePointer(LogFile
->hFile
,
662 LogFile
->Header
.EofOffset
,
664 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
666 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
667 LeaveCriticalSection(&LogFile
->cs
);
671 if (!WriteFile(LogFile
->hFile
, Buffer
, BufSize
, &dwWritten
, NULL
))
673 DPRINT1("WriteFile() failed! %d\n", GetLastError());
674 LeaveCriticalSection(&LogFile
->cs
);
678 if (!LogfAddOffsetInformation(LogFile
,
679 LogFile
->Header
.NextRecord
,
680 LogFile
->Header
.EofOffset
))
682 LeaveCriticalSection(&LogFile
->cs
);
686 LogFile
->Header
.NextRecord
++;
687 LogFile
->Header
.EofOffset
+= dwWritten
;
689 if (LogFile
->Header
.OldestRecord
== 0)
690 LogFile
->Header
.OldestRecord
= 1;
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
;
703 if (!WriteFile(LogFile
->hFile
,
709 DPRINT1("WriteFile() failed! %d\n", GetLastError());
710 LeaveCriticalSection(&LogFile
->cs
);
714 if (SetFilePointer(LogFile
->hFile
, 0, NULL
, FILE_BEGIN
) ==
715 INVALID_SET_FILE_POINTER
)
717 DPRINT1("SetFilePointer() failed! %d\n", GetLastError());
718 LeaveCriticalSection(&LogFile
->cs
);
722 if (!WriteFile(LogFile
->hFile
,
728 DPRINT1("WriteFile failed! LastError = %d\n", GetLastError());
729 LeaveCriticalSection(&LogFile
->cs
);
733 if (!FlushFileBuffers(LogFile
->hFile
))
735 LeaveCriticalSection(&LogFile
->cs
);
736 DPRINT1("FlushFileBuffers() failed! %d\n", GetLastError());
740 LeaveCriticalSection(&LogFile
->cs
);
744 ULONG
LogfOffsetByNumber(PLOGFILE LogFile
, DWORD RecordNumber
)
746 /* Returns 0 if nothing found. */
750 for (i
= 0; i
< LogFile
->OffsetInfoNext
; i
++)
752 if (LogFile
->OffsetInfo
[i
].EventNumber
== RecordNumber
)
753 return LogFile
->OffsetInfo
[i
].EventOffset
;
758 DWORD
LogfGetOldestRecord(PLOGFILE LogFile
)
760 return LogFile
->Header
.OldestRecord
;
763 BOOL
LogfAddOffsetInformation(PLOGFILE LogFile
, ULONG ulNumber
, ULONG ulOffset
)
765 LPVOID NewOffsetInfo
;
767 if (LogFile
->OffsetInfoNext
== LogFile
->OffsetInfoSize
)
769 NewOffsetInfo
= HeapReAlloc(MyHeap
,
772 (LogFile
->OffsetInfoSize
+ 64) *
773 sizeof(EVENT_OFFSET_INFO
));
777 DPRINT1("Can't reallocate heap.\n");
781 LogFile
->OffsetInfo
= (PEVENT_OFFSET_INFO
) NewOffsetInfo
;
782 LogFile
->OffsetInfoSize
+= 64;
785 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventNumber
= ulNumber
;
786 LogFile
->OffsetInfo
[LogFile
->OffsetInfoNext
].EventOffset
= ulOffset
;
787 LogFile
->OffsetInfoNext
++;
792 PBYTE
LogfAllocAndBuildNewRecord(LPDWORD lpRecSize
,
793 DWORD dwRecordNumber
,
798 LPCWSTR ComputerName
,
807 PEVENTLOGRECORD pRec
;
810 UINT i
, pos
, nStrings
;
814 sizeof(EVENTLOGRECORD
) + (lstrlenW(ComputerName
) +
815 lstrlenW(SourceName
) + 2) * sizeof(WCHAR
);
817 if (dwRecSize
% 4 != 0)
818 dwRecSize
+= 4 - (dwRecSize
% 4);
820 dwRecSize
+= dwSidLength
;
822 for (i
= 0, str
= lpStrings
; i
< wNumStrings
; i
++)
824 dwRecSize
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
825 str
+= lstrlenW(str
) + 1;
828 dwRecSize
+= dwDataSize
;
829 if (dwRecSize
% 4 != 0)
830 dwRecSize
+= 4 - (dwRecSize
% 4);
834 Buffer
= (BYTE
*) HeapAlloc(MyHeap
, HEAP_ZERO_MEMORY
, dwRecSize
);
838 DPRINT1("Can't allocate heap!\n");
842 pRec
= (PEVENTLOGRECORD
) Buffer
;
843 pRec
->Length
= dwRecSize
;
844 pRec
->Reserved
= LOGFILE_SIGNATURE
;
845 pRec
->RecordNumber
= dwRecordNumber
;
847 GetSystemTime(&SysTime
);
848 SystemTimeToEventTime(&SysTime
, &pRec
->TimeGenerated
);
849 SystemTimeToEventTime(&SysTime
, &pRec
->TimeWritten
);
851 pRec
->EventID
= dwEventId
;
852 pRec
->EventType
= wType
;
853 pRec
->NumStrings
= wNumStrings
;
854 pRec
->EventCategory
= wCategory
;
856 pos
= sizeof(EVENTLOGRECORD
);
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
);
863 pRec
->UserSidOffset
= pos
;
867 pos
+= 4 - (pos
% 4);
868 CopyMemory(Buffer
+ pos
, lpUserSid
, dwSidLength
);
869 pRec
->UserSidLength
= dwSidLength
;
870 pRec
->UserSidOffset
= pos
;
874 pRec
->StringOffset
= pos
;
875 for (i
= 0, str
= lpStrings
, nStrings
= 0; i
< wNumStrings
; i
++)
877 lstrcpyW((WCHAR
*) (Buffer
+ pos
), str
);
878 pos
+= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
879 str
+= lstrlenW(str
) + 1;
882 pRec
->NumStrings
= nStrings
;
884 pRec
->DataOffset
= pos
;
887 pRec
->DataLength
= dwDataSize
;
888 CopyMemory(Buffer
+ pos
, lpRawData
, dwDataSize
);
893 pos
+= 4 - (pos
% 4);
895 *((PDWORD
) (Buffer
+ pos
)) = dwRecSize
;
897 *lpRecSize
= dwRecSize
;