Procedure is exited upon marshalling a C struct received via WM_COPYDATA into a C# struct

97 Views Asked by At

Here is my problem. I am trying to Marshal a C struct into a C# struct. The C struct is sent from a C application to a C# application via a WM_COPYDATA message. Sending and acknowledging the message is not a problem and works perfectly fine.

I run the C application in debug, attach another debugger to the C# application and send the message. it is received and identified correctly but when I try to marshal the data, the Marshal.PtrToStructure function seems to exit the switch statement before executing the rest of it (see marked line in code).

The procedure manageComplexMessage is therefore not executed and the data remains raw and unusable.

This is the CopyDataStruct I use in C# :

private struct CopyDataStruct
{ 
    public IntPtr dwData; 
    public int cbData; 
    public IntPtr lpData; 
}

This is the struct I use in C# to store the data sent through WM_COPYDATA :

private struct ComplexData
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 75)]
    public int[] integers;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 75)]
    public double[] doubles;
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStr, SizeConst = 25)]
    public string[] strings;
};

The method that processes the WM_COPYDATA message :

protected override void WndProc(ref Message m)
{
    int id;

    base.WndProc(ref m);

    switch (m.Msg)
    {
        case WM_COPYDATA:
            CopyDataStruct rawData = (CopyDataStruct) Marshal.PtrToStructure(m.LParam, typeof(CopyDataStruct)); // This Call to PtrToStructure works perfectly fine.
            id = rawData.dwData.ToInt32();

            if (Enum.IsDefined(typeof(ComplexMessageId), id))
            {
                ComplexData data = (ComplexData) Marshal.PtrToStructure(rawData.lpData, typeof(ComplexData)); // This call makes the procedure exit.
                manageComplexMessage((ComplexMessageId) id, data);
                m.Result = (IntPtr) 1;
            }
            else
            {
                m.Result = (IntPtr) 2;
            }
            break;
    }
}

The struct I use in C to send the data to my C# application :

struct ComplexData {    
    int Integers[75]; // Maximum 75 integers
    double Doubles[75]; // Maximum 75 doubles
    char Strings[25][256]; // Maximum 25 strings of a maximum length of 256 characters
};  

And, finally, the procedure which sends the message :

int SendCopydataMessage(int MessageID, struct ComplexData MessageData)
{
    COPYDATASTRUCT DataToSend;

    int result;

    DataToSend.dwData = MessageID;
    DataToSend.cbData = sizeof(MessageData);
    DataToSend.lpData = &MessageData;

    if(WindowHandle != NULL) 
    {
        result = SendMessage(WindowHandle, WM_COPYDATA, (WPARAM) ((HWND) ExecWnd), (LPARAM) ((PVOID) &DataToSend));
        if(!result) 
        {
            return MESSAGENOTPROCESSED;
        }
        if(result == 2)
        {
            return UNDEFINEDMESSAGEID;
        }
    }

    return OK;
}

I suspect a problem when I Marshal the array of Strings but I can't find the problem.

Thank you all for your help! I hope someone can tell me what's wrong or point me toward the right direction!

EDIT : After more testing, the integer part and the double part of the struct works perfectly fine. Also if I send a single String it works. It only crashes when I try to send an array of String. The problem is then in my MarshalAs statement for the string array, but I still can't find out how to write properly.

0

There are 0 best solutions below