HOWTO: Enumerate & Print Contents of WSAPROTOCOL_INFO Structure

ID: Q192121

The information in this article applies to:

SUMMARY

The Winsock 2 API WSAEnumProtocols returns a list of supported WSAPROTOCOL_INFO structures. Each structure in the list represents a Winsock 2 service provider that is installed on the system. You need to understand the contents of this structure so that you can choose the proper Winsock 2 service provider (that is, the one that provides the capabilities your application needs). This articles provides sample code you need to enumerate all Winsock 2 service providers and print out the contents of the returned WSAPROTOCOL_INFO structure.

MORE INFORMATION

The sample code below demonstrates how to enumerate all Winsock 2 service providers and print out the contents of the returned WSAPROTOCOL_INFO structure.

Sample Code

   #include <winsock2.h>
   #include <rpc.h>
   #include <stdio.h>

   static void PrintBufEntry(WSAPROTOCOL_INFO *pProtocolBuf);

   int main(int argc, char *argv[])
       {
       WSADATA WSAData;
       int i, nRet;
       DWORD dwErr;
       WSAPROTOCOL_INFO *lpProtocolBuf = NULL;
       DWORD dwBufLen = 0;

       if (WSAStartup(MAKEWORD(2,2), &WSAData))
           printf("WSAStartup %d", WSAGetLastError());
       else
           {
           // First, have WSAEnumProtocols tell you how big a buffer you
           // need.
           nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
           if (SOCKET_ERROR != nRet)
               printf("WSAEnumProtocols: should not have succeeded\n");
           else if (WSAENOBUFS != (dwErr = WSAGetLastError()))
               // WSAEnumProtocols failed for some reason not relating
               // to buffer size - also odd.
               printf("WSAEnumProtocols(1): %d\n", WSAGetLastError());
           else
               {
               // WSAEnumProtocols failed for the "expected" reason.
               // Now you need to allocate a buffer that is the right size.
               lpProtocolBuf = (WSAPROTOCOL_INFO *)malloc(dwBufLen);
               if (lpProtocolBuf)
                   {
                   // Now you can call WSAEnumProtocols again with the
                   // expectation that it will succeed
                   // because you have allocated a big enough buffer.
                   nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
                   if (SOCKET_ERROR == nRet)
                       printf("WSAEnumProtocols(3): %d\n",
                               WSAGetLastError());
                   else
                       {
                       // Enumerate the protocols.
                       for (i=0; i<nRet; i++)
                           PrintBufEntry(&lpProtocolBuf[i]);
                       }
                   free(lpProtocolBuf);
                   }
               }
           }

       WSACleanup();
       return(0);
       }

   // Print out the contents of a WSAPROTOCOL_INFO structure in
   // a readable format.
   // 
   static void PrintBufEntry(
       WSAPROTOCOL_INFO *pProtocolBuf
       )
       {
       unsigned char *pszUuid;
       int j;

       printf("\nProtocol <%s>\n", pProtocolBuf->szProtocol);

       // A guid is the same as a uuid.
       UuidToString(&pProtocolBuf->ProviderId, &pszUuid);
       printf("  ProviderId {%s}\n", pszUuid);
       RpcStringFree(&pszUuid);

       if (!pProtocolBuf->dwServiceFlags1)
           printf("  dwServiceFlags1: 0\n");
       else
           printf("  dwServiceFlags1: 0x%08X\n",
                     pProtocolBuf->dwServiceFlags1);

       // Check which bit flags are set.
       if (pProtocolBuf->dwServiceFlags1 & XP1_CONNECTIONLESS)
           printf("    XP1_CONNECTIONLESS\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_GUARANTEED_DELIVERY)
           printf("    XP1_GUARANTEED_DELIVERY\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_GUARANTEED_ORDER)
           printf("    XP1_GUARANTEED_ORDER\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_MESSAGE_ORIENTED)
           printf("    XP1_MESSAGE_ORIENTED\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_PSEUDO_STREAM)
           printf("    XP1_PSEUDO_STREAM\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_GRACEFUL_CLOSE)
           printf("    XP1_GRACEFUL_CLOSE\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_EXPEDITED_DATA)
           printf("    XP1_EXPEDITED_DATA\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_CONNECT_DATA)
           printf("    XP1_CONNECT_DATA\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_DISCONNECT_DATA)
           printf("    XP1_DISCONNECT_DATA\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_SUPPORT_BROADCAST)
           printf("    XP1_SUPPORT_BROADCAST\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_SUPPORT_MULTIPOINT)
           printf("    XP1_SUPPORT_MULTIPOINT\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE)
           printf("    XP1_MULTIPOINT_CONTROL_PLANE\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE)
           printf("    XP1_MULTIPOINT_DATA_PLANE\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_QOS_SUPPORTED)
           printf("    XP1_QOS_SUPPORTED\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_INTERRUPT)
           printf("    XP1_INTERRUPT\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_UNI_SEND)
           printf("    XP1_UNI_SEND\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_UNI_RECV)
           printf("    XP1_UNI_RECV\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_IFS_HANDLES)
           printf("    XP1_IFS_HANDLES\n");
       if (pProtocolBuf->dwServiceFlags1 & XP1_PARTIAL_MESSAGE)
           printf("    XP1_PARTIAL_MESSAGE\n");

       printf("  dwServiceFlags2: reserved\n");

       printf("  dwServiceFlags3: reserved\n");

       printf("  dwServiceFlags4: reserved\n");

       printf("  dwProviderFlags:\n");
       if (pProtocolBuf->dwProviderFlags & PFL_MULTIPLE_PROTO_ENTRIES)
           printf("    PFL_MULTIPLE_PROTO_ENTRIES\n");
       if (pProtocolBuf->dwProviderFlags & PFL_RECOMMENDED_PROTO_ENTRY)
           printf("    PFL_RECOMMENDED_PROTO_ENTRY\n");
       if (pProtocolBuf->dwProviderFlags & PFL_HIDDEN)
           printf("    PFL_HIDDEN\n");
       if (pProtocolBuf->dwProviderFlags & PFL_MATCHES_PROTOCOL_ZERO)
           printf("    PFL_MATCHES_PROTOCOL_ZERO\n");

       printf("  dwCatalogEntryId = %u\n", pProtocolBuf->dwCatalogEntryId);

       printf("  ProtocolChain.ChainLen = %d ",
              pProtocolBuf->ProtocolChain.ChainLen);
       if (1 == pProtocolBuf->ProtocolChain.ChainLen)
           printf("  ==> this is a base service provider\n");
       else if (pProtocolBuf->ProtocolChain.ChainLen > 1)
           {
           printf("  ==>
                  ProtocolChain layered to base protocol\n");
           for (j=0; j<pProtocolBuf->ProtocolChain.ChainLen; j++)
               printf("    Chain Catalog Entry Id = %u\n",
                      pProtocolBuf->ProtocolChain.ChainEntries[j]);
           }
       else if (0 == pProtocolBuf->ProtocolChain.ChainLen)
           printf("  ==> this is a layered service provider\n");
       else
           printf("  Invalid\n");

       printf("  iVersion = %d\n", pProtocolBuf->iVersion);

       printf("  iAddressFamily = %d\n", pProtocolBuf->iAddressFamily);

       printf("  iMaxSockAddr = %d\n", pProtocolBuf->iMaxSockAddr);

       printf("  iMinSockAddr = %d\n", pProtocolBuf->iMinSockAddr);

       // iProtocols returns a negative number for Microsoft NetBIOS
       // service providers corresponding to the lana number * -1 (for
       // example, -2 implies lana 2), except for lana 0 which is equal to
       // 0x80000000 because protocol 0 is reserved for special use.
       printf("  iProtocol = %d\n", pProtocolBuf->iProtocol);

       printf("  iProtocolMaxOffset = %d\n",
              pProtocolBuf->iProtocolMaxOffset);

       printf("  iNetworkByteOrder = %s\n",
           ((pProtocolBuf->iNetworkByteOrder == LITTLEENDIAN) ?
             "LITTLEENDIAN" : "BIGENDIAN"));

       printf("  iSecurityScheme = %d\n", pProtocolBuf->iSecurityScheme);

       printf("  dwMessageSize = %u\n", pProtocolBuf->dwMessageSize);

       printf("  dwProviderReserved = reserved\n");

       return;
       }

MORE INFORMATION

When you compile this code, link with the libraries Ws2_32.lib and Rpcrt4.lib.

This program runs on Windows 98, Windows NT 4.0, and Windows 95 systems that have the Winsock 2 for Windows 95 Update installed.

Additional query words:

Keywords          : kbcode kbnetwork kbNTOS400 kbSDKPlatform kbWinOS95 kbWinOS98 kbWinsock kbCodeSam kbGrpNet 
Issue type        : kbhowto

Last Reviewed: September 11, 1998