- New winsock (part 2 of x)
authorCameron Gutman <aicommander@gmail.com>
Sat, 6 Feb 2010 02:40:26 +0000 (02:40 +0000)
committerCameron Gutman <aicommander@gmail.com>
Sat, 6 Feb 2010 02:40:26 +0000 (02:40 +0000)
 - Replace the old mswsock with the new one

svn path=/branches/aicom-network-branch/; revision=45449

84 files changed:
dll/win32/mswsock/dns/addr.c [new file with mode: 0644]
dll/win32/mswsock/dns/debug.c [new file with mode: 0644]
dll/win32/mswsock/dns/dnsaddr.c [new file with mode: 0644]
dll/win32/mswsock/dns/dnsutil.c [new file with mode: 0644]
dll/win32/mswsock/dns/flatbuf.c [new file with mode: 0644]
dll/win32/mswsock/dns/hostent.c [new file with mode: 0644]
dll/win32/mswsock/dns/inc/dnslib.h [new file with mode: 0644]
dll/win32/mswsock/dns/inc/dnslibp.h [new file with mode: 0644]
dll/win32/mswsock/dns/inc/windnsp.h [new file with mode: 0644]
dll/win32/mswsock/dns/ip6.c [new file with mode: 0644]
dll/win32/mswsock/dns/memory.c [new file with mode: 0644]
dll/win32/mswsock/dns/name.c [new file with mode: 0644]
dll/win32/mswsock/dns/print.c [new file with mode: 0644]
dll/win32/mswsock/dns/record.c [new file with mode: 0644]
dll/win32/mswsock/dns/rrprint.c [new file with mode: 0644]
dll/win32/mswsock/dns/sablob.c [new file with mode: 0644]
dll/win32/mswsock/dns/straddr.c [new file with mode: 0644]
dll/win32/mswsock/dns/string.c [new file with mode: 0644]
dll/win32/mswsock/dns/table.c [new file with mode: 0644]
dll/win32/mswsock/dns/utf8.c [new file with mode: 0644]
dll/win32/mswsock/extensions.c [deleted file]
dll/win32/mswsock/msafd/accept.c [new file with mode: 0644]
dll/win32/mswsock/msafd/addrconv.c [new file with mode: 0644]
dll/win32/mswsock/msafd/afdsan.c [new file with mode: 0644]
dll/win32/mswsock/msafd/async.c [new file with mode: 0644]
dll/win32/mswsock/msafd/bind.c [new file with mode: 0644]
dll/win32/mswsock/msafd/connect.c [new file with mode: 0644]
dll/win32/mswsock/msafd/eventsel.c [new file with mode: 0644]
dll/win32/mswsock/msafd/getname.c [new file with mode: 0644]
dll/win32/mswsock/msafd/helper.c [new file with mode: 0644]
dll/win32/mswsock/msafd/listen.c [new file with mode: 0644]
dll/win32/mswsock/msafd/nspeprot.c [new file with mode: 0644]
dll/win32/mswsock/msafd/proc.c [new file with mode: 0644]
dll/win32/mswsock/msafd/recv.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sanaccpt.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sanconn.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sanflow.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sanlistn.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sanprov.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sanrdma.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sanrecv.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sansend.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sanshutd.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sansock.c [new file with mode: 0644]
dll/win32/mswsock/msafd/santf.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sanutil.c [new file with mode: 0644]
dll/win32/mswsock/msafd/select.c [new file with mode: 0644]
dll/win32/mswsock/msafd/send.c [new file with mode: 0644]
dll/win32/mswsock/msafd/shutdown.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sockerr.c [new file with mode: 0644]
dll/win32/mswsock/msafd/socket.c [new file with mode: 0644]
dll/win32/mswsock/msafd/sockopt.c [new file with mode: 0644]
dll/win32/mswsock/msafd/spi.c [new file with mode: 0644]
dll/win32/mswsock/msafd/tpackets.c [new file with mode: 0644]
dll/win32/mswsock/msafd/tranfile.c [new file with mode: 0644]
dll/win32/mswsock/msafd/wspmisc.c [new file with mode: 0644]
dll/win32/mswsock/mswsock.rbuild
dll/win32/mswsock/mswsock/init.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/msext.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/nspgaddr.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/nspmisc.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/nspsvc.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/nsptcpip.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/nsputil.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/proc.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/recvex.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/setup.c [new file with mode: 0644]
dll/win32/mswsock/mswsock/stubs.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/context.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/getserv.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/init.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/logit.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/lookup.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/nbt.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/nsp.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/oldutil.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/proc.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/r_comp.c [new file with mode: 0644]
dll/win32/mswsock/rnr20/util.c [new file with mode: 0644]
dll/win32/mswsock/stubs.c [deleted file]
dll/win32/mswsock/wsmobile/lpc.c [new file with mode: 0644]
dll/win32/mswsock/wsmobile/nsp.c [new file with mode: 0644]
dll/win32/mswsock/wsmobile/service.c [new file with mode: 0644]
dll/win32/mswsock/wsmobile/update.c [new file with mode: 0644]

