最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - How to extract dialog items from an MFC DLL? - Stack Overflow

programmeradmin1浏览0评论

How can I correctly extract all Control texts from an MFC DLL with C# and PInvoke?

The problem is that there are two formats: DLGTEMPLATE and DLGTEMPLATEEX. In addition in these resources, there are Items and these also have two formats: DLGITEMTEMPLATE and DLGITEMTEMPLATEEX.

I use PInvoke to call Windows APIs: FindResource, LoadResource, LockResource, EnumResourceNames. I successfully could extract Texts from the Dialog. I enumerate through the Dialog resources, could retrieve the ID, the Caption, and many Control texts.

But still, there are many texts, which are not extracted correctly. And when I switch the DLL and use another, 50% work and the others don't.

So, I did research on the structs of the 4 Formats and saw that the extended Formats have variable elements. A few of them don't have a static size, but every dialog resource can have a different one. I work with pointers.

This is for the Items, because the code recognizes if it is an Extended format or not. Then when the normal Template is done, it iterates through the Items. But nevertheless, there are problems. And the normal Dialog Format DLGTEMPLATE does not work. Something is wrong.

This problem has haunted me for days and I need to fix it.

if (isExtended)
    {
        // ---- DLGTEMPLATEEX ----
        ushort dlgVer = (ushort)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  
        ushort signature = (ushort)Marshal.ReadInt16(currentPtr);
        currentPtr = IntPtr.Add(currentPtr, 2);  
        uint helpID = (uint)Marshal.ReadInt32(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 4);  
        uint exStyle = (uint)Marshal.ReadInt32(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 4);  
        uint style = (uint)Marshal.ReadInt32(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 4);  
        ushort cDlgItems = (ushort)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  
        short x = (short)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  
        short y = (short)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  
        short cx = (short)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  
        short cy = (short)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  

        // Variable Fields
        SkipDialogField(ref currentPtr); // Menu
        SkipDialogField(ref currentPtr); // Window Class
        string title = ReadUnicodeString(ref currentPtr); // Dialog Title
        result.DialogTitle = title;

        if ((style & 0x40) != 0)
        {
            ushort fontSize = (ushort)Marshal.ReadInt16(currentPtr); 
            currentPtr = IntPtr.Add(currentPtr, 2);  
            string fontName = ReadUnicodeString(ref currentPtr); 
        }

        result.ControlTexts = ParseDialogItems(ref currentPtr, cDlgItems, true);
    }
    else
    {
        // ---- Standard-DLGTEMPLATE ----
        uint style = (uint)Marshal.ReadInt32(currentPtr);
        currentPtr = IntPtr.Add(currentPtr, 4);  
        uint dwExtendedStyle = (uint)Marshal.ReadInt32(currentPtr);
        currentPtr = IntPtr.Add(currentPtr, 4); 
        ushort cdit = (ushort)Marshal.ReadInt16(currentPtr);
        currentPtr = IntPtr.Add(currentPtr, 2);  
        short x = (short)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  
        short y = (short)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  
        short cx = (short)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  
        short cy = (short)Marshal.ReadInt16(currentPtr); 
        currentPtr = IntPtr.Add(currentPtr, 2);  

        // Variable Fields: Menu, Window Class, Dialog Title
        SkipDialogField(ref currentPtr); // Menu
        SkipDialogField(ref currentPtr); // Window Class
        string title = ReadUnicodeString(ref currentPtr); // Dialog Title
        result.DialogTitle = title;

        
        if ((style & 0x40) != 0)
        {
            ushort fontSize = (ushort)Marshal.ReadInt16(currentPtr); 
            currentPtr = IntPtr.Add(currentPtr, 2);  
            string fontName = ReadUnicodeString(ref currentPtr); 
        }

 
        result.ControlTexts = ParseDialogItems(ref currentPtr, cdit, false);
    }
private string ReadUnicodeString(ref IntPtr ptr)
{
    StringBuilder sb = new StringBuilder();
    long startAddress = ptr.ToInt64();

    while (true)
    {
        char ch = (char)Marshal.ReadInt16(ptr);
        ptr = IntPtr.Add(ptr, 2);
        if (ch == '\0') break;
        sb.Append(ch);
    }

    return sb.ToString();
}

// To Skip the variable Fields 
private void SkipDialogField(ref IntPtr ptr)
{
    long startPtr = ptr.ToInt64();
    ushort check = (ushort)Marshal.ReadInt16(ptr);

    ptr = IntPtr.Add(ptr, 2);

    if (check == 0x0000)
    {
        ptr = IntPtr.Add(ptr, 2);
    }
    else if (check == 0xFFFF)
    {
        ptr = IntPtr.Add(ptr, 2);
    }
    else
    {
        ReadUnicodeString(ref ptr);
    }
}
private List<string> ParseDialogItems(ref IntPtr ptr, ushort controlCount, bool isExtended)
{
    List<string> controlTexts = new List<string>();
    for (int i = 0; i < controlCount; i++)
    {
        uint style = 0, exStyle = 0;

        if (isExtended)
        {
            ptr = IntPtr.Add(ptr, 4);
            exStyle = (uint)Marshal.ReadInt32(ptr);
            ptr = IntPtr.Add(ptr, 4);
            style = (uint)Marshal.ReadInt32(ptr);
            ptr = IntPtr.Add(ptr, 16);
        }
        else
        {
            style = (uint)Marshal.ReadInt32(ptr);
            ptr = IntPtr.Add(ptr, 4);
            exStyle = (uint)Marshal.ReadInt32(ptr);
            ptr = IntPtr.Add(ptr, 10);
        }

        SkipDialogField(ref ptr);
        string ctrlText = ReadUnicodeString(ref ptr);
        controlTexts.Add(ctrlText);

        ushort extraDataSize = (ushort)Marshal.ReadInt16(ptr);
        ptr = IntPtr.Add(ptr, 2 + extraDataSize);
    }
    return controlTexts;
}

The Templates can be found in the Microsoft Documentation.

I think I have to rework the whole code.

发布评论

评论列表(0)

  1. 暂无评论