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

WSAConnectByNameW

関数
ホスト名とサービス名を指定して接続を確立する。
DLLWS2_32.dll文字セットUnicode (-W)呼出規約winapiSetLastErrorあり対応OSWindows 8.1 以降

シグネチャ

// WS2_32.dll  (Unicode / -W)
#include <windows.h>

BOOL WSAConnectByNameW(
    SOCKET s,
    LPWSTR nodename,
    LPWSTR servicename,
    DWORD* LocalAddressLength,   // optional
    SOCKADDR* LocalAddress,   // optional
    DWORD* RemoteAddressLength,   // optional
    SOCKADDR* RemoteAddress,   // optional
    const TIMEVAL* timeout,   // optional
    OVERLAPPED* Reserved   // optional
);

パラメーター

名前方向説明
sSOCKETin

未接続のソケットを識別するディスクリプタ。

Note Windows 7、Windows Server 2008 R2 以前では、WSAConnectByName 関数はバインドされていない未接続のソケットを必要とします。これは接続を確立する他の Winsock 呼び出し(たとえば WSAConnect)とは異なります。
nodenameLPWSTRinIPv4 または IPv6 で接続先となるホストの名前、またはホストの IP アドレスを格納する NULL 終端文字列。
servicenameLPWSTRin

IPv4 または IPv6 で接続先となるホストのサービス名または宛先ポートを格納する NULL 終端文字列。

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

%WINDIR%\system32\drivers\etc\services

LocalAddressLengthDWORD*inoutoptional入力時には、呼び出し側が提供する LocalAddress バッファのサイズ(バイト単位)へのポインタ。出力時には、呼び出しが正常に完了した際にシステムが LocalAddress バッファに格納したローカルアドレスの SOCKADDR のサイズ(バイト単位)へのポインタ。
LocalAddressSOCKADDR*outoptional接続のローカルアドレスを受け取る SOCKADDR 構造体へのポインタ。このパラメータのサイズは LocalAddressLength で返されるサイズと正確に一致します。これは getsockname 関数が返すものと同じ情報です。このパラメータには NULL を指定でき、その場合 LocalAddressLength パラメータは無視されます。
RemoteAddressLengthDWORD*inoutoptional入力時には、呼び出し側が提供する RemoteAddress バッファのサイズ(バイト単位)へのポインタ。出力時には、呼び出しが正常に完了した際にシステムが RemoteAddress バッファに格納したリモートアドレスの SOCKADDR のサイズ(バイト単位)へのポインタ。
RemoteAddressSOCKADDR*outoptional接続のリモートアドレスを受け取る SOCKADDR 構造体へのポインタ。これは getpeername 関数が返すものと同じ情報です。このパラメータには NULL を指定でき、その場合 RemoteAddressLength は無視されます。
timeoutTIMEVAL*inoptional呼び出しを中止する前に、リモートアプリケーションからの応答を待機する時間(ミリ秒単位)。
ReservedOVERLAPPED*optional将来の実装のために予約されています。このパラメータは NULL に設定する必要があります。

戻り値の型: BOOL

公式ドキュメント

指定したホストおよびポートへの接続を確立します。(Unicode)

戻り値

接続が確立された場合、WSAConnectByNameTRUE を返し、呼び出し側がバッファを提供していれば LocalAddress および RemoteAddress パラメータが設定されます。

呼び出しが失敗した場合は FALSE が返されます。続いて WSAGetLastError を呼び出すことで、拡張エラー情報を取得できます。

戻り値 説明
WSAEHOSTUNREACH
nodename パラメータとして渡されたホストに到達できませんでした。
WSAEINVAL
無効なパラメータが関数に渡されました。nodename または servicename パラメータは NULL であってはなりません。Reserved パラメータは NULL でなければなりません。
WSAENOBUFS
十分なメモリを割り当てることができませんでした。
WSAENOTSOCK
無効なソケットが関数に渡されました。s パラメータは INVALID_SOCKET または NULL であってはなりません。
WSAETIMEDOUT
timeout パラメータを超過する前に、リモートアプリケーションからの応答を受信できませんでした。

解説(Remarks)

WSAConnectByName は、特定のポート上のリモートホストへの迅速で透過的な接続を可能にするために提供されています。IPv6 版と IPv4 版の両方に対応しています。

IPv6 と IPv4 の両方の通信を有効にするには、次の方法を使用します。

