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

GetAddrInfoW

関数
ホスト名やサービス名からアドレス情報を解決する。
DLLWS2_32.dll呼出規約winapi対応OSWindows 8.1 以降

シグネチャ

// WS2_32.dll
#include <windows.h>

INT GetAddrInfoW(
    LPCWSTR pNodeName,   // optional
    LPCWSTR pServiceName,   // optional
    const ADDRINFOW* pHints,   // optional
    ADDRINFOW** ppResult
);

パラメーター

名前方向説明
pNodeNameLPCWSTRinoptionalホスト (ノード) 名または数値ホストアドレス文字列を含む NULL 終端の Unicode 文字列へのポインター。インターネットプロトコルの場合、数値ホストアドレス文字列はドット区切り 10 進表記の IPv4 アドレス、または 16 進表記の IPv6 アドレスです。
pServiceNameLPCWSTRinoptional

サービス名、または文字列として表現されたポート番号のいずれかを含む NULL 終端の Unicode 文字列へのポインター。

サービス名はポート番号の文字列エイリアスです。たとえば「http」は、HTTP プロトコルで Web サーバーが使用する既定のポートとして Internet Engineering Task Force (IETF) によって定義された、ポート 80 のエイリアスです。ポート番号が指定されない場合に pServiceName パラメーターに指定可能な値は、次のファイルに一覧されています。

%WINDIR%\system32\drivers\etc\services

pHintsADDRINFOW*inoptional

呼び出し側がサポートする socket の種類に関するヒントを提供する addrinfoW 構造体へのポインター。

pHints パラメーターが指す addrinfoW 構造体の ai_addrlenai_canonnameai_addrai_next の各メンバーは、0 または NULL でなければなりません。そうでない場合、GetAddrInfoEx 関数は WSANO_RECOVERY で失敗します。

詳細は「解説」を参照してください。

ppResultADDRINFOW**outホストに関する応答情報を含む 1 つ以上の addrinfoW 構造体の連結リストへのポインター。

戻り値の型: INT

公式ドキュメント

Unicode のホスト名からアドレスへの、プロトコルに依存しない変換を行います。

戻り値

成功した場合は 0 を返します。失敗した場合は、 Windows Sockets エラーコードに記載されている、0 以外の Windows Sockets エラーコードを返します。

GetAddrInfoW 関数が返す 0 以外のエラーコードのほとんどは、Internet Engineering Task Force (IETF) 勧告で概説されている一連のエラーに対応します。次の表に、これらのエラーコードとそれに対応する WSA 相当のエラーを示します。WSA エラーコードは Winsock プログラマーにとってなじみがあり包括的なエラー情報を提供するため、WSA エラーコードの使用を推奨します。

エラー値 WSA 相当 説明
EAI_AGAIN WSATRY_AGAIN 名前解決で一時的な失敗が発生しました。
EAI_BADFLAGS WSAEINVAL pHints パラメーターの ai_flags メンバーに無効な値が指定されました。
EAI_FAIL WSANO_RECOVERY 名前解決で回復不能な失敗が発生しました。
EAI_FAMILY WSAEAFNOSUPPORT pHints パラメーターの ai_family メンバーがサポートされていません。
EAI_MEMORY WSA_NOT_ENOUGH_MEMORY メモリ割り当ての失敗が発生しました。
EAI_NONAME WSAHOST_NOT_FOUND 指定されたパラメーターでは名前が解決されないか、pNodeName パラメーターと pServiceName パラメーターが指定されませんでした。
EAI_SERVICE WSATYPE_NOT_FOUND pServiceName パラメーターは、pHints パラメーターで指定された ai_socktype メンバーではサポートされていません。
EAI_SOCKTYPE WSAESOCKTNOSUPPORT pHints パラメーターの ai_socktype メンバーがサポートされていません。

GetAddrInfoW 関数が返す EAI_* コードに基づいてエラーメッセージを表示するには、 gai_strerror 関数を使用します。 gai_strerror 関数は IETF 勧告への準拠のために提供されていますが、スレッドセーフではありません。そのため、 WSAGetLastError などの従来の Windows Sockets 関数の使用を推奨します。

エラーコード 意味
WSA_NOT_ENOUGH_MEMORY
操作を実行するためのメモリが不足していました。
WSAEAFNOSUPPORT
要求されたプロトコルと互換性のないアドレスが使用されました。このエラーは、hints パラメーターが指す addrinfoW 構造体の ai_family メンバーがサポートされていない場合に返されます。
WSAEINVAL
無効な引数が指定されました。このエラーは、hints パラメーターが指す addrinfoW 構造体の ai_flags メンバーに無効な値が指定された場合に返されます。
WSAESOCKTNOSUPPORT
このアドレスファミリには、指定された socket の種類のサポートが存在しません。このエラーは、hints パラメーターが指す addrinfoW 構造体の ai_socktype メンバーがサポートされていない場合に返されます。
WSAHOST_NOT_FOUND
そのようなホストは認識されていません。このエラーは、指定されたパラメーターでは名前が解決されないか、pNodename パラメーターと pServicename パラメーターが指定されなかった場合に返されます。
WSANO_DATA
要求された名前は有効ですが、要求された種類のデータが見つかりませんでした。
WSANO_RECOVERY
データベース検索中に回復不能なエラーが発生しました。このエラーは、名前解決で回復不能なエラーが発生した場合に返されます。
WSANOTINITIALISED
この関数を使用する前に、 WSAStartup の呼び出しが成功している必要があります。
WSATRY_AGAIN
これは通常、ホスト名解決中の一時的なエラーであり、ローカルサーバーが権威サーバーから応答を受信しなかったことを意味します。このエラーは、名前解決で一時的な失敗が発生した場合に返されます。
WSATYPE_NOT_FOUND
指定されたクラスが見つかりませんでした。pServiceName パラメーターは、hints パラメーターが指す addrinfoW 構造体の指定された ai_socktype メンバーではサポートされていません。

