I've been working on an application that use API to get events from the Windows event log. I'm stuck on pointer offsets at the moment. The specific struct I'm using is EVENTLOGRECORD (see: http://msdn.microsoft.com/en-us/library/aa363646(v=vs.85).aspx). My C# struct is defined as:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
internal struct EVENTLOGRECORD
{
internal UInt32 Length;
internal UInt32 Reserved;
internal UInt32 RecordNumber;
internal UInt32 TimeGenerated;
internal UInt32 TimeWritten;
internal UInt32 EventID;
internal UInt16 EventType;
internal UInt16 NumStrings;
internal UInt16 EventCategory;
internal UInt16 ReservedFlags;
internal UInt32 ClosingRecordNumber;
internal UInt32 StringOffset;
internal UInt32 UserSidLength;
internal UInt32 UserSidOffset;
internal UInt32 DataLength;
internal UInt32 DataOffset;
}
My ReadEventLog function is declared as:
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "ReadEventLog")]
internal static extern Boolean ReadEventLog(IntPtr hEventLog, EVT_READ_FLAGS dwReadFlags, UInt32 dwRecordOffset, IntPtr lpBuffer, UInt32 nNumberOfBytesToRead, out UInt32 pnBytesRead, out UInt32 pnMinNumberOfBytesNeeded);
I'm able to get the struct filled with data and I can get to SourceName and ComputerName sections by using IntPtr.Add. Example:
IntPtr pSrc = IntPtr.Add(pRecord, Marshal.SizeOf(typeof(EVENTLOGRECORD)));
string sSrc = Marshal.PtrToStringAuto(pSrc);
Console.WriteLine("source: {0}\n", sSrc);
IntPtr pComp = IntPtr.Add(pSrc, (sSrc.Length * 2) + 2);
string sComp = Marshal.PtrToStringAuto(pComp);
Console.WriteLine("computer: {0}\n", sComp);
My issue is trying to get the Strings portion from the struct. I can't seem to figure out what the correct offsets will be. I can do it in C++, but I can't seem to make it work in C#. Here's a snippet of what I use in C++ (elr is (EVENTLOGRECORD*)pRecord):
char* strings = (LPSTR)((LPBYTE) elr + elr->StringOffset);
while (elr->NumStrings)
{
wprintf(L"String: %s\n", strings);
strings += (wcslen((wchar_t*)strings) * sizeof(wchar_t)) + sizeof(wchar_t);
elr->NumStrings--;
}
Hopefully someone can help explain what I'm missing. I'd also be curious if there are any alternatives to IntPtr.Add since that require .NET 4.0. I'm not an expert with p/invoke by any means. Thanks.