I'm trying to recreate a struct in C# which will be used with Win API, this is the struct:
typedef struct _LDR_MODULE {
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;
The two members I'm not sure about are LIST_ENTRY and UNICODE_STRING, how would I mimic these in C#?
I'm coming way late to the party, but I just had to do this for a personal "curiosity project" - the signatures end up looking like:
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct LIST_ENTRY
{
public IntPtr Flink;
public IntPtr Blink;
public ListEntryWrapper Fwd
{
get
{
var fwdAddr = Flink.ToInt32();
return new ListEntryWrapper()
{
Header = Flink.ReadMemory<LIST_ENTRY>(),
Body = new IntPtr(fwdAddr + Marshal.SizeOf(typeof(LIST_ENTRY))).ReadMemory<LDR_MODULE>()
};
}
}
public ListEntryWrapper Back
{
get
{
var fwdAddr = Blink.ToInt32();
return new ListEntryWrapper()
{
Header = Flink.ReadMemory<LIST_ENTRY>(),
Body = new IntPtr(fwdAddr + Marshal.SizeOf(typeof(LIST_ENTRY))).ReadMemory<LDR_MODULE>()
};
}
}
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct ListEntryWrapper
{
public LIST_ENTRY Header;
public LDR_MODULE Body;
}
[StructLayout(LayoutKind.Sequential)]
public struct UNICODE_STRING : IDisposable
{
public ushort Length;
public ushort MaximumLength;
private IntPtr buffer;
public UNICODE_STRING(string s)
{
Length = (ushort)(s.Length * 2);
MaximumLength = (ushort)(Length + 2);
buffer = Marshal.StringToHGlobalUni(s);
}
public void Dispose()
{
Marshal.FreeHGlobal(buffer);
buffer = IntPtr.Zero;
}
public override string ToString()
{
return Marshal.PtrToStringUni(buffer);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct PEB_LDR_DATA
{
public int Length;
public int Initialized;
public int SsHandle;
public IntPtr InLoadOrderModuleListPtr;
public IntPtr InMemoryOrderModuleListPtr;
public IntPtr InInitOrderModuleListPtr;
public int EntryInProgress;
public ListEntryWrapper InLoadOrderModuleList { get { return InLoadOrderModuleListPtr.ReadMemory<ListEntryWrapper>(); } }
public ListEntryWrapper InMemoryOrderModuleList { get { return InLoadOrderModuleListPtr.ReadMemory<ListEntryWrapper>(); } }
public ListEntryWrapper InInitOrderModuleList { get { return InLoadOrderModuleListPtr.ReadMemory<ListEntryWrapper>(); } }
}
Where IntPtr.ReadMemory is just an extension method:
public static T ReadMemory<T>(this IntPtr atAddress)
{
var ret = (T)Marshal.PtrToStructure(atAddress, typeof (T));
return ret;
}