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

WSAIoctl

関数
ソケットに対する制御操作を実行する。
DLLWS2_32.dll呼出規約winapiSetLastErrorあり対応OSWindows 8.1 以降

シグネチャ

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

INT WSAIoctl(
    SOCKET s,
    DWORD dwIoControlCode,
    void* lpvInBuffer,   // optional
    DWORD cbInBuffer,
    void* lpvOutBuffer,   // optional
    DWORD cbOutBuffer,
    DWORD* lpcbBytesReturned,
    OVERLAPPED* lpOverlapped,   // optional
    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine   // optional
);

パラメーター

名前方向説明
sSOCKETinソケットを識別するディスクリプタです。
dwIoControlCodeDWORDin実行する操作の制御コードです。Winsock IOCTLs を参照してください。
lpvInBuffervoid*inoptional入力バッファへのポインタです。
cbInBufferDWORDin入力バッファのサイズ(バイト単位)です。
lpvOutBuffervoid*outoptional出力バッファへのポインタです。
cbOutBufferDWORDin出力バッファのサイズ(バイト単位)です。
lpcbBytesReturnedDWORD*out実際の出力バイト数へのポインタです。
lpOverlappedOVERLAPPED*inoutoptionalWSAOVERLAPPED 構造体へのポインタです(非オーバーラップソケットでは無視されます)。
lpCompletionRoutineLPWSAOVERLAPPED_COMPLETION_ROUTINEinoptional
注意 操作が完了したときに呼び出される完了ルーチンへのポインタです(非オーバーラップソケットでは無視されます)。「解説」を参照してください。

戻り値の型: INT

公式ドキュメント

WSAIoctl 関数は、ソケットのモードを制御します。

戻り値

正常に完了すると、 WSAIoctl はゼロを返します。それ以外の場合は SOCKET_ERROR が返され、 WSAGetLastError を呼び出すことで具体的なエラーコードを取得できます。

エラーコード 意味
WSA_IO_PENDING
オーバーラップ操作が正常に開始され、後で完了が通知されます。
WSAENETDOWN
ネットワークサブシステムが失敗しました。
WSAEFAULT
lpvInBufferlpvOutBufferlpcbBytesReturnedlpOverlapped、または lpCompletionRoutine パラメーターが、ユーザーアドレス空間の有効な部分に完全に含まれていないか、cbInBuffer または cbOutBuffer パラメーターが小さすぎます。
WSAEINVAL
dwIoControlCode パラメーターが有効なコマンドではないか、指定された入力パラメーターが受け入れられないか、コマンドが指定されたソケットの種類に適用できません。
WSAEINPROGRESS
コールバックの進行中に関数が呼び出されました。
WSAENOTSOCK
ディスクリプタ s はソケットではありません。
WSAEOPNOTSUPP
指定された IOCTL コマンドを実行できません。(たとえば、SIO_SET_QOS または SIO_SET_GROUP_QOS で指定された FLOWSPEC 構造体を満たすことができない場合などです。)
WSAEWOULDBLOCK
ソケットが非ブロッキングとしてマークされており、要求された操作はブロックします。
WSAENOPROTOOPT
指定されたプロトコルではソケットオプションがサポートされていません。たとえば、IPv6 ソケットで SIO_GET_BROADCAST_ADDRESS IOCTL を使用しようとした場合や、データグラムソケットで TCP の SIO_KEEPALIVE_VALS IOCTL を使用しようとした場合などです。

解説(Remarks)

WSAIoctl 関数は、ソケット、トランスポートプロトコル、または通信サブシステムに関連する動作パラメーターを設定または取得するために使用されます。

lpOverlappedlpCompletionRoutine の両方が NULL の場合、この関数のソケットは非オーバーラップソケットとして扱われます。非オーバーラップソケットの場合、lpOverlapped および lpCompletionRoutine パラメーターは無視され、関数は標準の ioctlsocket 関数と同様に動作しますが、ソケット s がブロッキングモードの場合は関数がブロックすることがあります。ソケット s が非ブロッキングモードの場合、指定された操作を即座に完了できないときにこの関数は WSAEWOULDBLOCK を返すことがあります。この場合、アプリケーションはソケットをブロッキングモードに変更して要求を再発行するか、Windows メッセージベース( WSAAsyncSelect を使用)またはイベントベース( WSAEventSelect を使用)の通知メカニズムを用いて、対応するネットワークイベント(SIO_ROUTING_INTERFACE_CHANGESIO_ADDRESS_LIST_CHANGE の場合の FD_ROUTING_INTERFACE_CHANGE や FD_ADDRESS_LIST_CHANGE など)を待つことができます。