解説(Remarks)

GetAddrInfoW 関数は、ホスト名からアドレスへのプロトコルに依存しない変換を行う関数の Unicode 版です。この関数の ANSI 版は getaddrinfo です。

GetAddrInfoW 関数は NS_DNS 名前空間の結果を返します。複数の名前空間プロバイダーが情報を返した場合、GetAddrInfoW 関数はすべての応答を集約します。IPv6 および IPv4 プロトコルで使用する場合、NS_DNS 名前空間の名前解決は、Domain Name System (DNS)、ローカルの hosts ファイル、またはその他の命名メカニズムによって行われます。

Winsock のヘッダーファイル内のマクロは、大文字小文字を混在させた関数名 GetAddrInfoADDRINFOT 構造体を定義します。この GetAddrInfo 関数は、pNodeName および pServiceName パラメーターを TCHAR 型のポインターとして、pHints および ppResult パラメーターを ADDRINFOT 型のポインターとして呼び出す必要があります。UNICODE または _UNICODE が定義されている場合、GetAddrInfo は関数の Unicode 版である GetAddrInfoW として定義され、ADDRINFOTaddrinfoW 構造体として定義されます。UNICODE または _UNICODE が定義されていない場合、GetAddrInfo は関数の ANSI 版である getaddrinfo として定義され、ADDRINFOTaddrinfo 構造体として定義されます。

pNodeName または pServiceName パラメーターの一方または両方が、NULL 終端の Unicode 文字列を指している必要があります。通常は両方が指定されます。

成功すると、addrinfoW 構造体の連結リストが ppResult パラメーターに返されます。このリストは、返された各 addrinfoW 構造体の ai_next メンバーが提供するポインターを NULL ポインターに到達するまでたどることで処理できます。返された各 addrinfoW 構造体において、ai_familyai_socktypeai_protocol の各メンバーは、 socket 関数または WSASocket 関数呼び出しの対応する引数に相当します。また、返された各 addrinfoW 構造体の ai_addr メンバーは、入力済みのソケットアドレス構造体を指し、その長さは ai_addrlen メンバーで指定されます。

pNodeName パラメーターがコンピューター名を指している場合、ソース アドレスとして使用できる、そのコンピューターのすべての永続的なアドレスが返されます。Windows Vista 以降では、これらのアドレスには、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが false に設定されている、GetUnicastIpAddressTable 関数または GetUnicastIpAddressEntry 関数が返すすべてのユニキャスト IP アドレスが含まれます。

pNodeName パラメーターが "localhost" に等しい文字列を指している場合、ローカルコンピューター上のすべてのループバックアドレスが返されます。

pNodeName パラメーターが空文字列を含む場合、ローカルコンピューター上に登録されているすべてのアドレスが返されます。

Windows Server 2003 以降では、pNodeName パラメーターが "..localmachine" に等しい文字列を指している場合、ローカルコンピューター上に登録されているすべてのアドレスが返されます。

pNodeName パラメーターがクラスター仮想サーバー名を参照している場合、仮想サーバーのアドレスのみが返されます。Windows Vista 以降では、これらのアドレスには、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが true に設定されている、GetUnicastIpAddressTable 関数または GetUnicastIpAddressEntry 関数が返すすべてのユニキャスト IP アドレスが含まれます。クラスタリングの詳細については、Windows Clustering を参照してください。

Windows 7 Service Pack 1 (SP1) および Windows Server 2008 R2 Service Pack 1 (SP1) では、IP アドレスに SkipAsSource 属性を設定するためのサポートが Netsh.exe に追加されました。これにより動作も変更され、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが false に設定されている場合、IP アドレスは DNS に登録されます。SkipAsSource メンバーが true に設定されている場合、IP アドレスは DNS に登録されません。

Windows 7 および Windows Server 2008 R2 向けには、IP アドレスに SkipAsSource 属性を設定するためのサポートを Netsh.exe に追加する修正プログラムが提供されています。この修正プログラムによっても動作が変更され、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが false に設定されている場合、IP アドレスは DNS に登録されます。SkipAsSource メンバーが true に設定されている場合、IP アドレスは DNS に登録されません。詳細については、サポート技術情報 (KB) 2386184 を参照してください。

同様の修正プログラムは Windows Vista Service Pack 2 (SP2) および Windows Server 2008 Service Pack 2 (SP2) 向けにも提供されており、IP アドレスに SkipAsSource 属性を設定するためのサポートを Netsh.exe に追加します。この修正プログラムによっても動作が変更され、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが false に設定されている場合、IP アドレスは DNS に登録されます。SkipAsSource メンバーが true に設定されている場合、IP アドレスは DNS に登録されません。

GetAddrInfoW 関数の呼び出し側は、pHints パラメーターが指す addrinfoW 構造体を通じて、サポートする socket の種類に関するヒントを提供できます。pHints パラメーターを使用する場合、それに関連付けられた addrinfoW 構造体には次の規則が適用されます。

pHints パラメーターで提供される addrinfoW 構造体内のその他の値は、特定の要件を示します。たとえば、呼び出し側が IPv4 のみを扱い IPv6 を扱わない場合、ai_family メンバーを AF_INET に設定します。別の例として、呼び出し側が TCP のみを扱い UDP を扱わない場合、ai_socktype メンバーを SOCK_STREAM に設定します。

