Функция WSAEnumProtocolsA (winsock2.h)

Функция WSAEnumProtocols извлекает сведения о доступных транспортных протоколах.

Синтаксис

int WSAAPI WSAEnumProtocolsA(
  [in]      LPINT               lpiProtocols,
  [out]     LPWSAPROTOCOL_INFOA lpProtocolBuffer,
  [in, out] LPDWORD             lpdwBufferLength
);

Параметры

[in] lpiProtocols

Массив значений iProtocol, заканчивающийся значением NULL. Этот параметр является необязательным; Если lpiProtocols имеет значение NULL, возвращаются сведения обо всех доступных протоколах. В противном случае сведения извлекаются только для протоколов, перечисленных в массиве.

[out] lpProtocolBuffer

Указатель на буфер, заполненный WSAPROTOCOL_INFO структурами.

[in, out] lpdwBufferLength

Во входных данных — количество байтов в буфере lpProtocolBuffer , передаваемого в WSAEnumProtocols. В выходных данных — минимальный размер буфера, который можно передать в WSAEnumProtocols для получения всех запрошенных сведений. Эта подпрограмма не может выполнять перечисление нескольких вызовов; Переданный буфер должен быть достаточно большим, чтобы вместить все записи, чтобы подпрограмма была успешной. Это снижает сложность API и не должно создавать проблем, так как количество протоколов, загруженных на компьютер, как правило, невелико.

Возвращаемое значение

Если ошибка не возникает, WSAEnumProtocols возвращает количество протоколов, которые необходимо сообщить. В противном случае возвращается значение SOCKET_ERROR, и можно получить определенный код ошибки, вызвав WSAGetLastError.

Код ошибки Значение
WSANOTINITIALISED
Перед использованием этой функции должен произойти успешный вызов WSAStartup .
WSAENETDOWN
Произошел сбой сетевой подсистемы.
WSAEINPROGRESS
Выполняется блокирующий вызов Windows Sockets 1.1.
WSAEINVAL
Указывает, что один из указанных параметров был недопустимым.
WSAENOBUFS
Длина буфера была слишком мала для получения всех соответствующих WSAPROTOCOL_INFO структур и связанных с ними сведений. Передайте буфер размером по крайней мере значение, возвращаемое в lpdwBufferLength.
WSAEFAULT
Один или несколько параметров lpiProtocols, lpProtocolBuffer или lpdwBufferLength не являются допустимой частью адресного пространства пользователя.

Комментарии

Функция WSAEnumProtocols используется для обнаружения сведений о коллекции транспортных протоколов, установленных на локальном компьютере. Многоуровневые протоколы могут использоваться приложениями только при установке в цепочках протоколов. Сведения о многоуровневых протоколах не возвращаются, за исключением фиктивных поставщиков многоуровневых служб (LSP), установленных с нулевой длиной цепочки в lpProtocolBuffer.

Примечание Многоуровневые поставщики служб являются устаревшими. Начиная с Windows 8 и Windows Server 2012, используйте платформу фильтрации Windows.
 
Параметр lpiProtocols можно использовать в качестве фильтра для ограничения объема предоставленной информации. Часто lpiProtocols указывается в качестве указателя NULL , что приводит к тому, что функция возвращает сведения обо всех доступных транспортных протоколах и цепочках протоколов.

Функция WSAEnumProtocols отличается от функций WSCEnumProtocols и WSCEnumProtocols32 тем, что функция WSAEnumProtocols не возвращает WSAPROTOCOL_INFO структуры для всех установленных протоколов. Функция WSAEnumProtocols исключает протоколы, установленные поставщиком услуг с флагом PFL_HIDDEN в элементе dwProviderFlags структуры WSAPROTOCOL_INFO , чтобы указать Ws2_32.dll, что этот протокол не должен возвращаться в буфере результатов, созданном функцией WSAEnumProtocols . Кроме того, функция WSAEnumProtocols не возвращает данные для WSAPROTOCOL_INFO структур, длина цепочки которых равна одной или больше (поставщик LSP). WSAEnumProtocols возвращает только сведения о базовых протоколах и цепочках протоколов, в которых отсутствует флаг PFL_HIDDEN и длина цепочки протоколов не равна нулю.