WSAConnectByName には次の制限があります。 SOCK_STREAM 型のような、コネクション指向のソケットに対してのみ動作します。 この関数はオーバーラップ I/O や非ブロッキング動作をサポートしません。WSAConnectByName は、ソケットが非ブロッキングモードであってもブロックします。

WSAConnectByName は、接続確立時のユーザ提供データをサポートしません。この呼び出しは FLOWSPEC 構造体もサポートしません。これらの機能が必要な場合は、代わりに WSAConnect を使用する必要があります。

Windows 10 より前のバージョンでは、WSAConnectByName の socket パラメータはバインドされていないソケットでなければならないため、アプリケーションが特定のローカルアドレスまたはポートにバインドする必要がある場合は WSAConnectByName を使用できません。

この制限は Windows 10 で撤廃されました。

RemoteAddress および LocalAddress パラメータは、汎用的なデータ型である SOCKADDR 構造体を指します。WSAConnectByName が呼び出される際には、これらのパラメータには実際に使用されるネットワークプロトコルまたはアドレスファミリ固有のソケットアドレス型が渡されることが想定されています。したがって IPv4 アドレスの場合は、RemoteAddress および LocalAddress パラメータとして、sockaddr_in 構造体へのポインタを SOCKADDR へのポインタにキャストします。IPv6 アドレスの場合は、RemoteAddress および LocalAddress パラメータとして、sockaddr_in6 構造体へのポインタを SOCKADDR へのポインタにキャストします。

WSAConnectByName 関数が TRUE を返した時点で、ソケット s は接続済みソケットの既定の状態にあります。ソケット s は、SO_UPDATE_CONNECT_CONTEXT がソケットに設定されるまで、以前に設定したプロパティやオプションを有効にしません。SO_UPDATE_CONNECT_CONTEXT オプションを設定するには、setsockopt 関数を使用します。

例:

//Need to #include <mswsock.h> for SO_UPDATE_CONNECT_CONTEXT

int iResult = 0;

iResult = setsockopt( s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 );
Note timeout パラメータを NULL に設定して WSAConnectByName のようなブロッキング Winsock 呼び出しを発行する場合、呼び出しが完了する前に Winsock がネットワークイベントを待機する必要が生じることがあります。この状況で Winsock はアラート可能な待機を実行しますが、これは同じスレッド上でスケジュールされた非同期プロシージャ呼び出し (APC) によって中断され得ます。同じスレッド上で進行中のブロッキング Winsock 呼び出しを中断した APC の内部で、別のブロッキング Winsock 呼び出しを発行すると未定義の動作につながるため、Winsock クライアントは決してこれを試みてはなりません。
Windows Phone 8: WSAConnectByNameW 関数は、Windows Phone 8 以降の Windows Phone ストアアプリでサポートされています。

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

Examples

WSAConnectByName を使用して接続を確立します。

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <mswsock.h>   // Need for SO_UPDATE_CONNECT_CONTEXT
#include <stdio.h>

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

