LIST_ENTRY和UNICODE_STRING pinvoke C#

时间:2011-07-27 00:49:11

标签: c# winapi pinvoke

我正在尝试在C#中重新创建一个将与Win API一起使用的结构,这是结构:

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;

我不确定的两个成员是LIST_ENTRY和UNICODE_STRING,我将如何在C#中模仿这些?

2 个答案:

答案 0 :(得分:3)

我的建议是为计划与LDR_MODULE一起使用的函数创建托管C ++包装器。用pinvoke做这种复杂的结构会非常痛苦。

答案 1 :(得分:3)

我来参加派对的时间已经很晚了,但我只是为了个人的“好奇心项目”而这么做 - 签名最终看起来像:

    [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>(); } }
    }

其中IntPtr.ReadMemory只是一个扩展方法:

    public static T ReadMemory<T>(this IntPtr atAddress)
    {
        var ret = (T)Marshal.PtrToStructure(atAddress, typeof (T));
        return ret;
    }