From 4e9b968c96424fadd3e9832553e30e5063aab064 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 17 Dec 2011 13:22:10 +0000 Subject: [PATCH] [EVENTLOG] - Implement ElfrReadELA. - Improve LogfReadEvent in such a way that it can return ANSI and UNICODE log entries. - Add a hack to ElfrReadELW in order to return a proper status code in case of an end-of-file situation. svn path=/trunk/; revision=54672 --- reactos/base/services/eventlog/eventlog.h | 3 +- reactos/base/services/eventlog/file.c | 216 ++++++++++++++++++++-- reactos/base/services/eventlog/rpc.c | 62 ++++++- 3 files changed, 259 insertions(+), 22 deletions(-) diff --git a/reactos/base/services/eventlog/eventlog.h b/reactos/base/services/eventlog/eventlog.h index f4db6a38690..0de6c87df9f 100644 --- a/reactos/base/services/eventlog/eventlog.h +++ b/reactos/base/services/eventlog/eventlog.h @@ -134,7 +134,8 @@ DWORD LogfReadEvent(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer, DWORD * BytesRead, - DWORD * BytesNeeded); + DWORD * BytesNeeded, + BOOL Ansi); BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, diff --git a/reactos/base/services/eventlog/file.c b/reactos/base/services/eventlog/file.c index 72ca7c15042..245bb6b9721 100644 --- a/reactos/base/services/eventlog/file.c +++ b/reactos/base/services/eventlog/file.c @@ -511,7 +511,7 @@ PLOGFILE LogfListItemByIndex(INT Index) return Result; } -INT LogfListItemCount() +INT LogfListItemCount(VOID) { PLIST_ENTRY CurrentEntry; INT i = 0; @@ -543,13 +543,171 @@ VOID LogfListRemoveItem(PLOGFILE Item) LeaveCriticalSection(&LogFileListCs); } +static BOOL +ReadAnsiLogEntry(HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead) +{ + PEVENTLOGRECORD Dst; + PEVENTLOGRECORD Src; + ANSI_STRING StringA; + UNICODE_STRING StringW; + LPWSTR SrcPtr; + LPSTR DstPtr; + LPWSTR SrcString; + LPSTR DstString; + LPVOID lpUnicodeBuffer = NULL; + DWORD dwRead = 0; + DWORD i; + DWORD dwPadding; + DWORD dwEntryLength; + PDWORD pLength; + NTSTATUS Status; + BOOL ret = TRUE; + + *lpNumberOfBytesRead = 0; + + lpUnicodeBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nNumberOfBytesToRead); + if (lpUnicodeBuffer == NULL) + { + DPRINT1("Alloc failed!\n"); + return FALSE; + } + + if (!ReadFile(hFile, lpUnicodeBuffer, nNumberOfBytesToRead, &dwRead, NULL)) + { + DPRINT1("Read failed!\n"); + ret = FALSE; + goto done; + } + + Dst = (PEVENTLOGRECORD)lpBuffer; + Src = (PEVENTLOGRECORD)lpUnicodeBuffer; + + Dst->TimeGenerated = Src->TimeGenerated; + Dst->Reserved = Src->Reserved; + Dst->RecordNumber = Src->RecordNumber; + Dst->TimeWritten = Src->TimeWritten; + Dst->EventID = Src->EventID; + Dst->EventType = Src->EventType; + Dst->EventCategory = Src->EventCategory; + Dst->NumStrings = Src->NumStrings; + Dst->UserSidLength = Src->UserSidLength; + Dst->DataLength = Src->DataLength; + + SrcPtr = (LPWSTR)((DWORD_PTR)Src + sizeof(EVENTLOGRECORD)); + DstPtr = (LPSTR)((DWORD_PTR)Dst + sizeof(EVENTLOGRECORD)); + + /* Convert the module name */ + RtlInitUnicodeString(&StringW, SrcPtr); + Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE); + if (NT_SUCCESS(Status)) + { + RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength); + + DstPtr = (PVOID)((DWORD_PTR)DstPtr + StringA.MaximumLength); + + RtlFreeAnsiString(&StringA); + } + + /* Convert the computer name */ + if (NT_SUCCESS(Status)) + { + SrcPtr = (PWSTR)((DWORD_PTR)SrcPtr + StringW.MaximumLength); + + RtlInitUnicodeString(&StringW, SrcPtr); + Status = RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE); + if (NT_SUCCESS(Status)) + { + RtlCopyMemory(DstPtr, StringA.Buffer, StringA.MaximumLength); + + DstPtr = (PVOID)((DWORD_PTR)DstPtr + StringA.MaximumLength); + + RtlFreeAnsiString(&StringA); + } + } + + /* Add the padding and the User SID*/ + if (NT_SUCCESS(Status)) + { + dwPadding = sizeof(DWORD) - (((DWORD_PTR)DstPtr - (DWORD_PTR)Dst) % sizeof(DWORD)); + RtlZeroMemory(DstPtr, dwPadding); + + DstPtr = (LPSTR)((DWORD_PTR)DstPtr + dwPadding); + RtlCopyMemory(DstPtr, + (PVOID)((DWORD_PTR)Src + Src->UserSidOffset), + Src->UserSidLength); + + Dst->UserSidOffset = (DWORD)((DWORD_PTR)DstPtr - (DWORD_PTR)Dst); + } + + + /* Convert the strings */ + if (NT_SUCCESS(Status)) + { + DstPtr = (PVOID)((DWORD_PTR)DstPtr + Src->UserSidLength); + + SrcString = (LPWSTR)((DWORD_PTR)Src + (DWORD)Src->StringOffset); + DstString = (LPSTR)DstPtr; + + for (i = 0; i < Dst->NumStrings; i++) + { + RtlInitUnicodeString(&StringW, SrcString); + + RtlUnicodeStringToAnsiString(&StringA, &StringW, TRUE); + + RtlCopyMemory(DstString, StringA.Buffer, StringA.MaximumLength); + + SrcString = (LPWSTR)((DWORD_PTR)SrcString + + (DWORD)StringW.MaximumLength); + + DstString = (LPSTR)((DWORD_PTR)DstString + + (DWORD)StringA.MaximumLength); + + RtlFreeAnsiString(&StringA); + } + + Dst->StringOffset = (DWORD)((DWORD_PTR)DstPtr - (DWORD_PTR)Dst); + + + /* Copy the binary data */ + DstPtr = (PVOID)DstString; + Dst->DataOffset = (DWORD_PTR)DstPtr - (DWORD_PTR)Dst; + + RtlCopyMemory(DstPtr, (PVOID)((DWORD_PTR)Src + Src->DataOffset), Src->DataLength); + + /* Add the padding */ + DstPtr = (PVOID)((DWORD_PTR)DstPtr + Src->DataLength); + dwPadding = sizeof(DWORD) - (((DWORD_PTR)DstPtr-(DWORD_PTR)Dst) % sizeof(DWORD)); + RtlZeroMemory(DstPtr, dwPadding); + + dwEntryLength = (DWORD)((DWORD_PTR)DstPtr + dwPadding + sizeof(DWORD) - (DWORD_PTR)Dst); + + /* Set the entry length at the end of the entry*/ + pLength = (PDWORD)((DWORD_PTR)DstPtr + dwPadding); + *pLength = dwEntryLength; + Dst->Length = dwEntryLength; + + *lpNumberOfBytesRead = dwEntryLength; + } + +done: + if (lpUnicodeBuffer != NULL) + HeapFree(GetProcessHeap(), 0, lpUnicodeBuffer); + + return ret; +} + + DWORD LogfReadEvent(PLOGFILE LogFile, DWORD Flags, DWORD * RecordNumber, DWORD BufSize, PBYTE Buffer, DWORD * BytesRead, - DWORD * BytesNeeded) + DWORD * BytesNeeded, + BOOL Ansi) { DWORD dwOffset, dwRead, dwRecSize; DWORD dwBufferUsage = 0, dwRecNum; @@ -611,10 +769,21 @@ DWORD LogfReadEvent(PLOGFILE LogFile, goto Done; } - if (!ReadFile(LogFile->hFile, Buffer, dwRecSize, &dwRead, NULL)) + if (Ansi == TRUE) { - DPRINT1("ReadFile() failed!\n"); - goto Done; + if (!ReadAnsiLogEntry(LogFile->hFile, Buffer, dwRecSize, &dwRead)) + { + DPRINT1("ReadAnsiLogEntry() failed!\n"); + goto Done; + } + } + else + { + if (!ReadFile(LogFile->hFile, Buffer, dwRecSize, &dwRead, NULL)) + { + DPRINT1("ReadFile() failed!\n"); + goto Done; + } } dwBufferUsage += dwRead; @@ -659,14 +828,28 @@ DWORD LogfReadEvent(PLOGFILE LogFile, goto Done; } - if (!ReadFile(LogFile->hFile, - Buffer + dwBufferUsage, - dwRecSize, - &dwRead, - NULL)) + if (Ansi == TRUE) { - DPRINT1("ReadFile() failed!\n"); - goto Done; + if (!ReadAnsiLogEntry(LogFile->hFile, + Buffer + dwBufferUsage, + dwRecSize, + &dwRead)) + { + DPRINT1("ReadAnsiLogEntry() failed!\n"); + goto Done; + } + } + else + { + if (!ReadFile(LogFile->hFile, + Buffer + dwBufferUsage, + dwRecSize, + &dwRead, + NULL)) + { + DPRINT1("ReadFile() failed!\n"); + goto Done; + } } dwBufferUsage += dwRead; @@ -870,9 +1053,8 @@ BOOL LogfWriteData(PLOGFILE LogFile, DWORD BufSize, PBYTE Buffer) return TRUE; } -ULONG LogfOffsetByNumber(PLOGFILE LogFile, DWORD RecordNumber) - /* Returns 0 if nothing found. */ +ULONG LogfOffsetByNumber(PLOGFILE LogFile, DWORD RecordNumber) { DWORD i; @@ -1012,10 +1194,12 @@ PBYTE LogfAllocAndBuildNewRecord(LPDWORD lpRecSize, pos += (lstrlenW(ComputerName) + 1) * sizeof(WCHAR); pRec->UserSidOffset = pos; + + if (pos % 4 != 0) + pos += 4 - (pos % 4); + if (dwSidLength) { - if (pos % 4 != 0) - pos += 4 - (pos % 4); CopyMemory(Buffer + pos, lpUserSid, dwSidLength); pRec->UserSidLength = dwSidLength; pRec->UserSidOffset = pos; diff --git a/reactos/base/services/eventlog/rpc.c b/reactos/base/services/eventlog/rpc.c index 0526e5dbd30..91a0f770083 100644 --- a/reactos/base/services/eventlog/rpc.c +++ b/reactos/base/services/eventlog/rpc.c @@ -225,6 +225,8 @@ NTSTATUS ElfrNumberOfRecords( PLOGHANDLE lpLogHandle; PLOGFILE lpLogFile; + DPRINT("ElfrNumberOfRecords()"); + lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); if (!lpLogHandle) { @@ -233,6 +235,10 @@ NTSTATUS ElfrNumberOfRecords( lpLogFile = lpLogHandle->LogFile; + DPRINT("Oldest: %lu Current: %lu\n", + lpLogFile->Header.OldestRecordNumber, + lpLogFile->Header.CurrentRecordNumber); + if (lpLogFile->Header.OldestRecordNumber == 0) *NumberOfRecords = 0; else @@ -372,8 +378,8 @@ NTSTATUS ElfrReadELW( return STATUS_INVALID_HANDLE; } - if (!Buffer) - return I_RpcMapWin32Status(ERROR_INVALID_PARAMETER); + if (!Buffer) + return STATUS_INVALID_PARAMETER; /* If sequential read, retrieve the CurrentRecord from this log handle */ if (ReadFlags & EVENTLOG_SEQUENTIAL_READ) @@ -386,7 +392,8 @@ NTSTATUS ElfrReadELW( } dwError = LogfReadEvent(lpLogHandle->LogFile, ReadFlags, &RecordNumber, - NumberOfBytesToRead, Buffer, NumberOfBytesRead, MinNumberOfBytesNeeded); + NumberOfBytesToRead, Buffer, NumberOfBytesRead, MinNumberOfBytesNeeded, + FALSE); /* Update the handles CurrentRecord if success*/ if (dwError == ERROR_SUCCESS) @@ -394,6 +401,10 @@ NTSTATUS ElfrReadELW( lpLogHandle->CurrentRecord = RecordNumber; } + /* HACK!!! */ + if (dwError == ERROR_HANDLE_EOF) + return STATUS_END_OF_FILE; + return I_RpcMapWin32Status(dwError); } @@ -664,8 +675,49 @@ NTSTATUS ElfrReadELA( DWORD *NumberOfBytesRead, DWORD *MinNumberOfBytesNeeded) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PLOGHANDLE lpLogHandle; + DWORD dwError; + DWORD RecordNumber; + + lpLogHandle = ElfGetLogHandleEntryByHandle(LogHandle); + if (!lpLogHandle) + { + return STATUS_INVALID_HANDLE; + } + + if (!Buffer) + return STATUS_INVALID_PARAMETER; + + /* If sequential read, retrieve the CurrentRecord from this log handle */ + if (ReadFlags & EVENTLOG_SEQUENTIAL_READ) + { + RecordNumber = lpLogHandle->CurrentRecord; + } + else + { + RecordNumber = RecordOffset; + } + + dwError = LogfReadEvent(lpLogHandle->LogFile, + ReadFlags, + &RecordNumber, + NumberOfBytesToRead, + Buffer, + NumberOfBytesRead, + MinNumberOfBytesNeeded, + TRUE); + + /* Update the handles CurrentRecord if success*/ + if (dwError == ERROR_SUCCESS) + { + lpLogHandle->CurrentRecord = RecordNumber; + } + + /* HACK!!! */ + if (dwError == ERROR_HANDLE_EOF) + return STATUS_END_OF_FILE; + + return I_RpcMapWin32Status(dwError); }