SOCKET
OpenAndConnect(LPWSTR NodeName, LPWSTR PortName) 
{
    SOCKET ConnSocket = INVALID_SOCKET;
    int ipv6only = 0;
    int iResult;
    BOOL bSuccess;
    SOCKADDR_STORAGE LocalAddr = {0};
    SOCKADDR_STORAGE RemoteAddr = {0};
    DWORD dwLocalAddr = sizeof(LocalAddr);
    DWORD dwRemoteAddr = sizeof(RemoteAddr);
  
    ConnSocket = socket(AF_INET6, SOCK_STREAM, 0);
    if (ConnSocket == INVALID_SOCKET){
        wprintf(L"socket failed with error: %d\n", WSAGetLastError());
        return INVALID_SOCKET;
    }

    iResult = setsockopt(ConnSocket, IPPROTO_IPV6,
        IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
    if (iResult == SOCKET_ERROR){
        wprintf(L"setsockopt for IPV6_V6ONLY failed with error: %d\n",
            WSAGetLastError());
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    bSuccess = WSAConnectByName(ConnSocket, NodeName, 
            PortName, &dwLocalAddr,
            (SOCKADDR*)&LocalAddr,
            &dwRemoteAddr,
            (SOCKADDR*)&RemoteAddr,
            NULL,
            NULL);
    if (!bSuccess){
        wprintf(L"WsaConnectByName failed with error: %d\n", WSAGetLastError());
        closesocket(ConnSocket);
        return INVALID_SOCKET;       

    
    }

    iResult = setsockopt(ConnSocket, SOL_SOCKET,
        SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
    if (iResult == SOCKET_ERROR){
        wprintf(L"setsockopt for SO_UPDATE_CONNECT_CONTEXT failed with error: %d\n",
            WSAGetLastError());
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    return ConnSocket;
}

int __cdecl wmain(int argc, wchar_t **argv)
{
   //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;

    SOCKET s = INVALID_SOCKET;

    // Validate the parameters
    if (argc != 3) {
        wprintf(L"usage: %ws <Nodename> <Portname>\n", argv[0]);
        wprintf(L"wsaconnectbyname establishes a connection to a specified host and port.\n");
        wprintf(L"%ws www.contoso.com 8080\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;
    }

    wprintf(L"WsaConnectByName with following parameters:\n");
    wprintf(L"\tNodename = %ws\n", argv[1]);
    wprintf(L"\tPortname (or port) = %ws\n\n", argv[2]);

    //--------------------------------
    // Call our function that uses the WsaConnectByName. 
    
    s = OpenAndConnect(argv[1], argv[2]);
    if ( s == INVALID_SOCKET ) {
        wprintf(L"WsaConnectByName failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    else
    {
        wprintf(L"WsaConnectByName succeeded\n");
        
        closesocket(s);
        WSACleanup();
        return 0;
    }
}
メモ

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

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

各言語での呼び出し定義

// WS2_32.dll  (Unicode / -W)
#include <windows.h>

BOOL WSAConnectByNameW(
    SOCKET s,
    LPWSTR nodename,
    LPWSTR servicename,
    DWORD* LocalAddressLength,   // optional
    SOCKADDR* LocalAddress,   // optional
    DWORD* RemoteAddressLength,   // optional
    SOCKADDR* RemoteAddress,   // optional
    const TIMEVAL* timeout,   // optional
    OVERLAPPED* Reserved   // optional
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WS2_32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
static extern bool WSAConnectByNameW(
    UIntPtr s,   // SOCKET
    [MarshalAs(UnmanagedType.LPWStr)] string nodename,   // LPWSTR
    [MarshalAs(UnmanagedType.LPWStr)] string servicename,   // LPWSTR
    IntPtr LocalAddressLength,   // DWORD* optional, in/out
    IntPtr LocalAddress,   // SOCKADDR* optional, out
    IntPtr RemoteAddressLength,   // DWORD* optional, in/out
    IntPtr RemoteAddress,   // SOCKADDR* optional, out
    IntPtr timeout,   // TIMEVAL* optional
    IntPtr Reserved   // OVERLAPPED* optional
);
<DllImport("WS2_32.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function WSAConnectByNameW(
    s As UIntPtr,   ' SOCKET
    <MarshalAs(UnmanagedType.LPWStr)> nodename As String,   ' LPWSTR
    <MarshalAs(UnmanagedType.LPWStr)> servicename As String,   ' LPWSTR
    LocalAddressLength As IntPtr,   ' DWORD* optional, in/out
    LocalAddress As IntPtr,   ' SOCKADDR* optional, out
    RemoteAddressLength As IntPtr,   ' DWORD* optional, in/out
    RemoteAddress As IntPtr,   ' SOCKADDR* optional, out
    timeout As IntPtr,   ' TIMEVAL* optional
    Reserved As IntPtr   ' OVERLAPPED* optional
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' s : SOCKET
' nodename : LPWSTR
' servicename : LPWSTR
' LocalAddressLength : DWORD* optional, in/out
' LocalAddress : SOCKADDR* optional, out
' RemoteAddressLength : DWORD* optional, in/out
' RemoteAddress : SOCKADDR* optional, out
' timeout : TIMEVAL* optional
' Reserved : OVERLAPPED* optional
Declare PtrSafe Function WSAConnectByNameW Lib "ws2_32" ( _
    ByVal s As LongPtr, _
    ByVal nodename As LongPtr, _
    ByVal servicename As LongPtr, _
    ByVal LocalAddressLength As LongPtr, _
    ByVal LocalAddress As LongPtr, _
    ByVal RemoteAddressLength As LongPtr, _
    ByVal RemoteAddress As LongPtr, _
    ByVal timeout As LongPtr, _
    ByVal Reserved 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

WSAConnectByNameW = ctypes.windll.ws2_32.WSAConnectByNameW
WSAConnectByNameW.restype = wintypes.BOOL
WSAConnectByNameW.argtypes = [
    ctypes.c_size_t,  # s : SOCKET
    wintypes.LPCWSTR,  # nodename : LPWSTR
    wintypes.LPCWSTR,  # servicename : LPWSTR
    ctypes.POINTER(wintypes.DWORD),  # LocalAddressLength : DWORD* optional, in/out
    ctypes.c_void_p,  # LocalAddress : SOCKADDR* optional, out
    ctypes.POINTER(wintypes.DWORD),  # RemoteAddressLength : DWORD* optional, in/out
    ctypes.c_void_p,  # RemoteAddress : SOCKADDR* optional, out
    ctypes.c_void_p,  # timeout : TIMEVAL* optional
    ctypes.c_void_p,  # Reserved : OVERLAPPED* optional
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WS2_32.dll')
WSAConnectByNameW = Fiddle::Function.new(
  lib['WSAConnectByNameW'],
  [
    Fiddle::TYPE_UINTPTR_T,  # s : SOCKET
    Fiddle::TYPE_VOIDP,  # nodename : LPWSTR
    Fiddle::TYPE_VOIDP,  # servicename : LPWSTR
    Fiddle::TYPE_VOIDP,  # LocalAddressLength : DWORD* optional, in/out
    Fiddle::TYPE_VOIDP,  # LocalAddress : SOCKADDR* optional, out
    Fiddle::TYPE_VOIDP,  # RemoteAddressLength : DWORD* optional, in/out
    Fiddle::TYPE_VOIDP,  # RemoteAddress : SOCKADDR* optional, out
    Fiddle::TYPE_VOIDP,  # timeout : TIMEVAL* optional
    Fiddle::TYPE_VOIDP,  # Reserved : OVERLAPPED* optional
  ],
  Fiddle::TYPE_INT)
# Wide strings: pass str.encode("UTF-16LE") + "\x00\x00"
#[link(name = "ws2_32")]
extern "system" {
    fn WSAConnectByNameW(
        s: usize,  // SOCKET
        nodename: *mut u16,  // LPWSTR
        servicename: *mut u16,  // LPWSTR
        LocalAddressLength: *mut u32,  // DWORD* optional, in/out
        LocalAddress: *mut SOCKADDR,  // SOCKADDR* optional, out
        RemoteAddressLength: *mut u32,  // DWORD* optional, in/out
        RemoteAddress: *mut SOCKADDR,  // SOCKADDR* optional, out
        timeout: *const TIMEVAL,  // TIMEVAL* optional
        Reserved: *mut OVERLAPPED  // OVERLAPPED* optional
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WS2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool WSAConnectByNameW(UIntPtr s, [MarshalAs(UnmanagedType.LPWStr)] string nodename, [MarshalAs(UnmanagedType.LPWStr)] string servicename, IntPtr LocalAddressLength, IntPtr LocalAddress, IntPtr RemoteAddressLength, IntPtr RemoteAddress, IntPtr timeout, IntPtr Reserved);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_WSAConnectByNameW' -Namespace Win32 -PassThru
# $api::WSAConnectByNameW(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
#uselib "WS2_32.dll"
#func global WSAConnectByNameW "WSAConnectByNameW" wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr, wptr
; WSAConnectByNameW s, nodename, servicename, varptr(LocalAddressLength), varptr(LocalAddress), varptr(RemoteAddressLength), varptr(RemoteAddress), varptr(timeout), varptr(Reserved)   ; 戻り値は stat
; s : SOCKET -> "wptr"
; nodename : LPWSTR -> "wptr"
; servicename : LPWSTR -> "wptr"
; LocalAddressLength : DWORD* optional, in/out -> "wptr"
; LocalAddress : SOCKADDR* optional, out -> "wptr"
; RemoteAddressLength : DWORD* optional, in/out -> "wptr"
; RemoteAddress : SOCKADDR* optional, out -> "wptr"
; timeout : TIMEVAL* optional -> "wptr"
; Reserved : OVERLAPPED* optional -> "wptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "WS2_32.dll"
#cfunc global WSAConnectByNameW "WSAConnectByNameW" sptr, wstr, wstr, var, var, var, var, var, var
; res = WSAConnectByNameW(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
; s : SOCKET -> "sptr"
; nodename : LPWSTR -> "wstr"
; servicename : LPWSTR -> "wstr"
; LocalAddressLength : DWORD* optional, in/out -> "var"
; LocalAddress : SOCKADDR* optional, out -> "var"
; RemoteAddressLength : DWORD* optional, in/out -> "var"
; RemoteAddress : SOCKADDR* optional, out -> "var"
; timeout : TIMEVAL* optional -> "var"
; Reserved : OVERLAPPED* optional -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; BOOL WSAConnectByNameW(SOCKET s, LPWSTR nodename, LPWSTR servicename, DWORD* LocalAddressLength, SOCKADDR* LocalAddress, DWORD* RemoteAddressLength, SOCKADDR* RemoteAddress, TIMEVAL* timeout, OVERLAPPED* Reserved)
#uselib "WS2_32.dll"
#cfunc global WSAConnectByNameW "WSAConnectByNameW" intptr, wstr, wstr, var, var, var, var, var, var
; res = WSAConnectByNameW(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
; s : SOCKET -> "intptr"
; nodename : LPWSTR -> "wstr"
; servicename : LPWSTR -> "wstr"
; LocalAddressLength : DWORD* optional, in/out -> "var"
; LocalAddress : SOCKADDR* optional, out -> "var"
; RemoteAddressLength : DWORD* optional, in/out -> "var"
; RemoteAddress : SOCKADDR* optional, out -> "var"
; timeout : TIMEVAL* optional -> "var"
; Reserved : OVERLAPPED* optional -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procWSAConnectByNameW = ws2_32.NewProc("WSAConnectByNameW")
)

// s (SOCKET), nodename (LPWSTR), servicename (LPWSTR), LocalAddressLength (DWORD* optional, in/out), LocalAddress (SOCKADDR* optional, out), RemoteAddressLength (DWORD* optional, in/out), RemoteAddress (SOCKADDR* optional, out), timeout (TIMEVAL* optional), Reserved (OVERLAPPED* optional)
r1, _, err := procWSAConnectByNameW.Call(
	uintptr(s),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(nodename))),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(servicename))),
	uintptr(LocalAddressLength),
	uintptr(LocalAddress),
	uintptr(RemoteAddressLength),
	uintptr(RemoteAddress),
	uintptr(timeout),
	uintptr(Reserved),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // BOOL
function WSAConnectByNameW(
  s: NativeUInt;   // SOCKET
  nodename: PWideChar;   // LPWSTR
  servicename: PWideChar;   // LPWSTR
  LocalAddressLength: Pointer;   // DWORD* optional, in/out
  LocalAddress: Pointer;   // SOCKADDR* optional, out
  RemoteAddressLength: Pointer;   // DWORD* optional, in/out
  RemoteAddress: Pointer;   // SOCKADDR* optional, out
  timeout: Pointer;   // TIMEVAL* optional
  Reserved: Pointer   // OVERLAPPED* optional
): BOOL; stdcall;
  external 'WS2_32.dll' name 'WSAConnectByNameW';
result := DllCall("WS2_32\WSAConnectByNameW"
    , "UPtr", s   ; SOCKET
    , "WStr", nodename   ; LPWSTR
    , "WStr", servicename   ; LPWSTR
    , "Ptr", LocalAddressLength   ; DWORD* optional, in/out
    , "Ptr", LocalAddress   ; SOCKADDR* optional, out
    , "Ptr", RemoteAddressLength   ; DWORD* optional, in/out
    , "Ptr", RemoteAddress   ; SOCKADDR* optional, out
    , "Ptr", timeout   ; TIMEVAL* optional
    , "Ptr", Reserved   ; OVERLAPPED* optional
    , "Int")   ; return: BOOL
●WSAConnectByNameW(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved) = DLL("WS2_32.dll", "bool WSAConnectByNameW(int, char*, char*, void*, void*, void*, void*, void*, void*)")
# 呼び出し: WSAConnectByNameW(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
# s : SOCKET -> "int"
# nodename : LPWSTR -> "char*"
# servicename : LPWSTR -> "char*"
# LocalAddressLength : DWORD* optional, in/out -> "void*"
# LocalAddress : SOCKADDR* optional, out -> "void*"
# RemoteAddressLength : DWORD* optional, in/out -> "void*"
# RemoteAddress : SOCKADDR* optional, out -> "void*"
# timeout : TIMEVAL* optional -> "void*"
# Reserved : OVERLAPPED* optional -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
# ※-W(Unicode)関数。なでしこ1はANSIのため -A 版の利用を推奨。
const std = @import("std");

extern "ws2_32" fn WSAConnectByNameW(
    s: usize, // SOCKET
    nodename: [*c]const u16, // LPWSTR
    servicename: [*c]const u16, // LPWSTR
    LocalAddressLength: [*c]u32, // DWORD* optional, in/out
    LocalAddress: [*c]SOCKADDR, // SOCKADDR* optional, out
    RemoteAddressLength: [*c]u32, // DWORD* optional, in/out
    RemoteAddress: [*c]SOCKADDR, // SOCKADDR* optional, out
    timeout: [*c]TIMEVAL, // TIMEVAL* optional
    Reserved: [*c]OVERLAPPED // OVERLAPPED* optional
) callconv(std.os.windows.WINAPI) i32;
// Unicode(-W): UTF-16LE のヌル終端バッファ([*c]const u16)を渡す。
proc WSAConnectByNameW(
    s: uint,  # SOCKET
    nodename: WideCString,  # LPWSTR
    servicename: WideCString,  # LPWSTR
    LocalAddressLength: ptr uint32,  # DWORD* optional, in/out
    LocalAddress: ptr SOCKADDR,  # SOCKADDR* optional, out
    RemoteAddressLength: ptr uint32,  # DWORD* optional, in/out
    RemoteAddress: ptr SOCKADDR,  # SOCKADDR* optional, out
    timeout: ptr TIMEVAL,  # TIMEVAL* optional
    Reserved: ptr OVERLAPPED  # OVERLAPPED* optional
): int32 {.importc: "WSAConnectByNameW", stdcall, dynlib: "WS2_32.dll".}
# Unicode(-W): WideCString は newWideCString("...") で生成。
pragma(lib, "ws2_32");
extern(Windows)
int WSAConnectByNameW(
    size_t s,   // SOCKET
    const(wchar)* nodename,   // LPWSTR
    const(wchar)* servicename,   // LPWSTR
    uint* LocalAddressLength,   // DWORD* optional, in/out
    SOCKADDR* LocalAddress,   // SOCKADDR* optional, out
    uint* RemoteAddressLength,   // DWORD* optional, in/out
    SOCKADDR* RemoteAddress,   // SOCKADDR* optional, out
    TIMEVAL* timeout,   // TIMEVAL* optional
    OVERLAPPED* Reserved   // OVERLAPPED* optional
);
ccall((:WSAConnectByNameW, "WS2_32.dll"), stdcall, Int32,
      (Csize_t, Cwstring, Cwstring, Ptr{UInt32}, Ptr{SOCKADDR}, Ptr{UInt32}, Ptr{SOCKADDR}, Ptr{TIMEVAL}, Ptr{OVERLAPPED}),
      s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
# s : SOCKET -> Csize_t
# nodename : LPWSTR -> Cwstring
# servicename : LPWSTR -> Cwstring
# LocalAddressLength : DWORD* optional, in/out -> Ptr{UInt32}
# LocalAddress : SOCKADDR* optional, out -> Ptr{SOCKADDR}
# RemoteAddressLength : DWORD* optional, in/out -> Ptr{UInt32}
# RemoteAddress : SOCKADDR* optional, out -> Ptr{SOCKADDR}
# timeout : TIMEVAL* optional -> Ptr{TIMEVAL}
# Reserved : OVERLAPPED* optional -> Ptr{OVERLAPPED}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
# Unicode(-W): Cwstring には transcode(UInt16, "...") 等で UTF-16 を渡す。
local ffi = require("ffi")
ffi.cdef[[
int32_t WSAConnectByNameW(
    uintptr_t s,
    const uint16_t* nodename,
    const uint16_t* servicename,
    uint32_t* LocalAddressLength,
    void* LocalAddress,
    uint32_t* RemoteAddressLength,
    void* RemoteAddress,
    void* timeout,
    void* Reserved);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.WSAConnectByNameW(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
-- s : SOCKET
-- nodename : LPWSTR
-- servicename : LPWSTR
-- LocalAddressLength : DWORD* optional, in/out
-- LocalAddress : SOCKADDR* optional, out
-- RemoteAddressLength : DWORD* optional, in/out
-- RemoteAddress : SOCKADDR* optional, out
-- timeout : TIMEVAL* optional
-- Reserved : OVERLAPPED* optional
-- 構造体/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 WSAConnectByNameW = lib.func('__stdcall', 'WSAConnectByNameW', 'int32_t', ['uintptr_t', 'str16', 'str16', 'uint32_t *', 'void *', 'uint32_t *', 'void *', 'void *', 'void *']);
// WSAConnectByNameW(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
// s : SOCKET -> 'uintptr_t'
// nodename : LPWSTR -> 'str16'
// servicename : LPWSTR -> 'str16'
// LocalAddressLength : DWORD* optional, in/out -> 'uint32_t *'
// LocalAddress : SOCKADDR* optional, out -> 'void *'
// RemoteAddressLength : DWORD* optional, in/out -> 'uint32_t *'
// RemoteAddress : SOCKADDR* optional, out -> 'void *'
// timeout : TIMEVAL* optional -> 'void *'
// Reserved : OVERLAPPED* optional -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("WS2_32.dll", {
  WSAConnectByNameW: { parameters: ["usize", "buffer", "buffer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.WSAConnectByNameW(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
// s : SOCKET -> "usize"
// nodename : LPWSTR -> "buffer"
// servicename : LPWSTR -> "buffer"
// LocalAddressLength : DWORD* optional, in/out -> "pointer"
// LocalAddress : SOCKADDR* optional, out -> "pointer"
// RemoteAddressLength : DWORD* optional, in/out -> "pointer"
// RemoteAddress : SOCKADDR* optional, out -> "pointer"
// timeout : TIMEVAL* optional -> "pointer"
// Reserved : OVERLAPPED* optional -> "pointer"
// 文字列は "buffer"。Unicode(-W) は new TextEncoder() ではなく UTF-16LE のバイト列(末尾に \x00\x00)を Uint8Array で渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t WSAConnectByNameW(
    size_t s,
    const uint16_t* nodename,
    const uint16_t* servicename,
    uint32_t* LocalAddressLength,
    void* LocalAddress,
    uint32_t* RemoteAddressLength,
    void* RemoteAddress,
    void* timeout,
    void* Reserved);
C, "WS2_32.dll");
// $ffi->WSAConnectByNameW(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved);
// s : SOCKET
// nodename : LPWSTR
// servicename : LPWSTR
// LocalAddressLength : DWORD* optional, in/out
// LocalAddress : SOCKADDR* optional, out
// RemoteAddressLength : DWORD* optional, in/out
// RemoteAddress : SOCKADDR* optional, out
// timeout : TIMEVAL* optional
// Reserved : OVERLAPPED* optional
// 構造体/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);
    boolean WSAConnectByNameW(
        long s,   // SOCKET
        WString nodename,   // LPWSTR
        WString servicename,   // LPWSTR
        IntByReference LocalAddressLength,   // DWORD* optional, in/out
        Pointer LocalAddress,   // SOCKADDR* optional, out
        IntByReference RemoteAddressLength,   // DWORD* optional, in/out
        Pointer RemoteAddress,   // SOCKADDR* optional, out
        Pointer timeout,   // TIMEVAL* optional
        Pointer Reserved   // OVERLAPPED* optional
    );
}
// Unicode(-W): WString(入力)/char[](出力)で UTF-16 をマーシャリング。
@[Link("ws2_32")]
lib LibWS2_32
  fun WSAConnectByNameW = WSAConnectByNameW(
    s : LibC::SizeT,   # SOCKET
    nodename : UInt16*,   # LPWSTR
    servicename : UInt16*,   # LPWSTR
    LocalAddressLength : UInt32*,   # DWORD* optional, in/out
    LocalAddress : SOCKADDR*,   # SOCKADDR* optional, out
    RemoteAddressLength : UInt32*,   # DWORD* optional, in/out
    RemoteAddress : SOCKADDR*,   # SOCKADDR* optional, out
    timeout : TIMEVAL*,   # TIMEVAL* optional
    Reserved : OVERLAPPED*   # OVERLAPPED* optional
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef WSAConnectByNameWNative = Int32 Function(UintPtr, Pointer<Utf16>, Pointer<Utf16>, Pointer<Uint32>, Pointer<Void>, Pointer<Uint32>, Pointer<Void>, Pointer<Void>, Pointer<Void>);
typedef WSAConnectByNameWDart = int Function(int, Pointer<Utf16>, Pointer<Utf16>, Pointer<Uint32>, Pointer<Void>, Pointer<Uint32>, Pointer<Void>, Pointer<Void>, Pointer<Void>);
final WSAConnectByNameW = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<WSAConnectByNameWNative, WSAConnectByNameWDart>('WSAConnectByNameW');
// s : SOCKET -> UintPtr
// nodename : LPWSTR -> Pointer<Utf16>
// servicename : LPWSTR -> Pointer<Utf16>
// LocalAddressLength : DWORD* optional, in/out -> Pointer<Uint32>
// LocalAddress : SOCKADDR* optional, out -> Pointer<Void>
// RemoteAddressLength : DWORD* optional, in/out -> Pointer<Uint32>
// RemoteAddress : SOCKADDR* optional, out -> Pointer<Void>
// timeout : TIMEVAL* optional -> Pointer<Void>
// Reserved : OVERLAPPED* optional -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function WSAConnectByNameW(
  s: NativeUInt;   // SOCKET
  nodename: PWideChar;   // LPWSTR
  servicename: PWideChar;   // LPWSTR
  LocalAddressLength: Pointer;   // DWORD* optional, in/out
  LocalAddress: Pointer;   // SOCKADDR* optional, out
  RemoteAddressLength: Pointer;   // DWORD* optional, in/out
  RemoteAddress: Pointer;   // SOCKADDR* optional, out
  timeout: Pointer;   // TIMEVAL* optional
  Reserved: Pointer   // OVERLAPPED* optional
): BOOL; stdcall;
  external 'WS2_32.dll' name 'WSAConnectByNameW';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "WSAConnectByNameW"
  c_WSAConnectByNameW :: CUIntPtr -> CWString -> CWString -> Ptr Word32 -> Ptr () -> Ptr Word32 -> Ptr () -> Ptr () -> Ptr () -> IO CInt
-- s : SOCKET -> CUIntPtr
-- nodename : LPWSTR -> CWString
-- servicename : LPWSTR -> CWString
-- LocalAddressLength : DWORD* optional, in/out -> Ptr Word32
-- LocalAddress : SOCKADDR* optional, out -> Ptr ()
-- RemoteAddressLength : DWORD* optional, in/out -> Ptr Word32
-- RemoteAddress : SOCKADDR* optional, out -> Ptr ()
-- timeout : TIMEVAL* optional -> Ptr ()
-- Reserved : OVERLAPPED* optional -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let wsaconnectbynamew =
  foreign "WSAConnectByNameW"
    (size_t @-> (ptr uint16_t) @-> (ptr uint16_t) @-> (ptr uint32_t) @-> (ptr void) @-> (ptr uint32_t) @-> (ptr void) @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* s : SOCKET -> size_t *)
(* nodename : LPWSTR -> (ptr uint16_t) *)
(* servicename : LPWSTR -> (ptr uint16_t) *)
(* LocalAddressLength : DWORD* optional, in/out -> (ptr uint32_t) *)
(* LocalAddress : SOCKADDR* optional, out -> (ptr void) *)
(* RemoteAddressLength : DWORD* optional, in/out -> (ptr uint32_t) *)
(* RemoteAddress : SOCKADDR* optional, out -> (ptr void) *)
(* timeout : TIMEVAL* optional -> (ptr void) *)
(* Reserved : OVERLAPPED* optional -> (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 ("WSAConnectByNameW" wsaconnect-by-name-w :convention :stdcall) :int32
  (s :uint64)   ; SOCKET
  (nodename (:string :encoding :utf-16le))   ; LPWSTR
  (servicename (:string :encoding :utf-16le))   ; LPWSTR
  (local-address-length :pointer)   ; DWORD* optional, in/out
  (local-address :pointer)   ; SOCKADDR* optional, out
  (remote-address-length :pointer)   ; DWORD* optional, in/out
  (remote-address :pointer)   ; SOCKADDR* optional, out
  (timeout :pointer)   ; TIMEVAL* optional
  (reserved :pointer))   ; OVERLAPPED* optional
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $WSAConnectByNameW = Win32::API::More->new('WS2_32',
    'BOOL WSAConnectByNameW(WPARAM s, LPCWSTR nodename, LPCWSTR servicename, LPVOID LocalAddressLength, LPVOID LocalAddress, LPVOID RemoteAddressLength, LPVOID RemoteAddress, LPVOID timeout, LPVOID Reserved)');
# my $ret = $WSAConnectByNameW->Call($s, $nodename, $servicename, $LocalAddressLength, $LocalAddress, $RemoteAddressLength, $RemoteAddress, $timeout, $Reserved);
# s : SOCKET -> WPARAM
# nodename : LPWSTR -> LPCWSTR
# servicename : LPWSTR -> LPCWSTR
# LocalAddressLength : DWORD* optional, in/out -> LPVOID
# LocalAddress : SOCKADDR* optional, out -> LPVOID
# RemoteAddressLength : DWORD* optional, in/out -> LPVOID
# RemoteAddress : SOCKADDR* optional, out -> LPVOID
# timeout : TIMEVAL* optional -> LPVOID
# Reserved : OVERLAPPED* optional -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# Unicode(-W): LPCWSTR/LPWSTR は Win32::API が UTF-16 変換を行う。

関連項目

文字セット違い
公式の関連項目
使用する型