/*++ Copyright (c) 1992 Microsoft Corporation Module Name: addrconv.c Abstract: This module contains address conversion routines. Author: Keith Moore (keithmo) 8-Jan-1996 Revision History: --*/ #define UNICODE #include "winsockp.h" PWINSOCK_HELPER_DLL_INFO SockFindHelperDllForAddressFamily( INT AddressFamily ); BOOL SockIsAddressFamilySupported( IN PWINSOCK_MAPPING Mapping, IN INT AddressFamily ); int WSPAPI WSPAddressToString( LPSOCKADDR lpsaAddress, DWORD dwAddressLength, LPWSAPROTOCOL_INFOW lpProtocolInfo, LPWSTR lpszAddressString, LPDWORD lpdwAddressStringLength, LPINT lpErrno ) /*++ Routine Description: This routine converts all components of a SOCKADDR structure into a human- readable string representation of the address. This is used mainly for display purposes. Arguments: lpsaAddress - Points to a SOCKADDR structure to translate into a string. dwAddressLength - The length of the Address SOCKADDR. lpProtocolInfo - The WSAPROTOCOL_INFOW struct for a particular provider. lpszAddressString - A buffer which receives the human-readable address string. lpdwAddressStringLength - The length of the AddressString buffer. Returns the length of the string actually copied into the buffer. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPAddressToString() returns 0. Otherwise, it returns SOCKET_ERROR, and a specific error code is available in lpErrno. --*/ { PWINSOCK_HELPER_DLL_INFO helperDll; // // Find a helper DLL supporting this address family. // helperDll = SockFindHelperDllForAddressFamily( (INT)lpsaAddress->sa_family ); if( helperDll == NULL || helperDll->WSHAddressToString == NULL ) { *lpErrno = WSA_INVALID_PARAMETER; return SOCKET_ERROR; } if( dwAddressLength < (DWORD)helperDll->MinSockaddrLength ) { *lpErrno = WSAEFAULT; return SOCKET_ERROR; } *lpErrno = helperDll->WSHAddressToString( lpsaAddress, dwAddressLength, lpProtocolInfo, lpszAddressString, lpdwAddressStringLength ); return ( *lpErrno == 0 ) ? NO_ERROR : SOCKET_ERROR; } // WSPAddressToString int WSPAPI WSPStringToAddress( LPWSTR AddressString, INT AddressFamily, LPWSAPROTOCOL_INFOW lpProtocolInfo, LPSOCKADDR lpAddress, LPINT lpAddressLength, LPINT lpErrno ) /*++ Routine Description: This routine converts a human-readable string to a socket address structure (SOCKADDR) suitable for pass to Windows Sockets routines which take such a structure. Any missing components of the address will be defaulted to a reasonable value if possible. For example, a missing port number will be defaulted to zero. Arguments: AddressString - Points to the zero-terminated human-readable string to convert. AddressFamily - The address family to which the string belongs, or AF_UNSPEC if it is unknown. lpProtocolInfo - The provider's WSAPROTOCOL_INFOW struct. lpAddress - A buffer which is filled with a single SOCKADDR structure. lpAddressLength - The length of the Address buffer. Returns the size of the resultant SOCKADDR structure. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPStringToAddress() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { PWINSOCK_HELPER_DLL_INFO helperDll; // // Find a helper DLL supporting this address family. // helperDll = SockFindHelperDllForAddressFamily( AddressFamily ); if( helperDll == NULL || helperDll->WSHStringToAddress == NULL ) { *lpErrno = WSA_INVALID_PARAMETER; return SOCKET_ERROR; } if( *lpAddressLength < helperDll->MinSockaddrLength ) { *lpErrno = WSAEFAULT; return SOCKET_ERROR; } *lpErrno = helperDll->WSHStringToAddress( AddressString, AddressFamily, lpProtocolInfo, lpAddress, lpAddressLength ); return ( *lpErrno == 0 ) ? NO_ERROR : SOCKET_ERROR; } // WSPStringToAddress PWINSOCK_HELPER_DLL_INFO SockFindHelperDllForAddressFamily( INT AddressFamily ) { PLIST_ENTRY listEntry; PWINSOCK_HELPER_DLL_INFO helperDll; INT error; PWSTR transportList; PWSTR currentTransport; PWINSOCK_MAPPING mapping; // // Acquire the global sockets lock and search the list of helper // DLLs for one which supports this address family. // SockAcquireGlobalLockExclusive(); for( listEntry = SockHelperDllListHead.Flink; listEntry != &SockHelperDllListHead; listEntry = listEntry->Flink ) { helperDll = CONTAINING_RECORD( listEntry, WINSOCK_HELPER_DLL_INFO, HelperDllListEntry ); IF_DEBUG( HELPER_DLL ) { WS_PRINT(( "SockFindHelperDllForAddressFamily: examining DLL at %lx for AF %ld\n", helperDll, AddressFamily )); } // // Check to see whether the DLL supports the address family. // if( SockIsAddressFamilySupported( helperDll->Mapping, AddressFamily ) ) { // // Found a match. // SockReleaseGlobalLock(); return helperDll; } } // // We don't have any loaded DLLs that support this address family. // Attempt to find a DLL in the registry that can handle the // specified address family. First get the REG_MULTI_SZ that contains // the list of transports that have winsock support. // error = SockLoadTransportList( &transportList ); if( error != NO_ERROR ) { SockReleaseGlobalLock(); return NULL; } // // Loop through the transports looking for one which will support // the socket we're opening. // for( currentTransport = transportList; *currentTransport != UNICODE_NULL; currentTransport += wcslen( currentTransport ) + 1 ) { // // Load the list of triples supported by this transport. // error = SockLoadTransportMapping( currentTransport, &mapping ); if( error != NO_ERROR ) { WS_PRINT(( "SockLoadTransportMapping( %ws ) failed: %ld\n", currentTransport, error )); continue; } // // Determine whether the triple of the socket we're opening is // in this transport's mapping. // if( SockIsAddressFamilySupported( mapping, AddressFamily ) ) { // // The address family is supported. Load the helper DLL for the // transport. // error = SockLoadHelperDll( currentTransport, mapping, &helperDll ); // // If we couldn't load the DLL, continue looking for a helper // DLL that will support this triple. // if( error == NO_ERROR ) { // // Success! // SockReleaseGlobalLock(); return helperDll; } } // // This transport does not support the socket we're opening. // Free the memory that held the mapping and try the next // transport in the list. // FREE_HEAP( mapping ); } SockReleaseGlobalLock(); // // Bummer. // return NULL; } // SockFindHelperDllForAddressFamily BOOL SockIsAddressFamilySupported( IN PWINSOCK_MAPPING Mapping, IN INT AddressFamily ) { ULONG i; // // Loop through the mapping attempting to find the address family. // for ( i = 0; i < Mapping->Rows; i++ ) { if ( (INT)Mapping->Mapping[i].AddressFamily == AddressFamily ) { return TRUE; } } return FALSE; } // SockIsAddressFamilySupported