Структура WSAPROTOCOL_INFO предоставляется в буфере, на который указывает lpProtocolBuffer для каждого запрошенного протокола. Если указанный буфер недостаточно велик (как указано входным значением lpdwBufferLength ), значение, на которое указывает lpdwBufferLength , будет обновлено для указания требуемого размера буфера. Затем приложение должно получить достаточно большой буфер и снова вызвать WSAEnumProtocols .

Порядок, в котором структуры WSAPROTOCOL_INFO отображаются в буфере, совпадает с порядком, в котором записи протокола были зарегистрированы поставщиком услуг с помощью WS2_32.DLL, или с любым последующим изменением порядка, которое произошло с помощью приложения Windows Sockets или библиотеки DLL, предоставленной для установки поставщиков TCP/IP по умолчанию.

Windows Phone 8. Функция WSAEnumProtocolsW поддерживается для приложений Магазина Windows Phone на Windows Phone 8 и более поздних версий.

Windows 8.1 и Windows Server 2012 R2. Функция WSAEnumProtocolsW поддерживается для приложений Магазина Windows на Windows 8.1, Windows Server 2012 R2 и более поздних версиях.

Примеры

В следующем примере показано использование функции WSAEnumProtocols для получения массива WSAPROTOCOL_INFO структур для доступных транспортных протоколов.

#ifndef UNICODE
#define UNICODE 1
#endif

#include <winsock2.h>
#include <ws2tcpip.h>
#include <objbase.h>
#include <stdio.h>

// Link with ws2_32.lib and ole32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "ole32.lib")

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
// Note: could also use malloc() and free()

