Using the WSCEnumProtocols function. Code based on an example from the Windows SDK :
#include <stdlib.h> #include <locale.h> #include <stdio.h> #include <tchar.h> #include <winsock2.h> #include <Windows.h> #include <ws2spi.h> //https://github.com/pauldotknopf/WindowsSDK7-Samples/blob/e8fe83b043727e71f5179da11fc6228475e7973c/netds/winsock/lsp/install/instlsp.cpp #pragma comment(lib,"Ws2_32.lib") typedef enum { LspCatalogBoth = 0, LspCatalog32Only, LspCatalog64Only } WINSOCK_CATALOG; //*** private LSP heap **** HANDLE gLspHeap = NULL; int LspCreateHeap( int *lpErrno ) { gLspHeap = HeapCreate( 0, 128000, 0 ); if ( NULL == gLspHeap ) { *lpErrno = WSAEPROVIDERFAILEDINIT; return SOCKET_ERROR; } return NO_ERROR; } void * LspAlloc( SIZE_T size, int *lpErrno ) { void *mem = NULL; mem = HeapAlloc( gLspHeap, HEAP_ZERO_MEMORY, size ); if ( NULL == mem ) { *lpErrno = WSAENOBUFS; } return mem; } void LspFree( LPVOID buf ) { HeapFree( gLspHeap, 0, buf ); } //********************************************** LPWSAPROTOCOL_INFOW EnumerateProviders( WINSOCK_CATALOG Catalog, LPINT TotalProtocols ) { LPWSAPROTOCOL_INFOW ProtocolInfo = NULL; DWORD ProtocolInfoSize = 0; INT ErrorCode = NO_ERROR, rc; if ( NULL == TotalProtocols ) goto cleanup; *TotalProtocols = 0; #ifdef _WIN64 // Find out how many entries we need to enumerate if ( LspCatalog64Only == Catalog ) { // Find the size of the buffer rc = WSCEnumProtocols( NULL, ProtocolInfo, &ProtocolInfoSize, &ErrorCode ); if ( SOCKET_ERROR == rc ) { if ( WSAENOBUFS != ErrorCode ) goto cleanup; ErrorCode = NO_ERROR; } // Allocate the buffer ProtocolInfo = (LPWSAPROTOCOL_INFOW) LspAlloc( ProtocolInfoSize, &ErrorCode ); if (ProtocolInfo == NULL) goto cleanup; // Enumerate the catalog for real rc = WSCEnumProtocols( NULL, ProtocolInfo, &ProtocolInfoSize, &ErrorCode ); if ( SOCKET_ERROR == rc ) goto cleanup; // Update the count *TotalProtocols = rc; } else if ( LspCatalog32Only == Catalog ) { HMODULE hModule; LPWSCENUMPROTOCOLS fnWscEnumProtocols32 = NULL; // Load ws2_32.dll hModule = LoadLibrary( TEXT( "ws2_32.dll" ) ); if ( NULL == hModule ) goto cleanup; // Find the 32-bit catalog enumerator fnWscEnumProtocols32 = (LPWSCENUMPROTOCOLS) GetProcAddress( hModule, "WSCEnumProtocols32" ); if ( NULL == fnWscEnumProtocols32 ) goto cleanup; // Find the required buffer size rc = fnWscEnumProtocols32(NULL, ProtocolInfo, &ProtocolInfoSize, &ErrorCode); if ( SOCKET_ERROR == rc ) { if ( WSAENOBUFS != ErrorCode ) goto cleanup; ErrorCode = NO_ERROR; } // Allocate the buffer ProtocolInfo = (LPWSAPROTOCOL_INFOW) LspAlloc( ProtocolInfoSize, &ErrorCode ); if ( NULL == ProtocolInfo ) goto cleanup; // Enumrate the catalog for real this time rc = fnWscEnumProtocols32( NULL, ProtocolInfo, &ProtocolInfoSize, &ErrorCode ); if ( SOCKET_ERROR == rc ) goto cleanup; // Update the count *TotalProtocols = rc; FreeLibrary( hModule ); } #else if ( LspCatalog32Only == Catalog ) { // Find the size of the buffer rc = WSCEnumProtocols( NULL, ProtocolInfo, &ProtocolInfoSize, &ErrorCode ); if ( SOCKET_ERROR == rc ) { if ( WSAENOBUFS != ErrorCode ) goto cleanup; ErrorCode = NO_ERROR; } // Allocate the buffer ProtocolInfo = (LPWSAPROTOCOL_INFOW) LspAlloc( ProtocolInfoSize, &ErrorCode ); if ( NULL == ProtocolInfo ) goto cleanup; // Enumerate the catalog for real rc = WSCEnumProtocols( NULL, ProtocolInfo, &ProtocolInfoSize, &ErrorCode ); if ( SOCKET_ERROR == rc ) goto cleanup; // Update the count *TotalProtocols = rc; } else if ( LspCatalog64Only == Catalog ) { puts( "Unable to enumerate 64-bit Winsock catalog from 32-bit process!"); } #endif else { // Find the size of the buffer rc = WSCEnumProtocols( NULL, ProtocolInfo, &ProtocolInfoSize, &ErrorCode ); if ( SOCKET_ERROR == rc ) { if ( WSAENOBUFS != ErrorCode ) goto cleanup; ErrorCode = NO_ERROR; } // Allocate the buffer ProtocolInfo = (LPWSAPROTOCOL_INFOW) LspAlloc( ProtocolInfoSize, &ErrorCode ); if ( NULL == ProtocolInfo ) goto cleanup; // Enumerate the catalog for real rc = WSCEnumProtocols( NULL, ProtocolInfo, &ProtocolInfoSize, &ErrorCode ); if ( SOCKET_ERROR == rc ) goto cleanup; // Update the count *TotalProtocols = rc; } cleanup: if ( ( NO_ERROR != ErrorCode ) && ( NULL != ProtocolInfo ) ) { LspFree( ProtocolInfo ); ProtocolInfo = NULL; } return ProtocolInfo; } void PrintProtocolInfo( WSAPROTOCOL_INFOW *wsapi) { WCHAR szGuidString[MAX_PATH], wszProviderPath[MAX_PATH]; INT dwProviderPathLen=MAX_PATH-1; int rc, error, i; rc = WSCGetProviderPath( &wsapi->ProviderId, wszProviderPath, &dwProviderPathLen, &error ); if ( 0 != rc ) { fprintf(stderr, "WSCGetProviderPath failed: %d\n", error); lstrcpyW(wszProviderPath, L"(error)"); } // // Display protocol information // printf("*** %S ***\n", wsapi->szProtocol); printf("Path: %S\n", wszProviderPath); // // Display provider ID and catalog ID as well as LSP chain information // StringFromGUID2( wsapi->ProviderId, szGuidString, MAX_PATH-1 ); printf("Provider Id: %S\n", szGuidString); if(wsapi->ProtocolChain.ChainLen == LAYERED_PROTOCOL)printf("LSP: Yes\n"); else printf("LSP: No\n"); printf("Catalog Entry Id: %ld\n", wsapi->dwCatalogEntryId); printf("Number of Chain Entries: %d {",wsapi->ProtocolChain.ChainLen); for(i=0; i < wsapi->ProtocolChain.ChainLen ;i++) printf("%ld ", wsapi->ProtocolChain.ChainEntries[i]); printf("}\n"); printf("Version: %d\n\n", wsapi->iVersion); } void FreeProviders( LPWSAPROTOCOL_INFOW ProtocolInfo ) { LspFree( ProtocolInfo ); } void PrintProviders( WINSOCK_CATALOG Catalog) { WSAPROTOCOL_INFOW *pProtocolInfo = NULL; INT iProtocolCount = 0, i; // Enumerate catalog and print it pProtocolInfo = EnumerateProviders( Catalog, &iProtocolCount ); if ( NULL == pProtocolInfo ) { fprintf( stderr, "PrintProviders: Unable to enumerate catalog!\n" ); goto cleanup; } for(i=0; i < iProtocolCount ;i++) { PrintProtocolInfo( &pProtocolInfo[ i ] ); } cleanup: if ( NULL != pProtocolInfo ) FreeProviders( pProtocolInfo ); return; } int main(void) { #ifdef _WIN64 WINSOCK_CATALOG eCatalog = /*LspCatalog64Only*/LspCatalogBoth; #else WINSOCK_CATALOG eCatalog = LspCatalog32Only; #endif WSADATA wsd; int rc; setlocale(LC_ALL,"Russian"); // Load Winsock rc = WSAStartup( MAKEWORD(2,2), &wsd ); if ( 0 != rc ) { fprintf( stderr, "Unable to load Winsock: %d\n", rc ); return -1; } // Initialize data structures LspCreateHeap( &rc ); // Print the 32-bit catalog if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) ) { printf( "\n32-bit providers:\n\n" ); PrintProviders( LspCatalog32Only); printf( "=======================\n" ); } // Print the 64-bit catalog if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) ) { printf( "\n64-bit providers:\n\n" ); PrintProviders( LspCatalog64Only); printf( "=======================\n" ); } system("PAUSE"); return 0; }