オーバーラップソケットの場合、即座に完了できない操作は開始され、後で完了が通知されます。lpcbBytesReturned パラメーターが指す DWORD 値は無視してかまいません。操作が完了して適切な完了メソッドがシグナル状態になったときに、最終的な完了ステータスと返されたバイト数を取得できます。

IOCTL は、サービスプロバイダーの実装によっては無期限にブロックする可能性があります。アプリケーションが WSAIoctl 呼び出しでのブロックを許容できない場合、特にブロックする可能性が高い次の IOCTL についてはオーバーラップ I/O の使用が推奨されます。

SIO_ADDRESS_LIST_CHANGE

SIO_FINDROUTE

SIO_FLUSH

SIO_GET_QOS

SIO_GET_GROUP_QOS

SIO_ROUTING_INTERFACE_CHANGE

SIO_SET_QOS

SIO_SET_GROUP_QOS

一部のプロトコル固有の IOCTL も、特にブロックする可能性があります。利用可能な情報については、該当するプロトコル固有の付録を確認してください。

lpCompletionRoutine パラメーターが指す完了ルーチンのプロトタイプは次のとおりです。

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

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

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


void CALLBACK CompletionRoutine (
  IN DWORD dwError,
  IN DWORD cbTransferred,
  IN LPWSAOVERLAPPED lpOverlapped,
  IN DWORD dwFlags 
);

CompletionRoutine は、アプリケーションが指定する関数名のプレースホルダーです。dwError パラメーターは、lpOverlapped パラメーターで示されるオーバーラップ操作の完了ステータスを指定します。cbTransferred パラメーターは、受信したバイト数を指定します。dwFlags パラメーターは、この IOCTL では使用されません。完了ルーチンは値を返しません。

dwIoControlCode パラメーターは現在 32 ビットの実体となっているため、現在定義されている ioctlsocket のオペコードを保持しつつ、オペコード識別子空間を分割する便利な方法を提供するエンコード方式を採用できます。dwIoControlCode パラメーターは、新しい制御コードを追加する際にプロトコルやベンダーに依存しないようにしつつ、Windows Sockets 1.1 および Unix の制御コードとの後方互換性を保つように構成されています。dwIoControlCode パラメーターは次の形式を持ちます。

I O V T ベンダー/アドレスファミリ コード
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
注意 表に表示されている dwIoControlCode パラメーターのビットは、列ごとに上から下へ縦に読む必要があります。したがって、最も左のビットがビット 31、次のビットがビット 30、最も右のビットがビット 0 です。
I は、IOC_IN と同様に、入力バッファがコードに対して有効な場合に設定されます。

O は、IOC_OUT と同様に、出力バッファがコードに対して有効な場合に設定されます。入力バッファと出力バッファの両方を使用する制御コードは、I と O の両方を設定します。

V は、IOC_VOID と同様に、コードにパラメーターがない場合に設定されます。

T は、IOCTL の種類を定義する 2 ビットの量です。次の値が定義されています。

0 IOCTL は、FIONREADFIONBIO と同様に、標準的な Unix IOCTL コードです。

1 IOCTL は、汎用の Windows Sockets 2 IOCTL コードです。Windows Sockets 2 用に新しく定義された IOCTL コードは T == 1 になります。

2 IOCTL は、特定のアドレスファミリにのみ適用されます。

3 IOCTL は、IOC_VENDOR と同様に、特定のベンダーのプロバイダーにのみ適用されます。この種類により、各社に ベンダー/アドレスファミリ パラメーターに現れるベンダー番号を割り当てることができます。これにより、ベンダーは IOCTL をクリアリングハウスに登録することなく、そのベンダー固有の新しい IOCTL を定義でき、ベンダーの柔軟性とプライバシーが提供されます。

ベンダー/アドレスファミリ コードを所有するベンダー(T == 3 の場合)を定義するか、コードが適用されるアドレスファミリ(T == 2 の場合)を含む 11 ビットの量です。これが Unix IOCTL コード(T == 0)の場合、このパラメーターは Unix 上のコードと同じ値を持ちます。これが汎用の Windows Sockets 2 IOCTL(T == 1)の場合、このパラメーターはコードパラメーターの拡張として使用し、追加のコード値を提供できます。

