From 9bd7d5ce0f5842593712de4d40da97c3d3e9eb85 Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Thu, 18 Dec 2003 10:54:02 +0000 Subject: [PATCH] Initial dnsapi sources. svn path=/trunk/; revision=7112 --- reactos/lib/dnsapi/dnsapi/adns.c | 26 +++ reactos/lib/dnsapi/dnsapi/context.c | 117 ++++++++++ reactos/lib/dnsapi/dnsapi/free.c | 36 +++ reactos/lib/dnsapi/dnsapi/names.c | 199 ++++++++++++++++ reactos/lib/dnsapi/dnsapi/query.c | 348 ++++++++++++++++++++++++++++ 5 files changed, 726 insertions(+) create mode 100644 reactos/lib/dnsapi/dnsapi/adns.c create mode 100644 reactos/lib/dnsapi/dnsapi/context.c create mode 100644 reactos/lib/dnsapi/dnsapi/free.c create mode 100644 reactos/lib/dnsapi/dnsapi/names.c create mode 100644 reactos/lib/dnsapi/dnsapi/query.c diff --git a/reactos/lib/dnsapi/dnsapi/adns.c b/reactos/lib/dnsapi/dnsapi/adns.c new file mode 100644 index 00000000000..c148fc15d47 --- /dev/null +++ b/reactos/lib/dnsapi/dnsapi/adns.c @@ -0,0 +1,26 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/context.c + * PURPOSE: ADNS translation. + * PROGRAMER: Art Yerkes + * UPDATE HISTORY: + * 12/15/03 -- Created + */ + +#include +#include +#include +#include + +DNS_STATUS DnsIntTranslateAdnsToDNS_STATUS( int Status ) { + switch( Status ) { + case adns_s_ok: + return ERROR_SUCCESS; + case adns_s_nomemory: + case adns_s_systemfail: + default: /* There really aren't any general errors in the dns part. */ + return DNS_ERROR_NO_MEMORY; + } +} + diff --git a/reactos/lib/dnsapi/dnsapi/context.c b/reactos/lib/dnsapi/dnsapi/context.c new file mode 100644 index 00000000000..855bab072db --- /dev/null +++ b/reactos/lib/dnsapi/dnsapi/context.c @@ -0,0 +1,117 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/context.c + * PURPOSE: DNSAPI functions built on the ADNS library. + * PROGRAMER: Art Yerkes + * UPDATE HISTORY: + * 12/15/03 -- Created + */ + +#include +#include +#include +#include + +/* DnsAcquireContextHandle ************* + * Create a context handle that will allow us to open and retrieve queries. + * + * DWORD CredentialsFlags -- TRUE -- Unicode + * FALSE -- Ansi or UTF-8? + * + * PVOID Credentials -- Pointer to a SEC_WINNT_AUTH_IDENTITY + * TODO: Use it. + * + * PHANDLE ContextHandle -- Pointer to a HANDLE that will receive + * our context pointer. + * + * RETURNS: + * ERROR_SUCCESS or a failure code. + * TODO: Which ones area allowed? + */ + +extern DNS_STATUS WINAPI DnsAcquireContextHandle_UTF8 +( DWORD CredentialsFlags, + PVOID Credentials, + HANDLE *ContextHandle ); + +DNS_STATUS WINAPI DnsAcquireContextHandle_W +( DWORD CredentialsFlags, + PVOID Credentials, + HANDLE *ContextHandle ) { + if( CredentialsFlags ) { + PWINDNS_CONTEXT Context; + int adns_status; + + /* For now, don't worry about the user's identity. */ + Context = (PWINDNS_CONTEXT)RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof( WINDNS_CONTEXT ) ); + /* The real work here is to create an adns_state that will help us + * do what we want to later. */ + adns_status = adns_init( &Context->State, + adns_if_noenv | + adns_if_noerrprint | + adns_if_noserverwarn, + 0 ); + if( adns_status != adns_s_ok ) { + *ContextHandle = 0; + return DnsIntTranslateAdnsToDNS_STATUS( adns_status ); + } else { + *ContextHandle = (HANDLE)Context; + return ERROR_SUCCESS; + } + } else { + return DnsAcquireContextHandle_UTF8( CredentialsFlags, + Credentials, + ContextHandle ); + } +} + +DNS_STATUS WINAPI DnsAcquireContextHandle_UTF8 +( DWORD CredentialsFlags, + PVOID Credentials, + HANDLE *ContextHandle ) { + if( CredentialsFlags ) { + return DnsAcquireContextHandle_W( CredentialsFlags, + Credentials, + ContextHandle ); + } else { + /* Convert to unicode, then call the _W version + * For now, there is no conversion */ + DNS_STATUS Status; + + Status = DnsAcquireContextHandle_W( TRUE, + Credentials, /* XXX arty */ + ContextHandle ); + + /* Free the unicode credentials when they exist. */ + + return Status; + } +} + +DNS_STATUS WINAPI DnsAcquireContextHandle_A +( DWORD CredentialFlags, + PVOID Credentials, + HANDLE *ContextHandle ) { + if( CredentialFlags ) { + return DnsAcquireContextHandle_W( CredentialFlags, + Credentials, + ContextHandle ); + } else { + return DnsAcquireContextHandle_UTF8( CredentialFlags, + Credentials, + ContextHandle ); + } +} +/* DnsReleaseContextHandle ************* + * Release a context handle, freeing all resources. + */ + +void WINAPI DnsReleaseContextHandle +( HANDLE ContextHandle ) { + PWINDNS_CONTEXT Context = (PWINDNS_CONTEXT)ContextHandle; + adns_finish( Context->State ); + RtlFreeHeap( RtlGetProcessHeap(), 0, Context ); +} + diff --git a/reactos/lib/dnsapi/dnsapi/free.c b/reactos/lib/dnsapi/dnsapi/free.c new file mode 100644 index 00000000000..fabb3436369 --- /dev/null +++ b/reactos/lib/dnsapi/dnsapi/free.c @@ -0,0 +1,36 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/free.c + * PURPOSE: DNSAPI functions built on the ADNS library. + * PROGRAMER: Art Yerkes + * UPDATE HISTORY: + * 12/15/03 -- Created + */ + +#include +#include +#include +#include + +VOID WINAPI DnsFree +( PVOID Data, DNS_FREE_TYPE FreeType ) { + switch( FreeType ) { + case DnsFreeFlat: + RtlFreeHeap( RtlGetProcessHeap(), 0, Data ); + break; + + case DnsFreeRecordList: + DnsIntFreeRecordList( (PDNS_RECORDA)Data ); + break; + + case DnsFreeParsedMessageFields: + /* assert( FALSE ); XXX arty not yet implemented. */ + break; + } +} + +VOID WINAPI DnsRecordListFree +( PVOID Data, DNS_FREE_TYPE FreeType ) { + DnsFree( Data, FreeType ); +} diff --git a/reactos/lib/dnsapi/dnsapi/names.c b/reactos/lib/dnsapi/dnsapi/names.c new file mode 100644 index 00000000000..0cd5f226c71 --- /dev/null +++ b/reactos/lib/dnsapi/dnsapi/names.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include +#include + +static BOOL DnsIntNameContainsDots( LPCWSTR Name ) { + return wcschr( Name, '.' ) ? TRUE : FALSE; +} + +static BOOL DnsIntTwoConsecutiveDots( LPCWSTR Name ) { + return wcsstr( Name, L".." ) ? TRUE : FALSE; +} + +static BOOL DnsIntContainsUnderscore( LPCWSTR Name ) { + return wcschr( Name, '_' ) ? TRUE : FALSE; +} + +/* DnsValidateName ********************* + * Use some different algorithms to validate the given name as suitable for + * use with DNS. + * + * Name -- The name to evaluate. + * Format -- Format to use: + * DnsNameDomain + * DnsNameDomainLabel + * DnsNameHostnameFull + * DnsNameHostnameLabel + * DnsNameWildcard + * DnsNameSrvRecord + * RETURNS: + * ERROR_SUCCESS -- All good + * ERROR_INVALID_NAME -- + * Name greater than 255 chars. + * Label greater than 63 chars. + * Two consecutive dots, or starts with dot. + * Contains a dot, but a Label check was specified. + * DNS_ERROR_INVALID_NAME_CHAR + * Contains any invalid char: " {|}~[\]^':;<=>?@!"#$%^`()+/," + * Contains an *, except when it is the first label and Wildcard was + * specified. + * DNS_ERROR_NUMERIC_NAME + * Set if the name contains only numerics, unless Domain is specified. + * DNS_ERROR_NON_RFC_NAME + * If the name contains underscore. + * If there is an underscore in any position but the first in the SrvRecord + * case. + * If the name contains a non-ascii character. + */ + +DNS_STATUS WINAPI DnsValidateName_W +( LPCWSTR Name, + DNS_NAME_FORMAT Format ) { + BOOL AllowDot = FALSE; + BOOL AllowLeadingAst = FALSE; + BOOL AllowLeadingUnderscore = FALSE; + BOOL AllowAllDigits = FALSE; + const WCHAR *NextLabel, *CurrentLabel, *CurrentChar; + + switch( Format ) { + case DnsNameDomain: + AllowAllDigits = TRUE; + AllowDot = TRUE; + break; + case DnsNameDomainLabel: + AllowAllDigits = TRUE; + break; + case DnsNameHostnameFull: + AllowDot = TRUE; + break; + case DnsNameHostnameLabel: + break; + case DnsNameWildcard: + AllowLeadingAst = TRUE; + AllowDot = TRUE; + break; + case DnsNameSrvRecord: + AllowLeadingUnderscore = TRUE; + break; + default: + break; + } + + /* Preliminary checks */ + if( Name[0] == 0 ) return ERROR_INVALID_NAME; /* XXX arty: Check this */ + + /* Name too long */ + if( wcslen( Name ) > 255 ) { + return ERROR_INVALID_NAME; + } + + /* Violations about dots */ + if( (!AllowDot && DnsIntNameContainsDots( Name )) || + Name[0] == '.' || DnsIntTwoConsecutiveDots( Name ) ) + return ERROR_INVALID_NAME; + + /* Check component sizes */ + CurrentLabel = Name; + do { + NextLabel = CurrentLabel; + while( *NextLabel && *NextLabel != '.' ) NextLabel++; + + if( NextLabel - CurrentLabel > 63 ) + return ERROR_INVALID_NAME; + + CurrentLabel = NextLabel; + } while( *CurrentLabel ); + + CurrentChar = Name; + + while( *CurrentChar ) { + if( wcschr(L" {|}~[\\]^':;<=>?@!\"#$%^`()+/,",*CurrentChar) ) + return DNS_ERROR_INVALID_NAME_CHAR; + CurrentChar++; + } + + if( (!AllowLeadingAst && Name[0] == '*') || + (AllowLeadingAst && Name[0] == '*' && Name[1] && Name[1] != '.') ) + return DNS_ERROR_INVALID_NAME_CHAR; + + if( wcschr( Name + 1, '*' ) ) + return DNS_ERROR_INVALID_NAME_CHAR; + + CurrentChar = Name; + while( !AllowAllDigits && *CurrentChar ) { + if( *CurrentChar == '.' || (*CurrentChar >= '0' && *CurrentChar <= '9') ) + return DNS_ERROR_NUMERIC_NAME; + } + + if( ((AllowLeadingUnderscore && Name[0] == '_') || Name[0] != '_') && + !DnsIntContainsUnderscore( Name + 1 ) ) + return DNS_ERROR_NON_RFC_NAME; + + return ERROR_SUCCESS; +} + +DNS_STATUS WINAPI DnsValidateName_UTF8 +( LPCSTR Name, + DNS_NAME_FORMAT Format ) { + PWCHAR Buffer; + int StrLenWc; + DNS_STATUS Status; + + StrLenWc = mbstowcs( NULL, Name, 0 ); + Buffer = RtlAllocateHeap( GetProcessHeap(), 0, + sizeof( WCHAR ) * (StrLenWc + 1) ); + mbstowcs( Buffer, Name, StrLenWc + 1 ); + Status = DnsValidateName_W( Buffer, Format ); + RtlFreeHeap( GetProcessHeap(), 0, Buffer ); + + return Status; +} + +DNS_STATUS WINAPI DnsValidateName_A +( LPCSTR Name, + DNS_NAME_FORMAT Format ) { + return DnsValidateName_UTF8( Name, Format ); +} + +/* DnsNameCompare ********************** + * Return TRUE if the names are identical. + * + * Name1 & Name2 -- Names. + */ + +BOOL WINAPI DnsNameCompare_W +( LPWSTR Name1, + LPWSTR Name2 ) { + int offset = 0; + + while( Name1[offset] && Name2[offset] && + towupper( Name1[offset] ) == towupper( Name2[offset] ) ) offset++; + return + (!Name1[offset] && !Name2[offset]) || + (!Name1[offset] && !wcscmp( Name2 + offset, L"." )) || + (!Name2[offset] && !wcscmp( Name1 + offset, L"." )); +} + +BOOL WINAPI DnsNameCompare_UTF8 +( LPCSTR Name1, + LPCSTR Name2 ) { + int offset = 0; + + while( Name1[offset] && Name2[offset] && + toupper( Name1[offset] ) == toupper( Name2[offset] ) ) offset++; + return + (!Name1[offset] && !Name2[offset]) || + (!Name1[offset] && !strcmp( Name2 + offset, ".")) || + (!Name2[offset] && !strcmp( Name1 + offset, ".")); +} + +BOOL WINAPI DnsNameCompare_A +( LPCSTR Name1, + LPCSTR Name2 ) { + return DnsNameCompare_UTF8( Name1, Name2 ); +} + diff --git a/reactos/lib/dnsapi/dnsapi/query.c b/reactos/lib/dnsapi/dnsapi/query.c new file mode 100644 index 00000000000..8271903480e --- /dev/null +++ b/reactos/lib/dnsapi/dnsapi/query.c @@ -0,0 +1,348 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/query.c + * PURPOSE: DNSAPI functions built on the ADNS library. + * PROGRAMER: Art Yerkes + * UPDATE HISTORY: + * 12/15/03 -- Created + */ + +#include +#include +#include +#include +#include + +/* DnsQuery **************************** + * Begin a DNS query, and allow the result to be placed in the application + * supplied result pointer. The result can be manipulated with the record + * functions. + * + * Name -- The DNS object to be queried. + * Type -- The type of records to be returned. These are + * listed in windns.h + * Options -- Query options. DNS_QUERY_STANDARD is the base + * state, and every other option takes precedence. + * multiple options can be combined. Listed in + * windns.h + * Servers -- List of alternate servers (optional) + * QueryResultSet -- Pointer to the result pointer that will be filled + * when the response is available. + * Reserved -- Response as it appears on the wire. Optional. + */ + +char *xstrsave(const char *str) { + char *p; + + p= RtlAllocateHeap( RtlGetProcessHeap(), 0, strlen(str)+1 ); + strcpy(p,str); + return p; +} + +DNS_STATUS WINAPI DnsQuery_A +( LPCSTR Name, + WORD Type, + DWORD Options, + PIP4_ARRAY Servers, + PDNS_RECORDA *QueryResultSet, + PVOID *Reserved ) { + adns_state astate; + int quflags = 0; + int adns_error; + adns_answer *answer; + + *QueryResultSet = 0; + + switch( Type ) { + case DNS_TYPE_A: + adns_error = adns_init( &astate, + adns_if_noenv | + adns_if_noerrprint | + adns_if_noserverwarn, + 0 ); + if( adns_error != adns_s_ok ) { + adns_finish( astate ); + return DnsIntTranslateAdnsToDNS_STATUS( adns_error ); + } + + adns_error = adns_synchronous( astate, + Name, + adns_r_addr, + quflags, + &answer ); + + if( adns_error != adns_s_ok ) { + adns_finish( astate ); + return DnsIntTranslateAdnsToDNS_STATUS( adns_error ); + } + + *QueryResultSet = (PDNS_RECORDA)RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof( DNS_RECORDA ) ); + (*QueryResultSet)->wType = Type; + (*QueryResultSet)->pName = xstrsave( Name ); + (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA); + (*QueryResultSet)->Data.A.IpAddress = + ntohl( answer->rrs.addr->addr.inet.sin_addr.s_addr ); + adns_finish( astate ); + return ERROR_SUCCESS; + + default: + return DNS_ERROR_NO_MEMORY; /* XXX arty: find a better error code. */ + } +} + +static PCHAR DnsWToC( const WCHAR *WideString ) { + int chars = wcstombs( NULL, WideString, 0 ); + PCHAR out = RtlAllocateHeap( RtlGetProcessHeap(), 0, chars + 1 ); + wcstombs( out, WideString, chars + 1 ); + return out; +} + +static PWCHAR DnsCToW( const CHAR *NarrowString ) { + int chars = mbstowcs( NULL, NarrowString, 0 ); + PWCHAR out = RtlAllocateHeap( RtlGetProcessHeap(), 0, + (chars + 1) * sizeof(WCHAR) ); + mbstowcs( out, NarrowString, chars + 1 ); + return out; +} + +DNS_STATUS WINAPI DnsQuery_W +( LPCWSTR Name, + WORD Type, + DWORD Options, + PIP4_ARRAY Servers, + PDNS_RECORDW *QueryResultSet, + PVOID *Reserved ) { + int i; + PCHAR Buffer; + DNS_STATUS Status; + PDNS_RECORDA QueryResultWide; + PDNS_RECORDW ConvertedRecord = 0, LastRecord = 0; + + Buffer = DnsWToC( Name ); + + Status = DnsQuery_A( Buffer, Type, Options, Servers, &QueryResultWide, + Reserved ); + + while( Status == ERROR_SUCCESS && QueryResultWide ) { + switch( QueryResultWide->wType ) { + case DNS_TYPE_A: + case DNS_TYPE_WKS: + case DNS_TYPE_AAAA: + case DNS_TYPE_KEY: + ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof(DNS_RECORDA) ); + ConvertedRecord->pName = DnsCToW( QueryResultWide->pName ); + ConvertedRecord->wType = QueryResultWide->wType; + ConvertedRecord->wDataLength = QueryResultWide->wDataLength; + memcpy( ConvertedRecord, QueryResultWide, + QueryResultWide->wDataLength ); + break; + + case DNS_TYPE_CNAME: + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_MB: + case DNS_TYPE_MD: + case DNS_TYPE_MF: + case DNS_TYPE_MG: + case DNS_TYPE_MR: + ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof(DNS_RECORDA) ); + ConvertedRecord->pName = DnsCToW( QueryResultWide->pName ); + ConvertedRecord->wType = QueryResultWide->wType; + ConvertedRecord->wDataLength = sizeof(DNS_PTR_DATAA); + ConvertedRecord->Data.PTR.pNameHost = + DnsCToW( QueryResultWide->Data.PTR.pNameHost ); + break; + case DNS_TYPE_MINFO: + case DNS_TYPE_RP: + ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof(DNS_RECORDA) ); + ConvertedRecord->pName = DnsCToW( QueryResultWide->pName ); + ConvertedRecord->wType = QueryResultWide->wType; + ConvertedRecord->wDataLength = sizeof(DNS_MINFO_DATAA); + ConvertedRecord->Data.MINFO.pNameMailbox = + DnsCToW( QueryResultWide->Data.MINFO.pNameMailbox ); + ConvertedRecord->Data.MINFO.pNameErrorsMailbox = + DnsCToW( QueryResultWide->Data.MINFO.pNameErrorsMailbox ); + break; + + case DNS_TYPE_MX: + case DNS_TYPE_AFSDB: + case DNS_TYPE_RT: + ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof(DNS_RECORDA) ); + ConvertedRecord->pName = DnsCToW( QueryResultWide->pName ); + ConvertedRecord->wType = QueryResultWide->wType; + ConvertedRecord->wDataLength = sizeof(DNS_MX_DATAW); + ConvertedRecord->Data.MX.pNameExchange = + DnsCToW( QueryResultWide->Data.MX.pNameExchange ); + ConvertedRecord->Data.MX.wPreference = + QueryResultWide->Data.MX.wPreference; + break; + + case DNS_TYPE_TXT: + case DNS_TYPE_HINFO: + case DNS_TYPE_ISDN: + ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof(DNS_TXT_DATAW) + + QueryResultWide-> + Data.TXT.dwStringCount ); + ConvertedRecord->pName = DnsCToW( QueryResultWide->pName ); + ConvertedRecord->wType = QueryResultWide->wType; + ConvertedRecord->wDataLength = + sizeof(DNS_TXT_DATAW) + + (sizeof(PWCHAR) * QueryResultWide->Data.TXT.dwStringCount); + ConvertedRecord->Data.TXT.dwStringCount = + QueryResultWide->Data.TXT.dwStringCount; + for( i = 0; i < ConvertedRecord->Data.TXT.dwStringCount; i++ ) { + ConvertedRecord->Data.TXT.pStringArray[i] = + DnsCToW( QueryResultWide->Data.TXT.pStringArray[i] ); + } + break; + + case DNS_TYPE_NULL: + ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof(DNS_NULL_DATA) + + QueryResultWide-> + Data.Null.dwByteCount ); + ConvertedRecord->pName = DnsCToW( QueryResultWide->pName ); + ConvertedRecord->wType = QueryResultWide->wType; + ConvertedRecord->wDataLength = + sizeof(DNS_NULL_DATA) + QueryResultWide->Data.Null.dwByteCount; + ConvertedRecord->Data.Null.dwByteCount = + QueryResultWide->Data.Null.dwByteCount; + memcpy( &ConvertedRecord->Data.Null.Data, + &QueryResultWide->Data.Null.Data, + QueryResultWide->Data.Null.dwByteCount ); + break; + + case DNS_TYPE_SIG: + ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof(DNS_RECORDA) ); + ConvertedRecord->pName = DnsCToW( QueryResultWide->pName ); + ConvertedRecord->wType = QueryResultWide->wType; + ConvertedRecord->wDataLength = sizeof(DNS_SIG_DATAA); + memcpy( &ConvertedRecord->Data.SIG, + &QueryResultWide->Data.SIG, + sizeof(QueryResultWide->Data.SIG) ); + ConvertedRecord->Data.SIG.pNameSigner = + DnsCToW( QueryResultWide->Data.SIG.pNameSigner ); + break; + + case DNS_TYPE_NXT: + ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof(DNS_RECORDA) ); + ConvertedRecord->pName = DnsCToW( QueryResultWide->pName ); + ConvertedRecord->wType = QueryResultWide->wType; + ConvertedRecord->wDataLength = sizeof(DNS_NXT_DATAA); + memcpy( &ConvertedRecord->Data.NXT, + &QueryResultWide->Data.NXT, + sizeof(QueryResultWide->Data.NXT) ); + ConvertedRecord->Data.NXT.pNameNext = + DnsCToW( QueryResultWide->Data.NXT.pNameNext ); + break; + + case DNS_TYPE_SRV: + ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0, + sizeof(DNS_RECORDA) ); + ConvertedRecord->pName = DnsCToW( QueryResultWide->pName ); + ConvertedRecord->wType = QueryResultWide->wType; + ConvertedRecord->wDataLength = sizeof(DNS_SRV_DATAA); + memcpy( &ConvertedRecord->Data.SRV, + &QueryResultWide->Data.SRV, + sizeof(QueryResultWide->Data.SRV) ); + ConvertedRecord->Data.SRV.pNameTarget = + DnsCToW( QueryResultWide->Data.SRV.pNameTarget ); + break; + } + + if( LastRecord ) { + LastRecord->pNext = ConvertedRecord; + LastRecord = LastRecord->pNext; + } else { + LastRecord = *QueryResultSet = ConvertedRecord; + } + } + + LastRecord->pNext = 0; + + /* The name */ + RtlFreeHeap( RtlGetProcessHeap(), 0, Buffer ); + + return Status; +} + +DNS_STATUS WINAPI DnsQuery_UTF8 +( LPCSTR Name, + WORD Type, + DWORD Options, + PIP4_ARRAY Servers, + PDNS_RECORDA *QueryResultSet, + PVOID *Reserved ) { + return DnsQuery_UTF8( Name, Type, Options, Servers, QueryResultSet, + Reserved ); +} + +void DnsIntFreeRecordList( PDNS_RECORDA ToDelete ) { + int i; + PDNS_RECORDA next = 0; + + while( ToDelete ) { + if( ToDelete->pName ) + RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->pName ); + switch( ToDelete->wType ) { + case DNS_TYPE_CNAME: + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_MB: + case DNS_TYPE_MD: + case DNS_TYPE_MF: + case DNS_TYPE_MG: + case DNS_TYPE_MR: + RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.PTR.pNameHost ); + break; + case DNS_TYPE_MINFO: + case DNS_TYPE_RP: + RtlFreeHeap( RtlGetProcessHeap(), 0, + ToDelete->Data.MINFO.pNameMailbox ); + RtlFreeHeap( RtlGetProcessHeap(), 0, + ToDelete->Data.MINFO.pNameErrorsMailbox ); + break; + + case DNS_TYPE_MX: + case DNS_TYPE_AFSDB: + case DNS_TYPE_RT: + RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.MX.pNameExchange ); + break; + + case DNS_TYPE_TXT: + case DNS_TYPE_HINFO: + case DNS_TYPE_ISDN: + for( i = 0; i < ToDelete->Data.TXT.dwStringCount; i++ ) { + RtlFreeHeap( RtlGetProcessHeap(), 0, + ToDelete->Data.TXT.pStringArray[i] ); + } + RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.TXT.pStringArray ); + break; + + case DNS_TYPE_SIG: + RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.SIG.pNameSigner ); + break; + + case DNS_TYPE_NXT: + RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.NXT.pNameNext ); + break; + + case DNS_TYPE_SRV: + RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.SRV.pNameTarget ); + break; + } + + next = ToDelete->pNext; + RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete ); + ToDelete = next; + } +}