diff --git a/PInvoke/Ws2_32/ws2def.cs b/PInvoke/Ws2_32/ws2def.cs index f4de079d..b8ac78a0 100644 --- a/PInvoke/Ws2_32/ws2def.cs +++ b/PInvoke/Ws2_32/ws2def.cs @@ -1290,6 +1290,49 @@ namespace Vanara.PInvoke } } + /// The SOCKADDR_IN structure specifies a transport address and port for the AF_INET address family. + /// + /// All of the data in the SOCKADDR_IN structure, except for the address family, must be specified in network-byte-order (big-endian). + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-sockaddr_in typedef struct sockaddr_in { #if ... short + // sin_family; #else ADDRESS_FAMILY sin_family; #endif USHORT sin_port; IN_ADDR sin_addr; CHAR sin_zero[8]; } SOCKADDR_IN, *PSOCKADDR_IN; + [PInvokeData("ws2def.h", MSDNShortId = "96379562-403f-451c-ac7a-f0eec34bfe5e")] + [StructLayout(LayoutKind.Sequential, Pack = 2)] + public struct SOCKADDR_IN + { + /// The address family for the transport address. This member should always be set to AF_INET. + public ADDRESS_FAMILY sin_family; + + /// A transport protocol port number. + public ushort sin_port; + + /// An IN_ADDR structure that contains an IPv4 transport address. + public IN_ADDR sin_addr; + + /// Reserved for system use. A WSK application should set the contents of this array to zero. + public ulong sin_zero; + + /// Initializes a new instance of the struct. + /// An IN_ADDR structure that contains an IPv4 transport address. + /// A transport protocol port number. + public SOCKADDR_IN(IN_ADDR addr, ushort port = 0) + { + sin_family = ADDRESS_FAMILY.AF_INET; + sin_port = port; + sin_addr = addr; + sin_zero = 0; + } + + /// Performs an implicit conversion from to . + /// The addr. + /// The resulting instance from the conversion. + public static implicit operator SOCKADDR_IN(IN_ADDR addr) => new SOCKADDR_IN(addr); + + /// Converts to string. + /// A that represents this instance. + public override string ToString() => $"{sin_addr}:{sin_port}"; + } + /// The SOCKADDR_STORAGE structure is a generic structure that specifies a transport address. /// /// A WSK application typically does not directly access any of the members of the SOCKADDR_STORAGE structure except for the @@ -1328,6 +1371,7 @@ namespace Vanara.PInvoke mem.Size = Marshal.SizeOf(typeof(SOCKADDR_STORAGE)); return mem.ToStructure(); } + /// Performs an explicit conversion from to . /// The address. /// The resulting instance from the conversion. @@ -1358,14 +1402,456 @@ namespace Vanara.PInvoke return mem.ToStructure(); } - /// - /// Performs an explicit conversion from to . - /// + /// Performs an explicit conversion from to . /// The addr. - /// - /// The resulting instance from the conversion. - /// + /// The resulting instance from the conversion. public static explicit operator SOCKADDR(SOCKADDR_STORAGE addr) => SOCKADDR.CreateFromStructure(addr); } + + /// The SOCKET_ADDRESS structure stores protocol-specific address information. + /// + /// + /// The SOCKADDR structure pointed to by the lpSockaddr member varies depending on the protocol or address family selected. + /// For example, the sockaddr_in6 structure is used for an IPv6 socket address while the sockaddr_in4 structure is + /// used for an IPv4 socket address. The address family is the first member of all of the SOCKADDR structures. The address + /// family is used to determine which structure is used. + /// + /// + /// On the Microsoft Windows Software Development Kit (SDK) released for Windows Vista and later, the organization of header files + /// has changed and the SOCKET_ADDRESS structure is defined in the Ws2def.h header file. Note that the Ws2def.h header file + /// is automatically included in Winsock2.h, and should never be used directly. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-socket_address typedef struct _SOCKET_ADDRESS { LPSOCKADDR + // lpSockaddr; INT iSockaddrLength; } SOCKET_ADDRESS, *PSOCKET_ADDRESS, *LPSOCKET_ADDRESS; + [PInvokeData("ws2def.h", MSDNShortId = "37fbcb96-a859-4eca-8928-8051f95407b9")] + [StructLayout(LayoutKind.Sequential)] + public struct SOCKET_ADDRESS + { + /// A pointer to a socket address represented as a SOCKADDR structure. + public IntPtr lpSockaddr; + + /// The length, in bytes, of the socket address. + public int iSockaddrLength; + + /// Gets the from this instance. + /// The value pointed to by this instance. + public SOCKADDR_INET GetSOCKADDR() => lpSockaddr.ToStructure(); + + /// Converts to string. + /// A that represents this instance. + public override string ToString() => GetSOCKADDR().ToString(); + } + + /// The SOCKET_ADDRESS_LIST structure defines a variable-sized list of transport addresses. + /// + /// + /// A WSK application passes a buffer to the WskControlSocket function when the WSK application queries the current list of local + /// transport addresses that match a socket's address family. If the call to the WskControlSocket function succeeds, the + /// buffer contains a SOCKET_ADDRESS_LIST structure followed by the SOCKADDR structures for each of the local transport addresses + /// that match the socket's address family. The WSK subsystem fills in the Address array and sets the iAddressCount + /// member to the number of entries in the array. The lpSockaddr pointers in each of the SOCKET_ADDRESS structures in the + /// array point to the specific SOCKADDR structure type that corresponds to the address family that the WSK application specified + /// when it created the socket. + /// + /// For more information about querying the current list of local transport addresses, see SIO_ADDRESS_LIST_QUERY. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-socket_address_list typedef struct _SOCKET_ADDRESS_LIST { INT + // iAddressCount; SOCKET_ADDRESS Address[1]; } SOCKET_ADDRESS_LIST, *PSOCKET_ADDRESS_LIST, *LPSOCKET_ADDRESS_LIST; + [PInvokeData("ws2def.h", MSDNShortId = "b005200b-b0c2-4f19-8765-cd26fbfc0cff")] + [VanaraMarshaler(typeof(SafeAnysizeStructMarshaler), nameof(iAddressCount))] + [StructLayout(LayoutKind.Sequential)] + public struct SOCKET_ADDRESS_LIST + { + /// The number of transport addresses in the list. + public int iAddressCount; + + /// A variable-sized array of SOCKET_ADDRESS structures. The SOCKET_ADDRESS structure is defined as follows: + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + public SOCKET_ADDRESS[] Address; + } + + /// + /// The SOCKET_PROCESSOR_AFFINITY structure contains the association between a socket and an RSS processor core and NUMA node.. + /// + /// + /// + /// The SOCKET_PROCESSOR_AFFINITY structure is supported on Windows 8, and Windows Server 2012, and later versions of the + /// operating system. + /// + /// + /// The SIO_QUERY_RSS_PROCESSOR_INFO IOCTL is used to determine the association between a socket and an RSS processor core and NUMA + /// node. This IOCTL returns a SOCKET_PROCESSOR_AFFINITY structure that contains the processor number and the NUMA node ID. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-socket_processor_affinity typedef struct + // _SOCKET_PROCESSOR_AFFINITY { PROCESSOR_NUMBER Processor; USHORT NumaNodeId; USHORT Reserved; } SOCKET_PROCESSOR_AFFINITY, *PSOCKET_PROCESSOR_AFFINITY; + [PInvokeData("ws2def.h", MSDNShortId = "CB1E9F79-C6BD-40C2-8D0F-36B24B1BBBF4")] + [StructLayout(LayoutKind.Sequential)] + public struct SOCKET_PROCESSOR_AFFINITY + { + /// + /// A structure to represent a system wide processor number. This PROCESSOR_NUMBER structure contains a group number and + /// relative processor number within the group. + /// + public Kernel32.PROCESSOR_NUMBER Processor; + + /// The NUMA node ID. + public ushort NumaNodeId; + + /// A value reserved for future use. + public ushort Reserved; + } + + /// The WSABUF structure enables the creation or manipulation of a data buffer used by some Winsock functions. + // https://docs.microsoft.com/en-us/windows/desktop/api/ws2def/ns-ws2def-_wsabuf typedef struct _WSABUF { ULONG len; CHAR *buf; } + // WSABUF, *LPWSABUF; + [PInvokeData("ws2def.h", MSDNShortId = "a012c3ba-67fd-4fcf-84d1-85e9d495c29c")] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct WSABUF + { + /// The length of the buffer, in bytes. + public uint len; + + /// A pointer to the buffer. + public IntPtr buf; + } + + /// + /// The WSAMSG structure is used with the WSARecvMsg and WSASendMsg functions to store address and optional control + /// information about connected and unconnected sockets as well as an array of buffers used to store message data. + /// + /// + /// + /// In the Microsoft Windows Software Development Kit (SDK), the version of this structure for use on Windows Vistais defined with + /// the data type for the dwBufferCount and dwFlags members as a ULONG. When compiling an application if the + /// target platform is Windows Vista and later ( NTDDI_VERSION >= NTDDI_LONGHORN, _WIN32_WINNT >= 0x0600, or WINVER + /// >= 0x0600), the data type for the dwBufferCount and dwFlags members is a ULONG. + /// + /// + /// Windows Server 2003 and Windows XP: When compiling an application, the data type for the dwBufferCount and + /// dwFlags members is a DWORD. + /// + /// + /// On the Windows SDK released for Windows Vista and later, the WSAMSG structure is defined in the Ws2def.h header file. + /// Note that the Ws2def.h header file is automatically included in Winsock2.h, and should never be used directly + /// + /// + /// If the datagram or control data is truncated during the transmission, the function being used in association with the + /// WSAMSG structure returns SOCKET_ERROR and a call to the WSAGetLastError function returns WSAEMSGSIZE. It is up to the + /// application to determine what was truncated by checking for MSG_TRUNC and/or MSG_CTRUNC flags. + /// + /// Use of the Control Member + /// + /// The following table summarizes the various uses of control data available for use in the Control member for IPv4 and IPv6. + /// + /// + /// + /// Protocol + /// cmsg_level + /// cmsg_type + /// Description + /// + /// + /// IPv4 + /// IPPROTO_IP + /// IP_ORIGINAL_ARRIVAL_IF + /// + /// Receives the original IPv4 arrival interface where the packet was received for datagram sockets. This control data is used by + /// firewalls when a Teredo, 6to4, or ISATAP tunnel is used for IPv4 NAT traversal. The cmsg_data[] member in the WSAMSG structure + /// is a ULONG that contains the IF_INDEX defined in the Ifdef.h header file. For more information, see the IPPROTO_IP Socket + /// Options for the IP_ORIGINAL_ARRIVAL_IF socket option. Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: + /// The IP_ORIGINAL_ARRIVAL_IF cmsg_type is not supported. + /// + /// + /// + /// IPv4 + /// IPPROTO_IP + /// IP_PKTINFO + /// Specifies/receives packet information for an IPv4 socket. For more information, see the IP_PKTINFO socket option. + /// + /// + /// IPv6 + /// IPPROTO_IPV6 + /// IPV6_DSTOPTS + /// Specifies/receives destination options. + /// + /// + /// IPv6 + /// IPPROTO_IPV6 + /// IPV6_HOPLIMIT + /// Specifies/receives hop limit. For more information, see the IPPROTO_IPV6 Socket Options for the IPV6_HOPLIMIT socket option. + /// + /// + /// IPv6 + /// IPPROTO_IPV6 + /// IPV6_HOPOPTS + /// Specifies/receives hop-by-hop options. + /// + /// + /// IPv6 + /// IPPROTO_IPV6 + /// IPV6_NEXTHOP + /// Specifies next-hop address. + /// + /// + /// IPv6 + /// IPPROTO_IPV6 + /// IPV6_PKTINFO + /// Specifies/receives packet information for an IPv6 socket. For more information, see the IPV6_PKTINFO socket option. + /// + /// + /// IPv6 + /// IPPROTO_IPV6 + /// IPV6_RTHDR + /// Specifies/receives routing header. + /// + /// + /// + /// Control data is made up of one or more control data objects, each beginning with a WSACMSGHDR structure, defined as the following. + /// + /// + /// Note The transport, not the application, fills out the header information in the WSACMSGHDR structure. The + /// application simply sets the needed socket options and provides the adequate buffer size. + /// + /// The members of the WSACMSGHDR structure are as follows: + /// + /// + /// Term + /// Description + /// + /// + /// cmsg_len + /// + /// The number of bytes of data starting from the beginning of the WSACMSGHDR to the end of data (excluding padding bytes that may + /// follow data). + /// + /// + /// + /// cmsg_level + /// The protocol that originated the control information. + /// + /// + /// cmsg_type + /// The protocol-specific type of control information. + /// + /// + /// The following macros are used to navigate the data objects: + /// + /// Returns a pointer to the first control data object. Returns a NULL pointer if there is no control data in the + /// WSAMSG structure, such as when the Control member is a NULL pointer. + /// + /// + /// Returns a pointer to the next control data object, or NULL if there are no more data objects. If the pcmsg parameter is + /// NULL, a pointer to the first control data object is returned. + /// + /// + /// Returns a pointer to the first byte of data (referred to as the cmsg_data member, though it is not defined in the structure). + /// + /// + /// Returns the total size of a control data object, given the amount of data. Used to allocate the correct amount of buffer space. + /// Includes alignment padding. + /// + /// Returns the value in cmsg_len given the amount of data. Includes alignment padding. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-wsamsg typedef struct _WSAMSG { LPSOCKADDR name; INT namelen; + // LPWSABUF lpBuffers; #if ... ULONG dwBufferCount; #else DWORD dwBufferCount; #endif WSABUF Control; #if ... ULONG dwFlags; #else + // DWORD dwFlags; #endif } WSAMSG, *PWSAMSG, *LPWSAMSG; + [PInvokeData("ws2def.h", MSDNShortId = "105a6e2c-1edf-4ec0-a1c2-ac0bcafeda30")] + [StructLayout(LayoutKind.Sequential)] + public struct WSAMSG + { + /// + /// Type: LPSOCKADDR + /// + /// A pointer to a SOCKET_ADDRESS structure that stores information about the remote address. Used only with unconnected sockets. + /// + /// + public IntPtr name; + + /// + /// Type: INT + /// + /// The length, in bytes, of the SOCKET_ADDRESS structure pointed to in the pAddr member. Used only with unconnected sockets. + /// + /// + public int namelen; + + /// + /// Type: LPWSABUF + /// + /// An array of WSABUF structures used to receive the message data. The capability of the lpBuffers member to contain + /// multiple buffers enables the use of scatter/gather I/O. + /// + /// + public IntPtr lpBuffers; + + /// + /// Type: DWORD + /// The number of buffers pointed to in the lpBuffers member. + /// + public uint dwBufferCount; + + /// + /// Type: WSABUF + /// A structure of WSABUF type used to specify optional control data. See Remarks. + /// + public WSABUF Control; + + /// + /// Type: DWORD + /// + /// One or more control flags, specified as the logical OR of values. The possible values for dwFlags member on + /// input are defined in the Winsock2.h header file. The possible values for dwFlags member on output are defined in the + /// Ws2def.h header file which is automatically included by the Winsock2.h header file. + /// + /// + /// + /// Flags on input + /// Meaning + /// + /// + /// MSG_PEEK + /// + /// Peek at the incoming data. The data is copied into the buffer, but is not removed from the input queue. This flag is valid + /// only for non-overlapped sockets. + /// + /// + /// + /// + /// + /// Flag returned + /// Meaning + /// + /// + /// MSG_BCAST + /// The datagram was received as a link-layer broadcast or with a destination IP address that is a broadcast address. + /// + /// + /// MSG_MCAST + /// The datagram was received with a destination IP address that is a multicast address. + /// + /// + /// MSG_TRUNC + /// The datagram was truncated. More data was present than the process allocated room for. + /// + /// + /// MSG_CTRUNC + /// The control (ancillary) data was truncated. More control data was present than the process allocated room for. + /// + /// + /// + public MsgFlags dwFlags; + } + + /// + /// + /// Some of the socket IOCTL opcodes for Windows Sockets 2 are summarized in the following table. More detailed information is in + /// the Winsock reference on Winsock IOCTLs and the WSPIoctl function. There are other new protocol-specific IOCTL + /// opcodes that can be found in the protocol-specific annex. + /// + /// A complete list of Winsock IOCTLs are available in the Winsock reference. + /// + // https://docs.microsoft.com/en-us/windows/win32/winsock/summary-of-socket-ioctl-opcodes-2 + [PInvokeData("ws2def.h", MSDNShortId = "fb6447b4-28f5-4ab7-bbdc-5a57ed38a994")] + public static class WinSockIOControlCode + { + /// Requests notification of changes in information reported through SIO_ADDRESS_LIST_QUERY + public static readonly uint SIO_ADDRESS_LIST_CHANGE = _WSAIO(IOC_WS2, 23); + + /// + /// Obtains a list of local transport addresses of the socket's protocol family to which the application can bind. The list of + /// addresses varies based on address family and some addresses are excluded from the list. + /// + [CorrespondingType(typeof(SOCKET_ADDRESS), CorrespondingAction.Get)] + public static readonly uint SIO_ADDRESS_LIST_QUERY = _WSAIOR(IOC_WS2, 22); + + /// + /// Allows application developers to sort a list of IPv6 and IPv4 destination addresses to determine the best available address + /// for making a connection. + /// + [CorrespondingType(typeof(SOCKET_ADDRESS_LIST), CorrespondingAction.GetSet)] + public static readonly uint SIO_ADDRESS_LIST_SORT = _WSAIORW(IOC_WS2, 25); + + /// Associates the socket with the specified handle of a companion interface. + public static readonly uint SIO_ASSOCIATE_HANDLE = _WSAIOW(IOC_WS2, 1); + + /// Enables circular queuing. + public static readonly uint SIO_ENABLE_CIRCULAR_QUEUEING = _WSAIO(IOC_WS2, 2); + + /// Requests the route to the specified address to be discovered. + [CorrespondingType(typeof(SOCKADDR), CorrespondingAction.Set)] + public static readonly uint SIO_FIND_ROUTE = _WSAIOR(IOC_WS2, 3); + + /// Discards current contents of the sending queue. + public static readonly uint SIO_FLUSH = _WSAIO(IOC_WS2, 4); + + /// Retrieves the protocol-specific broadcast address to be used in WSPSendTo. + [CorrespondingType(typeof(SOCKADDR), CorrespondingAction.Get)] + public static readonly uint SIO_GET_BROADCAST_ADDRESS = _WSAIOR(IOC_WS2, 5); + + /// Gets the function pointer for the WSASendMsg function obtained at run time. + public static readonly uint SIO_GET_EXTENSION_FUNCTION_POINTER = _WSAIORW(IOC_WS2, 6); + + /// Reserved. + [CorrespondingType(typeof(QOS), CorrespondingAction.Get)] + public static readonly uint SIO_GET_GROUP_QOS = _WSAIORW(IOC_WS2, 8); + + /// Retrieves current flow specifications for the socket. + [CorrespondingType(typeof(QOS), CorrespondingAction.Get)] + public static readonly uint SIO_GET_QOS = _WSAIORW(IOC_WS2, 7); + + /// Specifies the scope over which multicast transmissions will occur. + [CorrespondingType(typeof(int), CorrespondingAction.Set)] + public static readonly uint SIO_MULTICAST_SCOPE = _WSAIOW(IOC_WS2, 10); + + /// Controls whether data sent in a multipoint session will also be received by the same socket on the local host. + [CorrespondingType(typeof(BOOL), CorrespondingAction.Set)] + public static readonly uint SIO_MULTIPOINT_LOOPBACK = _WSAIOW(IOC_WS2, 9); + + /// Queries the association between a socket and an RSS processor core and NUMA node. + [CorrespondingType(typeof(SOCKET_PROCESSOR_AFFINITY), CorrespondingAction.Get)] + public static readonly uint SIO_QUERY_RSS_PROCESSOR_INFO = _WSAIOR(IOC_WS2, 37); + + /// Obtains socket descriptor of the next provider in the chain on which current socket depends in regards to PnP. + [CorrespondingType(typeof(SOCKET), CorrespondingAction.Get)] + public static readonly uint SIO_QUERY_TARGET_PNP_HANDLE = _WSAIOR(IOC_WS2, 24); + + /// + /// Requests notification of changes in information reported through SIO_ROUTING_INTERFACE_QUERY for the specified address. + /// + [CorrespondingType(typeof(SOCKADDR), CorrespondingAction.Set)] + public static readonly uint SIO_ROUTING_INTERFACE_CHANGE = _WSAIOW(IOC_WS2, 21); + + /// Obtains the address of the local interface that should be used to send to the specified address. + [CorrespondingType(typeof(SOCKADDR), CorrespondingAction.GetSet)] + public static readonly uint SIO_ROUTING_INTERFACE_QUERY = _WSAIORW(IOC_WS2, 20); + + /// Reserved. + [CorrespondingType(typeof(QOS), CorrespondingAction.Set)] + public static readonly uint SIO_SET_GROUP_QOS = _WSAIOW(IOC_WS2, 12); + + /// Establishes new flow specifications for the socket. + [CorrespondingType(typeof(QOS), CorrespondingAction.Set)] + public static readonly uint SIO_SET_QOS = _WSAIOW(IOC_WS2, 11); + + /// Obtains a corresponding handle for socket s that is valid in the context of a companion interface. + [CorrespondingType(typeof(int), CorrespondingAction.Set)] + public static readonly uint SIO_TRANSLATE_HANDLE = _WSAIORW(IOC_WS2, 13); + + private const uint IOC_PROTOCOL = 0x10000000; + private const uint IOC_UNIX = 0x00000000; + private const uint IOC_VENDOR = 0x18000000; + private const uint IOC_WS2 = 0x08000000; + private const uint IOC_WSK = IOC_WS2 | 0x07000000; + + private static uint _WSAIO(uint x, uint y) => (IOC_VOID | (x) | (y)); + + private static uint _WSAIOR(uint x, uint y) => (IOC_OUT | (x) | (y)); + + private static uint _WSAIORW(uint x, uint y) => (IOC_INOUT | (x) | (y)); + + private static uint _WSAIOW(uint x, uint y) => (IOC_IN | (x) | (y)); + } } } \ No newline at end of file