コード 操作に対する具体的な IOCTL コードを含む 16 ビットの量です。

次の Unix IOCTL コード(コマンド)がサポートされています。

次の Windows Sockets 2 コマンドがサポートされています。

オーバーラップ操作が即座に完了した場合、 WSAIoctl はゼロを返し、lpcbBytesReturned パラメーターは出力バッファ内のバイト数で更新されます。オーバーラップ操作が正常に開始され、後で完了する場合、この関数は SOCKET_ERROR を返し、エラーコード WSA_IO_PENDING を示します。この場合、lpcbBytesReturned は更新されません。オーバーラップ操作が完了すると、出力バッファ内のデータ量は、完了ルーチンの cbTransferred パラメーター(指定されている場合)を通じて、または WSAGetOverlappedResultlpcbTransfer パラメーターを通じて示されます。

オーバーラップソケットで呼び出された場合、lpOverlapped パラメーターはオーバーラップ操作の期間中、有効である必要があります。lpOverlapped パラメーターには WSAOVERLAPPED 構造体のアドレスが含まれます。

lpCompletionRoutine パラメーターが NULL の場合、lpOverlappedhEvent パラメーターが有効なイベントオブジェクトハンドルを含んでいれば、オーバーラップ操作の完了時にシグナル状態になります。アプリケーションは WSAWaitForMultipleEvents または WSAGetOverlappedResult を使用して、イベントオブジェクトを待機またはポーリングできます。

注意 指定されたスレッドによって開始されたすべての I/O は、そのスレッドが終了するとキャンセルされます。オーバーラップソケットの場合、操作が完了する前にスレッドが閉じられると、保留中の非同期操作が失敗することがあります。詳細については ExitThread を参照してください。
lpCompletionRoutineNULL でない場合、hEvent パラメーターは無視され、アプリケーションが完了ルーチンにコンテキスト情報を渡すために使用できます。NULL でない lpCompletionRoutine を渡し、後で同じオーバーラップ I/O 要求に対して WSAGetOverlappedResult を呼び出す呼び出し元は、その WSAGetOverlappedResult の呼び出しで fWait パラメーターを TRUE に設定してはなりません。この場合、hEvent パラメーターの使用は未定義であり、hEvent パラメーターでの待機を試みると予測できない結果になります。

完了ルーチンのプロトタイプは次のとおりです。


void CALLBACK CompletionRoutine(
  IN DWORD dwError, 
  IN DWORD cbTransferred, 
  IN LPWSAOVERLAPPED lpOverlapped, 
  IN DWORD dwFlags 
);

この CompletionRoutine は、アプリケーション定義またはライブラリ定義の関数のプレースホルダーです。完了ルーチンは、スレッドがアラート可能な状態にある場合にのみ呼び出されます。スレッドをアラート可能な状態にするには、fAlertable または bAlertable パラメーターを TRUE に設定して、WSAWaitForMultipleEventsWaitForSingleObjectEx、または WaitForMultipleObjectsEx 関数を使用します。

CompletionRoutinedwError パラメーターは、lpOverlapped で示されるオーバーラップ操作の完了ステータスを指定します。cbTransferred パラメーターは、返されたバイト数を指定します。現在、フラグ値は定義されておらず、dwFlags はゼロになります。CompletionRoutine 関数は値を返しません。

この関数から戻ると、このソケットに対する別の保留中の完了ルーチンを呼び出せるようになります。完了ルーチンは任意の順序で呼び出される可能性があり、必ずしもオーバーラップ操作が完了したのと同じ順序とは限りません。

互換性

T == 0 の IOCTL コードは、Berkeley ソケットで使用される IOCTL コードのサブセットです。特に、FIOASYNC に相当するコマンドはありません。
注意 一部の IOCTL コードには追加のヘッダーファイルが必要です。たとえば、SIO_RCVALL IOCTL を使用するには Mstcpip.h ヘッダーファイルが必要です。
Windows Phone 8: この関数は、Windows Phone 8 以降の Windows Phone ストアアプリでサポートされています。

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

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

各言語での呼び出し定義

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

