diff --git a/PInvoke/Ws2_32/WinSock2.WSA.cs b/PInvoke/Ws2_32/WinSock2.WSA.cs
index ead28249..2f23c7a1 100644
--- a/PInvoke/Ws2_32/WinSock2.WSA.cs
+++ b/PInvoke/Ws2_32/WinSock2.WSA.cs
@@ -4846,6 +4846,190 @@ namespace Vanara.PInvoke
[PInvokeData("winsock2.h", MSDNShortId = "038aeca6-d7b7-4f74-ac69-4536c2e5118b")]
public static extern Win32Error WSAIoctl(SOCKET s, uint dwIoControlCode, [In] IntPtr lpvInBuffer, uint cbInBuffer, [Out] IntPtr lpvOutBuffer, uint cbOutBuffer, out uint lpcbBytesReturned, [Optional] IntPtr lpOverlapped, [Optional] IntPtr lpCompletionRoutine);
+ /// The WSAIoctl function controls the mode of a socket.
+ /// A descriptor identifying a socket.
+ /// The control code of operation to perform.
+ /// The input value.
+ /// The output value.
+ ///
+ ///
+ /// Upon successful completion, the WSAIoctl returns zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific
+ /// error code can be retrieved by calling WSAGetLastError.
+ ///
+ ///
+ ///
+ /// Error code
+ /// Meaning
+ ///
+ /// -
+ /// WSAENETDOWN
+ /// The network subsystem has failed.
+ ///
+ /// -
+ /// WSAEFAULT
+ ///
+ /// The lpvInBuffer, lpvOutBuffer, lpcbBytesReturned, lpOverlapped, or lpCompletionRoutine parameter is not totally contained in a
+ /// valid part of the user address space, or the cbInBuffer or cbOutBuffer parameter is too small.
+ ///
+ ///
+ /// -
+ /// WSAEINVAL
+ ///
+ /// The dwIoControlCode parameter is not a valid command, or a specified input parameter is not acceptable, or the command is not
+ /// applicable to the type of socket specified.
+ ///
+ ///
+ /// -
+ /// WSAENOTSOCK
+ /// The descriptor s is not a socket.
+ ///
+ /// -
+ /// WSAEOPNOTSUPP
+ ///
+ /// The specified IOCTL command cannot be realized. (For example, the FLOWSPEC structures specified in SIO_SET_QOS or
+ /// SIO_SET_GROUP_QOS cannot be satisfied.)
+ ///
+ ///
+ /// -
+ /// WSAEWOULDBLOCK
+ /// The socket is marked as non-blocking and the requested operation would block.
+ ///
+ /// -
+ /// WSAENOPROTOOPT
+ ///
+ /// The socket option is not supported on the specified protocol. For example, an attempt to use the SIO_GET_BROADCAST_ADDRESS IOCTL
+ /// was made on an IPv6 socket or an attempt to use the TCP SIO_KEEPALIVE_VALS IOCTL was made on a datagram socket.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// The WSAIoctl function is used to set or retrieve operating parameters associated with the socket, the transport protocol,
+ /// or the communications subsystem.
+ ///
+ ///
+ /// If both lpOverlapped and lpCompletionRoutine are NULL, the socket in this function will be treated as a non-overlapped
+ /// socket. For a non-overlapped socket, lpOverlapped and lpCompletionRoutine parameters are ignored, which causes the function to
+ /// behave like the standard ioctlsocket function except that the function can block if socket s is in blocking mode. If socket s is
+ /// in non-blocking mode, this function can return WSAEWOULDBLOCK when the specified operation cannot be finished immediately. In
+ /// this case, the application may change the socket to blocking mode and reissue the request or wait for the corresponding network
+ /// event (such as FD_ROUTING_INTERFACE_CHANGE or FD_ADDRESS_LIST_CHANGE in the case of SIO_ROUTING_INTERFACE_CHANGE or
+ /// SIO_ADDRESS_LIST_CHANGE) using a Windows message (using WSAAsyncSelect)-based or event (using WSAEventSelect)-based
+ /// notification mechanism.
+ ///
+ ///
+ /// Any IOCTL may block indefinitely, depending on the service provider's implementation. If the application cannot tolerate
+ /// blocking in a WSAIoctl call, overlapped I/O would be advised for IOCTLs that are especially likely to block including:
+ ///
+ /// 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
+ ///
+ /// Some protocol-specific IOCTLs may also be especially likely to block. Check the relevant protocol-specific annex for any
+ /// available information.
+ ///
+ ///
+ /// It is possible to adopt an encoding scheme that preserves the currently defined ioctlsocket opcodes while providing a convenient
+ /// way to partition the opcode identifier space in as much as the dwIoControlCode parameter is now a 32-bit entity. The
+ /// dwIoControlCode parameter is built to allow for protocol and vendor independence when adding new control codes while retaining
+ /// backward compatibility with the Windows Sockets 1.1 and Unix control codes. The dwIoControlCode parameter has the following form.
+ ///
+ ///
+ ///
+ /// I
+ /// O
+ /// V
+ /// T
+ /// Vendor/address family
+ /// Code
+ ///
+ /// -
+ /// 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
+ ///
+ ///
+ ///
+ /// Note The bits in dwIoControlCode parameter displayed in the table must be read vertically from top to bottom by column.
+ /// So the left-most bit is bit 31, the next bit is bit 30, and the right-most bit is bit 0.
+ ///
+ /// I is set if the input buffer is valid for the code, as with IOC_IN.
+ ///
+ /// O is set if the output buffer is valid for the code, as with IOC_OUT. Control codes using both input and output buffers
+ /// set both I and O.
+ ///
+ /// V is set if there are no parameters for the code, as with IOC_VOID.
+ /// T is a 2-bit quantity that defines the type of the IOCTL. The following values are defined:
+ /// 0 The IOCTL is a standard Unix IOCTL code, as with FIONREAD and FIONBIO.
+ /// 1 The IOCTL is a generic Windows Sockets 2 IOCTL code. New IOCTL codes defined for Windows Sockets 2 will have T == 1.
+ /// 2 The IOCTL applies only to a specific address family.
+ ///
+ /// 3 The IOCTL applies only to a specific vendor's provider, as with IOC_VENDOR. This type allows companies to be assigned a
+ /// vendor number that appears in the Vendor/Address family parameter. Then, the vendor can define new IOCTLs specific to
+ /// that vendor without having to register the IOCTL with a clearinghouse, thereby providing vendor flexibility and privacy.
+ ///
+ ///
+ /// Vendor/Address family An 11-bit quantity that defines the vendor who owns the code (if T == 3) or that contains the
+ /// address family to which the code applies (if T == 2). If this is a Unix IOCTL code (T == 0) then this parameter has the same
+ /// value as the code on Unix. If this is a generic Windows Sockets 2 IOCTL (T == 1) then this parameter can be used as an extension
+ /// of the code parameter to provide additional code values.
+ ///
+ /// Code The 16-bit quantity that contains the specific IOCTL code for the operation.
+ /// The following Unix IOCTL codes (commands) are supported.
+ /// The following Windows Sockets 2 commands are supported.
+ ///
+ /// Note All I/O initiated by a given thread is canceled when that thread exits. For overlapped sockets, pending asynchronous
+ /// operations can fail if the thread is closed before the operations complete. See ExitThread for more information.
+ ///
+ /// Compatibility
+ ///
+ /// The IOCTL codes with T == 0 are a subset of the IOCTL codes used in Berkeley sockets. In particular, there is no command that is
+ /// equivalent to FIOASYNC.
+ ///
+ ///
+ /// Note Some IOCTL codes require additional header files. For example, use of the SIO_RCVALL IOCTL requires the
+ /// Mstcpip.h header file.
+ ///
+ /// Windows Phone 8: This function is supported for Windows Phone Store apps on Windows Phone 8 and later.
+ ///
+ /// Windows 8.1 and Windows Server 2012 R2: This function is supported for Windows Store apps on Windows 8.1, Windows
+ /// Server 2012 R2, and later.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-wsaioctl int WSAAPI WSAIoctl( SOCKET s, DWORD
+ // dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned,
+ // LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );
+ [PInvokeData("winsock2.h", MSDNShortId = "038aeca6-d7b7-4f74-ac69-4536c2e5118b")]
+ public static Win32Error WSAIoctl(SOCKET s, uint dwIoControlCode, TIn inVal, out TOut outVal) where TIn : struct where TOut : struct
+ {
+ using SafeHGlobalHandle ptrIn = SafeHGlobalHandle.CreateFromStructure(inVal), ptrOut = SafeHGlobalHandle.CreateFromStructure();
+ var ret = WSAIoctl(s, dwIoControlCode, ptrIn, ptrIn.Size, ptrOut, ptrOut.Size, out var bRet);
+ if (ret == Win32Error.ERROR_INSUFFICIENT_BUFFER)
+ {
+ ptrOut.Size = bRet;
+ ret = WSAIoctl(s, dwIoControlCode, ptrIn, ptrIn.Size, ptrOut, ptrOut.Size, out bRet);
+ }
+ outVal = ret.Succeeded ? ptrOut.ToStructure() : default;
+ return ret;
+ }
+
///
/// The WSAJoinLeaf function joins a leaf node into a multipoint session, exchanges connect data, and specifies needed
/// quality of service based on the specified FLOWSPEC structures.
@@ -10806,7 +10990,7 @@ namespace Vanara.PInvoke
}
/// Provides a for that is disposed using .
- public class SafeWSAEVENT : SafeHANDLE
+ public class SafeWSAEVENT : SafeHANDLE, ISyncHandle
{
/// Initializes a new instance of the class and assigns an existing handle.
/// An object that represents the pre-existing handle to use.