CVS: winex/dlls/dnsapi dnsapi.h, NONE, 1.1 dnsapi.spec, NONE, 1.1 main.c, NONE, 1.1 Makefile.in, NONE, 1.1 name.c, NONE, 1.1 ns_name.c, NONE, 1.1 ns_parse.c, NONE, 1.1 query.c, NONE, 1.1 record.c, NONE, 1.1
[email protected] 29 Aug 2007 11:59:03 -0000
| Newsgroups | gmane.comp.emulators.winex.cvs |
|---|---|
| Message-ID | <[email protected]> |
Subject: winex/dlls/dnsapi dnsapi.h,NONE,1.1 dnsapi.spec,NONE,1.1 main.c,NONE,1.1 Makefile.in,NONE,1.1 name.c,NONE,1.1 ns_name.c,NONE,1.1 ns_parse.c,NONE,1.1 query.c,NONE,1.1 record.c,NONE,1.1Update of /var/lib/cvsd/cvsroot/winex/dlls/dnsapi
In directory agravaine:/tmp/cvs-serv29642/dlls/dnsapi
Added Files:
dnsapi.h dnsapi.spec main.c Makefile.in name.c ns_name.c
ns_parse.c query.c record.c
Log Message:
Import dnsapi from WineHQ
TRAC #2084
--- NEW FILE: dnsapi.h ---
/*
* DNS support
*
* Copyright 2006 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
static inline void *dns_alloc( SIZE_T size )
{
return HeapAlloc( GetProcessHeap(), 0, size );
}
static inline void *dns_zero_alloc( SIZE_T size )
{
return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
}
static inline void dns_free( LPVOID mem )
{
HeapFree( GetProcessHeap(), 0, mem );
}
static inline LPSTR dns_strdup_a( LPCSTR src )
{
LPSTR dst;
if (!src) return NULL;
dst = dns_alloc( (lstrlenA( src ) + 1) * sizeof(char) );
if (dst) lstrcpyA( dst, src );
return dst;
}
static inline char *dns_strdup_u( const char *src )
{
char *dst;
if (!src) return NULL;
dst = dns_alloc( (strlen( src ) + 1) * sizeof(char) );
if (dst) strcpy( dst, src );
return dst;
}
static inline LPWSTR dns_strdup_w( LPCWSTR src )
{
LPWSTR dst;
if (!src) return NULL;
dst = dns_alloc( (lstrlenW( src ) + 1) * sizeof(WCHAR) );
if (dst) lstrcpyW( dst, src );
return dst;
}
static inline LPWSTR dns_strdup_aw( LPCSTR str )
{
LPWSTR ret = NULL;
if (str)
{
DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
if ((ret = dns_alloc( len * sizeof(WCHAR) )))
MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
}
return ret;
}
static inline LPWSTR dns_strdup_uw( const char *str )
{
LPWSTR ret = NULL;
if (str)
{
DWORD len = MultiByteToWideChar( CP_UTF8, 0, str, -1, NULL, 0 );
if ((ret = dns_alloc( len * sizeof(WCHAR) )))
MultiByteToWideChar( CP_UTF8, 0, str, -1, ret, len );
}
return ret;
}
static inline LPSTR dns_strdup_wa( LPCWSTR str )
{
LPSTR ret = NULL;
if (str)
{
DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
if ((ret = dns_alloc( len )))
WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
}
return ret;
}
static inline char *dns_strdup_wu( LPCWSTR str )
{
LPSTR ret = NULL;
if (str)
{
DWORD len = WideCharToMultiByte( CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL );
if ((ret = dns_alloc( len )))
WideCharToMultiByte( CP_UTF8, 0, str, -1, ret, len, NULL, NULL );
}
return ret;
}
static inline char *dns_strdup_au( LPCSTR src )
{
char *dst = NULL;
LPWSTR ret = dns_strdup_aw( src );
if (ret)
{
dst = dns_strdup_wu( ret );
dns_free( ret );
}
return dst;
}
static inline LPSTR dns_strdup_ua( const char *src )
{
LPSTR dst = NULL;
LPWSTR ret = dns_strdup_uw( src );
if (ret)
{
dst = dns_strdup_wa( ret );
dns_free( ret );
}
return dst;
}
const char *dns_type_to_str( unsigned short );
int dns_ns_initparse( const u_char *, int, ns_msg * );
int dns_ns_parserr( ns_msg *, ns_sect, int, ns_rr * );
int dns_ns_name_skip( const u_char **, const u_char * );
int dns_ns_name_uncompress( const u_char *, const u_char *, const u_char *, char *, size_t );
--- NEW FILE: dnsapi.spec ---
name dnsapi
type win32
init DllMain
import netapi32.dll
import kernel32.dll
@ stdcall DnsAcquireContextHandle_A(long ptr ptr) DnsAcquireContextHandle_A
@ stdcall DnsAcquireContextHandle_UTF8(long ptr ptr) DnsAcquireContextHandle_UTF8
@ stdcall DnsAcquireContextHandle_W(long ptr ptr) DnsAcquireContextHandle_W
@ stub DnsAddRecordSet_A
@ stub DnsAddRecordSet_UTF8
@ stub DnsAddRecordSet_W
@ stub DnsAllocateRecord
@ stub DnsApiHeapReset
@ stub DnsAsyncRegisterHostAddrs_A
@ stub DnsAsyncRegisterHostAddrs_UTF8
@ stub DnsAsyncRegisterHostAddrs_W
@ stub DnsAsyncRegisterInit
@ stub DnsAsyncRegisterTerm
@ stub DnsCheckNameCollision_A
@ stub DnsCheckNameCollision_UTF8
@ stub DnsCheckNameCollision_W
@ stub DnsCopyStringEx
@ stub DnsCreateReverseNameStringForIpAddress
@ stub DnsCreateStandardDnsNameCopy
@ stub DnsCreateStringCopy
@ stub DnsDhcpSrvRegisterHostName_W
@ stub DnsDhcpSrvRegisterInit
@ stub DnsDhcpSrvRegisterTerm
@ stub DnsDisableAdapterDomainNameRegistration
@ stub DnsDisableBNodeResolverThread
@ stub DnsDisableDynamicRegistration
@ stub DnsDowncaseDnsNameLabel
@ stub DnsEnableAdapterDomainNameRegistration
@ stub DnsEnableBNodeResolverThread
@ stub DnsEnableDynamicRegistration
@ stdcall DnsExtractRecordsFromMessage_UTF8(ptr long ptr) DnsExtractRecordsFromMessage_UTF8
@ stdcall DnsExtractRecordsFromMessage_W(ptr long ptr) DnsExtractRecordsFromMessage_W
@ stub DnsFindAuthoritativeZone
@ stub DnsFlushResolverCache
@ stub DnsFlushResolverCacheEntry_A
@ stub DnsFlushResolverCacheEntry_UTF8
@ stub DnsFlushResolverCacheEntry_W
@ stub DnsFreeAdapterInformation
@ stub DnsFreeNetworkInformation
@ stub DnsFreeSearchInformation
@ stub DnsGetBufferLengthForStringCopy
@ stub DnsGetCacheDataTable
@ stub DnsGetDnsServerList
@ stub DnsGetDomainName
@ stub DnsGetHostName_A
@ stub DnsGetHostName_UTF8
@ stub DnsGetHostName_W
@ stub DnsGetIpAddressInfoList
@ stub DnsGetIpAddressList
@ stub DnsGetLastServerUpdateIP
@ stub DnsGetMaxNumberOfAddressesToRegister
@ stub DnsGetNetworkInformation
@ stub DnsGetPrimaryDomainName_A
@ stub DnsGetPrimaryDomainName_UTF8
@ stub DnsGetPrimaryDomainName_W
@ stub DnsGetSearchInformation
@ stub DnsIpv6AddressToString
@ stub DnsIpv6StringToAddress
@ stub DnsIsAdapterDomainNameRegistrationEnabled
@ stub DnsIsAMailboxType
@ stub DnsIsDynamicRegistrationEnabled
@ stub DnsIsStatusRcode
@ stub DnsIsStringCountValidForTextType
@ stub DnsMapRcodeToStatus
@ stub DnsModifyRecordSet_A
@ stub DnsModifyRecordSet_UTF8
@ stub DnsModifyRecordSet_W
@ stdcall DnsModifyRecordsInSet_A(ptr ptr long ptr ptr ptr) DnsModifyRecordsInSet_A
@ stdcall DnsModifyRecordsInSet_UTF8(ptr ptr long ptr ptr ptr) DnsModifyRecordsInSet_UTF8
@ stdcall DnsModifyRecordsInSet_W(ptr ptr long ptr ptr ptr) DnsModifyRecordsInSet_W
@ stdcall DnsNameCompare_A(str str) DnsNameCompare_A
@ stub DnsNameCompareEx_A
@ stub DnsNameCompareEx_UTF8
@ stub DnsNameCompareEx_W
@ stdcall DnsNameCompare_W(wstr wstr) DnsNameCompare_W
@ stub DnsNameCopy
@ stub DnsNameCopyAllocate
@ stub DnsNotifyResolver
@ stdcall DnsQuery_A(str long long ptr ptr ptr) DnsQuery_A
@ stdcall DnsQueryConfig(long long wstr ptr ptr ptr) DnsQueryConfig
@ stub DnsQueryEx
@ stdcall DnsQuery_UTF8(str long long ptr ptr ptr) DnsQuery_UTF8
@ stdcall DnsQuery_W(wstr long long ptr ptr ptr) DnsQuery_W
@ stub DnsRecordBuild_UTF8
@ stub DnsRecordBuild_W
@ stdcall DnsRecordCompare(ptr ptr) DnsRecordCompare
@ stdcall DnsRecordCopyEx(ptr long long) DnsRecordCopyEx
@ stdcall DnsRecordListFree(ptr long) DnsRecordListFree
@ stdcall DnsRecordSetCompare(ptr ptr ptr ptr) DnsRecordSetCompare
@ stdcall DnsRecordSetCopyEx(ptr long long) DnsRecordSetCopyEx
@ stdcall DnsRecordSetDetach(ptr) DnsRecordSetDetach
@ stub DnsRecordStringForType
@ stub DnsRecordStringForWritableType
@ stub DnsRecordTypeForName
@ stub DnsRelationalCompare_UTF8
@ stub DnsRelationalCompare_W
@ stdcall DnsReleaseContextHandle(ptr) DnsReleaseContextHandle
@ stub DnsRemoveRegistrations
@ stdcall DnsReplaceRecordSetA(ptr long ptr ptr ptr) DnsReplaceRecordSetA
@ stub DnsReplaceRecordSet_A
@ stdcall DnsReplaceRecordSetUTF8(ptr long ptr ptr ptr) DnsReplaceRecordSetUTF8
@ stub DnsReplaceRecordSet_UTF8
@ stdcall DnsReplaceRecordSetW(ptr long ptr ptr ptr) DnsReplaceRecordSetW
@ stub DnsReplaceRecordSet_W
@ stub DnsServiceNotificationDeregister_A
@ stub DnsServiceNotificationDeregister_UTF8
@ stub DnsServiceNotificationDeregister_W
@ stub DnsServiceNotificationRegister_A
@ stub DnsServiceNotificationRegister_UTF8
@ stub DnsServiceNotificationRegister_W
@ stub DnsSetMaxNumberOfAddressesToRegister
@ stub DnsStatusString
@ stub DnsStringCopyAllocateEx
@ stub DnsUnicodeToUtf8
@ stub DnsUpdate
@ stub DnsUpdateTest_A
@ stub DnsUpdateTest_UTF8
@ stub DnsUpdateTest_W
@ stub DnsUtf8ToUnicode
@ stdcall DnsValidateName_A(str long) DnsValidateName_A
@ stdcall DnsValidateName_UTF8(str long) DnsValidateName_UTF8
@ stdcall DnsValidateName_W(wstr long) DnsValidateName_W
@ stub DnsValidateUtf8Byte
@ stub DnsWinsRecordFlagForString
@ stub DnsWinsRecordFlagString
@ stdcall DnsWriteQuestionToBuffer_UTF8(ptr ptr str long long long) DnsWriteQuestionToBuffer_UTF8
@ stdcall DnsWriteQuestionToBuffer_W(ptr ptr wstr long long long) DnsWriteQuestionToBuffer_W
@ stub DnsWriteReverseNameStringForIpAddress
@ stub GetCurrentTimeInSeconds
--- NEW FILE: main.c ---
/*
* DNS support
*
* Copyright (C) 2006 Matthew Kehrer
* Copyright (C) 2006 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine-lgpl/windns.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
static HINSTANCE hdnsapi;
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
{
TRACE( "(%p, %d, %p)\n", hinst, reason, reserved );
switch (reason)
{
#if 0
case DLL_WINE_PREATTACH:
return FALSE; /* prefer native version */
#endif
case DLL_PROCESS_ATTACH:
hdnsapi = hinst;
DisableThreadLibraryCalls( hinst );
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
/******************************************************************************
* DnsAcquireContextHandle_A [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsAcquireContextHandle_A( DWORD flags, PVOID cred,
PHANDLE context )
{
FIXME( "(0x%08x,%p,%p) stub\n", flags, cred, context );
*context = (HANDLE)0xdeadbeef;
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsAcquireContextHandle_UTF8 [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsAcquireContextHandle_UTF8( DWORD flags, PVOID cred,
PHANDLE context )
{
FIXME( "(0x%08x,%p,%p) stub\n", flags, cred, context );
*context = (HANDLE)0xdeadbeef;
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsAcquireContextHandle_W [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsAcquireContextHandle_W( DWORD flags, PVOID cred,
PHANDLE context )
{
FIXME( "(0x%08x,%p,%p) stub\n", flags, cred, context );
*context = (HANDLE)0xdeadbeef;
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsReleaseContextHandle [DNSAPI.@]
*
*/
VOID WINAPI DnsReleaseContextHandle( HANDLE context )
{
FIXME( "(%p) stub\n", context );
}
/******************************************************************************
* DnsExtractRecordsFromMessage_UTF8 [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsExtractRecordsFromMessage_UTF8( PDNS_MESSAGE_BUFFER buffer,
WORD len, PDNS_RECORDA *record )
{
FIXME( "(%p,%d,%p) stub\n", buffer, len, record );
*record = NULL;
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsExtractRecordsFromMessage_W [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsExtractRecordsFromMessage_W( PDNS_MESSAGE_BUFFER buffer,
WORD len, PDNS_RECORDW *record )
{
FIXME( "(%p,%d,%p) stub\n", buffer, len, record );
*record = NULL;
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsModifyRecordsInSet_A [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsModifyRecordsInSet_A( PDNS_RECORDA add, PDNS_RECORDA delete,
DWORD options, HANDLE context,
PVOID servers, PVOID reserved )
{
FIXME( "(%p,%p,0x%08x,%p,%p,%p) stub\n", add, delete, options,
context, servers, reserved );
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsModifyRecordsInSet_UTF8 [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsModifyRecordsInSet_UTF8( PDNS_RECORDA add, PDNS_RECORDA delete,
DWORD options, HANDLE context,
PVOID servers, PVOID reserved )
{
FIXME( "(%p,%p,0x%08x,%p,%p,%p) stub\n", add, delete, options,
context, servers, reserved );
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsModifyRecordsInSet_W [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsModifyRecordsInSet_W( PDNS_RECORDW add, PDNS_RECORDW delete,
DWORD options, HANDLE context,
PVOID servers, PVOID reserved )
{
FIXME( "(%p,%p,0x%08x,%p,%p,%p) stub\n", add, delete, options,
context, servers, reserved );
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsWriteQuestionToBuffer_UTF8 [DNSAPI.@]
*
*/
BOOL WINAPI DnsWriteQuestionToBuffer_UTF8( PDNS_MESSAGE_BUFFER buffer, PDWORD size,
PCSTR name, WORD type, WORD xid,
BOOL recurse )
{
FIXME( "(%p,%p,%s,%d,%d,%d) stub\n", buffer, size, debugstr_a(name),
type, xid, recurse );
return FALSE;
}
/******************************************************************************
* DnsWriteQuestionToBuffer_W [DNSAPI.@]
*
*/
BOOL WINAPI DnsWriteQuestionToBuffer_W( PDNS_MESSAGE_BUFFER buffer, PDWORD size,
PCWSTR name, WORD type, WORD xid,
BOOL recurse )
{
FIXME( "(%p,%p,%s,%d,%d,%d) stub\n", buffer, size, debugstr_w(name),
type, xid, recurse );
return FALSE;
}
/******************************************************************************
* DnsReplaceRecordSetA [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsReplaceRecordSetA( PDNS_RECORDA set, DWORD options,
HANDLE context, PVOID servers,
PVOID reserved )
{
FIXME( "(%p,0x%08x,%p,%p,%p) stub\n", set, options, context,
servers, reserved );
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsReplaceRecordSetUTF8 [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsReplaceRecordSetUTF8( PDNS_RECORDA set, DWORD options,
HANDLE context, PVOID servers,
PVOID reserved )
{
FIXME( "(%p,0x%08x,%p,%p,%p) stub\n", set, options, context,
servers, reserved );
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsReplaceRecordSetW [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsReplaceRecordSetW( PDNS_RECORDW set, DWORD options,
HANDLE context, PVOID servers,
PVOID reserved )
{
FIXME( "(%p,0x%08x,%p,%p,%p) stub\n", set, options, context,
servers, reserved );
return ERROR_SUCCESS;
}
--- NEW FILE: Makefile.in ---
EXTRADEFS = -D__WINESRC__ -DSTRICT
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = dnsapi
EXTRALIBS = @LIBRESOLV@
LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
C_SRCS = \
main.c \
name.c \
ns_name.c \
ns_parse.c \
query.c \
record.c
@MAKE_DLL_RULES@
### Dependencies:
--- NEW FILE: name.c ---
/*
* DNS support
*
* Copyright (C) 2006 Matthew Kehrer
* Copyright (C) 2006 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include <stdarg.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
# undef NOERROR
#endif
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
#include "wine-lgpl/windns.h"
#include "dnsapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
/******************************************************************************
* DnsNameCompare_A [DNSAPI.@]
*
*/
BOOL WINAPI DnsNameCompare_A( PCSTR name1, PCSTR name2 )
{
BOOL ret;
PWSTR name1W, name2W;
TRACE( "(%s,%s)\n", debugstr_a(name1), debugstr_a(name2) );
name1W = dns_strdup_aw( name1 );
name2W = dns_strdup_aw( name2 );
ret = DnsNameCompare_W( name1W, name2W );
dns_free( name1W );
dns_free( name2W );
return ret;
}
/******************************************************************************
* DnsNameCompare_W [DNSAPI.@]
*
*/
BOOL WINAPI DnsNameCompare_W( PCWSTR name1, PCWSTR name2 )
{
PCWSTR p, q;
TRACE( "(%s,%s)\n", debugstr_w(name1), debugstr_w(name2) );
if (!name1 && !name2) return TRUE;
if (!name1 || !name2) return FALSE;
p = name1 + lstrlenW( name1 ) - 1;
q = name2 + lstrlenW( name2 ) - 1;
while (*p == '.' && p >= name1) p--;
while (*q == '.' && q >= name2) q--;
if (p - name1 != q - name2) return FALSE;
while (name1 <= p)
{
if (toupperW( *name1 ) != toupperW( *name2 ))
return FALSE;
name1++;
name2++;
}
return TRUE;
}
/******************************************************************************
* DnsValidateName_A [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsValidateName_A( PCSTR name, DNS_NAME_FORMAT format )
{
PWSTR nameW;
DNS_STATUS ret;
TRACE( "(%s, %d)\n", debugstr_a(name), format );
nameW = dns_strdup_aw( name );
ret = DnsValidateName_W( nameW, format );
dns_free( nameW );
return ret;
}
/******************************************************************************
* DnsValidateName_UTF8 [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsValidateName_UTF8( PCSTR name, DNS_NAME_FORMAT format )
{
PWSTR nameW;
DNS_STATUS ret;
TRACE( "(%s, %d)\n", debugstr_a(name), format );
nameW = dns_strdup_uw( name );
ret = DnsValidateName_W( nameW, format );
dns_free( nameW );
return ret;
}
#define HAS_EXTENDED 0x0001
#define HAS_NUMERIC 0x0002
#define HAS_NON_NUMERIC 0x0004
#define HAS_DOT 0x0008
#define HAS_DOT_DOT 0x0010
#define HAS_SPACE 0x0020
#define HAS_INVALID 0x0040
#define HAS_ASTERISK 0x0080
#define HAS_UNDERSCORE 0x0100
#define HAS_LONG_LABEL 0x0200
/******************************************************************************
* DnsValidateName_W [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsValidateName_W( PCWSTR name, DNS_NAME_FORMAT format )
{
PCWSTR p;
unsigned int i, j, state = 0;
static const WCHAR invalid[] = {
'{','|','}','~','[','\\',']','^','\'',':',';','<','=','>',
'?','@','!','\"','#','$','%','^','`','(',')','+','/',',',0 };
TRACE( "(%s, %d)\n", debugstr_w(name), format );
if (!name) return ERROR_INVALID_NAME;
for (p = name, i = 0, j = 0; *p; p++, i++, j++)
{
if (*p == '.')
{
j = 0;
state |= HAS_DOT;
if (p[1] == '.') state |= HAS_DOT_DOT;
}
else if (*p < '0' || *p > '9') state |= HAS_NON_NUMERIC;
else state |= HAS_NUMERIC;
if (j > 62) state |= HAS_LONG_LABEL;
if (strchrW( invalid, *p )) state |= HAS_INVALID;
else if ((unsigned)*p > 127) state |= HAS_EXTENDED;
else if (*p == ' ') state |= HAS_SPACE;
else if (*p == '_') state |= HAS_UNDERSCORE;
else if (*p == '*') state |= HAS_ASTERISK;
}
if (i == 0 || i > 255 ||
(state & HAS_LONG_LABEL) ||
(state & HAS_DOT_DOT) ||
(name[0] == '.' && name[1])) return ERROR_INVALID_NAME;
switch (format)
{
case DnsNameDomain:
{
if (!(state & HAS_NON_NUMERIC) && (state & HAS_NUMERIC))
return DNS_ERROR_NUMERIC_NAME;
if ((state & HAS_EXTENDED) || (state & HAS_UNDERSCORE))
return DNS_ERROR_NON_RFC_NAME;
if ((state & HAS_SPACE) ||
(state & HAS_INVALID) ||
(state & HAS_ASTERISK)) return DNS_ERROR_INVALID_NAME_CHAR;
break;
}
case DnsNameDomainLabel:
{
if (state & HAS_DOT) return ERROR_INVALID_NAME;
if ((state & HAS_EXTENDED) || (state & HAS_UNDERSCORE))
return DNS_ERROR_NON_RFC_NAME;
if ((state & HAS_SPACE) ||
(state & HAS_INVALID) ||
(state & HAS_ASTERISK)) return DNS_ERROR_INVALID_NAME_CHAR;
break;
}
case DnsNameHostnameFull:
{
if (!(state & HAS_NON_NUMERIC) && (state & HAS_NUMERIC))
return DNS_ERROR_NUMERIC_NAME;
if ((state & HAS_EXTENDED) || (state & HAS_UNDERSCORE))
return DNS_ERROR_NON_RFC_NAME;
if ((state & HAS_SPACE) ||
(state & HAS_INVALID) ||
(state & HAS_ASTERISK)) return DNS_ERROR_INVALID_NAME_CHAR;
break;
}
case DnsNameHostnameLabel:
{
if (state & HAS_DOT) return ERROR_INVALID_NAME;
if (!(state & HAS_NON_NUMERIC) && (state & HAS_NUMERIC))
return DNS_ERROR_NUMERIC_NAME;
if ((state & HAS_EXTENDED) || (state & HAS_UNDERSCORE))
return DNS_ERROR_NON_RFC_NAME;
if ((state & HAS_SPACE) ||
(state & HAS_INVALID) ||
(state & HAS_ASTERISK)) return DNS_ERROR_INVALID_NAME_CHAR;
break;
}
case DnsNameWildcard:
{
if (!(state & HAS_NON_NUMERIC) && (state & HAS_NUMERIC))
return ERROR_INVALID_NAME;
if (name[0] != '*') return ERROR_INVALID_NAME;
if (name[1] && name[1] != '.')
return DNS_ERROR_INVALID_NAME_CHAR;
if ((state & HAS_EXTENDED) ||
(state & HAS_SPACE) ||
(state & HAS_INVALID)) return ERROR_INVALID_NAME;
break;
}
case DnsNameSrvRecord:
{
if (!(state & HAS_NON_NUMERIC) && (state & HAS_NUMERIC))
return ERROR_INVALID_NAME;
if (name[0] != '_') return ERROR_INVALID_NAME;
if ((state & HAS_UNDERSCORE) && !name[1])
return DNS_ERROR_NON_RFC_NAME;
if ((state & HAS_EXTENDED) ||
(state & HAS_SPACE) ||
(state & HAS_INVALID)) return ERROR_INVALID_NAME;
break;
}
default:
WARN( "unknown format: %d\n", format );
break;
}
return ERROR_SUCCESS;
}
--- NEW FILE: ns_name.c ---
/*
* Copyright (c) 1996,1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include "config.h"
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
#include <ctype.h>
#include <errno.h>
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#include <string.h>
#include <ctype.h>
/* Data. */
static const char digits[] = "0123456789";
/* Forward. */
static int special(int);
static int printable(int);
/* Public. */
/*
* dns_ns_name_ntop(src, dst, dstsiz)
* Convert an encoded domain name to printable ascii as per RFC1035.
* return:
* Number of bytes written to buffer, or -1 (with errno set)
* notes:
* The root is returned as "."
* All other domains are returned in non absolute form
*/
static int
dns_ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
const u_char *cp;
char *dn, *eom;
u_char c;
u_int n;
cp = src;
dn = dst;
eom = dst + dstsiz;
while ((n = *cp++) != 0) {
if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) {
/* Some kind of compression pointer. */
return (-1);
}
if (dn != dst) {
if (dn >= eom) {
return (-1);
}
*dn++ = '.';
}
if (n == 0x41) {
n = *cp++ / 8;
if (dn + n * 2 + 4 >= eom) {
return (-1);
}
*dn++ = '\\';
*dn++ = '[';
*dn++ = 'x';
while (n-- > 0) {
unsigned u;
c = *cp++;
u = c >> 4;
*dn++ = u > 9 ? 'a' + u - 10 : '0' + u;
u = c & 0xf;
*dn++ = u > 9 ? 'a' + u - 10 : '0' + u;
}
*dn++ = ']';
continue;
}
if (dn + n >= eom) {
return (-1);
}
for ((void)NULL; n > 0; n--) {
c = *cp++;
if (special(c)) {
if (dn + 1 >= eom) {
return (-1);
}
*dn++ = '\\';
*dn++ = (char)c;
} else if (!printable(c)) {
if (dn + 3 >= eom) {
return (-1);
}
*dn++ = '\\';
*dn++ = digits[c / 100];
*dn++ = digits[(c % 100) / 10];
*dn++ = digits[c % 10];
} else {
if (dn >= eom) {
return (-1);
}
*dn++ = (char)c;
}
}
}
if (dn == dst) {
if (dn >= eom) {
return (-1);
}
*dn++ = '.';
}
if (dn >= eom) {
return (-1);
}
*dn++ = '\0';
return (dn - dst);
}
/*
* dns_ns_name_pton(src, dst, dstsiz)
* Convert a ascii string into an encoded domain name as per RFC1035.
* return:
* -1 if it fails
* 1 if string was fully qualified
* 0 is string was not fully qualified
* notes:
* Enforces label and domain length limits.
*/
int
dns_ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
u_char *label, *bp, *eom;
int c, n, escaped;
char *cp;
escaped = 0;
bp = dst;
eom = dst + dstsiz;
label = bp++;
while ((c = *src++) != 0) {
if (escaped) {
if ((cp = strchr(digits, c)) != NULL) {
n = (cp - digits) * 100;
if ((c = *src++) == 0 ||
(cp = strchr(digits, c)) == NULL) {
return (-1);
}
n += (cp - digits) * 10;
if ((c = *src++) == 0 ||
(cp = strchr(digits, c)) == NULL) {
return (-1);
}
n += (cp - digits);
if (n > 255) {
return (-1);
}
c = n;
} else if (c == '[' && label == bp - 1 && *src == 'x') {
/* Theoretically we would have to handle \[o
as well but we do not since we do not need
it internally. */
*label = 0x41;
label = bp++;
++src;
while (isxdigit (*src)) {
n = *src > '9' ? *src - 'a' + 10 : *src - '0';
++src;
if (! isxdigit(*src)) {
return (-1);
}
n <<= 4;
n += *src > '9' ? *src - 'a' + 10 : *src - '0';
if (bp + 1 >= eom) {
return (-1);
}
*bp++ = n;
++src;
}
*label = (bp - label - 1) * 8;
if (*src++ != ']' || *src++ != '.') {
return (-1);
}
escaped = 0;
label = bp++;
if (bp >= eom) {
return (-1);
}
continue;
}
escaped = 0;
} else if (c == '\\') {
escaped = 1;
continue;
} else if (c == '.') {
c = (bp - label - 1);
if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
return (-1);
}
if (label >= eom) {
return (-1);
}
*label = c;
/* Fully qualified ? */
if (*src == '\0') {
if (c != 0) {
if (bp >= eom) {
return (-1);
}
*bp++ = '\0';
}
if ((bp - dst) > NS_MAXCDNAME) {
return (-1);
}
return (1);
}
if (c == 0 || *src == '.') {
return (-1);
}
label = bp++;
continue;
}
if (bp >= eom) {
return (-1);
}
*bp++ = (u_char)c;
}
c = (bp - label - 1);
if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
return (-1);
}
if (label >= eom) {
return (-1);
}
*label = c;
if (c != 0) {
if (bp >= eom) {
return (-1);
}
*bp++ = 0;
}
if ((bp - dst) > NS_MAXCDNAME) { /* src too big */
return (-1);
}
return (0);
}
/*
* dns_ns_name_unpack(msg, eom, src, dst, dstsiz)
* Unpack a domain name from a message, source may be compressed.
* return:
* -1 if it fails, or consumed octets if it succeeds.
*/
static int
dns_ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
u_char *dst, size_t dstsiz)
{
const u_char *srcp, *dstlim;
u_char *dstp;
int n, len, checked;
len = -1;
checked = 0;
dstp = dst;
srcp = src;
dstlim = dst + dstsiz;
if (srcp < msg || srcp >= eom) {
return (-1);
}
/* Fetch next label in domain name. */
while ((n = *srcp++) != 0) {
/* Check for indirection. */
switch (n & NS_CMPRSFLGS) {
case 0x40:
if (n == 0x41) {
if (dstp + 1 >= dstlim) {
return (-1);
}
*dstp++ = 0x41;
n = *srcp++ / 8;
++checked;
} else {
return (-1); /* flag error */
}
/* FALLTHROUGH */
case 0:
/* Limit checks. */
if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
return (-1);
}
checked += n + 1;
dstp = memcpy(dstp, srcp - 1, n + 1);
dstp += n + 1;
srcp += n;
break;
case NS_CMPRSFLGS:
if (srcp >= eom) {
return (-1);
}
if (len < 0)
len = srcp - src + 1;
srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
if (srcp < msg || srcp >= eom) { /* Out of range. */
return (-1);
}
checked += 2;
/*
* Check for loops in the compressed name;
* if we've looked at the whole message,
* there must be a loop.
*/
if (checked >= eom - msg) {
return (-1);
}
break;
default:
return (-1); /* flag error */
}
}
*dstp = '\0';
if (len < 0)
len = srcp - src;
return (len);
}
/*
* dns_ns_name_uncompress(msg, eom, src, dst, dstsiz)
* Expand compressed domain name to presentation format.
* return:
* Number of bytes read out of `src', or -1 (with errno set).
* note:
* Root domain returns as "." not "".
*/
int
dns_ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
char *dst, size_t dstsiz)
{
u_char tmp[NS_MAXCDNAME];
int n;
if ((n = dns_ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
return (-1);
if (dns_ns_name_ntop(tmp, dst, dstsiz) == -1)
return (-1);
return (n);
}
/*
* dns_ns_name_skip(ptrptr, eom)
* Advance *ptrptr to skip over the compressed name it points at.
* return:
* 0 on success, -1 (with errno set) on failure.
*/
int
dns_ns_name_skip(const u_char **ptrptr, const u_char *eom) {
const u_char *cp;
u_int n;
cp = *ptrptr;
while (cp < eom && (n = *cp++) != 0) {
/* Check for indirection. */
switch (n & NS_CMPRSFLGS) {
case 0: /* normal case, n == len */
cp += n;
continue;
case NS_CMPRSFLGS: /* indirection */
cp++;
break;
default: /* illegal type */
return (-1);
}
break;
}
if (cp > eom) {
return (-1);
}
*ptrptr = cp;
return (0);
}
/* Private. */
/*
* special(ch)
* Thinking in noninternationalized USASCII (per the DNS spec),
* is this characted special ("in need of quoting") ?
* return:
* boolean.
*/
static int
special(int ch) {
switch (ch) {
case 0x22: /* '"' */
case 0x2E: /* '.' */
case 0x3B: /* ';' */
case 0x5C: /* '\\' */
/* Special modifiers in zone files. */
case 0x40: /* '@' */
case 0x24: /* '$' */
return (1);
default:
return (0);
}
}
/*
* printable(ch)
* Thinking in noninternationalized USASCII (per the DNS spec),
* is this character visible and not a space when printed ?
* return:
* boolean.
*/
static int
printable(int ch) {
return (ch > 0x20 && ch < 0x7f);
}
--- NEW FILE: ns_parse.c ---
/*
* Copyright (c) 1996,1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include "config.h"
#ifdef HAVE_RESOLV
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
#include <errno.h>
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#include <string.h>
#include "windef.h"
/* Forward. */
static void setsection(ns_msg *msg, ns_sect sect);
/* Macros. */
#define RETERR(err) do { return (-1); } while (0)
#ifdef HAVE_NS_MSG__MSG_PTR
# define NS_PTR(ns_msg) ((ns_msg)->_msg_ptr)
#else
# define NS_PTR(ns_msg) ((ns_msg)->_ptr)
#endif
#define DNS_NS_GET16(s, cp) do { \
register const u_char *t_cp = (const u_char *)(cp); \
(s) = ((WORD)t_cp[0] << 8) \
| ((WORD)t_cp[1]) \
; \
(cp) += NS_INT16SZ; \
} while (0)
#define DNS_NS_GET32(l, cp) do { \
register const u_char *t_cp = (const u_char *)(cp); \
(l) = ((DWORD)t_cp[0] << 24) \
| ((DWORD)t_cp[1] << 16) \
| ((DWORD)t_cp[2] << 8) \
| ((DWORD)t_cp[3]) \
; \
(cp) += NS_INT32SZ; \
} while (0)
/* Public. */
static int
dns_ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
const u_char *optr = ptr;
for ((void)NULL; count > 0; count--) {
int b, rdlength;
b = dn_skipname(ptr, eom);
if (b < 0)
RETERR(EMSGSIZE);
ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
if (section != ns_s_qd) {
if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
RETERR(EMSGSIZE);
ptr += NS_INT32SZ/*TTL*/;
DNS_NS_GET16(rdlength, ptr);
ptr += rdlength/*RData*/;
}
}
if (ptr > eom)
RETERR(EMSGSIZE);
return (ptr - optr);
}
int
dns_ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
const u_char *eom = msg + msglen;
int i;
memset(handle, 0x5e, sizeof *handle);
handle->_msg = msg;
handle->_eom = eom;
if (msg + NS_INT16SZ > eom)
RETERR(EMSGSIZE);
DNS_NS_GET16(handle->_id, msg);
if (msg + NS_INT16SZ > eom)
RETERR(EMSGSIZE);
DNS_NS_GET16(handle->_flags, msg);
for (i = 0; i < ns_s_max; i++) {
if (msg + NS_INT16SZ > eom)
RETERR(EMSGSIZE);
DNS_NS_GET16(handle->_counts[i], msg);
}
for (i = 0; i < ns_s_max; i++)
if (handle->_counts[i] == 0)
handle->_sections[i] = NULL;
else {
int b = dns_ns_skiprr(msg, eom, (ns_sect)i,
handle->_counts[i]);
if (b < 0)
return (-1);
handle->_sections[i] = msg;
msg += b;
}
if (msg != eom)
RETERR(EMSGSIZE);
setsection(handle, ns_s_max);
return (0);
}
int
dns_ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
int b;
/* Make section right. */
if (section < 0 || section >= ns_s_max)
RETERR(ENODEV);
if (section != handle->_sect)
setsection(handle, section);
/* Make rrnum right. */
if (rrnum == -1)
rrnum = handle->_rrnum;
if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
RETERR(ENODEV);
if (rrnum < handle->_rrnum)
setsection(handle, section);
if (rrnum > handle->_rrnum) {
b = dns_ns_skiprr(NS_PTR(handle), handle->_eom, section,
rrnum - handle->_rrnum);
if (b < 0)
return (-1);
NS_PTR(handle) += b;
handle->_rrnum = rrnum;
}
/* Do the parse. */
b = dn_expand(handle->_msg, handle->_eom,
NS_PTR(handle), rr->name, NS_MAXDNAME);
if (b < 0)
return (-1);
NS_PTR(handle) += b;
if (NS_PTR(handle) + NS_INT16SZ + NS_INT16SZ > handle->_eom)
RETERR(EMSGSIZE);
DNS_NS_GET16(rr->type, NS_PTR(handle));
DNS_NS_GET16(rr->rr_class, NS_PTR(handle));
if (section == ns_s_qd) {
rr->ttl = 0;
rr->rdlength = 0;
rr->rdata = NULL;
} else {
if (NS_PTR(handle) + NS_INT32SZ + NS_INT16SZ > handle->_eom)
RETERR(EMSGSIZE);
DNS_NS_GET32(rr->ttl, NS_PTR(handle));
DNS_NS_GET16(rr->rdlength, NS_PTR(handle));
if (NS_PTR(handle) + rr->rdlength > handle->_eom)
RETERR(EMSGSIZE);
rr->rdata = NS_PTR(handle);
NS_PTR(handle) += rr->rdlength;
}
if (++handle->_rrnum > handle->_counts[(int)section])
setsection(handle, (ns_sect)((int)section + 1));
/* All done. */
return (0);
}
/* Private. */
static void
setsection(ns_msg *msg, ns_sect sect) {
msg->_sect = sect;
if (sect == ns_s_max) {
msg->_rrnum = -1;
NS_PTR(msg) = NULL;
} else {
msg->_rrnum = 0;
NS_PTR(msg) = msg->_sections[(int)sect];
}
}
#endif
--- NEW FILE: query.c ---
/*
* DNS support
*
* Copyright (C) 2006 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include "wine/debug.h"
#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
#include "wine-lgpl/windns.h"
#include "nb30.h"
#include "dnsapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
#ifdef HAVE_RESOLV
static CRITICAL_SECTION resolver_cs;
static CRITICAL_SECTION_DEBUG resolver_cs_debug =
{
0, 0, &resolver_cs,
{ &resolver_cs_debug.ProcessLocksList,
&resolver_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": resolver_cs") }
};
static CRITICAL_SECTION resolver_cs = { &resolver_cs_debug, -1, 0, 0, 0, 0 };
#define LOCK_RESOLVER() do { EnterCriticalSection( &resolver_cs ); } while (0)
#define UNLOCK_RESOLVER() do { LeaveCriticalSection( &resolver_cs ); } while (0)
static int resolver_initialised;
/* call res_init() just once because of a bug in Mac OS X 10.4 */
static void initialise_resolver( void )
{
if (!resolver_initialised)
{
res_init();
resolver_initialised = 1;
}
}
static const char *dns_section_to_str( ns_sect section )
{
switch (section)
{
case ns_s_qd: return "Question";
case ns_s_an: return "Answer";
case ns_s_ns: return "Authority";
case ns_s_ar: return "Additional";
default:
{
static char tmp[5];
FIXME( "unknown section: 0x%02x\n", section );
sprintf( tmp, "0x%02x", section );
return tmp;
}
}
}
static unsigned long dns_map_options( DWORD options )
{
unsigned long ret = 0;
if (options == DNS_QUERY_STANDARD)
return RES_DEFAULT;
if (options & DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE)
ret |= RES_IGNTC;
if (options & DNS_QUERY_USE_TCP_ONLY)
ret |= RES_USEVC;
if (options & DNS_QUERY_NO_RECURSION)
ret &= ~RES_RECURSE;
if (options & DNS_QUERY_NO_LOCAL_NAME)
ret &= ~RES_DNSRCH;
if (options & DNS_QUERY_NO_HOSTS_FILE)
ret |= RES_NOALIASES;
if (options & DNS_QUERY_TREAT_AS_FQDN)
ret &= ~RES_DEFNAMES;
if (options & DNS_QUERY_DONT_RESET_TTL_VALUES)
FIXME( "option DNS_QUERY_DONT_RESET_TTL_VALUES not implemented\n" );
if (options & DNS_QUERY_RESERVED)
FIXME( "option DNS_QUERY_RESERVED not implemented\n" );
if (options & DNS_QUERY_WIRE_ONLY)
FIXME( "option DNS_QUERY_WIRE_ONLY not implemented\n" );
if (options & DNS_QUERY_NO_WIRE_QUERY)
FIXME( "option DNS_QUERY_NO_WIRE_QUERY not implemented\n" );
if (options & DNS_QUERY_BYPASS_CACHE)
FIXME( "option DNS_QUERY_BYPASS_CACHE not implemented\n" );
if (options & DNS_QUERY_RETURN_MESSAGE)
FIXME( "option DNS_QUERY_RETURN_MESSAGE not implemented\n" );
if (options & DNS_QUERY_NO_NETBT)
TRACE( "netbios query disabled\n" );
return ret;
}
static DNS_STATUS dns_map_error( int error )
{
switch (error)
{
case ns_r_noerror: return ERROR_SUCCESS;
case ns_r_formerr: return DNS_ERROR_RCODE_FORMAT_ERROR;
case ns_r_servfail: return DNS_ERROR_RCODE_SERVER_FAILURE;
case ns_r_nxdomain: return DNS_ERROR_RCODE_NAME_ERROR;
case ns_r_notimpl: return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
case ns_r_refused: return DNS_ERROR_RCODE_REFUSED;
case ns_r_yxdomain: return DNS_ERROR_RCODE_YXDOMAIN;
case ns_r_yxrrset: return DNS_ERROR_RCODE_YXRRSET;
case ns_r_nxrrset: return DNS_ERROR_RCODE_NXRRSET;
case ns_r_notauth: return DNS_ERROR_RCODE_NOTAUTH;
case ns_r_notzone: return DNS_ERROR_RCODE_NOTZONE;
default:
FIXME( "unmapped error code: %d\n", error );
return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
}
}
static DNS_STATUS dns_map_h_errno( int error )
{
switch (error)
{
case NO_DATA:
case HOST_NOT_FOUND: return DNS_ERROR_RCODE_NAME_ERROR;
case TRY_AGAIN: return DNS_ERROR_RCODE_SERVER_FAILURE;
case NO_RECOVERY: return DNS_ERROR_RCODE_REFUSED;
case NETDB_INTERNAL: return DNS_ERROR_RCODE;
default:
FIXME( "unmapped error code: %d\n", error );
return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
}
}
static char *dns_dname_from_msg( ns_msg msg, const unsigned char *pos )
{
int len;
char *str, dname[NS_MAXDNAME] = ".";
/* returns *compressed* length, ignore it */
len = dns_ns_name_uncompress( ns_msg_base( msg ), ns_msg_end( msg ),
pos, dname, sizeof(dname) );
len = strlen( dname );
str = dns_alloc( len + 1 );
if (str) strcpy( str, dname );
return str;
}
static char *dns_str_from_rdata( const unsigned char *rdata )
{
char *str;
unsigned int len = rdata[0];
str = dns_alloc( len + 1 );
if (str)
{
memcpy( str, ++rdata, len );
str[len] = '\0';
}
return str;
}
static unsigned int dns_get_record_size( const ns_rr *rr )
{
const unsigned char *pos = rr->rdata;
unsigned int num = 0, size = sizeof(DNS_RECORDA);
switch (rr->type)
{
case ns_t_key:
{
pos += sizeof(WORD) + sizeof(BYTE) + sizeof(BYTE);
size += rr->rdata + rr->rdlength - pos - 1;
break;
}
case ns_t_sig:
{
pos += sizeof(PCHAR) + sizeof(WORD) + 2 * sizeof(BYTE);
pos += 3 * sizeof(DWORD) + 2 * sizeof(WORD);
size += rr->rdata + rr->rdlength - pos - 1;
break;
}
case ns_t_hinfo:
case ns_t_isdn:
case ns_t_txt:
case ns_t_x25:
{
while (pos[0] && pos < rr->rdata + rr->rdlength)
{
num++;
pos += pos[0] + 1;
}
size += (num - 1) * sizeof(PCHAR);
break;
}
case ns_t_null:
{
size += rr->rdlength - 1;
break;
}
case ns_t_nxt:
case ns_t_wks:
case 0xff01: /* WINS */
{
FIXME( "unhandled type: %s\n", dns_type_to_str( rr->type ) );
break;
}
default:
break;
}
return size;
}
static DNS_STATUS dns_copy_rdata( ns_msg msg, const ns_rr *rr, DNS_RECORDA *r, WORD *dlen )
{
DNS_STATUS ret = ERROR_SUCCESS;
const unsigned char *pos = rr->rdata;
unsigned int i, size;
switch (rr->type)
{
case ns_t_a:
{
r->Data.A.IpAddress = *(const DWORD *)pos;
*dlen = sizeof(DNS_A_DATA);
break;
}
case ns_t_aaaa:
{
for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
{
r->Data.AAAA.Ip6Address.IP6Dword[i] = *(const DWORD *)pos;
pos += sizeof(DWORD);
}
*dlen = sizeof(DNS_AAAA_DATA);
break;
}
case ns_t_key:
{
/* FIXME: byte order? */
r->Data.KEY.wFlags = *(const WORD *)pos; pos += sizeof(WORD);
r->Data.KEY.chProtocol = *(const BYTE *)pos++;
r->Data.KEY.chAlgorithm = *(const BYTE *)pos++;
size = rr->rdata + rr->rdlength - pos;
for (i = 0; i < size; i++)
r->Data.KEY.Key[i] = *(const BYTE *)pos++;
*dlen = sizeof(DNS_KEY_DATA) + (size - 1) * sizeof(BYTE);
break;
}
case ns_t_rp:
case ns_t_minfo:
{
r->Data.MINFO.pNameMailbox = dns_dname_from_msg( msg, pos );
if (!r->Data.MINFO.pNameMailbox) return ERROR_NOT_ENOUGH_MEMORY;
if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
return DNS_ERROR_BAD_PACKET;
r->Data.MINFO.pNameErrorsMailbox = dns_dname_from_msg( msg, pos );
if (!r->Data.MINFO.pNameErrorsMailbox)
{
dns_free( r->Data.MINFO.pNameMailbox );
return ERROR_NOT_ENOUGH_MEMORY;
}
*dlen = sizeof(DNS_MINFO_DATAA);
break;
}
case ns_t_afsdb:
case ns_t_rt:
case ns_t_mx:
{
r->Data.MX.wPreference = ntohs( *(const WORD *)pos );
r->Data.MX.pNameExchange = dns_dname_from_msg( msg, pos + sizeof(WORD) );
if (!r->Data.MX.pNameExchange) return ERROR_NOT_ENOUGH_MEMORY;
*dlen = sizeof(DNS_MX_DATAA);
break;
}
case ns_t_null:
{
r->Data.Null.dwByteCount = rr->rdlength;
memcpy( r->Data.Null.Data, rr->rdata, rr->rdlength );
*dlen = sizeof(DNS_NULL_DATA) + rr->rdlength - 1;
break;
}
case ns_t_cname:
case ns_t_ns:
case ns_t_mb:
case ns_t_md:
case ns_t_mf:
case ns_t_mg:
case ns_t_mr:
case ns_t_ptr:
{
r->Data.PTR.pNameHost = dns_dname_from_msg( msg, pos );
if (!r->Data.PTR.pNameHost) return ERROR_NOT_ENOUGH_MEMORY;
*dlen = sizeof(DNS_PTR_DATAA);
break;
}
case ns_t_sig:
{
r->Data.SIG.pNameSigner = dns_dname_from_msg( msg, pos );
if (!r->Data.SIG.pNameSigner) return ERROR_NOT_ENOUGH_MEMORY;
if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
return DNS_ERROR_BAD_PACKET;
/* FIXME: byte order? */
r->Data.SIG.wTypeCovered = *(const WORD *)pos; pos += sizeof(WORD);
r->Data.SIG.chAlgorithm = *(const BYTE *)pos++;
r->Data.SIG.chLabelCount = *(const BYTE *)pos++;
r->Data.SIG.dwOriginalTtl = *(const DWORD *)pos; pos += sizeof(DWORD);
r->Data.SIG.dwExpiration = *(const DWORD *)pos; pos += sizeof(DWORD);
r->Data.SIG.dwTimeSigned = *(const DWORD *)pos; pos += sizeof(DWORD);
r->Data.SIG.wKeyTag = *(const WORD *)pos;
size = rr->rdata + rr->rdlength - pos;
for (i = 0; i < size; i++)
r->Data.SIG.Signature[i] = *(const BYTE *)pos++;
*dlen = sizeof(DNS_SIG_DATAA) + (size - 1) * sizeof(BYTE);
break;
}
case ns_t_soa:
{
r->Data.SOA.pNamePrimaryServer = dns_dname_from_msg( msg, pos );
if (!r->Data.SOA.pNamePrimaryServer) return ERROR_NOT_ENOUGH_MEMORY;
if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
return DNS_ERROR_BAD_PACKET;
r->Data.SOA.pNameAdministrator = dns_dname_from_msg( msg, pos );
if (!r->Data.SOA.pNameAdministrator)
{
dns_free( r->Data.SOA.pNamePrimaryServer );
return ERROR_NOT_ENOUGH_MEMORY;
}
if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
return DNS_ERROR_BAD_PACKET;
r->Data.SOA.dwSerialNo = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
r->Data.SOA.dwRefresh = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
r->Data.SOA.dwRetry = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
r->Data.SOA.dwExpire = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
r->Data.SOA.dwDefaultTtl = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
*dlen = sizeof(DNS_SOA_DATAA);
break;
}
case ns_t_srv:
{
r->Data.SRV.wPriority = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
r->Data.SRV.wWeight = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
r->Data.SRV.wPort = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
r->Data.SRV.pNameTarget = dns_dname_from_msg( msg, pos );
if (!r->Data.SRV.pNameTarget) return ERROR_NOT_ENOUGH_MEMORY;
*dlen = sizeof(DNS_SRV_DATAA);
break;
}
case ns_t_hinfo:
case ns_t_isdn:
case ns_t_x25:
case ns_t_txt:
{
i = 0;
while (pos[0] && pos < rr->rdata + rr->rdlength)
{
r->Data.TXT.pStringArray[i] = dns_str_from_rdata( pos );
if (!r->Data.TXT.pStringArray[i])
{
while (i > 0) dns_free( r->Data.TXT.pStringArray[--i] );
return ERROR_NOT_ENOUGH_MEMORY;
}
i++;
pos += pos[0] + 1;
}
r->Data.TXT.dwStringCount = i;
*dlen = sizeof(DNS_TXT_DATAA) + (i - 1) * sizeof(PCHAR);
break;
}
case ns_t_atma:
case ns_t_loc:
case ns_t_nxt:
case ns_t_tsig:
case ns_t_wks:
case 0x00f9: /* TKEY */
case 0xff01: /* WINS */
case 0xff02: /* WINSR */
default:
FIXME( "unhandled type: %s\n", dns_type_to_str( rr->type ) );
return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
}
return ret;
}
static DNS_STATUS dns_copy_record( ns_msg msg, ns_sect section,
unsigned short num, DNS_RECORDA **recp )
{
DNS_STATUS ret;
DNS_RECORDA *record;
WORD dlen;
ns_rr rr;
if (dns_ns_parserr( &msg, section, num, &rr ) < 0)
return DNS_ERROR_BAD_PACKET;
if (!(record = dns_zero_alloc( dns_get_record_size( &rr ) )))
return ERROR_NOT_ENOUGH_MEMORY;
record->pName = dns_strdup_u( rr.name );
if (!record->pName)
{
dns_free( record );
return ERROR_NOT_ENOUGH_MEMORY;
}
record->wType = rr.type;
record->Flags.S.Section = section;
record->Flags.S.CharSet = DnsCharSetUtf8;
record->dwTtl = rr.ttl;
if ((ret = dns_copy_rdata( msg, &rr, record, &dlen )))
{
dns_free( record->pName );
dns_free( record );
return ret;
}
record->wDataLength = dlen;
*recp = record;
TRACE( "found %s record in %s section\n",
dns_type_to_str( rr.type ), dns_section_to_str( section ) );
return ERROR_SUCCESS;
}
#define DEFAULT_TTL 1200
static DNS_STATUS dns_do_query_netbios( PCSTR name, DNS_RECORDA **recp )
{
NCB ncb;
UCHAR ret;
DNS_RRSET rrset;
FIND_NAME_BUFFER *buffer;
FIND_NAME_HEADER *header;
DNS_RECORDA *record = NULL;
unsigned int i, len;
DNS_STATUS status = ERROR_INVALID_NAME;
len = strlen( name );
if (len >= NCBNAMSZ) return DNS_ERROR_RCODE_NAME_ERROR;
DNS_RRSET_INIT( rrset );
memset( &ncb, 0, sizeof(ncb) );
ncb.ncb_command = NCBFINDNAME;
memset( ncb.ncb_callname, ' ', sizeof(ncb.ncb_callname) );
memcpy( ncb.ncb_callname, name, len );
ncb.ncb_callname[NCBNAMSZ - 1] = '\0';
ret = Netbios( &ncb );
if (ret != NRC_GOODRET) return ERROR_INVALID_NAME;
header = (FIND_NAME_HEADER *)ncb.ncb_buffer;
buffer = (FIND_NAME_BUFFER *)((char *)header + sizeof(FIND_NAME_HEADER));
for (i = 0; i < header->node_count; i++)
{
record = dns_zero_alloc( sizeof(DNS_RECORDA) );
if (!record)
{
status = ERROR_NOT_ENOUGH_MEMORY;
goto exit;
}
else
{
record->pName = dns_strdup_u( name );
if (!record->pName)
{
status = ERROR_NOT_ENOUGH_MEMORY;
goto exit;
}
record->wType = DNS_TYPE_A;
record->Flags.S.Section = DnsSectionAnswer;
record->Flags.S.CharSet = DnsCharSetUtf8;
record->dwTtl = DEFAULT_TTL;
/* FIXME: network byte order? */
record->Data.A.IpAddress = *(DWORD *)((char *)buffer[i].destination_addr + 2);
DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
}
}
status = ERROR_SUCCESS;
exit:
DNS_RRSET_TERMINATE( rrset );
if (status != ERROR_SUCCESS)
DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
else
*recp = (DNS_RECORDA *)rrset.pFirstRR;
return status;
}
/* The resolver lock must be held and res_init() must have been
* called before calling these three functions.
*/
static DNS_STATUS dns_set_serverlist( const IP4_ARRAY *addrs )
{
unsigned int i;
if (addrs->AddrCount > MAXNS)
{
WARN( "too many servers: %d only using the first: %d\n",
addrs->AddrCount, MAXNS );
_res.nscount = MAXNS;
}
else _res.nscount = addrs->AddrCount;
for (i = 0; i < _res.nscount; i++)
_res.nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i];
return ERROR_SUCCESS;
}
static DNS_STATUS dns_get_serverlist( PIP4_ARRAY addrs, PDWORD len )
{
unsigned int i, size;
size = sizeof(IP4_ARRAY) + sizeof(IP4_ADDRESS) * (_res.nscount - 1);
if (!addrs || *len < size)
{
*len = size;
return ERROR_INSUFFICIENT_BUFFER;
}
addrs->AddrCount = _res.nscount;
for (i = 0; i < _res.nscount; i++)
addrs->AddrArray[i] = _res.nsaddr_list[i].sin_addr.s_addr;
return ERROR_SUCCESS;
}
static DNS_STATUS dns_do_query( PCSTR name, WORD type, DWORD options,
PDNS_RECORDA *result )
{
DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
unsigned int i, num;
unsigned char answer[NS_PACKETSZ];
ns_sect sections[] = { ns_s_an, ns_s_ar };
ns_msg msg;
DNS_RECORDA *record = NULL;
DNS_RRSET rrset;
int len;
DNS_RRSET_INIT( rrset );
len = res_query( name, ns_c_in, type, answer, sizeof(answer) );
if (len < 0)
{
ret = dns_map_h_errno( h_errno );
goto exit;
}
if (dns_ns_initparse( answer, len, &msg ) < 0)
{
ret = DNS_ERROR_BAD_PACKET;
goto exit;
}
#define RCODE_MASK 0x0f
if ((msg._flags & RCODE_MASK) != ns_r_noerror)
{
ret = dns_map_error( msg._flags & RCODE_MASK );
goto exit;
}
for (i = 0; i < sizeof(sections)/sizeof(sections[0]); i++)
{
for (num = 0; num < ns_msg_count( msg, sections[i] ); num++)
{
ret = dns_copy_record( msg, sections[i], num, &record );
if (ret != ERROR_SUCCESS) goto exit;
DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
}
}
exit:
DNS_RRSET_TERMINATE( rrset );
if (ret != ERROR_SUCCESS)
DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
else
*result = (DNS_RECORDA *)rrset.pFirstRR;
return ret;
}
#endif /* HAVE_RESOLV */
/******************************************************************************
* DnsQuery_A [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsQuery_A( PCSTR name, WORD type, DWORD options, PVOID servers,
PDNS_RECORDA *result, PVOID *reserved )
{
WCHAR *nameW;
DNS_RECORDW *resultW;
DNS_STATUS status;
TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ),
options, servers, result, reserved );
if (!name || !result)
return ERROR_INVALID_PARAMETER;
nameW = dns_strdup_aw( name );
if (!nameW) return ERROR_NOT_ENOUGH_MEMORY;
status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved );
if (status == ERROR_SUCCESS)
{
*result = (DNS_RECORDA *)DnsRecordSetCopyEx(
(DNS_RECORD *)resultW, DnsCharSetUnicode, DnsCharSetAnsi );
if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
DnsRecordListFree( (DNS_RECORD *)resultW, DnsFreeRecordList );
}
dns_free( nameW );
return status;
}
/******************************************************************************
* DnsQuery_UTF8 [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID servers,
PDNS_RECORDA *result, PVOID *reserved )
{
DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
#ifdef HAVE_RESOLV
TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ),
options, servers, result, reserved );
if (!name || !result)
return ERROR_INVALID_PARAMETER;
LOCK_RESOLVER();
initialise_resolver();
_res.options |= dns_map_options( options );
if (servers && (ret = dns_set_serverlist( servers )))
{
UNLOCK_RESOLVER();
return ret;
}
ret = dns_do_query( name, type, options, result );
if (ret == DNS_ERROR_RCODE_NAME_ERROR && type == DNS_TYPE_A &&
!(options & DNS_QUERY_NO_NETBT))
{
TRACE( "dns lookup failed, trying netbios query\n" );
ret = dns_do_query_netbios( name, result );
}
UNLOCK_RESOLVER();
#endif
return ret;
}
/******************************************************************************
* DnsQuery_W [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsQuery_W( PCWSTR name, WORD type, DWORD options, PVOID servers,
PDNS_RECORDW *result, PVOID *reserved )
{
char *nameU;
DNS_RECORDA *resultA;
DNS_STATUS status;
TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_w(name), dns_type_to_str( type ),
options, servers, result, reserved );
if (!name || !result)
return ERROR_INVALID_PARAMETER;
nameU = dns_strdup_wu( name );
if (!nameU) return ERROR_NOT_ENOUGH_MEMORY;
status = DnsQuery_UTF8( nameU, type, options, servers, &resultA, reserved );
if (status == ERROR_SUCCESS)
{
*result = (DNS_RECORDW *)DnsRecordSetCopyEx(
(DNS_RECORD *)resultA, DnsCharSetUtf8, DnsCharSetUnicode );
if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
DnsRecordListFree( (DNS_RECORD *)resultA, DnsFreeRecordList );
}
dns_free( nameU );
return status;
}
static DNS_STATUS dns_get_hostname_a( COMPUTER_NAME_FORMAT format,
PSTR buffer, PDWORD len )
{
char name[256];
DWORD size = sizeof(name);
if (!GetComputerNameExA( format, name, &size ))
return DNS_ERROR_NAME_DOES_NOT_EXIST;
if (!buffer || (size = lstrlenA( name ) + 1) > *len)
{
*len = size;
return ERROR_INSUFFICIENT_BUFFER;
}
lstrcpyA( buffer, name );
return ERROR_SUCCESS;
}
static DNS_STATUS dns_get_hostname_w( COMPUTER_NAME_FORMAT format,
PWSTR buffer, PDWORD len )
{
WCHAR name[256];
DWORD size = sizeof(name);
if (!GetComputerNameExW( format, name, &size ))
return DNS_ERROR_NAME_DOES_NOT_EXIST;
if (!buffer || (size = lstrlenW( name ) + 1) > *len)
{
*len = size;
return ERROR_INSUFFICIENT_BUFFER;
}
lstrcpyW( buffer, name );
return ERROR_SUCCESS;
}
/******************************************************************************
* DnsQueryConfig [DNSAPI.@]
*
*/
DNS_STATUS WINAPI DnsQueryConfig( DNS_CONFIG_TYPE config, DWORD flag, PWSTR adapter,
PVOID reserved, PVOID buffer, PDWORD len )
{
DNS_STATUS ret = ERROR_INVALID_PARAMETER;
TRACE( "(%d,0x%08x,%s,%p,%p,%p)\n", config, flag, debugstr_w(adapter),
reserved, buffer, len );
if (!len) return ERROR_INVALID_PARAMETER;
switch (config)
{
case DnsConfigDnsServerList:
{
#ifdef HAVE_RESOLV
LOCK_RESOLVER();
initialise_resolver();
ret = dns_get_serverlist( buffer, len );
UNLOCK_RESOLVER();
break;
#else
WARN( "compiled without resolver support\n" );
break;
#endif
}
case DnsConfigHostName_A:
case DnsConfigHostName_UTF8:
return dns_get_hostname_a( ComputerNameDnsHostname, buffer, len );
case DnsConfigFullHostName_A:
case DnsConfigFullHostName_UTF8:
return dns_get_hostname_a( ComputerNameDnsFullyQualified, buffer, len );
case DnsConfigPrimaryDomainName_A:
case DnsConfigPrimaryDomainName_UTF8:
return dns_get_hostname_a( ComputerNameDnsDomain, buffer, len );
case DnsConfigHostName_W:
return dns_get_hostname_w( ComputerNameDnsHostname, buffer, len );
case DnsConfigFullHostName_W:
return dns_get_hostname_w( ComputerNameDnsFullyQualified, buffer, len );
case DnsConfigPrimaryDomainName_W:
return dns_get_hostname_w( ComputerNameDnsDomain, buffer, len );
case DnsConfigAdapterDomainName_A:
case DnsConfigAdapterDomainName_W:
case DnsConfigAdapterDomainName_UTF8:
case DnsConfigSearchList:
case DnsConfigAdapterInfo:
case DnsConfigPrimaryHostNameRegistrationEnabled:
case DnsConfigAdapterHostNameRegistrationEnabled:
case DnsConfigAddressRegistrationMaxCount:
FIXME( "unimplemented config type %d\n", config );
break;
default:
WARN( "unknown config type: %d\n", config );
break;
}
return ret;
}
--- NEW FILE: record.c ---
/*
* DNS support
*
* Copyright (C) 2006 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include "wine/debug.h"
#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "wine-lgpl/windns.h"
#include "dnsapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
const char *dns_type_to_str( unsigned short type )
{
switch (type)
{
#define X(x) case (x): return #x;
X(DNS_TYPE_ZERO)
X(DNS_TYPE_A)
X(DNS_TYPE_NS)
X(DNS_TYPE_MD)
X(DNS_TYPE_MF)
X(DNS_TYPE_CNAME)
X(DNS_TYPE_SOA)
X(DNS_TYPE_MB)
X(DNS_TYPE_MG)
X(DNS_TYPE_MR)
X(DNS_TYPE_NULL)
X(DNS_TYPE_WKS)
X(DNS_TYPE_PTR)
X(DNS_TYPE_HINFO)
X(DNS_TYPE_MINFO)
X(DNS_TYPE_MX)
X(DNS_TYPE_TEXT)
X(DNS_TYPE_RP)
X(DNS_TYPE_AFSDB)
X(DNS_TYPE_X25)
X(DNS_TYPE_ISDN)
X(DNS_TYPE_RT)
X(DNS_TYPE_NSAP)
X(DNS_TYPE_NSAPPTR)
X(DNS_TYPE_SIG)
X(DNS_TYPE_KEY)
X(DNS_TYPE_PX)
X(DNS_TYPE_GPOS)
X(DNS_TYPE_AAAA)
X(DNS_TYPE_LOC)
X(DNS_TYPE_NXT)
X(DNS_TYPE_EID)
X(DNS_TYPE_NIMLOC)
X(DNS_TYPE_SRV)
X(DNS_TYPE_ATMA)
X(DNS_TYPE_NAPTR)
X(DNS_TYPE_KX)
X(DNS_TYPE_CERT)
X(DNS_TYPE_A6)
X(DNS_TYPE_DNAME)
X(DNS_TYPE_SINK)
X(DNS_TYPE_OPT)
X(DNS_TYPE_UINFO)
X(DNS_TYPE_UID)
X(DNS_TYPE_GID)
X(DNS_TYPE_UNSPEC)
X(DNS_TYPE_ADDRS)
X(DNS_TYPE_TKEY)
X(DNS_TYPE_TSIG)
X(DNS_TYPE_IXFR)
X(DNS_TYPE_AXFR)
X(DNS_TYPE_MAILB)
X(DNS_TYPE_MAILA)
X(DNS_TYPE_ANY)
X(DNS_TYPE_WINS)
X(DNS_TYPE_WINSR)
#undef X
default: { static char tmp[7]; sprintf( tmp, "0x%04x", type ); return tmp; }
}
}
static int dns_strcmpX( LPCVOID str1, LPCVOID str2, BOOL wide )
{
if (wide)
return lstrcmpiW( str1, str2 );
else
return lstrcmpiA( str1, str2 );
}
/******************************************************************************
* DnsRecordCompare [DNSAPI.@]
*
*/
BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
{
BOOL wide;
unsigned int i;
TRACE( "(%p,%p)\n", r1, r2 );
if (r1->wType != r2->wType ||
r1->wDataLength != r2->wDataLength ||
r1->Flags.DW != r2->Flags.DW ||
r1->dwReserved != r2->dwReserved) return FALSE;
wide = (r1->Flags.S.CharSet == DnsCharSetUnicode) ? TRUE : FALSE;
if (dns_strcmpX( r1->pName, r2->pName, wide )) return FALSE;
switch (r1->wType)
{
case DNS_TYPE_A:
{
if (r1->Data.A.IpAddress != r2->Data.A.IpAddress) return FALSE;
break;
}
case DNS_TYPE_SOA:
{
if (r1->Data.SOA.dwSerialNo != r2->Data.SOA.dwSerialNo ||
r1->Data.SOA.dwRefresh != r2->Data.SOA.dwRefresh ||
r1->Data.SOA.dwRetry != r2->Data.SOA.dwRetry ||
r1->Data.SOA.dwExpire != r2->Data.SOA.dwExpire ||
r1->Data.SOA.dwDefaultTtl != r2->Data.SOA.dwDefaultTtl)
return FALSE;
if (dns_strcmpX( r1->Data.SOA.pNamePrimaryServer,
r2->Data.SOA.pNamePrimaryServer, wide ) ||
dns_strcmpX( r1->Data.SOA.pNameAdministrator,
r2->Data.SOA.pNameAdministrator, wide ))
return FALSE;
break;
}
case DNS_TYPE_PTR:
case DNS_TYPE_NS:
case DNS_TYPE_CNAME:
case DNS_TYPE_MB:
case DNS_TYPE_MD:
case DNS_TYPE_MF:
case DNS_TYPE_MG:
case DNS_TYPE_MR:
{
if (dns_strcmpX( r1->Data.PTR.pNameHost,
r2->Data.PTR.pNameHost, wide )) return FALSE;
break;
}
case DNS_TYPE_MINFO:
case DNS_TYPE_RP:
{
if (dns_strcmpX( r1->Data.MINFO.pNameMailbox,
r2->Data.MINFO.pNameMailbox, wide ) ||
dns_strcmpX( r1->Data.MINFO.pNameErrorsMailbox,
r2->Data.MINFO.pNameErrorsMailbox, wide ))
return FALSE;
break;
}
case DNS_TYPE_MX:
case DNS_TYPE_AFSDB:
case DNS_TYPE_RT:
{
if (r1->Data.MX.wPreference != r2->Data.MX.wPreference)
return FALSE;
if (dns_strcmpX( r1->Data.MX.pNameExchange,
r2->Data.MX.pNameExchange, wide ))
return FALSE;
break;
}
case DNS_TYPE_HINFO:
case DNS_TYPE_ISDN:
case DNS_TYPE_TEXT:
case DNS_TYPE_X25:
{
if (r1->Data.TXT.dwStringCount != r2->Data.TXT.dwStringCount)
return FALSE;
for (i = 0; i < r1->Data.TXT.dwStringCount; i++)
{
if (dns_strcmpX( r1->Data.TXT.pStringArray[i],
r2->Data.TXT.pStringArray[i], wide ))
return FALSE;
}
break;
}
case DNS_TYPE_NULL:
{
if (r1->Data.Null.dwByteCount != r2->Data.Null.dwByteCount)
return FALSE;
if (memcmp( r1->Data.Null.Data,
r2->Data.Null.Data, r1->Data.Null.dwByteCount ))
return FALSE;
break;
}
case DNS_TYPE_AAAA:
{
for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
{
if (r1->Data.AAAA.Ip6Address.IP6Dword[i] !=
r2->Data.AAAA.Ip6Address.IP6Dword[i]) return FALSE;
}
break;
}
case DNS_TYPE_KEY:
{
if (r1->Data.KEY.wFlags != r2->Data.KEY.wFlags ||
r1->Data.KEY.chProtocol != r2->Data.KEY.chProtocol ||
r1->Data.KEY.chAlgorithm != r2->Data.KEY.chAlgorithm)
return FALSE;
if (memcmp( r1->Data.KEY.Key, r2->Data.KEY.Key,
r1->wDataLength - sizeof(DNS_KEY_DATA) + 1 ))
return FALSE;
break;
}
case DNS_TYPE_SIG:
{
if (dns_strcmpX( r1->Data.SIG.pNameSigner,
r2->Data.SIG.pNameSigner, wide ))
return FALSE;
if (r1->Data.SIG.wTypeCovered != r2->Data.SIG.wTypeCovered ||
r1->Data.SIG.chAlgorithm != r2->Data.SIG.chAlgorithm ||
r1->Data.SIG.chLabelCount != r2->Data.SIG.chLabelCount ||
r1->Data.SIG.dwOriginalTtl != r2->Data.SIG.dwOriginalTtl ||
r1->Data.SIG.dwExpiration != r2->Data.SIG.dwExpiration ||
r1->Data.SIG.dwTimeSigned != r2->Data.SIG.dwTimeSigned ||
r1->Data.SIG.wKeyTag != r2->Data.SIG.wKeyTag)
return FALSE;
if (memcmp( r1->Data.SIG.Signature, r2->Data.SIG.Signature,
r1->wDataLength - sizeof(DNS_SIG_DATAA) + 1 ))
return FALSE;
break;
}
case DNS_TYPE_ATMA:
{
if (r1->Data.ATMA.AddressType != r2->Data.ATMA.AddressType)
return FALSE;
for (i = 0; i < DNS_ATMA_MAX_ADDR_LENGTH; i++)
{
if (r1->Data.ATMA.Address[i] != r2->Data.ATMA.Address[i])
return FALSE;
}
break;
}
case DNS_TYPE_NXT:
{
if (dns_strcmpX( r1->Data.NXT.pNameNext,
r2->Data.NXT.pNameNext, wide )) return FALSE;
if (r1->Data.NXT.wNumTypes != r2->Data.NXT.wNumTypes) return FALSE;
if (memcmp( r1->Data.NXT.wTypes, r2->Data.NXT.wTypes,
r1->wDataLength - sizeof(DNS_NXT_DATAA) + sizeof(WORD) ))
return FALSE;
break;
}
case DNS_TYPE_SRV:
{
if (dns_strcmpX( r1->Data.SRV.pNameTarget,
r2->Data.SRV.pNameTarget, wide )) return FALSE;
if (r1->Data.SRV.wPriority != r2->Data.SRV.wPriority ||
r1->Data.SRV.wWeight != r2->Data.SRV.wWeight ||
r1->Data.SRV.wPort != r2->Data.SRV.wPort)
return FALSE;
break;
}
case DNS_TYPE_TKEY:
{
if (dns_strcmpX( r1->Data.TKEY.pNameAlgorithm,
r2->Data.TKEY.pNameAlgorithm, wide ))
return FALSE;
if (r1->Data.TKEY.dwCreateTime != r2->Data.TKEY.dwCreateTime ||
r1->Data.TKEY.dwExpireTime != r2->Data.TKEY.dwExpireTime ||
r1->Data.TKEY.wMode != r2->Data.TKEY.wMode ||
r1->Data.TKEY.wError != r2->Data.TKEY.wError ||
r1->Data.TKEY.wKeyLength != r2->Data.TKEY.wKeyLength ||
r1->Data.TKEY.wOtherLength != r2->Data.TKEY.wOtherLength ||
r1->Data.TKEY.cAlgNameLength != r2->Data.TKEY.cAlgNameLength ||
r1->Data.TKEY.bPacketPointers != r2->Data.TKEY.bPacketPointers)
return FALSE;
/* FIXME: ignoring pAlgorithmPacket field */
if (memcmp( r1->Data.TKEY.pKey, r2->Data.TKEY.pKey,
r1->Data.TKEY.wKeyLength ) ||
memcmp( r1->Data.TKEY.pOtherData, r2->Data.TKEY.pOtherData,
r1->Data.TKEY.wOtherLength )) return FALSE;
break;
}
case DNS_TYPE_TSIG:
{
if (dns_strcmpX( r1->Data.TSIG.pNameAlgorithm,
r2->Data.TSIG.pNameAlgorithm, wide ))
return FALSE;
if (r1->Data.TSIG.i64CreateTime != r2->Data.TSIG.i64CreateTime ||
r1->Data.TSIG.wFudgeTime != r2->Data.TSIG.wFudgeTime ||
r1->Data.TSIG.wOriginalXid != r2->Data.TSIG.wOriginalXid ||
r1->Data.TSIG.wError != r2->Data.TSIG.wError ||
r1->Data.TSIG.wSigLength != r2->Data.TSIG.wSigLength ||
r1->Data.TSIG.wOtherLength != r2->Data.TSIG.wOtherLength ||
r1->Data.TSIG.cAlgNameLength != r2->Data.TSIG.cAlgNameLength ||
r1->Data.TSIG.bPacketPointers != r2->Data.TSIG.bPacketPointers)
return FALSE;
/* FIXME: ignoring pAlgorithmPacket field */
if (memcmp( r1->Data.TSIG.pSignature, r2->Data.TSIG.pSignature,
r1->Data.TSIG.wSigLength ) ||
memcmp( r1->Data.TSIG.pOtherData, r2->Data.TSIG.pOtherData,
r1->Data.TSIG.wOtherLength )) return FALSE;
break;
}
case DNS_TYPE_WINS:
{
if (r1->Data.WINS.dwMappingFlag != r2->Data.WINS.dwMappingFlag ||
r1->Data.WINS.dwLookupTimeout != r2->Data.WINS.dwLookupTimeout ||
r1->Data.WINS.dwCacheTimeout != r2->Data.WINS.dwCacheTimeout ||
r1->Data.WINS.cWinsServerCount != r2->Data.WINS.cWinsServerCount)
return FALSE;
if (memcmp( r1->Data.WINS.WinsServers, r2->Data.WINS.WinsServers,
r1->wDataLength - sizeof(DNS_WINS_DATA) + sizeof(IP4_ADDRESS) ))
return FALSE;
break;
}
case DNS_TYPE_WINSR:
{
if (r1->Data.WINSR.dwMappingFlag != r2->Data.WINSR.dwMappingFlag ||
r1->Data.WINSR.dwLookupTimeout != r2->Data.WINSR.dwLookupTimeout ||
r1->Data.WINSR.dwCacheTimeout != r2->Data.WINSR.dwCacheTimeout)
return FALSE;
if (dns_strcmpX( r1->Data.WINSR.pNameResultDomain,
r2->Data.WINSR.pNameResultDomain, wide ))
return FALSE;
break;
}
default:
FIXME( "unknown type: %s\n", dns_type_to_str( r1->wType ) );
return FALSE;
}
return TRUE;
}
static LPVOID dns_strcpyX( LPCVOID src, DNS_CHARSET in, DNS_CHARSET out )
{
switch (in)
{
case DnsCharSetUnicode:
{
switch (out)
{
case DnsCharSetUnicode: return dns_strdup_w( src );
case DnsCharSetUtf8: return dns_strdup_wu( src );
case DnsCharSetAnsi: return dns_strdup_wa( src );
default:
WARN( "unhandled target charset: %d\n", out );
break;
}
}
case DnsCharSetUtf8:
switch (out)
{
case DnsCharSetUnicode: return dns_strdup_uw( src );
case DnsCharSetUtf8: return dns_strdup_u( src );
case DnsCharSetAnsi: return dns_strdup_ua( src );
default:
WARN( "unhandled target charset: %d\n", out );
break;
}
case DnsCharSetAnsi:
switch (out)
{
case DnsCharSetUnicode: return dns_strdup_aw( src );
case DnsCharSetUtf8: return dns_strdup_au( src );
case DnsCharSetAnsi: return dns_strdup_a( src );
default:
WARN( "unhandled target charset: %d\n", out );
break;
}
default:
WARN( "unhandled source charset: %d\n", in );
break;
}
return NULL;
}
/******************************************************************************
* DnsRecordCopyEx [DNSAPI.@]
*
*/
PDNS_RECORD WINAPI DnsRecordCopyEx( PDNS_RECORD src, DNS_CHARSET in, DNS_CHARSET out )
{
DNS_RECORD *dst;
unsigned int i, size;
TRACE( "(%p,%d,%d)\n", src, in, out );
size = FIELD_OFFSET(DNS_RECORD, Data) + src->wDataLength;
dst = dns_zero_alloc( size );
if (!dst) return NULL;
memcpy( dst, src, size );
if (src->Flags.S.CharSet == DnsCharSetUtf8 ||
src->Flags.S.CharSet == DnsCharSetAnsi ||
src->Flags.S.CharSet == DnsCharSetUnicode) in = src->Flags.S.CharSet;
dst->Flags.S.CharSet = out;
dst->pName = dns_strcpyX( src->pName, in, out );
if (!dst->pName) goto error;
switch (src->wType)
{
case DNS_TYPE_HINFO:
case DNS_TYPE_ISDN:
case DNS_TYPE_TEXT:
case DNS_TYPE_X25:
{
for (i = 0; i < src->Data.TXT.dwStringCount; i++)
{
dst->Data.TXT.pStringArray[i] =
dns_strcpyX( src->Data.TXT.pStringArray[i], in, out );
if (!dst->Data.TXT.pStringArray[i])
{
while (i > 0) dns_free( dst->Data.TXT.pStringArray[--i] );
goto error;
}
}
break;
}
case DNS_TYPE_MINFO:
case DNS_TYPE_RP:
{
dst->Data.MINFO.pNameMailbox =
dns_strcpyX( src->Data.MINFO.pNameMailbox, in, out );
if (!dst->Data.MINFO.pNameMailbox) goto error;
dst->Data.MINFO.pNameErrorsMailbox =
dns_strcpyX( src->Data.MINFO.pNameErrorsMailbox, in, out );
if (!dst->Data.MINFO.pNameErrorsMailbox)
{
dns_free( dst->Data.MINFO.pNameMailbox );
goto error;
}
break;
}
case DNS_TYPE_AFSDB:
case DNS_TYPE_RT:
case DNS_TYPE_MX:
{
dst->Data.MX.pNameExchange =
dns_strcpyX( src->Data.MX.pNameExchange, in, out );
if (!dst->Data.MX.pNameExchange) goto error;
break;
}
case DNS_TYPE_NXT:
{
dst->Data.NXT.pNameNext =
dns_strcpyX( src->Data.NXT.pNameNext, in, out );
if (!dst->Data.NXT.pNameNext) goto error;
break;
}
case DNS_TYPE_CNAME:
case DNS_TYPE_MB:
case DNS_TYPE_MD:
case DNS_TYPE_MF:
case DNS_TYPE_MG:
case DNS_TYPE_MR:
case DNS_TYPE_NS:
case DNS_TYPE_PTR:
{
dst->Data.PTR.pNameHost =
dns_strcpyX( src->Data.PTR.pNameHost, in, out );
if (!dst->Data.PTR.pNameHost) goto error;
break;
}
case DNS_TYPE_SIG:
{
dst->Data.SIG.pNameSigner =
dns_strcpyX( src->Data.SIG.pNameSigner, in, out );
if (!dst->Data.SIG.pNameSigner) goto error;
break;
}
case DNS_TYPE_SOA:
{
dst->Data.SOA.pNamePrimaryServer =
dns_strcpyX( src->Data.SOA.pNamePrimaryServer, in, out );
if (!dst->Data.SOA.pNamePrimaryServer) goto error;
dst->Data.SOA.pNameAdministrator =
dns_strcpyX( src->Data.SOA.pNameAdministrator, in, out );
if (!dst->Data.SOA.pNameAdministrator)
{
dns_free( dst->Data.SOA.pNamePrimaryServer );
goto error;
}
break;
}
case DNS_TYPE_SRV:
{
dst->Data.SRV.pNameTarget =
dns_strcpyX( src->Data.SRV.pNameTarget, in, out );
if (!dst->Data.SRV.pNameTarget) goto error;
break;
}
default:
break;
}
return dst;
error:
dns_free( dst->pName );
dns_free( dst );
return NULL;
}
/******************************************************************************
* DnsRecordListFree [DNSAPI.@]
*
*/
VOID WINAPI DnsRecordListFree( PDNS_RECORD list, DNS_FREE_TYPE type )
{
DNS_RECORD *r, *next;
unsigned int i;
TRACE( "(%p,%d)\n", list, type );
if (!list) return;
switch (type)
{
case DnsFreeRecordList:
{
for (r = list; (list = r); r = next)
{
dns_free( r->pName );
switch (r->wType)
{
case DNS_TYPE_HINFO:
case DNS_TYPE_ISDN:
case DNS_TYPE_TEXT:
case DNS_TYPE_X25:
{
for (i = 0; i < r->Data.TXT.dwStringCount; i++)
dns_free( r->Data.TXT.pStringArray[i] );
break;
}
case DNS_TYPE_MINFO:
case DNS_TYPE_RP:
{
dns_free( r->Data.MINFO.pNameMailbox );
dns_free( r->Data.MINFO.pNameErrorsMailbox );
break;
}
case DNS_TYPE_AFSDB:
case DNS_TYPE_RT:
case DNS_TYPE_MX:
{
dns_free( r->Data.MX.pNameExchange );
break;
}
case DNS_TYPE_NXT:
{
dns_free( r->Data.NXT.pNameNext );
break;
}
case DNS_TYPE_CNAME:
case DNS_TYPE_MB:
case DNS_TYPE_MD:
case DNS_TYPE_MF:
case DNS_TYPE_MG:
case DNS_TYPE_MR:
case DNS_TYPE_NS:
case DNS_TYPE_PTR:
{
dns_free( r->Data.PTR.pNameHost );
break;
}
case DNS_TYPE_SIG:
{
dns_free( r->Data.SIG.pNameSigner );
break;
}
case DNS_TYPE_SOA:
{
dns_free( r->Data.SOA.pNamePrimaryServer );
dns_free( r->Data.SOA.pNameAdministrator );
break;
}
case DNS_TYPE_SRV:
{
dns_free( r->Data.SRV.pNameTarget );
break;
}
default:
break;
}
next = r->pNext;
dns_free( r );
}
break;
}
case DnsFreeFlat:
case DnsFreeParsedMessageFields:
{
FIXME( "unhandled free type: %d\n", type );
break;
}
default:
WARN( "unknown free type: %d\n", type );
break;
}
}
/******************************************************************************
* DnsRecordSetCompare [DNSAPI.@]
*
*/
BOOL WINAPI DnsRecordSetCompare( PDNS_RECORD set1, PDNS_RECORD set2,
PDNS_RECORD *diff1, PDNS_RECORD *diff2 )
{
BOOL ret = TRUE;
DNS_RECORD *r, *s1, *s2, *t, *u;
DNS_RRSET rr1, rr2;
TRACE( "(%p,%p,%p,%p)\n", set1, set2, diff1, diff2 );
if (!set1 && !set2) return FALSE;
if (diff1) *diff1 = NULL;
if (diff2) *diff2 = NULL;
if (set1 && !set2)
{
if (diff1) *diff1 = DnsRecordSetCopyEx( set1, 0, set1->Flags.S.CharSet );
return FALSE;
}
if (!set1 && set2)
{
if (diff2) *diff2 = DnsRecordSetCopyEx( set2, 0, set2->Flags.S.CharSet );
return FALSE;
}
DNS_RRSET_INIT( rr1 );
DNS_RRSET_INIT( rr2 );
for (r = s1 = set1; (s1 = r); r = r->pNext)
{
for (t = s2 = set2; (s2 = t); t = t->pNext)
{
u = DnsRecordCopyEx( r, r->Flags.S.CharSet, t->Flags.S.CharSet );
if (!u) goto error;
if (!DnsRecordCompare( t, u ))
{
DNS_RRSET_ADD( rr1, u );
ret = FALSE;
}
else dns_free( u );
}
}
for (t = s2 = set2; (s2 = t); t = t->pNext)
{
for (r = s1 = set1; (s1 = r); r = r->pNext)
{
u = DnsRecordCopyEx( t, t->Flags.S.CharSet, r->Flags.S.CharSet );
if (!u) goto error;
if (!DnsRecordCompare( r, u ))
{
DNS_RRSET_ADD( rr2, u );
ret = FALSE;
}
else dns_free( u );
}
}
DNS_RRSET_TERMINATE( rr1 );
DNS_RRSET_TERMINATE( rr2 );
if (diff1) *diff1 = rr1.pFirstRR;
if (diff2) *diff2 = rr2.pFirstRR;
return ret;
error:
DNS_RRSET_TERMINATE( rr1 );
DNS_RRSET_TERMINATE( rr2 );
DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList );
DnsRecordListFree( rr2.pFirstRR, DnsFreeRecordList );
return FALSE;
}
/******************************************************************************
* DnsRecordSetCopyEx [DNSAPI.@]
*
*/
PDNS_RECORD WINAPI DnsRecordSetCopyEx( PDNS_RECORD src_set, DNS_CHARSET in, DNS_CHARSET out )
{
DNS_RRSET dst_set;
DNS_RECORD *src, *dst;
TRACE( "(%p,%d,%d)\n", src_set, in, out );
DNS_RRSET_INIT( dst_set );
for (src = src_set; (src_set = src); src = src_set->pNext)
{
dst = DnsRecordCopyEx( src, in, out );
if (!dst)
{
DNS_RRSET_TERMINATE( dst_set );
DnsRecordListFree( dst_set.pFirstRR, DnsFreeRecordList );
return NULL;
}
DNS_RRSET_ADD( dst_set, dst );
}
DNS_RRSET_TERMINATE( dst_set );
return dst_set.pFirstRR;
}
/******************************************************************************
* DnsRecordSetDetach [DNSAPI.@]
*
*/
PDNS_RECORD WINAPI DnsRecordSetDetach( PDNS_RECORD set )
{
DNS_RECORD *r, *s;
TRACE( "(%p)\n", set );
for (r = set; (set = r); r = set->pNext)
{
if (r->pNext && !r->pNext->pNext)
{
s = r->pNext;
r->pNext = NULL;
return s;
}
}
return NULL;
}