INT WSAIoctl(
    SOCKET s,
    DWORD dwIoControlCode,
    void* lpvInBuffer,   // optional
    DWORD cbInBuffer,
    void* lpvOutBuffer,   // optional
    DWORD cbOutBuffer,
    DWORD* lpcbBytesReturned,
    OVERLAPPED* lpOverlapped,   // optional
    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine   // optional
);
[DllImport("WS2_32.dll", SetLastError = true, ExactSpelling = true)]
static extern int WSAIoctl(
    UIntPtr s,   // SOCKET
    uint dwIoControlCode,   // DWORD
    IntPtr lpvInBuffer,   // void* optional
    uint cbInBuffer,   // DWORD
    IntPtr lpvOutBuffer,   // void* optional, out
    uint cbOutBuffer,   // DWORD
    out uint lpcbBytesReturned,   // DWORD* out
    IntPtr lpOverlapped,   // OVERLAPPED* optional, in/out
    IntPtr lpCompletionRoutine   // LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
);
<DllImport("WS2_32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function WSAIoctl(
    s As UIntPtr,   ' SOCKET
    dwIoControlCode As UInteger,   ' DWORD
    lpvInBuffer As IntPtr,   ' void* optional
    cbInBuffer As UInteger,   ' DWORD
    lpvOutBuffer As IntPtr,   ' void* optional, out
    cbOutBuffer As UInteger,   ' DWORD
    <Out> ByRef lpcbBytesReturned As UInteger,   ' DWORD* out
    lpOverlapped As IntPtr,   ' OVERLAPPED* optional, in/out
    lpCompletionRoutine As IntPtr   ' LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
) As Integer
End Function
' s : SOCKET
' dwIoControlCode : DWORD
' lpvInBuffer : void* optional
' cbInBuffer : DWORD
' lpvOutBuffer : void* optional, out
' cbOutBuffer : DWORD
' lpcbBytesReturned : DWORD* out
' lpOverlapped : OVERLAPPED* optional, in/out
' lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
Declare PtrSafe Function WSAIoctl Lib "ws2_32" ( _
    ByVal s As LongPtr, _
    ByVal dwIoControlCode As Long, _
    ByVal lpvInBuffer As LongPtr, _
    ByVal cbInBuffer As Long, _
    ByVal lpvOutBuffer As LongPtr, _
    ByVal cbOutBuffer As Long, _
    ByRef lpcbBytesReturned As Long, _
    ByVal lpOverlapped As LongPtr, _
    ByVal lpCompletionRoutine As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

WSAIoctl = ctypes.windll.ws2_32.WSAIoctl
WSAIoctl.restype = ctypes.c_int
WSAIoctl.argtypes = [
    ctypes.c_size_t,  # s : SOCKET
    wintypes.DWORD,  # dwIoControlCode : DWORD
    ctypes.POINTER(None),  # lpvInBuffer : void* optional
    wintypes.DWORD,  # cbInBuffer : DWORD
    ctypes.POINTER(None),  # lpvOutBuffer : void* optional, out
    wintypes.DWORD,  # cbOutBuffer : DWORD
    ctypes.POINTER(wintypes.DWORD),  # lpcbBytesReturned : DWORD* out
    ctypes.c_void_p,  # lpOverlapped : OVERLAPPED* optional, in/out
    ctypes.c_void_p,  # lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WS2_32.dll')
WSAIoctl = Fiddle::Function.new(
  lib['WSAIoctl'],
  [
    Fiddle::TYPE_UINTPTR_T,  # s : SOCKET
    -Fiddle::TYPE_INT,  # dwIoControlCode : DWORD
    Fiddle::TYPE_VOIDP,  # lpvInBuffer : void* optional
    -Fiddle::TYPE_INT,  # cbInBuffer : DWORD
    Fiddle::TYPE_VOIDP,  # lpvOutBuffer : void* optional, out
    -Fiddle::TYPE_INT,  # cbOutBuffer : DWORD
    Fiddle::TYPE_VOIDP,  # lpcbBytesReturned : DWORD* out
    Fiddle::TYPE_VOIDP,  # lpOverlapped : OVERLAPPED* optional, in/out
    Fiddle::TYPE_VOIDP,  # lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
  ],
  Fiddle::TYPE_INT)
#[link(name = "ws2_32")]
extern "system" {
    fn WSAIoctl(
        s: usize,  // SOCKET
        dwIoControlCode: u32,  // DWORD
        lpvInBuffer: *mut (),  // void* optional
        cbInBuffer: u32,  // DWORD
        lpvOutBuffer: *mut (),  // void* optional, out
        cbOutBuffer: u32,  // DWORD
        lpcbBytesReturned: *mut u32,  // DWORD* out
        lpOverlapped: *mut OVERLAPPED,  // OVERLAPPED* optional, in/out
        lpCompletionRoutine: *const core::ffi::c_void  // LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("WS2_32.dll", SetLastError = true)]
public static extern int WSAIoctl(UIntPtr s, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer, IntPtr lpvOutBuffer, uint cbOutBuffer, out uint lpcbBytesReturned, IntPtr lpOverlapped, IntPtr lpCompletionRoutine);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_WSAIoctl' -Namespace Win32 -PassThru
# $api::WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine)
#uselib "WS2_32.dll"
#func global WSAIoctl "WSAIoctl" sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr
; WSAIoctl s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, varptr(lpcbBytesReturned), varptr(lpOverlapped), lpCompletionRoutine   ; 戻り値は stat
; s : SOCKET -> "sptr"
; dwIoControlCode : DWORD -> "sptr"
; lpvInBuffer : void* optional -> "sptr"
; cbInBuffer : DWORD -> "sptr"
; lpvOutBuffer : void* optional, out -> "sptr"
; cbOutBuffer : DWORD -> "sptr"
; lpcbBytesReturned : DWORD* out -> "sptr"
; lpOverlapped : OVERLAPPED* optional, in/out -> "sptr"
; lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "WS2_32.dll"
#cfunc global WSAIoctl "WSAIoctl" sptr, int, sptr, int, sptr, int, var, var, sptr
; res = WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine)
; s : SOCKET -> "sptr"
; dwIoControlCode : DWORD -> "int"
; lpvInBuffer : void* optional -> "sptr"
; cbInBuffer : DWORD -> "int"
; lpvOutBuffer : void* optional, out -> "sptr"
; cbOutBuffer : DWORD -> "int"
; lpcbBytesReturned : DWORD* out -> "var"
; lpOverlapped : OVERLAPPED* optional, in/out -> "var"
; lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> "sptr"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; INT WSAIoctl(SOCKET s, DWORD dwIoControlCode, void* lpvInBuffer, DWORD cbInBuffer, void* lpvOutBuffer, DWORD cbOutBuffer, DWORD* lpcbBytesReturned, OVERLAPPED* lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
#uselib "WS2_32.dll"
#cfunc global WSAIoctl "WSAIoctl" intptr, int, intptr, int, intptr, int, var, var, intptr
; res = WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine)
; s : SOCKET -> "intptr"
; dwIoControlCode : DWORD -> "int"
; lpvInBuffer : void* optional -> "intptr"
; cbInBuffer : DWORD -> "int"
; lpvOutBuffer : void* optional, out -> "intptr"
; cbOutBuffer : DWORD -> "int"
; lpcbBytesReturned : DWORD* out -> "var"
; lpOverlapped : OVERLAPPED* optional, in/out -> "var"
; lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> "intptr"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procWSAIoctl = ws2_32.NewProc("WSAIoctl")
)

// s (SOCKET), dwIoControlCode (DWORD), lpvInBuffer (void* optional), cbInBuffer (DWORD), lpvOutBuffer (void* optional, out), cbOutBuffer (DWORD), lpcbBytesReturned (DWORD* out), lpOverlapped (OVERLAPPED* optional, in/out), lpCompletionRoutine (LPWSAOVERLAPPED_COMPLETION_ROUTINE optional)
r1, _, err := procWSAIoctl.Call(
	uintptr(s),
	uintptr(dwIoControlCode),
	uintptr(lpvInBuffer),
	uintptr(cbInBuffer),
	uintptr(lpvOutBuffer),
	uintptr(cbOutBuffer),
	uintptr(lpcbBytesReturned),
	uintptr(lpOverlapped),
	uintptr(lpCompletionRoutine),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // INT
function WSAIoctl(
  s: NativeUInt;   // SOCKET
  dwIoControlCode: DWORD;   // DWORD
  lpvInBuffer: Pointer;   // void* optional
  cbInBuffer: DWORD;   // DWORD
  lpvOutBuffer: Pointer;   // void* optional, out
  cbOutBuffer: DWORD;   // DWORD
  lpcbBytesReturned: Pointer;   // DWORD* out
  lpOverlapped: Pointer;   // OVERLAPPED* optional, in/out
  lpCompletionRoutine: Pointer   // LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
): Integer; stdcall;
  external 'WS2_32.dll' name 'WSAIoctl';
result := DllCall("WS2_32\WSAIoctl"
    , "UPtr", s   ; SOCKET
    , "UInt", dwIoControlCode   ; DWORD
    , "Ptr", lpvInBuffer   ; void* optional
    , "UInt", cbInBuffer   ; DWORD
    , "Ptr", lpvOutBuffer   ; void* optional, out
    , "UInt", cbOutBuffer   ; DWORD
    , "Ptr", lpcbBytesReturned   ; DWORD* out
    , "Ptr", lpOverlapped   ; OVERLAPPED* optional, in/out
    , "Ptr", lpCompletionRoutine   ; LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
    , "Int")   ; return: INT
●WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine) = DLL("WS2_32.dll", "int WSAIoctl(int, dword, void*, dword, void*, dword, void*, void*, void*)")
# 呼び出し: WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine)
# s : SOCKET -> "int"
# dwIoControlCode : DWORD -> "dword"
# lpvInBuffer : void* optional -> "void*"
# cbInBuffer : DWORD -> "dword"
# lpvOutBuffer : void* optional, out -> "void*"
# cbOutBuffer : DWORD -> "dword"
# lpcbBytesReturned : DWORD* out -> "void*"
# lpOverlapped : OVERLAPPED* optional, in/out -> "void*"
# lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "ws2_32" fn WSAIoctl(
    s: usize, // SOCKET
    dwIoControlCode: u32, // DWORD
    lpvInBuffer: ?*anyopaque, // void* optional
    cbInBuffer: u32, // DWORD
    lpvOutBuffer: ?*anyopaque, // void* optional, out
    cbOutBuffer: u32, // DWORD
    lpcbBytesReturned: [*c]u32, // DWORD* out
    lpOverlapped: [*c]OVERLAPPED, // OVERLAPPED* optional, in/out
    lpCompletionRoutine: ?*anyopaque // LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
) callconv(std.os.windows.WINAPI) i32;
proc WSAIoctl(
    s: uint,  # SOCKET
    dwIoControlCode: uint32,  # DWORD
    lpvInBuffer: pointer,  # void* optional
    cbInBuffer: uint32,  # DWORD
    lpvOutBuffer: pointer,  # void* optional, out
    cbOutBuffer: uint32,  # DWORD
    lpcbBytesReturned: ptr uint32,  # DWORD* out
    lpOverlapped: ptr OVERLAPPED,  # OVERLAPPED* optional, in/out
    lpCompletionRoutine: pointer  # LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
): int32 {.importc: "WSAIoctl", stdcall, dynlib: "WS2_32.dll".}
pragma(lib, "ws2_32");
extern(Windows)
int WSAIoctl(
    size_t s,   // SOCKET
    uint dwIoControlCode,   // DWORD
    void* lpvInBuffer,   // void* optional
    uint cbInBuffer,   // DWORD
    void* lpvOutBuffer,   // void* optional, out
    uint cbOutBuffer,   // DWORD
    uint* lpcbBytesReturned,   // DWORD* out
    OVERLAPPED* lpOverlapped,   // OVERLAPPED* optional, in/out
    void* lpCompletionRoutine   // LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
);
ccall((:WSAIoctl, "WS2_32.dll"), stdcall, Int32,
      (Csize_t, UInt32, Ptr{Cvoid}, UInt32, Ptr{Cvoid}, UInt32, Ptr{UInt32}, Ptr{OVERLAPPED}, Ptr{Cvoid}),
      s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine)
# s : SOCKET -> Csize_t
# dwIoControlCode : DWORD -> UInt32
# lpvInBuffer : void* optional -> Ptr{Cvoid}
# cbInBuffer : DWORD -> UInt32
# lpvOutBuffer : void* optional, out -> Ptr{Cvoid}
# cbOutBuffer : DWORD -> UInt32
# lpcbBytesReturned : DWORD* out -> Ptr{UInt32}
# lpOverlapped : OVERLAPPED* optional, in/out -> Ptr{OVERLAPPED}
# lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> Ptr{Cvoid}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t WSAIoctl(
    uintptr_t s,
    uint32_t dwIoControlCode,
    void* lpvInBuffer,
    uint32_t cbInBuffer,
    void* lpvOutBuffer,
    uint32_t cbOutBuffer,
    uint32_t* lpcbBytesReturned,
    void* lpOverlapped,
    void* lpCompletionRoutine);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine)