pHints パラメーターが NULL ポインターの場合、 GetAddrInfoW 関数は、pHints 内の addrinfoW 構造体が ai_family メンバーを AF_UNSPEC に、その他すべてのメンバーを 0 に設定して初期化されたものとして扱います。

Windows Vista 以降で GetAddrInfoW がサービスから呼び出される場合、その操作がサービスを呼び出したユーザープロセスの結果であるときは、サービスはそのユーザーになりすます (impersonate) 必要があります。これはセキュリティを適切に強制するためです。

GetAddrInfoW 関数は、IP アドレスのテキスト文字列表現を、その IP アドレスの sockaddr 構造体やその他の情報を含む addrinfoW 構造体に変換するために使用できます。この方法で使用するには、pNodeName パラメーターが指す文字列に IP アドレスのテキスト表現を含め、pHints パラメーターが指す addrinfoW 構造体の ai_flags メンバーに AI_NUMERICHOST フラグを設定する必要があります。pNodeName パラメーターが指す文字列には、IPv4 アドレスまたは IPv6 アドレスのいずれかのテキスト表現を含めることができます。テキスト IP アドレスは、ppResult パラメーターが指す addrinfoW 構造体に変換されます。返される addrinfoW 構造体には、IP アドレスの sockaddr 構造体と、その IP アドレスに関する追加情報が含まれます。Windows Server 2003 および Windows XP で IPv6 アドレス文字列に対してこの方法を機能させるには、ローカルコンピューターに IPv6 プロトコルがインストールされている必要があります。そうでない場合は、WSAHOST_NOT_FOUND エラーが返されます。

動的に割り当てられたアドレス情報の解放

ppResult パラメーターが指す、 GetAddrInfoW 関数が返すすべての情報は動的に割り当てられます。これには、すべての addrinfoW 構造体、ソケットアドレス構造体、および addrinfoW 構造体が指す正規ホスト名文字列が含まれます。この関数の呼び出しが成功して割り当てられたメモリは、その後 FreeAddrInfoW を呼び出して解放する必要があります。

サンプルコード

次のコード例は、GetAddrInfoW 関数の使用方法を示しています。
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

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

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

// set APPVER=5.02 for WinXP SP2 and later

int __cdecl wmain(int argc, wchar_t **argv)
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;
    INT iRetval;

    DWORD dwRetval;

    int i = 1;
    
    ADDRINFOW *result = NULL;
    ADDRINFOW *ptr = NULL;
    ADDRINFOW hints;

//    struct sockaddr_in6 *sockaddr_ipv6;
    LPSOCKADDR sockaddr_ip;

    wchar_t ipstringbuffer[46];
    DWORD ipbufferlength = 46;

    // Validate the parameters
    if (argc != 3) {
        wprintf(L"usage: %ws <hostname> <servicename>\n", argv[0]);
        wprintf(L"getaddrinfow provides protocol-independent translation\n");
        wprintf(L"   from an Unicode host name to an IP address\n");
        wprintf(L"%ws example usage\n", argv[0]);
        wprintf(L"   %ws www.contoso.com 0\n", argv[0]);
        return 1;
    }


    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        wprintf(L"WSAStartup failed: %d\n", iResult);
        return 1;
    }

    //--------------------------------
    // Setup the hints address info structure
    // which is passed to the getaddrinfo() function
    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    wprintf(L"Calling getaddrinfow with following parameters:\n");
    wprintf(L"\tnodename = %ws\n", argv[1]);
    wprintf(L"\tservname (or port) = %ws\n\n", argv[2]);
    

