Shaitan00
Shaitan00

Reputation: 323

Unable to extract data after PtrToStructure through NamedPipe [C#]

Ok, I'm trying to send a STRUCT from a legacy C++ application to a new C# application using Named Pipes, however I can't seem to find out how to correctly extract the information on the C# side - here is the code I currently have:

C++ Sending Code

// Structure for message
struct MESSAGE
{
    CHAR  cSender[256];
    CHAR  cCommand[256];
};

// Sending the MESSAGE
DWORD dwWrote = 0
MESSAGE msg;
strcpy(msg.cSender, "LOCAL");
strcpy(msg.cCommand, "COMMAND");
WriteFile(pipe, msg, sizeof(msg), dwWrote);



C# Recieving Code:

// Corresponding C# MESSAGE structure
[StructLayout(LayoutKind.Sequential)]
public struct MESSAGE
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public byte[] cSender;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public byte[] cCommand;
}

MESSAGE msg = new MESSAGE();
byte[] byteData = new byte[Marshal.SizeOf(msg)];
uint uBytesRead;

bool fSuccess = ReadFile(hPipeInst,
                  byteData,
                  (uint)byteData.Length,
                  out uBytesRead,
                  IntPtr.Zero);     // no overlapping


// Generate Structure at the C# side
IntPtr ptr = Marshal.AllocHGlobal(byteData.Length);
try
{
    Marshal.Copy(byteData, 0, ptr, byteData.Length);
    msg = (MESSAGE)Marshal.PtrToStructure(ptr, typeof(MESSAGE));
}
finally
{
    Marshal.FreeHGlobal(ptr);
}

// Extract Sender & Command to be used
string sSender = Encoding.ASCII.GetString(msg.cSender);
string sCommand = Encoding.ASCII.GetString(msg.cCommand);

Some is going horribly wrong, when I test this and trace out sSender and sCommand I get the following: Sender: LOCAL ? (? 8? ?? ?? ?? X P P ?? ???w@??w ??? ?? ???J??w x? ??? ?? ???J??w ?? #-| ,? ???? ? J??w ?? I -| ??? ???D 0 \ ?? ? ? ?? ??? ??

Command: COMMAND ?? ??? ?? ?w?? ? ?? ?0-|? ?? ,? 72-|?? ?? ??J ?? nW& "-|? @? ?-|? ?-|p?? @? ?`& ??p?? O| @? ? ?? ^+ ??????? T? f ??? l? , ??J

As you can see, in both cases the string is there (LOCAL & COMMAND) but they are both followed by tons of garbage, is there something I can do to fix this or does the cSender and cCommand have to be exactly FIXED LENGTH? I put them at 256/256 thinking "that would be more then long enough for anything I could ever need" but now I am wondering ...

Any help would be much appreciated. Thanks,

Upvotes: 0

Views: 311

Answers (1)

Steve Gilham
Steve Gilham

Reputation: 11277

Have you tried dumping the whole of 256 byte chunks you send? Are the received bytes following LOCAL and COMMAND zero?

I suspect that you will find that you are receiving the same uninitialized tail as is present in the sender; just that C# doesn't interpret a null byte as a string terminator.

Edit -- lift adjusted struct definition into the answer from the comment

// Corresponding C# MESSAGE structure
[ StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct MESSAGE
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string cSender;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string cCommand;
}

Upvotes: 2

Related Questions