WSCEnumProtocols 함수(ws2spi.h)

WSCEnumProtocols 함수는 사용 가능한 전송 프로토콜에 대한 정보를 검색합니다.

구문

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

매개 변수

[in] lpiProtocols

iProtocol 값의 NULL로 종료된 배열입니다. 이 매개 변수는 선택 사항입니다. lpiProtocols 가 NULL이면 사용 가능한 모든 프로토콜에 대한 정보가 반환됩니다. 그렇지 않으면 배열에 나열된 프로토콜에 대해서만 정보가 검색됩니다.

[out] lpProtocolBuffer

WSAPROTOCOL_INFOW 구조체로 채워진 버퍼에 대한 포인터입니다.

[in, out] lpdwBufferLength

입력에서 WSCEnumProtocols에 전달된 lpProtocolBuffer 버퍼의 크기(바이트)입니다. 출력에서 요청된 모든 정보를 검색하기 위해 WSCEnumProtocols 에 전달할 수 있는 최소 버퍼 크기(바이트)입니다.

[out] lpErrno

오류 코드에 대한 포인터입니다.

반환 값

오류가 발생하지 않으면 WSCEnumProtocols 는 보고할 프로토콜 수를 반환합니다. 그렇지 않으면 SOCKET_ERROR 값이 반환되고 lpErrno에서 특정 오류 코드를 사용할 수 있습니다.

오류 코드 의미
WSAEFAULT
인수 중 하나가 사용자 주소 공간의 유효한 부분에 있지 않습니다.
WSAEINVAL
지정된 매개 변수 중 하나가 잘못되었음을 나타냅니다.
WSAENOBUFS
버퍼 길이가 너무 작아 관련 WSAProtocol_Info 구조 및 관련 정보를 모두 받을 수 없습니다. lpdwBufferLength에서 반환된 값만큼 큰 버퍼를 전달합니다.

설명

WSCEnumProtocols 함수는 로컬 컴퓨터에 설치된 전송 프로토콜 컬렉션에 대한 정보를 검색하는 데 사용됩니다. 이 함수는 설치된 모든 프로토콜에 대한 WSAPROTOCOL_INFOW 구조가 반환된다는 점에서 API 대응(WSAEnumProtocols)과 다릅니다. 여기에는 서비스 공급자가 WSAPROTOCOL_INFOW 구조의 dwProviderFlags 멤버에서 PFL_HIDDEN 플래그를 설정하여 WSAEnumProtocols 함수에서 생성된 결과 버퍼에서 이 프로토콜을 반환해서는 안 됨을 Ws2_32.dll 나타내는 프로토콜이 포함됩니다. 또한 WSCEnumProtocols 는 체인 길이가 0(더미 LSP 공급자)인 WSAPROTOCOL_INFOW 구조체에 대한 데이터도 반환합니다. WSAEnumProtocolsPFL_HIDDEN 플래그가 부족하고 프로토콜 체인 길이가 0이 아닌 기본 프로토콜 및 프로토콜 체인에 대한 정보만 반환합니다.

**참고** 계층화된 서비스 공급자는 더 이상 사용되지 않습니다. Windows 8 및 Windows Server 2012부터 Windows 필터링 플랫폼을 사용합니다.
 
lpiProtocols 매개 변수를 필터로 사용하여 제공된 정보의 양을 제한할 수 있습니다. 일반적으로 null 포인터가 제공되므로 함수는 사용 가능한 모든 전송 프로토콜에 대한 정보를 반환합니다.

요청된 각 프로토콜에 대해 lpProtocolBuffer가 가리키는 버퍼에 WSAPROTOCOL_INFOW 구조가 제공됩니다. 제공된 버퍼가 충분히 크지 않으면( lpdwBufferLength의 입력 값으로 나타낸 대로) lpdwBufferLength 가 가리키는 값이 필요한 버퍼 크기를 나타내도록 업데이트됩니다. 그런 다음 Windows 소켓 SPI 클라이언트는 충분히 큰 버퍼를 가져와서 이 함수를 다시 호출해야 합니다. WSCEnumProtocols 함수는 여러 호출을 통해 열거할 수 없습니다. 함수가 성공하려면 전달된 버퍼가 모든 예상 항목을 저장할 수 있을 만큼 커야 합니다. 이렇게 하면 함수의 복잡성이 줄어들고 로컬 컴퓨터에 로드되는 프로토콜 수가 일반적으로 적기 때문에 문제가 되지 않아야 합니다.

버퍼에 WSAPROTOCOL_INFOW 구조가 표시되는 순서는 프로토콜 항목이 서비스 공급자가 WS2_32.dll 등록한 순서 또는 기본 전송 공급자를 설정하기 위해 제공된 Windows 소켓 애플릿을 통해 발생할 수 있는 후속 다시 정렬과 일치합니다.

예제

다음 예제에서는 WSCEnumProtocols 함수를 사용하여 로컬 컴퓨터에 설치된 프로토콜에 대한 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 = WSCEnumProtocols(NULL, lpProtocolInfo, &dwBufferLen, &iErrno);
    if (iNuminfo == SOCKET_ERROR) {
        if (iErrno != WSAENOBUFS) {
            wprintf(L"WSCEnumProtocols failed with error: %d\n", iErrno);
            if (lpProtocolInfo) {
                FREE(lpProtocolInfo);
                lpProtocolInfo = NULL;
            }
            WSACleanup();
            return 1;
        } else {
            wprintf(L"WSCEnumProtocols 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 =
                WSCEnumProtocols(NULL, lpProtocolInfo, &dwBufferLen, &iErrno);
            if (iNuminfo == SOCKET_ERROR) {
                wprintf(L"WSCEnumProtocols failed with error: %d\n", iErrno);
                if (lpProtocolInfo) {
                    FREE(lpProtocolInfo);
                    lpProtocolInfo = NULL;
                }
                WSACleanup();
                return 1;
            }

        }
    }

    wprintf(L"WSCEnumProtocols 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 2000 Professional[데스크톱 앱만]
지원되는 최소 서버 Windows 2000 Server[데스크톱 앱만]
대상 플랫폼 Windows
헤더 ws2spi.h
라이브러리 Ws2_32.lib
DLL Ws2_32.dll

참고 항목

WSAEnumProtocols

WSAPROTOCOL_INFOW

WSCEnumProtocols32