Безопасно ли использование.NET WSAStartup для 64-битных приложений?

Существует несоответствие между версией.NET Framework и собственной версией Win32 структуры WSAData для 64-битных приложений, поскольку порядок полей различен. Я скопировал версию.NET для использования в нашем продукте на C#, и коллега обеспокоен тем, что я вызвал повреждение памяти. Есть ли риск повреждения памяти из-за этого несоответствия при использовании DllImport / PInvoke? Есть ли риск неправильного доступа к памяти при маршалинге нативной версии в управляемую? Предположим, меня не интересует фактический доступ к полям результирующего объекта WSAData. Я просто хочу быть уверен, что мой вызов WSAStartup не повредит память и не приведет к сбою приложения.

Вот родная версия C++ в WinSock2.h. Обратите внимание, что порядок членов отличается в 64-разрядном и 32-разрядном. WSADESCRIPTION_LEN - 256, а WSASYS_STATUS_LEN - 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;

Вот управляемая версия в.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
                                               );

2 ответа

Решение

Конечно, это неправильно..NET Framework сходит с рук, размеры структур по-прежнему правильны (400 байт в 32-разрядном режиме, 408 в 64-разрядном режиме), поэтому повреждение памяти не может произойти. И он на самом деле не использует никакую возвращаемую информацию, они наверняка поймали бы ошибку, если бы сделали.

Вы можете отправить сообщение об ошибке на connect.microsoft.com, но я сомневаюсь, что они будут спешить исправить это.

Да, структура неправильная... Вы можете проверить, используя неправильную структуру и правильную структуру:

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

WSAData data;
int res = WSAStartup(2 << 8 | 2, out data);
Console.WriteLine("64bits: {0}, Result = {1}, szDescription: {2}, szSystemStatus: {3}", Environment.Is64BitProcess, res, data.szDescription, data.szSystemStatus);

НО у вас нет никаких проблем, потому что, вероятно,.NET не использует все эти различные поля (для чего нужно описание?) Не может быть даже проблемы с преобразованием Unicode, потому что используемый метод - Ansi один (CharSet=CharSet.Ansi), и каждый символ Анси является юридическим символом в Юникоде.

Другие вопросы по тегам