[PSDK]
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 2 Apr 2010 09:14:55 +0000 (09:14 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 2 Apr 2010 09:14:55 +0000 (09:14 +0000)
- Add missing mstcpip.h, wsipv6ok.h and wspiapi.h definitions.

svn path=/branches/header-work/; revision=46666

include/psdk/mstcpip.h [new file with mode: 0644]
include/psdk/wsipv6ok.h [new file with mode: 0644]
include/psdk/wspiapi.h [new file with mode: 0644]

diff --git a/include/psdk/mstcpip.h b/include/psdk/mstcpip.h
new file mode 100644 (file)
index 0000000..2d25e70
--- /dev/null
@@ -0,0 +1,1525 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ASSERT
+#define MSTCPIP_ASSERT_UNDEFINED
+#define ASSERT(exp) ((VOID) 0)
+#endif
+
+#ifdef _MSC_VER
+#define MSTCPIP_INLINE __inline
+#else
+#define MSTCPIP_INLINE extern inline
+#endif
+
+/* FIXME : 
+#include <nldef.h>
+*/
+
+struct tcp_keepalive {
+  ULONG onoff;
+  ULONG keepalivetime;
+  ULONG keepaliveinterval;
+};
+
+#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
+#define SIO_RCVALL_MCAST _WSAIOW(IOC_VENDOR,2)
+#define SIO_RCVALL_IGMPMCAST _WSAIOW(IOC_VENDOR,3)
+#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
+#define SIO_ABSORB_RTRALERT _WSAIOW(IOC_VENDOR,5)
+#define SIO_UCAST_IF _WSAIOW(IOC_VENDOR,6)
+#define SIO_LIMIT_BROADCASTS _WSAIOW(IOC_VENDOR,7)
+#define SIO_INDEX_BIND _WSAIOW(IOC_VENDOR,8)
+#define SIO_INDEX_MCASTIF _WSAIOW(IOC_VENDOR,9)
+#define SIO_INDEX_ADD_MCAST _WSAIOW(IOC_VENDOR,10)
+#define SIO_INDEX_DEL_MCAST _WSAIOW(IOC_VENDOR,11)
+#define SIO_RCVALL_MCAST_IF _WSAIOW(IOC_VENDOR,13)
+#define SIO_RCVALL_IF _WSAIOW(IOC_VENDOR,14)
+
+typedef enum {
+  RCVALL_OFF = 0,
+  RCVALL_ON = 1,
+  RCVALL_SOCKETLEVELONLY = 2,
+  RCVALL_IPLEVEL = 3,
+} RCVALL_VALUE, *PRCVALL_VALUE;
+
+#define RCVALL_MAX RCVALL_IPLEVEL
+
+typedef struct {
+  RCVALL_VALUE Mode;
+  ULONG Interface;
+} RCVALL_IF, *PRCVALL_IF;
+
+#if (NTDDI_VERSION >= NTDDI_WIN7)
+DEFINE_GUID(SOCKET_DEFAULT2_QM_POLICY, 0xaec2ef9c, 0x3a4d, 0x4d3e, 0x88, 0x42, 0x23, 0x99, 0x42, 0xe3, 0x9a, 0x47);
+#endif
+
+#define SIO_ACQUIRE_PORT_RESERVATION _WSAIOW(IOC_VENDOR, 100)
+#define SIO_RELEASE_PORT_RESERVATION _WSAIOW(IOC_VENDOR, 101)
+#define SIO_ASSOCIATE_PORT_RESERVATION _WSAIOW(IOC_VENDOR, 102)
+
+typedef struct _INET_PORT_RANGE {
+  USHORT StartPort;
+  USHORT NumberOfPorts;
+} INET_PORT_RANGE, *PINET_PORT_RANGE;
+typedef struct _INET_PORT_RANGE INET_PORT_RESERVATION, *PINET_PORT_RESERVATION;
+
+typedef struct {
+  ULONG64 Token;
+} INET_PORT_RESERVATION_TOKEN, *PINET_PORT_RESERVATION_TOKEN;
+
+#define INVALID_PORT_RESERVATION_TOKEN ((ULONG64)0)
+
+typedef struct {
+#ifdef __cplusplus
+  INET_PORT_RESERVATION Reservation;
+  INET_PORT_RESERVATION_TOKEN Token;
+#else
+  INET_PORT_RESERVATION;
+  INET_PORT_RESERVATION_TOKEN;
+#endif
+} INET_PORT_RESERVATION_INSTANCE, *PINET_PORT_RESERVATION_INSTANCE;
+
+typedef struct {
+  ULONG AssignmentCount;
+  ULONG OwningPid;
+} INET_PORT_RESERVATION_INFORMATION, *PINET_PORT_RESERVATION_INFORMATION;
+
+#ifdef _WS2DEF_
+
+#if (NTDDI_VERSION >= NTDDI_VISTA)
+
+#define _SECURE_SOCKET_TYPES_DEFINED_
+
+#define SIO_SET_SECURITY             _WSAIOW(IOC_VENDOR, 200)
+#define SIO_QUERY_SECURITY           _WSAIORW(IOC_VENDOR, 201)
+#define SIO_SET_PEER_TARGET_NAME     _WSAIOW(IOC_VENDOR, 202)
+#define SIO_DELETE_PEER_TARGET_NAME  _WSAIOW(IOC_VENDOR, 203)
+
+#define SIO_SOCKET_USAGE_NOTIFICATION _WSAIOW(IOC_VENDOR, 204)
+
+typedef enum _SOCKET_USAGE_TYPE {
+  SYSTEM_CRITICAL_SOCKET = 1
+}SOCKET_USAGE_TYPE;
+
+typedef enum _SOCKET_SECURITY_PROTOCOL {
+  SOCKET_SECURITY_PROTOCOL_DEFAULT,
+  SOCKET_SECURITY_PROTOCOL_IPSEC,
+#if (NTDDI_VERSION >= NTDDI_WIN7)
+  SOCKET_SECURITY_PROTOCOL_IPSEC2,
+#endif
+  SOCKET_SECURITY_PROTOCOL_INVALID
+} SOCKET_SECURITY_PROTOCOL;
+
+#define SOCKET_SETTINGS_GUARANTEE_ENCRYPTION  0x1
+#define SOCKET_SETTINGS_ALLOW_INSECURE  0x2
+
+typedef struct _SOCKET_SECURITY_SETTINGS {
+  SOCKET_SECURITY_PROTOCOL SecurityProtocol;
+  ULONG SecurityFlags;
+} SOCKET_SECURITY_SETTINGS;
+
+#define SOCKET_SETTINGS_IPSEC_SKIP_FILTER_INSTANTIATION            0x1
+
+#if (NTDDI_VERSION >= NTDDI_WIN7)
+
+#define SOCKET_SETTINGS_IPSEC_OPTIONAL_PEER_NAME_VERIFICATION      0x2
+#define SOCKET_SETTINGS_IPSEC_ALLOW_FIRST_INBOUND_PKT_UNENCRYPTED  0x4
+#define SOCKET_SETTINGS_IPSEC_PEER_NAME_IS_RAW_FORMAT              0x8
+
+#endif /* (NTDDI_VERSION >= NTDDI_WIN7) */
+
+typedef struct _SOCKET_SECURITY_SETTINGS_IPSEC {
+  SOCKET_SECURITY_PROTOCOL SecurityProtocol;
+  ULONG SecurityFlags;
+  ULONG IpsecFlags;
+  GUID AuthipMMPolicyKey;
+  GUID AuthipQMPolicyKey;
+  GUID Reserved;
+  UINT64 Reserved2;
+  ULONG UserNameStringLen;
+  ULONG DomainNameStringLen;
+  ULONG PasswordStringLen;
+  wchar_t AllStrings[0];
+} SOCKET_SECURITY_SETTINGS_IPSEC;
+
+typedef struct _SOCKET_PEER_TARGET_NAME {
+  SOCKET_SECURITY_PROTOCOL SecurityProtocol;
+  SOCKADDR_STORAGE PeerAddress;
+  ULONG PeerTargetNameStringLen;
+  wchar_t AllStrings[0];
+} SOCKET_PEER_TARGET_NAME;
+
+typedef struct _SOCKET_SECURITY_QUERY_TEMPLATE {
+  SOCKET_SECURITY_PROTOCOL SecurityProtocol;
+  SOCKADDR_STORAGE PeerAddress;
+  ULONG PeerTokenAccessMask;
+} SOCKET_SECURITY_QUERY_TEMPLATE;
+
+#if (NTDDI_VERSION >= NTDDI_WIN7)
+
+#define SOCKET_QUERY_IPSEC2_ABORT_CONNECTION_ON_FIELD_CHANGE 0x1
+
+#define SOCKET_QUERY_IPSEC2_FIELD_MASK_MM_SA_ID 0x1
+#define SOCKET_QUERY_IPSEC2_FIELD_MASK_QM_SA_ID 0x2
+
+typedef struct _SOCKET_SECURITY_QUERY_TEMPLATE_IPSEC2 {
+  SOCKET_SECURITY_PROTOCOL SecurityProtocol;
+  SOCKADDR_STORAGE PeerAddress;
+  ULONG PeerTokenAccessMask;
+  ULONG Flags;
+  ULONG FieldMask;
+} SOCKET_SECURITY_QUERY_TEMPLATE_IPSEC2;
+
+#endif /* (NTDDI_VERSION >= NTDDI_WIN7) */
+
+#define SOCKET_INFO_CONNECTION_SECURED  0x1
+#define SOCKET_INFO_CONNECTION_ENCRYPTED  0x2
+#define SOCKET_INFO_CONNECTION_IMPERSONATED 0x4
+
+typedef struct _SOCKET_SECURITY_QUERY_INFO {
+  SOCKET_SECURITY_PROTOCOL SecurityProtocol;
+  ULONG Flags;
+  UINT64 PeerApplicationAccessTokenHandle;
+  UINT64 PeerMachineAccessTokenHandle;
+} SOCKET_SECURITY_QUERY_INFO;
+
+#if (NTDDI_VERSION >= NTDDI_WIN7)
+typedef struct _SOCKET_SECURITY_QUERY_INFO_IPSEC2 {
+  SOCKET_SECURITY_PROTOCOL SecurityProtocol;
+  ULONG Flags;
+  UINT64 PeerApplicationAccessTokenHandle;
+  UINT64 PeerMachineAccessTokenHandle;
+  UINT64 MmSaId;
+  UINT64 QmSaId;
+  UINT32 NegotiationWinerr;
+  GUID SaLookupContext;
+} SOCKET_SECURITY_QUERY_INFO_IPSEC2;
+#endif
+
+#define SIO_QUERY_WFP_ALE_ENDPOINT_HANDLE _WSAIOR(IOC_VENDOR, 205)
+#define SIO_QUERY_RSS_SCALABILITY_INFO _WSAIOR(IOC_VENDOR, 210)
+
+typedef struct _RSS_SCALABILITY_INFO {
+  BOOLEAN RssEnabled;
+} RSS_SCALABILITY_INFO, *PRSS_SCALABILITY_INFO;
+
+#endif /* (NTDDI_VERSION >= NTDDI_VISTA) */
+
+#define IN4_CLASSA(i) (((LONG)(i) & 0x00000080) == 0)
+#define IN4_CLASSB(i) (((LONG)(i) & 0x000000c0) == 0x00000080)
+#define IN4_CLASSC(i) (((LONG)(i) & 0x000000e0) == 0x000000c0)
+#define IN4_CLASSD(i) (((LONG)(i) & 0x000000f0) == 0x000000e0)
+#define IN4_MULTICAST(i) IN4_CLASSD(i)
+
+#define IN4ADDR_ANY INADDR_ANY
+#define IN4ADDR_LOOPBACK 0x0100007f
+#define IN4ADDR_BROADCAST INADDR_BROADCAST
+#define IN4ADDR_NONE INADDR_NONE
+#define IN4ADDR_ANY_INIT { 0 }
+#define IN4ADDR_LOOPBACK_INIT { 0x7f, 0, 0, 1 }
+#define IN4ADDR_BROADCAST_INIT { 0xff, 0xff, 0xff, 0xff }
+#define IN4ADDR_ALLNODESONLINK_INIT { 0xe0, 0, 0, 1 }
+#define IN4ADDR_ALLROUTERSONLINK_INIT { 0xe0, 0, 0, 2 }
+#define IN4ADDR_ALLIGMPV3ROUTERSONLINK_INIT { 0xe0, 0, 0, 0x16 }
+#define IN4ADDR_ALLTEREDONODESONLINK_INIT { 0xe0, 0, 0, 0xfd }
+#define IN4ADDR_LINKLOCALPREFIX_INIT { 0xa9, 0xfe, }
+#define IN4ADDR_MULTICASTPREFIX_INIT { 0xe0, }
+
+#define IN4ADDR_LOOPBACKPREFIX_LENGTH 8
+#define IN4ADDR_LINKLOCALPREFIX_LENGTH 16
+#define IN4ADDR_MULTICASTPREFIX_LENGTH 4
+
+#if (NTDDI_VERSION >= NTDDI_WIN2KSP1)
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_ADDR_EQUAL(
+  IN CONST IN_ADDR *a,
+  IN CONST IN_ADDR *b)
+{
+  return (BOOLEAN)(a->s_addr == b->s_addr);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_UNALIGNED_ADDR_EQUAL(
+  IN CONST IN_ADDR UNALIGNED *a,
+  IN CONST IN_ADDR UNALIGNED *b)
+{
+  return (BOOLEAN)(a->s_addr == b->s_addr);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_UNSPECIFIED(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)(a->s_addr == IN4ADDR_ANY);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_UNALIGNED_ADDR_UNSPECIFIED(
+  IN CONST IN_ADDR UNALIGNED *a)
+{
+  return (BOOLEAN)(a->s_addr == IN4ADDR_ANY);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_LOOPBACK(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)(*((PUCHAR) a) == 0x7f);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_UNALIGNED_ADDR_LOOPBACK(
+  IN CONST IN_ADDR UNALIGNED *a)
+{
+  return (BOOLEAN)(*((PUCHAR) a) == 0x7f);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_BROADCAST(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)(a->s_addr == IN4ADDR_BROADCAST);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_UNALIGNED_ADDR_BROADCAST(
+  IN CONST IN_ADDR UNALIGNED *a)
+{
+  return (BOOLEAN)(a->s_addr == IN4ADDR_BROADCAST);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_MULTICAST(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)IN4_MULTICAST(a->s_addr);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_UNALIGNED_ADDR_MULTICAST(
+  IN CONST IN_ADDR UNALIGNED *a)
+{
+  return (BOOLEAN)IN4_MULTICAST(a->s_addr);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_LINKLOCAL(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)((a->s_addr & 0xffff) == 0xfea9);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_UNALIGNED_ADDR_LINKLOCAL(
+  IN CONST IN_ADDR UNALIGNED *a)
+{
+  return (BOOLEAN)((a->s_addr & 0xffff) == 0xfea9); // 169.254/16
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_SITELOCAL(
+  IN CONST IN_ADDR *a)
+{
+  UNREFERENCED_PARAMETER(a);
+  return FALSE;
+}
+#define IN4_IS_UNALIGNED_ADDR_SITELOCAL IN4_IS_ADDR_SITELOCAL
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_RFC1918(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)(((a->s_addr & 0x00ff) == 0x0a) ||
+                   ((a->s_addr & 0xf0ff) == 0x10ac) ||
+                   ((a->s_addr & 0xffff) == 0xa8c0));
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_UNALIGNED_ADDR_RFC1918(
+  IN CONST IN_ADDR UNALIGNED *a)
+{
+  IN_ADDR Ipv4Address = *a;
+  return IN4_IS_ADDR_RFC1918(&Ipv4Address);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_MC_LINKLOCAL(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)((a->s_addr & 0xffffff) == 0xe0);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_MC_ADMINLOCAL(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)((a->s_addr & 0xffff) == 0xffef);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_MC_SITELOCAL(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)((a->s_addr & 0xff) == 0xef) &&
+                  !IN4_IS_ADDR_MC_ADMINLOCAL(a);
+}
+
+MSTCPIP_INLINE
+VOID
+IN4ADDR_SETSOCKADDR(
+  OUT PSOCKADDR_IN a,
+  IN CONST IN_ADDR *addr,
+  IN USHORT port)
+{
+  a->sin_family = AF_INET;
+  a->sin_port = port;
+  a->sin_addr = *addr;
+  memset(a->sin_zero, 0, sizeof(a->sin_zero));
+}
+
+MSTCPIP_INLINE
+VOID
+IN4ADDR_SETANY(
+  OUT PSOCKADDR_IN a)
+{
+  a->sin_family = AF_INET;
+  a->sin_port = 0;
+  a->sin_addr.s_addr = IN4ADDR_ANY;
+  memset(a->sin_zero, 0, sizeof(a->sin_zero));
+}
+
+MSTCPIP_INLINE
+VOID
+IN4ADDR_SETLOOPBACK(
+  OUT PSOCKADDR_IN a)
+{
+  a->sin_family = AF_INET;
+  a->sin_port = 0;
+  a->sin_addr.s_addr = IN4ADDR_LOOPBACK;
+  memset(a->sin_zero, 0, sizeof(a->sin_zero));
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4ADDR_ISANY(
+  IN CONST SOCKADDR_IN *a)
+{
+  ASSERT(a->sin_family == AF_INET);
+  return IN4_IS_ADDR_UNSPECIFIED(&a->sin_addr);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4ADDR_ISLOOPBACK(
+  IN CONST SOCKADDR_IN *a)
+{
+  ASSERT(a->sin_family == AF_INET);
+  return IN4_IS_ADDR_LOOPBACK(&a->sin_addr);
+}
+
+MSTCPIP_INLINE
+SCOPE_ID
+IN4ADDR_SCOPE_ID(
+  IN CONST SOCKADDR_IN *a)
+{
+  SCOPE_ID UnspecifiedScopeId = {0};
+  UNREFERENCED_PARAMETER(a);
+  return UnspecifiedScopeId;
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4ADDR_ISEQUAL(
+  IN CONST SOCKADDR_IN *a,
+  IN CONST SOCKADDR_IN *b)
+{
+  ASSERT(a->sin_family == AF_INET);
+  return (BOOLEAN)(IN4ADDR_SCOPE_ID(a).Value == IN4ADDR_SCOPE_ID(b).Value &&
+                   IN4_ADDR_EQUAL(&a->sin_addr, &b->sin_addr));
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4ADDR_ISUNSPECIFIED(
+  IN CONST SOCKADDR_IN *a)
+{
+  ASSERT(a->sin_family == AF_INET);
+  return (BOOLEAN)(IN4ADDR_SCOPE_ID(a).Value == 0 &&
+                   IN4_IS_ADDR_UNSPECIFIED(&a->sin_addr));
+}
+
+#define INET_IS_ALIGNED(Pointer, Type) \
+   (((ULONG_PTR)Pointer & (__builtin_alignof(Type)-1)) == 0)
+
+MSTCPIP_INLINE
+SCOPE_LEVEL
+Ipv4UnicastAddressScope(
+  IN CONST UCHAR *Address)
+{
+  IN_ADDR Ipv4Address;
+
+  if (!INET_IS_ALIGNED(Address, IN_ADDR)) {
+      Ipv4Address = *(CONST IN_ADDR UNALIGNED *)Address;
+      Address = (CONST UCHAR *) &Ipv4Address;
+  }
+  if (IN4_IS_ADDR_LINKLOCAL((PIN_ADDR) Address) ||
+      IN4_IS_ADDR_LOOPBACK((PIN_ADDR) Address)) {
+      return ScopeLevelLink;
+  }
+  return ScopeLevelGlobal;
+}
+
+MSTCPIP_INLINE
+SCOPE_LEVEL
+Ipv4MulticastAddressScope(
+  IN CONST UCHAR *Address)
+{
+  IN_ADDR Ipv4Address;
+
+  if (!INET_IS_ALIGNED(Address, IN_ADDR)) {
+    Ipv4Address = *(CONST IN_ADDR UNALIGNED *)Address;
+    Address = (CONST UCHAR *) &Ipv4Address;
+  }
+  if (IN4_IS_ADDR_MC_LINKLOCAL((PIN_ADDR) Address)) {
+    return ScopeLevelLink;
+  } else if (IN4_IS_ADDR_MC_ADMINLOCAL((PIN_ADDR) Address)) {
+    return ScopeLevelAdmin;
+  } else if (IN4_IS_ADDR_MC_SITELOCAL((PIN_ADDR) Address)) {
+    return ScopeLevelSite;
+  } else {
+    return ScopeLevelGlobal;
+  }
+}
+
+MSTCPIP_INLINE
+SCOPE_LEVEL
+Ipv4AddressScope(
+  IN CONST UCHAR *Address)
+{
+  IN CONST IN_ADDR Ipv4Address = *(CONST IN_ADDR UNALIGNED *)Address;
+
+  if (IN4_IS_ADDR_BROADCAST(&Ipv4Address)) {
+    return ScopeLevelLink;
+  } else if (IN4_IS_ADDR_MULTICAST(&Ipv4Address)) {
+    return Ipv4MulticastAddressScope((UCHAR *) &Ipv4Address);
+  } else {
+    return Ipv4UnicastAddressScope((UCHAR *) &Ipv4Address);
+  }
+}
+
+MSTCPIP_INLINE
+NL_ADDRESS_TYPE
+Ipv4AddressType(
+  IN CONST UCHAR *Address)
+{
+  IN_ADDR Ipv4Address = *(CONST IN_ADDR UNALIGNED *) Address;
+
+  if (IN4_IS_ADDR_MULTICAST(&Ipv4Address)) {
+    return NlatMulticast;
+  }
+  if (IN4_IS_ADDR_BROADCAST(&Ipv4Address)) {
+    return NlatBroadcast;
+  }
+  if (IN4_IS_ADDR_UNSPECIFIED(&Ipv4Address)) {
+    return NlatUnspecified;
+  }
+  if (((Ipv4Address.s_addr & 0x000000ff) == 0) ||
+    ((Ipv4Address.s_addr & 0x000000f0) == 240)) {
+    return NlatInvalid;
+  }
+  return NlatUnicast;
+}
+
+MSTCPIP_INLINE
+VOID
+IN4_UNCANONICALIZE_SCOPE_ID(
+  IN CONST IN_ADDR *Address,
+  IN OUT SCOPE_ID *ScopeId)
+{
+  SCOPE_LEVEL ScopeLevel = Ipv4AddressScope((CONST UCHAR *)Address);
+
+  if ((IN4_IS_ADDR_LOOPBACK(Address)) || (ScopeLevel == ScopeLevelGlobal)) {
+    ScopeId->Value = 0;
+  }
+  if ((SCOPE_LEVEL)ScopeId->Level == ScopeLevel) {
+    ScopeId->Level = 0;
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_ADDR_6TO4ELIGIBLE(
+  IN CONST IN_ADDR *a)
+{
+  return (BOOLEAN)((Ipv4AddressType((CONST UCHAR *) a) == NlatUnicast) &&
+                   !(IN4_IS_ADDR_LOOPBACK(a) ||
+                     IN4_IS_ADDR_LINKLOCAL(a) ||
+                     IN4_IS_ADDR_SITELOCAL(a) ||
+                     IN4_IS_ADDR_RFC1918(a)));
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN4_IS_UNALIGNED_ADDR_6TO4ELIGIBLE(
+  IN CONST IN_ADDR UNALIGNED *a)
+{
+  IN_ADDR Ipv4Address = *a;
+  return IN4_IS_ADDR_6TO4ELIGIBLE(&Ipv4Address);
+}
+
+#endif /* (NTDDI_VERSION >= NTDDI_WIN2KSP1) */
+
+#endif /* _WS2DEF_ */
+
+#ifdef _WS2IPDEF_
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6_PREFIX_EQUAL(
+  IN CONST IN6_ADDR *a,
+  IN CONST IN6_ADDR *b,
+  IN UINT8 len)
+{
+  UINT8 Bytes = len / 8;
+  UINT8 Bits = len % 8;
+  UINT8 Mask = 0xff << (8 - Bits);
+
+  ASSERT(len <= (sizeof(IN6_ADDR) * 8));
+  return (BOOLEAN) (((memcmp(a, b, Bytes)) == 0) && ((Bits == 0) ||
+                    ((a->s6_bytes[Bytes] | Mask) == (b->s6_bytes[Bytes] | Mask))));
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6_IS_ADDR_ALLNODESONNODE(
+  IN CONST IN6_ADDR *a)
+{
+  return IN6_ADDR_EQUAL(a, &in6addr_allnodesonnode);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6_IS_ADDR_ALLNODESONLINK(
+  IN CONST IN6_ADDR *a)
+{
+  return IN6_ADDR_EQUAL(a, &in6addr_allnodesonlink);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6_IS_ADDR_ALLROUTERSONLINK(
+  IN CONST IN6_ADDR *a)
+{
+  return IN6_ADDR_EQUAL(a, &in6addr_allroutersonlink);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6_IS_ADDR_SOLICITEDNODE(
+  IN CONST IN6_ADDR *a)
+{
+  return IN6_PREFIX_EQUAL(a, &in6addr_solicitednodemulticastprefix,
+                          IN6ADDR_SOLICITEDNODEMULTICASTPREFIX_LENGTH);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6_IS_ADDR_ISATAP(
+  IN CONST IN6_ADDR *a)
+{
+  return (BOOLEAN)(((a->s6_words[4] & 0xfffd) == 0x0000) &&
+                   (a->s6_words[5] == 0xfe5e));
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6_IS_ADDR_6TO4(
+  IN CONST IN6_ADDR *a)
+{
+  C_ASSERT(IN6ADDR_6TO4PREFIX_LENGTH == RTL_BITS_OF(USHORT));
+  return (BOOLEAN)(a->s6_words[0] == in6addr_6to4prefix.s6_words[0]);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6_IS_ADDR_TEREDO(
+  IN CONST IN6_ADDR *a)
+{
+  C_ASSERT(IN6ADDR_TEREDOPREFIX_LENGTH == 2 * RTL_BITS_OF(USHORT));
+  return (BOOLEAN)
+      (((a->s6_words[0] == in6addr_teredoprefix.s6_words[0]) &&
+        (a->s6_words[1] == in6addr_teredoprefix.s6_words[1])) ||
+       ((a->s6_words[0] == in6addr_teredoprefix_old.s6_words[0]) &&
+        (a->s6_words[1] == in6addr_teredoprefix_old.s6_words[1])));
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6ADDR_ISV4MAPPED(
+  IN CONST SOCKADDR_IN6 *a)
+{
+  ASSERT(a->sin6_family == AF_INET6);
+  return IN6_IS_ADDR_V4MAPPED(&a->sin6_addr);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6ADDR_ISISATAP(
+  IN CONST SOCKADDR_IN6 *a)
+{
+  ASSERT(a->sin6_family == AF_INET6);
+  return IN6_IS_ADDR_ISATAP(&a->sin6_addr);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6ADDR_IS6TO4(
+  IN CONST SOCKADDR_IN6 *a)
+{
+  ASSERT(a->sin6_family == AF_INET6);
+  return IN6_IS_ADDR_6TO4(&a->sin6_addr);
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+IN6ADDR_ISTEREDO(
+  IN CONST SOCKADDR_IN6 *a)
+{
+  ASSERT(a->sin6_family == AF_INET6);
+  return IN6_IS_ADDR_TEREDO(&a->sin6_addr);
+}
+
+MSTCPIP_INLINE
+CONST UCHAR*
+IN6_GET_ADDR_V4MAPPED(
+  IN CONST IN6_ADDR *Ipv6Address)
+{
+  return (CONST UCHAR *) (Ipv6Address->s6_words + 6);
+}
+
+MSTCPIP_INLINE
+CONST UCHAR*
+IN6_GET_ADDR_V4COMPAT(
+  IN CONST IN6_ADDR *Ipv6Address)
+{
+  return (CONST UCHAR *) (Ipv6Address->s6_words + 6);
+}
+
+MSTCPIP_INLINE
+CONST UCHAR*
+IN6_EXTRACT_V4ADDR_FROM_ISATAP(
+  IN CONST IN6_ADDR *Ipv6Address)
+{
+  return (CONST UCHAR *) (Ipv6Address->s6_words + 6);
+}
+
+MSTCPIP_INLINE
+CONST UCHAR*
+IN6_EXTRACT_V4ADDR_FROM_6TO4(
+  IN CONST IN6_ADDR *Ipv6Address)
+{
+  return (CONST UCHAR *) (Ipv6Address->s6_words + 1);
+}
+
+MSTCPIP_INLINE
+VOID
+IN6_SET_ADDR_V4MAPPED(
+  OUT PIN6_ADDR a6,
+  IN CONST IN_ADDR* a4)
+{
+  *a6 = in6addr_v4mappedprefix;
+  a6->s6_bytes[12] = ((CONST UCHAR *) a4)[0];
+  a6->s6_bytes[13] = ((CONST UCHAR *) a4)[1];
+  a6->s6_bytes[14] = ((CONST UCHAR *) a4)[2];
+  a6->s6_bytes[15] = ((CONST UCHAR *) a4)[3];
+}
+
+MSTCPIP_INLINE
+VOID
+IN6_SET_ADDR_V4COMPAT(
+  OUT PIN6_ADDR a6,
+  IN CONST IN_ADDR* a4)
+{
+  *a6 = in6addr_any;
+  a6->s6_bytes[12] = ((CONST UCHAR *) a4)[0];
+  a6->s6_bytes[13] = ((CONST UCHAR *) a4)[1];
+  a6->s6_bytes[14] = ((CONST UCHAR *) a4)[2];
+  a6->s6_bytes[15] = ((CONST UCHAR *) a4)[3];
+}
+
+MSTCPIP_INLINE
+VOID
+IN6_SET_ADDR_SOLICITEDNODE(
+  OUT PIN6_ADDR Multicast,
+  IN CONST IN6_ADDR *Unicast)
+{
+  *Multicast = in6addr_solicitednodemulticastprefix;
+  Multicast->s6_bytes[13] = Unicast->s6_bytes[13];
+  Multicast->s6_bytes[14] = Unicast->s6_bytes[14];
+  Multicast->s6_bytes[15] = Unicast->s6_bytes[15];
+}
+
+MSTCPIP_INLINE
+VOID
+IN6_SET_ISATAP_IDENTIFIER(
+  IN OUT IN6_ADDR *Ipv6Address,
+  IN CONST IN_ADDR *Ipv4Address)
+{
+  if (IN4_IS_ADDR_6TO4ELIGIBLE(Ipv4Address)) {
+    Ipv6Address->s6_words[4] = 0x0002;
+  } else {
+    Ipv6Address->s6_words[4] = 0x0000;
+  }
+  Ipv6Address->s6_words[5] = 0xFE5E;
+  *((UNALIGNED IN_ADDR *) (Ipv6Address->s6_words + 6)) = *Ipv4Address;
+}
+
+MSTCPIP_INLINE
+VOID
+IN6_SET_6TO4_PREFIX(
+  IN OUT IN6_ADDR *Ipv6Address,
+  IN CONST IN_ADDR *Ipv4Address)
+{
+  Ipv6Address->s6_words[0] = 0x0220;
+  *((UNALIGNED IN_ADDR *) (Ipv6Address->s6_words + 1)) = *Ipv4Address;
+  Ipv6Address->s6_words[3] = 0x0000;
+}
+
+MSTCPIP_INLINE
+SCOPE_LEVEL
+Ipv6UnicastAddressScope(
+  IN CONST UCHAR *Address)
+{
+  IN6_ADDR Ipv6Address;
+
+  if (!INET_IS_ALIGNED(Address, IN6_ADDR)) {
+    Ipv6Address = *(CONST IN6_ADDR UNALIGNED *)Address;
+    Address = (CONST UCHAR *) &Ipv6Address;
+  }
+  if (IN6_IS_ADDR_LINKLOCAL((PIN6_ADDR) Address) ||
+    IN6_IS_ADDR_LOOPBACK((PIN6_ADDR) Address)) {
+    return ScopeLevelLink;
+  } else if (IN6_IS_ADDR_SITELOCAL((PIN6_ADDR) Address)) {
+    return ScopeLevelSite;
+  } else {
+    return ScopeLevelGlobal;
+  }
+}
+
+MSTCPIP_INLINE
+SCOPE_LEVEL
+IN6_MULTICAST_SCOPE(
+  IN CONST UCHAR *Address)
+{
+  PIN6_ADDR Ipv6Address = (PIN6_ADDR) Address;
+  return (SCOPE_LEVEL)(Ipv6Address->s6_bytes[1] & 0xf);
+}
+
+MSTCPIP_INLINE
+SCOPE_LEVEL
+Ipv6AddressScope(
+  IN CONST UCHAR *Address)
+{
+  if (IN6_IS_ADDR_MULTICAST((CONST IN6_ADDR *) Address)) {
+    return IN6_MULTICAST_SCOPE(Address);
+  } else {
+    return Ipv6UnicastAddressScope(Address);
+  }
+}
+
+MSTCPIP_INLINE
+NL_ADDRESS_TYPE
+Ipv6AddressType(
+  IN CONST UCHAR *Address)
+{
+  CONST IN6_ADDR *Ipv6Address = (CONST IN6_ADDR *) Address;
+  CONST UCHAR *Ipv4Address;
+
+  if (IN6_IS_ADDR_MULTICAST(Ipv6Address)) {
+    return NlatMulticast;
+  }
+  if (IN6_IS_ADDR_UNSPECIFIED(Ipv6Address)) {
+    return NlatUnspecified;
+  }
+  if (IN6_IS_ADDR_ISATAP(Ipv6Address) || IN6_IS_ADDR_V4COMPAT(Ipv6Address) ||
+      IN6_IS_ADDR_V4MAPPED(Ipv6Address) || IN6_IS_ADDR_V4TRANSLATED(Ipv6Address)) {
+    Ipv4Address = IN6_EXTRACT_V4ADDR_FROM_ISATAP(Ipv6Address);
+  } else if (IN6_IS_ADDR_6TO4(Ipv6Address)) {
+  Ipv4Address = IN6_EXTRACT_V4ADDR_FROM_6TO4(Ipv6Address);
+  } else {
+    return NlatUnicast;
+  }
+  if (Ipv4AddressType(Ipv4Address) != NlatUnicast) {
+    return NlatInvalid;
+  }
+  return NlatUnicast;
+}
+
+MSTCPIP_INLINE
+VOID
+IN6_UNCANONICALIZE_SCOPE_ID(
+  IN CONST IN6_ADDR *Address,
+  IN OUT SCOPE_ID *ScopeId)
+{
+  SCOPE_LEVEL ScopeLevel = Ipv6AddressScope((CONST UCHAR *)Address);
+
+  if ((IN6_IS_ADDR_LOOPBACK(Address)) || (ScopeLevel == ScopeLevelGlobal)) {
+      ScopeId->Value = 0;
+  }
+  if ((SCOPE_LEVEL)ScopeId->Level == ScopeLevel) {
+    ScopeId->Level = 0;
+  }
+}
+
+#if (NTDDI_VERSION >= NTDDI_VISTA)
+
+MSTCPIP_INLINE
+VOID
+IN6ADDR_SETSOCKADDR(
+  OUT PSOCKADDR_IN6 a,
+  IN CONST IN6_ADDR *addr,
+  IN SCOPE_ID scope,
+  IN USHORT port)
+{
+  a->sin6_family = AF_INET6;
+  a->sin6_port = port;
+  a->sin6_flowinfo = 0;
+  RtlCopyMemory(&a->sin6_addr, addr, sizeof(IN6_ADDR));
+  a->sin6_scope_struct = scope;
+  IN6_UNCANONICALIZE_SCOPE_ID(&a->sin6_addr, &a->sin6_scope_struct);
+}
+
+MSTCPIP_INLINE
+VOID
+IN6ADDR_SETV4MAPPED(
+  OUT PSOCKADDR_IN6 a6,
+  IN CONST IN_ADDR* a4,
+  IN SCOPE_ID scope,
+  IN USHORT port)
+{
+  a6->sin6_family = AF_INET6;
+  a6->sin6_port = port;
+  a6->sin6_flowinfo = 0;
+  IN6_SET_ADDR_V4MAPPED(&a6->sin6_addr, a4);
+  a6->sin6_scope_struct = scope;
+  IN4_UNCANONICALIZE_SCOPE_ID(a4, &a6->sin6_scope_struct);
+}
+
+#endif /* (NTDDI_VERSION >= NTDDI_VISTA) */
+
+MSTCPIP_INLINE
+BOOLEAN
+INET_ADDR_EQUAL(
+  IN ADDRESS_FAMILY af,
+  IN CONST VOID* a,
+  IN CONST VOID* b)
+{
+  if (af == AF_INET6) {
+    return IN6_ADDR_EQUAL((CONST IN6_ADDR*)a, (CONST IN6_ADDR*)b);
+  } else {
+    ASSERT(af == AF_INET);
+    return IN4_ADDR_EQUAL((CONST IN_ADDR*)a, (CONST IN_ADDR*)b);
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INET_UNALIGNED_ADDR_EQUAL(
+  IN ADDRESS_FAMILY af,
+  IN CONST VOID* a,
+  IN CONST VOID* b)
+{
+  if (af == AF_INET6) {
+    return IN6_ADDR_EQUAL((CONST IN6_ADDR*)a, (CONST IN6_ADDR*)b);
+  } else {
+    ASSERT(af == AF_INET);
+    return IN4_UNALIGNED_ADDR_EQUAL((CONST IN_ADDR*)a, (CONST IN_ADDR*)b);
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INET_IS_ADDR_UNSPECIFIED(
+  IN ADDRESS_FAMILY af,
+  IN CONST VOID* a)
+{
+  if (af == AF_INET6) {
+    return IN6_IS_ADDR_UNSPECIFIED((CONST IN6_ADDR*)a);
+  } else {
+    ASSERT(af == AF_INET);
+    return IN4_IS_ADDR_UNSPECIFIED((CONST IN_ADDR*)a);
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INET_IS_UNALIGNED_ADDR_UNSPECIFIED(
+  IN ADDRESS_FAMILY af,
+  IN CONST VOID* a)
+{
+  if (af == AF_INET6) {
+    return IN6_IS_ADDR_UNSPECIFIED((CONST IN6_ADDR*)a);
+  } else {
+    ASSERT(af == AF_INET);
+    return IN4_IS_UNALIGNED_ADDR_UNSPECIFIED((CONST IN_ADDR UNALIGNED*)a);
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INET_IS_ADDR_LOOPBACK(
+  IN ADDRESS_FAMILY af,
+  IN CONST VOID* a)
+{
+  if (af == AF_INET6) {
+    return IN6_IS_ADDR_LOOPBACK((CONST IN6_ADDR*)a);
+  } else {
+    ASSERT(af == AF_INET);
+    return IN4_IS_ADDR_LOOPBACK((CONST IN_ADDR*)a);
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INET_IS_ADDR_BROADCAST(
+  IN ADDRESS_FAMILY af,
+  IN CONST VOID* a)
+{
+  if (af == AF_INET6) {
+    return FALSE;
+  } else {
+    ASSERT(af == AF_INET);
+    return IN4_IS_ADDR_BROADCAST((CONST IN_ADDR*)a);
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INET_IS_ADDR_MULTICAST(
+  IN ADDRESS_FAMILY af,
+  IN CONST VOID* a)
+{
+  if (af == AF_INET6) {
+    return IN6_IS_ADDR_MULTICAST((CONST IN6_ADDR*)a);
+  } else {
+    ASSERT(af == AF_INET);
+    return IN4_IS_ADDR_MULTICAST((CONST IN_ADDR*)a);
+  }
+}
+
+MSTCPIP_INLINE
+CONST UCHAR*
+INET_ADDR_UNSPECIFIED(
+  IN ADDRESS_FAMILY af)
+{
+  if (af == AF_INET6) {
+    return (CONST UCHAR*)&in6addr_any;
+  } else {
+    ASSERT(af == AF_INET);
+    return (CONST UCHAR*)&in4addr_any;
+  }
+}
+
+MSTCPIP_INLINE
+VOID
+INET_SET_ADDRESS(
+  IN ADDRESS_FAMILY Family,
+  OUT PUCHAR Address,
+  IN CONST UCHAR *Value)
+{
+  if (Family == AF_INET6) {
+    *((PIN6_ADDR)Address) = *((PIN6_ADDR)Value);
+  } else {
+    ASSERT(Family == AF_INET);
+    *((PIN_ADDR)Address) = *((PIN_ADDR)Value);
+  }
+}
+
+MSTCPIP_INLINE
+SIZE_T
+INET_ADDR_LENGTH(
+  IN ADDRESS_FAMILY af)
+{
+  if (af == AF_INET6) {
+    return sizeof(IN6_ADDR);
+  } else {
+    ASSERT(af == AF_INET);
+    return sizeof(IN_ADDR);
+  }
+}
+
+MSTCPIP_INLINE
+SIZE_T
+INET_SOCKADDR_LENGTH(
+  IN ADDRESS_FAMILY af)
+{
+  if (af == AF_INET6) {
+    return sizeof(SOCKADDR_IN6);
+  } else {
+    ASSERT(af == AF_INET);
+    return sizeof(SOCKADDR_IN);
+  }
+}
+
+#if (NTDDI_VERSION >= NTDDI_VISTA)
+MSTCPIP_INLINE
+VOID
+INETADDR_SETSOCKADDR(
+  IN ADDRESS_FAMILY af,
+  OUT PSOCKADDR a,
+  IN CONST VOID* addr,
+  IN SCOPE_ID scope,
+  IN USHORT port)
+{
+  if (af == AF_INET6) {
+    IN6ADDR_SETSOCKADDR((PSOCKADDR_IN6) a, (CONST IN6_ADDR *) addr, scope, port);
+  } else {
+    CONST IN_ADDR addr4 = *((IN_ADDR UNALIGNED *) addr);
+    ASSERT(af == AF_INET);
+    IN4ADDR_SETSOCKADDR((PSOCKADDR_IN) a, (CONST IN_ADDR *) &addr4, port);
+  }
+}
+#endif /* (NTDDI_VERSION >= NTDDI_VISTA) */
+
+MSTCPIP_INLINE
+VOID
+INETADDR_SETANY(
+  OUT PSOCKADDR a)
+{
+  if (a->sa_family == AF_INET6) {
+    IN6ADDR_SETANY((PSOCKADDR_IN6)a);
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    IN4ADDR_SETANY((PSOCKADDR_IN)a);
+  }
+}
+
+MSTCPIP_INLINE
+VOID
+INETADDR_SETLOOPBACK(
+  OUT PSOCKADDR a)
+{
+  if (a->sa_family == AF_INET6) {
+    IN6ADDR_SETLOOPBACK((PSOCKADDR_IN6)a);
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    IN4ADDR_SETLOOPBACK((PSOCKADDR_IN)a);
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INETADDR_ISANY(
+  IN CONST SOCKADDR *a)
+{
+  if (a->sa_family == AF_INET6) {
+    return IN6ADDR_ISANY((CONST SOCKADDR_IN6*)a);
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    return IN4ADDR_ISANY((CONST SOCKADDR_IN*)a);
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INETADDR_ISLOOPBACK(
+  IN CONST SOCKADDR *a)
+{
+  if (a->sa_family == AF_INET6) {
+    return IN6ADDR_ISLOOPBACK((CONST SOCKADDR_IN6*)a);
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    return IN4ADDR_ISLOOPBACK((CONST SOCKADDR_IN*)a);
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INETADDR_ISV4MAPPED(IN CONST SOCKADDR *a)
+{
+  if (a->sa_family == AF_INET6) {
+    return IN6ADDR_ISV4MAPPED((CONST SOCKADDR_IN6*)a);
+  } else {
+    return FALSE;
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+NL_ADDR_EQUAL(
+  IN ADDRESS_FAMILY af,
+  IN SCOPE_ID sa,
+  IN CONST UCHAR* aa,
+  IN SCOPE_ID sb,
+  IN CONST UCHAR* ab)
+{
+  return (BOOLEAN)((sa.Value == sb.Value) && INET_ADDR_EQUAL(af, aa, ab));
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+NL_IS_ADDR_UNSPECIFIED(
+  IN ADDRESS_FAMILY af,
+  IN SCOPE_ID s,
+  IN CONST UCHAR* a)
+{
+  return (BOOLEAN)((s.Value == 0) && INET_IS_ADDR_UNSPECIFIED(af, a));
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INETADDR_ISEQUAL(
+  IN CONST SOCKADDR *a,
+  IN CONST SOCKADDR *b)
+{
+  if (a->sa_family == AF_INET6) {
+    return (BOOLEAN) (b->sa_family == AF_INET6 &&
+           IN6ADDR_ISEQUAL((CONST SOCKADDR_IN6*)a, (CONST SOCKADDR_IN6*)b));
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    return (BOOLEAN) (b->sa_family == AF_INET &&
+           IN4ADDR_ISEQUAL((CONST SOCKADDR_IN*)a, (CONST SOCKADDR_IN*)b));
+  }
+}
+
+MSTCPIP_INLINE
+BOOLEAN
+INETADDR_ISUNSPECIFIED(
+  IN CONST SOCKADDR *a)
+{
+  if (a->sa_family == AF_INET6) {
+    return IN6ADDR_ISUNSPECIFIED((CONST SOCKADDR_IN6*)a);
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    return IN4ADDR_ISUNSPECIFIED((CONST SOCKADDR_IN*)a);
+  }
+}
+
+#if (NTDDI_VERSION >= NTDDI_VISTA)
+MSTCPIP_INLINE
+SCOPE_ID
+INETADDR_SCOPE_ID(
+  IN CONST SOCKADDR *a)
+{
+  if (a->sa_family == AF_INET6) {
+    return ((CONST SOCKADDR_IN6*)a)->sin6_scope_struct;
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    return IN4ADDR_SCOPE_ID((CONST SOCKADDR_IN*)a);
+  }
+}
+#endif
+
+MSTCPIP_INLINE
+USHORT
+INETADDR_PORT(
+  IN CONST SOCKADDR *a)
+{
+  if (a->sa_family == AF_INET6) {
+    return ((CONST SOCKADDR_IN6*)a)->sin6_port;
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    return ((CONST SOCKADDR_IN*)a)->sin_port;
+  }
+}
+
+MSTCPIP_INLINE
+PUCHAR
+INETADDR_ADDRESS(
+  IN CONST SOCKADDR* a)
+{
+  if (a->sa_family == AF_INET6) {
+    return (PUCHAR)&((PSOCKADDR_IN6)a)->sin6_addr;
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    return (PUCHAR)&((PSOCKADDR_IN)a)->sin_addr;
+  }
+}
+
+MSTCPIP_INLINE
+VOID
+INETADDR_SET_PORT(
+  IN OUT PSOCKADDR a,
+  IN USHORT Port)
+{
+  SS_PORT(a) = Port;
+}
+
+MSTCPIP_INLINE
+VOID
+INETADDR_SET_ADDRESS(
+  IN OUT PSOCKADDR a,
+  IN CONST UCHAR *Address)
+{
+  if (a->sa_family == AF_INET6) {
+    ((PSOCKADDR_IN6)a)->sin6_addr = *((CONST IN6_ADDR*)Address);
+  } else {
+    ASSERT(a->sa_family == AF_INET);
+    ((PSOCKADDR_IN)a)->sin_addr = *((CONST IN_ADDR*)Address);
+  }
+}
+
+MSTCPIP_INLINE
+VOID
+INET_UNCANONICALIZE_SCOPE_ID(
+  IN ADDRESS_FAMILY AddressFamily,
+  IN CONST UCHAR *Address,
+  IN OUT SCOPE_ID *ScopeId)
+{
+  if (AddressFamily == AF_INET6) {
+    IN6_UNCANONICALIZE_SCOPE_ID((CONST IN6_ADDR*) Address, ScopeId);
+  } else {
+    IN4_UNCANONICALIZE_SCOPE_ID((CONST IN_ADDR*) Address, ScopeId);
+  }
+}
+
+#endif /* _WS2IPDEF_ */
+
+#ifndef __IP2STRING__
+#define __IP2STRING__
+
+#if (NTDDI_VERSION >= NTDDI_VISTA)
+
+#ifdef _WS2DEF_
+
+NTSYSAPI
+PSTR
+NTAPI
+RtlIpv4AddressToStringA(
+  IN const struct in_addr *Addr,
+  OUT PSTR S);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv4AddressToStringExA(
+  IN const struct in_addr *Address,
+  IN USHORT Port,
+  OUT PSTR AddressString,
+  IN OUT PULONG AddressStringLength);
+
+NTSYSAPI
+PWSTR
+NTAPI
+RtlIpv4AddressToStringW(
+  IN const struct in_addr *Addr,
+  OUT PWSTR S);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv4AddressToStringExW(
+  IN const struct in_addr *Address,
+  IN USHORT Port,
+  OUT PWSTR AddressString,
+  IN OUT PULONG AddressStringLength);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv4StringToAddressA(
+  IN PCSTR S,
+  IN BOOLEAN Strict,
+  OUT PCSTR *Terminator,
+  OUT struct in_addr *Addr);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv4StringToAddressExA(
+  IN PCSTR AddressString,
+  IN BOOLEAN Strict,
+  OUT struct in_addr *Address,
+  OUT PUSHORT Port);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv4StringToAddressW(
+  IN PCWSTR S,
+  IN BOOLEAN Strict,
+  OUT LPCWSTR *Terminator,
+  OUT struct in_addr *Addr);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv4StringToAddressExW(
+  IN PCWSTR AddressString,
+  IN BOOLEAN Strict,
+  OUT struct in_addr *Address,
+  OUT PUSHORT Port);
+
+#ifdef UNICODE
+#define RtlIpv4AddressToString RtlIpv4AddressToStringW
+#define RtlIpv4StringToAddress RtlIpv4StringToAddressW
+#define RtlIpv4AddressToStringEx RtlIpv4AddressToStringExW
+#define RtlIpv4StringToAddressEx RtlIpv4StringToAddressExW
+#else
+#define RtlIpv4AddressToString RtlIpv4AddressToStringA
+#define RtlIpv4StringToAddress RtlIpv4StringToAddressA
+#define RtlIpv4AddressToStringEx RtlIpv4AddressToStringExA
+#define RtlIpv4StringToAddressEx RtlIpv4StringToAddressExA
+#endif
+
+#endif /* _WS2DEF_ */
+
+#ifdef _WS2IPDEF_
+
+NTSYSAPI
+PSTR
+NTAPI
+RtlIpv6AddressToStringA(
+  IN const struct in6_addr *Addr,
+  OUT PSTR S);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv6AddressToStringExA(
+  IN const struct in6_addr *Address,
+  IN ULONG ScopeId,
+  IN USHORT Port,
+  OUT PSTR AddressString,
+  IN OUT PULONG AddressStringLength);
+
+NTSYSAPI
+PWSTR
+NTAPI
+RtlIpv6AddressToStringW(
+  IN const struct in6_addr *Addr,
+  OUT PWSTR S);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv6AddressToStringExW(
+  IN const struct in6_addr *Address,
+  IN ULONG ScopeId,
+  IN USHORT Port,
+  OUT PWSTR AddressString,
+  IN OUT PULONG AddressStringLength);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv6StringToAddressA(
+  IN PCSTR S,
+  OUT PCSTR *Terminator,
+  OUT struct in6_addr *Addr);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv6StringToAddressExA(
+  IN PCSTR AddressString,
+  OUT struct in6_addr *Address,
+  OUT PULONG ScopeId,
+  OUT PUSHORT Port);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv6StringToAddressW(
+  IN PCWSTR S,
+  OUT PCWSTR *Terminator,
+  OUT struct in6_addr *Addr);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlIpv6StringToAddressExW(
+  IN PCWSTR AddressString,
+  OUT struct in6_addr *Address,
+  OUT PULONG ScopeId,
+  OUT PUSHORT Port);
+
+#ifdef UNICODE
+#define RtlIpv6AddressToString RtlIpv6AddressToStringW
+#define RtlIpv6StringToAddress RtlIpv6StringToAddressW
+#define RtlIpv6StringToAddressEx RtlIpv6StringToAddressExW
+#define RtlIpv6AddressToStringEx RtlIpv6AddressToStringExW
+#else
+#define RtlIpv6AddressToString RtlIpv6AddressToStringA
+#define RtlIpv6StringToAddress RtlIpv6StringToAddressA
+#define RtlIpv6StringToAddressEx RtlIpv6StringToAddressExA
+#define RtlIpv6AddressToStringEx RtlIpv6AddressToStringExA
+#endif
+
+#endif /* __WS2IPDEF__ */
+
+#ifdef _WS2DEF_
+
+union _DL_EUI48;
+typedef union _DL_EUI48 DL_EUI48, *PDL_EUI48;
+
+NTSYSAPI
+PSTR
+NTAPI
+RtlEthernetAddressToStringA(
+  IN const DL_EUI48 *Addr,
+  OUT PSTR S);
+
+NTSYSAPI
+PWSTR
+NTAPI
+RtlEthernetAddressToStringW(
+  IN const DL_EUI48 *Addr,
+  OUT PWSTR S);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlEthernetStringToAddressA(
+  IN PCSTR S,
+  OUT PCSTR *Terminator,
+  OUT DL_EUI48 *Addr);
+
+NTSYSAPI
+LONG
+NTAPI
+RtlEthernetStringToAddressW(
+  IN PCWSTR S,
+  OUT LPCWSTR *Terminator,
+  OUT DL_EUI48 *Addr);
+
+#ifdef UNICODE
+#define RtlEthernetAddressToString RtlEthernetAddressToStringW
+#define RtlEthernetStringToAddress RtlEthernetStringToAddressW
+#else
+#define RtlEthernetAddressToString RtlEthernetAddressToStringA
+#define RtlEthernetStringToAddress RtlEthernetStringToAddressA
+#endif
+
+#endif /* _WS2DEF_ */
+
+#endif /* (NTDDI >= NTDDI_VISTA) */
+
+#endif /* __IP2STRING__ */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/psdk/wsipv6ok.h b/include/psdk/wsipv6ok.h
new file mode 100644 (file)
index 0000000..b995025
--- /dev/null
@@ -0,0 +1,83 @@
+#pragma once
+
+#ifdef IPV6STRICT
+
+#include <ws2tcpip.h>
+#include <wspiapi.h>
+
+#undef AF_INET
+#define AF_INET AF_INET_IPV6INCOMPATIBLE
+#undef PF_INET
+#define PF_INET PF_INET_IPV6INCOMPATIBLE
+#undef in_addr
+#define in_addr in_addr_IPV6INCOMPATIBLE
+#undef IN_ADDR
+#define IN_ADDR IN_ADDR_IPV6INCOMPATIBLE
+#undef PIN_ADDR
+#define PIN_ADDR PIN_ADDR_IPV6INCOMPATIBLE
+#undef LPIN_ADDR
+#define LPIN_ADDR LPIN_ADDR_IPV6INCOMPATIBLE
+#undef IPAddr
+#define IPAddr IPAddr_IPV6INCOMPATIBLE
+#undef sockaddr_in
+#define sockaddr_in sockaddr_in_IPV6INCOMPATIBLE
+#undef SOCKADDR_IN
+#define SOCKADDR_IN SOCKADDR_IN_IPV6INCOMPATIBLE
+#undef PSOCKADDR_IN
+#define PSOCKADDR_IN PSOCKADDR_IN_IPV6INCOMPATIBLE
+#undef LPSOCKADDR_IN
+#define LPSOCKADDR_IN LPSOCKADDR_IN_IPV6INCOMPATIBLE
+#undef INADDR_ANY
+#define INADDR_ANY INADDR_ANY_IPV6INCOMPATIBLE
+#undef INADDR_LOOPBACK
+#define INADDR_LOOPBACK INADDR_LOOPBACK_IPV6INCOMPATIBLE
+#undef IPPROTO_IP
+#define IPPROTO_IP IPPROTO_IP_IPV6INCOMPATIBLE
+#undef IP_MULTICAST_IF
+#define IP_MULTICAST_IF IP_MULTICAST_IF_IPV6INCOMPATIBLE
+#undef IP_MULTICAST_TTL
+#define IP_MULTICAST_TTL IP_MULTICAST_TTL_IPV6INCOMPATIBLE
+#undef IP_MULTICAST_LOOP
+#define IP_MULTICAST_LOOP IP_MULTICAST_LOOP_IPV6INCOMPATIBLE
+#undef IP_ADD_MEMBERSHIP
+#define IP_ADD_MEMBERSHIP IP_ADD_MEMBERSHIP_IPV6INCOMPATIBLE
+#undef IP_DROP_MEMBERSHIP
+#define IP_DROP_MEMBERSHIP IP_DROP_MEMBERSHIP_IPV6INCOMPATIBLE
+#undef ip_mreq
+#define ip_mreq ip_mreq_IPV6INCOMPATIBLE
+#undef gethostbyname
+#define gethostbyname(a) gethostbyname_IPV6INCOMPATIBLE
+#undef hostent
+#define hostent hostent_IPV6INCOMPATIBLE
+#undef HOSTENT
+#define HOSTENT HOSTENT_IPV6INCOMPATIBLE
+#undef PHOSTENT
+#define PHOSTENT PHOSTENT_IPV6INCOMPATIBLE
+#undef LPHOSTENT
+#define LPHOSTENT LPHOSTENT_IPV6INCOMPATIBLE
+#undef inet_addr
+#define inet_addr(a) inet_addr_IPV6INCOMPATIBLE
+#undef gethostbyaddr
+#define gethostbyaddr(a,b,c) gethostbyaddr_IPV6INCOMPATIBLE
+#undef inet_ntoa
+#define inet_ntoa(a) inet_ntoa_IPV6INCOMPATIBLE
+#undef IN_MULTICAST
+#define IN_MULTICAST(a) IN_MULTICAST_IPV6INCOMPATIBLE
+#undef IN_CLASSD
+#define IN_CLASSD(a) IN_CLASSD_IPV6INCOMPATIBLE
+#undef IP_TTL
+#define IP_TTL IP_TTL_IPV6INCOMPATIBLE
+#undef IN_CLASSA
+#define IN_CLASSA(a) IN_CLASSA_IPV6INCOMPATIBLE
+#undef IN_CLASSB
+#define IN_CLASSB(a) IN_CLASSB_IPV6INCOMPATIBLE
+#undef IN_CLASSC
+#define IN_CLASSC(a) IN_CLASSC_IPV6INCOMPATIBLE
+#undef INADDR_BROADCAST
+#define INADDR_BROADCAST(a) INADDR_BROADCAST_IPV6INCOMPATIBLE
+#undef WSAAsyncGetHostByAddr
+#define WSAAsyncGetHostByAddr(a,b,c,d,e,f,g) WSAAsyncGetHostByAddr_IPV6INCOMPATIBLE
+#undef WSAAsyncGetHostByName
+#define WSAAsyncGetHostByName(a,b,c,d,e) WSAAsyncGetHostByName_IPV6INCOMPATIBLE
+
+#endif
\ No newline at end of file
diff --git a/include/psdk/wspiapi.h b/include/psdk/wspiapi.h
new file mode 100644 (file)
index 0000000..12c8ac4
--- /dev/null
@@ -0,0 +1,564 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (NTDDI_VERSION >= NTDDI_WIN2K)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+#if defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L
+
+#define _WSPIAPI_STRCPY_S strcpy_s
+#define _WSPIAPI_STRCAT_S strcat_s
+#define _WSPIAPI_STRNCPY_S strncpy_s
+#define _WSPIAPI_SPRINTF_S_1 sprintf_s
+
+#else
+
+#define _WSPIAPI_STRCPY_S(_Dst, _Size, _Src) strcpy((_Dst), (_Src))
+#define _WSPIAPI_STRCAT_S(_Dst, _Size, _Src) strcat((_Dst), (_Src))
+#define _WSPIAPI_STRNCPY_S(_Dst, _Size, _Src, _Count) strncpy((_Dst), (_Src), (_Count)); (_Dst)[(_Size) - 1] = 0
+#define _WSPIAPI_SPRINTF_S_1(_Dst, _Size, _Format, _Arg1) sprintf((_Dst), (_Format), (_Arg1))
+
+#endif /* #if defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L */
+
+#if !defined(_WSPIAPI_COUNTOF)
+
+#if !defined(__cplusplus)
+#define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#else
+template <typename __CountofType, size_t _N>
+char (&__wspiapi_countof_helper(__CountofType (&_Array)[_N]))[_N];
+#define _WSPIAPI_COUNTOF(_Array) sizeof(__wspiapi_countof_helper(_Array))
+#endif
+
+#endif /* !defined(_WSPIAPI_COUNTOF) */
+
+#define WspiapiMalloc(tSize) calloc(1, (tSize))
+#define WspiapiFree(p) free(p)
+#define WspiapiSwap(a, b, c) {(c) = (a); (a) = (b); (b) = (c);}
+#define getaddrinfo WspiapiGetAddrInfo
+#define getnameinfo WspiapiGetNameInfo
+#define freeaddrinfo WspiapiFreeAddrInfo
+
+typedef int
+(WINAPI *WSPIAPI_PGETADDRINFO)(
+  IN const char *nodename,
+  IN const char *servname,
+  IN const struct addrinfo *hints,
+  OUT struct addrinfo **res);
+
+typedef int
+(WINAPI *WSPIAPI_PGETNAMEINFO)(
+  IN const struct sockaddr *sa,
+  IN socklen_t salen,
+  OUT char *host,
+  IN size_t hostlen,
+  OUT char *serv,
+  IN size_t servlen,
+  IN int flags);
+
+typedef void
+(WINAPI *WSPIAPI_PFREEADDRINFO)(
+  IN struct addrinfo *ai);
+
+__inline
+char *
+WINAPI
+WspiapiStrdup(
+  IN const char *pszString)
+{
+  char *pszMemory;
+  size_t cchMemory;
+
+  if (!pszString) return(NULL);
+  cchMemory = strlen(pszString) + 1;
+  pszMemory = (char *) WspiapiMalloc(cchMemory);
+  if (!pszMemory) return(NULL);
+  _WSPIAPI_STRCPY_S(pszMemory, cchMemory, pszString);
+  return pszMemory;
+}
+
+__inline
+BOOL
+WINAPI
+WspiapiParseV4Address(
+  IN const char *pszAddress,
+  OUT PDWORD pdwAddress)
+{
+  DWORD dwAddress = 0;
+  const char *pcNext = NULL;
+  int iCount = 0;
+
+  for (pcNext = pszAddress; *pcNext != '\0'; pcNext++)
+    if (*pcNext == '.') iCount++;
+  if (iCount != 3) return FALSE;
+  dwAddress = inet_addr(pszAddress);
+  if (dwAddress == INADDR_NONE) return FALSE;
+  *pdwAddress = dwAddress;
+  return TRUE;
+}
+
+__inline
+struct addrinfo *
+WINAPI
+WspiapiNewAddrInfo(
+  IN int iSocketType,
+  IN int iProtocol,
+  IN WORD wPort,
+  IN DWORD dwAddress)
+{
+  struct addrinfo *ptNew;
+  struct sockaddr_in *ptAddress;
+
+  ptNew = (struct addrinfo *) WspiapiMalloc(sizeof(struct addrinfo));
+  if (!ptNew) return NULL;
+  ptAddress = (struct sockaddr_in *) WspiapiMalloc(sizeof(struct sockaddr_in));
+  if (!ptAddress) {
+    WspiapiFree(ptNew);
+    return NULL;
+  }
+  ptAddress->sin_family = AF_INET;
+  ptAddress->sin_port = wPort;
+  ptAddress->sin_addr.s_addr = dwAddress;
+  ptNew->ai_family = PF_INET;
+  ptNew->ai_socktype = iSocketType;
+  ptNew->ai_protocol = iProtocol;
+  ptNew->ai_addrlen = sizeof(struct sockaddr_in);
+  ptNew->ai_addr = (struct sockaddr *) ptAddress;
+
+  return ptNew;
+}
+
+__inline
+int
+WINAPI
+WspiapiQueryDNS(
+  IN const char *pszNodeName,
+  IN int iSocketType,
+  IN int iProtocol,
+  IN WORD wPort,
+  OUT char pszAlias[NI_MAXHOST],
+  OUT struct addrinfo **pptResult)
+{
+  struct addrinfo **pptNext = pptResult;
+  struct hostent *ptHost = NULL;
+  char **ppAddresses;
+
+  *pptNext = NULL;
+  pszAlias[0] = '\0';
+
+  ptHost = gethostbyname(pszNodeName);
+  if (ptHost) {
+    if ((ptHost->h_addrtype == AF_INET) && (ptHost->h_length == sizeof(struct in_addr))) {
+      for (ppAddresses = ptHost->h_addr_list; *ppAddresses != NULL; ppAddresses++) {
+        *pptNext = WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, ((struct in_addr *) *ppAddresses)->s_addr);
+        if (!*pptNext) return EAI_MEMORY;
+        pptNext = &((*pptNext)->ai_next);
+      }
+    }
+    _WSPIAPI_STRNCPY_S(pszAlias, NI_MAXHOST, ptHost->h_name, NI_MAXHOST - 1);
+    return 0;
+  }
+  switch (WSAGetLastError()) {
+    case WSAHOST_NOT_FOUND: return EAI_NONAME;
+    case WSATRY_AGAIN: return EAI_AGAIN;
+    case WSANO_RECOVERY: return EAI_FAIL;
+    case WSANO_DATA: return EAI_NODATA;
+    default: return EAI_NONAME;
+  }
+}
+
+__inline
+int
+WINAPI
+WspiapiLookupNode(
+  IN const char *pszNodeName,
+  IN int iSocketType,
+  IN int iProtocol,
+  IN WORD wPort,
+  IN BOOL bAI_CANONNAME,
+  OUT struct addrinfo **pptResult)
+{
+  int iError = 0;
+  int iAliasCount = 0;
+  char szFQDN1[NI_MAXHOST] = "";
+  char szFQDN2[NI_MAXHOST] = "";
+  char *pszName = szFQDN1;
+  char *pszAlias = szFQDN2;
+  char *pszScratch = NULL;
+
+  _WSPIAPI_STRNCPY_S(pszName, NI_MAXHOST, pszNodeName, NI_MAXHOST - 1);
+  for (;;) {
+    iError = WspiapiQueryDNS(pszNodeName, iSocketType, iProtocol, wPort, pszAlias, pptResult);
+    if (iError) break;
+    if (*pptResult) break;
+    if ((!strlen(pszAlias)) || (!strcmp(pszName, pszAlias)) || (++iAliasCount == 16)) {
+      iError = EAI_FAIL;
+      break;
+    }
+    WspiapiSwap(pszName, pszAlias, pszScratch);
+  }
+  if (!iError && bAI_CANONNAME) {
+    (*pptResult)->ai_canonname = WspiapiStrdup(pszAlias);
+    if (!(*pptResult)->ai_canonname) iError = EAI_MEMORY;
+  }
+
+  return iError;
+}
+
+
+
+__inline
+int
+WINAPI
+WspiapiClone(
+  IN WORD wPort,
+  IN struct addrinfo *ptResult)
+{
+  struct addrinfo *ptNext = NULL;
+  struct addrinfo *ptNew  = NULL;
+
+  for (ptNext = ptResult; ptNext != NULL; ) {
+    ptNew = WspiapiNewAddrInfo(SOCK_DGRAM, ptNext->ai_protocol, wPort,
+                               ((struct sockaddr_in *) ptNext->ai_addr)->sin_addr.s_addr);
+    if (!ptNew) break;
+    ptNew->ai_next = ptNext->ai_next;
+    ptNext->ai_next = ptNew;
+    ptNext = ptNew->ai_next;
+  }
+  if (ptNext != NULL) return EAI_MEMORY;
+
+  return 0;
+}
+
+__inline
+void
+WINAPI
+WspiapiLegacyFreeAddrInfo(
+  IN  struct addrinfo *ptHead)
+{
+  struct addrinfo *ptNext;
+
+  for (ptNext = ptHead; ptNext != NULL; ptNext = ptHead) {
+    if (ptNext->ai_canonname) WspiapiFree(ptNext->ai_canonname);
+    if (ptNext->ai_addr) WspiapiFree(ptNext->ai_addr);
+    ptHead = ptNext->ai_next;
+    WspiapiFree(ptNext);
+  }
+}
+
+__inline
+int
+WINAPI
+WspiapiLegacyGetAddrInfo(
+  IN const char *pszNodeName,
+  IN const char *pszServiceName,
+  IN const struct addrinfo *ptHints,
+  OUT struct addrinfo **pptResult)
+{
+  int iError = 0;
+  int iFlags = 0;
+  int iFamily = PF_UNSPEC;
+  int iSocketType = 0;
+  int iProtocol = 0;
+  WORD wPort = 0;
+  DWORD dwAddress = 0;
+  struct servent *ptService = NULL;
+  char *pc = NULL;
+  BOOL bClone = FALSE;
+  WORD wTcpPort = 0;
+  WORD wUdpPort = 0;
+  *pptResult  = NULL;
+
+  if ((!pszNodeName) && (!pszServiceName)) return EAI_NONAME;
+  if (ptHints) {
+    if ((ptHints->ai_addrlen != 0) ||
+        (ptHints->ai_canonname != NULL) ||
+        (ptHints->ai_addr != NULL) ||
+        (ptHints->ai_next != NULL)) {
+      return EAI_FAIL;
+    }
+    iFlags = ptHints->ai_flags;
+    if ((iFlags & AI_CANONNAME) && !pszNodeName) return EAI_BADFLAGS;
+    iFamily = ptHints->ai_family;
+    if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET)) return EAI_FAMILY;
+    iSocketType = ptHints->ai_socktype;
+    if ((iSocketType != 0) &&
+        (iSocketType != SOCK_STREAM) &&
+        (iSocketType != SOCK_DGRAM) &&
+        (iSocketType != SOCK_RAW))
+      return EAI_SOCKTYPE;
+    iProtocol = ptHints->ai_protocol;
+  }
+  if (pszServiceName) {
+    wPort = (WORD) strtoul(pszServiceName, &pc, 10);
+    if (*pc == '\0') {
+      wPort = wTcpPort = wUdpPort = htons(wPort);
+      if (iSocketType == 0) {
+        bClone = TRUE;
+        iSocketType = SOCK_STREAM;
+      }
+    }
+    else {
+      if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM)) {
+        ptService = getservbyname(pszServiceName, "udp");
+        if (ptService) wPort = wUdpPort = ptService->s_port;
+      }
+      if ((iSocketType == 0) || (iSocketType == SOCK_STREAM)) {
+        ptService = getservbyname(pszServiceName, "tcp");
+        if (ptService) wPort = wTcpPort = ptService->s_port;
+      }
+      if (wPort == 0) return (iSocketType ? EAI_SERVICE : EAI_NONAME);
+      if (iSocketType == 0) {
+        iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
+        bClone = (wTcpPort && wUdpPort); 
+      }
+    }
+  }
+  if ((!pszNodeName) || (WspiapiParseV4Address(pszNodeName, &dwAddress))) {
+    if (!pszNodeName) dwAddress = htonl((iFlags & AI_PASSIVE) ? INADDR_ANY : INADDR_LOOPBACK);
+    *pptResult = WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
+    if (!(*pptResult)) iError = EAI_MEMORY;
+    if (!iError && pszNodeName) {
+      (*pptResult)->ai_flags |= AI_NUMERICHOST;
+      if (iFlags & AI_CANONNAME) {
+        (*pptResult)->ai_canonname = WspiapiStrdup(inet_ntoa(*((struct in_addr *) &dwAddress)));
+        if (!(*pptResult)->ai_canonname) iError = EAI_MEMORY;
+      }
+    }
+  }
+  else if (iFlags & AI_NUMERICHOST) {
+    iError = EAI_NONAME;
+  }
+  else {
+    iError = WspiapiLookupNode(pszNodeName, iSocketType,
+                               iProtocol, wPort,
+                               (iFlags & AI_CANONNAME),
+                               pptResult);
+  }
+  if (!iError && bClone) {
+    iError = WspiapiClone(wUdpPort, *pptResult);
+  }
+  if (iError) {
+    WspiapiLegacyFreeAddrInfo(*pptResult);
+    *pptResult = NULL;
+  }
+
+  return (iError);
+}
+
+__inline
+int
+WINAPI
+WspiapiLegacyGetNameInfo(
+  IN const struct sockaddr *ptSocketAddress,
+  IN socklen_t tSocketLength,
+  OUT char *pszNodeName,
+  IN size_t tNodeLength,
+  OUT char *pszServiceName,
+  IN size_t tServiceLength,
+  IN int iFlags)
+{
+  struct servent *ptService;
+  WORD wPort;
+  char szBuffer[] = "65535";
+  char *pszService = szBuffer;
+  struct hostent *ptHost;
+  struct in_addr tAddress;
+  char *pszNode = NULL;
+  char *pc = NULL;
+
+  if ((!ptSocketAddress) || (tSocketLength < sizeof(struct sockaddr))) return EAI_FAIL;
+  if (ptSocketAddress->sa_family != AF_INET) return EAI_FAMILY;
+  if (tSocketLength < sizeof(struct sockaddr_in)) return EAI_FAIL;
+  if (!(pszNodeName && tNodeLength) && !(pszServiceName && tServiceLength)) {
+    return EAI_NONAME;
+  }
+  if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD)) {
+    return EAI_BADFLAGS;
+  }
+  if (pszServiceName && tServiceLength) {
+    wPort = ((struct sockaddr_in *) ptSocketAddress)->sin_port;
+    if (iFlags & NI_NUMERICSERV) {
+      _WSPIAPI_SPRINTF_S_1(szBuffer, _WSPIAPI_COUNTOF(szBuffer), "%u", ntohs(wPort));
+    }
+    else {
+      ptService = getservbyport(wPort, (iFlags & NI_DGRAM) ? "udp" : NULL);
+      if (ptService && ptService->s_name) {
+        pszService = ptService->s_name;
+      }
+      else {
+        _WSPIAPI_SPRINTF_S_1(szBuffer, _WSPIAPI_COUNTOF(szBuffer), "%u", ntohs(wPort));
+      }
+    }
+    if (tServiceLength > strlen(pszService))
+      _WSPIAPI_STRCPY_S(pszServiceName, tServiceLength, pszService);
+    else return EAI_FAIL;
+  }
+  if (pszNodeName && tNodeLength) {
+    tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr;
+    if (iFlags & NI_NUMERICHOST) {
+      pszNode = inet_ntoa(tAddress);
+    }
+    else {
+      ptHost = gethostbyaddr((char *) &tAddress, sizeof(struct in_addr), AF_INET);
+      if (ptHost && ptHost->h_name) {
+        pszNode = ptHost->h_name;
+        if ((iFlags & NI_NOFQDN) && ((pc = strchr(pszNode, '.')) != NULL)) *pc = '\0';
+      }
+      else {
+        if (iFlags & NI_NAMEREQD) {
+          switch (WSAGetLastError()) {
+            case WSAHOST_NOT_FOUND: return EAI_NONAME;
+            case WSATRY_AGAIN: return EAI_AGAIN;
+            case WSANO_RECOVERY: return EAI_FAIL;
+            default: return EAI_NONAME;
+          }
+        }
+        else pszNode = inet_ntoa(tAddress);
+      }
+    }
+    if (tNodeLength > strlen(pszNode)) _WSPIAPI_STRCPY_S(pszNodeName, tNodeLength, pszNode);
+    else return EAI_FAIL;
+  }
+
+  return 0;
+}
+
+typedef struct {
+  char const *pszName;
+  FARPROC pfAddress;
+} WSPIAPI_FUNCTION;
+
+#define WSPIAPI_FUNCTION_ARRAY {                         \
+  "getaddrinfo", (FARPROC) WspiapiLegacyGetAddrInfo,     \
+  "getnameinfo", (FARPROC) WspiapiLegacyGetNameInfo,     \
+  "freeaddrinfo", (FARPROC) WspiapiLegacyFreeAddrInfo,   \
+}
+
+__inline
+FARPROC
+WINAPI
+WspiapiLoad(
+  IN WORD wFunction)
+{
+  HMODULE hLibrary = NULL;
+
+  static BOOL bInitialized = FALSE;
+  static WSPIAPI_FUNCTION rgtGlobal[] = WSPIAPI_FUNCTION_ARRAY;
+  static const int iNumGlobal = (sizeof(rgtGlobal) / sizeof(WSPIAPI_FUNCTION));
+  WSPIAPI_FUNCTION rgtLocal[] = WSPIAPI_FUNCTION_ARRAY;
+  FARPROC fScratch = NULL;
+  int i = 0;
+
+  if (bInitialized) return (rgtGlobal[wFunction].pfAddress);
+  for (;;) {
+    CHAR SystemDir[MAX_PATH + 1];
+    CHAR Path[MAX_PATH + 8];
+    if (GetSystemDirectoryA(SystemDir, MAX_PATH) == 0) break;
+    _WSPIAPI_STRCPY_S(Path, _WSPIAPI_COUNTOF(Path), SystemDir);
+    _WSPIAPI_STRCAT_S(Path, _WSPIAPI_COUNTOF(Path), "\\ws2_32");
+    hLibrary = LoadLibraryA(Path);
+    if (hLibrary != NULL) {
+      fScratch = GetProcAddress(hLibrary, "getaddrinfo");
+      if (fScratch == NULL) {
+        FreeLibrary(hLibrary);
+        hLibrary = NULL;
+      }
+    }
+    if (hLibrary != NULL) break;
+    _WSPIAPI_STRCPY_S(Path, _WSPIAPI_COUNTOF(Path), SystemDir);
+    _WSPIAPI_STRCAT_S(Path, _WSPIAPI_COUNTOF(Path), "\\wship6");
+    hLibrary = LoadLibraryA(Path);
+    if (hLibrary != NULL) {
+      fScratch = GetProcAddress(hLibrary, "getaddrinfo");
+      if (fScratch == NULL) {
+        FreeLibrary(hLibrary);
+        hLibrary = NULL;
+      }
+    }
+    break;
+  }
+  if (hLibrary != NULL) {
+    for (i = 0; i < iNumGlobal; i++) {
+      rgtLocal[i].pfAddress = GetProcAddress(hLibrary, rgtLocal[i].pszName);
+      if (rgtLocal[i].pfAddress == NULL) {
+        FreeLibrary(hLibrary);
+        hLibrary = NULL;
+        break;
+      }
+    }
+    if (hLibrary != NULL) {
+      for (i = 0; i < iNumGlobal; i++)
+        rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress;
+    }
+  }
+  bInitialized = TRUE;
+
+  return (rgtGlobal[wFunction].pfAddress);
+}
+
+__inline
+int
+WINAPI
+WspiapiGetAddrInfo(
+  IN const char *nodename OPTIONAL,
+  IN const char *servname OPTIONAL,
+  IN const struct addrinfo *hints OPTIONAL,
+  OUT struct addrinfo **res)
+{
+  int iError;
+  static WSPIAPI_PGETADDRINFO pfGetAddrInfo = NULL;
+
+  if (!pfGetAddrInfo) pfGetAddrInfo = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0);
+  iError = (*pfGetAddrInfo)(nodename, servname, hints, res);
+  WSASetLastError(iError);
+
+  return iError;
+}
+
+__inline
+int
+WINAPI
+WspiapiGetNameInfo(
+  IN const struct sockaddr *sa,
+  IN socklen_t salen,
+  OUT char *host,
+  IN size_t hostlen,
+  OUT char *serv,
+  IN size_t servlen,
+  IN int flags)
+{
+  int iError;
+  static WSPIAPI_PGETNAMEINFO pfGetNameInfo = NULL;
+
+  if (!pfGetNameInfo) pfGetNameInfo = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1);
+  iError = (*pfGetNameInfo)(sa, salen, host, hostlen, serv, servlen, flags);
+  WSASetLastError(iError);
+
+  return iError;
+}
+
+__inline
+void
+WINAPI
+WspiapiFreeAddrInfo(
+  IN struct addrinfo *ai)
+{
+  static WSPIAPI_PFREEADDRINFO    pfFreeAddrInfo   = NULL;
+
+  if (!pfFreeAddrInfo) pfFreeAddrInfo = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2);
+  (*pfFreeAddrInfo)(ai);
+}
+
+#endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */
+
+#ifdef __cplusplus
+}
+#endif