Search code examples
c#.netpinvokewsastartup

Is the .NET use of WSAStartup safe for 64-bit apps?


There is a mismatch between the .NET Framework version and the native Win32 version of the WSAData struct, for 64-bit apps, because the order of the fields is different. I had copied the .NET version for use in our C#-based product and a coworker is concerned that I have caused a memory corruption. Is there any risk of memory corruption because of this mismatch when using DllImport / PInvoke? Is there any risk of an invalid memory access when marshaling the native version to the managed version? Let's assume I'm not concerned with actually accessing the fields of the resulting WSAData object. I just want to be certain that my call to WSAStartup does not corrupt memory or crash the app.

Here is the native C++ version in WinSock2.h. Note that the order of the members is different in 64-bit versus 32-bit. WSADESCRIPTION_LEN is 256 and WSASYS_STATUS_LEN is 128.

typedef struct WSAData {
        WORD                    wVersion;
        WORD                    wHighVersion;
#ifdef _WIN64
        unsigned short          iMaxSockets;
        unsigned short          iMaxUdpDg;
        char FAR *              lpVendorInfo;
        char                    szDescription[WSADESCRIPTION_LEN+1];
        char                    szSystemStatus[WSASYS_STATUS_LEN+1];
#else
        char                    szDescription[WSADESCRIPTION_LEN+1];
        char                    szSystemStatus[WSASYS_STATUS_LEN+1];
        unsigned short          iMaxSockets;
        unsigned short          iMaxUdpDg;
        char FAR *              lpVendorInfo;
#endif
} WSADATA, FAR * LPWSADATA;

Here is the managed version in the .NET Framework:

[StructLayout(LayoutKind.Sequential)]
internal struct WSAData {
    internal short wVersion;
    internal short wHighVersion;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=257)]
    internal string szDescription;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=129)]
    internal string szSystemStatus;
    internal short iMaxSockets;
    internal short iMaxUdpDg;
    internal IntPtr lpVendorInfo;
}

[DllImport(WS2_32, CharSet=CharSet.Ansi, BestFitMapping=false,
    ThrowOnUnmappableChar=true, SetLastError=true)]
internal static extern SocketError WSAStartup(
    [In] short wVersionRequested,
    [Out] out WSAData lpWSAData
                                               );

Solution

  • Sure, this is incorrect. The .NET Framework gets away with it, the structure sizes are still correct (400 bytes in 32-bit mode, 408 in 64-bit mode) so no memory corruption can occur. And it doesn't actually use any of the returned info, they would surely have caught the bug if they did.

    You can file the bug at connect.microsoft.com, I doubt they'll be in a hurry to fix it however.