diff --git a/dll/win32/mswsock/dns/addr.c b/dll/win32/mswsock/dns/addr.c
new file mode 100644 (file)
index 0000000..8742b30
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/addr.c
+ * PURPOSE:     Contains the Address Family Information Tables
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+DNS_FAMILY_INFO AddrFamilyTable[3] =
+{
+    {
+        AF_INET,
+        DNS_TYPE_A,
+        sizeof(IP4_ADDRESS),
+        sizeof(SOCKADDR_IN),
+        FIELD_OFFSET(SOCKADDR_IN, sin_addr)
+    },
+    {
+        AF_INET6,
+        DNS_TYPE_AAAA,
+        sizeof(IP6_ADDRESS),
+        sizeof(SOCKADDR_IN6),
+        FIELD_OFFSET(SOCKADDR_IN6, sin6_addr)
+    },
+    {
+        AF_ATM,
+        DNS_TYPE_ATMA,
+        sizeof(ATM_ADDRESS),
+        sizeof(SOCKADDR_ATM),
+        FIELD_OFFSET(SOCKADDR_ATM, satm_number)
+    }
+};
+
+/* FUNCTIONS *****************************************************************/
+
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily)
+{
+    /* Check which family this is */
+    switch (AddressFamily)
+    {
+        case AF_INET:
+            /* Return IPv4 Family Info */
+            return &AddrFamilyTable[0];
+        
+        case AF_INET6:
+            /* Return IPv6 Family Info */
+            return &AddrFamilyTable[1];
+        
+        case AF_ATM:
+            /* Return ATM Family Info */
+            return &AddrFamilyTable[2];
+        
+        default:
+            /* Invalid family */
+            return NULL;
+    }
+
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/addr.c
+ * PURPOSE:     Contains the Address Family Information Tables
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+DNS_FAMILY_INFO AddrFamilyTable[3] =
+{
+    {
+        AF_INET,
+        DNS_TYPE_A,
+        sizeof(IP4_ADDRESS),
+        sizeof(SOCKADDR_IN),
+        FIELD_OFFSET(SOCKADDR_IN, sin_addr)
+    },
+    {
+        AF_INET6,
+        DNS_TYPE_AAAA,
+        sizeof(IP6_ADDRESS),
+        sizeof(SOCKADDR_IN6),
+        FIELD_OFFSET(SOCKADDR_IN6, sin6_addr)
+    },
+    {
+        AF_ATM,
+        DNS_TYPE_ATMA,
+        sizeof(ATM_ADDRESS),
+        sizeof(SOCKADDR_ATM),
+        FIELD_OFFSET(SOCKADDR_ATM, satm_number)
+    }
+};
+
+/* FUNCTIONS *****************************************************************/
+
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily)
+{
+    /* Check which family this is */
+    switch (AddressFamily)
+    {
+        case AF_INET:
+            /* Return IPv4 Family Info */
+            return &AddrFamilyTable[0];
+        
+        case AF_INET6:
+            /* Return IPv6 Family Info */
+            return &AddrFamilyTable[1];
+        
+        case AF_ATM:
+            /* Return ATM Family Info */
+            return &AddrFamilyTable[2];
+        
+        default:
+            /* Invalid family */
+            return NULL;
+    }
+
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/addr.c
+ * PURPOSE:     Contains the Address Family Information Tables
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+DNS_FAMILY_INFO AddrFamilyTable[3] =
+{
+    {
+        AF_INET,
+        DNS_TYPE_A,
+        sizeof(IP4_ADDRESS),
+        sizeof(SOCKADDR_IN),
+        FIELD_OFFSET(SOCKADDR_IN, sin_addr)
+    },
+    {
+        AF_INET6,
+        DNS_TYPE_AAAA,
+        sizeof(IP6_ADDRESS),
+        sizeof(SOCKADDR_IN6),
+        FIELD_OFFSET(SOCKADDR_IN6, sin6_addr)
+    },
+    {
+        AF_ATM,
+        DNS_TYPE_ATMA,
+        sizeof(ATM_ADDRESS),
+        sizeof(SOCKADDR_ATM),
+        FIELD_OFFSET(SOCKADDR_ATM, satm_number)
+    }
+};
+
+/* FUNCTIONS *****************************************************************/
+
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily)
+{
+    /* Check which family this is */
+    switch (AddressFamily)
+    {
+        case AF_INET:
+            /* Return IPv4 Family Info */
+            return &AddrFamilyTable[0];
+        
+        case AF_INET6:
+            /* Return IPv6 Family Info */
+            return &AddrFamilyTable[1];
+        
+        case AF_ATM:
+            /* Return ATM Family Info */
+            return &AddrFamilyTable[2];
+        
+        default:
+            /* Invalid family */
+            return NULL;
+    }
+
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/addr.c
+ * PURPOSE:     Contains the Address Family Information Tables
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+DNS_FAMILY_INFO AddrFamilyTable[3] =
+{
+    {
+        AF_INET,
+        DNS_TYPE_A,
+        sizeof(IP4_ADDRESS),
+        sizeof(SOCKADDR_IN),
+        FIELD_OFFSET(SOCKADDR_IN, sin_addr)
+    },
+    {
+        AF_INET6,
+        DNS_TYPE_AAAA,
+        sizeof(IP6_ADDRESS),
+        sizeof(SOCKADDR_IN6),
+        FIELD_OFFSET(SOCKADDR_IN6, sin6_addr)
+    },
+    {
+        AF_ATM,
+        DNS_TYPE_ATMA,
+        sizeof(ATM_ADDRESS),
+        sizeof(SOCKADDR_ATM),
+        FIELD_OFFSET(SOCKADDR_ATM, satm_number)
+    }
+};
+
+/* FUNCTIONS *****************************************************************/
+
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily)
+{
+    /* Check which family this is */
+    switch (AddressFamily)
+    {
+        case AF_INET:
+            /* Return IPv4 Family Info */
+            return &AddrFamilyTable[0];
+        
+        case AF_INET6:
+            /* Return IPv6 Family Info */
+            return &AddrFamilyTable[1];
+        
+        case AF_ATM:
+            /* Return ATM Family Info */
+            return &AddrFamilyTable[2];
+        
+        default:
+            /* Invalid family */
+            return NULL;
+    }
+
+}
+
diff --git a/dll/win32/mswsock/dns/debug.c b/dll/win32/mswsock/dns/debug.c
new file mode 100644 (file)
index 0000000..f194e1e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/debug.c
+ * PURPOSE:     Contains helpful debugging functions for DNSLIB structures.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/debug.c
+ * PURPOSE:     Contains helpful debugging functions for DNSLIB structures.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/debug.c
+ * PURPOSE:     Contains helpful debugging functions for DNSLIB structures.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/debug.c
+ * PURPOSE:     Contains helpful debugging functions for DNSLIB structures.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
diff --git a/dll/win32/mswsock/dns/dnsaddr.c b/dll/win32/mswsock/dns/dnsaddr.c
new file mode 100644 (file)
index 0000000..20ebe48
--- /dev/null
@@ -0,0 +1,800 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/dnsaddr.c
+ * PURPOSE:     Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count)
+{
+    PDNS_ARRAY DnsAddrArray;
+
+    /* Allocate space for the array and the addresses within it */
+    DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) +
+                                 (Count * sizeof(DNS_ADDRESS)));
+
+    /* Write the allocated address count */
+    if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count;
+
+    /* Return it */
+    return DnsAddrArray;
+}
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray)
+{
+    /* Just free the entire array */
+    Dns_Free(DnsAddrArray);
+}
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray,
+                    IN IN_ADDR Address,
+                    IN DWORD AddressType)
+{
+    DNS_ADDRESS DnsAddress;
+
+    /* Build the DNS Address */
+    DnsAddr_BuildFromIp4(&DnsAddress, Address, 0);
+
+    /* Add it to the array */
+    return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType);
+}
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray,
+                     IN PDNS_ADDRESS DnsAddress,
+                     IN WORD AddressFamily OPTIONAL,
+                     IN DWORD AddressType OPTIONAL)
+{
+    /* Make sure we have an array */
+    if (!DnsAddrArray) return FALSE;
+    
+    /* Check if we should validate the Address Family */
+    if (AddressFamily)
+    {
+        /* Validate it */
+        if (AddressFamily != DnsAddress->AddressFamily) return TRUE;
+    }
+
+    /* Check if we should validate the Address Type */
+    if (AddressType)
+    {
+        /* Make sure that this array contains this type of addresses */
+        if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType))
+        {
+            /* Won't be adding it */
+            return TRUE;
+        }
+    }
+
+    /* Make sure we have space in the array */
+    if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses)
+    {
+        return FALSE; 
+    }
+
+    /* Now add the address */
+    RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses],
+                  DnsAddress,
+                  sizeof(DNS_ADDRESS));
+
+    /* Return success */
+    return TRUE;
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress,
+                     IN IN_ADDR Address,
+                     IN WORD Port)
+{
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Write data */
+    DnsAddress->Ip4Address.sin_family = AF_INET;
+    DnsAddress->Ip4Address.sin_port  = Port;
+    DnsAddress->Ip4Address.sin_addr = Address;
+    DnsAddress->AddressLength = sizeof(SOCKADDR_IN);
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress,
+                     IN PIN6_ADDR Address,
+                     IN ULONG ScopeId,
+                     IN WORD Port)
+{
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Write data */
+    DnsAddress->Ip6Address.sin6_family = AF_INET6;
+    DnsAddress->Ip6Address.sin6_port  = Port;
+    DnsAddress->Ip6Address.sin6_addr = *Address;
+    DnsAddress->Ip6Address.sin6_scope_id = ScopeId;
+    DnsAddress->AddressLength = sizeof(SOCKADDR_IN6);
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress,
+                     IN DWORD AddressType,
+                     IN PVOID AddressData)
+{
+    ATM_ADDRESS Address;
+
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Build an ATM Address */
+    Address.AddressType = AddressType;
+    Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH;
+    RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH);
+
+    /* Write data */
+    DnsAddress->AtmAddress = Address;
+    DnsAddress->AddressLength = sizeof(ATM_ADDRESS);
+}
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord,
+                           OUT PDNS_ADDRESS DnsAddr)
+{
+    /* Check what kind of record this is */
+    switch(DnsRecord->wType)
+    {
+        /* IPv4 */
+        case DNS_TYPE_A:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromIp4(DnsAddr,
+                                 *(PIN_ADDR)&DnsRecord->Data.A.IpAddress,
+                                 0);
+            break;
+
+        /* IPv6 */
+        case DNS_TYPE_AAAA:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromIp6(DnsAddr,
+                                 (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address,
+                                 DnsRecord->dwReserved,
+                                 0);
+            break;
+
+        /* ATM */
+        case DNS_TYPE_ATMA:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromAtm(DnsAddr,
+                                 DnsRecord->Data.Atma.AddressType,
+                                 &DnsRecord->Data.Atma.Address);
+            break;
+    }
+
+    /* Done! */
+    return TRUE;
+}
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray,
+                          IN PDNS_ADDRESS DnsAddress,
+                          IN DWORD AddressType)
+{
+    /* FIXME */
+    return TRUE;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/dnsaddr.c
+ * PURPOSE:     Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count)
+{
+    PDNS_ARRAY DnsAddrArray;
+
+    /* Allocate space for the array and the addresses within it */
+    DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) +
+                                 (Count * sizeof(DNS_ADDRESS)));
+
+    /* Write the allocated address count */
+    if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count;
+
+    /* Return it */
+    return DnsAddrArray;
+}
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray)
+{
+    /* Just free the entire array */
+    Dns_Free(DnsAddrArray);
+}
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray,
+                    IN IN_ADDR Address,
+                    IN DWORD AddressType)
+{
+    DNS_ADDRESS DnsAddress;
+
+    /* Build the DNS Address */
+    DnsAddr_BuildFromIp4(&DnsAddress, Address, 0);
+
+    /* Add it to the array */
+    return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType);
+}
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray,
+                     IN PDNS_ADDRESS DnsAddress,
+                     IN WORD AddressFamily OPTIONAL,
+                     IN DWORD AddressType OPTIONAL)
+{
+    /* Make sure we have an array */
+    if (!DnsAddrArray) return FALSE;
+    
+    /* Check if we should validate the Address Family */
+    if (AddressFamily)
+    {
+        /* Validate it */
+        if (AddressFamily != DnsAddress->AddressFamily) return TRUE;
+    }
+
+    /* Check if we should validate the Address Type */
+    if (AddressType)
+    {
+        /* Make sure that this array contains this type of addresses */
+        if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType))
+        {
+            /* Won't be adding it */
+            return TRUE;
+        }
+    }
+
+    /* Make sure we have space in the array */
+    if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses)
+    {
+        return FALSE; 
+    }
+
+    /* Now add the address */
+    RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses],
+                  DnsAddress,
+                  sizeof(DNS_ADDRESS));
+
+    /* Return success */
+    return TRUE;
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress,
+                     IN IN_ADDR Address,
+                     IN WORD Port)
+{
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Write data */
+    DnsAddress->Ip4Address.sin_family = AF_INET;
+    DnsAddress->Ip4Address.sin_port  = Port;
+    DnsAddress->Ip4Address.sin_addr = Address;
+    DnsAddress->AddressLength = sizeof(SOCKADDR_IN);
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress,
+                     IN PIN6_ADDR Address,
+                     IN ULONG ScopeId,
+                     IN WORD Port)
+{
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Write data */
+    DnsAddress->Ip6Address.sin6_family = AF_INET6;
+    DnsAddress->Ip6Address.sin6_port  = Port;
+    DnsAddress->Ip6Address.sin6_addr = *Address;
+    DnsAddress->Ip6Address.sin6_scope_id = ScopeId;
+    DnsAddress->AddressLength = sizeof(SOCKADDR_IN6);
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress,
+                     IN DWORD AddressType,
+                     IN PVOID AddressData)
+{
+    ATM_ADDRESS Address;
+
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Build an ATM Address */
+    Address.AddressType = AddressType;
+    Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH;
+    RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH);
+
+    /* Write data */
+    DnsAddress->AtmAddress = Address;
+    DnsAddress->AddressLength = sizeof(ATM_ADDRESS);
+}
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord,
+                           OUT PDNS_ADDRESS DnsAddr)
+{
+    /* Check what kind of record this is */
+    switch(DnsRecord->wType)
+    {
+        /* IPv4 */
+        case DNS_TYPE_A:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromIp4(DnsAddr,
+                                 *(PIN_ADDR)&DnsRecord->Data.A.IpAddress,
+                                 0);
+            break;
+
+        /* IPv6 */
+        case DNS_TYPE_AAAA:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromIp6(DnsAddr,
+                                 (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address,
+                                 DnsRecord->dwReserved,
+                                 0);
+            break;
+
+        /* ATM */
+        case DNS_TYPE_ATMA:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromAtm(DnsAddr,
+                                 DnsRecord->Data.Atma.AddressType,
+                                 &DnsRecord->Data.Atma.Address);
+            break;
+    }
+
+    /* Done! */
+    return TRUE;
+}
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray,
+                          IN PDNS_ADDRESS DnsAddress,
+                          IN DWORD AddressType)
+{
+    /* FIXME */
+    return TRUE;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/dnsaddr.c
+ * PURPOSE:     Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count)
+{
+    PDNS_ARRAY DnsAddrArray;
+
+    /* Allocate space for the array and the addresses within it */
+    DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) +
+                                 (Count * sizeof(DNS_ADDRESS)));
+
+    /* Write the allocated address count */
+    if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count;
+
+    /* Return it */
+    return DnsAddrArray;
+}
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray)
+{
+    /* Just free the entire array */
+    Dns_Free(DnsAddrArray);
+}
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray,
+                    IN IN_ADDR Address,
+                    IN DWORD AddressType)
+{
+    DNS_ADDRESS DnsAddress;
+
+    /* Build the DNS Address */
+    DnsAddr_BuildFromIp4(&DnsAddress, Address, 0);
+
+    /* Add it to the array */
+    return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType);
+}
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray,
+                     IN PDNS_ADDRESS DnsAddress,
+                     IN WORD AddressFamily OPTIONAL,
+                     IN DWORD AddressType OPTIONAL)
+{
+    /* Make sure we have an array */
+    if (!DnsAddrArray) return FALSE;
+    
+    /* Check if we should validate the Address Family */
+    if (AddressFamily)
+    {
+        /* Validate it */
+        if (AddressFamily != DnsAddress->AddressFamily) return TRUE;
+    }
+
+    /* Check if we should validate the Address Type */
+    if (AddressType)
+    {
+        /* Make sure that this array contains this type of addresses */
+        if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType))
+        {
+            /* Won't be adding it */
+            return TRUE;
+        }
+    }
+
+    /* Make sure we have space in the array */
+    if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses)
+    {
+        return FALSE; 
+    }
+
+    /* Now add the address */
+    RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses],
+                  DnsAddress,
+                  sizeof(DNS_ADDRESS));
+
+    /* Return success */
+    return TRUE;
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress,
+                     IN IN_ADDR Address,
+                     IN WORD Port)
+{
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Write data */
+    DnsAddress->Ip4Address.sin_family = AF_INET;
+    DnsAddress->Ip4Address.sin_port  = Port;
+    DnsAddress->Ip4Address.sin_addr = Address;
+    DnsAddress->AddressLength = sizeof(SOCKADDR_IN);
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress,
+                     IN PIN6_ADDR Address,
+                     IN ULONG ScopeId,
+                     IN WORD Port)
+{
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Write data */
+    DnsAddress->Ip6Address.sin6_family = AF_INET6;
+    DnsAddress->Ip6Address.sin6_port  = Port;
+    DnsAddress->Ip6Address.sin6_addr = *Address;
+    DnsAddress->Ip6Address.sin6_scope_id = ScopeId;
+    DnsAddress->AddressLength = sizeof(SOCKADDR_IN6);
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress,
+                     IN DWORD AddressType,
+                     IN PVOID AddressData)
+{
+    ATM_ADDRESS Address;
+
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Build an ATM Address */
+    Address.AddressType = AddressType;
+    Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH;
+    RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH);
+
+    /* Write data */
+    DnsAddress->AtmAddress = Address;
+    DnsAddress->AddressLength = sizeof(ATM_ADDRESS);
+}
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord,
+                           OUT PDNS_ADDRESS DnsAddr)
+{
+    /* Check what kind of record this is */
+    switch(DnsRecord->wType)
+    {
+        /* IPv4 */
+        case DNS_TYPE_A:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromIp4(DnsAddr,
+                                 *(PIN_ADDR)&DnsRecord->Data.A.IpAddress,
+                                 0);
+            break;
+
+        /* IPv6 */
+        case DNS_TYPE_AAAA:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromIp6(DnsAddr,
+                                 (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address,
+                                 DnsRecord->dwReserved,
+                                 0);
+            break;
+
+        /* ATM */
+        case DNS_TYPE_ATMA:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromAtm(DnsAddr,
+                                 DnsRecord->Data.Atma.AddressType,
+                                 &DnsRecord->Data.Atma.Address);
+            break;
+    }
+
+    /* Done! */
+    return TRUE;
+}
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray,
+                          IN PDNS_ADDRESS DnsAddress,
+                          IN DWORD AddressType)
+{
+    /* FIXME */
+    return TRUE;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/dnsaddr.c
+ * PURPOSE:     Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count)
+{
+    PDNS_ARRAY DnsAddrArray;
+
+    /* Allocate space for the array and the addresses within it */
+    DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) +
+                                 (Count * sizeof(DNS_ADDRESS)));
+
+    /* Write the allocated address count */
+    if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count;
+
+    /* Return it */
+    return DnsAddrArray;
+}
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray)
+{
+    /* Just free the entire array */
+    Dns_Free(DnsAddrArray);
+}
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray,
+                    IN IN_ADDR Address,
+                    IN DWORD AddressType)
+{
+    DNS_ADDRESS DnsAddress;
+
+    /* Build the DNS Address */
+    DnsAddr_BuildFromIp4(&DnsAddress, Address, 0);
+
+    /* Add it to the array */
+    return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType);
+}
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray,
+                     IN PDNS_ADDRESS DnsAddress,
+                     IN WORD AddressFamily OPTIONAL,
+                     IN DWORD AddressType OPTIONAL)
+{
+    /* Make sure we have an array */
+    if (!DnsAddrArray) return FALSE;
+    
+    /* Check if we should validate the Address Family */
+    if (AddressFamily)
+    {
+        /* Validate it */
+        if (AddressFamily != DnsAddress->AddressFamily) return TRUE;
+    }
+
+    /* Check if we should validate the Address Type */
+    if (AddressType)
+    {
+        /* Make sure that this array contains this type of addresses */
+        if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType))
+        {
+            /* Won't be adding it */
+            return TRUE;
+        }
+    }
+
+    /* Make sure we have space in the array */
+    if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses)
+    {
+        return FALSE; 
+    }
+
+    /* Now add the address */
+    RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses],
+                  DnsAddress,
+                  sizeof(DNS_ADDRESS));
+
+    /* Return success */
+    return TRUE;
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress,
+                     IN IN_ADDR Address,
+                     IN WORD Port)
+{
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Write data */
+    DnsAddress->Ip4Address.sin_family = AF_INET;
+    DnsAddress->Ip4Address.sin_port  = Port;
+    DnsAddress->Ip4Address.sin_addr = Address;
+    DnsAddress->AddressLength = sizeof(SOCKADDR_IN);
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress,
+                     IN PIN6_ADDR Address,
+                     IN ULONG ScopeId,
+                     IN WORD Port)
+{
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Write data */
+    DnsAddress->Ip6Address.sin6_family = AF_INET6;
+    DnsAddress->Ip6Address.sin6_port  = Port;
+    DnsAddress->Ip6Address.sin6_addr = *Address;
+    DnsAddress->Ip6Address.sin6_scope_id = ScopeId;
+    DnsAddress->AddressLength = sizeof(SOCKADDR_IN6);
+}
+
+VOID
+WINAPI
+DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress,
+                     IN DWORD AddressType,
+                     IN PVOID AddressData)
+{
+    ATM_ADDRESS Address;
+
+    /* Clear the address */
+    RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS));
+
+    /* Build an ATM Address */
+    Address.AddressType = AddressType;
+    Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH;
+    RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH);
+
+    /* Write data */
+    DnsAddress->AtmAddress = Address;
+    DnsAddress->AddressLength = sizeof(ATM_ADDRESS);
+}
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord,
+                           OUT PDNS_ADDRESS DnsAddr)
+{
+    /* Check what kind of record this is */
+    switch(DnsRecord->wType)
+    {
+        /* IPv4 */
+        case DNS_TYPE_A:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromIp4(DnsAddr,
+                                 *(PIN_ADDR)&DnsRecord->Data.A.IpAddress,
+                                 0);
+            break;
+
+        /* IPv6 */
+        case DNS_TYPE_AAAA:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromIp6(DnsAddr,
+                                 (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address,
+                                 DnsRecord->dwReserved,
+                                 0);
+            break;
+
+        /* ATM */
+        case DNS_TYPE_ATMA:
+            /* Create the DNS Address */
+            DnsAddr_BuildFromAtm(DnsAddr,
+                                 DnsRecord->Data.Atma.AddressType,
+                                 &DnsRecord->Data.Atma.Address);
+            break;
+    }
+
+    /* Done! */
+    return TRUE;
+}
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray,
+                          IN PDNS_ADDRESS DnsAddress,
+                          IN DWORD AddressType)
+{
+    /* FIXME */
+    return TRUE;
+}
+
diff --git a/dll/win32/mswsock/dns/dnsutil.c b/dll/win32/mswsock/dns/dnsutil.c
new file mode 100644 (file)
index 0000000..0830457
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/dnsutil.c
+ * PURPOSE:     Contains misc. DNS utility functions, like DNS_STATUS->String.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/dnsutil.c
+ * PURPOSE:     Contains misc. DNS utility functions, like DNS_STATUS->String.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/dnsutil.c
+ * PURPOSE:     Contains misc. DNS utility functions, like DNS_STATUS->String.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/dnsutil.c
+ * PURPOSE:     Contains misc. DNS utility functions, like DNS_STATUS->String.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
diff --git a/dll/win32/mswsock/dns/flatbuf.c b/dll/win32/mswsock/dns/flatbuf.c
new file mode 100644 (file)
index 0000000..6d33b21
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/flatbuf.c
+ * PURPOSE:     Functions for managing the Flat Buffer Implementation (FLATBUF)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WINAPI
+FlatBuf_Init(IN PFLATBUFF FlatBuffer,
+             IN PVOID Buffer,
+             IN SIZE_T Size)
+{
+    /* Set up the Flat Buffer start, current and ending position */
+    FlatBuffer->Buffer = Buffer;
+    FlatBuffer->BufferPos = (ULONG_PTR)Buffer;
+    FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size);
+
+    /* Setup the current size and the available size */
+    FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position,
+                    IN OUT PSIZE_T FreeSize,
+                    IN SIZE_T Size,
+                    IN ULONG Align)
+{
+    ULONG_PTR NewPosition, OldPosition = *Position;
+    SIZE_T NewFreeSize = *FreeSize;
+
+    /* Start by aligning our position */
+    if (Align) OldPosition += (Align - 1) & ~Align;
+
+    /* Update it */
+    NewPosition = OldPosition + Size;
+
+    /* Update Free Size */
+    NewFreeSize += (OldPosition - NewPosition);
+
+    /* Save new values */
+    *Position = NewPosition;
+    *FreeSize = NewFreeSize;
+
+    /* Check if we're out of space or not */
+    if (NewFreeSize > 0) return (PVOID)OldPosition;
+    return NULL;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position,
+                       IN OUT PSIZE_T FreeSize,
+                       IN PVOID Buffer,
+                       IN SIZE_T Size,
+                       IN ULONG Align)
+{
+    PVOID Destination;
+
+    /* First reserve the memory */
+    Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align);
+    if (Destination)
+    {
+        /* We have space, do the copy */
+        RtlCopyMemory(Destination, Buffer, Size);
+    }
+
+    /* Return the pointer to the data */
+    return Destination;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position,
+                        IN OUT PSIZE_T FreeSize,
+                        IN PVOID String,
+                        IN BOOLEAN IsUnicode)
+{
+    PVOID Destination;
+    SIZE_T StringLength;
+    ULONG Align;
+
+    /* Calculate the string length */
+    if (IsUnicode)
+    {
+        /* Get the length in bytes and use WCHAR alignment */
+        StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR);
+        Align = sizeof(WCHAR);
+    }
+    else
+    {
+        /* Get the length in bytes and use CHAR alignment */
+        StringLength = strlen((LPSTR)String) + 1;
+        Align = sizeof(CHAR);
+    }
+
+    /* Now reserve the memory */
+    Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align);
+    if (Destination)
+    {
+        /* We have space, do the copy */
+        RtlCopyMemory(Destination, String, StringLength);
+    }
+
+    /* Return the pointer to the data */
+    return Destination;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/flatbuf.c
+ * PURPOSE:     Functions for managing the Flat Buffer Implementation (FLATBUF)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WINAPI
+FlatBuf_Init(IN PFLATBUFF FlatBuffer,
+             IN PVOID Buffer,
+             IN SIZE_T Size)
+{
+    /* Set up the Flat Buffer start, current and ending position */
+    FlatBuffer->Buffer = Buffer;
+    FlatBuffer->BufferPos = (ULONG_PTR)Buffer;
+    FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size);
+
+    /* Setup the current size and the available size */
+    FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position,
+                    IN OUT PSIZE_T FreeSize,
+                    IN SIZE_T Size,
+                    IN ULONG Align)
+{
+    ULONG_PTR NewPosition, OldPosition = *Position;
+    SIZE_T NewFreeSize = *FreeSize;
+
+    /* Start by aligning our position */
+    if (Align) OldPosition += (Align - 1) & ~Align;
+
+    /* Update it */
+    NewPosition = OldPosition + Size;
+
+    /* Update Free Size */
+    NewFreeSize += (OldPosition - NewPosition);
+
+    /* Save new values */
+    *Position = NewPosition;
+    *FreeSize = NewFreeSize;
+
+    /* Check if we're out of space or not */
+    if (NewFreeSize > 0) return (PVOID)OldPosition;
+    return NULL;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position,
+                       IN OUT PSIZE_T FreeSize,
+                       IN PVOID Buffer,
+                       IN SIZE_T Size,
+                       IN ULONG Align)
+{
+    PVOID Destination;
+
+    /* First reserve the memory */
+    Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align);
+    if (Destination)
+    {
+        /* We have space, do the copy */
+        RtlCopyMemory(Destination, Buffer, Size);
+    }
+
+    /* Return the pointer to the data */
+    return Destination;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position,
+                        IN OUT PSIZE_T FreeSize,
+                        IN PVOID String,
+                        IN BOOLEAN IsUnicode)
+{
+    PVOID Destination;
+    SIZE_T StringLength;
+    ULONG Align;
+
+    /* Calculate the string length */
+    if (IsUnicode)
+    {
+        /* Get the length in bytes and use WCHAR alignment */
+        StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR);
+        Align = sizeof(WCHAR);
+    }
+    else
+    {
+        /* Get the length in bytes and use CHAR alignment */
+        StringLength = strlen((LPSTR)String) + 1;
+        Align = sizeof(CHAR);
+    }
+
+    /* Now reserve the memory */
+    Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align);
+    if (Destination)
+    {
+        /* We have space, do the copy */
+        RtlCopyMemory(Destination, String, StringLength);
+    }
+
+    /* Return the pointer to the data */
+    return Destination;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/flatbuf.c
+ * PURPOSE:     Functions for managing the Flat Buffer Implementation (FLATBUF)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WINAPI
+FlatBuf_Init(IN PFLATBUFF FlatBuffer,
+             IN PVOID Buffer,
+             IN SIZE_T Size)
+{
+    /* Set up the Flat Buffer start, current and ending position */
+    FlatBuffer->Buffer = Buffer;
+    FlatBuffer->BufferPos = (ULONG_PTR)Buffer;
+    FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size);
+
+    /* Setup the current size and the available size */
+    FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position,
+                    IN OUT PSIZE_T FreeSize,
+                    IN SIZE_T Size,
+                    IN ULONG Align)
+{
+    ULONG_PTR NewPosition, OldPosition = *Position;
+    SIZE_T NewFreeSize = *FreeSize;
+
+    /* Start by aligning our position */
+    if (Align) OldPosition += (Align - 1) & ~Align;
+
+    /* Update it */
+    NewPosition = OldPosition + Size;
+
+    /* Update Free Size */
+    NewFreeSize += (OldPosition - NewPosition);
+
+    /* Save new values */
+    *Position = NewPosition;
+    *FreeSize = NewFreeSize;
+
+    /* Check if we're out of space or not */
+    if (NewFreeSize > 0) return (PVOID)OldPosition;
+    return NULL;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position,
+                       IN OUT PSIZE_T FreeSize,
+                       IN PVOID Buffer,
+                       IN SIZE_T Size,
+                       IN ULONG Align)
+{
+    PVOID Destination;
+
+    /* First reserve the memory */
+    Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align);
+    if (Destination)
+    {
+        /* We have space, do the copy */
+        RtlCopyMemory(Destination, Buffer, Size);
+    }
+
+    /* Return the pointer to the data */
+    return Destination;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position,
+                        IN OUT PSIZE_T FreeSize,
+                        IN PVOID String,
+                        IN BOOLEAN IsUnicode)
+{
+    PVOID Destination;
+    SIZE_T StringLength;
+    ULONG Align;
+
+    /* Calculate the string length */
+    if (IsUnicode)
+    {
+        /* Get the length in bytes and use WCHAR alignment */
+        StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR);
+        Align = sizeof(WCHAR);
+    }
+    else
+    {
+        /* Get the length in bytes and use CHAR alignment */
+        StringLength = strlen((LPSTR)String) + 1;
+        Align = sizeof(CHAR);
+    }
+
+    /* Now reserve the memory */
+    Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align);
+    if (Destination)
+    {
+        /* We have space, do the copy */
+        RtlCopyMemory(Destination, String, StringLength);
+    }
+
+    /* Return the pointer to the data */
+    return Destination;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/flatbuf.c
+ * PURPOSE:     Functions for managing the Flat Buffer Implementation (FLATBUF)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WINAPI
+FlatBuf_Init(IN PFLATBUFF FlatBuffer,
+             IN PVOID Buffer,
+             IN SIZE_T Size)
+{
+    /* Set up the Flat Buffer start, current and ending position */
+    FlatBuffer->Buffer = Buffer;
+    FlatBuffer->BufferPos = (ULONG_PTR)Buffer;
+    FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size);
+
+    /* Setup the current size and the available size */
+    FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position,
+                    IN OUT PSIZE_T FreeSize,
+                    IN SIZE_T Size,
+                    IN ULONG Align)
+{
+    ULONG_PTR NewPosition, OldPosition = *Position;
+    SIZE_T NewFreeSize = *FreeSize;
+
+    /* Start by aligning our position */
+    if (Align) OldPosition += (Align - 1) & ~Align;
+
+    /* Update it */
+    NewPosition = OldPosition + Size;
+
+    /* Update Free Size */
+    NewFreeSize += (OldPosition - NewPosition);
+
+    /* Save new values */
+    *Position = NewPosition;
+    *FreeSize = NewFreeSize;
+
+    /* Check if we're out of space or not */
+    if (NewFreeSize > 0) return (PVOID)OldPosition;
+    return NULL;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position,
+                       IN OUT PSIZE_T FreeSize,
+                       IN PVOID Buffer,
+                       IN SIZE_T Size,
+                       IN ULONG Align)
+{
+    PVOID Destination;
+
+    /* First reserve the memory */
+    Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align);
+    if (Destination)
+    {
+        /* We have space, do the copy */
+        RtlCopyMemory(Destination, Buffer, Size);
+    }
+
+    /* Return the pointer to the data */
+    return Destination;
+}
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position,
+                        IN OUT PSIZE_T FreeSize,
+                        IN PVOID String,
+                        IN BOOLEAN IsUnicode)
+{
+    PVOID Destination;
+    SIZE_T StringLength;
+    ULONG Align;
+
+    /* Calculate the string length */
+    if (IsUnicode)
+    {
+        /* Get the length in bytes and use WCHAR alignment */
+        StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR);
+        Align = sizeof(WCHAR);
+    }
+    else
+    {
+        /* Get the length in bytes and use CHAR alignment */
+        StringLength = strlen((LPSTR)String) + 1;
+        Align = sizeof(CHAR);
+    }
+
+    /* Now reserve the memory */
+    Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align);
+    if (Destination)
+    {
+        /* We have space, do the copy */
+        RtlCopyMemory(Destination, String, StringLength);
+    }
+
+    /* Return the pointer to the data */
+    return Destination;
+}
+
diff --git a/dll/win32/mswsock/dns/hostent.c b/dll/win32/mswsock/dns/hostent.c
new file mode 100644 (file)
index 0000000..c444ac2
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/hostent.c
+ * PURPOSE:     Functions for dealing with Host Entry structures
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PHOSTENT
+WINAPI
+Hostent_Init(IN PVOID *Buffer,
+             IN WORD AddressFamily,
+             IN ULONG AddressSize,
+             IN ULONG AddressCount,
+             IN ULONG AliasCount)
+{
+    PHOSTENT Hostent;
+    ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer;
+
+    /* Align the hostent on the buffer's 4 byte boundary */
+    BufferPosition += 3 & ~3;
+
+    /* Set up the basic data */
+    Hostent = (PHOSTENT)BufferPosition;
+    Hostent->h_length = (WORD)AddressSize;
+    Hostent->h_addrtype = AddressFamily;
+
+    /* Put aliases after Hostent */
+    Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3);
+
+    /* Zero it out */
+    RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR));
+
+    /* Put addresses after aliases */
+    Hostent->h_addr_list = (PCHAR*)
+                           ((ULONG_PTR)Hostent->h_aliases +
+                            (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR));
+
+    /* Update the location */
+    BufferPosition = (ULONG_PTR)Hostent->h_addr_list +
+                     ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR));
+
+    /* Send it back */
+    *Buffer = (PVOID)BufferPosition;
+
+    /* Return the hostent */
+    return Hostent;
+}
+
+VOID
+WINAPI
+Dns_PtrArrayToOffsetArray(PCHAR *List,
+                          ULONG_PTR Base)
+{
+    /* Loop every pointer in the list */
+    do 
+    {
+        /* Update the pointer */
+        *List = (PCHAR)((ULONG_PTR)*List - Base);
+    } while(*List++);
+}
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent)
+{
+    /* Do we have a name? */
+    if (Hostent->h_name)
+    {
+        /* Update it */
+        Hostent->h_name -= (ULONG_PTR)Hostent;
+    }
+
+    /* Do we have aliases? */
+    if (Hostent->h_aliases)
+    {
+        /* Update the pointer */
+        Hostent->h_aliases -= (ULONG_PTR)Hostent;
+
+        /* Fix them up */
+        Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent);
+    }
+
+    /* Do we have addresses? */
+    if (Hostent->h_addr_list)
+    {
+        /* Fix them up */
+        Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent);
+    }
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/hostent.c
+ * PURPOSE:     Functions for dealing with Host Entry structures
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PHOSTENT
+WINAPI
+Hostent_Init(IN PVOID *Buffer,
+             IN WORD AddressFamily,
+             IN ULONG AddressSize,
+             IN ULONG AddressCount,
+             IN ULONG AliasCount)
+{
+    PHOSTENT Hostent;
+    ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer;
+
+    /* Align the hostent on the buffer's 4 byte boundary */
+    BufferPosition += 3 & ~3;
+
+    /* Set up the basic data */
+    Hostent = (PHOSTENT)BufferPosition;
+    Hostent->h_length = (WORD)AddressSize;
+    Hostent->h_addrtype = AddressFamily;
+
+    /* Put aliases after Hostent */
+    Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3);
+
+    /* Zero it out */
+    RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR));
+
+    /* Put addresses after aliases */
+    Hostent->h_addr_list = (PCHAR*)
+                           ((ULONG_PTR)Hostent->h_aliases +
+                            (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR));
+
+    /* Update the location */
+    BufferPosition = (ULONG_PTR)Hostent->h_addr_list +
+                     ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR));
+
+    /* Send it back */
+    *Buffer = (PVOID)BufferPosition;
+
+    /* Return the hostent */
+    return Hostent;
+}
+
+VOID
+WINAPI
+Dns_PtrArrayToOffsetArray(PCHAR *List,
+                          ULONG_PTR Base)
+{
+    /* Loop every pointer in the list */
+    do 
+    {
+        /* Update the pointer */
+        *List = (PCHAR)((ULONG_PTR)*List - Base);
+    } while(*List++);
+}
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent)
+{
+    /* Do we have a name? */
+    if (Hostent->h_name)
+    {
+        /* Update it */
+        Hostent->h_name -= (ULONG_PTR)Hostent;
+    }
+
+    /* Do we have aliases? */
+    if (Hostent->h_aliases)
+    {
+        /* Update the pointer */
+        Hostent->h_aliases -= (ULONG_PTR)Hostent;
+
+        /* Fix them up */
+        Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent);
+    }
+
+    /* Do we have addresses? */
+    if (Hostent->h_addr_list)
+    {
+        /* Fix them up */
+        Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent);
+    }
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/hostent.c
+ * PURPOSE:     Functions for dealing with Host Entry structures
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PHOSTENT
+WINAPI
+Hostent_Init(IN PVOID *Buffer,
+             IN WORD AddressFamily,
+             IN ULONG AddressSize,
+             IN ULONG AddressCount,
+             IN ULONG AliasCount)
+{
+    PHOSTENT Hostent;
+    ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer;
+
+    /* Align the hostent on the buffer's 4 byte boundary */
+    BufferPosition += 3 & ~3;
+
+    /* Set up the basic data */
+    Hostent = (PHOSTENT)BufferPosition;
+    Hostent->h_length = (WORD)AddressSize;
+    Hostent->h_addrtype = AddressFamily;
+
+    /* Put aliases after Hostent */
+    Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3);
+
+    /* Zero it out */
+    RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR));
+
+    /* Put addresses after aliases */
+    Hostent->h_addr_list = (PCHAR*)
+                           ((ULONG_PTR)Hostent->h_aliases +
+                            (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR));
+
+    /* Update the location */
+    BufferPosition = (ULONG_PTR)Hostent->h_addr_list +
+                     ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR));
+
+    /* Send it back */
+    *Buffer = (PVOID)BufferPosition;
+
+    /* Return the hostent */
+    return Hostent;
+}
+
+VOID
+WINAPI
+Dns_PtrArrayToOffsetArray(PCHAR *List,
+                          ULONG_PTR Base)
+{
+    /* Loop every pointer in the list */
+    do 
+    {
+        /* Update the pointer */
+        *List = (PCHAR)((ULONG_PTR)*List - Base);
+    } while(*List++);
+}
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent)
+{
+    /* Do we have a name? */
+    if (Hostent->h_name)
+    {
+        /* Update it */
+        Hostent->h_name -= (ULONG_PTR)Hostent;
+    }
+
+    /* Do we have aliases? */
+    if (Hostent->h_aliases)
+    {
+        /* Update the pointer */
+        Hostent->h_aliases -= (ULONG_PTR)Hostent;
+
+        /* Fix them up */
+        Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent);
+    }
+
+    /* Do we have addresses? */
+    if (Hostent->h_addr_list)
+    {
+        /* Fix them up */
+        Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent);
+    }
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/hostent.c
+ * PURPOSE:     Functions for dealing with Host Entry structures
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PHOSTENT
+WINAPI
+Hostent_Init(IN PVOID *Buffer,
+             IN WORD AddressFamily,
+             IN ULONG AddressSize,
+             IN ULONG AddressCount,
+             IN ULONG AliasCount)
+{
+    PHOSTENT Hostent;
+    ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer;
+
+    /* Align the hostent on the buffer's 4 byte boundary */
+    BufferPosition += 3 & ~3;
+
+    /* Set up the basic data */
+    Hostent = (PHOSTENT)BufferPosition;
+    Hostent->h_length = (WORD)AddressSize;
+    Hostent->h_addrtype = AddressFamily;
+
+    /* Put aliases after Hostent */
+    Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3);
+
+    /* Zero it out */
+    RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR));
+
+    /* Put addresses after aliases */
+    Hostent->h_addr_list = (PCHAR*)
+                           ((ULONG_PTR)Hostent->h_aliases +
+                            (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR));
+
+    /* Update the location */
+    BufferPosition = (ULONG_PTR)Hostent->h_addr_list +
+                     ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR));
+
+    /* Send it back */
+    *Buffer = (PVOID)BufferPosition;
+
+    /* Return the hostent */
+    return Hostent;
+}
+
+VOID
+WINAPI
+Dns_PtrArrayToOffsetArray(PCHAR *List,
+                          ULONG_PTR Base)
+{
+    /* Loop every pointer in the list */
+    do 
+    {
+        /* Update the pointer */
+        *List = (PCHAR)((ULONG_PTR)*List - Base);
+    } while(*List++);
+}
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent)
+{
+    /* Do we have a name? */
+    if (Hostent->h_name)
+    {
+        /* Update it */
+        Hostent->h_name -= (ULONG_PTR)Hostent;
+    }
+
+    /* Do we have aliases? */
+    if (Hostent->h_aliases)
+    {
+        /* Update the pointer */
+        Hostent->h_aliases -= (ULONG_PTR)Hostent;
+
+        /* Fix them up */
+        Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent);
+    }
+
+    /* Do we have addresses? */
+    if (Hostent->h_addr_list)
+    {
+        /* Fix them up */
+        Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent);
+    }
+}
+
diff --git a/dll/win32/mswsock/dns/inc/dnslib.h b/dll/win32/mswsock/dns/inc/dnslib.h
new file mode 100644 (file)
index 0000000..b19220f
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/precomp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE
+#define _WIN32_WINNT 0x502
+#define WIN32_NO_STATUS
+
+/* PSDK Headers */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windns.h>
+
+/* DNSLIB and DNSAPI Headers */
+#include <dnslibp.h>
+#include <windnsp.h>
+
+/* NDK */
+#include <rtlfuncs.h>
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/precomp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE
+#define _WIN32_WINNT 0x502
+#define WIN32_NO_STATUS
+
+/* PSDK Headers */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windns.h>
+
+/* DNSLIB and DNSAPI Headers */
+#include <dnslibp.h>
+#include <windnsp.h>
+
+/* NDK */
+#include <rtlfuncs.h>
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/precomp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE
+#define _WIN32_WINNT 0x502
+#define WIN32_NO_STATUS
+
+/* PSDK Headers */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windns.h>
+
+/* DNSLIB and DNSAPI Headers */
+#include <dnslibp.h>
+#include <windnsp.h>
+
+/* NDK */
+#include <rtlfuncs.h>
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/precomp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE
+#define _WIN32_WINNT 0x502
+#define WIN32_NO_STATUS
+
+/* PSDK Headers */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windns.h>
+
+/* DNSLIB and DNSAPI Headers */
+#include <dnslibp.h>
+#include <windnsp.h>
+
+/* NDK */
+#include <rtlfuncs.h>
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/precomp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE
+#define _WIN32_WINNT 0x502
+#define WIN32_NO_STATUS
+
+/* PSDK Headers */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windns.h>
+
+/* DNSLIB and DNSAPI Headers */
+#include <dnslibp.h>
+#include <windnsp.h>
+
+/* NDK */
+#include <rtlfuncs.h>
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/precomp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE
+#define _WIN32_WINNT 0x502
+#define WIN32_NO_STATUS
+
+/* PSDK Headers */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windns.h>
+
+/* DNSLIB and DNSAPI Headers */
+#include <dnslibp.h>
+#include <windnsp.h>
+
+/* NDK */
+#include <rtlfuncs.h>
+
+/* EOF */
diff --git a/dll/win32/mswsock/dns/inc/dnslibp.h b/dll/win32/mswsock/dns/inc/dnslibp.h
new file mode 100644 (file)
index 0000000..86359ae
--- /dev/null
@@ -0,0 +1,2058 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS Ancillary Function Driver DLL
+ * FILE:        include/mswsock.h
+ * PURPOSE:     Ancillary Function Driver DLL header
+ */
+#ifndef __DNSLIB_H
+#define __DNSLIB_H
+
+/* INCLUDES ******************************************************************/
+#include <ws2atm.h>
+
+/* ENUMERATIONS **************************************************************/
+
+typedef enum _DNS_STRING_TYPE
+{
+    UnicodeString = 1,
+    Utf8String,
+    AnsiString,
+} DNS_STRING_TYPE;
+
+#define IpV4Address 3
+
+/* TYPES *********************************************************************/
+
+typedef struct _DNS_IPV6_ADDRESS
+{
+    ULONG Unknown;
+    ULONG Unknown2;
+    IP6_ADDRESS Address;
+    ULONG Unknown3;
+    ULONG Unknown4;
+    DWORD Reserved;
+    ULONG Unknown5;
+} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS;
+
+typedef struct _DNS_ADDRESS
+{
+    union
+    {
+        struct
+        {
+            WORD AddressFamily;
+            WORD Port;
+            ATM_ADDRESS AtmAddress;
+        };
+        SOCKADDR_IN Ip4Address;
+        SOCKADDR_IN6 Ip6Address;
+    };
+    ULONG AddressLength;
+    DWORD Sub;
+    ULONG Flag;
+} DNS_ADDRESS, *PDNS_ADDRESS;
+
+typedef struct _DNS_ARRAY
+{
+    ULONG AllocatedAddresses;
+    ULONG UsedAddresses;
+    ULONG Unknown[0x6];
+    DNS_ADDRESS Addresses[1];
+} DNS_ARRAY, *PDNS_ARRAY;
+
+typedef struct _DNS_BLOB
+{
+    LPWSTR Name;
+    PDNS_ARRAY DnsAddrArray;
+    PHOSTENT Hostent;
+    ULONG AliasCount;
+    ULONG Unknown;
+    LPWSTR Aliases[8];
+} DNS_BLOB, *PDNS_BLOB;
+
+typedef struct _DNS_FAMILY_INFO
+{
+    WORD AddrType;
+    WORD DnsType;
+    DWORD AddressSize;
+    DWORD SockaddrSize;
+    DWORD AddressOffset;
+} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO;
+
+typedef struct _FLATBUFF
+{
+    PVOID Buffer;
+    PVOID BufferEnd;
+    ULONG_PTR BufferPos;
+    SIZE_T BufferSize;
+    SIZE_T BufferFreeSize;
+} FLATBUFF, *PFLATBUFF;
+
+/*
+ * memory.c
+ */
+VOID
+WINAPI
+Dns_Free(IN PVOID Address);
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size);
+
+/*
+ * addr.c
+ */
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily);
+
+/*
+ * dnsaddr.c
+ */
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(
+    IN PDNS_ADDRESS DnsAddress,
+    IN IN_ADDR Address,
+    IN WORD Unknown
+);
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(
+    IN PDNS_ADDRESS DnsAddress,
+    IN PIN6_ADDR Address,
+    IN ULONG ScopeId,
+    IN WORD Port
+);
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count);
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN WORD AddressFamily OPTIONAL,
+    IN DWORD AddressType OPTIONAL
+);
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray);
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN IN_ADDR Address,
+    IN DWORD AddressType
+);
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN DWORD AddressType
+);
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(
+    IN PDNS_RECORD DnsRecord,
+    OUT PDNS_ADDRESS DnsAddr
+);
+
+/*
+ * hostent.c
+ */
+PHOSTENT
+WINAPI
+Hostent_Init(
+    IN PVOID *Buffer,
+    IN WORD AddressFamily,
+    IN ULONG AddressSize,
+    IN ULONG AddressCount,
+    IN ULONG AliasCount
+);
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent);
+
+/*
+ * flatbuf.c
+ */
+VOID
+WINAPI
+FlatBuf_Init(
+    IN PFLATBUFF FlatBuffer,
+    IN PVOID Buffer,
+    IN SIZE_T Size
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID Buffer,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID String,
+    IN BOOLEAN IsUnicode
+);
+
+/*
+ * sablob.c
+ */
+PDNS_BLOB
+WINAPI
+SaBlob_Create(
+    IN ULONG Count
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(
+    IN LPWSTR Name,
+    IN ULONG Count,
+    IN PIN_ADDR AddressArray
+);
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob);
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(
+    IN OUT PULONG_PTR BufferPosition,
+    IN OUT PSIZE_T RemainingBufferSpace,
+    IN OUT PSIZE_T HostEntrySize,
+    IN PDNS_BLOB Blob,
+    IN DWORD StringType,
+    IN BOOLEAN Relative,
+    IN BOOLEAN BufferAllocated
+);
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(
+    IN PDNS_BLOB Blob,
+    IN LPWSTR String,
+    IN BOOLEAN IsAlias
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(
+    IN LPWSTR Name,
+    IN WORD DnsType,
+    IN ULONG Flags,
+    IN PVOID *Reserved,
+    IN DWORD AddressFamily
+);
+
+/*
+ * string.c
+ */
+ULONG
+WINAPI
+Dns_StringCopy(
+    OUT PVOID Destination,
+    IN OUT PULONG DestinationSize,
+    IN PVOID String,
+    IN ULONG StringSize OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name);
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(
+    IN PVOID String,
+    IN ULONG Size OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+/*
+ * straddr.c
+ */
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(
+    OUT PVOID Address,
+    IN OUT PULONG AddressSize,
+    IN LPWSTR AddressName,
+    IN OUT PDWORD AddressFamily
+);
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN_ADDR Address
+);
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN6_ADDR Address
+);
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(
+    OUT PDNS_ADDRESS DnsAddr,
+    IN LPWSTR Name
+);
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(
+    OUT PIN_ADDR Address,
+    IN LPWSTR Name
+);
+
+#endif
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS Ancillary Function Driver DLL
+ * FILE:        include/mswsock.h
+ * PURPOSE:     Ancillary Function Driver DLL header
+ */
+#ifndef __DNSLIB_H
+#define __DNSLIB_H
+
+/* INCLUDES ******************************************************************/
+#include <ws2atm.h>
+
+/* ENUMERATIONS **************************************************************/
+
+typedef enum _DNS_STRING_TYPE
+{
+    UnicodeString = 1,
+    Utf8String,
+    AnsiString,
+} DNS_STRING_TYPE;
+
+#define IpV4Address 3
+
+/* TYPES *********************************************************************/
+
+typedef struct _DNS_IPV6_ADDRESS
+{
+    ULONG Unknown;
+    ULONG Unknown2;
+    IP6_ADDRESS Address;
+    ULONG Unknown3;
+    ULONG Unknown4;
+    DWORD Reserved;
+    ULONG Unknown5;
+} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS;
+
+typedef struct _DNS_ADDRESS
+{
+    union
+    {
+        struct
+        {
+            WORD AddressFamily;
+            WORD Port;
+            ATM_ADDRESS AtmAddress;
+        };
+        SOCKADDR_IN Ip4Address;
+        SOCKADDR_IN6 Ip6Address;
+    };
+    ULONG AddressLength;
+    DWORD Sub;
+    ULONG Flag;
+} DNS_ADDRESS, *PDNS_ADDRESS;
+
+typedef struct _DNS_ARRAY
+{
+    ULONG AllocatedAddresses;
+    ULONG UsedAddresses;
+    ULONG Unknown[0x6];
+    DNS_ADDRESS Addresses[1];
+} DNS_ARRAY, *PDNS_ARRAY;
+
+typedef struct _DNS_BLOB
+{
+    LPWSTR Name;
+    PDNS_ARRAY DnsAddrArray;
+    PHOSTENT Hostent;
+    ULONG AliasCount;
+    ULONG Unknown;
+    LPWSTR Aliases[8];
+} DNS_BLOB, *PDNS_BLOB;
+
+typedef struct _DNS_FAMILY_INFO
+{
+    WORD AddrType;
+    WORD DnsType;
+    DWORD AddressSize;
+    DWORD SockaddrSize;
+    DWORD AddressOffset;
+} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO;
+
+typedef struct _FLATBUFF
+{
+    PVOID Buffer;
+    PVOID BufferEnd;
+    ULONG_PTR BufferPos;
+    SIZE_T BufferSize;
+    SIZE_T BufferFreeSize;
+} FLATBUFF, *PFLATBUFF;
+
+/*
+ * memory.c
+ */
+VOID
+WINAPI
+Dns_Free(IN PVOID Address);
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size);
+
+/*
+ * addr.c
+ */
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily);
+
+/*
+ * dnsaddr.c
+ */
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(
+    IN PDNS_ADDRESS DnsAddress,
+    IN IN_ADDR Address,
+    IN WORD Unknown
+);
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(
+    IN PDNS_ADDRESS DnsAddress,
+    IN PIN6_ADDR Address,
+    IN ULONG ScopeId,
+    IN WORD Port
+);
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count);
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN WORD AddressFamily OPTIONAL,
+    IN DWORD AddressType OPTIONAL
+);
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray);
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN IN_ADDR Address,
+    IN DWORD AddressType
+);
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN DWORD AddressType
+);
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(
+    IN PDNS_RECORD DnsRecord,
+    OUT PDNS_ADDRESS DnsAddr
+);
+
+/*
+ * hostent.c
+ */
+PHOSTENT
+WINAPI
+Hostent_Init(
+    IN PVOID *Buffer,
+    IN WORD AddressFamily,
+    IN ULONG AddressSize,
+    IN ULONG AddressCount,
+    IN ULONG AliasCount
+);
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent);
+
+/*
+ * flatbuf.c
+ */
+VOID
+WINAPI
+FlatBuf_Init(
+    IN PFLATBUFF FlatBuffer,
+    IN PVOID Buffer,
+    IN SIZE_T Size
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID Buffer,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID String,
+    IN BOOLEAN IsUnicode
+);
+
+/*
+ * sablob.c
+ */
+PDNS_BLOB
+WINAPI
+SaBlob_Create(
+    IN ULONG Count
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(
+    IN LPWSTR Name,
+    IN ULONG Count,
+    IN PIN_ADDR AddressArray
+);
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob);
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(
+    IN OUT PULONG_PTR BufferPosition,
+    IN OUT PSIZE_T RemainingBufferSpace,
+    IN OUT PSIZE_T HostEntrySize,
+    IN PDNS_BLOB Blob,
+    IN DWORD StringType,
+    IN BOOLEAN Relative,
+    IN BOOLEAN BufferAllocated
+);
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(
+    IN PDNS_BLOB Blob,
+    IN LPWSTR String,
+    IN BOOLEAN IsAlias
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(
+    IN LPWSTR Name,
+    IN WORD DnsType,
+    IN ULONG Flags,
+    IN PVOID *Reserved,
+    IN DWORD AddressFamily
+);
+
+/*
+ * string.c
+ */
+ULONG
+WINAPI
+Dns_StringCopy(
+    OUT PVOID Destination,
+    IN OUT PULONG DestinationSize,
+    IN PVOID String,
+    IN ULONG StringSize OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name);
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(
+    IN PVOID String,
+    IN ULONG Size OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+/*
+ * straddr.c
+ */
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(
+    OUT PVOID Address,
+    IN OUT PULONG AddressSize,
+    IN LPWSTR AddressName,
+    IN OUT PDWORD AddressFamily
+);
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN_ADDR Address
+);
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN6_ADDR Address
+);
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(
+    OUT PDNS_ADDRESS DnsAddr,
+    IN LPWSTR Name
+);
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(
+    OUT PIN_ADDR Address,
+    IN LPWSTR Name
+);
+
+#endif
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS Ancillary Function Driver DLL
+ * FILE:        include/mswsock.h
+ * PURPOSE:     Ancillary Function Driver DLL header
+ */
+#ifndef __DNSLIB_H
+#define __DNSLIB_H
+
+/* INCLUDES ******************************************************************/
+#include <ws2atm.h>
+
+/* ENUMERATIONS **************************************************************/
+
+typedef enum _DNS_STRING_TYPE
+{
+    UnicodeString = 1,
+    Utf8String,
+    AnsiString,
+} DNS_STRING_TYPE;
+
+#define IpV4Address 3
+
+/* TYPES *********************************************************************/
+
+typedef struct _DNS_IPV6_ADDRESS
+{
+    ULONG Unknown;
+    ULONG Unknown2;
+    IP6_ADDRESS Address;
+    ULONG Unknown3;
+    ULONG Unknown4;
+    DWORD Reserved;
+    ULONG Unknown5;
+} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS;
+
+typedef struct _DNS_ADDRESS
+{
+    union
+    {
+        struct
+        {
+            WORD AddressFamily;
+            WORD Port;
+            ATM_ADDRESS AtmAddress;
+        };
+        SOCKADDR_IN Ip4Address;
+        SOCKADDR_IN6 Ip6Address;
+    };
+    ULONG AddressLength;
+    DWORD Sub;
+    ULONG Flag;
+} DNS_ADDRESS, *PDNS_ADDRESS;
+
+typedef struct _DNS_ARRAY
+{
+    ULONG AllocatedAddresses;
+    ULONG UsedAddresses;
+    ULONG Unknown[0x6];
+    DNS_ADDRESS Addresses[1];
+} DNS_ARRAY, *PDNS_ARRAY;
+
+typedef struct _DNS_BLOB
+{
+    LPWSTR Name;
+    PDNS_ARRAY DnsAddrArray;
+    PHOSTENT Hostent;
+    ULONG AliasCount;
+    ULONG Unknown;
+    LPWSTR Aliases[8];
+} DNS_BLOB, *PDNS_BLOB;
+
+typedef struct _DNS_FAMILY_INFO
+{
+    WORD AddrType;
+    WORD DnsType;
+    DWORD AddressSize;
+    DWORD SockaddrSize;
+    DWORD AddressOffset;
+} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO;
+
+typedef struct _FLATBUFF
+{
+    PVOID Buffer;
+    PVOID BufferEnd;
+    ULONG_PTR BufferPos;
+    SIZE_T BufferSize;
+    SIZE_T BufferFreeSize;
+} FLATBUFF, *PFLATBUFF;
+
+/*
+ * memory.c
+ */
+VOID
+WINAPI
+Dns_Free(IN PVOID Address);
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size);
+
+/*
+ * addr.c
+ */
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily);
+
+/*
+ * dnsaddr.c
+ */
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(
+    IN PDNS_ADDRESS DnsAddress,
+    IN IN_ADDR Address,
+    IN WORD Unknown
+);
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(
+    IN PDNS_ADDRESS DnsAddress,
+    IN PIN6_ADDR Address,
+    IN ULONG ScopeId,
+    IN WORD Port
+);
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count);
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN WORD AddressFamily OPTIONAL,
+    IN DWORD AddressType OPTIONAL
+);
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray);
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN IN_ADDR Address,
+    IN DWORD AddressType
+);
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN DWORD AddressType
+);
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(
+    IN PDNS_RECORD DnsRecord,
+    OUT PDNS_ADDRESS DnsAddr
+);
+
+/*
+ * hostent.c
+ */
+PHOSTENT
+WINAPI
+Hostent_Init(
+    IN PVOID *Buffer,
+    IN WORD AddressFamily,
+    IN ULONG AddressSize,
+    IN ULONG AddressCount,
+    IN ULONG AliasCount
+);
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent);
+
+/*
+ * flatbuf.c
+ */
+VOID
+WINAPI
+FlatBuf_Init(
+    IN PFLATBUFF FlatBuffer,
+    IN PVOID Buffer,
+    IN SIZE_T Size
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID Buffer,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID String,
+    IN BOOLEAN IsUnicode
+);
+
+/*
+ * sablob.c
+ */
+PDNS_BLOB
+WINAPI
+SaBlob_Create(
+    IN ULONG Count
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(
+    IN LPWSTR Name,
+    IN ULONG Count,
+    IN PIN_ADDR AddressArray
+);
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob);
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(
+    IN OUT PULONG_PTR BufferPosition,
+    IN OUT PSIZE_T RemainingBufferSpace,
+    IN OUT PSIZE_T HostEntrySize,
+    IN PDNS_BLOB Blob,
+    IN DWORD StringType,
+    IN BOOLEAN Relative,
+    IN BOOLEAN BufferAllocated
+);
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(
+    IN PDNS_BLOB Blob,
+    IN LPWSTR String,
+    IN BOOLEAN IsAlias
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(
+    IN LPWSTR Name,
+    IN WORD DnsType,
+    IN ULONG Flags,
+    IN PVOID *Reserved,
+    IN DWORD AddressFamily
+);
+
+/*
+ * string.c
+ */
+ULONG
+WINAPI
+Dns_StringCopy(
+    OUT PVOID Destination,
+    IN OUT PULONG DestinationSize,
+    IN PVOID String,
+    IN ULONG StringSize OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name);
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(
+    IN PVOID String,
+    IN ULONG Size OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+/*
+ * straddr.c
+ */
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(
+    OUT PVOID Address,
+    IN OUT PULONG AddressSize,
+    IN LPWSTR AddressName,
+    IN OUT PDWORD AddressFamily
+);
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN_ADDR Address
+);
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN6_ADDR Address
+);
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(
+    OUT PDNS_ADDRESS DnsAddr,
+    IN LPWSTR Name
+);
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(
+    OUT PIN_ADDR Address,
+    IN LPWSTR Name
+);
+
+#endif
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS Ancillary Function Driver DLL
+ * FILE:        include/mswsock.h
+ * PURPOSE:     Ancillary Function Driver DLL header
+ */
+#ifndef __DNSLIB_H
+#define __DNSLIB_H
+
+/* INCLUDES ******************************************************************/
+#include <ws2atm.h>
+
+/* ENUMERATIONS **************************************************************/
+
+typedef enum _DNS_STRING_TYPE
+{
+    UnicodeString = 1,
+    Utf8String,
+    AnsiString,
+} DNS_STRING_TYPE;
+
+#define IpV4Address 3
+
+/* TYPES *********************************************************************/
+
+typedef struct _DNS_IPV6_ADDRESS
+{
+    ULONG Unknown;
+    ULONG Unknown2;
+    IP6_ADDRESS Address;
+    ULONG Unknown3;
+    ULONG Unknown4;
+    DWORD Reserved;
+    ULONG Unknown5;
+} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS;
+
+typedef struct _DNS_ADDRESS
+{
+    union
+    {
+        struct
+        {
+            WORD AddressFamily;
+            WORD Port;
+            ATM_ADDRESS AtmAddress;
+        };
+        SOCKADDR_IN Ip4Address;
+        SOCKADDR_IN6 Ip6Address;
+    };
+    ULONG AddressLength;
+    DWORD Sub;
+    ULONG Flag;
+} DNS_ADDRESS, *PDNS_ADDRESS;
+
+typedef struct _DNS_ARRAY
+{
+    ULONG AllocatedAddresses;
+    ULONG UsedAddresses;
+    ULONG Unknown[0x6];
+    DNS_ADDRESS Addresses[1];
+} DNS_ARRAY, *PDNS_ARRAY;
+
+typedef struct _DNS_BLOB
+{
+    LPWSTR Name;
+    PDNS_ARRAY DnsAddrArray;
+    PHOSTENT Hostent;
+    ULONG AliasCount;
+    ULONG Unknown;
+    LPWSTR Aliases[8];
+} DNS_BLOB, *PDNS_BLOB;
+
+typedef struct _DNS_FAMILY_INFO
+{
+    WORD AddrType;
+    WORD DnsType;
+    DWORD AddressSize;
+    DWORD SockaddrSize;
+    DWORD AddressOffset;
+} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO;
+
+typedef struct _FLATBUFF
+{
+    PVOID Buffer;
+    PVOID BufferEnd;
+    ULONG_PTR BufferPos;
+    SIZE_T BufferSize;
+    SIZE_T BufferFreeSize;
+} FLATBUFF, *PFLATBUFF;
+
+/*
+ * memory.c
+ */
+VOID
+WINAPI
+Dns_Free(IN PVOID Address);
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size);
+
+/*
+ * addr.c
+ */
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily);
+
+/*
+ * dnsaddr.c
+ */
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(
+    IN PDNS_ADDRESS DnsAddress,
+    IN IN_ADDR Address,
+    IN WORD Unknown
+);
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(
+    IN PDNS_ADDRESS DnsAddress,
+    IN PIN6_ADDR Address,
+    IN ULONG ScopeId,
+    IN WORD Port
+);
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count);
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN WORD AddressFamily OPTIONAL,
+    IN DWORD AddressType OPTIONAL
+);
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray);
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN IN_ADDR Address,
+    IN DWORD AddressType
+);
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN DWORD AddressType
+);
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(
+    IN PDNS_RECORD DnsRecord,
+    OUT PDNS_ADDRESS DnsAddr
+);
+
+/*
+ * hostent.c
+ */
+PHOSTENT
+WINAPI
+Hostent_Init(
+    IN PVOID *Buffer,
+    IN WORD AddressFamily,
+    IN ULONG AddressSize,
+    IN ULONG AddressCount,
+    IN ULONG AliasCount
+);
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent);
+
+/*
+ * flatbuf.c
+ */
+VOID
+WINAPI
+FlatBuf_Init(
+    IN PFLATBUFF FlatBuffer,
+    IN PVOID Buffer,
+    IN SIZE_T Size
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID Buffer,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID String,
+    IN BOOLEAN IsUnicode
+);
+
+/*
+ * sablob.c
+ */
+PDNS_BLOB
+WINAPI
+SaBlob_Create(
+    IN ULONG Count
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(
+    IN LPWSTR Name,
+    IN ULONG Count,
+    IN PIN_ADDR AddressArray
+);
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob);
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(
+    IN OUT PULONG_PTR BufferPosition,
+    IN OUT PSIZE_T RemainingBufferSpace,
+    IN OUT PSIZE_T HostEntrySize,
+    IN PDNS_BLOB Blob,
+    IN DWORD StringType,
+    IN BOOLEAN Relative,
+    IN BOOLEAN BufferAllocated
+);
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(
+    IN PDNS_BLOB Blob,
+    IN LPWSTR String,
+    IN BOOLEAN IsAlias
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(
+    IN LPWSTR Name,
+    IN WORD DnsType,
+    IN ULONG Flags,
+    IN PVOID *Reserved,
+    IN DWORD AddressFamily
+);
+
+/*
+ * string.c
+ */
+ULONG
+WINAPI
+Dns_StringCopy(
+    OUT PVOID Destination,
+    IN OUT PULONG DestinationSize,
+    IN PVOID String,
+    IN ULONG StringSize OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name);
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(
+    IN PVOID String,
+    IN ULONG Size OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+/*
+ * straddr.c
+ */
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(
+    OUT PVOID Address,
+    IN OUT PULONG AddressSize,
+    IN LPWSTR AddressName,
+    IN OUT PDWORD AddressFamily
+);
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN_ADDR Address
+);
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN6_ADDR Address
+);
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(
+    OUT PDNS_ADDRESS DnsAddr,
+    IN LPWSTR Name
+);
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(
+    OUT PIN_ADDR Address,
+    IN LPWSTR Name
+);
+
+#endif
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS Ancillary Function Driver DLL
+ * FILE:        include/mswsock.h
+ * PURPOSE:     Ancillary Function Driver DLL header
+ */
+#ifndef __DNSLIB_H
+#define __DNSLIB_H
+
+/* INCLUDES ******************************************************************/
+#include <ws2atm.h>
+
+/* ENUMERATIONS **************************************************************/
+
+typedef enum _DNS_STRING_TYPE
+{
+    UnicodeString = 1,
+    Utf8String,
+    AnsiString,
+} DNS_STRING_TYPE;
+
+#define IpV4Address 3
+
+/* TYPES *********************************************************************/
+
+typedef struct _DNS_IPV6_ADDRESS
+{
+    ULONG Unknown;
+    ULONG Unknown2;
+    IP6_ADDRESS Address;
+    ULONG Unknown3;
+    ULONG Unknown4;
+    DWORD Reserved;
+    ULONG Unknown5;
+} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS;
+
+typedef struct _DNS_ADDRESS
+{
+    union
+    {
+        struct
+        {
+            WORD AddressFamily;
+            WORD Port;
+            ATM_ADDRESS AtmAddress;
+        };
+        SOCKADDR_IN Ip4Address;
+        SOCKADDR_IN6 Ip6Address;
+    };
+    ULONG AddressLength;
+    DWORD Sub;
+    ULONG Flag;
+} DNS_ADDRESS, *PDNS_ADDRESS;
+
+typedef struct _DNS_ARRAY
+{
+    ULONG AllocatedAddresses;
+    ULONG UsedAddresses;
+    ULONG Unknown[0x6];
+    DNS_ADDRESS Addresses[1];
+} DNS_ARRAY, *PDNS_ARRAY;
+
+typedef struct _DNS_BLOB
+{
+    LPWSTR Name;
+    PDNS_ARRAY DnsAddrArray;
+    PHOSTENT Hostent;
+    ULONG AliasCount;
+    ULONG Unknown;
+    LPWSTR Aliases[8];
+} DNS_BLOB, *PDNS_BLOB;
+
+typedef struct _DNS_FAMILY_INFO
+{
+    WORD AddrType;
+    WORD DnsType;
+    DWORD AddressSize;
+    DWORD SockaddrSize;
+    DWORD AddressOffset;
+} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO;
+
+typedef struct _FLATBUFF
+{
+    PVOID Buffer;
+    PVOID BufferEnd;
+    ULONG_PTR BufferPos;
+    SIZE_T BufferSize;
+    SIZE_T BufferFreeSize;
+} FLATBUFF, *PFLATBUFF;
+
+/*
+ * memory.c
+ */
+VOID
+WINAPI
+Dns_Free(IN PVOID Address);
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size);
+
+/*
+ * addr.c
+ */
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily);
+
+/*
+ * dnsaddr.c
+ */
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(
+    IN PDNS_ADDRESS DnsAddress,
+    IN IN_ADDR Address,
+    IN WORD Unknown
+);
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(
+    IN PDNS_ADDRESS DnsAddress,
+    IN PIN6_ADDR Address,
+    IN ULONG ScopeId,
+    IN WORD Port
+);
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count);
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN WORD AddressFamily OPTIONAL,
+    IN DWORD AddressType OPTIONAL
+);
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray);
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN IN_ADDR Address,
+    IN DWORD AddressType
+);
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN DWORD AddressType
+);
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(
+    IN PDNS_RECORD DnsRecord,
+    OUT PDNS_ADDRESS DnsAddr
+);
+
+/*
+ * hostent.c
+ */
+PHOSTENT
+WINAPI
+Hostent_Init(
+    IN PVOID *Buffer,
+    IN WORD AddressFamily,
+    IN ULONG AddressSize,
+    IN ULONG AddressCount,
+    IN ULONG AliasCount
+);
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent);
+
+/*
+ * flatbuf.c
+ */
+VOID
+WINAPI
+FlatBuf_Init(
+    IN PFLATBUFF FlatBuffer,
+    IN PVOID Buffer,
+    IN SIZE_T Size
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID Buffer,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID String,
+    IN BOOLEAN IsUnicode
+);
+
+/*
+ * sablob.c
+ */
+PDNS_BLOB
+WINAPI
+SaBlob_Create(
+    IN ULONG Count
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(
+    IN LPWSTR Name,
+    IN ULONG Count,
+    IN PIN_ADDR AddressArray
+);
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob);
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(
+    IN OUT PULONG_PTR BufferPosition,
+    IN OUT PSIZE_T RemainingBufferSpace,
+    IN OUT PSIZE_T HostEntrySize,
+    IN PDNS_BLOB Blob,
+    IN DWORD StringType,
+    IN BOOLEAN Relative,
+    IN BOOLEAN BufferAllocated
+);
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(
+    IN PDNS_BLOB Blob,
+    IN LPWSTR String,
+    IN BOOLEAN IsAlias
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(
+    IN LPWSTR Name,
+    IN WORD DnsType,
+    IN ULONG Flags,
+    IN PVOID *Reserved,
+    IN DWORD AddressFamily
+);
+
+/*
+ * string.c
+ */
+ULONG
+WINAPI
+Dns_StringCopy(
+    OUT PVOID Destination,
+    IN OUT PULONG DestinationSize,
+    IN PVOID String,
+    IN ULONG StringSize OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name);
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(
+    IN PVOID String,
+    IN ULONG Size OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+/*
+ * straddr.c
+ */
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(
+    OUT PVOID Address,
+    IN OUT PULONG AddressSize,
+    IN LPWSTR AddressName,
+    IN OUT PDWORD AddressFamily
+);
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN_ADDR Address
+);
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN6_ADDR Address
+);
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(
+    OUT PDNS_ADDRESS DnsAddr,
+    IN LPWSTR Name
+);
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(
+    OUT PIN_ADDR Address,
+    IN LPWSTR Name
+);
+
+#endif
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS Ancillary Function Driver DLL
+ * FILE:        include/mswsock.h
+ * PURPOSE:     Ancillary Function Driver DLL header
+ */
+#ifndef __DNSLIB_H
+#define __DNSLIB_H
+
+/* INCLUDES ******************************************************************/
+#include <ws2atm.h>
+
+/* ENUMERATIONS **************************************************************/
+
+typedef enum _DNS_STRING_TYPE
+{
+    UnicodeString = 1,
+    Utf8String,
+    AnsiString,
+} DNS_STRING_TYPE;
+
+#define IpV4Address 3
+
+/* TYPES *********************************************************************/
+
+typedef struct _DNS_IPV6_ADDRESS
+{
+    ULONG Unknown;
+    ULONG Unknown2;
+    IP6_ADDRESS Address;
+    ULONG Unknown3;
+    ULONG Unknown4;
+    DWORD Reserved;
+    ULONG Unknown5;
+} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS;
+
+typedef struct _DNS_ADDRESS
+{
+    union
+    {
+        struct
+        {
+            WORD AddressFamily;
+            WORD Port;
+            ATM_ADDRESS AtmAddress;
+        };
+        SOCKADDR_IN Ip4Address;
+        SOCKADDR_IN6 Ip6Address;
+    };
+    ULONG AddressLength;
+    DWORD Sub;
+    ULONG Flag;
+} DNS_ADDRESS, *PDNS_ADDRESS;
+
+typedef struct _DNS_ARRAY
+{
+    ULONG AllocatedAddresses;
+    ULONG UsedAddresses;
+    ULONG Unknown[0x6];
+    DNS_ADDRESS Addresses[1];
+} DNS_ARRAY, *PDNS_ARRAY;
+
+typedef struct _DNS_BLOB
+{
+    LPWSTR Name;
+    PDNS_ARRAY DnsAddrArray;
+    PHOSTENT Hostent;
+    ULONG AliasCount;
+    ULONG Unknown;
+    LPWSTR Aliases[8];
+} DNS_BLOB, *PDNS_BLOB;
+
+typedef struct _DNS_FAMILY_INFO
+{
+    WORD AddrType;
+    WORD DnsType;
+    DWORD AddressSize;
+    DWORD SockaddrSize;
+    DWORD AddressOffset;
+} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO;
+
+typedef struct _FLATBUFF
+{
+    PVOID Buffer;
+    PVOID BufferEnd;
+    ULONG_PTR BufferPos;
+    SIZE_T BufferSize;
+    SIZE_T BufferFreeSize;
+} FLATBUFF, *PFLATBUFF;
+
+/*
+ * memory.c
+ */
+VOID
+WINAPI
+Dns_Free(IN PVOID Address);
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size);
+
+/*
+ * addr.c
+ */
+PDNS_FAMILY_INFO
+WINAPI
+FamilyInfo_GetForFamily(IN WORD AddressFamily);
+
+/*
+ * dnsaddr.c
+ */
+VOID
+WINAPI
+DnsAddr_BuildFromIp4(
+    IN PDNS_ADDRESS DnsAddress,
+    IN IN_ADDR Address,
+    IN WORD Unknown
+);
+
+VOID
+WINAPI
+DnsAddr_BuildFromIp6(
+    IN PDNS_ADDRESS DnsAddress,
+    IN PIN6_ADDR Address,
+    IN ULONG ScopeId,
+    IN WORD Port
+);
+
+PDNS_ARRAY
+WINAPI
+DnsAddrArray_Create(ULONG Count);
+
+BOOL
+WINAPI
+DnsAddrArray_AddAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN WORD AddressFamily OPTIONAL,
+    IN DWORD AddressType OPTIONAL
+);
+
+VOID
+WINAPI
+DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray);
+
+BOOL
+WINAPI
+DnsAddrArray_AddIp4(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN IN_ADDR Address,
+    IN DWORD AddressType
+);
+
+BOOL
+WINAPI
+DnsAddrArray_ContainsAddr(
+    IN PDNS_ARRAY DnsAddrArray,
+    IN PDNS_ADDRESS DnsAddress,
+    IN DWORD AddressType
+);
+
+BOOLEAN
+WINAPI
+DnsAddr_BuildFromDnsRecord(
+    IN PDNS_RECORD DnsRecord,
+    OUT PDNS_ADDRESS DnsAddr
+);
+
+/*
+ * hostent.c
+ */
+PHOSTENT
+WINAPI
+Hostent_Init(
+    IN PVOID *Buffer,
+    IN WORD AddressFamily,
+    IN ULONG AddressSize,
+    IN ULONG AddressCount,
+    IN ULONG AliasCount
+);
+
+VOID
+WINAPI
+Hostent_ConvertToOffsets(IN PHOSTENT Hostent);
+
+/*
+ * flatbuf.c
+ */
+VOID
+WINAPI
+FlatBuf_Init(
+    IN PFLATBUFF FlatBuffer,
+    IN PVOID Buffer,
+    IN SIZE_T Size
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_CopyMemory(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID Buffer,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_Reserve(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN SIZE_T Size,
+    IN ULONG Align
+);
+
+PVOID
+WINAPI
+FlatBuf_Arg_WriteString(
+    IN OUT PULONG_PTR Position,
+    IN OUT PSIZE_T FreeSize,
+    IN PVOID String,
+    IN BOOLEAN IsUnicode
+);
+
+/*
+ * sablob.c
+ */
+PDNS_BLOB
+WINAPI
+SaBlob_Create(
+    IN ULONG Count
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(
+    IN LPWSTR Name,
+    IN ULONG Count,
+    IN PIN_ADDR AddressArray
+);
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob);
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(
+    IN OUT PULONG_PTR BufferPosition,
+    IN OUT PSIZE_T RemainingBufferSpace,
+    IN OUT PSIZE_T HostEntrySize,
+    IN PDNS_BLOB Blob,
+    IN DWORD StringType,
+    IN BOOLEAN Relative,
+    IN BOOLEAN BufferAllocated
+);
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(
+    IN PDNS_BLOB Blob,
+    IN LPWSTR String,
+    IN BOOLEAN IsAlias
+);
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(
+    IN LPWSTR Name,
+    IN WORD DnsType,
+    IN ULONG Flags,
+    IN PVOID *Reserved,
+    IN DWORD AddressFamily
+);
+
+/*
+ * string.c
+ */
+ULONG
+WINAPI
+Dns_StringCopy(
+    OUT PVOID Destination,
+    IN OUT PULONG DestinationSize,
+    IN PVOID String,
+    IN ULONG StringSize OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name);
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(
+    IN PVOID String,
+    IN ULONG Size OPTIONAL,
+    IN DWORD InputType,
+    IN DWORD OutputType
+);
+
+/*
+ * straddr.c
+ */
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(
+    OUT PVOID Address,
+    IN OUT PULONG AddressSize,
+    IN LPWSTR AddressName,
+    IN OUT PDWORD AddressFamily
+);
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN_ADDR Address
+);
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(
+    OUT LPWSTR Name,
+    IN IN6_ADDR Address
+);
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(
+    OUT PDNS_ADDRESS DnsAddr,
+    IN LPWSTR Name
+);
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(
+    OUT PIN_ADDR Address,
+    IN LPWSTR Name
+);
+
+#endif
diff --git a/dll/win32/mswsock/dns/inc/windnsp.h b/dll/win32/mswsock/dns/inc/windnsp.h
new file mode 100644 (file)
index 0000000..66cfbd8
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNSAPI Header
+ * FILE:        include/libs/dns/windnsp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+PVOID
+WINAPI
+DnsApiAlloc(
+    IN DWORD Size
+);
+
+PVOID
+WINAPI
+DnsQueryConfigAllocEx(
+    IN DNS_CONFIG_TYPE Config,
+    OUT PVOID pBuffer,
+    IN OUT PDWORD pBufferLength
+);
+
+VOID
+WINAPI
+DnsApiFree(
+    IN PVOID pBuffer
+);
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNSAPI Header
+ * FILE:        include/libs/dns/windnsp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+PVOID
+WINAPI
+DnsApiAlloc(
+    IN DWORD Size
+);
+
+PVOID
+WINAPI
+DnsQueryConfigAllocEx(
+    IN DNS_CONFIG_TYPE Config,
+    OUT PVOID pBuffer,
+    IN OUT PDWORD pBufferLength
+);
+
+VOID
+WINAPI
+DnsApiFree(
+    IN PVOID pBuffer
+);
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNSAPI Header
+ * FILE:        include/libs/dns/windnsp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+PVOID
+WINAPI
+DnsApiAlloc(
+    IN DWORD Size
+);
+
+PVOID
+WINAPI
+DnsQueryConfigAllocEx(
+    IN DNS_CONFIG_TYPE Config,
+    OUT PVOID pBuffer,
+    IN OUT PDWORD pBufferLength
+);
+
+VOID
+WINAPI
+DnsApiFree(
+    IN PVOID pBuffer
+);
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNSAPI Header
+ * FILE:        include/libs/dns/windnsp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+PVOID
+WINAPI
+DnsApiAlloc(
+    IN DWORD Size
+);
+
+PVOID
+WINAPI
+DnsQueryConfigAllocEx(
+    IN DNS_CONFIG_TYPE Config,
+    OUT PVOID pBuffer,
+    IN OUT PDWORD pBufferLength
+);
+
+VOID
+WINAPI
+DnsApiFree(
+    IN PVOID pBuffer
+);
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNSAPI Header
+ * FILE:        include/libs/dns/windnsp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+PVOID
+WINAPI
+DnsApiAlloc(
+    IN DWORD Size
+);
+
+PVOID
+WINAPI
+DnsQueryConfigAllocEx(
+    IN DNS_CONFIG_TYPE Config,
+    OUT PVOID pBuffer,
+    IN OUT PDWORD pBufferLength
+);
+
+VOID
+WINAPI
+DnsApiFree(
+    IN PVOID pBuffer
+);
+
+/* EOF */
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNSAPI Header
+ * FILE:        include/libs/dns/windnsp.h
+ * PURPOSE:     DNSLIB Precompiled Header
+ */
+
+PVOID
+WINAPI
+DnsApiAlloc(
+    IN DWORD Size
+);
+
+PVOID
+WINAPI
+DnsQueryConfigAllocEx(
+    IN DNS_CONFIG_TYPE Config,
+    OUT PVOID pBuffer,
+    IN OUT PDWORD pBufferLength
+);
+
+VOID
+WINAPI
+DnsApiFree(
+    IN PVOID pBuffer
+);
+
+/* EOF */
diff --git a/dll/win32/mswsock/dns/ip6.c b/dll/win32/mswsock/dns/ip6.c
new file mode 100644 (file)
index 0000000..1148642
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/ip6.c
+ * PURPOSE:     Functions for dealing with IPv6 Specific issues.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/ip6.c
+ * PURPOSE:     Functions for dealing with IPv6 Specific issues.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/ip6.c
+ * PURPOSE:     Functions for dealing with IPv6 Specific issues.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/ip6.c
+ * PURPOSE:     Functions for dealing with IPv6 Specific issues.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
diff --git a/dll/win32/mswsock/dns/memory.c b/dll/win32/mswsock/dns/memory.c
new file mode 100644 (file)
index 0000000..8db2f0a
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/memory.c
+ * PURPOSE:     DNS Memory Manager Implementation and Heap.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+typedef PVOID
+(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size);
+typedef VOID
+(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer);
+
+PDNS_ALLOC_FUNCTION pDnsAllocFunction;
+PDNS_FREE_FUNCTION pDnsFreeFunction;
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WINAPI
+Dns_Free(IN PVOID Address)
+{
+    /* Check if whoever imported us specified a special free function */
+    if (pDnsFreeFunction)
+    {
+        /* Use it */
+        pDnsFreeFunction(Address);
+    }
+    else
+    {
+        /* Use our own */
+        LocalFree(Address);
+    }
+}
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size)
+{
+    PVOID Buffer;
+
+    /* Check if whoever imported us specified a special allocation function */
+    if (pDnsAllocFunction)
+    {
+        /* Use it to allocate the memory */
+        Buffer = pDnsAllocFunction(Size);
+        if (Buffer)
+        {
+            /* Zero it out */
+            RtlZeroMemory(Buffer, Size);
+        }
+    }
+    else
+    {
+        /* Use our default */
+        Buffer = LocalAlloc(LMEM_ZEROINIT, Size);
+    }
+
+    /* Return the allocate pointer */
+    return Buffer;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/memory.c
+ * PURPOSE:     DNS Memory Manager Implementation and Heap.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+typedef PVOID
+(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size);
+typedef VOID
+(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer);
+
+PDNS_ALLOC_FUNCTION pDnsAllocFunction;
+PDNS_FREE_FUNCTION pDnsFreeFunction;
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WINAPI
+Dns_Free(IN PVOID Address)
+{
+    /* Check if whoever imported us specified a special free function */
+    if (pDnsFreeFunction)
+    {
+        /* Use it */
+        pDnsFreeFunction(Address);
+    }
+    else
+    {
+        /* Use our own */
+        LocalFree(Address);
+    }
+}
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size)
+{
+    PVOID Buffer;
+
+    /* Check if whoever imported us specified a special allocation function */
+    if (pDnsAllocFunction)
+    {
+        /* Use it to allocate the memory */
+        Buffer = pDnsAllocFunction(Size);
+        if (Buffer)
+        {
+            /* Zero it out */
+            RtlZeroMemory(Buffer, Size);
+        }
+    }
+    else
+    {
+        /* Use our default */
+        Buffer = LocalAlloc(LMEM_ZEROINIT, Size);
+    }
+
+    /* Return the allocate pointer */
+    return Buffer;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/memory.c
+ * PURPOSE:     DNS Memory Manager Implementation and Heap.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+typedef PVOID
+(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size);
+typedef VOID
+(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer);
+
+PDNS_ALLOC_FUNCTION pDnsAllocFunction;
+PDNS_FREE_FUNCTION pDnsFreeFunction;
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WINAPI
+Dns_Free(IN PVOID Address)
+{
+    /* Check if whoever imported us specified a special free function */
+    if (pDnsFreeFunction)
+    {
+        /* Use it */
+        pDnsFreeFunction(Address);
+    }
+    else
+    {
+        /* Use our own */
+        LocalFree(Address);
+    }
+}
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size)
+{
+    PVOID Buffer;
+
+    /* Check if whoever imported us specified a special allocation function */
+    if (pDnsAllocFunction)
+    {
+        /* Use it to allocate the memory */
+        Buffer = pDnsAllocFunction(Size);
+        if (Buffer)
+        {
+            /* Zero it out */
+            RtlZeroMemory(Buffer, Size);
+        }
+    }
+    else
+    {
+        /* Use our default */
+        Buffer = LocalAlloc(LMEM_ZEROINIT, Size);
+    }
+
+    /* Return the allocate pointer */
+    return Buffer;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/memory.c
+ * PURPOSE:     DNS Memory Manager Implementation and Heap.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+typedef PVOID
+(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size);
+typedef VOID
+(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer);
+
+PDNS_ALLOC_FUNCTION pDnsAllocFunction;
+PDNS_FREE_FUNCTION pDnsFreeFunction;
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+WINAPI
+Dns_Free(IN PVOID Address)
+{
+    /* Check if whoever imported us specified a special free function */
+    if (pDnsFreeFunction)
+    {
+        /* Use it */
+        pDnsFreeFunction(Address);
+    }
+    else
+    {
+        /* Use our own */
+        LocalFree(Address);
+    }
+}
+
+PVOID
+WINAPI
+Dns_AllocZero(IN SIZE_T Size)
+{
+    PVOID Buffer;
+
+    /* Check if whoever imported us specified a special allocation function */
+    if (pDnsAllocFunction)
+    {
+        /* Use it to allocate the memory */
+        Buffer = pDnsAllocFunction(Size);
+        if (Buffer)
+        {
+            /* Zero it out */
+            RtlZeroMemory(Buffer, Size);
+        }
+    }
+    else
+    {
+        /* Use our default */
+        Buffer = LocalAlloc(LMEM_ZEROINIT, Size);
+    }
+
+    /* Return the allocate pointer */
+    return Buffer;
+}
+
diff --git a/dll/win32/mswsock/dns/name.c b/dll/win32/mswsock/dns/name.c
new file mode 100644 (file)
index 0000000..75fdbc9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/name.c
+ * PURPOSE:     Functions dealing with DNS (Canonical, FQDN, Host) Names
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/name.c
+ * PURPOSE:     Functions dealing with DNS (Canonical, FQDN, Host) Names
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/name.c
+ * PURPOSE:     Functions dealing with DNS (Canonical, FQDN, Host) Names
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/name.c
+ * PURPOSE:     Functions dealing with DNS (Canonical, FQDN, Host) Names
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
diff --git a/dll/win32/mswsock/dns/print.c b/dll/win32/mswsock/dns/print.c
new file mode 100644 (file)
index 0000000..956c4ea
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/print.c
+ * PURPOSE:     Callback Functions for printing a variety of DNSLIB Structures
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/print.c
+ * PURPOSE:     Callback Functions for printing a variety of DNSLIB Structures
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/print.c
+ * PURPOSE:     Callback Functions for printing a variety of DNSLIB Structures
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/print.c
+ * PURPOSE:     Callback Functions for printing a variety of DNSLIB Structures
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
diff --git a/dll/win32/mswsock/dns/record.c b/dll/win32/mswsock/dns/record.c
new file mode 100644 (file)
index 0000000..62f577d
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/record.c
+ * PURPOSE:     Functions for managing DNS Record structures.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/record.c
+ * PURPOSE:     Functions for managing DNS Record structures.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/record.c
+ * PURPOSE:     Functions for managing DNS Record structures.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/record.c
+ * PURPOSE:     Functions for managing DNS Record structures.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
diff --git a/dll/win32/mswsock/dns/rrprint.c b/dll/win32/mswsock/dns/rrprint.c
new file mode 100644 (file)
index 0000000..1e302d4
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/rrprint.c
+ * PURPOSE:     Callback functions for printing RR Structures for each Record.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/rrprint.c
+ * PURPOSE:     Callback functions for printing RR Structures for each Record.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/rrprint.c
+ * PURPOSE:     Callback functions for printing RR Structures for each Record.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/rrprint.c
+ * PURPOSE:     Callback functions for printing RR Structures for each Record.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
diff --git a/dll/win32/mswsock/dns/sablob.c b/dll/win32/mswsock/dns/sablob.c
new file mode 100644 (file)
index 0000000..ff1a9ba
--- /dev/null
@@ -0,0 +1,2580 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/sablob.c
+ * PURPOSE:     Functions for the Saved Answer Blob Implementation
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PVOID
+WINAPI
+FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position,
+                                IN PSIZE_T FreeSize,
+                                IN SIZE_T Size)
+{
+    /* Just a little helper that we use */
+    return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID));
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_Create(IN ULONG Count)
+{
+    PDNS_BLOB Blob;
+    PDNS_ARRAY DnsAddrArray;
+
+    /* Allocate the blob */
+    Blob = Dns_AllocZero(sizeof(DNS_BLOB));
+    if (Blob)
+    {
+        /* Check if it'll hold any addresses */
+        if (Count)
+        {
+            /* Create the DNS Address Array */
+            DnsAddrArray = DnsAddrArray_Create(Count);
+            if (!DnsAddrArray)
+            {
+                /* Failure, free the blob */
+                SaBlob_Free(Blob);
+                SetLastError(ERROR_OUTOFMEMORY);
+            }
+            else
+            {
+                /* Link it with the blob */
+                Blob->DnsAddrArray = DnsAddrArray;
+            }
+        }
+    }
+
+    /* Return the blob */
+    return Blob;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(IN LPWSTR Name,
+                     IN ULONG Count,
+                     IN PIN_ADDR AddressArray)
+{
+    PDNS_BLOB Blob;
+    LPWSTR NameCopy;
+    ULONG i;
+
+    /* Create the blob */
+    Blob = SaBlob_Create(Count);
+    if (!Blob) goto Quickie;
+
+    /* If we have a name */
+    if (Name)
+    {
+        /* Create a copy of it */
+        NameCopy = Dns_CreateStringCopy_W(Name);
+        if (!NameCopy) goto Quickie;
+
+        /* Save the pointer to the name */
+        Blob->Name = NameCopy;
+    }
+
+    /* Loop all the addresses */
+    for (i = 0; i < Count; i++)
+    {
+        /* Add an entry for this address */
+        DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address);
+    }
+
+    /* Return the blob */
+    return Blob;
+
+Quickie:
+    /* Free the blob, set error and fail */
+    SaBlob_Free(Blob);
+    SetLastError(ERROR_OUTOFMEMORY);
+    return NULL;
+}
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob)
+{
+    /* Make sure we got a blob */
+    if (Blob)
+    {
+        /* Free the name */
+        Dns_Free(Blob->Name);
+
+        /* Loop the aliases */
+        while (Blob->AliasCount)
+        {
+            /* Free the alias */
+            Dns_Free(Blob->Aliases[Blob->AliasCount]);
+
+            /* Decrease number of aliases */
+            Blob->AliasCount--;
+        }
+
+        /* Free the DNS Address Array */
+        DnsAddrArray_Free(Blob->DnsAddrArray);
+
+        /* Free the blob itself */
+        Dns_Free(Blob);
+    }
+}
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition,
+                     IN OUT PSIZE_T FreeBufferSpace,
+                     IN OUT PSIZE_T HostEntrySize,
+                     IN PDNS_BLOB Blob,
+                     IN DWORD StringType,
+                     IN BOOLEAN Relative,
+                     IN BOOLEAN BufferAllocated)
+{
+    PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray;
+    ULONG AliasCount = Blob->AliasCount;
+    WORD AddressFamily = AF_UNSPEC;
+    ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize;
+    ULONG AliasPointerSize;
+    PDNS_FAMILY_INFO FamilyInfo = NULL;
+    ULONG StringLength = 0;
+    ULONG i;
+    ULONG HostentSize = 0;
+    PHOSTENT Hostent = NULL;
+    ULONG_PTR HostentPtr;
+    PVOID CurrentAddress;
+
+    /* Check if we actually have any addresses */
+    if (DnsAddrArray)
+    {
+        /* Get the address family */
+        AddressFamily = DnsAddrArray->Addresses[0].AddressFamily;
+
+        /* Get family information */
+        FamilyInfo = FamilyInfo_GetForFamily(AddressFamily);
+
+        /* Save the current address count and their size */
+        AddressCount = DnsAddrArray->UsedAddresses;
+        AddressSize = FamilyInfo->AddressSize;
+    }
+
+    /* Calculate total size for all the addresses, and their pointers */
+    TotalSize = AddressSize * AddressCount;
+    NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID);
+
+    /* Check if we have a name */
+    if (Blob->Name)
+    {
+        /* Find out the size we'll need for a copy */
+        StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name,
+                                                         0,
+                                                         UnicodeString,
+                                                         StringType) + 1) & ~1;
+    }
+
+    /*  Now do the same for the aliases */
+    for (i = AliasCount; i; i--)
+    {
+        /* Find out the size we'll need for a copy */
+        HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i],
+                                                         0,
+                                                         UnicodeString,
+                                                         StringType) + 1) & ~1;
+    }
+
+    /* Find out how much the pointers will take */
+    AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID);
+
+    /* Calculate Hostent Size */
+    HostentSize += TotalSize +
+                   NamePointerSize +
+                   AliasPointerSize +
+                   StringLength +
+                   sizeof(HOSTENT);
+
+    /* Check if we already have a buffer */
+    if (!BufferAllocated)
+    {
+        /* We don't, allocate space ourselves */
+        HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize);
+    }
+    else
+    {
+        /* We do, so allocate space in the buffer */
+        HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition,
+                                                                FreeBufferSpace,
+                                                                HostentSize);
+    }
+
+    /* Make sure we got space */
+    if (HostentPtr)
+    {
+        /* Initialize it */
+        Hostent = Hostent_Init((PVOID)&HostentPtr,
+                               AddressFamily,
+                               AddressSize,
+                               AddressCount,
+                               AliasCount);
+    }
+
+    /* Loop the addresses */
+    for (i = 0; i < AddressCount; i++)
+    {
+        /* Get the pointer of the current address */
+        CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] +
+                                             FamilyInfo->AddressOffset);
+
+        /* Write the pointer */
+        Hostent->h_addr_list[i] = (PCHAR)HostentPtr;
+
+        /* Copy the address */
+        RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize);
+
+        /* Advance the buffer */
+        HostentPtr += AddressSize;
+    }
+
+    /* Check if we have a name */
+    if (Blob->Name)
+    {
+        /* Align our current position */
+        HostentPtr += 1 & ~1;
+
+        /* Save our name here */
+        Hostent->h_name = (LPSTR)HostentPtr;
+
+        /* Now copy it in the blob */
+        HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
+                                     NULL,
+                                     Blob->Name,
+                                     0,
+                                     UnicodeString,
+                                     StringType);
+    }
+
+    /* Loop the Aliases */
+    for (i = AliasCount; i; i--)
+    {
+        /* Align our current position */
+        HostentPtr += 1 & ~1;
+
+        /* Save our alias here */
+        Hostent->h_aliases[i] = (LPSTR)HostentPtr;
+
+        /* Now copy it in the blob */
+        HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
+                                     NULL,
+                                     Blob->Aliases[i],
+                                     0,
+                                     UnicodeString,
+                                     StringType);
+    }
+
+    /* Check if the caller didn't have a buffer */
+    if (!BufferAllocated)
+    {
+        /* Return the size; not needed if we had a blob, since it's internal */
+        *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr;
+    }
+
+    /* Convert to Offsets if requested */
+    if(Relative) Hostent_ConvertToOffsets(Hostent);
+
+    /* Return the full, complete, hostent */
+    return Hostent;
+}
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob,
+                        IN LPWSTR String,
+                        IN BOOLEAN IsAlias)
+{
+    /* Check if this is an alias */
+    if (!IsAlias)
+    {
+        /* It's not. Simply create a copy of the string */
+        Blob->Name = Dns_CreateStringCopy_W(String);
+        if (!Blob->Name) return GetLastError();
+    }
+    else
+    {
+        /* Does it have a name, and less then 8 aliases? */
+        if ((Blob->Name) && (Blob->AliasCount <= 8))
+        {
+            /* Yup, create a copy of the string and increase the alias count */
+            Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String);
+            Blob->AliasCount++;
+        }
+        else
+        {
+            /* Invalid request! */
+            return ERROR_MORE_DATA;
+        }
+    }
+
+    /* Return Success */
+    return ERROR_SUCCESS;
+}
+
+INT
+WINAPI
+SaBlob_WriteAddress(IN PDNS_BLOB Blob,
+                    OUT PDNS_ADDRESS DnsAddr)
+{
+    /* Check if we have an array yet */
+    if (!Blob->DnsAddrArray)
+    {
+        /* Allocate one! */
+        Blob->DnsAddrArray = DnsAddrArray_Create(1);
+        if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY;
+    }
+
+    /* Add this address */
+    return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ?
+           ERROR_SUCCESS:
+           ERROR_MORE_DATA;
+}
+
+BOOLEAN
+WINAPI
+SaBlob_IsSupportedAddrType(WORD DnsType)
+{
+    /* Check for valid Types that we support */
+    return (DnsType == DNS_TYPE_A ||
+            DnsType == DNS_TYPE_ATMA ||
+            DnsType == DNS_TYPE_AAAA);
+}
+
+INT
+WINAPI
+SaBlob_WriteRecords(OUT PDNS_BLOB Blob,
+                    IN PDNS_RECORD DnsRecord,
+                    IN BOOLEAN DoAlias)
+{
+    DNS_ADDRESS DnsAddress;
+    INT ErrorCode = STATUS_INVALID_PARAMETER;
+    BOOLEAN WroteOnce = FALSE;
+
+    /* Zero out the Address */
+    RtlZeroMemory(&DnsAddress, sizeof(DnsAddress));
+
+    /* Loop through all the Records */
+    while (DnsRecord)
+    {
+        /* Is this not an answer? */
+        if (DnsRecord->Flags.S.Section != DNSREC_ANSWER)
+        {
+            /* Then simply move on to the next DNS Record */
+            DnsRecord = DnsRecord->pNext;
+            continue;
+        }
+
+        /* Check the type of thsi record */
+        switch(DnsRecord->wType)
+        {
+            /* Regular IPv4, v6 or ATM Record */
+            case DNS_TYPE_A:
+            case DNS_TYPE_AAAA:
+            case DNS_TYPE_ATMA:
+
+                /* Create a DNS Address from the record */
+                DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress);
+
+                /* Add it to the DNS Blob */
+                ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress);
+
+                /* Add the name, if needed */
+                if ((DoAlias) &&
+                    (!WroteOnce) &&
+                    (!Blob->Name) &&
+                    (DnsRecord->pName))
+                {
+                    /* Write the name from the DNS Record */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        FALSE);
+                    WroteOnce = TRUE;
+                }
+                break;
+
+            case DNS_TYPE_CNAME:
+
+                /* Just write the alias name */
+                ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                    DnsRecord->pName,
+                                                    TRUE);
+                break;
+
+            case DNS_TYPE_PTR:
+
+                /* Check if we already have a name */
+                if (Blob->Name)
+                {
+                    /* We don't, so add this as a name */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        FALSE);
+                }
+                else
+                {
+                    /* We do, so add it as an alias */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        TRUE);
+                }
+                break;
+            default:
+                break;
+        }
+
+        /* Next record */
+        DnsRecord = DnsRecord->pNext;
+    }
+
+    /* Return error code */
+    return ErrorCode;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord,
+                         IN BOOLEAN DoAliases,
+                         IN DWORD DnsType)
+{
+    PDNS_RECORD LocalDnsRecord;
+    ULONG ProcessedCount = 0;
+    PDNS_BLOB DnsBlob;
+    INT ErrorCode;
+    DNS_ADDRESS DnsAddress;
+
+    /* Find out how many DNS Addresses to allocate */
+    LocalDnsRecord = DnsRecord;
+    while (LocalDnsRecord)
+    {
+        /* Make sure this record is an answer */
+        if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) &&
+            (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType)))
+        {
+            /* Increase number of records to process */
+            ProcessedCount++;
+        }
+
+        /* Move to the next record */
+        LocalDnsRecord = LocalDnsRecord->pNext;
+    }
+
+    /* Create the DNS Blob */
+    DnsBlob = SaBlob_Create(ProcessedCount);
+    if (!DnsBlob)
+    {
+        /* Fail */
+        ErrorCode = GetLastError();
+        goto Quickie;
+    }
+
+    /* Write the record to the DNS Blob */
+    ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE);
+    if (ErrorCode != NO_ERROR)
+    {
+        /* We failed... but do we still have valid data? */
+        if ((DnsBlob->Name) || (DnsBlob->AliasCount))
+        {
+            /* We'll just assume success then */
+            ErrorCode = NO_ERROR;
+        }
+        else
+        {
+            /* Ok, last chance..do you have a DNS Address Array? */
+            if ((DnsBlob->DnsAddrArray) &&
+                (DnsBlob->DnsAddrArray->UsedAddresses))
+            {
+                /* Boy are you lucky! */
+                ErrorCode = NO_ERROR;
+            }
+        }
+
+        /* Buh-bye! */
+        goto Quickie;
+    }
+
+    /* Check if this is a PTR record */
+    if ((DnsRecord->wType == DNS_TYPE_PTR) ||
+        ((DnsType == DNS_TYPE_PTR) &&
+         (DnsRecord->wType == DNS_TYPE_CNAME) &&
+         (DnsRecord->Flags.S.Section == DNSREC_ANSWER)))
+    {
+        /* Get a DNS Address Structure */
+        if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName))
+        {
+            /* Add it to the Blob */
+            if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR;
+        }
+    }
+
+    /* Ok...do we still not have a name? */
+    if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord))
+    {
+        /* We have an local DNS Record, so just use it to write the name */
+        ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob,
+                                            LocalDnsRecord->pName,
+                                            FALSE);
+    }
+
+Quickie:
+    /* Check error code */
+    if (ErrorCode != NO_ERROR)
+    {
+        /* Free the blob and set the error */
+        SaBlob_Free(DnsBlob);
+        DnsBlob = NULL;
+        SetLastError(ErrorCode);
+    }
+
+    /* Return */
+    return DnsBlob;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(IN LPWSTR Name,
+             IN WORD DnsType,
+             IN ULONG Flags,
+             IN PVOID *Reserved,
+             IN DWORD AddressFamily)
+{
+    PDNS_RECORD DnsRecord = NULL;
+    INT ErrorCode;
+    PDNS_BLOB DnsBlob = NULL;
+    LPWSTR LocalName, LocalNameCopy;
+
+    /* If they want reserved data back, clear it out in case we fail */
+    if (Reserved) *Reserved = NULL;
+
+    /* Query DNS */
+    ErrorCode = DnsQuery_W(Name,
+                           DnsType,
+                           Flags,
+                           NULL,
+                           &DnsRecord,
+                           Reserved);
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* We failed... did the caller use reserved data? */
+        if (Reserved && *Reserved)
+        {
+            /* He did, and it was valid. Free it */
+            DnsApiFree(*Reserved);
+            *Reserved = NULL;
+        }
+
+        /* Normalize error code */
+        if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN;
+        goto Quickie;
+    }
+
+    /* Now create the Blob from the DNS Records */
+    DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType);
+    if (!DnsBlob)
+    {
+        /* Failed, get error code */
+        ErrorCode = GetLastError();
+        goto Quickie;
+    }
+
+    /* Make sure it has a name */
+    if (!DnsBlob->Name)
+    {
+        /* It doesn't, fail */
+        ErrorCode = DNS_INFO_NO_RECORDS;
+        goto Quickie;
+    }
+
+    /* Check if the name is local or loopback */
+    if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) &&
+        !(DnsNameCompare_W(DnsBlob->Name, L"loopback")))
+    {
+        /* Nothing left to do, exit! */
+        goto Quickie;
+    }
+
+    /* This is a local name...query it */
+    DnsQueryConfig(DnsConfigFullHostName_W,
+                   DNS_CONFIG_FLAG_ALLOC,
+                   NULL,
+                   NULL,
+                   &LocalName,
+                   0);
+    if (LocalName)
+    {
+        /* Create a copy for the caller */
+        LocalNameCopy = Dns_CreateStringCopy_W(LocalName);
+        if (LocalNameCopy)
+        {
+            /* Overwrite the one in the blob */
+            DnsBlob->Name = LocalNameCopy;
+        }
+        else
+        {
+            /* We failed to make a copy, free memory */
+            DnsApiFree(LocalName);
+        }
+    }
+
+Quickie:
+    /* Free the DNS Record if we have one */
+    if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList);
+
+    /* Check if this is a failure path with an active blob */
+    if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob))
+    {
+        /* Free the blob */
+        SaBlob_Free(DnsBlob);
+        DnsBlob = NULL;
+    }
+
+    /* Set the last error and return */
+    SetLastError(ErrorCode);
+    return DnsBlob;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/sablob.c
+ * PURPOSE:     Functions for the Saved Answer Blob Implementation
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PVOID
+WINAPI
+FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position,
+                                IN PSIZE_T FreeSize,
+                                IN SIZE_T Size)
+{
+    /* Just a little helper that we use */
+    return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID));
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_Create(IN ULONG Count)
+{
+    PDNS_BLOB Blob;
+    PDNS_ARRAY DnsAddrArray;
+
+    /* Allocate the blob */
+    Blob = Dns_AllocZero(sizeof(DNS_BLOB));
+    if (Blob)
+    {
+        /* Check if it'll hold any addresses */
+        if (Count)
+        {
+            /* Create the DNS Address Array */
+            DnsAddrArray = DnsAddrArray_Create(Count);
+            if (!DnsAddrArray)
+            {
+                /* Failure, free the blob */
+                SaBlob_Free(Blob);
+                SetLastError(ERROR_OUTOFMEMORY);
+            }
+            else
+            {
+                /* Link it with the blob */
+                Blob->DnsAddrArray = DnsAddrArray;
+            }
+        }
+    }
+
+    /* Return the blob */
+    return Blob;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(IN LPWSTR Name,
+                     IN ULONG Count,
+                     IN PIN_ADDR AddressArray)
+{
+    PDNS_BLOB Blob;
+    LPWSTR NameCopy;
+    ULONG i;
+
+    /* Create the blob */
+    Blob = SaBlob_Create(Count);
+    if (!Blob) goto Quickie;
+
+    /* If we have a name */
+    if (Name)
+    {
+        /* Create a copy of it */
+        NameCopy = Dns_CreateStringCopy_W(Name);
+        if (!NameCopy) goto Quickie;
+
+        /* Save the pointer to the name */
+        Blob->Name = NameCopy;
+    }
+
+    /* Loop all the addresses */
+    for (i = 0; i < Count; i++)
+    {
+        /* Add an entry for this address */
+        DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address);
+    }
+
+    /* Return the blob */
+    return Blob;
+
+Quickie:
+    /* Free the blob, set error and fail */
+    SaBlob_Free(Blob);
+    SetLastError(ERROR_OUTOFMEMORY);
+    return NULL;
+}
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob)
+{
+    /* Make sure we got a blob */
+    if (Blob)
+    {
+        /* Free the name */
+        Dns_Free(Blob->Name);
+
+        /* Loop the aliases */
+        while (Blob->AliasCount)
+        {
+            /* Free the alias */
+            Dns_Free(Blob->Aliases[Blob->AliasCount]);
+
+            /* Decrease number of aliases */
+            Blob->AliasCount--;
+        }
+
+        /* Free the DNS Address Array */
+        DnsAddrArray_Free(Blob->DnsAddrArray);
+
+        /* Free the blob itself */
+        Dns_Free(Blob);
+    }
+}
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition,
+                     IN OUT PSIZE_T FreeBufferSpace,
+                     IN OUT PSIZE_T HostEntrySize,
+                     IN PDNS_BLOB Blob,
+                     IN DWORD StringType,
+                     IN BOOLEAN Relative,
+                     IN BOOLEAN BufferAllocated)
+{
+    PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray;
+    ULONG AliasCount = Blob->AliasCount;
+    WORD AddressFamily = AF_UNSPEC;
+    ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize;
+    ULONG AliasPointerSize;
+    PDNS_FAMILY_INFO FamilyInfo = NULL;
+    ULONG StringLength = 0;
+    ULONG i;
+    ULONG HostentSize = 0;
+    PHOSTENT Hostent = NULL;
+    ULONG_PTR HostentPtr;
+    PVOID CurrentAddress;
+
+    /* Check if we actually have any addresses */
+    if (DnsAddrArray)
+    {
+        /* Get the address family */
+        AddressFamily = DnsAddrArray->Addresses[0].AddressFamily;
+
+        /* Get family information */
+        FamilyInfo = FamilyInfo_GetForFamily(AddressFamily);
+
+        /* Save the current address count and their size */
+        AddressCount = DnsAddrArray->UsedAddresses;
+        AddressSize = FamilyInfo->AddressSize;
+    }
+
+    /* Calculate total size for all the addresses, and their pointers */
+    TotalSize = AddressSize * AddressCount;
+    NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID);
+
+    /* Check if we have a name */
+    if (Blob->Name)
+    {
+        /* Find out the size we'll need for a copy */
+        StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name,
+                                                         0,
+                                                         UnicodeString,
+                                                         StringType) + 1) & ~1;
+    }
+
+    /*  Now do the same for the aliases */
+    for (i = AliasCount; i; i--)
+    {
+        /* Find out the size we'll need for a copy */
+        HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i],
+                                                         0,
+                                                         UnicodeString,
+                                                         StringType) + 1) & ~1;
+    }
+
+    /* Find out how much the pointers will take */
+    AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID);
+
+    /* Calculate Hostent Size */
+    HostentSize += TotalSize +
+                   NamePointerSize +
+                   AliasPointerSize +
+                   StringLength +
+                   sizeof(HOSTENT);
+
+    /* Check if we already have a buffer */
+    if (!BufferAllocated)
+    {
+        /* We don't, allocate space ourselves */
+        HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize);
+    }
+    else
+    {
+        /* We do, so allocate space in the buffer */
+        HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition,
+                                                                FreeBufferSpace,
+                                                                HostentSize);
+    }
+
+    /* Make sure we got space */
+    if (HostentPtr)
+    {
+        /* Initialize it */
+        Hostent = Hostent_Init((PVOID)&HostentPtr,
+                               AddressFamily,
+                               AddressSize,
+                               AddressCount,
+                               AliasCount);
+    }
+
+    /* Loop the addresses */
+    for (i = 0; i < AddressCount; i++)
+    {
+        /* Get the pointer of the current address */
+        CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] +
+                                             FamilyInfo->AddressOffset);
+
+        /* Write the pointer */
+        Hostent->h_addr_list[i] = (PCHAR)HostentPtr;
+
+        /* Copy the address */
+        RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize);
+
+        /* Advance the buffer */
+        HostentPtr += AddressSize;
+    }
+
+    /* Check if we have a name */
+    if (Blob->Name)
+    {
+        /* Align our current position */
+        HostentPtr += 1 & ~1;
+
+        /* Save our name here */
+        Hostent->h_name = (LPSTR)HostentPtr;
+
+        /* Now copy it in the blob */
+        HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
+                                     NULL,
+                                     Blob->Name,
+                                     0,
+                                     UnicodeString,
+                                     StringType);
+    }
+
+    /* Loop the Aliases */
+    for (i = AliasCount; i; i--)
+    {
+        /* Align our current position */
+        HostentPtr += 1 & ~1;
+
+        /* Save our alias here */
+        Hostent->h_aliases[i] = (LPSTR)HostentPtr;
+
+        /* Now copy it in the blob */
+        HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
+                                     NULL,
+                                     Blob->Aliases[i],
+                                     0,
+                                     UnicodeString,
+                                     StringType);
+    }
+
+    /* Check if the caller didn't have a buffer */
+    if (!BufferAllocated)
+    {
+        /* Return the size; not needed if we had a blob, since it's internal */
+        *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr;
+    }
+
+    /* Convert to Offsets if requested */
+    if(Relative) Hostent_ConvertToOffsets(Hostent);
+
+    /* Return the full, complete, hostent */
+    return Hostent;
+}
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob,
+                        IN LPWSTR String,
+                        IN BOOLEAN IsAlias)
+{
+    /* Check if this is an alias */
+    if (!IsAlias)
+    {
+        /* It's not. Simply create a copy of the string */
+        Blob->Name = Dns_CreateStringCopy_W(String);
+        if (!Blob->Name) return GetLastError();
+    }
+    else
+    {
+        /* Does it have a name, and less then 8 aliases? */
+        if ((Blob->Name) && (Blob->AliasCount <= 8))
+        {
+            /* Yup, create a copy of the string and increase the alias count */
+            Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String);
+            Blob->AliasCount++;
+        }
+        else
+        {
+            /* Invalid request! */
+            return ERROR_MORE_DATA;
+        }
+    }
+
+    /* Return Success */
+    return ERROR_SUCCESS;
+}
+
+INT
+WINAPI
+SaBlob_WriteAddress(IN PDNS_BLOB Blob,
+                    OUT PDNS_ADDRESS DnsAddr)
+{
+    /* Check if we have an array yet */
+    if (!Blob->DnsAddrArray)
+    {
+        /* Allocate one! */
+        Blob->DnsAddrArray = DnsAddrArray_Create(1);
+        if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY;
+    }
+
+    /* Add this address */
+    return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ?
+           ERROR_SUCCESS:
+           ERROR_MORE_DATA;
+}
+
+BOOLEAN
+WINAPI
+SaBlob_IsSupportedAddrType(WORD DnsType)
+{
+    /* Check for valid Types that we support */
+    return (DnsType == DNS_TYPE_A ||
+            DnsType == DNS_TYPE_ATMA ||
+            DnsType == DNS_TYPE_AAAA);
+}
+
+INT
+WINAPI
+SaBlob_WriteRecords(OUT PDNS_BLOB Blob,
+                    IN PDNS_RECORD DnsRecord,
+                    IN BOOLEAN DoAlias)
+{
+    DNS_ADDRESS DnsAddress;
+    INT ErrorCode = STATUS_INVALID_PARAMETER;
+    BOOLEAN WroteOnce = FALSE;
+
+    /* Zero out the Address */
+    RtlZeroMemory(&DnsAddress, sizeof(DnsAddress));
+
+    /* Loop through all the Records */
+    while (DnsRecord)
+    {
+        /* Is this not an answer? */
+        if (DnsRecord->Flags.S.Section != DNSREC_ANSWER)
+        {
+            /* Then simply move on to the next DNS Record */
+            DnsRecord = DnsRecord->pNext;
+            continue;
+        }
+
+        /* Check the type of thsi record */
+        switch(DnsRecord->wType)
+        {
+            /* Regular IPv4, v6 or ATM Record */
+            case DNS_TYPE_A:
+            case DNS_TYPE_AAAA:
+            case DNS_TYPE_ATMA:
+
+                /* Create a DNS Address from the record */
+                DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress);
+
+                /* Add it to the DNS Blob */
+                ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress);
+
+                /* Add the name, if needed */
+                if ((DoAlias) &&
+                    (!WroteOnce) &&
+                    (!Blob->Name) &&
+                    (DnsRecord->pName))
+                {
+                    /* Write the name from the DNS Record */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        FALSE);
+                    WroteOnce = TRUE;
+                }
+                break;
+
+            case DNS_TYPE_CNAME:
+
+                /* Just write the alias name */
+                ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                    DnsRecord->pName,
+                                                    TRUE);
+                break;
+
+            case DNS_TYPE_PTR:
+
+                /* Check if we already have a name */
+                if (Blob->Name)
+                {
+                    /* We don't, so add this as a name */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        FALSE);
+                }
+                else
+                {
+                    /* We do, so add it as an alias */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        TRUE);
+                }
+                break;
+            default:
+                break;
+        }
+
+        /* Next record */
+        DnsRecord = DnsRecord->pNext;
+    }
+
+    /* Return error code */
+    return ErrorCode;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord,
+                         IN BOOLEAN DoAliases,
+                         IN DWORD DnsType)
+{
+    PDNS_RECORD LocalDnsRecord;
+    ULONG ProcessedCount = 0;
+    PDNS_BLOB DnsBlob;
+    INT ErrorCode;
+    DNS_ADDRESS DnsAddress;
+
+    /* Find out how many DNS Addresses to allocate */
+    LocalDnsRecord = DnsRecord;
+    while (LocalDnsRecord)
+    {
+        /* Make sure this record is an answer */
+        if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) &&
+            (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType)))
+        {
+            /* Increase number of records to process */
+            ProcessedCount++;
+        }
+
+        /* Move to the next record */
+        LocalDnsRecord = LocalDnsRecord->pNext;
+    }
+
+    /* Create the DNS Blob */
+    DnsBlob = SaBlob_Create(ProcessedCount);
+    if (!DnsBlob)
+    {
+        /* Fail */
+        ErrorCode = GetLastError();
+        goto Quickie;
+    }
+
+    /* Write the record to the DNS Blob */
+    ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE);
+    if (ErrorCode != NO_ERROR)
+    {
+        /* We failed... but do we still have valid data? */
+        if ((DnsBlob->Name) || (DnsBlob->AliasCount))
+        {
+            /* We'll just assume success then */
+            ErrorCode = NO_ERROR;
+        }
+        else
+        {
+            /* Ok, last chance..do you have a DNS Address Array? */
+            if ((DnsBlob->DnsAddrArray) &&
+                (DnsBlob->DnsAddrArray->UsedAddresses))
+            {
+                /* Boy are you lucky! */
+                ErrorCode = NO_ERROR;
+            }
+        }
+
+        /* Buh-bye! */
+        goto Quickie;
+    }
+
+    /* Check if this is a PTR record */
+    if ((DnsRecord->wType == DNS_TYPE_PTR) ||
+        ((DnsType == DNS_TYPE_PTR) &&
+         (DnsRecord->wType == DNS_TYPE_CNAME) &&
+         (DnsRecord->Flags.S.Section == DNSREC_ANSWER)))
+    {
+        /* Get a DNS Address Structure */
+        if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName))
+        {
+            /* Add it to the Blob */
+            if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR;
+        }
+    }
+
+    /* Ok...do we still not have a name? */
+    if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord))
+    {
+        /* We have an local DNS Record, so just use it to write the name */
+        ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob,
+                                            LocalDnsRecord->pName,
+                                            FALSE);
+    }
+
+Quickie:
+    /* Check error code */
+    if (ErrorCode != NO_ERROR)
+    {
+        /* Free the blob and set the error */
+        SaBlob_Free(DnsBlob);
+        DnsBlob = NULL;
+        SetLastError(ErrorCode);
+    }
+
+    /* Return */
+    return DnsBlob;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(IN LPWSTR Name,
+             IN WORD DnsType,
+             IN ULONG Flags,
+             IN PVOID *Reserved,
+             IN DWORD AddressFamily)
+{
+    PDNS_RECORD DnsRecord = NULL;
+    INT ErrorCode;
+    PDNS_BLOB DnsBlob = NULL;
+    LPWSTR LocalName, LocalNameCopy;
+
+    /* If they want reserved data back, clear it out in case we fail */
+    if (Reserved) *Reserved = NULL;
+
+    /* Query DNS */
+    ErrorCode = DnsQuery_W(Name,
+                           DnsType,
+                           Flags,
+                           NULL,
+                           &DnsRecord,
+                           Reserved);
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* We failed... did the caller use reserved data? */
+        if (Reserved && *Reserved)
+        {
+            /* He did, and it was valid. Free it */
+            DnsApiFree(*Reserved);
+            *Reserved = NULL;
+        }
+
+        /* Normalize error code */
+        if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN;
+        goto Quickie;
+    }
+
+    /* Now create the Blob from the DNS Records */
+    DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType);
+    if (!DnsBlob)
+    {
+        /* Failed, get error code */
+        ErrorCode = GetLastError();
+        goto Quickie;
+    }
+
+    /* Make sure it has a name */
+    if (!DnsBlob->Name)
+    {
+        /* It doesn't, fail */
+        ErrorCode = DNS_INFO_NO_RECORDS;
+        goto Quickie;
+    }
+
+    /* Check if the name is local or loopback */
+    if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) &&
+        !(DnsNameCompare_W(DnsBlob->Name, L"loopback")))
+    {
+        /* Nothing left to do, exit! */
+        goto Quickie;
+    }
+
+    /* This is a local name...query it */
+    DnsQueryConfig(DnsConfigFullHostName_W,
+                   DNS_CONFIG_FLAG_ALLOC,
+                   NULL,
+                   NULL,
+                   &LocalName,
+                   0);
+    if (LocalName)
+    {
+        /* Create a copy for the caller */
+        LocalNameCopy = Dns_CreateStringCopy_W(LocalName);
+        if (LocalNameCopy)
+        {
+            /* Overwrite the one in the blob */
+            DnsBlob->Name = LocalNameCopy;
+        }
+        else
+        {
+            /* We failed to make a copy, free memory */
+            DnsApiFree(LocalName);
+        }
+    }
+
+Quickie:
+    /* Free the DNS Record if we have one */
+    if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList);
+
+    /* Check if this is a failure path with an active blob */
+    if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob))
+    {
+        /* Free the blob */
+        SaBlob_Free(DnsBlob);
+        DnsBlob = NULL;
+    }
+
+    /* Set the last error and return */
+    SetLastError(ErrorCode);
+    return DnsBlob;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/sablob.c
+ * PURPOSE:     Functions for the Saved Answer Blob Implementation
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PVOID
+WINAPI
+FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position,
+                                IN PSIZE_T FreeSize,
+                                IN SIZE_T Size)
+{
+    /* Just a little helper that we use */
+    return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID));
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_Create(IN ULONG Count)
+{
+    PDNS_BLOB Blob;
+    PDNS_ARRAY DnsAddrArray;
+
+    /* Allocate the blob */
+    Blob = Dns_AllocZero(sizeof(DNS_BLOB));
+    if (Blob)
+    {
+        /* Check if it'll hold any addresses */
+        if (Count)
+        {
+            /* Create the DNS Address Array */
+            DnsAddrArray = DnsAddrArray_Create(Count);
+            if (!DnsAddrArray)
+            {
+                /* Failure, free the blob */
+                SaBlob_Free(Blob);
+                SetLastError(ERROR_OUTOFMEMORY);
+            }
+            else
+            {
+                /* Link it with the blob */
+                Blob->DnsAddrArray = DnsAddrArray;
+            }
+        }
+    }
+
+    /* Return the blob */
+    return Blob;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(IN LPWSTR Name,
+                     IN ULONG Count,
+                     IN PIN_ADDR AddressArray)
+{
+    PDNS_BLOB Blob;
+    LPWSTR NameCopy;
+    ULONG i;
+
+    /* Create the blob */
+    Blob = SaBlob_Create(Count);
+    if (!Blob) goto Quickie;
+
+    /* If we have a name */
+    if (Name)
+    {
+        /* Create a copy of it */
+        NameCopy = Dns_CreateStringCopy_W(Name);
+        if (!NameCopy) goto Quickie;
+
+        /* Save the pointer to the name */
+        Blob->Name = NameCopy;
+    }
+
+    /* Loop all the addresses */
+    for (i = 0; i < Count; i++)
+    {
+        /* Add an entry for this address */
+        DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address);
+    }
+
+    /* Return the blob */
+    return Blob;
+
+Quickie:
+    /* Free the blob, set error and fail */
+    SaBlob_Free(Blob);
+    SetLastError(ERROR_OUTOFMEMORY);
+    return NULL;
+}
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob)
+{
+    /* Make sure we got a blob */
+    if (Blob)
+    {
+        /* Free the name */
+        Dns_Free(Blob->Name);
+
+        /* Loop the aliases */
+        while (Blob->AliasCount)
+        {
+            /* Free the alias */
+            Dns_Free(Blob->Aliases[Blob->AliasCount]);
+
+            /* Decrease number of aliases */
+            Blob->AliasCount--;
+        }
+
+        /* Free the DNS Address Array */
+        DnsAddrArray_Free(Blob->DnsAddrArray);
+
+        /* Free the blob itself */
+        Dns_Free(Blob);
+    }
+}
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition,
+                     IN OUT PSIZE_T FreeBufferSpace,
+                     IN OUT PSIZE_T HostEntrySize,
+                     IN PDNS_BLOB Blob,
+                     IN DWORD StringType,
+                     IN BOOLEAN Relative,
+                     IN BOOLEAN BufferAllocated)
+{
+    PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray;
+    ULONG AliasCount = Blob->AliasCount;
+    WORD AddressFamily = AF_UNSPEC;
+    ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize;
+    ULONG AliasPointerSize;
+    PDNS_FAMILY_INFO FamilyInfo = NULL;
+    ULONG StringLength = 0;
+    ULONG i;
+    ULONG HostentSize = 0;
+    PHOSTENT Hostent = NULL;
+    ULONG_PTR HostentPtr;
+    PVOID CurrentAddress;
+
+    /* Check if we actually have any addresses */
+    if (DnsAddrArray)
+    {
+        /* Get the address family */
+        AddressFamily = DnsAddrArray->Addresses[0].AddressFamily;
+
+        /* Get family information */
+        FamilyInfo = FamilyInfo_GetForFamily(AddressFamily);
+
+        /* Save the current address count and their size */
+        AddressCount = DnsAddrArray->UsedAddresses;
+        AddressSize = FamilyInfo->AddressSize;
+    }
+
+    /* Calculate total size for all the addresses, and their pointers */
+    TotalSize = AddressSize * AddressCount;
+    NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID);
+
+    /* Check if we have a name */
+    if (Blob->Name)
+    {
+        /* Find out the size we'll need for a copy */
+        StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name,
+                                                         0,
+                                                         UnicodeString,
+                                                         StringType) + 1) & ~1;
+    }
+
+    /*  Now do the same for the aliases */
+    for (i = AliasCount; i; i--)
+    {
+        /* Find out the size we'll need for a copy */
+        HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i],
+                                                         0,
+                                                         UnicodeString,
+                                                         StringType) + 1) & ~1;
+    }
+
+    /* Find out how much the pointers will take */
+    AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID);
+
+    /* Calculate Hostent Size */
+    HostentSize += TotalSize +
+                   NamePointerSize +
+                   AliasPointerSize +
+                   StringLength +
+                   sizeof(HOSTENT);
+
+    /* Check if we already have a buffer */
+    if (!BufferAllocated)
+    {
+        /* We don't, allocate space ourselves */
+        HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize);
+    }
+    else
+    {
+        /* We do, so allocate space in the buffer */
+        HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition,
+                                                                FreeBufferSpace,
+                                                                HostentSize);
+    }
+
+    /* Make sure we got space */
+    if (HostentPtr)
+    {
+        /* Initialize it */
+        Hostent = Hostent_Init((PVOID)&HostentPtr,
+                               AddressFamily,
+                               AddressSize,
+                               AddressCount,
+                               AliasCount);
+    }
+
+    /* Loop the addresses */
+    for (i = 0; i < AddressCount; i++)
+    {
+        /* Get the pointer of the current address */
+        CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] +
+                                             FamilyInfo->AddressOffset);
+
+        /* Write the pointer */
+        Hostent->h_addr_list[i] = (PCHAR)HostentPtr;
+
+        /* Copy the address */
+        RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize);
+
+        /* Advance the buffer */
+        HostentPtr += AddressSize;
+    }
+
+    /* Check if we have a name */
+    if (Blob->Name)
+    {
+        /* Align our current position */
+        HostentPtr += 1 & ~1;
+
+        /* Save our name here */
+        Hostent->h_name = (LPSTR)HostentPtr;
+
+        /* Now copy it in the blob */
+        HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
+                                     NULL,
+                                     Blob->Name,
+                                     0,
+                                     UnicodeString,
+                                     StringType);
+    }
+
+    /* Loop the Aliases */
+    for (i = AliasCount; i; i--)
+    {
+        /* Align our current position */
+        HostentPtr += 1 & ~1;
+
+        /* Save our alias here */
+        Hostent->h_aliases[i] = (LPSTR)HostentPtr;
+
+        /* Now copy it in the blob */
+        HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
+                                     NULL,
+                                     Blob->Aliases[i],
+                                     0,
+                                     UnicodeString,
+                                     StringType);
+    }
+
+    /* Check if the caller didn't have a buffer */
+    if (!BufferAllocated)
+    {
+        /* Return the size; not needed if we had a blob, since it's internal */
+        *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr;
+    }
+
+    /* Convert to Offsets if requested */
+    if(Relative) Hostent_ConvertToOffsets(Hostent);
+
+    /* Return the full, complete, hostent */
+    return Hostent;
+}
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob,
+                        IN LPWSTR String,
+                        IN BOOLEAN IsAlias)
+{
+    /* Check if this is an alias */
+    if (!IsAlias)
+    {
+        /* It's not. Simply create a copy of the string */
+        Blob->Name = Dns_CreateStringCopy_W(String);
+        if (!Blob->Name) return GetLastError();
+    }
+    else
+    {
+        /* Does it have a name, and less then 8 aliases? */
+        if ((Blob->Name) && (Blob->AliasCount <= 8))
+        {
+            /* Yup, create a copy of the string and increase the alias count */
+            Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String);
+            Blob->AliasCount++;
+        }
+        else
+        {
+            /* Invalid request! */
+            return ERROR_MORE_DATA;
+        }
+    }
+
+    /* Return Success */
+    return ERROR_SUCCESS;
+}
+
+INT
+WINAPI
+SaBlob_WriteAddress(IN PDNS_BLOB Blob,
+                    OUT PDNS_ADDRESS DnsAddr)
+{
+    /* Check if we have an array yet */
+    if (!Blob->DnsAddrArray)
+    {
+        /* Allocate one! */
+        Blob->DnsAddrArray = DnsAddrArray_Create(1);
+        if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY;
+    }
+
+    /* Add this address */
+    return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ?
+           ERROR_SUCCESS:
+           ERROR_MORE_DATA;
+}
+
+BOOLEAN
+WINAPI
+SaBlob_IsSupportedAddrType(WORD DnsType)
+{
+    /* Check for valid Types that we support */
+    return (DnsType == DNS_TYPE_A ||
+            DnsType == DNS_TYPE_ATMA ||
+            DnsType == DNS_TYPE_AAAA);
+}
+
+INT
+WINAPI
+SaBlob_WriteRecords(OUT PDNS_BLOB Blob,
+                    IN PDNS_RECORD DnsRecord,
+                    IN BOOLEAN DoAlias)
+{
+    DNS_ADDRESS DnsAddress;
+    INT ErrorCode = STATUS_INVALID_PARAMETER;
+    BOOLEAN WroteOnce = FALSE;
+
+    /* Zero out the Address */
+    RtlZeroMemory(&DnsAddress, sizeof(DnsAddress));
+
+    /* Loop through all the Records */
+    while (DnsRecord)
+    {
+        /* Is this not an answer? */
+        if (DnsRecord->Flags.S.Section != DNSREC_ANSWER)
+        {
+            /* Then simply move on to the next DNS Record */
+            DnsRecord = DnsRecord->pNext;
+            continue;
+        }
+
+        /* Check the type of thsi record */
+        switch(DnsRecord->wType)
+        {
+            /* Regular IPv4, v6 or ATM Record */
+            case DNS_TYPE_A:
+            case DNS_TYPE_AAAA:
+            case DNS_TYPE_ATMA:
+
+                /* Create a DNS Address from the record */
+                DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress);
+
+                /* Add it to the DNS Blob */
+                ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress);
+
+                /* Add the name, if needed */
+                if ((DoAlias) &&
+                    (!WroteOnce) &&
+                    (!Blob->Name) &&
+                    (DnsRecord->pName))
+                {
+                    /* Write the name from the DNS Record */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        FALSE);
+                    WroteOnce = TRUE;
+                }
+                break;
+
+            case DNS_TYPE_CNAME:
+
+                /* Just write the alias name */
+                ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                    DnsRecord->pName,
+                                                    TRUE);
+                break;
+
+            case DNS_TYPE_PTR:
+
+                /* Check if we already have a name */
+                if (Blob->Name)
+                {
+                    /* We don't, so add this as a name */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        FALSE);
+                }
+                else
+                {
+                    /* We do, so add it as an alias */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        TRUE);
+                }
+                break;
+            default:
+                break;
+        }
+
+        /* Next record */
+        DnsRecord = DnsRecord->pNext;
+    }
+
+    /* Return error code */
+    return ErrorCode;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord,
+                         IN BOOLEAN DoAliases,
+                         IN DWORD DnsType)
+{
+    PDNS_RECORD LocalDnsRecord;
+    ULONG ProcessedCount = 0;
+    PDNS_BLOB DnsBlob;
+    INT ErrorCode;
+    DNS_ADDRESS DnsAddress;
+
+    /* Find out how many DNS Addresses to allocate */
+    LocalDnsRecord = DnsRecord;
+    while (LocalDnsRecord)
+    {
+        /* Make sure this record is an answer */
+        if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) &&
+            (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType)))
+        {
+            /* Increase number of records to process */
+            ProcessedCount++;
+        }
+
+        /* Move to the next record */
+        LocalDnsRecord = LocalDnsRecord->pNext;
+    }
+
+    /* Create the DNS Blob */
+    DnsBlob = SaBlob_Create(ProcessedCount);
+    if (!DnsBlob)
+    {
+        /* Fail */
+        ErrorCode = GetLastError();
+        goto Quickie;
+    }
+
+    /* Write the record to the DNS Blob */
+    ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE);
+    if (ErrorCode != NO_ERROR)
+    {
+        /* We failed... but do we still have valid data? */
+        if ((DnsBlob->Name) || (DnsBlob->AliasCount))
+        {
+            /* We'll just assume success then */
+            ErrorCode = NO_ERROR;
+        }
+        else
+        {
+            /* Ok, last chance..do you have a DNS Address Array? */
+            if ((DnsBlob->DnsAddrArray) &&
+                (DnsBlob->DnsAddrArray->UsedAddresses))
+            {
+                /* Boy are you lucky! */
+                ErrorCode = NO_ERROR;
+            }
+        }
+
+        /* Buh-bye! */
+        goto Quickie;
+    }
+
+    /* Check if this is a PTR record */
+    if ((DnsRecord->wType == DNS_TYPE_PTR) ||
+        ((DnsType == DNS_TYPE_PTR) &&
+         (DnsRecord->wType == DNS_TYPE_CNAME) &&
+         (DnsRecord->Flags.S.Section == DNSREC_ANSWER)))
+    {
+        /* Get a DNS Address Structure */
+        if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName))
+        {
+            /* Add it to the Blob */
+            if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR;
+        }
+    }
+
+    /* Ok...do we still not have a name? */
+    if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord))
+    {
+        /* We have an local DNS Record, so just use it to write the name */
+        ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob,
+                                            LocalDnsRecord->pName,
+                                            FALSE);
+    }
+
+Quickie:
+    /* Check error code */
+    if (ErrorCode != NO_ERROR)
+    {
+        /* Free the blob and set the error */
+        SaBlob_Free(DnsBlob);
+        DnsBlob = NULL;
+        SetLastError(ErrorCode);
+    }
+
+    /* Return */
+    return DnsBlob;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(IN LPWSTR Name,
+             IN WORD DnsType,
+             IN ULONG Flags,
+             IN PVOID *Reserved,
+             IN DWORD AddressFamily)
+{
+    PDNS_RECORD DnsRecord = NULL;
+    INT ErrorCode;
+    PDNS_BLOB DnsBlob = NULL;
+    LPWSTR LocalName, LocalNameCopy;
+
+    /* If they want reserved data back, clear it out in case we fail */
+    if (Reserved) *Reserved = NULL;
+
+    /* Query DNS */
+    ErrorCode = DnsQuery_W(Name,
+                           DnsType,
+                           Flags,
+                           NULL,
+                           &DnsRecord,
+                           Reserved);
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* We failed... did the caller use reserved data? */
+        if (Reserved && *Reserved)
+        {
+            /* He did, and it was valid. Free it */
+            DnsApiFree(*Reserved);
+            *Reserved = NULL;
+        }
+
+        /* Normalize error code */
+        if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN;
+        goto Quickie;
+    }
+
+    /* Now create the Blob from the DNS Records */
+    DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType);
+    if (!DnsBlob)
+    {
+        /* Failed, get error code */
+        ErrorCode = GetLastError();
+        goto Quickie;
+    }
+
+    /* Make sure it has a name */
+    if (!DnsBlob->Name)
+    {
+        /* It doesn't, fail */
+        ErrorCode = DNS_INFO_NO_RECORDS;
+        goto Quickie;
+    }
+
+    /* Check if the name is local or loopback */
+    if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) &&
+        !(DnsNameCompare_W(DnsBlob->Name, L"loopback")))
+    {
+        /* Nothing left to do, exit! */
+        goto Quickie;
+    }
+
+    /* This is a local name...query it */
+    DnsQueryConfig(DnsConfigFullHostName_W,
+                   DNS_CONFIG_FLAG_ALLOC,
+                   NULL,
+                   NULL,
+                   &LocalName,
+                   0);
+    if (LocalName)
+    {
+        /* Create a copy for the caller */
+        LocalNameCopy = Dns_CreateStringCopy_W(LocalName);
+        if (LocalNameCopy)
+        {
+            /* Overwrite the one in the blob */
+            DnsBlob->Name = LocalNameCopy;
+        }
+        else
+        {
+            /* We failed to make a copy, free memory */
+            DnsApiFree(LocalName);
+        }
+    }
+
+Quickie:
+    /* Free the DNS Record if we have one */
+    if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList);
+
+    /* Check if this is a failure path with an active blob */
+    if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob))
+    {
+        /* Free the blob */
+        SaBlob_Free(DnsBlob);
+        DnsBlob = NULL;
+    }
+
+    /* Set the last error and return */
+    SetLastError(ErrorCode);
+    return DnsBlob;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/sablob.c
+ * PURPOSE:     Functions for the Saved Answer Blob Implementation
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+PVOID
+WINAPI
+FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position,
+                                IN PSIZE_T FreeSize,
+                                IN SIZE_T Size)
+{
+    /* Just a little helper that we use */
+    return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID));
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_Create(IN ULONG Count)
+{
+    PDNS_BLOB Blob;
+    PDNS_ARRAY DnsAddrArray;
+
+    /* Allocate the blob */
+    Blob = Dns_AllocZero(sizeof(DNS_BLOB));
+    if (Blob)
+    {
+        /* Check if it'll hold any addresses */
+        if (Count)
+        {
+            /* Create the DNS Address Array */
+            DnsAddrArray = DnsAddrArray_Create(Count);
+            if (!DnsAddrArray)
+            {
+                /* Failure, free the blob */
+                SaBlob_Free(Blob);
+                SetLastError(ERROR_OUTOFMEMORY);
+            }
+            else
+            {
+                /* Link it with the blob */
+                Blob->DnsAddrArray = DnsAddrArray;
+            }
+        }
+    }
+
+    /* Return the blob */
+    return Blob;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromIp4(IN LPWSTR Name,
+                     IN ULONG Count,
+                     IN PIN_ADDR AddressArray)
+{
+    PDNS_BLOB Blob;
+    LPWSTR NameCopy;
+    ULONG i;
+
+    /* Create the blob */
+    Blob = SaBlob_Create(Count);
+    if (!Blob) goto Quickie;
+
+    /* If we have a name */
+    if (Name)
+    {
+        /* Create a copy of it */
+        NameCopy = Dns_CreateStringCopy_W(Name);
+        if (!NameCopy) goto Quickie;
+
+        /* Save the pointer to the name */
+        Blob->Name = NameCopy;
+    }
+
+    /* Loop all the addresses */
+    for (i = 0; i < Count; i++)
+    {
+        /* Add an entry for this address */
+        DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address);
+    }
+
+    /* Return the blob */
+    return Blob;
+
+Quickie:
+    /* Free the blob, set error and fail */
+    SaBlob_Free(Blob);
+    SetLastError(ERROR_OUTOFMEMORY);
+    return NULL;
+}
+
+VOID
+WINAPI
+SaBlob_Free(IN PDNS_BLOB Blob)
+{
+    /* Make sure we got a blob */
+    if (Blob)
+    {
+        /* Free the name */
+        Dns_Free(Blob->Name);
+
+        /* Loop the aliases */
+        while (Blob->AliasCount)
+        {
+            /* Free the alias */
+            Dns_Free(Blob->Aliases[Blob->AliasCount]);
+
+            /* Decrease number of aliases */
+            Blob->AliasCount--;
+        }
+
+        /* Free the DNS Address Array */
+        DnsAddrArray_Free(Blob->DnsAddrArray);
+
+        /* Free the blob itself */
+        Dns_Free(Blob);
+    }
+}
+
+PHOSTENT
+WINAPI
+SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition,
+                     IN OUT PSIZE_T FreeBufferSpace,
+                     IN OUT PSIZE_T HostEntrySize,
+                     IN PDNS_BLOB Blob,
+                     IN DWORD StringType,
+                     IN BOOLEAN Relative,
+                     IN BOOLEAN BufferAllocated)
+{
+    PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray;
+    ULONG AliasCount = Blob->AliasCount;
+    WORD AddressFamily = AF_UNSPEC;
+    ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize;
+    ULONG AliasPointerSize;
+    PDNS_FAMILY_INFO FamilyInfo = NULL;
+    ULONG StringLength = 0;
+    ULONG i;
+    ULONG HostentSize = 0;
+    PHOSTENT Hostent = NULL;
+    ULONG_PTR HostentPtr;
+    PVOID CurrentAddress;
+
+    /* Check if we actually have any addresses */
+    if (DnsAddrArray)
+    {
+        /* Get the address family */
+        AddressFamily = DnsAddrArray->Addresses[0].AddressFamily;
+
+        /* Get family information */
+        FamilyInfo = FamilyInfo_GetForFamily(AddressFamily);
+
+        /* Save the current address count and their size */
+        AddressCount = DnsAddrArray->UsedAddresses;
+        AddressSize = FamilyInfo->AddressSize;
+    }
+
+    /* Calculate total size for all the addresses, and their pointers */
+    TotalSize = AddressSize * AddressCount;
+    NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID);
+
+    /* Check if we have a name */
+    if (Blob->Name)
+    {
+        /* Find out the size we'll need for a copy */
+        StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name,
+                                                         0,
+                                                         UnicodeString,
+                                                         StringType) + 1) & ~1;
+    }
+
+    /*  Now do the same for the aliases */
+    for (i = AliasCount; i; i--)
+    {
+        /* Find out the size we'll need for a copy */
+        HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i],
+                                                         0,
+                                                         UnicodeString,
+                                                         StringType) + 1) & ~1;
+    }
+
+    /* Find out how much the pointers will take */
+    AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID);
+
+    /* Calculate Hostent Size */
+    HostentSize += TotalSize +
+                   NamePointerSize +
+                   AliasPointerSize +
+                   StringLength +
+                   sizeof(HOSTENT);
+
+    /* Check if we already have a buffer */
+    if (!BufferAllocated)
+    {
+        /* We don't, allocate space ourselves */
+        HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize);
+    }
+    else
+    {
+        /* We do, so allocate space in the buffer */
+        HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition,
+                                                                FreeBufferSpace,
+                                                                HostentSize);
+    }
+
+    /* Make sure we got space */
+    if (HostentPtr)
+    {
+        /* Initialize it */
+        Hostent = Hostent_Init((PVOID)&HostentPtr,
+                               AddressFamily,
+                               AddressSize,
+                               AddressCount,
+                               AliasCount);
+    }
+
+    /* Loop the addresses */
+    for (i = 0; i < AddressCount; i++)
+    {
+        /* Get the pointer of the current address */
+        CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] +
+                                             FamilyInfo->AddressOffset);
+
+        /* Write the pointer */
+        Hostent->h_addr_list[i] = (PCHAR)HostentPtr;
+
+        /* Copy the address */
+        RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize);
+
+        /* Advance the buffer */
+        HostentPtr += AddressSize;
+    }
+
+    /* Check if we have a name */
+    if (Blob->Name)
+    {
+        /* Align our current position */
+        HostentPtr += 1 & ~1;
+
+        /* Save our name here */
+        Hostent->h_name = (LPSTR)HostentPtr;
+
+        /* Now copy it in the blob */
+        HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
+                                     NULL,
+                                     Blob->Name,
+                                     0,
+                                     UnicodeString,
+                                     StringType);
+    }
+
+    /* Loop the Aliases */
+    for (i = AliasCount; i; i--)
+    {
+        /* Align our current position */
+        HostentPtr += 1 & ~1;
+
+        /* Save our alias here */
+        Hostent->h_aliases[i] = (LPSTR)HostentPtr;
+
+        /* Now copy it in the blob */
+        HostentPtr += Dns_StringCopy((PVOID)HostentPtr,
+                                     NULL,
+                                     Blob->Aliases[i],
+                                     0,
+                                     UnicodeString,
+                                     StringType);
+    }
+
+    /* Check if the caller didn't have a buffer */
+    if (!BufferAllocated)
+    {
+        /* Return the size; not needed if we had a blob, since it's internal */
+        *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr;
+    }
+
+    /* Convert to Offsets if requested */
+    if(Relative) Hostent_ConvertToOffsets(Hostent);
+
+    /* Return the full, complete, hostent */
+    return Hostent;
+}
+
+INT
+WINAPI
+SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob,
+                        IN LPWSTR String,
+                        IN BOOLEAN IsAlias)
+{
+    /* Check if this is an alias */
+    if (!IsAlias)
+    {
+        /* It's not. Simply create a copy of the string */
+        Blob->Name = Dns_CreateStringCopy_W(String);
+        if (!Blob->Name) return GetLastError();
+    }
+    else
+    {
+        /* Does it have a name, and less then 8 aliases? */
+        if ((Blob->Name) && (Blob->AliasCount <= 8))
+        {
+            /* Yup, create a copy of the string and increase the alias count */
+            Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String);
+            Blob->AliasCount++;
+        }
+        else
+        {
+            /* Invalid request! */
+            return ERROR_MORE_DATA;
+        }
+    }
+
+    /* Return Success */
+    return ERROR_SUCCESS;
+}
+
+INT
+WINAPI
+SaBlob_WriteAddress(IN PDNS_BLOB Blob,
+                    OUT PDNS_ADDRESS DnsAddr)
+{
+    /* Check if we have an array yet */
+    if (!Blob->DnsAddrArray)
+    {
+        /* Allocate one! */
+        Blob->DnsAddrArray = DnsAddrArray_Create(1);
+        if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY;
+    }
+
+    /* Add this address */
+    return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ?
+           ERROR_SUCCESS:
+           ERROR_MORE_DATA;
+}
+
+BOOLEAN
+WINAPI
+SaBlob_IsSupportedAddrType(WORD DnsType)
+{
+    /* Check for valid Types that we support */
+    return (DnsType == DNS_TYPE_A ||
+            DnsType == DNS_TYPE_ATMA ||
+            DnsType == DNS_TYPE_AAAA);
+}
+
+INT
+WINAPI
+SaBlob_WriteRecords(OUT PDNS_BLOB Blob,
+                    IN PDNS_RECORD DnsRecord,
+                    IN BOOLEAN DoAlias)
+{
+    DNS_ADDRESS DnsAddress;
+    INT ErrorCode = STATUS_INVALID_PARAMETER;
+    BOOLEAN WroteOnce = FALSE;
+
+    /* Zero out the Address */
+    RtlZeroMemory(&DnsAddress, sizeof(DnsAddress));
+
+    /* Loop through all the Records */
+    while (DnsRecord)
+    {
+        /* Is this not an answer? */
+        if (DnsRecord->Flags.S.Section != DNSREC_ANSWER)
+        {
+            /* Then simply move on to the next DNS Record */
+            DnsRecord = DnsRecord->pNext;
+            continue;
+        }
+
+        /* Check the type of thsi record */
+        switch(DnsRecord->wType)
+        {
+            /* Regular IPv4, v6 or ATM Record */
+            case DNS_TYPE_A:
+            case DNS_TYPE_AAAA:
+            case DNS_TYPE_ATMA:
+
+                /* Create a DNS Address from the record */
+                DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress);
+
+                /* Add it to the DNS Blob */
+                ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress);
+
+                /* Add the name, if needed */
+                if ((DoAlias) &&
+                    (!WroteOnce) &&
+                    (!Blob->Name) &&
+                    (DnsRecord->pName))
+                {
+                    /* Write the name from the DNS Record */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        FALSE);
+                    WroteOnce = TRUE;
+                }
+                break;
+
+            case DNS_TYPE_CNAME:
+
+                /* Just write the alias name */
+                ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                    DnsRecord->pName,
+                                                    TRUE);
+                break;
+
+            case DNS_TYPE_PTR:
+
+                /* Check if we already have a name */
+                if (Blob->Name)
+                {
+                    /* We don't, so add this as a name */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        FALSE);
+                }
+                else
+                {
+                    /* We do, so add it as an alias */
+                    ErrorCode = SaBlob_WriteNameOrAlias(Blob,
+                                                        DnsRecord->pName,
+                                                        TRUE);
+                }
+                break;
+            default:
+                break;
+        }
+
+        /* Next record */
+        DnsRecord = DnsRecord->pNext;
+    }
+
+    /* Return error code */
+    return ErrorCode;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord,
+                         IN BOOLEAN DoAliases,
+                         IN DWORD DnsType)
+{
+    PDNS_RECORD LocalDnsRecord;
+    ULONG ProcessedCount = 0;
+    PDNS_BLOB DnsBlob;
+    INT ErrorCode;
+    DNS_ADDRESS DnsAddress;
+
+    /* Find out how many DNS Addresses to allocate */
+    LocalDnsRecord = DnsRecord;
+    while (LocalDnsRecord)
+    {
+        /* Make sure this record is an answer */
+        if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) &&
+            (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType)))
+        {
+            /* Increase number of records to process */
+            ProcessedCount++;
+        }
+
+        /* Move to the next record */
+        LocalDnsRecord = LocalDnsRecord->pNext;
+    }
+
+    /* Create the DNS Blob */
+    DnsBlob = SaBlob_Create(ProcessedCount);
+    if (!DnsBlob)
+    {
+        /* Fail */
+        ErrorCode = GetLastError();
+        goto Quickie;
+    }
+
+    /* Write the record to the DNS Blob */
+    ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE);
+    if (ErrorCode != NO_ERROR)
+    {
+        /* We failed... but do we still have valid data? */
+        if ((DnsBlob->Name) || (DnsBlob->AliasCount))
+        {
+            /* We'll just assume success then */
+            ErrorCode = NO_ERROR;
+        }
+        else
+        {
+            /* Ok, last chance..do you have a DNS Address Array? */
+            if ((DnsBlob->DnsAddrArray) &&
+                (DnsBlob->DnsAddrArray->UsedAddresses))
+            {
+                /* Boy are you lucky! */
+                ErrorCode = NO_ERROR;
+            }
+        }
+
+        /* Buh-bye! */
+        goto Quickie;
+    }
+
+    /* Check if this is a PTR record */
+    if ((DnsRecord->wType == DNS_TYPE_PTR) ||
+        ((DnsType == DNS_TYPE_PTR) &&
+         (DnsRecord->wType == DNS_TYPE_CNAME) &&
+         (DnsRecord->Flags.S.Section == DNSREC_ANSWER)))
+    {
+        /* Get a DNS Address Structure */
+        if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName))
+        {
+            /* Add it to the Blob */
+            if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR;
+        }
+    }
+
+    /* Ok...do we still not have a name? */
+    if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord))
+    {
+        /* We have an local DNS Record, so just use it to write the name */
+        ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob,
+                                            LocalDnsRecord->pName,
+                                            FALSE);
+    }
+
+Quickie:
+    /* Check error code */
+    if (ErrorCode != NO_ERROR)
+    {
+        /* Free the blob and set the error */
+        SaBlob_Free(DnsBlob);
+        DnsBlob = NULL;
+        SetLastError(ErrorCode);
+    }
+
+    /* Return */
+    return DnsBlob;
+}
+
+PDNS_BLOB
+WINAPI
+SaBlob_Query(IN LPWSTR Name,
+             IN WORD DnsType,
+             IN ULONG Flags,
+             IN PVOID *Reserved,
+             IN DWORD AddressFamily)
+{
+    PDNS_RECORD DnsRecord = NULL;
+    INT ErrorCode;
+    PDNS_BLOB DnsBlob = NULL;
+    LPWSTR LocalName, LocalNameCopy;
+
+    /* If they want reserved data back, clear it out in case we fail */
+    if (Reserved) *Reserved = NULL;
+
+    /* Query DNS */
+    ErrorCode = DnsQuery_W(Name,
+                           DnsType,
+                           Flags,
+                           NULL,
+                           &DnsRecord,
+                           Reserved);
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        /* We failed... did the caller use reserved data? */
+        if (Reserved && *Reserved)
+        {
+            /* He did, and it was valid. Free it */
+            DnsApiFree(*Reserved);
+            *Reserved = NULL;
+        }
+
+        /* Normalize error code */
+        if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN;
+        goto Quickie;
+    }
+
+    /* Now create the Blob from the DNS Records */
+    DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType);
+    if (!DnsBlob)
+    {
+        /* Failed, get error code */
+        ErrorCode = GetLastError();
+        goto Quickie;
+    }
+
+    /* Make sure it has a name */
+    if (!DnsBlob->Name)
+    {
+        /* It doesn't, fail */
+        ErrorCode = DNS_INFO_NO_RECORDS;
+        goto Quickie;
+    }
+
+    /* Check if the name is local or loopback */
+    if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) &&
+        !(DnsNameCompare_W(DnsBlob->Name, L"loopback")))
+    {
+        /* Nothing left to do, exit! */
+        goto Quickie;
+    }
+
+    /* This is a local name...query it */
+    DnsQueryConfig(DnsConfigFullHostName_W,
+                   DNS_CONFIG_FLAG_ALLOC,
+                   NULL,
+                   NULL,
+                   &LocalName,
+                   0);
+    if (LocalName)
+    {
+        /* Create a copy for the caller */
+        LocalNameCopy = Dns_CreateStringCopy_W(LocalName);
+        if (LocalNameCopy)
+        {
+            /* Overwrite the one in the blob */
+            DnsBlob->Name = LocalNameCopy;
+        }
+        else
+        {
+            /* We failed to make a copy, free memory */
+            DnsApiFree(LocalName);
+        }
+    }
+
+Quickie:
+    /* Free the DNS Record if we have one */
+    if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList);
+
+    /* Check if this is a failure path with an active blob */
+    if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob))
+    {
+        /* Free the blob */
+        SaBlob_Free(DnsBlob);
+        DnsBlob = NULL;
+    }
+
+    /* Set the last error and return */
+    SetLastError(ErrorCode);
+    return DnsBlob;
+}
+
diff --git a/dll/win32/mswsock/dns/straddr.c b/dll/win32/mswsock/dns/straddr.c
new file mode 100644 (file)
index 0000000..4bf80f5
--- /dev/null
@@ -0,0 +1,1848 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/straddr.c
+ * PURPOSE:     Functions for address<->string conversion.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name,
+                              IN IN6_ADDR Address)
+{
+    /* FIXME */
+    return NULL;
+}
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name,
+                              IN IN_ADDR Address)
+{
+    /* Simply append the ARPA string */
+    return Name + (wsprintfW(Name,
+                             L"%u.%u.%u.%u.in-addr.arpa.",
+                             Address.S_un.S_addr >> 24,
+                             Address.S_un.S_addr >> 10,
+                             Address.S_un.S_addr >> 8,
+                             Address.S_un.S_addr) * sizeof(WCHAR));
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address,
+                              IN LPSTR Name)
+{
+    /* FIXME */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address,
+                              IN LPSTR Name)
+{
+    /* FIXME */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address,
+                         IN LPSTR Name)
+{
+    PCHAR Terminator;
+    NTSTATUS Status;
+
+    /* Let RTL Do it for us */
+    Status = RtlIpv6StringToAddressA(Name, &Terminator, Address);
+    if (NT_SUCCESS(Status)) return TRUE;
+
+    /* We failed */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address,
+                         IN LPWSTR Name)
+{
+    PCHAR Terminator;
+    NTSTATUS Status;
+
+    /* Let RTL Do it for us */
+    Status = RtlIpv6StringToAddressW(Name, &Terminator, Address);
+    if (NT_SUCCESS(Status)) return TRUE;
+
+    /* We failed */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address,
+                         IN LPSTR Name)
+{
+    ULONG Addr;
+
+    /* Use inet_addr to convert it... */
+    Addr = inet_addr(Name);
+    if (Addr == -1)
+    {
+        /* Check if it's the wildcard (which is ok...) */
+        if (strcmp("255.255.255.255", Name)) return FALSE;
+    }
+
+    /* If we got here, then we suceeded... return the address */
+    Address->S_un.S_addr = Addr;
+    return TRUE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address,
+                         IN LPWSTR Name)
+{
+    CHAR AnsiName[16];
+    ULONG Size = sizeof(AnsiName);
+    INT ErrorCode;
+
+    /* Make a copy of the name in ANSI */
+    ErrorCode = Dns_StringCopy(&AnsiName,
+                               &Size,
+                               Name,
+                               0,
+                               UnicodeString,
+                               AnsiString);
+    if (ErrorCode)
+    {
+        /* Copy made sucesfully, now convert it */
+        ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName);
+    }
+
+    /* Return either 0 bytes copied (failure == false) or conversion status */
+    return ErrorCode;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address,
+                              IN LPWSTR Name)
+{
+    CHAR AnsiName[32];
+    ULONG Size = sizeof(AnsiName);
+    INT ErrorCode;
+
+    /* Make a copy of the name in ANSI */
+    ErrorCode = Dns_StringCopy(&AnsiName,
+                               &Size,
+                               Name,
+                               0,
+                               UnicodeString,
+                               AnsiString);
+    if (ErrorCode)
+    {
+        /* Copy made sucesfully, now convert it */
+        ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName);
+    }
+
+    /* Return either 0 bytes copied (failure == false) or conversion status */
+    return ErrorCode;
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToAddressEx(OUT PVOID Address,
+                      IN OUT PULONG AddressSize,
+                      IN PVOID AddressName,
+                      IN OUT PDWORD AddressFamily,
+                      IN BOOLEAN Unicode,
+                      IN BOOLEAN Reverse)
+{
+    DWORD Af = *AddressFamily;
+    ULONG AddrSize = *AddressSize;
+    IN6_ADDR Addr;
+    BOOLEAN Return;
+    INT ErrorCode;
+    CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
+    ULONG Size = sizeof(AnsiName);
+
+    /* First check if this is a reverse address string */
+    if (Reverse)
+    {
+        /* Convert it right now to ANSI as an optimization */
+        Dns_StringCopy(AnsiName,
+                       &Size,
+                       AddressName,
+                       0,
+                       UnicodeString,
+                       AnsiString);
+
+        /* Use the ANSI Name instead */
+        AddressName = AnsiName;
+    }
+
+    /* 
+     * If the caller doesn't know what the family is, we'll assume IPv4 and
+     * check if we failed or not. If the caller told us it's IPv4, then just
+     * do IPv4...
+     */
+    if ((Af == AF_UNSPEC) || (Af == AF_INET))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Save address family */
+            Af = AF_INET;
+
+            /* Check if the address size matches */
+            if (AddrSize < sizeof(IN_ADDR))
+            {
+                /* Invalid match, set error code */
+                ErrorCode = ERROR_MORE_DATA;
+            }
+            else
+            {
+                /* It matches, save the address! */
+                *(PIN_ADDR)Address = *(PIN_ADDR)&Addr;
+            }
+        }
+    }
+
+    /* If we are here, either AF_INET6 was specified or IPv4 failed */
+    if ((Af == AF_UNSPEC) || (Af == AF_INET6))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip6StringToAddress_W(&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip6StringToAddress_A(&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Save address family */
+            Af = AF_INET6;
+
+            /* Check if the address size matches */
+            if (AddrSize < sizeof(IN6_ADDR))
+            {
+                /* Invalid match, set error code */
+                ErrorCode = ERROR_MORE_DATA;
+            }
+            else
+            {
+                /* It matches, save the address! */
+                *(PIN6_ADDR)Address = Addr;
+            }
+        }
+    }
+    else if (Af != AF_INET)
+    {
+        /* You're like.. ATM or something? Get outta here! */
+        Af = AF_UNSPEC;
+        ErrorCode = WSA_INVALID_PARAMETER;
+    }
+
+    /* Set error if we had one */
+    if (ErrorCode) SetLastError(ErrorCode);
+
+    /* Return the address family and size */
+    *AddressFamily = Af;
+    *AddressSize = AddrSize;
+
+    /* Return success or failure */
+    return (ErrorCode == ERROR_SUCCESS);
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(OUT PVOID Address,
+                     IN OUT PULONG AddressSize,
+                     IN LPWSTR AddressName,
+                     IN OUT PDWORD AddressFamily)
+{
+    /* Call the common API */
+    return Dns_StringToAddressEx(Address,
+                                 AddressSize,
+                                 AddressName,
+                                 AddressFamily,
+                                 TRUE,
+                                 FALSE);
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr,
+                      IN PVOID AddressName,
+                      IN DWORD AddressFamily,
+                      IN BOOLEAN Unicode,
+                      IN BOOLEAN Reverse)
+{
+    IN6_ADDR Addr;
+    BOOLEAN Return;
+    INT ErrorCode = ERROR_SUCCESS;
+    CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
+    ULONG Size = sizeof(AnsiName);
+
+    /* First check if this is a reverse address string */
+    if ((Reverse) && (Unicode))
+    {
+        /* Convert it right now to ANSI as an optimization */
+        Dns_StringCopy(AnsiName,
+                       &Size,
+                       AddressName,
+                       0,
+                       UnicodeString,
+                       AnsiString);
+
+        /* Use the ANSI Name instead */
+        AddressName = AnsiName;
+    }
+
+    /* 
+     * If the caller doesn't know what the family is, we'll assume IPv4 and
+     * check if we failed or not. If the caller told us it's IPv4, then just
+     * do IPv4...
+     */
+    if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Build the IPv4 Address */
+            DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0);
+
+            /* So we don't go in the code below... */
+            AddressFamily = AF_INET;
+        }
+    }
+
+    /* If we are here, either AF_INET6 was specified or IPv4 failed */
+    if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
+            if (Return)
+            {
+                /* Build the IPv6 Address */
+                DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0);
+            }
+            else
+            {
+                goto Quickie;
+            }
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName,
+                                                         &DnsAddr->Ip6Address.sin6_addr,
+                                                         &DnsAddr->Ip6Address.sin6_scope_id,
+                                                         &DnsAddr->Ip6Address.sin6_port)))
+                    Return = TRUE;
+                else
+                    Return = FALSE;
+            }
+            else
+            {
+                /* Get the Address */
+                if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName,
+                                                         &DnsAddr->Ip6Address.sin6_addr,
+                                                         &DnsAddr->Ip6Address.sin6_scope_id,
+                                                         &DnsAddr->Ip6Address.sin6_port)))
+                   Return = TRUE;
+                else
+                   Return = FALSE;
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Finish setting up the structure */
+            DnsAddr->Ip6Address.sin6_family = AF_INET6;
+            DnsAddr->AddressLength = sizeof(SOCKADDR_IN6);
+        }
+    }
+    else if (AddressFamily != AF_INET)
+    {
+        /* You're like.. ATM or something? Get outta here! */
+        RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS));
+        SetLastError(WSA_INVALID_PARAMETER);
+    }
+
+Quickie:
+    /* Return success or failure */
+    return (ErrorCode == ERROR_SUCCESS);
+}
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr,
+                           IN LPWSTR Name)
+{
+    /* Call the common API */
+    return Dns_StringToDnsAddrEx(DnsAddr,
+                                 Name,
+                                 AF_UNSPEC,
+                                 TRUE,
+                                 TRUE);
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/straddr.c
+ * PURPOSE:     Functions for address<->string conversion.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name,
+                              IN IN6_ADDR Address)
+{
+    /* FIXME */
+    return NULL;
+}
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name,
+                              IN IN_ADDR Address)
+{
+    /* Simply append the ARPA string */
+    return Name + (wsprintfW(Name,
+                             L"%u.%u.%u.%u.in-addr.arpa.",
+                             Address.S_un.S_addr >> 24,
+                             Address.S_un.S_addr >> 10,
+                             Address.S_un.S_addr >> 8,
+                             Address.S_un.S_addr) * sizeof(WCHAR));
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address,
+                              IN LPSTR Name)
+{
+    /* FIXME */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address,
+                              IN LPSTR Name)
+{
+    /* FIXME */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address,
+                         IN LPSTR Name)
+{
+    PCHAR Terminator;
+    NTSTATUS Status;
+
+    /* Let RTL Do it for us */
+    Status = RtlIpv6StringToAddressA(Name, &Terminator, Address);
+    if (NT_SUCCESS(Status)) return TRUE;
+
+    /* We failed */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address,
+                         IN LPWSTR Name)
+{
+    PCHAR Terminator;
+    NTSTATUS Status;
+
+    /* Let RTL Do it for us */
+    Status = RtlIpv6StringToAddressW(Name, &Terminator, Address);
+    if (NT_SUCCESS(Status)) return TRUE;
+
+    /* We failed */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address,
+                         IN LPSTR Name)
+{
+    ULONG Addr;
+
+    /* Use inet_addr to convert it... */
+    Addr = inet_addr(Name);
+    if (Addr == -1)
+    {
+        /* Check if it's the wildcard (which is ok...) */
+        if (strcmp("255.255.255.255", Name)) return FALSE;
+    }
+
+    /* If we got here, then we suceeded... return the address */
+    Address->S_un.S_addr = Addr;
+    return TRUE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address,
+                         IN LPWSTR Name)
+{
+    CHAR AnsiName[16];
+    ULONG Size = sizeof(AnsiName);
+    INT ErrorCode;
+
+    /* Make a copy of the name in ANSI */
+    ErrorCode = Dns_StringCopy(&AnsiName,
+                               &Size,
+                               Name,
+                               0,
+                               UnicodeString,
+                               AnsiString);
+    if (ErrorCode)
+    {
+        /* Copy made sucesfully, now convert it */
+        ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName);
+    }
+
+    /* Return either 0 bytes copied (failure == false) or conversion status */
+    return ErrorCode;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address,
+                              IN LPWSTR Name)
+{
+    CHAR AnsiName[32];
+    ULONG Size = sizeof(AnsiName);
+    INT ErrorCode;
+
+    /* Make a copy of the name in ANSI */
+    ErrorCode = Dns_StringCopy(&AnsiName,
+                               &Size,
+                               Name,
+                               0,
+                               UnicodeString,
+                               AnsiString);
+    if (ErrorCode)
+    {
+        /* Copy made sucesfully, now convert it */
+        ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName);
+    }
+
+    /* Return either 0 bytes copied (failure == false) or conversion status */
+    return ErrorCode;
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToAddressEx(OUT PVOID Address,
+                      IN OUT PULONG AddressSize,
+                      IN PVOID AddressName,
+                      IN OUT PDWORD AddressFamily,
+                      IN BOOLEAN Unicode,
+                      IN BOOLEAN Reverse)
+{
+    DWORD Af = *AddressFamily;
+    ULONG AddrSize = *AddressSize;
+    IN6_ADDR Addr;
+    BOOLEAN Return;
+    INT ErrorCode;
+    CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
+    ULONG Size = sizeof(AnsiName);
+
+    /* First check if this is a reverse address string */
+    if (Reverse)
+    {
+        /* Convert it right now to ANSI as an optimization */
+        Dns_StringCopy(AnsiName,
+                       &Size,
+                       AddressName,
+                       0,
+                       UnicodeString,
+                       AnsiString);
+
+        /* Use the ANSI Name instead */
+        AddressName = AnsiName;
+    }
+
+    /* 
+     * If the caller doesn't know what the family is, we'll assume IPv4 and
+     * check if we failed or not. If the caller told us it's IPv4, then just
+     * do IPv4...
+     */
+    if ((Af == AF_UNSPEC) || (Af == AF_INET))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Save address family */
+            Af = AF_INET;
+
+            /* Check if the address size matches */
+            if (AddrSize < sizeof(IN_ADDR))
+            {
+                /* Invalid match, set error code */
+                ErrorCode = ERROR_MORE_DATA;
+            }
+            else
+            {
+                /* It matches, save the address! */
+                *(PIN_ADDR)Address = *(PIN_ADDR)&Addr;
+            }
+        }
+    }
+
+    /* If we are here, either AF_INET6 was specified or IPv4 failed */
+    if ((Af == AF_UNSPEC) || (Af == AF_INET6))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip6StringToAddress_W(&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip6StringToAddress_A(&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Save address family */
+            Af = AF_INET6;
+
+            /* Check if the address size matches */
+            if (AddrSize < sizeof(IN6_ADDR))
+            {
+                /* Invalid match, set error code */
+                ErrorCode = ERROR_MORE_DATA;
+            }
+            else
+            {
+                /* It matches, save the address! */
+                *(PIN6_ADDR)Address = Addr;
+            }
+        }
+    }
+    else if (Af != AF_INET)
+    {
+        /* You're like.. ATM or something? Get outta here! */
+        Af = AF_UNSPEC;
+        ErrorCode = WSA_INVALID_PARAMETER;
+    }
+
+    /* Set error if we had one */
+    if (ErrorCode) SetLastError(ErrorCode);
+
+    /* Return the address family and size */
+    *AddressFamily = Af;
+    *AddressSize = AddrSize;
+
+    /* Return success or failure */
+    return (ErrorCode == ERROR_SUCCESS);
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(OUT PVOID Address,
+                     IN OUT PULONG AddressSize,
+                     IN LPWSTR AddressName,
+                     IN OUT PDWORD AddressFamily)
+{
+    /* Call the common API */
+    return Dns_StringToAddressEx(Address,
+                                 AddressSize,
+                                 AddressName,
+                                 AddressFamily,
+                                 TRUE,
+                                 FALSE);
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr,
+                      IN PVOID AddressName,
+                      IN DWORD AddressFamily,
+                      IN BOOLEAN Unicode,
+                      IN BOOLEAN Reverse)
+{
+    IN6_ADDR Addr;
+    BOOLEAN Return;
+    INT ErrorCode = ERROR_SUCCESS;
+    CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
+    ULONG Size = sizeof(AnsiName);
+
+    /* First check if this is a reverse address string */
+    if ((Reverse) && (Unicode))
+    {
+        /* Convert it right now to ANSI as an optimization */
+        Dns_StringCopy(AnsiName,
+                       &Size,
+                       AddressName,
+                       0,
+                       UnicodeString,
+                       AnsiString);
+
+        /* Use the ANSI Name instead */
+        AddressName = AnsiName;
+    }
+
+    /* 
+     * If the caller doesn't know what the family is, we'll assume IPv4 and
+     * check if we failed or not. If the caller told us it's IPv4, then just
+     * do IPv4...
+     */
+    if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Build the IPv4 Address */
+            DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0);
+
+            /* So we don't go in the code below... */
+            AddressFamily = AF_INET;
+        }
+    }
+
+    /* If we are here, either AF_INET6 was specified or IPv4 failed */
+    if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
+            if (Return)
+            {
+                /* Build the IPv6 Address */
+                DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0);
+            }
+            else
+            {
+                goto Quickie;
+            }
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName,
+                                                         &DnsAddr->Ip6Address.sin6_addr,
+                                                         &DnsAddr->Ip6Address.sin6_scope_id,
+                                                         &DnsAddr->Ip6Address.sin6_port)))
+                    Return = TRUE;
+                else
+                    Return = FALSE;
+            }
+            else
+            {
+                /* Get the Address */
+                if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName,
+                                                         &DnsAddr->Ip6Address.sin6_addr,
+                                                         &DnsAddr->Ip6Address.sin6_scope_id,
+                                                         &DnsAddr->Ip6Address.sin6_port)))
+                   Return = TRUE;
+                else
+                   Return = FALSE;
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Finish setting up the structure */
+            DnsAddr->Ip6Address.sin6_family = AF_INET6;
+            DnsAddr->AddressLength = sizeof(SOCKADDR_IN6);
+        }
+    }
+    else if (AddressFamily != AF_INET)
+    {
+        /* You're like.. ATM or something? Get outta here! */
+        RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS));
+        SetLastError(WSA_INVALID_PARAMETER);
+    }
+
+Quickie:
+    /* Return success or failure */
+    return (ErrorCode == ERROR_SUCCESS);
+}
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr,
+                           IN LPWSTR Name)
+{
+    /* Call the common API */
+    return Dns_StringToDnsAddrEx(DnsAddr,
+                                 Name,
+                                 AF_UNSPEC,
+                                 TRUE,
+                                 TRUE);
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/straddr.c
+ * PURPOSE:     Functions for address<->string conversion.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name,
+                              IN IN6_ADDR Address)
+{
+    /* FIXME */
+    return NULL;
+}
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name,
+                              IN IN_ADDR Address)
+{
+    /* Simply append the ARPA string */
+    return Name + (wsprintfW(Name,
+                             L"%u.%u.%u.%u.in-addr.arpa.",
+                             Address.S_un.S_addr >> 24,
+                             Address.S_un.S_addr >> 10,
+                             Address.S_un.S_addr >> 8,
+                             Address.S_un.S_addr) * sizeof(WCHAR));
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address,
+                              IN LPSTR Name)
+{
+    /* FIXME */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address,
+                              IN LPSTR Name)
+{
+    /* FIXME */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address,
+                         IN LPSTR Name)
+{
+    PCHAR Terminator;
+    NTSTATUS Status;
+
+    /* Let RTL Do it for us */
+    Status = RtlIpv6StringToAddressA(Name, &Terminator, Address);
+    if (NT_SUCCESS(Status)) return TRUE;
+
+    /* We failed */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address,
+                         IN LPWSTR Name)
+{
+    PCHAR Terminator;
+    NTSTATUS Status;
+
+    /* Let RTL Do it for us */
+    Status = RtlIpv6StringToAddressW(Name, &Terminator, Address);
+    if (NT_SUCCESS(Status)) return TRUE;
+
+    /* We failed */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address,
+                         IN LPSTR Name)
+{
+    ULONG Addr;
+
+    /* Use inet_addr to convert it... */
+    Addr = inet_addr(Name);
+    if (Addr == -1)
+    {
+        /* Check if it's the wildcard (which is ok...) */
+        if (strcmp("255.255.255.255", Name)) return FALSE;
+    }
+
+    /* If we got here, then we suceeded... return the address */
+    Address->S_un.S_addr = Addr;
+    return TRUE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address,
+                         IN LPWSTR Name)
+{
+    CHAR AnsiName[16];
+    ULONG Size = sizeof(AnsiName);
+    INT ErrorCode;
+
+    /* Make a copy of the name in ANSI */
+    ErrorCode = Dns_StringCopy(&AnsiName,
+                               &Size,
+                               Name,
+                               0,
+                               UnicodeString,
+                               AnsiString);
+    if (ErrorCode)
+    {
+        /* Copy made sucesfully, now convert it */
+        ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName);
+    }
+
+    /* Return either 0 bytes copied (failure == false) or conversion status */
+    return ErrorCode;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address,
+                              IN LPWSTR Name)
+{
+    CHAR AnsiName[32];
+    ULONG Size = sizeof(AnsiName);
+    INT ErrorCode;
+
+    /* Make a copy of the name in ANSI */
+    ErrorCode = Dns_StringCopy(&AnsiName,
+                               &Size,
+                               Name,
+                               0,
+                               UnicodeString,
+                               AnsiString);
+    if (ErrorCode)
+    {
+        /* Copy made sucesfully, now convert it */
+        ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName);
+    }
+
+    /* Return either 0 bytes copied (failure == false) or conversion status */
+    return ErrorCode;
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToAddressEx(OUT PVOID Address,
+                      IN OUT PULONG AddressSize,
+                      IN PVOID AddressName,
+                      IN OUT PDWORD AddressFamily,
+                      IN BOOLEAN Unicode,
+                      IN BOOLEAN Reverse)
+{
+    DWORD Af = *AddressFamily;
+    ULONG AddrSize = *AddressSize;
+    IN6_ADDR Addr;
+    BOOLEAN Return;
+    INT ErrorCode;
+    CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
+    ULONG Size = sizeof(AnsiName);
+
+    /* First check if this is a reverse address string */
+    if (Reverse)
+    {
+        /* Convert it right now to ANSI as an optimization */
+        Dns_StringCopy(AnsiName,
+                       &Size,
+                       AddressName,
+                       0,
+                       UnicodeString,
+                       AnsiString);
+
+        /* Use the ANSI Name instead */
+        AddressName = AnsiName;
+    }
+
+    /* 
+     * If the caller doesn't know what the family is, we'll assume IPv4 and
+     * check if we failed or not. If the caller told us it's IPv4, then just
+     * do IPv4...
+     */
+    if ((Af == AF_UNSPEC) || (Af == AF_INET))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Save address family */
+            Af = AF_INET;
+
+            /* Check if the address size matches */
+            if (AddrSize < sizeof(IN_ADDR))
+            {
+                /* Invalid match, set error code */
+                ErrorCode = ERROR_MORE_DATA;
+            }
+            else
+            {
+                /* It matches, save the address! */
+                *(PIN_ADDR)Address = *(PIN_ADDR)&Addr;
+            }
+        }
+    }
+
+    /* If we are here, either AF_INET6 was specified or IPv4 failed */
+    if ((Af == AF_UNSPEC) || (Af == AF_INET6))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip6StringToAddress_W(&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip6StringToAddress_A(&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Save address family */
+            Af = AF_INET6;
+
+            /* Check if the address size matches */
+            if (AddrSize < sizeof(IN6_ADDR))
+            {
+                /* Invalid match, set error code */
+                ErrorCode = ERROR_MORE_DATA;
+            }
+            else
+            {
+                /* It matches, save the address! */
+                *(PIN6_ADDR)Address = Addr;
+            }
+        }
+    }
+    else if (Af != AF_INET)
+    {
+        /* You're like.. ATM or something? Get outta here! */
+        Af = AF_UNSPEC;
+        ErrorCode = WSA_INVALID_PARAMETER;
+    }
+
+    /* Set error if we had one */
+    if (ErrorCode) SetLastError(ErrorCode);
+
+    /* Return the address family and size */
+    *AddressFamily = Af;
+    *AddressSize = AddrSize;
+
+    /* Return success or failure */
+    return (ErrorCode == ERROR_SUCCESS);
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(OUT PVOID Address,
+                     IN OUT PULONG AddressSize,
+                     IN LPWSTR AddressName,
+                     IN OUT PDWORD AddressFamily)
+{
+    /* Call the common API */
+    return Dns_StringToAddressEx(Address,
+                                 AddressSize,
+                                 AddressName,
+                                 AddressFamily,
+                                 TRUE,
+                                 FALSE);
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr,
+                      IN PVOID AddressName,
+                      IN DWORD AddressFamily,
+                      IN BOOLEAN Unicode,
+                      IN BOOLEAN Reverse)
+{
+    IN6_ADDR Addr;
+    BOOLEAN Return;
+    INT ErrorCode = ERROR_SUCCESS;
+    CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
+    ULONG Size = sizeof(AnsiName);
+
+    /* First check if this is a reverse address string */
+    if ((Reverse) && (Unicode))
+    {
+        /* Convert it right now to ANSI as an optimization */
+        Dns_StringCopy(AnsiName,
+                       &Size,
+                       AddressName,
+                       0,
+                       UnicodeString,
+                       AnsiString);
+
+        /* Use the ANSI Name instead */
+        AddressName = AnsiName;
+    }
+
+    /* 
+     * If the caller doesn't know what the family is, we'll assume IPv4 and
+     * check if we failed or not. If the caller told us it's IPv4, then just
+     * do IPv4...
+     */
+    if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Build the IPv4 Address */
+            DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0);
+
+            /* So we don't go in the code below... */
+            AddressFamily = AF_INET;
+        }
+    }
+
+    /* If we are here, either AF_INET6 was specified or IPv4 failed */
+    if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
+            if (Return)
+            {
+                /* Build the IPv6 Address */
+                DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0);
+            }
+            else
+            {
+                goto Quickie;
+            }
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName,
+                                                         &DnsAddr->Ip6Address.sin6_addr,
+                                                         &DnsAddr->Ip6Address.sin6_scope_id,
+                                                         &DnsAddr->Ip6Address.sin6_port)))
+                    Return = TRUE;
+                else
+                    Return = FALSE;
+            }
+            else
+            {
+                /* Get the Address */
+                if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName,
+                                                         &DnsAddr->Ip6Address.sin6_addr,
+                                                         &DnsAddr->Ip6Address.sin6_scope_id,
+                                                         &DnsAddr->Ip6Address.sin6_port)))
+                   Return = TRUE;
+                else
+                   Return = FALSE;
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Finish setting up the structure */
+            DnsAddr->Ip6Address.sin6_family = AF_INET6;
+            DnsAddr->AddressLength = sizeof(SOCKADDR_IN6);
+        }
+    }
+    else if (AddressFamily != AF_INET)
+    {
+        /* You're like.. ATM or something? Get outta here! */
+        RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS));
+        SetLastError(WSA_INVALID_PARAMETER);
+    }
+
+Quickie:
+    /* Return success or failure */
+    return (ErrorCode == ERROR_SUCCESS);
+}
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr,
+                           IN LPWSTR Name)
+{
+    /* Call the common API */
+    return Dns_StringToDnsAddrEx(DnsAddr,
+                                 Name,
+                                 AF_UNSPEC,
+                                 TRUE,
+                                 TRUE);
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/straddr.c
+ * PURPOSE:     Functions for address<->string conversion.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+LPWSTR
+WINAPI
+Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name,
+                              IN IN6_ADDR Address)
+{
+    /* FIXME */
+    return NULL;
+}
+
+LPWSTR
+WINAPI
+Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name,
+                              IN IN_ADDR Address)
+{
+    /* Simply append the ARPA string */
+    return Name + (wsprintfW(Name,
+                             L"%u.%u.%u.%u.in-addr.arpa.",
+                             Address.S_un.S_addr >> 24,
+                             Address.S_un.S_addr >> 10,
+                             Address.S_un.S_addr >> 8,
+                             Address.S_un.S_addr) * sizeof(WCHAR));
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address,
+                              IN LPSTR Name)
+{
+    /* FIXME */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address,
+                              IN LPSTR Name)
+{
+    /* FIXME */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address,
+                         IN LPSTR Name)
+{
+    PCHAR Terminator;
+    NTSTATUS Status;
+
+    /* Let RTL Do it for us */
+    Status = RtlIpv6StringToAddressA(Name, &Terminator, Address);
+    if (NT_SUCCESS(Status)) return TRUE;
+
+    /* We failed */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address,
+                         IN LPWSTR Name)
+{
+    PCHAR Terminator;
+    NTSTATUS Status;
+
+    /* Let RTL Do it for us */
+    Status = RtlIpv6StringToAddressW(Name, &Terminator, Address);
+    if (NT_SUCCESS(Status)) return TRUE;
+
+    /* We failed */
+    return FALSE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address,
+                         IN LPSTR Name)
+{
+    ULONG Addr;
+
+    /* Use inet_addr to convert it... */
+    Addr = inet_addr(Name);
+    if (Addr == -1)
+    {
+        /* Check if it's the wildcard (which is ok...) */
+        if (strcmp("255.255.255.255", Name)) return FALSE;
+    }
+
+    /* If we got here, then we suceeded... return the address */
+    Address->S_un.S_addr = Addr;
+    return TRUE;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address,
+                         IN LPWSTR Name)
+{
+    CHAR AnsiName[16];
+    ULONG Size = sizeof(AnsiName);
+    INT ErrorCode;
+
+    /* Make a copy of the name in ANSI */
+    ErrorCode = Dns_StringCopy(&AnsiName,
+                               &Size,
+                               Name,
+                               0,
+                               UnicodeString,
+                               AnsiString);
+    if (ErrorCode)
+    {
+        /* Copy made sucesfully, now convert it */
+        ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName);
+    }
+
+    /* Return either 0 bytes copied (failure == false) or conversion status */
+    return ErrorCode;
+}
+
+BOOLEAN
+WINAPI
+Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address,
+                              IN LPWSTR Name)
+{
+    CHAR AnsiName[32];
+    ULONG Size = sizeof(AnsiName);
+    INT ErrorCode;
+
+    /* Make a copy of the name in ANSI */
+    ErrorCode = Dns_StringCopy(&AnsiName,
+                               &Size,
+                               Name,
+                               0,
+                               UnicodeString,
+                               AnsiString);
+    if (ErrorCode)
+    {
+        /* Copy made sucesfully, now convert it */
+        ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName);
+    }
+
+    /* Return either 0 bytes copied (failure == false) or conversion status */
+    return ErrorCode;
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToAddressEx(OUT PVOID Address,
+                      IN OUT PULONG AddressSize,
+                      IN PVOID AddressName,
+                      IN OUT PDWORD AddressFamily,
+                      IN BOOLEAN Unicode,
+                      IN BOOLEAN Reverse)
+{
+    DWORD Af = *AddressFamily;
+    ULONG AddrSize = *AddressSize;
+    IN6_ADDR Addr;
+    BOOLEAN Return;
+    INT ErrorCode;
+    CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
+    ULONG Size = sizeof(AnsiName);
+
+    /* First check if this is a reverse address string */
+    if (Reverse)
+    {
+        /* Convert it right now to ANSI as an optimization */
+        Dns_StringCopy(AnsiName,
+                       &Size,
+                       AddressName,
+                       0,
+                       UnicodeString,
+                       AnsiString);
+
+        /* Use the ANSI Name instead */
+        AddressName = AnsiName;
+    }
+
+    /* 
+     * If the caller doesn't know what the family is, we'll assume IPv4 and
+     * check if we failed or not. If the caller told us it's IPv4, then just
+     * do IPv4...
+     */
+    if ((Af == AF_UNSPEC) || (Af == AF_INET))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Save address family */
+            Af = AF_INET;
+
+            /* Check if the address size matches */
+            if (AddrSize < sizeof(IN_ADDR))
+            {
+                /* Invalid match, set error code */
+                ErrorCode = ERROR_MORE_DATA;
+            }
+            else
+            {
+                /* It matches, save the address! */
+                *(PIN_ADDR)Address = *(PIN_ADDR)&Addr;
+            }
+        }
+    }
+
+    /* If we are here, either AF_INET6 was specified or IPv4 failed */
+    if ((Af == AF_UNSPEC) || (Af == AF_INET6))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip6StringToAddress_W(&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip6StringToAddress_A(&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Save address family */
+            Af = AF_INET6;
+
+            /* Check if the address size matches */
+            if (AddrSize < sizeof(IN6_ADDR))
+            {
+                /* Invalid match, set error code */
+                ErrorCode = ERROR_MORE_DATA;
+            }
+            else
+            {
+                /* It matches, save the address! */
+                *(PIN6_ADDR)Address = Addr;
+            }
+        }
+    }
+    else if (Af != AF_INET)
+    {
+        /* You're like.. ATM or something? Get outta here! */
+        Af = AF_UNSPEC;
+        ErrorCode = WSA_INVALID_PARAMETER;
+    }
+
+    /* Set error if we had one */
+    if (ErrorCode) SetLastError(ErrorCode);
+
+    /* Return the address family and size */
+    *AddressFamily = Af;
+    *AddressSize = AddrSize;
+
+    /* Return success or failure */
+    return (ErrorCode == ERROR_SUCCESS);
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToAddressW(OUT PVOID Address,
+                     IN OUT PULONG AddressSize,
+                     IN LPWSTR AddressName,
+                     IN OUT PDWORD AddressFamily)
+{
+    /* Call the common API */
+    return Dns_StringToAddressEx(Address,
+                                 AddressSize,
+                                 AddressName,
+                                 AddressFamily,
+                                 TRUE,
+                                 FALSE);
+}
+
+BOOLEAN
+WINAPI
+Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr,
+                      IN PVOID AddressName,
+                      IN DWORD AddressFamily,
+                      IN BOOLEAN Unicode,
+                      IN BOOLEAN Reverse)
+{
+    IN6_ADDR Addr;
+    BOOLEAN Return;
+    INT ErrorCode = ERROR_SUCCESS;
+    CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")];
+    ULONG Size = sizeof(AnsiName);
+
+    /* First check if this is a reverse address string */
+    if ((Reverse) && (Unicode))
+    {
+        /* Convert it right now to ANSI as an optimization */
+        Dns_StringCopy(AnsiName,
+                       &Size,
+                       AddressName,
+                       0,
+                       UnicodeString,
+                       AnsiString);
+
+        /* Use the ANSI Name instead */
+        AddressName = AnsiName;
+    }
+
+    /* 
+     * If the caller doesn't know what the family is, we'll assume IPv4 and
+     * check if we failed or not. If the caller told us it's IPv4, then just
+     * do IPv4...
+     */
+    if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName);
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName);
+            }
+            else
+            {
+                /* Get the Address */
+                Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName);
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Build the IPv4 Address */
+            DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0);
+
+            /* So we don't go in the code below... */
+            AddressFamily = AF_INET;
+        }
+    }
+
+    /* If we are here, either AF_INET6 was specified or IPv4 failed */
+    if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6))
+    {
+        /* Now check if the caller gave us the reverse name or not */
+        if (Reverse)
+        {
+            /* Get the Address */
+            Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName);
+            if (Return)
+            {
+                /* Build the IPv6 Address */
+                DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0);
+            }
+            else
+            {
+                goto Quickie;
+            }
+        }
+        else
+        {
+            /* Check if the caller gave us unicode or not */
+            if (Unicode)
+            {
+                /* Get the Address */
+                if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName,
+                                                         &DnsAddr->Ip6Address.sin6_addr,
+                                                         &DnsAddr->Ip6Address.sin6_scope_id,
+                                                         &DnsAddr->Ip6Address.sin6_port)))
+                    Return = TRUE;
+                else
+                    Return = FALSE;
+            }
+            else
+            {
+                /* Get the Address */
+                if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName,
+                                                         &DnsAddr->Ip6Address.sin6_addr,
+                                                         &DnsAddr->Ip6Address.sin6_scope_id,
+                                                         &DnsAddr->Ip6Address.sin6_port)))
+                   Return = TRUE;
+                else
+                   Return = FALSE;
+            }
+        }
+
+        /* Check if we suceeded */
+        if (Return)
+        {
+            /* Finish setting up the structure */
+            DnsAddr->Ip6Address.sin6_family = AF_INET6;
+            DnsAddr->AddressLength = sizeof(SOCKADDR_IN6);
+        }
+    }
+    else if (AddressFamily != AF_INET)
+    {
+        /* You're like.. ATM or something? Get outta here! */
+        RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS));
+        SetLastError(WSA_INVALID_PARAMETER);
+    }
+
+Quickie:
+    /* Return success or failure */
+    return (ErrorCode == ERROR_SUCCESS);
+}
+
+BOOLEAN
+WINAPI
+Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr,
+                           IN LPWSTR Name)
+{
+    /* Call the common API */
+    return Dns_StringToDnsAddrEx(DnsAddr,
+                                 Name,
+                                 AF_UNSPEC,
+                                 TRUE,
+                                 TRUE);
+}
+
diff --git a/dll/win32/mswsock/dns/string.c b/dll/win32/mswsock/dns/string.c
new file mode 100644 (file)
index 0000000..d15e4e0
--- /dev/null
@@ -0,0 +1,1028 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/string.c
+ * PURPOSE:     functions for string manipulation and conversion.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+ULONG
+WINAPI
+Dns_StringCopy(OUT PVOID Destination,
+               IN OUT PULONG DestinationSize,
+               IN PVOID String,
+               IN ULONG StringSize OPTIONAL,
+               IN DWORD InputType,
+               IN DWORD OutputType)
+{
+    ULONG DestSize;
+    ULONG OutputSize = 0;
+
+    /* Check if the caller already gave us the string size */
+    if (!StringSize)
+    {
+        /* He didn't, get the input type */
+        if (InputType == UnicodeString)
+        {
+            /* Unicode string, calculate the size */
+            StringSize = (ULONG)wcslen((LPWSTR)String);
+        }
+        else
+        {
+            /* ANSI or UTF-8 sting, get the size */
+            StringSize = (ULONG)strlen((LPSTR)String);
+        }
+    }
+
+    /* Check if we have a limit on the desination size */
+    if (DestinationSize)
+    {
+        /* Make sure that we can respect it */
+        DestSize = Dns_GetBufferLengthForStringCopy(String,
+                                                    StringSize,
+                                                    InputType,
+                                                    OutputType);
+        if (*DestinationSize < DestSize)
+        {
+            /* Fail due to missing buffer space */
+            SetLastError(ERROR_MORE_DATA);
+
+            /* Return how much data we actually need */
+            *DestinationSize = DestSize;
+            return 0;
+        }
+        else if (!DestSize)
+        {
+            /* Fail due to invalid data */
+            SetLastError(ERROR_INVALID_DATA);
+            return 0;
+        }
+
+        /* Return how much data we actually need */
+        *DestinationSize = DestSize;
+    }
+
+    /* Now check if this is a Unicode String as input */
+    if (InputType == UnicodeString)
+    {
+        /* Check if the output is ANSI */
+        if (OutputType == AnsiString)
+        {
+            /* Convert and return the final desination size */
+            OutputSize = WideCharToMultiByte(CP_ACP,
+                                             0,
+                                             String,
+                                             StringSize,
+                                             Destination,
+                                             -1,
+                                             NULL,
+                                             NULL) + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Copy the string */
+            StringSize = StringSize * sizeof(WCHAR);
+            RtlMoveMemory(Destination, String, StringSize);
+
+            /* Return output length */
+            OutputSize = StringSize + 2;
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == AnsiString)
+    {
+        /* It's ANSI, is the output ansi too? */
+        if (OutputType == AnsiString)
+        {
+            /* Copy the string */
+            RtlMoveMemory(Destination, String, StringSize);
+
+            /* Return output length */
+            OutputSize = StringSize + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Convert to Unicode and return size */
+            OutputSize = MultiByteToWideChar(CP_ACP,
+                                             0,
+                                             String,
+                                             StringSize,
+                                             Destination,
+                                             -1) * sizeof(WCHAR) + 2;
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == Utf8String)
+    {
+        /* FIXME */
+        OutputSize = 0;
+    }
+
+    /* Return the output size */
+    return OutputSize;
+}
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name)
+{
+    SIZE_T StringLength;
+    LPWSTR NameCopy;
+
+    /* Make sure that we have a name */
+    if (!Name)
+    {
+        /* Fail */
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
+
+    /* Find out the size of the string */
+    StringLength = (wcslen(Name) + 1) * sizeof(WCHAR);
+
+    /* Allocate space for the copy */
+    NameCopy = Dns_AllocZero(StringLength);
+    if (NameCopy)
+    {
+        /* Copy it */
+        RtlCopyMemory(NameCopy, Name, StringLength);
+    }
+    else
+    {
+        /* Fail */
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    }
+
+    /* Return the copy */
+    return NameCopy;
+}
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(IN PVOID String,
+                                 IN ULONG Size OPTIONAL,
+                                 IN DWORD InputType,
+                                 IN DWORD OutputType)
+{
+    ULONG OutputSize = 0;
+
+    /* Check what kind of string this is */
+    if (InputType == UnicodeString)
+    {
+        /* Check if we have a size */
+        if (!Size)
+        {
+            /* Get it ourselves */
+            Size = (ULONG)wcslen(String);
+        }
+
+        /* Check the output type */
+        if (OutputType == UnicodeString)
+        {
+            /* Convert the size to bytes */
+            OutputSize = (Size + 1) * sizeof(WCHAR);
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+        else
+        {
+            /* Find out how much it will be in ANSI bytes */
+            OutputSize = WideCharToMultiByte(CP_ACP,
+                                             0,
+                                             String,
+                                             Size,
+                                             NULL,
+                                             0,
+                                             NULL,
+                                             NULL) + 1;
+        }
+    }
+    else if (InputType == AnsiString)
+    {
+        /* Check if we have a size */
+        if (!Size)
+        {
+            /* Get it ourselves */
+            Size = (ULONG)strlen(String);
+        }
+
+        /* Check the output type */
+        if (OutputType == AnsiString)
+        {
+            /* Just add a byte for the null char */
+            OutputSize = Size + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Calculate the bytes for a Unicode string */
+            OutputSize = (MultiByteToWideChar(CP_ACP,
+                                              0,
+                                              String,
+                                              Size,
+                                              NULL,
+                                              0) + 1) * sizeof(WCHAR);
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == Utf8String)
+    {
+        /* FIXME */
+        OutputSize = 0;
+    }
+
+    /* Return the size required */
+    return OutputSize;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/string.c
+ * PURPOSE:     functions for string manipulation and conversion.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+ULONG
+WINAPI
+Dns_StringCopy(OUT PVOID Destination,
+               IN OUT PULONG DestinationSize,
+               IN PVOID String,
+               IN ULONG StringSize OPTIONAL,
+               IN DWORD InputType,
+               IN DWORD OutputType)
+{
+    ULONG DestSize;
+    ULONG OutputSize = 0;
+
+    /* Check if the caller already gave us the string size */
+    if (!StringSize)
+    {
+        /* He didn't, get the input type */
+        if (InputType == UnicodeString)
+        {
+            /* Unicode string, calculate the size */
+            StringSize = (ULONG)wcslen((LPWSTR)String);
+        }
+        else
+        {
+            /* ANSI or UTF-8 sting, get the size */
+            StringSize = (ULONG)strlen((LPSTR)String);
+        }
+    }
+
+    /* Check if we have a limit on the desination size */
+    if (DestinationSize)
+    {
+        /* Make sure that we can respect it */
+        DestSize = Dns_GetBufferLengthForStringCopy(String,
+                                                    StringSize,
+                                                    InputType,
+                                                    OutputType);
+        if (*DestinationSize < DestSize)
+        {
+            /* Fail due to missing buffer space */
+            SetLastError(ERROR_MORE_DATA);
+
+            /* Return how much data we actually need */
+            *DestinationSize = DestSize;
+            return 0;
+        }
+        else if (!DestSize)
+        {
+            /* Fail due to invalid data */
+            SetLastError(ERROR_INVALID_DATA);
+            return 0;
+        }
+
+        /* Return how much data we actually need */
+        *DestinationSize = DestSize;
+    }
+
+    /* Now check if this is a Unicode String as input */
+    if (InputType == UnicodeString)
+    {
+        /* Check if the output is ANSI */
+        if (OutputType == AnsiString)
+        {
+            /* Convert and return the final desination size */
+            OutputSize = WideCharToMultiByte(CP_ACP,
+                                             0,
+                                             String,
+                                             StringSize,
+                                             Destination,
+                                             -1,
+                                             NULL,
+                                             NULL) + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Copy the string */
+            StringSize = StringSize * sizeof(WCHAR);
+            RtlMoveMemory(Destination, String, StringSize);
+
+            /* Return output length */
+            OutputSize = StringSize + 2;
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == AnsiString)
+    {
+        /* It's ANSI, is the output ansi too? */
+        if (OutputType == AnsiString)
+        {
+            /* Copy the string */
+            RtlMoveMemory(Destination, String, StringSize);
+
+            /* Return output length */
+            OutputSize = StringSize + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Convert to Unicode and return size */
+            OutputSize = MultiByteToWideChar(CP_ACP,
+                                             0,
+                                             String,
+                                             StringSize,
+                                             Destination,
+                                             -1) * sizeof(WCHAR) + 2;
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == Utf8String)
+    {
+        /* FIXME */
+        OutputSize = 0;
+    }
+
+    /* Return the output size */
+    return OutputSize;
+}
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name)
+{
+    SIZE_T StringLength;
+    LPWSTR NameCopy;
+
+    /* Make sure that we have a name */
+    if (!Name)
+    {
+        /* Fail */
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
+
+    /* Find out the size of the string */
+    StringLength = (wcslen(Name) + 1) * sizeof(WCHAR);
+
+    /* Allocate space for the copy */
+    NameCopy = Dns_AllocZero(StringLength);
+    if (NameCopy)
+    {
+        /* Copy it */
+        RtlCopyMemory(NameCopy, Name, StringLength);
+    }
+    else
+    {
+        /* Fail */
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    }
+
+    /* Return the copy */
+    return NameCopy;
+}
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(IN PVOID String,
+                                 IN ULONG Size OPTIONAL,
+                                 IN DWORD InputType,
+                                 IN DWORD OutputType)
+{
+    ULONG OutputSize = 0;
+
+    /* Check what kind of string this is */
+    if (InputType == UnicodeString)
+    {
+        /* Check if we have a size */
+        if (!Size)
+        {
+            /* Get it ourselves */
+            Size = (ULONG)wcslen(String);
+        }
+
+        /* Check the output type */
+        if (OutputType == UnicodeString)
+        {
+            /* Convert the size to bytes */
+            OutputSize = (Size + 1) * sizeof(WCHAR);
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+        else
+        {
+            /* Find out how much it will be in ANSI bytes */
+            OutputSize = WideCharToMultiByte(CP_ACP,
+                                             0,
+                                             String,
+                                             Size,
+                                             NULL,
+                                             0,
+                                             NULL,
+                                             NULL) + 1;
+        }
+    }
+    else if (InputType == AnsiString)
+    {
+        /* Check if we have a size */
+        if (!Size)
+        {
+            /* Get it ourselves */
+            Size = (ULONG)strlen(String);
+        }
+
+        /* Check the output type */
+        if (OutputType == AnsiString)
+        {
+            /* Just add a byte for the null char */
+            OutputSize = Size + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Calculate the bytes for a Unicode string */
+            OutputSize = (MultiByteToWideChar(CP_ACP,
+                                              0,
+                                              String,
+                                              Size,
+                                              NULL,
+                                              0) + 1) * sizeof(WCHAR);
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == Utf8String)
+    {
+        /* FIXME */
+        OutputSize = 0;
+    }
+
+    /* Return the size required */
+    return OutputSize;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/string.c
+ * PURPOSE:     functions for string manipulation and conversion.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+ULONG
+WINAPI
+Dns_StringCopy(OUT PVOID Destination,
+               IN OUT PULONG DestinationSize,
+               IN PVOID String,
+               IN ULONG StringSize OPTIONAL,
+               IN DWORD InputType,
+               IN DWORD OutputType)
+{
+    ULONG DestSize;
+    ULONG OutputSize = 0;
+
+    /* Check if the caller already gave us the string size */
+    if (!StringSize)
+    {
+        /* He didn't, get the input type */
+        if (InputType == UnicodeString)
+        {
+            /* Unicode string, calculate the size */
+            StringSize = (ULONG)wcslen((LPWSTR)String);
+        }
+        else
+        {
+            /* ANSI or UTF-8 sting, get the size */
+            StringSize = (ULONG)strlen((LPSTR)String);
+        }
+    }
+
+    /* Check if we have a limit on the desination size */
+    if (DestinationSize)
+    {
+        /* Make sure that we can respect it */
+        DestSize = Dns_GetBufferLengthForStringCopy(String,
+                                                    StringSize,
+                                                    InputType,
+                                                    OutputType);
+        if (*DestinationSize < DestSize)
+        {
+            /* Fail due to missing buffer space */
+            SetLastError(ERROR_MORE_DATA);
+
+            /* Return how much data we actually need */
+            *DestinationSize = DestSize;
+            return 0;
+        }
+        else if (!DestSize)
+        {
+            /* Fail due to invalid data */
+            SetLastError(ERROR_INVALID_DATA);
+            return 0;
+        }
+
+        /* Return how much data we actually need */
+        *DestinationSize = DestSize;
+    }
+
+    /* Now check if this is a Unicode String as input */
+    if (InputType == UnicodeString)
+    {
+        /* Check if the output is ANSI */
+        if (OutputType == AnsiString)
+        {
+            /* Convert and return the final desination size */
+            OutputSize = WideCharToMultiByte(CP_ACP,
+                                             0,
+                                             String,
+                                             StringSize,
+                                             Destination,
+                                             -1,
+                                             NULL,
+                                             NULL) + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Copy the string */
+            StringSize = StringSize * sizeof(WCHAR);
+            RtlMoveMemory(Destination, String, StringSize);
+
+            /* Return output length */
+            OutputSize = StringSize + 2;
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == AnsiString)
+    {
+        /* It's ANSI, is the output ansi too? */
+        if (OutputType == AnsiString)
+        {
+            /* Copy the string */
+            RtlMoveMemory(Destination, String, StringSize);
+
+            /* Return output length */
+            OutputSize = StringSize + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Convert to Unicode and return size */
+            OutputSize = MultiByteToWideChar(CP_ACP,
+                                             0,
+                                             String,
+                                             StringSize,
+                                             Destination,
+                                             -1) * sizeof(WCHAR) + 2;
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == Utf8String)
+    {
+        /* FIXME */
+        OutputSize = 0;
+    }
+
+    /* Return the output size */
+    return OutputSize;
+}
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name)
+{
+    SIZE_T StringLength;
+    LPWSTR NameCopy;
+
+    /* Make sure that we have a name */
+    if (!Name)
+    {
+        /* Fail */
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
+
+    /* Find out the size of the string */
+    StringLength = (wcslen(Name) + 1) * sizeof(WCHAR);
+
+    /* Allocate space for the copy */
+    NameCopy = Dns_AllocZero(StringLength);
+    if (NameCopy)
+    {
+        /* Copy it */
+        RtlCopyMemory(NameCopy, Name, StringLength);
+    }
+    else
+    {
+        /* Fail */
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    }
+
+    /* Return the copy */
+    return NameCopy;
+}
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(IN PVOID String,
+                                 IN ULONG Size OPTIONAL,
+                                 IN DWORD InputType,
+                                 IN DWORD OutputType)
+{
+    ULONG OutputSize = 0;
+
+    /* Check what kind of string this is */
+    if (InputType == UnicodeString)
+    {
+        /* Check if we have a size */
+        if (!Size)
+        {
+            /* Get it ourselves */
+            Size = (ULONG)wcslen(String);
+        }
+
+        /* Check the output type */
+        if (OutputType == UnicodeString)
+        {
+            /* Convert the size to bytes */
+            OutputSize = (Size + 1) * sizeof(WCHAR);
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+        else
+        {
+            /* Find out how much it will be in ANSI bytes */
+            OutputSize = WideCharToMultiByte(CP_ACP,
+                                             0,
+                                             String,
+                                             Size,
+                                             NULL,
+                                             0,
+                                             NULL,
+                                             NULL) + 1;
+        }
+    }
+    else if (InputType == AnsiString)
+    {
+        /* Check if we have a size */
+        if (!Size)
+        {
+            /* Get it ourselves */
+            Size = (ULONG)strlen(String);
+        }
+
+        /* Check the output type */
+        if (OutputType == AnsiString)
+        {
+            /* Just add a byte for the null char */
+            OutputSize = Size + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Calculate the bytes for a Unicode string */
+            OutputSize = (MultiByteToWideChar(CP_ACP,
+                                              0,
+                                              String,
+                                              Size,
+                                              NULL,
+                                              0) + 1) * sizeof(WCHAR);
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == Utf8String)
+    {
+        /* FIXME */
+        OutputSize = 0;
+    }
+
+    /* Return the size required */
+    return OutputSize;
+}
+
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS DNS Shared Library
+ * FILE:        lib/dnslib/string.c
+ * PURPOSE:     functions for string manipulation and conversion.
+ */
+
+/* INCLUDES ******************************************************************/
+#include "precomp.h"
+
+/* DATA **********************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+ULONG
+WINAPI
+Dns_StringCopy(OUT PVOID Destination,
+               IN OUT PULONG DestinationSize,
+               IN PVOID String,
+               IN ULONG StringSize OPTIONAL,
+               IN DWORD InputType,
+               IN DWORD OutputType)
+{
+    ULONG DestSize;
+    ULONG OutputSize = 0;
+
+    /* Check if the caller already gave us the string size */
+    if (!StringSize)
+    {
+        /* He didn't, get the input type */
+        if (InputType == UnicodeString)
+        {
+            /* Unicode string, calculate the size */
+            StringSize = (ULONG)wcslen((LPWSTR)String);
+        }
+        else
+        {
+            /* ANSI or UTF-8 sting, get the size */
+            StringSize = (ULONG)strlen((LPSTR)String);
+        }
+    }
+
+    /* Check if we have a limit on the desination size */
+    if (DestinationSize)
+    {
+        /* Make sure that we can respect it */
+        DestSize = Dns_GetBufferLengthForStringCopy(String,
+                                                    StringSize,
+                                                    InputType,
+                                                    OutputType);
+        if (*DestinationSize < DestSize)
+        {
+            /* Fail due to missing buffer space */
+            SetLastError(ERROR_MORE_DATA);
+
+            /* Return how much data we actually need */
+            *DestinationSize = DestSize;
+            return 0;
+        }
+        else if (!DestSize)
+        {
+            /* Fail due to invalid data */
+            SetLastError(ERROR_INVALID_DATA);
+            return 0;
+        }
+
+        /* Return how much data we actually need */
+        *DestinationSize = DestSize;
+    }
+
+    /* Now check if this is a Unicode String as input */
+    if (InputType == UnicodeString)
+    {
+        /* Check if the output is ANSI */
+        if (OutputType == AnsiString)
+        {
+            /* Convert and return the final desination size */
+            OutputSize = WideCharToMultiByte(CP_ACP,
+                                             0,
+                                             String,
+                                             StringSize,
+                                             Destination,
+                                             -1,
+                                             NULL,
+                                             NULL) + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Copy the string */
+            StringSize = StringSize * sizeof(WCHAR);
+            RtlMoveMemory(Destination, String, StringSize);
+
+            /* Return output length */
+            OutputSize = StringSize + 2;
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == AnsiString)
+    {
+        /* It's ANSI, is the output ansi too? */
+        if (OutputType == AnsiString)
+        {
+            /* Copy the string */
+            RtlMoveMemory(Destination, String, StringSize);
+
+            /* Return output length */
+            OutputSize = StringSize + 1;
+        }
+        else if (OutputType == UnicodeString)
+        {
+            /* Convert to Unicode and return size */
+            OutputSize = MultiByteToWideChar(CP_ACP,
+                                             0,
+                                             String,
+                                             StringSize,
+                                             Destination,
+                                             -1) * sizeof(WCHAR) + 2;
+        }
+        else if (OutputType == Utf8String)
+        {
+            /* FIXME */
+            OutputSize = 0;
+        }
+    }
+    else if (InputType == Utf8String)
+    {
+        /* FIXME */
+        OutputSize = 0;
+    }
+
+    /* Return the output size */
+    return OutputSize;
+}
+
+LPWSTR
+WINAPI
+Dns_CreateStringCopy_W(IN LPWSTR Name)
+{
+    SIZE_T StringLength;
+    LPWSTR NameCopy;
+
+    /* Make sure that we have a name */
+    if (!Name)
+    {
+        /* Fail */
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
+
+    /* Find out the size of the string */
+    StringLength = (wcslen(Name) + 1) * sizeof(WCHAR);
+
+    /* Allocate space for the copy */
+    NameCopy = Dns_AllocZero(StringLength);
+    if (NameCopy)
+    {
+        /* Copy it */
+        RtlCopyMemory(NameCopy, Name, StringLength);
+    }
+    else
+    {
+        /* Fail */
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    }
+
+    /* Return the copy */
+    return NameCopy;
+}
+
+ULONG
+WINAPI
+Dns_GetBufferLengthForStringCopy(IN PVOID String,
+                                 IN ULONG Size OPTIONAL,
+                              &nb