Win32 API 日本語リファレンス
ホーム › Networking.WinSock › LPWSCENUMPROTOCOLS

LPWSCENUMPROTOCOLS

コールバック

シグネチャ

INT LPWSCENUMPROTOCOLS(
    INT* lpiProtocols,
    WSAPROTOCOL_INFOW* lpProtocolBuffer,
    DWORD* lpdwBufferLength,
    INT* lpErrno
);

パラメーター

フィールド型説明
lpiProtocolsINT*NULL で終端された iProtocol 値の配列です。このパラメーターは省略可能です。lpiProtocols が NULL の場合は、利用可能なすべてのプロトコルの情報が返されます。それ以外の場合は、この配列に列挙されたプロトコルについてのみ情報が取得されます。
lpProtocolBufferWSAPROTOCOL_INFOW*WSAPROTOCOL_INFOW 構造体が格納されるバッファーへのポインターです。
lpdwBufferLengthDWORD*入力時には、WSCEnumProtocols に渡す lpProtocolBuffer バッファーのサイズ (バイト単位) を指定します。出力時には、要求したすべての情報を取得するために WSCEnumProtocols に渡す必要がある最小のバッファー サイズ (バイト単位) が格納されます。
lpErrnoINT*エラー コードへのポインターです。

公式ドキュメント

WSCEnumProtocols 関数は、利用可能なトランスポート プロトコルに関する情報を取得します。

戻り値

エラーが発生しなかった場合、WSCEnumProtocols は報告対象となるプロトコルの数を返します。それ以外の場合は SOCKET_ERROR が返され、固有のエラー コードが lpErrno に格納されます。

エラー コード 意味
WSAEFAULT
引数の 1 つ以上が、ユーザー アドレス空間の有効な範囲内にありません。
WSAEINVAL
指定されたパラメーターのいずれかが無効であることを示します。
WSAENOBUFS
バッファーの長さが小さすぎたため、関連するすべての WSAProtocol_Info 構造体と関連情報を受け取れませんでした。lpdwBufferLength に返された値以上の大きさのバッファーを渡してください。

解説(Remarks)

WSCEnumProtocols 関数は、ローカル コンピューターにインストールされているトランスポート プロトコル群に関する情報を調べるために使用します。この関数は、API 側の対応する関数 (WSAEnumProtocols) とは異なり、インストールされているすべてのプロトコルの WSAPROTOCOL_INFOW 構造体を返します。これには、サービス プロバイダーが WSAPROTOCOL_INFOW 構造体の dwProviderFlags メンバーに PFL_HIDDEN フラグを設定し、WSAEnumProtocols 関数が生成する結果バッファーにこのプロトコルを返さないよう Ws2_32.dll に指示しているプロトコルも含まれます。さらに WSCEnumProtocols は、チェーン長が 0 の WSAPROTOCOL_INFOW 構造体 (ダミーの LSP プロバイダー) のデータも返します。WSAEnumProtocols は、PFL_HIDDEN フラグが設定されておらず、プロトコル チェーン長が 0 でもない基本プロトコルとプロトコル チェーンの情報だけを返します。

**注意** レイヤード サービス プロバイダー (LSP) は非推奨です。Windows 8 および Windows Server 2012 以降では、Windows フィルタリング プラットフォーム を使用してください。
lpiProtocols パラメーターは、取得する情報の量を絞り込むフィルターとして使用できます。通常は NULL ポインターを指定し、利用可能なすべてのトランスポート プロトコルの情報を返させます。

要求されたプロトコルごとに、lpProtocolBuffer が指すバッファーに WSAPROTOCOL_INFOW 構造体が格納されます。指定したバッファーが十分な大きさでない場合 (lpdwBufferLength の入力値で示されます)、必要なバッファー サイズが lpdwBufferLength が指す値に設定されます。Windows Sockets SPI クライアントは、十分な大きさのバッファーを確保してこの関数を呼び出し直してください。WSCEnumProtocols 関数は複数回の呼び出しに分けて列挙することはできません。関数が成功するには、渡すバッファーが想定されるすべてのエントリを保持できる大きさである必要があります。これは関数の複雑さを抑えるためであり、ローカル コンピューターに読み込まれるプロトコルの数は通常少ないため、問題にはなりません。

バッファー内で WSAPROTOCOL_INFOW 構造体が並ぶ順序は、サービス プロバイダーが WS2_32.dll にプロトコル エントリを登録した順序、または既定のトランスポート プロバイダーを設定するための Windows Sockets アプレットによってその後に並べ替えが行われた場合はその順序と一致します。

例

次の例は、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;
}

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)