-- s : SOCKET
-- dwIoControlCode : DWORD
-- lpvInBuffer : void* optional
-- cbInBuffer : DWORD
-- lpvOutBuffer : void* optional, out
-- cbOutBuffer : DWORD
-- lpcbBytesReturned : DWORD* out
-- lpOverlapped : OVERLAPPED* optional, in/out
-- lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const WSAIoctl = lib.func('__stdcall', 'WSAIoctl', 'int32_t', ['uintptr_t', 'uint32_t', 'void *', 'uint32_t', 'void *', 'uint32_t', 'uint32_t *', 'void *', 'void *']);
// WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine)
// s : SOCKET -> 'uintptr_t'
// dwIoControlCode : DWORD -> 'uint32_t'
// lpvInBuffer : void* optional -> 'void *'
// cbInBuffer : DWORD -> 'uint32_t'
// lpvOutBuffer : void* optional, out -> 'void *'
// cbOutBuffer : DWORD -> 'uint32_t'
// lpcbBytesReturned : DWORD* out -> 'uint32_t *'
// lpOverlapped : OVERLAPPED* optional, in/out -> 'void *'
// lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
// コールバック(関数ポインタ)は koffi.proto/koffi.register で型を定義して渡す(素の void* では JS 関数を渡せない)。
const lib = Deno.dlopen("WS2_32.dll", {
  WSAIoctl: { parameters: ["usize", "u32", "pointer", "u32", "pointer", "u32", "pointer", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine)
// s : SOCKET -> "usize"
// dwIoControlCode : DWORD -> "u32"
// lpvInBuffer : void* optional -> "pointer"
// cbInBuffer : DWORD -> "u32"
// lpvOutBuffer : void* optional, out -> "pointer"
// cbOutBuffer : DWORD -> "u32"
// lpcbBytesReturned : DWORD* out -> "pointer"
// lpOverlapped : OVERLAPPED* optional, in/out -> "pointer"
// lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t WSAIoctl(
    size_t s,
    uint32_t dwIoControlCode,
    void* lpvInBuffer,
    uint32_t cbInBuffer,
    void* lpvOutBuffer,
    uint32_t cbOutBuffer,
    uint32_t* lpcbBytesReturned,
    void* lpOverlapped,
    void* lpCompletionRoutine);
C, "WS2_32.dll");
// $ffi->WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
// s : SOCKET
// dwIoControlCode : DWORD
// lpvInBuffer : void* optional
// cbInBuffer : DWORD
// lpvOutBuffer : void* optional, out
// cbOutBuffer : DWORD
// lpcbBytesReturned : DWORD* out
// lpOverlapped : OVERLAPPED* optional, in/out
// lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE 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);
    int WSAIoctl(
        long s,   // SOCKET
        int dwIoControlCode,   // DWORD
        Pointer lpvInBuffer,   // void* optional
        int cbInBuffer,   // DWORD
        Pointer lpvOutBuffer,   // void* optional, out
        int cbOutBuffer,   // DWORD
        IntByReference lpcbBytesReturned,   // DWORD* out
        Pointer lpOverlapped,   // OVERLAPPED* optional, in/out
        Callback lpCompletionRoutine   // LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
    );
}
@[Link("ws2_32")]
lib LibWS2_32
  fun WSAIoctl = WSAIoctl(
    s : LibC::SizeT,   # SOCKET
    dwIoControlCode : UInt32,   # DWORD
    lpvInBuffer : Void*,   # void* optional
    cbInBuffer : UInt32,   # DWORD
    lpvOutBuffer : Void*,   # void* optional, out
    cbOutBuffer : UInt32,   # DWORD
    lpcbBytesReturned : UInt32*,   # DWORD* out
    lpOverlapped : OVERLAPPED*,   # OVERLAPPED* optional, in/out
    lpCompletionRoutine : Void*   # LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef WSAIoctlNative = Int32 Function(UintPtr, Uint32, Pointer<Void>, Uint32, Pointer<Void>, Uint32, Pointer<Uint32>, Pointer<Void>, Pointer<Void>);
typedef WSAIoctlDart = int Function(int, int, Pointer<Void>, int, Pointer<Void>, int, Pointer<Uint32>, Pointer<Void>, Pointer<Void>);
final WSAIoctl = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<WSAIoctlNative, WSAIoctlDart>('WSAIoctl');
// s : SOCKET -> UintPtr
// dwIoControlCode : DWORD -> Uint32
// lpvInBuffer : void* optional -> Pointer<Void>
// cbInBuffer : DWORD -> Uint32
// lpvOutBuffer : void* optional, out -> Pointer<Void>
// cbOutBuffer : DWORD -> Uint32
// lpcbBytesReturned : DWORD* out -> Pointer<Uint32>
// lpOverlapped : OVERLAPPED* optional, in/out -> Pointer<Void>
// lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function WSAIoctl(
  s: NativeUInt;   // SOCKET
  dwIoControlCode: DWORD;   // DWORD
  lpvInBuffer: Pointer;   // void* optional
  cbInBuffer: DWORD;   // DWORD
  lpvOutBuffer: Pointer;   // void* optional, out
  cbOutBuffer: DWORD;   // DWORD
  lpcbBytesReturned: Pointer;   // DWORD* out
  lpOverlapped: Pointer;   // OVERLAPPED* optional, in/out
  lpCompletionRoutine: Pointer   // LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
): Integer; stdcall;
  external 'WS2_32.dll' name 'WSAIoctl';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "WSAIoctl"
  c_WSAIoctl :: CUIntPtr -> Word32 -> Ptr () -> Word32 -> Ptr () -> Word32 -> Ptr Word32 -> Ptr () -> Ptr () -> IO Int32