//--------------------------------
// Call GetAddrinfoW(). If the call succeeds,
// the result variable will hold a linked list
// of addrinfow structures containing response
// information
    dwRetval = GetAddrInfoW(argv[1], argv[2], &hints, &result);
    if ( dwRetval != 0 ) {
        wprintf(L"GetAddrInfoW failed with error: %d\n", dwRetval);
        WSACleanup();
        return 1;
    }

    wprintf(L"GetAddrInfoW returned success\n");
    
    // Retrieve each address and print out the hex bytes
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        wprintf(L"GetAddrInfoW response %d\n", i++);
        wprintf(L"\tFlags: 0x%x\n", ptr->ai_flags);
        wprintf(L"\tFamily: ");
        switch (ptr->ai_family) {
            case AF_UNSPEC:
                wprintf(L"Unspecified\n");
                break;
            case AF_INET:
                wprintf(L"AF_INET (IPv4)\n");
                sockaddr_ip = (LPSOCKADDR) ptr->ai_addr;
                // The buffer length is changed by each call to WSAAddresstoString
                // So we need to set it for each iteration through the loop for safety
                ipbufferlength = 46;
                iRetval = WSAAddressToString(sockaddr_ip, (DWORD) ptr->ai_addrlen, NULL, 
                    ipstringbuffer, &ipbufferlength );
                if (iRetval)
                    wprintf(L"WSAAddressToString failed with %u\n", WSAGetLastError() );
                else    
                    wprintf(L"\tIPv4 address %ws\n", ipstringbuffer);
                break;
            case AF_INET6:
                wprintf(L"AF_INET6 (IPv6)\n");
                // the InetNtop function is available on Windows Vista and later
                // sockaddr_ipv6 = (struct sockaddr_in6 *) ptr->ai_addr;
                // printf("\tIPv6 address %s\n",
                //    InetNtop(AF_INET6, &sockaddr_ipv6->sin6_addr, ipstringbuffer, 46) );
                
                // We use WSAAddressToString since it is supported on Windows XP and later
                sockaddr_ip = (LPSOCKADDR) ptr->ai_addr;
                // The buffer length is changed by each call to WSAAddresstoString
                // So we need to set it for each iteration through the loop for safety
                ipbufferlength = 46;
                iRetval = WSAAddressToString(sockaddr_ip, (DWORD) ptr->ai_addrlen, NULL, 
                    ipstringbuffer, &ipbufferlength );
                if (iRetval)
                    wprintf(L"WSAAddressToString failed with %u\n", WSAGetLastError() );
                else    
                    wprintf(L"\tIPv6 address %ws\n", ipstringbuffer);
                break;
            default:
                wprintf(L"Other %ld\n", ptr->ai_family);
                break;
        }
        wprintf(L"\tSocket type: ");
        switch (ptr->ai_socktype) {
            case 0:
                wprintf(L"Unspecified\n");
                break;
            case SOCK_STREAM:
                wprintf(L"SOCK_STREAM (stream)\n");
                break;
            case SOCK_DGRAM:
                wprintf(L"SOCK_DGRAM (datagram) \n");
                break;
            case SOCK_RAW:
                wprintf(L"SOCK_RAW (raw) \n");
                break;
            case SOCK_RDM:
                wprintf(L"SOCK_RDM (reliable message datagram)\n");
                break;
            case SOCK_SEQPACKET:
                wprintf(L"SOCK_SEQPACKET (pseudo-stream packet)\n");
                break;
            default:
                wprintf(L"Other %ld\n", ptr->ai_socktype);
                break;
        }
        wprintf(L"\tProtocol: ");
        switch (ptr->ai_protocol) {
            case 0:
                wprintf(L"Unspecified\n");
                break;
            case IPPROTO_TCP:
                wprintf(L"IPPROTO_TCP (TCP)\n");
                break;
            case IPPROTO_UDP:
                wprintf(L"IPPROTO_UDP (UDP) \n");
                break;
            default:
                wprintf(L"Other %ld\n", ptr->ai_protocol);
                break;
        }
        wprintf(L"\tLength of this sockaddr: %d\n", ptr->ai_addrlen);
        wprintf(L"\tCanonical name: %s\n", ptr->ai_canonname);
    }

    FreeAddrInfoW(result);
    WSACleanup();

    return 0;
}
開発環境が、addrinfoW および GetAddrInfoW の構造体定義と関数定義をそれぞれ含む最新バージョンの Ws2tcpip.h を対象としていることを確認してください。

国際化ドメイン名

インターネットのホスト名は通常、非常に限定された文字セットで構成されます。

インターネットの成長に伴い、ASCII 文字セットで表現されない他の言語のインターネットホスト名を識別する必要性が高まっています。この必要性を満たし、非 ASCII 文字 (Unicode) を特別な ASCII 文字列として表現できるようにする識別子は、国際化ドメイン名 (IDN) と呼ばれます。IDN を標準的な方法で扱うために、Internationalizing Domain Names in Applications (IDNA) と呼ばれるメカニズムが使用されます。IDN および IDNA の仕様は、Internet Engineering Task Force (IETF) が公開した RFC 3490RTF 5890RFC 6365 に記載されています。

Windows 8 および Windows Server 2012 では、GetAddrInfoW 関数は、pNodeName パラメーターに渡された名前に適用される国際化ドメイン名 (IDN) の解析をサポートします。Winsock が Punycode/IDN のエンコードと変換を実行します。この動作は、後述の AI_DISABLE_IDN_ENCODING フラグを使用して無効にできます。

Windows 7 および Windows Server 2008 R2 以前では、GetAddrInfoW 関数は現在のところ、pNodeName パラメーターに渡された名前に適用される IDN の解析をサポートしていません。Winsock は Punycode/IDN 変換を一切実行しません。GetAddrInfoW 関数は、RFC 3490 に従って IDN を変換するために Punycode を使用しません。GetAddrInfoW 関数は、DNS にクエリを実行する際、Unicode 名を、エンタープライズ環境の Microsoft DNS サーバーで使用される形式である UTF-8 形式でエンコードします。

Windows Vista 以降のいくつかの関数は、IDN 内の Unicode ラベルとその ASCII 相当の表現との間の変換をサポートします。変換後の各 Unicode ラベルの表現は ASCII 文字のみで構成され、Unicode ラベルに非 ASCII 文字が含まれていた場合は xn-- というプレフィックスで始まります。これは、一部の DNS ツールおよびサーバーが ASCII 文字のみをサポートするため、インターネット上の既存の DNS サーバーをサポートする目的によるものです (RFC 3490 を参照)。

IdnToAscii 関数は、RFC 3490 で定義された標準アルゴリズムを使用し、Punycode によって IDN を元の Unicode 文字列の ASCII 表現に変換します。IdnToUnicode 関数は、IDN の ASCII 形式を通常の Unicode UTF-16 エンコード構文に変換します。詳細および関連するドラフト標準へのリンクについては、国際化ドメイン名 (IDN) の処理を参照してください。

IdnToAscii 関数を使用して、IDN 名を ASCII 形式に変換できます。この ASCII 形式を GetAddrInfoW 関数に渡すには、MultiByteToWideChar 関数を使用して CHAR 文字列を WCHAR 文字列に変換し、それを pNodeName パラメーターとして GetAddrInfoW 関数に渡します。

hints パラメーターでの ai_flags の使用

pHints パラメーターで提供される省略可能な addrinfoW 構造体の ai_flags メンバー内のフラグは、関数の動作を変更します。

