From 46f90a281876b7fb7eed5da264fa3321a23092e0 Mon Sep 17 00:00:00 2001 From: dahall Date: Tue, 5 Jul 2022 20:20:41 -0600 Subject: [PATCH] Added WSAIoctl generic overload and ISyncHandle to WSAEVENT --- PInvoke/Ws2_32/WinSock2.WSA.cs | 186 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 185 insertions(+), 1 deletion(-) 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.