GetAddrInfoExW 関数 (ws2tcpip.h)
GetAddrInfoEx 関数は、プロトコルに依存しない名前解決と、要求を処理する名前空間プロバイダーを修飾するための追加パラメーターを提供します。
構文
INT WSAAPI GetAddrInfoExW(
[in, optional] PCWSTR pName,
[in, optional] PCWSTR pServiceName,
[in] DWORD dwNameSpace,
[in, optional] LPGUID lpNspId,
[in, optional] const ADDRINFOEXW *hints,
[out] PADDRINFOEXW *ppResult,
[in, optional] timeval *timeout,
[in, optional] LPOVERLAPPED lpOverlapped,
[in, optional] LPLOOKUPSERVICE_COMPLETION_ROUTINE lpCompletionRoutine,
[out, optional] LPHANDLE lpHandle
);
パラメーター
[in, optional] pName
ホスト (ノード) 名または数値ホスト アドレス文字列を含む NULL で終わる文字列へのポインター。 インターネット プロトコルの場合、数値ホスト アドレス文字列はドット 10 進数の IPv4 アドレスまたは IPv6 16 進アドレスです。
[in, optional] pServiceName
文字列として表されるサービス名またはポート番号を含む 、NULL で終わる省略可能な文字列へのポインター。
サービス名は、ポート番号の文字列エイリアスです。 たとえば、"http" は、インターネット エンジニアリング タスク フォース (IETF) によって HTTP プロトコルの Web サーバーで使用される既定のポートとして定義されているポート 80 のエイリアスです。 ポート番号が指定されていない場合の pServiceName パラメーターに指定できる値を次のファイルに示します。
%WINDIR%\system32\drivers\etc\services
[in] dwNameSpace
クエリを実行する名前空間プロバイダーを決定する省略可能な名前空間識別子。 特定の名前空間識別子を渡すと、指定された名前空間をサポートする名前空間プロバイダーのみが照会されます。 NS_ALLを指定すると、すべてのインストール済みおよびアクティブな名前空間プロバイダーが照会されます。
dwNameSpace パラメーターのオプションは、Winsock2.h インクルード ファイルに一覧表示されます。 Windows Vista 以降では、いくつかの名前空間プロバイダーが追加されています。 他の名前空間プロバイダーをインストールできるため、次の使用可能な値は、一般的に使用できる値のみです。 その他の多くの値を使用できます。
[in, optional] lpNspId
複数の名前空間プロバイダーが NS_DNS などの 1 つの名前空間に登録されている場合にクエリを実行する、特定の名前空間プロバイダーのオプションの GUID へのポインター。 特定の名前空間プロバイダーに GUID を渡すと、指定された名前空間プロバイダーのみがクエリされます。 WSAEnumNameSpaceProviders 関数を呼び出して、名前空間プロバイダーの GUID を取得できます。
[in, optional] hints
呼び出し元がサポートするソケットの種類に関するヒントを提供する addrinfoex 構造体へのポインター。
pHints パラメーターが指すaddrinfoex 構造体のai_addrlen、ai_canonname、ai_addr、およびai_nextメンバーは、0 または NULL である必要があります。 それ以外の場合、 GetAddrInfoEx 関数は WSANO_RECOVERYで失敗します。
詳細については、「解説」を参照してください。
[out] ppResult
ホストに関する応答情報を含む 1 つ以上の addrinfoex 構造体のリンクされたリストへのポインター。
[in, optional] timeout
呼び出しを中止する前に名前空間プロバイダーからの応答を待機する時間をミリ秒単位で示す省略可能なパラメーター。
このパラメーターは、GetAddrInfoEx関数を呼び出す前に UNICODE または_UNICODE マクロがソースで定義されている場合にのみサポートされます。 それ以外の場合、このパラメーターは現在予約されており、タイムアウト オプションがサポートされていないため、NULL に設定する必要があります。
[in, optional] lpOverlapped
非同期操作に使用される重複する構造体への省略可能なポインター。
このパラメーターは、GetAddrInfoEx関数を呼び出す前に UNICODE または_UNICODE マクロがソースで定義されている場合にのみサポートされます。
Windows 8 および Windows Server 2012 では、lpCompletionRoutine パラメーターが指定されていない場合、OVERLAPPED 構造体の hEvent メンバーを手動リセット イベントに設定して、非同期呼び出しの完了時に呼び出す必要があります。 完了ルーチンが指定されている場合、 hEvent メンバーは NULL である必要があります。 hEvent で指定されたイベントが設定されている場合は、GetAddrInfoExOverlappedResult 関数を呼び出すことで操作の結果を取得できます。
Windows 8 および Windows Server 2012 では、 UNICODE または _UNICODE マクロが定義されていない場合は常に、このパラメーターは現在予約されており、 NULL に設定する必要があります。
Windows 7 および Windows Server 2008 R2 以前では、このパラメーターは現在予約されており、非同期操作はサポートされていないため NULL に設定する必要があります。
[in, optional] lpCompletionRoutine
非同期操作の正常な完了時に呼び出される関数への省略可能なポインター。
このパラメーターは、GetAddrInfoEx関数を呼び出す前に UNICODE または_UNICODE マクロがソースで定義されている場合にのみサポートされます。
このパラメーターを指定する場合は、次のシグネチャを持つ関数へのポインターである必要があります。
typedef
void
(CALLBACK * LPLOOKUPSERVICE_COMPLETION_ROUTINE)(
__in DWORD dwError,
__in DWORD dwBytes,
__in LPWSAOVERLAPPED lpOverlapped
);
非同期操作が完了すると、完了ルーチンが呼び出され、lpOverlapped パラメーターが GetAddrInfoEx に渡される lpOverlapped パラメーターの値に設定されます。 OVERLAPPED 構造体の Pointer メンバーは、元の呼び出しの ppResult パラメーターの値に設定されます。 Pointer メンバーが addrinfoex 構造体への NULL 以外のポインターを指している場合、呼び出し元は FreeAddrInfoEx を呼び出して addrinfoex 構造体を解放する必要があります。 完了ルーチンに渡される dwError パラメーターは、Winsock エラー コードに設定されます。 dwBytes パラメーターは将来使用するために予約されており、無視する必要があります。
Windows 8 および Windows Server 2012 では、 UNICODE または _UNICODE マクロが定義されていない場合は常に、このパラメーターは現在予約されており、 NULL に設定する必要があります。
Windows 7 および Windows Server 2008 R2 以前では、このパラメーターは現在予約されており、非同期操作はサポートされていないため NULL に設定する必要があります。
[out, optional] lpHandle
非同期操作にのみ使用される省略可能なポインター。
このパラメーターは、GetAddrInfoEx関数を呼び出す前に UNICODE または_UNICODE マクロがソースで定義されている場合にのみサポートされます。
Windows 8 および Windows Server 2012 では、 GetAddrInfoEx 関数が非同期的に完了する場合、このフィールドで返されるポインターを GetAddrInfoExCancel 関数と共に使用できます。 返されるハンドルは、完了ルーチンが呼び出されるか、イベントがトリガーされるか、このハンドルで GetAddrInfoExCancel 関数が呼び出されるまで GetAddrInfoEx が戻るときに有効です。
Windows 8 および Windows Server 2012 では、 UNICODE または _UNICODE マクロが定義されていない場合は常に、このパラメーターは現在予約されており、 NULL に設定する必要があります。
Windows 7 および Windows Server 2008 R2 以前では、このパラメーターは現在予約されており、非同期操作はサポートされていないため NULL に設定する必要があります。
戻り値
成功すると、 GetAddrInfoEx は NO_ERROR (0) を返します。 Failure は、Windows ソケット エラー コードに示されているように、0 以外の Windows ソケット エラー コードを返します。
GetAddrInfoEx 関数によって返される 0 以外のエラー コードのほとんどは、インターネット エンジニアリング タスク フォース (IETF) の推奨事項で説明されている一連のエラーにマップされます。 次の表に、これらのエラー コードとその WSA に相当するエラー コードを示します。 WSA エラー コードは、Winsock プログラマにとって使い慣れた包括的なエラー情報を提供するため、使用することをお勧めします。
エラー値 | WSA と同等 | 説明 |
---|---|---|
EAI_AGAIN | WSATRY_AGAIN | 名前解決で一時的なエラーが発生しました。 |
EAI_BADFLAGS | WSAEINVAL | 無効なパラメーターが指定されました。 予約済みパラメーターのいずれかが NULL でない場合、このエラーが返されます。 このエラーは、pHints パラメーターのai_flags メンバーに無効な値が指定された場合にも返されます。 |
EAI_FAIL | WSANO_RECOVERY | 名前解決で回復できないエラーが発生しました。 |
EAI_FAMILY | WSAEAFNOSUPPORT | pHints パラメーターのai_family メンバーはサポートされていません。 |
EAI_MEMORY | WSA_NOT_ENOUGH_MEMORY | メモリ割り当てエラーが発生しました。 |
EAI_NONAME | WSAHOST_NOT_FOUND | 指定されたパラメーターの名前が解決されないか、 pName パラメーターと pServiceName パラメーターが指定されていません。 |
EAI_SERVICE | WSATYPE_NOT_FOUND | pServiceName パラメーターは、pHints パラメーターの指定したai_socktype メンバーではサポートされていません。 |
EAI_SOCKTYPE | WSAESOCKTNOSUPPORT | pHints パラメーターのai_socktype メンバーはサポートされていません。 |
getAddrInfoEx 関数によって返される EAI コードに基づいてエラー メッセージを出力するには、gai_strerror関数を使用します。 gai_strerror関数は IETF の推奨事項に準拠するために提供されますが、スレッド セーフではありません。 そのため、 WSAGetLastError などの従来の Windows ソケット関数を使用することをお勧めします。
エラー コード | 意味 |
---|---|
操作を実行するためのメモリが不足していました。 | |
要求されたプロトコルと互換性のないアドレスが使用されました。 このエラーは、pHints パラメーターが指す addrinfoex 構造体のai_family メンバーがサポートされていない場合に返されます。 | |
無効な引数が指定されました。 このエラーは、pHints パラメーターが指す addrinfoex 構造体のai_flags メンバーに無効な値が指定された場合に返されます。 このエラーは、 dwNameSpace パラメーターがNS_PNRPNAMEまたはNS_PNRPCLOUDであり、ピアツーピア名サービスが動作していない場合にも返されます。 | |
このアドレス ファミリでは、指定したソケット タイプはサポートされていません。 このエラーは、pHints パラメーターが指す addrinfoex 構造体のai_socktype メンバーがサポートされていない場合に返されます。 | |
そのようなホストは不明です。 このエラーは、指定されたパラメーターの名前が解決されない場合、または pName パラメーターと pServiceName パラメーターが指定されていない場合に返されます。 | |
要求された名前は有効ですが、要求された種類のデータが見つかりませんでした。 | |
データベースの参照中に、修復できないエラーが発生しました。 このエラーは、名前解決で回復不可能なエラーが発生した場合に返されます。 | |
この関数を使用する前に 、WSAStartup 呼び出しが正常に行われる必要があります。 | |
そのようなサービスは不明です。 指定された名前空間にサービスが見つかりません。 このエラーは、dwNameSpace パラメーターで指定された名前空間に対して pName パラメーターまたは pServiceName パラメーターが見つからない場合、または dwNameSpace パラメーターで指定された名前空間がインストールされていない場合に返されます。 | |
これは、通常、ホスト名の解決中に発生する一時エラーであり、ローカル サーバーが、権限のあるサーバーから応答を受信しなかったことを示します。 このエラーは、名前解決で一時的なエラーが発生したときに返されます。 | |
指定したクラスが見つかりませんでした。 pServiceName パラメーターは、pHints パラメーターが指す addrinfoex 構造体の指定されたai_socktype メンバーではサポートされていません。 |
注釈
GetAddrInfoEx 関数は、ホスト名からアドレス、サービス名からポート番号へのプロトコルに依存しない変換を提供します。 GetAddrInfoEx 関数は、getaddrinfo 関数と GetAddrInfoW 関数の拡張バージョンです。 GetAddrInfoEx 関数を使用すると、名前空間プロバイダーを指定してクエリを解決できます。
GetAddrInfoEx 関数は、特定の名前空間プロバイダーが指定されていない限り、複数の名前空間プロバイダーから結果を集計して返します。 IPv6 および IPv4 プロトコルで使用する場合、名前解決には、ドメイン ネーム システム (DNS)、ローカル ホスト ファイル、電子メール プロバイダー ( NS_EMAIL 名前空間)、またはその他の名前付けメカニズムを使用できます。
UNICODE または_UNICODEが定義されている場合、 GetAddrInfoEx は 、この関数の Unicode バージョンである GetAddrInfoExW に定義されます。 文字列パラメーターは PWSTR データ型に定義され、 ADDRINFOEXW 構造体が使用されます。 Windows 8 および Windows Server 2012 では、 タイムアウト、 lpOverlapped、 lpCompletionRoutine、 および lpHandle パラメーターを使用して 、GetAddrInfoEx 関数を呼び出して非同期的に完了できます。
UNICODE または_UNICODEが定義されていない場合、 GetAddrInfoExEx は、この関数の ANSI バージョンである GetAddrInfoExA に定義されます。 文字列パラメーターは PCSTR データ型であり、 ADDRINFOEXA 構造体が使用されます。 timeout、lpOverlapped、lpCompletionRoutine、lpHandle の各パラメーターを NULL に設定する必要があります。
pName パラメーターまたは pServiceName パラメーターの一方または両方が NULL で終わる文字列を指している必要があります。 一般に、どちらも提供されます。
成功すると、 addrinfoex 構造体のリンクされたリストが ppResult パラメーターで返されます。 リストは、NULL ポインターが検出されるまで、返された各 addrinfoex 構造体のai_next メンバーに指定されたポインターに従って処理できます。 返される各 addrinfoex 構造体では、 ai_family、 ai_socktype、 および ai_protocol メンバーは 、 ソケット または WSASocket 関数呼び出しのそれぞれの引数に対応します。 また、返される各 addrinfoex 構造体のai_addr メンバーは、入力されたソケット アドレス構造体を指し、その長さは ai_addrlen メンバーで指定されます。
pName パラメーターがコンピューター名を指している場合は、ソース アドレスとして使用できるコンピューターのすべての永続的なアドレスが返されます。 Windows Vista 以降では、これらのアドレスには、MIB_UNICASTIPADDRESS_ROW構造体でSkipAsSource メンバーが false に設定されている GetUnicastIpAddressTable 関数または GetUnicastIpAddressEntry 関数によって返されるすべてのユニキャスト IP アドレスが含まれます。
pName パラメーターが "localhost" と等しい文字列を指している場合は、ローカル コンピューター上のすべてのループバック アドレスが返されます。
pName パラメーターに空の文字列が含まれている場合は、ローカル コンピューター上のすべての登録済みアドレスが返されます。
Windows Server 2003 以降では、 pName パラメーターが に等しい文字列を指している場合。localmachine", all registered addresses on the local computer are returned.
pName パラメーターがクラスター仮想サーバー名を参照している場合は、仮想サーバー アドレスのみが返されます。 Windows Vista 以降では、これらのアドレスには、MIB_UNICASTIPADDRESS_ROW構造体でSkipAsSource メンバーが true に設定されている GetUnicastIpAddressTable 関数または GetUnicastIpAddressEntry 関数によって返されるすべてのユニキャスト IP アドレスが含まれます。 クラスタリングの詳細については、「 Windows クラスタリング 」を参照してください。
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」を参照してください。
同様の修正プログラムは、Service Pack 2 (SP2) と Windows Server 2008 Service Pack 2 (SP2) を使用する Windows Vista でも使用できます。この修正プログラムは、IP アドレスに SkipAsSource 属性を設定するためのサポートを Netsh.exe に追加します。 この修正プログラムは、MIB_UNICASTIPADDRESS_ROW構造体の SkipAsSource メンバーが false に設定されている場合、IP アドレスが DNS に登録されるように動作も変更します。 SkipAsSource メンバーが true に設定されている場合、IP アドレスは DNS に登録されません。
GetAddrInfoEx 関数の呼び出し元は、pHints パラメーターが指す addrinfoex 構造体を介してサポートされるソケットの種類に関するヒントを提供できます。 pHints パラメーターを使用すると、関連付けられている addrinfoex 構造体に次の規則が適用されます。
- ai_family の値AF_UNSPECは、呼び出し元がAF_INETとAF_INET6アドレス ファミリのみを受け入れることを示します。 AF_UNSPECとPF_UNSPECは同じであることに注意してください。
- ai_socktype の値 0 は、呼び出し元が任意のソケット型を受け入れることを示します。
- ai_protocol の値 0 は、呼び出し元が任意のプロトコルを受け入れることを示します。
- ai_addrlen メンバーは 0 に設定する必要があります。
- ai_canonname メンバーは NULL に設定する必要があります。
- ai_addr メンバーは NULL に設定する必要があります。
- ai_next メンバーは NULL に設定する必要があります。
pHints パラメーターで提供される addrinfoex 構造体のその他の値は、特定の要件を示します。 たとえば、呼び出し元が IPv4 のみを処理し、IPv6 を処理しない場合は、 ai_family メンバーを AF_INET に設定する必要があります。 別の例として、呼び出し元が TCP のみを処理し、UDP を処理しない場合は、 ai_socktype メンバーを SOCK_STREAM に設定する必要があります。
pHints パラメーターが NULL ポインターの場合、GetAddrInfoEx 関数は、pHints の addrinfoex 構造体が AF_UNSPEC に設定されたai_family メンバーで初期化され、他のすべてのメンバーが NULL またはゼロに設定されたかのように処理します。
GetAddrInfoEx がサービスから呼び出されると、操作がサービスを呼び出すユーザー プロセスの結果である場合、サービスはユーザーを偽装する必要があります。 これは、セキュリティを適切に適用できるようにするためです。
GetAddrInfoEx 関数を使用すると、IP アドレスのテキスト文字列表現を、IP アドレスとその他の情報の sockaddr 構造体を含む addrinfoex 構造体に変換できます。 この方法で使用するには、pName パラメーターが指す文字列に IP アドレスのテキスト表現が含まれている必要があります。また、pHints パラメーターが指す addrinfoex 構造体には、ai_flags メンバーに AI_NUMERICHOST フラグが設定されている必要があります。 pName パラメーターが指す文字列には、IPv4 アドレスまたは IPv6 アドレスのテキスト表現が含まれる場合があります。 テキスト IP アドレスは、ppResult パラメーターによって指される addrinfoex 構造体に変換されます。 返される addrinfoex 構造体には、IP アドレスの sockaddr 構造体と、IP アドレスに関する追加情報が含まれています。
同じ名前空間のローカル コンピューターに複数の名前空間プロバイダーをインストールできます。 たとえば、基本 Windows TCP/IP ネットワーク ソフトウェアは、NS_DNS名前空間に登録します。 Microsoft Forefront Threat Management Gateway (TMG) と古い Microsoft Internet Security and Acceleration (ISA) サーバーには、NS_DNS名前空間にも登録するファイアウォール クライアント ソフトウェアが含まれています。 dwNameSpace パラメーターが値 (たとえば、NS_DNS) に設定され、lpNspId パラメーターが NULL の場合、GetAddrInfoEx 関数によって返される結果は、重複する結果が排除された、指定された名前空間に登録されているすべての名前空間プロバイダーからのマージされた結果です。 1 つの名前空間プロバイダーのみを照会する場合は、 lpNspId パラメーターを特定の名前空間プロバイダーの GUID に設定する必要があります。
pNameSpace パラメーターが NS_ALL に設定されている場合、すべての名前空間プロバイダーに対してクエリを実行した結果がマージされて返されます。 この場合、複数の名前空間プロバイダーが同じ情報を返す場合、 ppResult パラメーターによって指される結果に重複する応答が返されることがあります。
Windows 8 および Windows Server 2012 では、 GetAddrInfoEx 関数が非同期的に完了する場合、 lpHandle パラメーターで返されるポインターを GetAddrInfoExCancel 関数と共に使用できます。 返されるハンドルは、 完了 ルーチンが呼び出されるか、イベントがトリガーされるか、このハンドルで GetAddrInfoExCancel 関数が呼び出されるまで GetAddrInfoEx が 返されるときに有効です。
動的割り当てからのアドレス情報の解放
ppResult パラメーターが指す GetAddrInfoEx 関数によって返されるすべての情報は、addrinfoex 構造体、ソケット アドレス構造体、addrinfoex構造体が指す正規ホスト名文字列を含め、動的に割り当てられます。 この関数の正常な呼び出しによって割り当てられたメモリは、 FreeAddrInfoEx の後続の呼び出しで解放する必要があります。コード例
次の例では、 GetAddrInfoEx 関数の使用方法を示します。#ifndef UNICODE
#define UNICODE
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <objbase.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
// Need to link with Ole32.lib to print GUID
#pragma comment(lib, "ole32.lib")
int __cdecl wmain(int argc, wchar_t ** argv)
{
//-----------------------------------------
// Declare and initialize variables
WSADATA wsaData;
int iResult;
DWORD dwRetval;
int i = 1;
DWORD dwNamespace = NS_ALL;
LPGUID lpNspid = NULL;
ADDRINFOEX *result = NULL;
ADDRINFOEX *ptr = NULL;
ADDRINFOEX hints;
// LPSOCKADDR sockaddr_ip;
struct sockaddr_in *sockaddr_ipv4;
struct sockaddr_in6 *sockaddr_ipv6;
// DWORD ipbufferlength = 46;
wchar_t ipstringbuffer[46];
// variables needed to print namespace provider GUID
int iRet = 0;
WCHAR GuidString[40] = { 0 };
// Validate the parameters
if (argc != 4) {
wprintf(L"usage: %ws <hostname> <servicename> <namespace>\n", argv[0]);
wprintf(L"getaddrinfoex provides protocol-independent translation\n");
wprintf(L" from a host name to an IP address\n");
wprintf(L"%ws example usage\n", argv[0]);
wprintf(L" %ws www.contoso.com 0 12\n", argv[0]);
wprintf(L" looks up the www.contoso.com in the NS_DNS namespace\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;
dwNamespace = (DWORD) _wtoi(argv[3]);
wprintf(L"Calling GetAddrInfoEx with following parameters:\n");
wprintf(L"\tName = %ws\n", argv[1]);
wprintf(L"\tServiceName (or port) = %ws\n", argv[2]);
wprintf(L"\tNamespace = %s (", argv[3]);
switch (dwNamespace) {
case NS_ALL:
wprintf(L"(NS_ALL)\n");
break;
case NS_DNS:
wprintf(L"(NS_DNS)\n");
break;
case NS_NETBT:
wprintf(L"NS_NETBT");
break;
case NS_WINS:
wprintf(L"NS_WINS");
break;
case NS_NLA:
wprintf(L"NS_NLA");
break;
case NS_BTH:
wprintf(L"NS_BTH");
break;
case NS_NTDS:
wprintf(L"NS_NTDS");
break;
case NS_EMAIL:
wprintf(L"NS_EMAIL");
break;
case NS_PNRPNAME:
wprintf(L"NS_PNRPNAME");
break;
case NS_PNRPCLOUD:
wprintf(L"NS_PNRPCLOUD");
break;
default:
wprintf(L"Other");
break;
}
wprintf(L")\n\n");
//--------------------------------
// Call getaddrinfoex(). If the call succeeds,
// the result variable will hold a linked list
// of addrinfo structures containing response
// information
dwRetval =
GetAddrInfoEx(argv[1], argv[2], dwNamespace, lpNspid, &hints, &result,
NULL, NULL, NULL, NULL);
if (dwRetval != 0) {
wprintf(L"GetAddrInfoEx failed with error: %d\n", dwRetval);
WSACleanup();
return 1;
}
wprintf(L"GetAddrInfoEx returned success\n");
// Retrieve each address and print out the hex bytes
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
wprintf(L"GetAddrInfoEx 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");
// the InetNtop function is available on Windows Vista and later
sockaddr_ipv4 = (struct sockaddr_in *) ptr->ai_addr;
wprintf(L"\tIPv4 address %ws\n",
InetNtop(AF_INET, &sockaddr_ipv4->sin_addr, ipstringbuffer,
46));
// We could also use the WSAAddressToString function
// 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;
wprintf(L"\tIPv6 address %ws\n",
InetNtop(AF_INET6, &sockaddr_ipv6->sin6_addr,
ipstringbuffer, 46));
// We could also use WSAAddressToString which also returns the scope ID
// 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);
if (ptr->ai_blob == NULL)
wprintf(L"\tBlob: (null)\n");
else
wprintf(L"\tLength of the blob: %u\n",
(DWORD) ptr->ai_bloblen);
if (ptr->ai_provider == NULL)
wprintf(L"\tNamespace provider GUID: (null)\n");
else {
iRet =
StringFromGUID2(*(ptr->ai_provider), (LPOLESTR) & GuidString,
39);
// For c rather than C++ source code, the above line needs to be
// iRet = StringFromGUID2(&ptr.ai_provider, (LPOLESTR) &GuidString, 39);
if (iRet == 0)
wprintf(L"StringFromGUID2 failed\n");
else {
wprintf(L"\tNamespace provider: %ws\n", GuidString);
}
}
}
FreeAddrInfoEx(result);
WSACleanup();
return 0;
}
次の例では、 GetAddrInfoEx 関数を非同期で使用して、名前を IP アドレスに解決する方法を示します。
//
// This sample demonstrates how to use asynchronous GetAddrInfoEx to
// resolve a name to an IP address.
//
// ResolveName <QueryName>
//
#ifndef UNICODE
#define UNICODE
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
#define MAX_ADDRESS_STRING_LENGTH 64
//
// Asynchronous query context structure.
//
typedef struct _QueryContext
{
OVERLAPPED QueryOverlapped;
PADDRINFOEX QueryResults;
HANDLE CompleteEvent;
}QUERY_CONTEXT, *PQUERY_CONTEXT;
VOID
WINAPI
QueryCompleteCallback(
_In_ DWORD Error,
_In_ DWORD Bytes,
_In_ LPOVERLAPPED Overlapped
);
int
__cdecl
wmain(
_In_ int Argc, PWCHAR Argv[]
)
{
INT Error = ERROR_SUCCESS;
WSADATA wsaData;
BOOL IsWSAStartupCalled = FALSE;
ADDRINFOEX Hints;
QUERY_CONTEXT QueryContext;
HANDLE CancelHandle = NULL;
DWORD QueryTimeout = 5 * 1000; // 5 seconds
ZeroMemory(&QueryContext, sizeof(QueryContext));
//
// Validate the parameters
//
if (Argc != 2)
{
wprintf(L"Usage: ResolveName <QueryName>\n");
goto exit;
}
//
// All Winsock functions require WSAStartup() to be called first
//
Error = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (Error != 0)
{
wprintf(L"WSAStartup failed with %d\n", Error);
goto exit;
}
IsWSAStartupCalled = TRUE;
ZeroMemory(&Hints, sizeof(Hints));
Hints.ai_family = AF_UNSPEC;
//
// Note that this is a simple sample that waits/cancels a single
// asynchronous query. The reader may extend this to support
// multiple asynchronous queries.
//
QueryContext.CompleteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (QueryContext.CompleteEvent == NULL)
{
Error = GetLastError();
wprintf(L"Failed to create completion event: Error %d\n", Error);
goto exit;
}
//
// Initiate asynchronous GetAddrInfoExW.
//
// Note GetAddrInfoEx can also be invoked asynchronously using an event
// in the overlapped object (Just set hEvent in the Overlapped object
// and set NULL as completion callback.)
//
// This sample uses the completion callback method.
//
Error = GetAddrInfoExW(Argv[1],
NULL,
NS_DNS,
NULL,
&Hints,
&QueryContext.QueryResults,
NULL,
&QueryContext.QueryOverlapped,
QueryCompleteCallback,
&CancelHandle);
//
// If GetAddrInfoExW() returns WSA_IO_PENDING, GetAddrInfoExW will invoke
// the completion routine. If GetAddrInfoExW returned anything else we must
// invoke the completion directly.
//
if (Error != WSA_IO_PENDING)
{
QueryCompleteCallback(Error, 0, &QueryContext.QueryOverlapped);
goto exit;
}
//
// Wait for query completion for 5 seconds and cancel the query if it has
// not yet completed.
//
if (WaitForSingleObject(QueryContext.CompleteEvent,
QueryTimeout) == WAIT_TIMEOUT )
{
//
// Cancel the query: Note that the GetAddrInfoExCancelcancel call does
// not block, so we must wait for the completion routine to be invoked.
// If we fail to wait, WSACleanup() could be called while an
// asynchronous query is still in progress, possibly causing a crash.
//
wprintf(L"The query took longer than %d seconds to complete; "
L"cancelling the query...\n", QueryTimeout/1000);
GetAddrInfoExCancel(&CancelHandle);
WaitForSingleObject(QueryContext.CompleteEvent,
INFINITE);
}
exit:
if (IsWSAStartupCalled)
{
WSACleanup();
}
if (QueryContext.CompleteEvent)
{
CloseHandle(QueryContext.CompleteEvent);
}
return Error;
}
//
// Callback function called by Winsock as part of asynchronous query complete
//
VOID
WINAPI
QueryCompleteCallback(
_In_ DWORD Error,
_In_ DWORD Bytes,
_In_ LPOVERLAPPED Overlapped
)
{
PQUERY_CONTEXT QueryContext = NULL;
PADDRINFOEX QueryResults = NULL;
WCHAR AddrString[MAX_ADDRESS_STRING_LENGTH];
DWORD AddressStringLength;
UNREFERENCED_PARAMETER(Bytes);
QueryContext = CONTAINING_RECORD(Overlapped,
QUERY_CONTEXT,
QueryOverlapped);
if (Error != ERROR_SUCCESS)
{
wprintf(L"ResolveName failed with %d\n", Error);
goto exit;
}
wprintf(L"ResolveName succeeded. Query Results:\n");
QueryResults = QueryContext->QueryResults;
while(QueryResults)
{
AddressStringLength = MAX_ADDRESS_STRING_LENGTH;
WSAAddressToString(QueryResults->ai_addr,
(DWORD)QueryResults->ai_addrlen,
NULL,
AddrString,
&AddressStringLength);
wprintf(L"Ip Address: %s\n", AddrString);
QueryResults = QueryResults->ai_next;
}
exit:
if (QueryContext->QueryResults)
{
FreeAddrInfoEx(QueryContext->QueryResults);
}
//
// Notify caller that the query completed
//
SetEvent(QueryContext->CompleteEvent);
return;
}
国際化されたドメイン名
インターネット ホスト名は、通常、非常に制限された文字セットで構成されます。- 英文字の大文字と小文字の ASCII 文字。
- 0 から 9 の数字。
- ASCII ハイフン文字。
インターネットの増加に伴い、ASCII 文字セットで表されない他の言語のインターネット ホスト名を識別する必要性が高まっています。 このニーズを容易にし、ASCII 以外の文字 (Unicode) を特殊な ASCII 文字列として表現できるようにする識別子は、国際化ドメイン名 (IDN) と呼ばれます。 アプリケーションのドメイン名の国際化 (IDNA) と呼ばれるメカニズムは、IDN を標準的な方法で処理するために使用されます。 IDN と IDNA の仕様については、インターネット エンジニアリング タスク フォース (IETF) によって公開されている RFC 3490、 RTF 5890、 RFC 6365 に記載されています。
Windows 8 および Windows Server 2012 では、 GetAddrInfoEx 関数は、 pName パラメーターで渡された名前に適用される国際化ドメイン名 (IDN) 解析のサポートを提供します。 Winsock は、Punycode/IDN エンコードと変換を実行します。 この動作は、以下で説明する AI_DISABLE_IDN_ENCODING フラグを使用して無効にすることができます。
Windows 7 および Windows Server 2008 R2 以前では、 GetAddrInfoEx 関数は現在、 pName パラメーターで渡された名前に適用される IDN 解析のサポートを提供していません。 GetAddrInfoEx 関数のワイド文字バージョンでは、RFC 3490 に従って IDN Punycode 形式を変換するために Punycode を使用しません。 DNS に対してクエリを実行する場合の GetAddrInfoEx 関数のワイド文字バージョンは、エンタープライズ環境で Microsoft DNS サーバーによって使用される形式である UNICODE 名を 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 バージョンが使用されている場合 (UNICODE と_UNICODEが定義されていない場合) に pName パラメーターで GetAddrInfoEx 関数に渡すことができます。 この関数のワイド文字バージョン (UNICODE または_UNICODEが定義されている場合) にこの IDN 名を GetAddrInfoEx 関数に渡すには、 MultiByteToWideChar 関数を使用して CHAR 文字列を WCHAR 文字列に変換できます。
hints パラメーターでのai_flagsの使用
hints パラメーターで提供される省略可能な addrinfoex 構造体の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 フラグを設定すると、呼び出し元は、バインド関数の呼び出しで返されたソケット アドレス構造を使用することを示します。 AI_PASSIVE フラグが設定され、pName が NULL ポインターである場合、ソケット・アドレス構造の IP アドレス部分は、IPv4 アドレスの場合はINADDR_ANY、IPv6 アドレスの場合はIN6ADDR_ANY_INITに設定されます。
AI_PASSIVE フラグが設定されていない場合、返されるソケット アドレス構造体は、接続指向プロトコルの接続関数を呼び出す準備が整っているか、コネクションレス プロトコルの接続、sendto、または send 関数を呼び出す準備ができています。 この場合、 pName パラメーターが NULL ポインターの場合、ソケット・アドレス構造の IP アドレス部分はループバック・アドレスに設定されます。 |
AI_CANONNAME |
AI_CANONNAMEもAI_NUMERICHOSTも使用しない場合、GetAddrInfoEx 関数は解決を試みます。 リテラル文字列が渡された場合 、GetAddrInfoEx は文字列の変換を試み、ホスト名が渡された場合 、GetAddrInfoEx 関数はアドレスまたは複数のアドレスに名前を解決しようとします。
AI_CANONNAME ビットが設定されている場合、pName パラメーターを NULL にすることはできません。 それ以外の場合、 GetAddrInfoEx 関数は WSANO_RECOVERYで失敗します。 AI_CANONNAME ビットが設定され、GetAddrInfoEx 関数が成功を返すと、ppResult パラメーターのai_canonname メンバーは、指定されたノードの正規名を含む NULL で終わる文字列を指します。 メモGetAddrInfoEx 関数は、AI_CANONNAME フラグが設定されている場合に成功を返すことができますが、関連付けられている addrinfo 構造体のai_canonname メンバーは NULL です。 したがって、AI_CANONNAME フラグの推奨される使用には、関連付けられた addrinfoex 構造体のai_canonname メンバーが NULL であるかどうかをテストすることが含まれます。
|
AI_NUMERICHOST | AI_NUMERICHOST ビットが設定されている場合、pName パラメーターには NULL 以外の数値ホスト アドレス文字列が含まれている必要があります。それ以外の場合は、EAI_NONAME エラーが返されます。 このフラグは、名前解決サービスが呼び出されないようにします。 |
AI_NUMERICSERV |
AI_NUMERICSERV ビットが設定されている場合、pServiceName パラメーターには NULL 以外の数値ポート番号が含まれている必要があります。それ以外の場合は、EAI_NONAME エラーが返されます。 このフラグは、名前解決サービスが呼び出されないようにします。
AI_NUMERICSERV フラグは、Windows Vista 以降の Windows SDK で定義されています。 AI_NUMERICSERV フラグは、Microsoft プロバイダーではサポートされていません。 |
AI_ALL |
AI_ALL ビットが設定されている場合は、AI_V4MAPPEDを持つ IPv6 アドレスと IPv4 アドレスに対して要求が行われます。
AI_ALL フラグは、Windows Vista 用 Windows SDK 以降で定義されています。 AI_ALL フラグは、Windows Vista 以降でサポートされています。 |
AI_ADDRCONFIG |
AI_ADDRCONFIG ビットが設定されている場合、グローバル アドレスが構成されている場合にのみ GetAddrInfoEx が解決されます。 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が設定されている場合は、pName パラメーターに名前を指定しないでください。 NS_EMAIL名前空間プロバイダーは、パブリケーションの優先名を返します。
AI_RETURN_PREFERRED_NAMES フラグは、Windows Vista 用 Windows SDK 以降で定義されています。 AI_RETURN_PREFERRED_NAMES フラグは Windows Vista 以降でサポートされており、NS_EMAIL名前空間にのみ適用されます。 |
AI_FQDN |
AI_FQDNが設定され、フラット名 (単一ラベル) が指定されている場合、GetAddrInfoEx は名前が最終的に解決された完全修飾ドメイン名を返します。 完全修飾ドメイン名は、関連付けられた addrinfoex 構造体の ai_canonname メンバーで返されます。 これは、DNS に登録されている正規名を返す AI_CANONNAME ビット フラグとは異なります。これは、フラット名が解決された完全修飾ドメイン名とは異なる場合があります。
AI_FQDN ビットが設定されている場合、pName パラメーターを NULL にすることはできません。 それ以外の場合、 GetAddrInfoEx 関数は WSANO_RECOVERYで失敗します。 Windows 8 および Windows Server 2012 では、 AI_FQDN ビットと AI_CANONNAME ビットの両方を設定できます。 getAddrInfoEx 関数がAI_FQDNビットとAI_CANONNAMEビットの両方で呼び出された場合、ppResult パラメーターは addrinfoex 構造体ではなく addrinfoex2 構造体へのポインターを返します。 Windows 7 および Windows Server 2008 R2 では、 AI_FQDN ビットと AI_CANONNAME ビットの 1 つだけを設定できます。 両方のフラグがEAI_BADFLAGSと共に存在する場合、GetAddrInfoEx 関数は失敗します。 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が設定されている場合、GetAddrInfoEx 関数によって呼び出される名前解決関数で Punycode を使用した国際ドメイン名の自動エンコードが無効になります。
Windows 8: AI_DISABLE_IDN_ENCODING フラグは、Windows 8 以降の Windows SDK で定義されています。 AI_DISABLE_IDN_ENCODING フラグは、Windows 8 以降でサポートされています。 |
注意
ws2tcpip.h ヘッダーは、Unicode プリプロセッサ定数の定義に基づいて、この関数の ANSI または Unicode バージョンを自動的に選択するエイリアスとして GetAddrInfoEx を定義します。 encoding-neutral エイリアスの使用を encoding-neutral ではないコードと混在すると、コンパイル エラーまたはランタイム エラーが発生する不一致が発生する可能性があります。 詳細については、「 関数プロトタイプの規則」を参照してください。
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows XP [デスクトップ アプリ | UWP アプリ] |
サポートされている最小のサーバー | Windows Server 2008 [デスクトップ アプリ | UWP アプリ] |
対象プラットフォーム | Windows |
ヘッダー | ws2tcpip.h |
Library | Ws2_32.lib |
[DLL] | Ws2_32.dll |