これらのフラグビットは、Windows 7 向け Microsoft Windows ソフトウェア開発キット (SDK) の Ws2def.h ヘッダーファイルで定義されています。これらのフラグビットは、Windows Server 2008 および Windows Vista 向け Windows SDK の Ws2tcpip.h ヘッダーファイルで定義されています。これらのフラグビットは、Windows Server 2003 および Windows XP 向けプラットフォームソフトウェア開発キット (SDK) の Ws2tcpip.h ヘッダーファイルで定義されています。

フラグビットには、次の組み合わせを指定できます。

フラグビット 説明
AI_PASSIVE AI_PASSIVE フラグを設定すると、呼び出し側が、返されたソケットアドレス構造体を bind 関数の呼び出しで使用する意図があることを示します。AI_PASSIVE フラグが設定され、かつ pNodeNameNULL ポインターの場合、ソケットアドレス構造体の IP アドレス部分は、IPv4 アドレスの場合は INADDR_ANY に、IPv6 アドレスの場合は IN6ADDR_ANY_INIT に設定されます。

AI_PASSIVE フラグが設定されていない場合、返されるソケットアドレス構造体は、コネクション指向プロトコルの connect 関数の呼び出し、またはコネクションレスプロトコルの connectsendtosend 関数のいずれかの呼び出しに対応できる状態になります。この場合、pNodeName パラメーターが NULL ポインターであれば、ソケットアドレス構造体の IP アドレス部分はループバックアドレスに設定されます。

AI_CANONNAME AI_CANONNAMEAI_NUMERICHOST も使用されていない場合、 GetAddrInfoW 関数は解決を試みます。リテラル文字列が渡された場合は GetAddrInfoW はその文字列の変換を試み、ホスト名が渡された場合は GetAddrInfoW 関数はその名前を 1 つまたは複数のアドレスに解決しようと試みます。

AI_CANONNAME ビットが設定されている場合、pNodeName パラメーターを NULL にすることはできません。そうでない場合、 GetAddrInfoEx 関数は WSANO_RECOVERY で失敗します。

AI_CANONNAME ビットが設定され、かつ GetAddrInfoW 関数が成功を返した場合、ppResult パラメーター内の ai_canonname メンバーは、指定されたノードの正規名を含む NULL 終端の文字列を指します。

GetAddrInfoW 関数は、AI_CANONNAME フラグが設定されている場合でも成功を返すことがありますが、関連付けられた addrinfoW 構造体内の ai_canonname メンバーが NULL になることがあります。そのため、AI_CANONNAME フラグを使用する際の推奨方法には、関連付けられた addrinfoW 構造体内の ai_canonname メンバーが NULL かどうかを確認することが含まれます。
AI_NUMERICHOST AI_NUMERICHOST ビットが設定されている場合、pNodeName パラメーターには NULL 以外の数値ホストアドレス文字列を含める必要があります。そうでない場合は EAI_NONAME エラーが返されます。このフラグは、名前解決サービスが呼び出されるのを防ぎます。
AI_NUMERICSERV AI_NUMERICSERV ビットが設定されている場合、pServiceName パラメーターには NULL 以外の数値ポート番号を含める必要があります。そうでない場合は EAI_NONAME エラーが返されます。このフラグは、名前解決サービスが呼び出されるのを防ぎます。

AI_NUMERICSERV フラグは、Windows Vista 以降向けの Windows SDK で定義されています。AI_NUMERICSERV フラグは Microsoft 製プロバイダーではサポートされていません。

AI_ALL AI_ALL ビットが設定されている場合、IPv6 アドレスと、AI_V4MAPPED を伴う IPv4 アドレスの両方が要求されます。

AI_ALL フラグは、Windows Vista 以降向けの Windows SDK で定義されています。AI_ALL フラグは Windows Vista 以降でサポートされています。

AI_ADDRCONFIG AI_ADDRCONFIG ビットが設定されている場合、GetAddrInfoW はグローバルアドレスが構成されている場合にのみ解決を行います。AI_ADDRCONFIG フラグが指定されている場合、IPv4 アドレスはローカルシステムに IPv4 アドレスが構成されている場合にのみ返され、IPv6 アドレスはローカルシステムに IPv6 アドレスが構成されている場合にのみ返されます。IPv4 または IPv6 のループバックアドレスは、有効なグローバルアドレスとは見なされません。

AI_ADDRCONFIG フラグは、Windows Vista 以降向けの Windows SDK で定義されています。AI_ADDRCONFIG フラグは Windows Vista 以降でサポートされています。

AI_V4MAPPED AI_V4MAPPED ビットが設定され、IPv6 アドレスの要求が失敗した場合、IPv4 アドレスに対する名前サービス要求が行われ、これらのアドレスは IPv4 マップ IPv6 アドレス形式に変換されます。

AI_V4MAPPED フラグは、Windows Vista 以降向けの Windows SDK で定義されています。AI_V4MAPPED フラグは Windows Vista 以降でサポートされています。

AI_NON_AUTHORITATIVE AI_NON_AUTHORITATIVE ビットが設定されている場合、NS_EMAIL 名前空間プロバイダーは権威ある結果と権威のない結果の両方を返します。AI_NON_AUTHORITATIVE ビットが設定されていない場合、NS_EMAIL 名前空間プロバイダーは権威ある結果のみを返します。

AI_NON_AUTHORITATIVE フラグは、Windows Vista 以降向けの Windows SDK で定義されています。AI_NON_AUTHORITATIVE フラグは Windows Vista 以降でサポートされており、NS_EMAIL 名前空間にのみ適用されます。