int wmain()
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult = 0;

    int iError = 0;
    INT iNuminfo = 0;

    int i;

    // Allocate a 16K buffer to retrieve all the protocol providers
    DWORD dwBufferLen = 16384;

    LPWSAPROTOCOL_INFO lpProtocolInfo = NULL;

    // variables needed for converting provider GUID to a string
    int iRet = 0;
    WCHAR GuidString[40] = { 0 };

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        wprintf(L"WSAStartup failed: %d\n", iResult);
        return 1;
    }

    lpProtocolInfo = (LPWSAPROTOCOL_INFO) MALLOC(dwBufferLen);
    if (lpProtocolInfo == NULL) {
        wprintf(L"Memory allocation for providers buffer failed\n");
        WSACleanup();
        return 1;
    }

    iNuminfo = WSAEnumProtocols(NULL, lpProtocolInfo, &dwBufferLen);
    if (iNuminfo == SOCKET_ERROR) {
        iError = WSAGetLastError();
        if (iError != WSAENOBUFS) {
            wprintf(L"WSAEnumProtocols failed with error: %d\n", iError);
            if (lpProtocolInfo) {
                FREE(lpProtocolInfo);
                lpProtocolInfo = NULL;
            }
            WSACleanup();
            return 1;
        } else {
            wprintf(L"WSAEnumProtocols failed with error: WSAENOBUFS (%d)\n",
                    iError);
            wprintf(L"  Increasing buffer size to %d\n\n", dwBufferLen);
            if (lpProtocolInfo) {
                FREE(lpProtocolInfo);
                lpProtocolInfo = NULL;
            }
            lpProtocolInfo = (LPWSAPROTOCOL_INFO) MALLOC(dwBufferLen);
            if (lpProtocolInfo == NULL) {
                wprintf(L"Memory allocation increase for buffer failed\n");
                WSACleanup();
                return 1;
            }
            iNuminfo = WSAEnumProtocols(NULL, lpProtocolInfo, &dwBufferLen);
            if (iNuminfo == SOCKET_ERROR) {
                iError = WSAGetLastError();
                wprintf(L"WSAEnumProtocols failed with error: %d\n", iError);
                if (lpProtocolInfo) {
                    FREE(lpProtocolInfo);
                    lpProtocolInfo = NULL;
                }
                WSACleanup();
                return 1;
            }

        }
    }

    wprintf(L"WSAEnumProtocols succeeded with protocol count = %d\n\n",
            iNuminfo);
    for (i = 0; i < iNuminfo; i++) {
        wprintf(L"Winsock Catalog Provider Entry #%d\n", i);
        wprintf
            (L"----------------------------------------------------------\n");
        wprintf(L"Entry type:\t\t\t ");
        if (lpProtocolInfo[i].ProtocolChain.ChainLen == 1)
            wprintf(L"Base Service Provider\n");
        else
            wprintf(L"Layered Chain Entry\n");

        wprintf(L"Protocol:\t\t\t %ws\n", lpProtocolInfo[i].szProtocol);

        iRet =
            StringFromGUID2(lpProtocolInfo[i].ProviderId,
                            (LPOLESTR) & GuidString, 39);
        if (iRet == 0)
            wprintf(L"StringFromGUID2 failed\n");
        else
            wprintf(L"Provider ID:\t\t\t %ws\n", GuidString);

        wprintf(L"Catalog Entry ID:\t\t %u\n",
                lpProtocolInfo[i].dwCatalogEntryId);

        wprintf(L"Version:\t\t\t %d\n", lpProtocolInfo[i].iVersion);

        wprintf(L"Address Family:\t\t\t %d\n",
                lpProtocolInfo[i].iAddressFamily);
        wprintf(L"Max Socket Address Length:\t %d\n",
                lpProtocolInfo[i].iMaxSockAddr);
        wprintf(L"Min Socket Address Length:\t %d\n",
                lpProtocolInfo[i].iMinSockAddr);

        wprintf(L"Socket Type:\t\t\t %d\n", lpProtocolInfo[i].iSocketType);
        wprintf(L"Socket Protocol:\t\t %d\n", lpProtocolInfo[i].iProtocol);
        wprintf(L"Socket Protocol Max Offset:\t %d\n",
                lpProtocolInfo[i].iProtocolMaxOffset);

        wprintf(L"Network Byte Order:\t\t %d\n",
                lpProtocolInfo[i].iNetworkByteOrder);
        wprintf(L"Security Scheme:\t\t %d\n",
                lpProtocolInfo[i].iSecurityScheme);
        wprintf(L"Max Message Size:\t\t %u\n", lpProtocolInfo[i].dwMessageSize);

        wprintf(L"ServiceFlags1:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwServiceFlags1);
        wprintf(L"ServiceFlags2:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwServiceFlags2);
        wprintf(L"ServiceFlags3:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwServiceFlags3);
        wprintf(L"ServiceFlags4:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwServiceFlags4);
        wprintf(L"ProviderFlags:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwProviderFlags);

        wprintf(L"Protocol Chain length:\t\t %d\n",
                lpProtocolInfo[i].ProtocolChain.ChainLen);

        wprintf(L"\n");
    }

    if (lpProtocolInfo) {
        FREE(lpProtocolInfo);
        lpProtocolInfo = NULL;
    }
    WSACleanup();

    return 0;
}


Примечание

Заголовок winsock2.h определяет WSAEnumProtocols в качестве псевдонима, который автоматически выбирает версию ANSI или Юникод этой функции на основе определения константы препроцессора ЮНИКОД. Использование псевдонима, не зависящий от кодирования, с кодом, который не является нейтральным для кодировки, может привести к несоответствиям, которые приводят к ошибкам компиляции или времени выполнения. Дополнительные сведения см. в разделе Соглашения для прототипов функций.

Требования

Требование Значение
Минимальная версия клиента Windows 8.1, Windows Vista [классические приложения | Приложения UWP]
Минимальная версия сервера Windows Server 2003 [классические приложения | Приложения UWP]
Целевая платформа Windows
Header winsock2.h
Библиотека Ws2_32.lib
DLL Ws2_32.dll

См. также раздел

WSAPROTOCOL_INFO

WSCEnumProtocols

WSCEnumProtocols32

Функции Winsock

Справочник по Winsock