GetAddrInfoExW
関数シグネチャ
// WS2_32.dll (Unicode / -W)
#include <windows.h>
INT GetAddrInfoExW(
LPCWSTR pName, // optional
LPCWSTR pServiceName, // optional
DWORD dwNameSpace,
GUID* lpNspId, // optional
const ADDRINFOEXW* hints, // optional
ADDRINFOEXW** ppResult,
TIMEVAL* timeout, // optional
OVERLAPPED* lpOverlapped, // optional
LPLOOKUPSERVICE_COMPLETION_ROUTINE lpCompletionRoutine, // optional
HANDLE* lpHandle // optional
);パラメーター
| 名前 | 型 | 方向 | 説明 | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| pName | LPCWSTR | inoptional | ホスト(ノード)名または数値ホストアドレス文字列を含む NULL 終端文字列へのポインター。インターネットプロトコルの場合、数値ホストアドレス文字列はドット区切り10進表記の IPv4 アドレス、または IPv6 の16進アドレスです。 | ||||||||||||||||||||||
| pServiceName | LPCWSTR | inoptional | サービス名またはポート番号を文字列として表したものを含む、省略可能な NULL 終端文字列へのポインター。 サービス名はポート番号の文字列エイリアスです。たとえば “http” はポート80のエイリアスであり、HTTP プロトコルで Web サーバーが使用する既定のポートとして Internet Engineering Task Force (IETF) によって定義されています。ポート番号を指定しない場合に pServiceName パラメーターに指定できる値は、次のファイルに一覧があります。
| ||||||||||||||||||||||
| dwNameSpace | DWORD | in | どのネームスペースプロバイダーに問い合わせるかを決定する、省略可能なネームスペース識別子。特定のネームスペース識別子を渡すと、指定したネームスペースをサポートするネームスペースプロバイダーのみが問い合わせ対象となります。NS_ALL を指定すると、インストール済みで有効なすべてのネームスペースプロバイダーが問い合わせ対象になります。 dwNameSpace パラメーターのオプションは Winsock2.h インクルードファイルに一覧があります。Windows Vista 以降ではいくつかのネームスペースプロバイダーが追加されています。その他のネームスペースプロバイダーもインストール可能なため、以下に挙げる値は一般的に利用可能なものに過ぎません。これ以外にも多数の値が存在し得ます。
| ||||||||||||||||||||||
| lpNspId | GUID* | inoptional | NS_DNS のような単一のネームスペースに複数のネームスペースプロバイダーが登録されている場合に、問い合わせる特定のネームスペースプロバイダーの GUID を指定する省略可能なポインター。特定のネームスペースプロバイダーの GUID を渡すと、指定したネームスペースプロバイダーのみが問い合わせ対象になります。ネームスペースプロバイダーの GUID を取得するには、WSAEnumNameSpaceProviders 関数を呼び出します。 | ||||||||||||||||||||||
| hints | ADDRINFOEXW* | inoptional | 呼び出し元がサポートするソケットの種類に関するヒントを提供する addrinfoex 構造体へのポインター。 pHints パラメーターが指す addrinfoex 構造体の ai_addrlen、ai_canonname、ai_addr、ai_next の各メンバーは、ゼロまたは NULL でなければなりません。そうでない場合、GetAddrInfoEx 関数は WSANO_RECOVERY で失敗します。 詳細は「解説」を参照してください。 | ||||||||||||||||||||||
| ppResult | ADDRINFOEXW** | out | ホストに関する応答情報を含む、1 つ以上の addrinfoex 構造体の連結リストへのポインター。 | ||||||||||||||||||||||
| timeout | TIMEVAL* | inoptional | 呼び出しを中止するまでにネームスペースプロバイダーからの応答を待機する時間をミリ秒単位で示す、省略可能なパラメーター。 このパラメーターは、GetAddrInfoEx 関数を呼び出す前にソース内で UNICODE または _UNICODE マクロが定義されている場合にのみサポートされます。それ以外の場合、timeout オプションはサポートされないため、このパラメーターは現在予約されており、NULL に設定する必要があります。 | ||||||||||||||||||||||
| lpOverlapped | OVERLAPPED* | inoptional | 非同期操作に使用される overlapped 構造体への省略可能なポインター。 このパラメーターは、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 に設定する必要があります。 | ||||||||||||||||||||||
| lpCompletionRoutine | LPLOOKUPSERVICE_COMPLETION_ROUTINE | inoptional | 非同期操作が正常に完了したときに呼び出される関数への省略可能なポインター。 このパラメーターは、GetAddrInfoEx 関数を呼び出す前にソース内で UNICODE または _UNICODE マクロが定義されている場合にのみサポートされます。 このパラメーターを指定する場合は、次のシグネチャを持つ関数へのポインターでなければなりません。
非同期操作が完了すると、完了ルーチンが呼び出され、lpOverlapped パラメーターには GetAddrInfoEx に渡された lpOverlapped パラメーターの値が設定されます。OVERLAPPED 構造体の Pointer メンバーには、元の呼び出しの ppResult パラメーターの値が設定されます。Pointer メンバーが addrinfoex 構造体への非 NULL ポインターを指している場合、その addrinfoex 構造体を解放するために FreeAddrInfoEx を呼び出すのは呼び出し元の責任です。完了ルーチンに渡される dwError パラメーターには Winsock エラーコードが設定されます。dwBytes パラメーターは将来の使用のために予約されており、無視する必要があります。 Windows 8 および Windows Server 2012 で UNICODE または _UNICODE マクロが定義されていない場合、このパラメーターは現在予約されており、NULL に設定する必要があります。 Windows 7 および Windows Server 2008 R2 以前では、非同期操作がサポートされないため、このパラメーターは現在予約されており、NULL に設定する必要があります。 | ||||||||||||||||||||||
| lpHandle | HANDLE* | outoptional | 非同期操作でのみ使用される省略可能なポインター。 このパラメーターは、GetAddrInfoEx 関数を呼び出す前にソース内で UNICODE または _UNICODE マクロが定義されている場合にのみサポートされます。 Windows 8 および Windows Server 2012 では、GetAddrInfoEx 関数が非同期で完了する場合、このフィールドで返されるポインターを GetAddrInfoExCancel 関数で使用できます。返されるハンドルは、GetAddrInfoEx が戻ってから、完了ルーチンが呼び出されるか、イベントがトリガーされるか、またはこのハンドルを指定して GetAddrInfoExCancel 関数が呼び出されるまでの間、有効です。 Windows 8 および Windows Server 2012 で UNICODE または _UNICODE マクロが定義されていない場合、このパラメーターは現在予約されており、NULL に設定する必要があります。 Windows 7 および Windows Server 2008 R2 以前では、非同期操作がサポートされないため、このパラメーターは現在予約されており、NULL に設定する必要があります。 |
戻り値の型: INT
公式ドキュメント
プロトコルに依存しない名前解決を行います。要求を処理すべきネームスペースプロバイダーを限定するための追加パラメーターを備えています。(Unicode)
戻り値
成功した場合、GetAddrInfoEx は NO_ERROR (0) を返します。失敗した場合は、 Windows Sockets Error Codes に記載されている 0 以外の Windows ソケットエラーコードを返します。
GetAddrInfoEx 関数が返す 0 以外のエラーコードのほとんどは、Internet Engineering Task Force (IETF) の推奨で規定されたエラーの集合に対応します。次の表に、これらのエラーコードとその WSA 相当値を示します。Winsock プログラマーにとってなじみがあり包括的なエラー情報が得られるため、WSA エラーコードの使用をお勧めします。
| Error value | WSA equivalent | Description |
|---|---|---|
| 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 Sockets 関数の使用をお勧めします。
| Error code | Meaning |
|---|---|
| 操作を実行するためのメモリが不足していました。 | |
| 要求されたプロトコルと互換性のないアドレスが使用されました。このエラーは、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 メンバーに対してサポートされていません。 |
解説(Remarks)
GetAddrInfoEx 関数は、ホスト名からアドレスへの変換、およびサービス名からポート番号への変換を、プロトコルに依存せずに行います。GetAddrInfoEx 関数は、getaddrinfo 関数および GetAddrInfoW 関数の拡張版です。GetAddrInfoEx 関数では、クエリを解決するネームスペースプロバイダーを指定できます。
GetAddrInfoEx 関数は、特定のネームスペースプロバイダーが指定されていない限り、複数のネームスペースプロバイダーからの結果を集約して返します。IPv6 および IPv4 プロトコルで使用する場合、名前解決はドメインネームシステム (DNS)、ローカルの hosts ファイル、メールプロバイダー (NS_EMAIL ネームスペース)、またはその他の名前付けメカニズムによって行われます。
UNICODE または _UNICODE が定義されている場合、GetAddrInfoEx はこの関数の Unicode 版である GetAddrInfoExW として定義されます。文字列パラメーターは PWSTR データ型として定義され、ADDRINFOEXW 構造体が使用されます。Windows 8 および Windows Server 2012 では、timeout、lpOverlapped、lpCompletionRoutine、lpHandle の各パラメーターを使用して GetAddrInfoEx 関数を呼び出すことで、非同期に完了させることができます。
UNICODE または _UNICODE が定義されていない場合、GetAddrInfoEx はこの関数の ANSI 版である GetAddrInfoExA として定義されます。文字列パラメーターは PCSTR データ型となり、ADDRINFOEXA 構造体が使用されます。timeout、lpOverlapped、lpCompletionRoutine、lpHandle の各パラメーターは NULL に設定する必要があります。
pName または pServiceName パラメーターのうち、少なくとも一方は NULL 終端文字列を指している必要があります。一般には両方が指定されます。
成功すると、addrinfoex 構造体の連結リストが ppResult パラメーターで返されます。このリストは、返された各 addrinfoex 構造体の ai_next メンバーで提供されるポインターを NULL ポインターに到達するまでたどることで処理できます。返された各 addrinfoex 構造体では、ai_family、ai_socktype、ai_protocol の各メンバーが、 socket 関数または 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" に等しい文字列を指している場合、ローカルコンピューター上に登録されているすべてのアドレスが返されます。
pName パラメーターがクラスター仮想サーバー名を参照している場合、仮想サーバーのアドレスのみが返されます。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 に登録されないように動作が変更されます。詳細については、Knowledge Base (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 に登録されないように動作が変更されます。
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 構造体が ai_family メンバーを AF_UNSPEC に設定し、その他のすべてのメンバーを NULL または 0 に設定して初期化されたものとして扱います。
GetAddrInfoEx がサービスから呼び出され、その操作がユーザープロセスによるサービス呼び出しの結果である場合、サービスはユーザーになりすます (impersonate) 必要があります。これは、セキュリティを適切に適用するためです。
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) Server には、同じく NS_DNS ネームスペースに登録される Firewall Client ソフトウェアが含まれます。dwNameSpace パラメーターに値 (たとえば NS_DNS) が設定され、lpNspId パラメーターが NULL の場合、GetAddrInfoEx 関数が返す結果は、指定されたネームスペースに登録されているすべてのネームスペースプロバイダーからの結果を統合し、重複を排除したものになります。単一のネームスペースプロバイダーのみを問い合わせる場合は、lpNspId パラメーターをその特定のネームスペースプロバイダーの GUID に設定する必要があります。
pNameSpace パラメーターが NS_ALL に設定されている場合、すべてのネームスペースプロバイダーへの問い合わせ結果が統合されて返されます。この場合、複数のネームスペースプロバイダーが同じ情報を返すと、ppResult パラメーターが指す結果に重複した応答が返されることがあります。
Windows 8 および Windows Server 2012 では、GetAddrInfoEx 関数が非同期で完了する場合、lpHandle パラメーターで返されるポインターを GetAddrInfoExCancel 関数で使用できます。返されるハンドルは、GetAddrInfoEx が戻ってから、完了ルーチンが呼び出されるか、イベントがトリガーされるか、またはこのハンドルを指定して GetAddrInfoExCancel 関数が呼び出されるまでの間、有効です。
動的に割り当てられたアドレス情報の解放
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;
}
次の例は、名前を IP アドレスに解決するために GetAddrInfoEx 関数を非同期で使用する方法を示しています。
//
// 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) と呼ばれます。IDN を標準的な方法で扱うために、Internationalizing Domain Names in Applications (IDNA) と呼ばれるメカニズムが使用されます。IDN および IDNA の仕様は、Internet Engineering Task Force (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 を使用しません。GetAddrInfoEx 関数のワイド文字版は、DNS を照会する際に Unicode 名を UTF-8 形式 (エンタープライズ環境の Microsoft DNS サーバーで使用される形式) でエンコードします。
Windows Vista 以降では、いくつかの関数が、IDN 内の Unicode ラベルとその ASCII 相当形式との間の変換をサポートします。各 Unicode ラベルの結果表現は ASCII 文字のみを含み、Unicode ラベルに非 ASCII 文字が含まれていた場合は xn-- プレフィックスで始まります。この理由は、一部の DNS ツールやサーバーが ASCII 文字のみをサポートするため (RFC 3490 を参照)、インターネット上の既存の DNS サーバーをサポートするためです。
IdnToAscii 関数は、RFC 3490 で定義された標準アルゴリズムを使用し、Punycode によって IDN を元の Unicode 文字列の ASCII 表現に変換します。IdnToUnicode 関数は、IDN の ASCII 形式を通常の Unicode UTF-16 エンコード構文に変換します。詳細および関連するドラフト標準へのリンクについては、Handling Internationalized Domain Names (IDNs) を参照してください。
IdnToAscii 関数を使用して IDN 名を ASCII 形式に変換し、この関数の ANSI 版を使用する場合 (UNICODE および _UNICODE が定義されていない場合) に、その ASCII 形式を GetAddrInfoEx 関数の pName パラメーターに渡すことができます。この関数のワイド文字版を使用する場合 (UNICODE または _UNICODE が定義されている場合) にこの IDN 名を GetAddrInfoEx 関数に渡すには、MultiByteToWideChar 関数を使用して CHAR 文字列を WCHAR 文字列に変換できます。
hints パラメーターでの ai_flags の使用
hints パラメーターで提供される省略可能な addrinfoex 構造体の ai_flags メンバー内のフラグは、関数の動作を変更します。
これらのフラグビットは、Windows 7 用の Microsoft Windows Software Development Kit (SDK) では Ws2def.h ヘッダーファイルで定義されています。Windows Server 2008 および Windows Vista 用の Windows SDK では、これらのフラグビットは Ws2tcpip.h ヘッダーファイルで定義されています。Windows Server 2003 および Windows XP 用の Platform Software Development Kit (SDK) では、これらのフラグビットは Ws2tcpip.h ヘッダーファイルで定義されています。
フラグビットには、次の値の組み合わせを指定できます。
| Flag Bits | Description |
|---|---|
| AI_PASSIVE |
AI_PASSIVE フラグを設定すると、呼び出し元が、返されたソケットアドレス構造体を
bind 関数の呼び出しで使用する意図があることを示します。AI_PASSIVE フラグが設定され、かつ pName が NULL ポインターの場合、ソケットアドレス構造体の IP アドレス部分は、IPv4 アドレスでは INADDR_ANY に、IPv6 アドレスでは IN6ADDR_ANY_INIT に設定されます。
AI_PASSIVE フラグが設定されていない場合、返されたソケットアドレス構造体は、コネクション指向プロトコルの connect 関数の呼び出し、またはコネクションレスプロトコルの connect、 sendto、 send 関数のいずれかの呼び出しにそのまま使用できる状態になっています。この場合に pName パラメーターが NULL ポインターであれば、ソケットアドレス構造体の IP アドレス部分はループバックアドレスに設定されます。 |
| AI_CANONNAME |
AI_CANONNAME も AI_NUMERICHOST も使用されていない場合、
GetAddrInfoEx 関数は名前解決を試みます。リテラル文字列が渡された場合は
GetAddrInfoEx がその文字列の変換を試み、ホスト名が渡された場合は
GetAddrInfoEx 関数がその名前を 1 つまたは複数のアドレスに解決することを試みます。
AI_CANONNAME ビットが設定されている場合、pName パラメーターを NULL にすることはできません。そうでない場合、 GetAddrInfoEx 関数は WSANO_RECOVERY で失敗します。 AI_CANONNAME ビットが設定され、かつ GetAddrInfoEx 関数が成功を返した場合、ppResult パラメーター内の ai_canonname メンバーは、指定されたノードの正規名を含む NULL 終端文字列を指します。 Note 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 ビットの両方を設定できます。AI_FQDN ビットと AI_CANONNAME ビットの両方を指定して GetAddrInfoEx 関数を呼び出した場合、ppResult パラメーターは addrinfoex 構造体ではなく addrinfoex2 構造体へのポインターを返します。 Windows 7 および Windows Server 2008 R2 では、AI_FQDN ビットと AI_CANONNAME ビットのいずれか一方のみを設定できます。両方のフラグが指定されている場合、GetAddrInfoEx 関数は EAI_BADFLAGS で失敗します。 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 を定義しています。エンコードに依存しないこのエイリアスの使用を、エンコードに依存しないわけではないコードと混在させると、コンパイルエラーや実行時エラーを引き起こす不一致が生じる可能性があります。詳細については、Conventions for Function Prototypes を参照してください。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
各言語での呼び出し定義
// WS2_32.dll (Unicode / -W)
#include <windows.h>
INT GetAddrInfoExW(
LPCWSTR pName, // optional
LPCWSTR pServiceName, // optional
DWORD dwNameSpace,
GUID* lpNspId, // optional
const ADDRINFOEXW* hints, // optional
ADDRINFOEXW** ppResult,
TIMEVAL* timeout, // optional
OVERLAPPED* lpOverlapped, // optional
LPLOOKUPSERVICE_COMPLETION_ROUTINE lpCompletionRoutine, // optional
HANDLE* lpHandle // optional
);[DllImport("WS2_32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
static extern int GetAddrInfoExW(
[MarshalAs(UnmanagedType.LPWStr)] string pName, // LPCWSTR optional
[MarshalAs(UnmanagedType.LPWStr)] string pServiceName, // LPCWSTR optional
uint dwNameSpace, // DWORD
IntPtr lpNspId, // GUID* optional
IntPtr hints, // ADDRINFOEXW* optional
IntPtr ppResult, // ADDRINFOEXW** out
IntPtr timeout, // TIMEVAL* optional
IntPtr lpOverlapped, // OVERLAPPED* optional
IntPtr lpCompletionRoutine, // LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
IntPtr lpHandle // HANDLE* optional, out
);<DllImport("WS2_32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True)>
Public Shared Function GetAddrInfoExW(
<MarshalAs(UnmanagedType.LPWStr)> pName As String, ' LPCWSTR optional
<MarshalAs(UnmanagedType.LPWStr)> pServiceName As String, ' LPCWSTR optional
dwNameSpace As UInteger, ' DWORD
lpNspId As IntPtr, ' GUID* optional
hints As IntPtr, ' ADDRINFOEXW* optional
ppResult As IntPtr, ' ADDRINFOEXW** out
timeout As IntPtr, ' TIMEVAL* optional
lpOverlapped As IntPtr, ' OVERLAPPED* optional
lpCompletionRoutine As IntPtr, ' LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
lpHandle As IntPtr ' HANDLE* optional, out
) As Integer
End Function' pName : LPCWSTR optional
' pServiceName : LPCWSTR optional
' dwNameSpace : DWORD
' lpNspId : GUID* optional
' hints : ADDRINFOEXW* optional
' ppResult : ADDRINFOEXW** out
' timeout : TIMEVAL* optional
' lpOverlapped : OVERLAPPED* optional
' lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
' lpHandle : HANDLE* optional, out
Declare PtrSafe Function GetAddrInfoExW Lib "ws2_32" ( _
ByVal pName As LongPtr, _
ByVal pServiceName As LongPtr, _
ByVal dwNameSpace As Long, _
ByVal lpNspId As LongPtr, _
ByVal hints As LongPtr, _
ByVal ppResult As LongPtr, _
ByVal timeout As LongPtr, _
ByVal lpOverlapped As LongPtr, _
ByVal lpCompletionRoutine As LongPtr, _
ByVal lpHandle As LongPtr) As Long
' Unicode(W): 文字列は ByVal As LongPtr とし StrPtr(unicodeStr) を渡す
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。import ctypes
from ctypes import wintypes
GetAddrInfoExW = ctypes.windll.ws2_32.GetAddrInfoExW
GetAddrInfoExW.restype = ctypes.c_int
GetAddrInfoExW.argtypes = [
wintypes.LPCWSTR, # pName : LPCWSTR optional
wintypes.LPCWSTR, # pServiceName : LPCWSTR optional
wintypes.DWORD, # dwNameSpace : DWORD
ctypes.c_void_p, # lpNspId : GUID* optional
ctypes.c_void_p, # hints : ADDRINFOEXW* optional
ctypes.c_void_p, # ppResult : ADDRINFOEXW** out
ctypes.c_void_p, # timeout : TIMEVAL* optional
ctypes.c_void_p, # lpOverlapped : OVERLAPPED* optional
ctypes.c_void_p, # lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
ctypes.c_void_p, # lpHandle : HANDLE* optional, out
]require 'fiddle'
require 'fiddle/import'
lib = Fiddle.dlopen('WS2_32.dll')
GetAddrInfoExW = Fiddle::Function.new(
lib['GetAddrInfoExW'],
[
Fiddle::TYPE_VOIDP, # pName : LPCWSTR optional
Fiddle::TYPE_VOIDP, # pServiceName : LPCWSTR optional
-Fiddle::TYPE_INT, # dwNameSpace : DWORD
Fiddle::TYPE_VOIDP, # lpNspId : GUID* optional
Fiddle::TYPE_VOIDP, # hints : ADDRINFOEXW* optional
Fiddle::TYPE_VOIDP, # ppResult : ADDRINFOEXW** out
Fiddle::TYPE_VOIDP, # timeout : TIMEVAL* optional
Fiddle::TYPE_VOIDP, # lpOverlapped : OVERLAPPED* optional
Fiddle::TYPE_VOIDP, # lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
Fiddle::TYPE_VOIDP, # lpHandle : HANDLE* optional, out
],
Fiddle::TYPE_INT)
# Wide strings: pass str.encode("UTF-16LE") + "\x00\x00"#[link(name = "ws2_32")]
extern "system" {
fn GetAddrInfoExW(
pName: *const u16, // LPCWSTR optional
pServiceName: *const u16, // LPCWSTR optional
dwNameSpace: u32, // DWORD
lpNspId: *mut GUID, // GUID* optional
hints: *const ADDRINFOEXW, // ADDRINFOEXW* optional
ppResult: *mut *mut ADDRINFOEXW, // ADDRINFOEXW** out
timeout: *mut TIMEVAL, // TIMEVAL* optional
lpOverlapped: *mut OVERLAPPED, // OVERLAPPED* optional
lpCompletionRoutine: *const core::ffi::c_void, // LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
lpHandle: *mut *mut core::ffi::c_void // HANDLE* optional, out
) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.$sig = @"
[DllImport("WS2_32.dll", CharSet = CharSet.Unicode)]
public static extern int GetAddrInfoExW([MarshalAs(UnmanagedType.LPWStr)] string pName, [MarshalAs(UnmanagedType.LPWStr)] string pServiceName, uint dwNameSpace, IntPtr lpNspId, IntPtr hints, IntPtr ppResult, IntPtr timeout, IntPtr lpOverlapped, IntPtr lpCompletionRoutine, IntPtr lpHandle);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_GetAddrInfoExW' -Namespace Win32 -PassThru
# $api::GetAddrInfoExW(pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle)#uselib "WS2_32.dll"
#func global GetAddrInfoExW "GetAddrInfoExW" wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr
; GetAddrInfoExW pName, pServiceName, dwNameSpace, varptr(lpNspId), varptr(hints), varptr(ppResult), varptr(timeout), varptr(lpOverlapped), lpCompletionRoutine, lpHandle ; 戻り値は stat
; pName : LPCWSTR optional -> "wptr"
; pServiceName : LPCWSTR optional -> "wptr"
; dwNameSpace : DWORD -> "wptr"
; lpNspId : GUID* optional -> "wptr"
; hints : ADDRINFOEXW* optional -> "wptr"
; ppResult : ADDRINFOEXW** out -> "wptr"
; timeout : TIMEVAL* optional -> "wptr"
; lpOverlapped : OVERLAPPED* optional -> "wptr"
; lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> "wptr"
; lpHandle : HANDLE* optional, out -> "wptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。#uselib "WS2_32.dll" #cfunc global GetAddrInfoExW "GetAddrInfoExW" wstr, wstr, int, var, var, var, var, var, sptr, sptr ; res = GetAddrInfoExW(pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle) ; pName : LPCWSTR optional -> "wstr" ; pServiceName : LPCWSTR optional -> "wstr" ; dwNameSpace : DWORD -> "int" ; lpNspId : GUID* optional -> "var" ; hints : ADDRINFOEXW* optional -> "var" ; ppResult : ADDRINFOEXW** out -> "var" ; timeout : TIMEVAL* optional -> "var" ; lpOverlapped : OVERLAPPED* optional -> "var" ; lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> "sptr" ; lpHandle : HANDLE* optional, out -> "sptr" ; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。#uselib "WS2_32.dll" #cfunc global GetAddrInfoExW "GetAddrInfoExW" wstr, wstr, int, sptr, sptr, sptr, sptr, sptr, sptr, sptr ; res = GetAddrInfoExW(pName, pServiceName, dwNameSpace, varptr(lpNspId), varptr(hints), varptr(ppResult), varptr(timeout), varptr(lpOverlapped), lpCompletionRoutine, lpHandle) ; pName : LPCWSTR optional -> "wstr" ; pServiceName : LPCWSTR optional -> "wstr" ; dwNameSpace : DWORD -> "int" ; lpNspId : GUID* optional -> "sptr" ; hints : ADDRINFOEXW* optional -> "sptr" ; ppResult : ADDRINFOEXW** out -> "sptr" ; timeout : TIMEVAL* optional -> "sptr" ; lpOverlapped : OVERLAPPED* optional -> "sptr" ; lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> "sptr" ; lpHandle : HANDLE* optional, out -> "sptr" ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。
; INT GetAddrInfoExW(LPCWSTR pName, LPCWSTR pServiceName, DWORD dwNameSpace, GUID* lpNspId, ADDRINFOEXW* hints, ADDRINFOEXW** ppResult, TIMEVAL* timeout, OVERLAPPED* lpOverlapped, LPLOOKUPSERVICE_COMPLETION_ROUTINE lpCompletionRoutine, HANDLE* lpHandle) #uselib "WS2_32.dll" #cfunc global GetAddrInfoExW "GetAddrInfoExW" wstr, wstr, int, var, var, var, var, var, intptr, intptr ; res = GetAddrInfoExW(pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle) ; pName : LPCWSTR optional -> "wstr" ; pServiceName : LPCWSTR optional -> "wstr" ; dwNameSpace : DWORD -> "int" ; lpNspId : GUID* optional -> "var" ; hints : ADDRINFOEXW* optional -> "var" ; ppResult : ADDRINFOEXW** out -> "var" ; timeout : TIMEVAL* optional -> "var" ; lpOverlapped : OVERLAPPED* optional -> "var" ; lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> "intptr" ; lpHandle : HANDLE* optional, out -> "intptr" ; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。; INT GetAddrInfoExW(LPCWSTR pName, LPCWSTR pServiceName, DWORD dwNameSpace, GUID* lpNspId, ADDRINFOEXW* hints, ADDRINFOEXW** ppResult, TIMEVAL* timeout, OVERLAPPED* lpOverlapped, LPLOOKUPSERVICE_COMPLETION_ROUTINE lpCompletionRoutine, HANDLE* lpHandle) #uselib "WS2_32.dll" #cfunc global GetAddrInfoExW "GetAddrInfoExW" wstr, wstr, int, intptr, intptr, intptr, intptr, intptr, intptr, intptr ; res = GetAddrInfoExW(pName, pServiceName, dwNameSpace, varptr(lpNspId), varptr(hints), varptr(ppResult), varptr(timeout), varptr(lpOverlapped), lpCompletionRoutine, lpHandle) ; pName : LPCWSTR optional -> "wstr" ; pServiceName : LPCWSTR optional -> "wstr" ; dwNameSpace : DWORD -> "int" ; lpNspId : GUID* optional -> "intptr" ; hints : ADDRINFOEXW* optional -> "intptr" ; ppResult : ADDRINFOEXW** out -> "intptr" ; timeout : TIMEVAL* optional -> "intptr" ; lpOverlapped : OVERLAPPED* optional -> "intptr" ; lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> "intptr" ; lpHandle : HANDLE* optional, out -> "intptr" ; ※出力/バッファ引数はポインタ方式(token=intptr / 呼び出しは varptr(変数))。
import (
"golang.org/x/sys/windows"
"unsafe"
)
var (
ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
procGetAddrInfoExW = ws2_32.NewProc("GetAddrInfoExW")
)
// pName (LPCWSTR optional), pServiceName (LPCWSTR optional), dwNameSpace (DWORD), lpNspId (GUID* optional), hints (ADDRINFOEXW* optional), ppResult (ADDRINFOEXW** out), timeout (TIMEVAL* optional), lpOverlapped (OVERLAPPED* optional), lpCompletionRoutine (LPLOOKUPSERVICE_COMPLETION_ROUTINE optional), lpHandle (HANDLE* optional, out)
r1, _, err := procGetAddrInfoExW.Call(
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(pName))),
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(pServiceName))),
uintptr(dwNameSpace),
uintptr(lpNspId),
uintptr(hints),
uintptr(ppResult),
uintptr(timeout),
uintptr(lpOverlapped),
uintptr(lpCompletionRoutine),
uintptr(lpHandle),
)
_ = err // syscall.Errno (valid when the call sets last-error)
_ = r1 // INTfunction GetAddrInfoExW(
pName: PWideChar; // LPCWSTR optional
pServiceName: PWideChar; // LPCWSTR optional
dwNameSpace: DWORD; // DWORD
lpNspId: PGUID; // GUID* optional
hints: Pointer; // ADDRINFOEXW* optional
ppResult: Pointer; // ADDRINFOEXW** out
timeout: Pointer; // TIMEVAL* optional
lpOverlapped: Pointer; // OVERLAPPED* optional
lpCompletionRoutine: Pointer; // LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
lpHandle: Pointer // HANDLE* optional, out
): Integer; stdcall;
external 'WS2_32.dll' name 'GetAddrInfoExW';result := DllCall("WS2_32\GetAddrInfoExW"
, "WStr", pName ; LPCWSTR optional
, "WStr", pServiceName ; LPCWSTR optional
, "UInt", dwNameSpace ; DWORD
, "Ptr", lpNspId ; GUID* optional
, "Ptr", hints ; ADDRINFOEXW* optional
, "Ptr", ppResult ; ADDRINFOEXW** out
, "Ptr", timeout ; TIMEVAL* optional
, "Ptr", lpOverlapped ; OVERLAPPED* optional
, "Ptr", lpCompletionRoutine ; LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
, "Ptr", lpHandle ; HANDLE* optional, out
, "Int") ; return: INT●GetAddrInfoExW(pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle) = DLL("WS2_32.dll", "int GetAddrInfoExW(char*, char*, dword, void*, void*, void*, void*, void*, void*, void*)")
# 呼び出し: GetAddrInfoExW(pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle)
# pName : LPCWSTR optional -> "char*"
# pServiceName : LPCWSTR optional -> "char*"
# dwNameSpace : DWORD -> "dword"
# lpNspId : GUID* optional -> "void*"
# hints : ADDRINFOEXW* optional -> "void*"
# ppResult : ADDRINFOEXW** out -> "void*"
# timeout : TIMEVAL* optional -> "void*"
# lpOverlapped : OVERLAPPED* optional -> "void*"
# lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> "void*"
# lpHandle : HANDLE* optional, out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
# ※-W(Unicode)関数。なでしこ1はANSIのため -A 版の利用を推奨。const std = @import("std");
extern "ws2_32" fn GetAddrInfoExW(
pName: [*c]const u16, // LPCWSTR optional
pServiceName: [*c]const u16, // LPCWSTR optional
dwNameSpace: u32, // DWORD
lpNspId: [*c]GUID, // GUID* optional
hints: [*c]ADDRINFOEXW, // ADDRINFOEXW* optional
ppResult: [*c][*c]ADDRINFOEXW, // ADDRINFOEXW** out
timeout: [*c]TIMEVAL, // TIMEVAL* optional
lpOverlapped: [*c]OVERLAPPED, // OVERLAPPED* optional
lpCompletionRoutine: ?*anyopaque, // LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
lpHandle: ?*anyopaque // HANDLE* optional, out
) callconv(std.os.windows.WINAPI) i32;
// Unicode(-W): UTF-16LE のヌル終端バッファ([*c]const u16)を渡す。proc GetAddrInfoExW(
pName: WideCString, # LPCWSTR optional
pServiceName: WideCString, # LPCWSTR optional
dwNameSpace: uint32, # DWORD
lpNspId: ptr GUID, # GUID* optional
hints: ptr ADDRINFOEXW, # ADDRINFOEXW* optional
ppResult: ptr ADDRINFOEXW, # ADDRINFOEXW** out
timeout: ptr TIMEVAL, # TIMEVAL* optional
lpOverlapped: ptr OVERLAPPED, # OVERLAPPED* optional
lpCompletionRoutine: pointer, # LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
lpHandle: pointer # HANDLE* optional, out
): int32 {.importc: "GetAddrInfoExW", stdcall, dynlib: "WS2_32.dll".}
# Unicode(-W): WideCString は newWideCString("...") で生成。pragma(lib, "ws2_32");
extern(Windows)
int GetAddrInfoExW(
const(wchar)* pName, // LPCWSTR optional
const(wchar)* pServiceName, // LPCWSTR optional
uint dwNameSpace, // DWORD
GUID* lpNspId, // GUID* optional
ADDRINFOEXW* hints, // ADDRINFOEXW* optional
ADDRINFOEXW** ppResult, // ADDRINFOEXW** out
TIMEVAL* timeout, // TIMEVAL* optional
OVERLAPPED* lpOverlapped, // OVERLAPPED* optional
void* lpCompletionRoutine, // LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
void* lpHandle // HANDLE* optional, out
);ccall((:GetAddrInfoExW, "WS2_32.dll"), stdcall, Int32,
(Cwstring, Cwstring, UInt32, Ptr{GUID}, Ptr{ADDRINFOEXW}, Ptr{ADDRINFOEXW}, Ptr{TIMEVAL}, Ptr{OVERLAPPED}, Ptr{Cvoid}, Ptr{Cvoid}),
pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle)
# pName : LPCWSTR optional -> Cwstring
# pServiceName : LPCWSTR optional -> Cwstring
# dwNameSpace : DWORD -> UInt32
# lpNspId : GUID* optional -> Ptr{GUID}
# hints : ADDRINFOEXW* optional -> Ptr{ADDRINFOEXW}
# ppResult : ADDRINFOEXW** out -> Ptr{ADDRINFOEXW}
# timeout : TIMEVAL* optional -> Ptr{TIMEVAL}
# lpOverlapped : OVERLAPPED* optional -> Ptr{OVERLAPPED}
# lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> Ptr{Cvoid}
# lpHandle : HANDLE* optional, out -> Ptr{Cvoid}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
# Unicode(-W): Cwstring には transcode(UInt16, "...") 等で UTF-16 を渡す。local ffi = require("ffi")
ffi.cdef[[
int32_t GetAddrInfoExW(
const uint16_t* pName,
const uint16_t* pServiceName,
uint32_t dwNameSpace,
void* lpNspId,
void* hints,
void* ppResult,
void* timeout,
void* lpOverlapped,
void* lpCompletionRoutine,
void* lpHandle);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.GetAddrInfoExW(pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle)
-- pName : LPCWSTR optional
-- pServiceName : LPCWSTR optional
-- dwNameSpace : DWORD
-- lpNspId : GUID* optional
-- hints : ADDRINFOEXW* optional
-- ppResult : ADDRINFOEXW** out
-- timeout : TIMEVAL* optional
-- lpOverlapped : OVERLAPPED* optional
-- lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
-- lpHandle : HANDLE* optional, out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
-- Unicode(-W): uint16_t* には UTF-16LE のバッファ(ffi.new("uint16_t[?]", ...))を渡す。const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const GetAddrInfoExW = lib.func('__stdcall', 'GetAddrInfoExW', 'int32_t', ['str16', 'str16', 'uint32_t', 'void *', 'void *', 'void *', 'void *', 'void *', 'void *', 'void *']);
// GetAddrInfoExW(pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle)
// pName : LPCWSTR optional -> 'str16'
// pServiceName : LPCWSTR optional -> 'str16'
// dwNameSpace : DWORD -> 'uint32_t'
// lpNspId : GUID* optional -> 'void *'
// hints : ADDRINFOEXW* optional -> 'void *'
// ppResult : ADDRINFOEXW** out -> 'void *'
// timeout : TIMEVAL* optional -> 'void *'
// lpOverlapped : OVERLAPPED* optional -> 'void *'
// lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> 'void *'
// lpHandle : HANDLE* optional, out -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
// コールバック(関数ポインタ)は koffi.proto/koffi.register で型を定義して渡す(素の void* では JS 関数を渡せない)。const lib = Deno.dlopen("WS2_32.dll", {
GetAddrInfoExW: { parameters: ["buffer", "buffer", "u32", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.GetAddrInfoExW(pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle)
// pName : LPCWSTR optional -> "buffer"
// pServiceName : LPCWSTR optional -> "buffer"
// dwNameSpace : DWORD -> "u32"
// lpNspId : GUID* optional -> "pointer"
// hints : ADDRINFOEXW* optional -> "pointer"
// ppResult : ADDRINFOEXW** out -> "pointer"
// timeout : TIMEVAL* optional -> "pointer"
// lpOverlapped : OVERLAPPED* optional -> "pointer"
// lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> "pointer"
// lpHandle : HANDLE* optional, out -> "pointer"
// 文字列は "buffer"。Unicode(-W) は new TextEncoder() ではなく UTF-16LE のバイト列(末尾に \x00\x00)を Uint8Array で渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。<?php
$ffi = FFI::cdef(<<<C
int32_t GetAddrInfoExW(
const uint16_t* pName,
const uint16_t* pServiceName,
uint32_t dwNameSpace,
void* lpNspId,
void* hints,
void* ppResult,
void* timeout,
void* lpOverlapped,
void* lpCompletionRoutine,
void* lpHandle);
C, "WS2_32.dll");
// $ffi->GetAddrInfoExW(pName, pServiceName, dwNameSpace, lpNspId, hints, ppResult, timeout, lpOverlapped, lpCompletionRoutine, lpHandle);
// pName : LPCWSTR optional
// pServiceName : LPCWSTR optional
// dwNameSpace : DWORD
// lpNspId : GUID* optional
// hints : ADDRINFOEXW* optional
// ppResult : ADDRINFOEXW** out
// timeout : TIMEVAL* optional
// lpOverlapped : OVERLAPPED* optional
// lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
// lpHandle : HANDLE* optional, 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, W32APIOptions.UNICODE_OPTIONS);
int GetAddrInfoExW(
WString pName, // LPCWSTR optional
WString pServiceName, // LPCWSTR optional
int dwNameSpace, // DWORD
Pointer lpNspId, // GUID* optional
Pointer hints, // ADDRINFOEXW* optional
Pointer ppResult, // ADDRINFOEXW** out
Pointer timeout, // TIMEVAL* optional
Pointer lpOverlapped, // OVERLAPPED* optional
Callback lpCompletionRoutine, // LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
Pointer lpHandle // HANDLE* optional, out
);
}
// Unicode(-W): WString(入力)/char[](出力)で UTF-16 をマーシャリング。@[Link("ws2_32")]
lib LibWS2_32
fun GetAddrInfoExW = GetAddrInfoExW(
pName : UInt16*, # LPCWSTR optional
pServiceName : UInt16*, # LPCWSTR optional
dwNameSpace : UInt32, # DWORD
lpNspId : GUID*, # GUID* optional
hints : ADDRINFOEXW*, # ADDRINFOEXW* optional
ppResult : ADDRINFOEXW**, # ADDRINFOEXW** out
timeout : TIMEVAL*, # TIMEVAL* optional
lpOverlapped : OVERLAPPED*, # OVERLAPPED* optional
lpCompletionRoutine : Void*, # LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
lpHandle : Void* # HANDLE* optional, out
) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。import 'dart:ffi';
import 'package:ffi/ffi.dart';
typedef GetAddrInfoExWNative = Int32 Function(Pointer<Utf16>, Pointer<Utf16>, Uint32, Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>);
typedef GetAddrInfoExWDart = int Function(Pointer<Utf16>, Pointer<Utf16>, int, Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>);
final GetAddrInfoExW = DynamicLibrary.open('WS2_32.dll')
.lookupFunction<GetAddrInfoExWNative, GetAddrInfoExWDart>('GetAddrInfoExW');
// pName : LPCWSTR optional -> Pointer<Utf16>
// pServiceName : LPCWSTR optional -> Pointer<Utf16>
// dwNameSpace : DWORD -> Uint32
// lpNspId : GUID* optional -> Pointer<Void>
// hints : ADDRINFOEXW* optional -> Pointer<Void>
// ppResult : ADDRINFOEXW** out -> Pointer<Void>
// timeout : TIMEVAL* optional -> Pointer<Void>
// lpOverlapped : OVERLAPPED* optional -> Pointer<Void>
// lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> Pointer<Void>
// lpHandle : HANDLE* optional, out -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。{$mode objfpc}{$H+}
function GetAddrInfoExW(
pName: PWideChar; // LPCWSTR optional
pServiceName: PWideChar; // LPCWSTR optional
dwNameSpace: DWORD; // DWORD
lpNspId: PGUID; // GUID* optional
hints: Pointer; // ADDRINFOEXW* optional
ppResult: Pointer; // ADDRINFOEXW** out
timeout: Pointer; // TIMEVAL* optional
lpOverlapped: Pointer; // OVERLAPPED* optional
lpCompletionRoutine: Pointer; // LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
lpHandle: Pointer // HANDLE* optional, out
): Integer; stdcall;
external 'WS2_32.dll' name 'GetAddrInfoExW';import Foreign
import Foreign.C.Types
import Foreign.C.String
foreign import stdcall safe "GetAddrInfoExW"
c_GetAddrInfoExW :: CWString -> CWString -> Word32 -> Ptr () -> Ptr () -> Ptr () -> Ptr () -> Ptr () -> Ptr () -> Ptr () -> IO Int32
-- pName : LPCWSTR optional -> CWString
-- pServiceName : LPCWSTR optional -> CWString
-- dwNameSpace : DWORD -> Word32
-- lpNspId : GUID* optional -> Ptr ()
-- hints : ADDRINFOEXW* optional -> Ptr ()
-- ppResult : ADDRINFOEXW** out -> Ptr ()
-- timeout : TIMEVAL* optional -> Ptr ()
-- lpOverlapped : OVERLAPPED* optional -> Ptr ()
-- lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> Ptr ()
-- lpHandle : HANDLE* optional, out -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。open Ctypes
open Foreign
let getaddrinfoexw =
foreign "GetAddrInfoExW"
((ptr uint16_t) @-> (ptr uint16_t) @-> uint32_t @-> (ptr void) @-> (ptr void) @-> (ptr void) @-> (ptr void) @-> (ptr void) @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* pName : LPCWSTR optional -> (ptr uint16_t) *)
(* pServiceName : LPCWSTR optional -> (ptr uint16_t) *)
(* dwNameSpace : DWORD -> uint32_t *)
(* lpNspId : GUID* optional -> (ptr void) *)
(* hints : ADDRINFOEXW* optional -> (ptr void) *)
(* ppResult : ADDRINFOEXW** out -> (ptr void) *)
(* timeout : TIMEVAL* optional -> (ptr void) *)
(* lpOverlapped : OVERLAPPED* optional -> (ptr void) *)
(* lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> (ptr void) *)
(* lpHandle : HANDLE* optional, 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 ("GetAddrInfoExW" get-addr-info-ex-w :convention :stdcall) :int32
(p-name (:string :encoding :utf-16le)) ; LPCWSTR optional
(p-service-name (:string :encoding :utf-16le)) ; LPCWSTR optional
(dw-name-space :uint32) ; DWORD
(lp-nsp-id :pointer) ; GUID* optional
(hints :pointer) ; ADDRINFOEXW* optional
(pp-result :pointer) ; ADDRINFOEXW** out
(timeout :pointer) ; TIMEVAL* optional
(lp-overlapped :pointer) ; OVERLAPPED* optional
(lp-completion-routine :pointer) ; LPLOOKUPSERVICE_COMPLETION_ROUTINE optional
(lp-handle :pointer)) ; HANDLE* optional, out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。use Win32::API;
my $GetAddrInfoExW = Win32::API::More->new('WS2_32',
'int GetAddrInfoExW(LPCWSTR pName, LPCWSTR pServiceName, DWORD dwNameSpace, LPVOID lpNspId, LPVOID hints, LPVOID ppResult, LPVOID timeout, LPVOID lpOverlapped, LPVOID lpCompletionRoutine, HANDLE lpHandle)');
# my $ret = $GetAddrInfoExW->Call($pName, $pServiceName, $dwNameSpace, $lpNspId, $hints, $ppResult, $timeout, $lpOverlapped, $lpCompletionRoutine, $lpHandle);
# pName : LPCWSTR optional -> LPCWSTR
# pServiceName : LPCWSTR optional -> LPCWSTR
# dwNameSpace : DWORD -> DWORD
# lpNspId : GUID* optional -> LPVOID
# hints : ADDRINFOEXW* optional -> LPVOID
# ppResult : ADDRINFOEXW** out -> LPVOID
# timeout : TIMEVAL* optional -> LPVOID
# lpOverlapped : OVERLAPPED* optional -> LPVOID
# lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE optional -> LPVOID
# lpHandle : HANDLE* optional, out -> HANDLE
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# コールバック(関数ポインタ)は Perl sub を直接渡せません。Win32::API::Callback を使用してください。
# Unicode(-W): LPCWSTR/LPWSTR は Win32::API が UTF-16 変換を行う。関連項目
- f GetAddrInfoExA (ANSI版) — 名前を非同期や拡張オプション付きでアドレス解決する。
- f FreeAddrInfoExW — 拡張アドレス情報構造体のメモリを解放する。
- f GetAddrInfoExCancel — 進行中の拡張アドレス解決要求を取り消す。
- f GetAddrInfoExOverlappedResult — 拡張アドレス解決のオーバーラップ操作結果を取得する。
- f GetAddrInfoW — ホスト名やサービス名からアドレス情報を解決する。
- f IdnToAscii — 国際化ドメイン名をUnicodeからASCII(Punycode)へ変換する。
- f IdnToUnicode — 国際化ドメイン名をASCII(Punycode)からUnicodeへ変換する。
- f WSAEnumNameSpaceProvidersW — 登録済みの名前空間プロバイダーを列挙する。
- f WSAGetLastError — 直前のソケット操作のエラーコードを取得する。
- s ADDRINFOEX2W
- f getaddrinfo — ホスト名やサービス名からアドレス情報を解決する。