AI_SECURE AI_SECURE ビットが設定されている場合、NS_EMAIL 名前空間プロバイダーは、なりすましの可能性を最小限に抑えるために強化されたセキュリティで取得された結果を返します。

AI_SECURE フラグは、Windows Vista 以降向けの Windows SDK で定義されています。AI_SECURE フラグは Windows Vista 以降でサポートされており、NS_EMAIL 名前空間にのみ適用されます。

AI_RETURN_PREFERRED_NAMES AI_RETURN_PREFERRED_NAMES が設定されている場合、pNodeName パラメーターには名前を指定しないでください。NS_EMAIL 名前空間プロバイダーは、公開用の優先名を返します。

AI_RETURN_PREFERRED_NAMES フラグは、Windows Vista 以降向けの Windows SDK で定義されています。AI_RETURN_PREFERRED_NAMES フラグは Windows Vista 以降でサポートされており、NS_EMAIL 名前空間にのみ適用されます。

AI_FQDN AI_FQDN が設定され、フラットな名前 (単一ラベル) が指定された場合、GetAddrInfoW は、その名前が最終的に解決された完全修飾ドメイン名を返します。完全修飾ドメイン名は、関連付けられた addrinfoW 構造体内の ai_canonname メンバーに返されます。これは、DNS に登録された正規名を返す AI_CANONNAME ビットフラグとは異なり、その正規名はフラットな名前が解決された完全修飾ドメイン名とは異なる場合があります。AI_FQDN ビットと AI_CANONNAME ビットのうち、設定できるのは一方のみです。両方のフラグが指定されている場合、GetAddrInfoW 関数は EAI_BADFLAGS で失敗します。

AI_FQDN ビットが設定されている場合、pNodeName パラメーターを NULL にすることはできません。そうでない場合、 GetAddrInfoEx 関数は WSANO_RECOVERY で失敗します。

Windows 7: AI_FQDN フラグは、Windows 7 以降向けの Windows SDK で定義されています。AI_FQDN フラグは Windows 7 以降でサポートされています。

AI_FILESERVER AI_FILESERVER が設定されている場合、これは、クエリ対象のホスト名がファイル共有シナリオで使用されていることを名前空間プロバイダーに伝えるヒントです。名前空間プロバイダーはこのヒントを無視する場合があります。

Windows 7: AI_FILESERVER フラグは、Windows 7 以降向けの Windows SDK で定義されています。AI_FILESERVER フラグは Windows 7 以降でサポートされています。

AI_DISABLE_IDN_ENCODING AI_DISABLE_IDN_ENCODING が設定されている場合、GetAddrInfoW 関数が呼び出す名前解決関数において、Punycode を使用した国際化ドメイン名の自動エンコードが無効になります。

Windows 8: AI_DISABLE_IDN_ENCODING フラグは、Windows 8 以降向けの Windows SDK で定義されています。AI_DISABLE_IDN_ENCODING フラグは Windows 8 以降でサポートされています。

Windows 8.1 および Windows Server 2012 R2: この関数は、Windows 8.1、Windows Server 2012 R2 以降の Windows ストアアプリでサポートされています。

メモ

ws2tcpip.h ヘッダーは GetAddrInfo を、UNICODE プリプロセッサ定数の定義に基づいてこの関数の ANSI 版または Unicode 版を自動的に選択するエイリアスとして定義します。エンコーディング中立のエイリアスの使用と、エンコーディング中立でないコードを混在させると、コンパイルエラーや実行時エラーを引き起こす不整合が生じる可能性があります。詳細については、関数プロトタイプの規約を参照してください。

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

各言語での呼び出し定義

// WS2_32.dll
#include <windows.h>

