WSCEnumProtocols32 函数 (ws2spi.h)

WSCEnumProtocols32 函数检索有关可用传输协议的信息。

注意 此调用是 WSCEnumProtocols 的严格 32 位版本,用于 64 位平台。 提供它以允许 64 位进程访问 32 位目录。

 

语法

int WSCEnumProtocols32(
  [in]      LPINT               lpiProtocols,
  [out]     LPWSAPROTOCOL_INFOW lpProtocolBuffer,
  [in, out] LPDWORD             lpdwBufferLength,
  [out]     LPINT               lpErrno
);

参数

[in] lpiProtocols

以 Null 结尾的 iProtocol 值数组。 此参数是可选的;如果 lpiProtocols 为 null,则返回有关所有可用协议的信息。 否则,仅检索数组中列出的那些协议的信息。

[out] lpProtocolBuffer

用WSAPROTOCOL_INFOW结构填充 缓冲区。

[in, out] lpdwBufferLength

输入时,传递给 WSCEnumProtocolslpProtocolBuffer 缓冲区的大小(以字节为单位)。 输出时,可以传递给 WSCEnumProtocols 以检索所有请求的信息的最小缓冲区大小(以字节为单位)。

[out] lpErrno

指向错误代码的指针。

返回值

如果未发生错误, WSCEnumProtocols32 将返回要报告的协议数。 否则,将返回值 SOCKET_ERROR,并在 lpErrno 中提供特定的错误代码。

错误代码 含义
WSAEFAULT
其中一个参数不在用户地址空间的有效部分。
WSAEINVAL
:指示指定参数之一无效。
WSAENOBUFS
缓冲区长度太小,无法接收所有相关 WSAProtocol_Info 结构和相关信息。 传入缓冲区至少与 lpdwBufferLength 中返回的值一样大。

注解

WSCEnumProtocols32WSCEnumProtocols 的严格 32 位版本。 例如,在 64 位计算机上,所有不专门调用 32 位 (所有不以“32”结尾的函数 ) 本机 64 位目录上运行。 在 64 位计算机上执行的进程必须使用特定的 32 位函数调用,才能对严格的 32 位目录进行操作并保持兼容性。 特定 32 位调用的定义和语义与其本机调用的定义和语义相同。

此函数用于发现有关本地计算机上安装的传输协议集合的信息。 此函数与 WSAEnumProtocols () 的 API 对应函数不同,因为它返回所有已安装协议 的WSAPROTOCOL_INFOW 结构。 这包括服务提供程序在 WSAPROTOCOL_INFOW 结构的 dwProviderFlags 成员中设置 PFL_HIDDEN标志的 协议,以向 Ws2_32.dll 指示不应在 WSAEnumProtocols 函数生成的结果缓冲区中返回此协议。 此外, WSCEnumProtocols32 还会返回链长度为零 的WSAPROTOCOL_INFOW 结构的数据 ( 虚拟 LSP 提供程序) 。 WSAEnumProtocols 仅返回缺少PFL_HIDDEN标志且协议链长度不为零的基本协议和协议链的信息。

**注意** 分层服务提供程序已弃用。 从 Windows 8 和 Windows Server 2012 开始,请使用 Windows 筛选平台
 
lpiProtocols 参数可用作筛选器来约束提供的信息量。 通常提供 NULL 指针,因此函数将返回有关所有可用传输协议的信息。

对于每个请求的协议,lpProtocolBuffer 指向的缓冲区中提供了WSAPROTOCOL_INFOW结构。 如果提供的缓冲区 (不够大,如 lpdwBufferLength) 的输入值所示,则将更新 lpdwBufferLength 指向的值以指示所需的缓冲区大小。 然后,Windows 套接字 SPI 客户端应获取足够大的缓冲区并再次调用此函数。 WSCEnumProtocols32 函数无法枚举多个调用;传入的缓冲区必须足够大,以容纳所有预期的条目,以便函数成功。 这降低了函数的复杂性,并且不会造成问题,因为计算机上加载的协议数通常很小。

WSAPROTOCOL_INFOW结构在缓冲区中的出现顺序与服务提供商向 WS2_32.dll 注册协议条目的顺序,或者通过为建立默认传输提供程序而提供的 Windows 套接字小程序进行的任何后续重新排序一致。

示例

以下示例演示如何在 64 位平台上使用 WSCEnumProtocols32 函数来检索 32 位目录中本地计算机上安装的协议 的WSAPROTOCOL_INFOW 结构数组。

#ifndef UNICODE
#define UNICODE 1
#endif

#include <winsock2.h>
#include <ws2tcpip.h>
#include <ws2spi.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 iNuminfo = 0;

    int i;

    // Allocate a 16K buffer to retrieve all the protocol providers
    DWORD dwBufferLen = 16384;
    LPWSAPROTOCOL_INFOW lpProtocolInfo = NULL;
    int iErrno = 0;

    // 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_INFOW) MALLOC(dwBufferLen);
    if (lpProtocolInfo == NULL) {
        wprintf(L"Memory allocation for providers buffer failed\n");
        WSACleanup();
        return 1;
    }

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

        }
    }

    wprintf(L"WSCEnumProtocols32 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;
}


要求

   
最低受支持的客户端 Windows Vista、Windows XP Professional x64 版本 [仅限桌面应用]
最低受支持的服务器 Windows Server 2008、Windows Server 2003 x64 Edition [仅限桌面应用]
目标平台 Windows
标头 ws2spi.h
Library Ws2_32.lib
DLL Ws2_32.dll

另请参阅

WSAEnumProtocols

WSAPROTOCOL_INFOW

WSCEnumProtocols