-- s : SOCKET -> CUIntPtr
-- dwIoControlCode : DWORD -> Word32
-- lpvInBuffer : void* optional -> Ptr ()
-- cbInBuffer : DWORD -> Word32
-- lpvOutBuffer : void* optional, out -> Ptr ()
-- cbOutBuffer : DWORD -> Word32
-- lpcbBytesReturned : DWORD* out -> Ptr Word32
-- lpOverlapped : OVERLAPPED* optional, in/out -> Ptr ()
-- lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let wsaioctl =
  foreign "WSAIoctl"
    (size_t @-> uint32_t @-> (ptr void) @-> uint32_t @-> (ptr void) @-> uint32_t @-> (ptr uint32_t) @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* s : SOCKET -> size_t *)
(* dwIoControlCode : DWORD -> uint32_t *)
(* lpvInBuffer : void* optional -> (ptr void) *)
(* cbInBuffer : DWORD -> uint32_t *)
(* lpvOutBuffer : void* optional, out -> (ptr void) *)
(* cbOutBuffer : DWORD -> uint32_t *)
(* lpcbBytesReturned : DWORD* out -> (ptr uint32_t) *)
(* lpOverlapped : OVERLAPPED* optional, in/out -> (ptr void) *)
(* lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE 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 ("WSAIoctl" wsaioctl :convention :stdcall) :int32
  (s :uint64)   ; SOCKET
  (dw-io-control-code :uint32)   ; DWORD
  (lpv-in-buffer :pointer)   ; void* optional
  (cb-in-buffer :uint32)   ; DWORD
  (lpv-out-buffer :pointer)   ; void* optional, out
  (cb-out-buffer :uint32)   ; DWORD
  (lpcb-bytes-returned :pointer)   ; DWORD* out
  (lp-overlapped :pointer)   ; OVERLAPPED* optional, in/out
  (lp-completion-routine :pointer))   ; LPWSAOVERLAPPED_COMPLETION_ROUTINE optional
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $WSAIoctl = Win32::API::More->new('WS2_32',
    'int WSAIoctl(WPARAM s, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPVOID lpcbBytesReturned, LPVOID lpOverlapped, LPVOID lpCompletionRoutine)');
# my $ret = $WSAIoctl->Call($s, $dwIoControlCode, $lpvInBuffer, $cbInBuffer, $lpvOutBuffer, $cbOutBuffer, $lpcbBytesReturned, $lpOverlapped, $lpCompletionRoutine);
# s : SOCKET -> WPARAM
# dwIoControlCode : DWORD -> DWORD
# lpvInBuffer : void* optional -> LPVOID
# cbInBuffer : DWORD -> DWORD
# lpvOutBuffer : void* optional, out -> LPVOID
# cbOutBuffer : DWORD -> DWORD
# lpcbBytesReturned : DWORD* out -> LPVOID
# lpOverlapped : OVERLAPPED* optional, in/out -> LPVOID
# lpCompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE optional -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# コールバック(関数ポインタ)は Perl sub を直接渡せません。Win32::API::Callback を使用してください。

関連項目

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