INT GetAddrInfoW(
    LPCWSTR pNodeName,   // optional
    LPCWSTR pServiceName,   // optional
    const ADDRINFOW* pHints,   // optional
    ADDRINFOW** ppResult
);
[DllImport("WS2_32.dll", ExactSpelling = true)]
static extern int GetAddrInfoW(
    [MarshalAs(UnmanagedType.LPWStr)] string pNodeName,   // LPCWSTR optional
    [MarshalAs(UnmanagedType.LPWStr)] string pServiceName,   // LPCWSTR optional
    IntPtr pHints,   // ADDRINFOW* optional
    IntPtr ppResult   // ADDRINFOW** out
);
<DllImport("WS2_32.dll", ExactSpelling:=True)>
Public Shared Function GetAddrInfoW(
    <MarshalAs(UnmanagedType.LPWStr)> pNodeName As String,   ' LPCWSTR optional
    <MarshalAs(UnmanagedType.LPWStr)> pServiceName As String,   ' LPCWSTR optional
    pHints As IntPtr,   ' ADDRINFOW* optional
    ppResult As IntPtr   ' ADDRINFOW** out
) As Integer
End Function
' pNodeName : LPCWSTR optional
' pServiceName : LPCWSTR optional
' pHints : ADDRINFOW* optional
' ppResult : ADDRINFOW** out
Declare PtrSafe Function GetAddrInfoW Lib "ws2_32" ( _
    ByVal pNodeName As LongPtr, _
    ByVal pServiceName As LongPtr, _
    ByVal pHints As LongPtr, _
    ByVal ppResult As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

GetAddrInfoW = ctypes.windll.ws2_32.GetAddrInfoW
GetAddrInfoW.restype = ctypes.c_int
GetAddrInfoW.argtypes = [
    wintypes.LPCWSTR,  # pNodeName : LPCWSTR optional
    wintypes.LPCWSTR,  # pServiceName : LPCWSTR optional
    ctypes.c_void_p,  # pHints : ADDRINFOW* optional
    ctypes.c_void_p,  # ppResult : ADDRINFOW** out
]
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WS2_32.dll')
GetAddrInfoW = Fiddle::Function.new(
  lib['GetAddrInfoW'],
  [
    Fiddle::TYPE_VOIDP,  # pNodeName : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # pServiceName : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # pHints : ADDRINFOW* optional
    Fiddle::TYPE_VOIDP,  # ppResult : ADDRINFOW** out
  ],
  Fiddle::TYPE_INT)
#[link(name = "ws2_32")]
extern "system" {
    fn GetAddrInfoW(
        pNodeName: *const u16,  // LPCWSTR optional
        pServiceName: *const u16,  // LPCWSTR optional
        pHints: *const ADDRINFOW,  // ADDRINFOW* optional
        ppResult: *mut *mut ADDRINFOW  // ADDRINFOW** out
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("WS2_32.dll")]
public static extern int GetAddrInfoW([MarshalAs(UnmanagedType.LPWStr)] string pNodeName, [MarshalAs(UnmanagedType.LPWStr)] string pServiceName, IntPtr pHints, IntPtr ppResult);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_GetAddrInfoW' -Namespace Win32 -PassThru
# $api::GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult)
#uselib "WS2_32.dll"
#func global GetAddrInfoW "GetAddrInfoW" sptr, sptr, sptr, sptr
; GetAddrInfoW pNodeName, pServiceName, varptr(pHints), varptr(ppResult)   ; 戻り値は stat
; pNodeName : LPCWSTR optional -> "sptr"
; pServiceName : LPCWSTR optional -> "sptr"
; pHints : ADDRINFOW* optional -> "sptr"
; ppResult : ADDRINFOW** out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "WS2_32.dll"
#cfunc global GetAddrInfoW "GetAddrInfoW" wstr, wstr, var, var
; res = GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult)
; pNodeName : LPCWSTR optional -> "wstr"
; pServiceName : LPCWSTR optional -> "wstr"
; pHints : ADDRINFOW* optional -> "var"
; ppResult : ADDRINFOW** out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; INT GetAddrInfoW(LPCWSTR pNodeName, LPCWSTR pServiceName, ADDRINFOW* pHints, ADDRINFOW** ppResult)
#uselib "WS2_32.dll"
#cfunc global GetAddrInfoW "GetAddrInfoW" wstr, wstr, var, var
; res = GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult)
; pNodeName : LPCWSTR optional -> "wstr"
; pServiceName : LPCWSTR optional -> "wstr"
; pHints : ADDRINFOW* optional -> "var"
; ppResult : ADDRINFOW** out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procGetAddrInfoW = ws2_32.NewProc("GetAddrInfoW")
)

// pNodeName (LPCWSTR optional), pServiceName (LPCWSTR optional), pHints (ADDRINFOW* optional), ppResult (ADDRINFOW** out)
r1, _, err := procGetAddrInfoW.Call(
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(pNodeName))),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(pServiceName))),
	uintptr(pHints),
	uintptr(ppResult),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // INT
function GetAddrInfoW(
  pNodeName: PWideChar;   // LPCWSTR optional
  pServiceName: PWideChar;   // LPCWSTR optional
  pHints: Pointer;   // ADDRINFOW* optional
  ppResult: Pointer   // ADDRINFOW** out
): Integer; stdcall;
  external 'WS2_32.dll' name 'GetAddrInfoW';
result := DllCall("WS2_32\GetAddrInfoW"
    , "WStr", pNodeName   ; LPCWSTR optional
    , "WStr", pServiceName   ; LPCWSTR optional
    , "Ptr", pHints   ; ADDRINFOW* optional
    , "Ptr", ppResult   ; ADDRINFOW** out
    , "Int")   ; return: INT
●GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult) = DLL("WS2_32.dll", "int GetAddrInfoW(char*, char*, void*, void*)")
# 呼び出し: GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult)
# pNodeName : LPCWSTR optional -> "char*"
# pServiceName : LPCWSTR optional -> "char*"
# pHints : ADDRINFOW* optional -> "void*"
# ppResult : ADDRINFOW** out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "ws2_32" fn GetAddrInfoW(
    pNodeName: [*c]const u16, // LPCWSTR optional
    pServiceName: [*c]const u16, // LPCWSTR optional
    pHints: [*c]ADDRINFOW, // ADDRINFOW* optional
    ppResult: [*c][*c]ADDRINFOW // ADDRINFOW** out
) callconv(std.os.windows.WINAPI) i32;
proc GetAddrInfoW(
    pNodeName: WideCString,  # LPCWSTR optional
    pServiceName: WideCString,  # LPCWSTR optional
    pHints: ptr ADDRINFOW,  # ADDRINFOW* optional
    ppResult: ptr ADDRINFOW  # ADDRINFOW** out
): int32 {.importc: "GetAddrInfoW", stdcall, dynlib: "WS2_32.dll".}
pragma(lib, "ws2_32");
extern(Windows)
int GetAddrInfoW(
    const(wchar)* pNodeName,   // LPCWSTR optional
    const(wchar)* pServiceName,   // LPCWSTR optional
    ADDRINFOW* pHints,   // ADDRINFOW* optional
    ADDRINFOW** ppResult   // ADDRINFOW** out
);
ccall((:GetAddrInfoW, "WS2_32.dll"), stdcall, Int32,
      (Cwstring, Cwstring, Ptr{ADDRINFOW}, Ptr{ADDRINFOW}),
      pNodeName, pServiceName, pHints, ppResult)
# pNodeName : LPCWSTR optional -> Cwstring
# pServiceName : LPCWSTR optional -> Cwstring
# pHints : ADDRINFOW* optional -> Ptr{ADDRINFOW}
# ppResult : ADDRINFOW** out -> Ptr{ADDRINFOW}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t GetAddrInfoW(
    const uint16_t* pNodeName,
    const uint16_t* pServiceName,
    void* pHints,
    void* ppResult);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult)
-- pNodeName : LPCWSTR optional
-- pServiceName : LPCWSTR optional
-- pHints : ADDRINFOW* optional
-- ppResult : ADDRINFOW** out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const GetAddrInfoW = lib.func('__stdcall', 'GetAddrInfoW', 'int32_t', ['str16', 'str16', 'void *', 'void *']);
// GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult)
// pNodeName : LPCWSTR optional -> 'str16'
// pServiceName : LPCWSTR optional -> 'str16'
// pHints : ADDRINFOW* optional -> 'void *'
// ppResult : ADDRINFOW** out -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("WS2_32.dll", {
  GetAddrInfoW: { parameters: ["buffer", "buffer", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult)
// pNodeName : LPCWSTR optional -> "buffer"
// pServiceName : LPCWSTR optional -> "buffer"
// pHints : ADDRINFOW* optional -> "pointer"
// ppResult : ADDRINFOW** out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t GetAddrInfoW(
    const uint16_t* pNodeName,
    const uint16_t* pServiceName,
    void* pHints,
    void* ppResult);
C, "WS2_32.dll");
// $ffi->GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult);
// pNodeName : LPCWSTR optional
// pServiceName : LPCWSTR optional
// pHints : ADDRINFOW* optional
// ppResult : ADDRINFOW** out
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Ws2_32 extends StdCallLibrary {
    Ws2_32 INSTANCE = Native.load("ws2_32", Ws2_32.class);
    int GetAddrInfoW(
        WString pNodeName,   // LPCWSTR optional
        WString pServiceName,   // LPCWSTR optional
        Pointer pHints,   // ADDRINFOW* optional
        Pointer ppResult   // ADDRINFOW** out
    );
}
@[Link("ws2_32")]
lib LibWS2_32
  fun GetAddrInfoW = GetAddrInfoW(
    pNodeName : UInt16*,   # LPCWSTR optional
    pServiceName : UInt16*,   # LPCWSTR optional
    pHints : ADDRINFOW*,   # ADDRINFOW* optional
    ppResult : ADDRINFOW**   # ADDRINFOW** out
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef GetAddrInfoWNative = Int32 Function(Pointer<Utf16>, Pointer<Utf16>, Pointer<Void>, Pointer<Void>);
typedef GetAddrInfoWDart = int Function(Pointer<Utf16>, Pointer<Utf16>, Pointer<Void>, Pointer<Void>);
final GetAddrInfoW = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<GetAddrInfoWNative, GetAddrInfoWDart>('GetAddrInfoW');
// pNodeName : LPCWSTR optional -> Pointer<Utf16>
// pServiceName : LPCWSTR optional -> Pointer<Utf16>
// pHints : ADDRINFOW* optional -> Pointer<Void>
// ppResult : ADDRINFOW** out -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function GetAddrInfoW(
  pNodeName: PWideChar;   // LPCWSTR optional
  pServiceName: PWideChar;   // LPCWSTR optional
  pHints: Pointer;   // ADDRINFOW* optional
  ppResult: Pointer   // ADDRINFOW** out
): Integer; stdcall;
  external 'WS2_32.dll' name 'GetAddrInfoW';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "GetAddrInfoW"
  c_GetAddrInfoW :: CWString -> CWString -> Ptr () -> Ptr () -> IO Int32
-- pNodeName : LPCWSTR optional -> CWString
-- pServiceName : LPCWSTR optional -> CWString
-- pHints : ADDRINFOW* optional -> Ptr ()
-- ppResult : ADDRINFOW** out -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let getaddrinfow =
  foreign "GetAddrInfoW"
    ((ptr uint16_t) @-> (ptr uint16_t) @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* pNodeName : LPCWSTR optional -> (ptr uint16_t) *)
(* pServiceName : LPCWSTR optional -> (ptr uint16_t) *)
(* pHints : ADDRINFOW* optional -> (ptr void) *)
(* ppResult : ADDRINFOW** out -> (ptr void) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library ws2_32 (t "WS2_32.dll"))
(cffi:use-foreign-library ws2_32)

(cffi:defcfun ("GetAddrInfoW" get-addr-info-w :convention :stdcall) :int32
  (p-node-name (:string :encoding :utf-16le))   ; LPCWSTR optional
  (p-service-name (:string :encoding :utf-16le))   ; LPCWSTR optional
  (p-hints :pointer)   ; ADDRINFOW* optional
  (pp-result :pointer))   ; ADDRINFOW** out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $GetAddrInfoW = Win32::API::More->new('WS2_32',
    'int GetAddrInfoW(LPCWSTR pNodeName, LPCWSTR pServiceName, LPVOID pHints, LPVOID ppResult)');
# my $ret = $GetAddrInfoW->Call($pNodeName, $pServiceName, $pHints, $ppResult);
# pNodeName : LPCWSTR optional -> LPCWSTR
# pServiceName : LPCWSTR optional -> LPCWSTR
# pHints : ADDRINFOW* optional -> LPVOID
# ppResult : ADDRINFOW** out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目
使用する型