Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104/* * 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 "precomp.h"#include <winreg.h>#include <iphlpapi.h>#include <strsafe.h>
#define NDEBUG#include <debug.h>
staticBOOLParseIpv4Address( _In_ PCWSTR AddressString, _Out_ PIN_ADDR pAddress){ PCWSTR pTerminator = NULL; NTSTATUS Status;
Status = RtlIpv4StringToAddressW(AddressString, TRUE, &pTerminator, pAddress); if (NT_SUCCESS(Status) && pTerminator != NULL && *pTerminator == L'\0') return TRUE;
return FALSE;}
staticBOOLParseIpv6Address( _In_ PCWSTR AddressString, _Out_ PIN6_ADDR pAddress){ PCWSTR pTerminator = NULL; NTSTATUS Status;
Status = RtlIpv6StringToAddressW(AddressString, &pTerminator, pAddress); if (NT_SUCCESS(Status) && pTerminator != NULL && *pTerminator == L'\0') return TRUE;
return FALSE;}
staticPDNS_RECORDWCreateRecordForIpAddress( _In_ PCWSTR Name, _In_ WORD Type){ IN_ADDR Ip4Address; IN6_ADDR Ip6Address; PDNS_RECORDW pRecord = NULL;
if (Type == DNS_TYPE_A) { if (ParseIpv4Address(Name, &Ip4Address)) { pRecord = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DNS_RECORDW)); if (pRecord == NULL) return NULL;
pRecord->pName = RtlAllocateHeap(RtlGetProcessHeap(), 0, (wcslen(Name) + 1) * sizeof(WCHAR)); if (pRecord == NULL) { RtlFreeHeap(RtlGetProcessHeap(), 0, pRecord); return NULL; }
wcscpy(pRecord->pName, Name); pRecord->wType = DNS_TYPE_A; pRecord->wDataLength = sizeof(DNS_A_DATA); pRecord->Flags.S.Section = DnsSectionQuestion; pRecord->Flags.S.CharSet = DnsCharSetUnicode; pRecord->dwTtl = 7 * 24 * 60 * 60;
pRecord->Data.A.IpAddress = Ip4Address.S_un.S_addr;
return pRecord; } } else if (Type == DNS_TYPE_AAAA) { if (ParseIpv6Address(Name, &Ip6Address)) { pRecord = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DNS_RECORDW)); if (pRecord == NULL) return NULL;
pRecord->pName = RtlAllocateHeap(RtlGetProcessHeap(), 0, (wcslen(Name) + 1) * sizeof(WCHAR)); if (pRecord == NULL) { RtlFreeHeap(RtlGetProcessHeap(), 0, pRecord); return NULL; }
wcscpy(pRecord->pName, Name); pRecord->wType = DNS_TYPE_AAAA; pRecord->wDataLength = sizeof(DNS_AAAA_DATA); pRecord->Flags.S.Section = DnsSectionQuestion; pRecord->Flags.S.CharSet = DnsCharSetUnicode; pRecord->dwTtl = 7 * 24 * 60 * 60;
CopyMemory(&pRecord->Data.AAAA.Ip6Address, &Ip6Address.u.Byte, sizeof(IN6_ADDR));
return pRecord; } }
return NULL;}
/* 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. */
static PCHARDnsWToC(const WCHAR *WideString){ PCHAR AnsiString; int AnsiLen = WideCharToMultiByte(CP_ACP, 0, WideString, -1, NULL, 0, NULL, 0); if (AnsiLen == 0) return NULL; AnsiString = RtlAllocateHeap(RtlGetProcessHeap(), 0, AnsiLen); if (AnsiString == NULL) { return NULL; } WideCharToMultiByte(CP_ACP, 0, WideString, -1, AnsiString, AnsiLen, NULL, 0);
return AnsiString;}
static PWCHARDnsCToW(const CHAR *NarrowString){ PWCHAR WideString; int WideLen = MultiByteToWideChar(CP_ACP, 0, NarrowString, -1, NULL, 0); if (WideLen == 0) return NULL; WideString = RtlAllocateHeap(RtlGetProcessHeap(), 0, WideLen * sizeof(WCHAR)); if (WideString == NULL) { return NULL; } MultiByteToWideChar(CP_ACP, 0, NarrowString, -1, WideString, WideLen);
return WideString;}
static PCHARDnsWToUTF8(const WCHAR *WideString){ PCHAR AnsiString; int AnsiLen = WideCharToMultiByte(CP_UTF8, 0, WideString, -1, NULL, 0, NULL, 0); if (AnsiLen == 0) return NULL; AnsiString = RtlAllocateHeap(RtlGetProcessHeap(), 0, AnsiLen); if (AnsiString == NULL) { return NULL; } WideCharToMultiByte(CP_UTF8, 0, WideString, -1, AnsiString, AnsiLen, NULL, 0);
return AnsiString;}
static PWCHARDnsUTF8ToW(const CHAR *NarrowString){ PWCHAR WideString; int WideLen = MultiByteToWideChar(CP_UTF8, 0, NarrowString, -1, NULL, 0); if (WideLen == 0) return NULL; WideString = RtlAllocateHeap(RtlGetProcessHeap(), 0, WideLen * sizeof(WCHAR)); if (WideString == NULL) { return NULL; } MultiByteToWideChar(CP_UTF8, 0, NarrowString, -1, WideString, WideLen);
return WideString;}
DNS_STATUS WINAPIDnsQuery_CodePage(UINT CodePage, LPCSTR Name, WORD Type, DWORD Options, PVOID Extra, PDNS_RECORD *QueryResultSet, PVOID *Reserved){ UINT i; PWCHAR Buffer; DNS_STATUS Status; PDNS_RECORD QueryResultWide; PDNS_RECORD ConvertedRecord = 0, LastRecord = 0;
if (Name == NULL) return ERROR_INVALID_PARAMETER; if (QueryResultSet == NULL) return ERROR_INVALID_PARAMETER;
switch (CodePage) { case CP_ACP: Buffer = DnsCToW(Name); break;
case CP_UTF8: Buffer = DnsUTF8ToW(Name); break;
default: return ERROR_INVALID_PARAMETER; }
Status = DnsQuery_W(Buffer, Type, Options, Extra, &QueryResultWide, Reserved);
while (Status == ERROR_SUCCESS && QueryResultWide) { switch (QueryResultWide->wType) { case DNS_TYPE_A: case DNS_TYPE_WKS: 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_RECORD)); break;
case DNS_TYPE_MINFO: ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_TXT_DATA) + QueryResultWide->Data.TXT.dwStringCount); break;
case DNS_TYPE_NULL: ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_NULL_DATA) + QueryResultWide->Data.Null.dwByteCount); break; } if (ConvertedRecord == NULL) { /* The name */ RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); /* The result*/ DnsIntFreeRecordList(QueryResultWide); QueryResultSet = NULL; return ERROR_OUTOFMEMORY; }
if (CodePage == CP_ACP) { ConvertedRecord->pName = DnsWToC((PWCHAR)QueryResultWide->pName); ConvertedRecord->Flags.S.CharSet = DnsCharSetAnsi; } else { ConvertedRecord->pName = DnsWToUTF8((PWCHAR)QueryResultWide->pName); ConvertedRecord->Flags.S.CharSet = DnsCharSetUtf8; }
ConvertedRecord->wType = QueryResultWide->wType;
switch (QueryResultWide->wType) { case DNS_TYPE_A: case DNS_TYPE_WKS: ConvertedRecord->wDataLength = QueryResultWide->wDataLength; memcpy(&ConvertedRecord->Data, &QueryResultWide->Data, 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->wDataLength = sizeof(DNS_PTR_DATA); if (CodePage == CP_ACP) ConvertedRecord->Data.PTR.pNameHost = DnsWToC((PWCHAR)QueryResultWide->Data.PTR.pNameHost); else ConvertedRecord->Data.PTR.pNameHost = DnsWToUTF8((PWCHAR)QueryResultWide->Data.PTR.pNameHost); break;
case DNS_TYPE_MINFO: ConvertedRecord->wDataLength = sizeof(DNS_MINFO_DATA); if (CodePage == CP_ACP) { ConvertedRecord->Data.MINFO.pNameMailbox = DnsWToC((PWCHAR)QueryResultWide->Data.MINFO.pNameMailbox); ConvertedRecord->Data.MINFO.pNameErrorsMailbox = DnsWToC((PWCHAR)QueryResultWide->Data.MINFO.pNameErrorsMailbox); } else { ConvertedRecord->Data.MINFO.pNameMailbox = DnsWToUTF8((PWCHAR)QueryResultWide->Data.MINFO.pNameMailbox); ConvertedRecord->Data.MINFO.pNameErrorsMailbox = DnsWToUTF8((PWCHAR)QueryResultWide->Data.MINFO.pNameErrorsMailbox); } break;
case DNS_TYPE_MX: ConvertedRecord->wDataLength = sizeof(DNS_MX_DATA); if (CodePage == CP_ACP) ConvertedRecord->Data.MX.pNameExchange = DnsWToC((PWCHAR)QueryResultWide->Data.MX.pNameExchange); else ConvertedRecord->Data.MX.pNameExchange = DnsWToUTF8((PWCHAR)QueryResultWide->Data.MX.pNameExchange); ConvertedRecord->Data.MX.wPreference = QueryResultWide->Data.MX.wPreference; break;
case DNS_TYPE_HINFO: ConvertedRecord->wDataLength = sizeof(DNS_TXT_DATA) + (sizeof(PCHAR) * QueryResultWide->Data.TXT.dwStringCount); ConvertedRecord->Data.TXT.dwStringCount = QueryResultWide->Data.TXT.dwStringCount;
if (CodePage == CP_ACP) for (i = 0; i < ConvertedRecord->Data.TXT.dwStringCount; i++) ConvertedRecord->Data.TXT.pStringArray[i] = DnsWToC((PWCHAR)QueryResultWide->Data.TXT.pStringArray[i]); else for (i = 0; i < ConvertedRecord->Data.TXT.dwStringCount; i++) ConvertedRecord->Data.TXT.pStringArray[i] = DnsWToUTF8((PWCHAR)QueryResultWide->Data.TXT.pStringArray[i]);
break;
case DNS_TYPE_NULL: 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; }
if (LastRecord) { LastRecord->pNext = ConvertedRecord; LastRecord = LastRecord->pNext; } else { LastRecord = *QueryResultSet = ConvertedRecord; }
QueryResultWide = QueryResultWide->pNext; }
if (LastRecord) LastRecord->pNext = 0;
/* The name */ RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); /* The result*/ if (QueryResultWide) DnsIntFreeRecordList(QueryResultWide);
return Status;}
DNS_STATUS WINAPIDnsQuery_A(LPCSTR Name, WORD Type, DWORD Options, PVOID Extra, PDNS_RECORD *QueryResultSet, PVOID *Reserved){ return DnsQuery_CodePage(CP_ACP, Name, Type, Options, Extra, QueryResultSet, Reserved);}
DNS_STATUS WINAPIDnsQuery_UTF8(LPCSTR Name, WORD Type, DWORD Options, PVOID Extra, PDNS_RECORD *QueryResultSet, PVOID *Reserved){ return DnsQuery_CodePage(CP_UTF8, Name, Type, Options, Extra, QueryResultSet, Reserved);}
DNS_STATUSWINAPIDnsQuery_W(LPCWSTR Name, WORD Type, DWORD Options, PVOID Extra, PDNS_RECORD *QueryResultSet, PVOID *Reserved){ DWORD dwRecords = 0; PDNS_RECORDW pRecord = NULL; size_t NameLen, i; DNS_STATUS Status = ERROR_SUCCESS;
DPRINT("DnsQuery_W()\n");
if ((Name == NULL) || (QueryResultSet == NULL)) return ERROR_INVALID_PARAMETER;
*QueryResultSet = NULL;
/* Create an A or AAAA record for an IP4 or IP6 address */ pRecord = CreateRecordForIpAddress(Name, Type); if (pRecord != NULL) { *QueryResultSet = (PDNS_RECORD)pRecord; return ERROR_SUCCESS; }
/* * Check allowed characters * According to RFC a-z,A-Z,0-9,-,_, but can't start or end with - or _ */ NameLen = wcslen(Name); if (Name[0] == L'-' || Name[0] == L'_' || Name[NameLen - 1] == L'-' || Name[NameLen - 1] == L'_' || wcsstr(Name, L"..") != NULL) { return ERROR_INVALID_NAME; }
i = 0; while (i < NameLen) { if (!((Name[i] >= L'a' && Name[i] <= L'z') || (Name[i] >= L'A' && Name[i] <= L'Z') || (Name[i] >= L'0' && Name[i] <= L'9') || Name[i] == L'-' || Name[i] == L'_' || Name[i] == L'.')) { return DNS_ERROR_INVALID_NAME_CHAR; }
i++; }
RpcTryExcept { Status = R_ResolverQuery(NULL, Name, Type, Options, &dwRecords, (DNS_RECORDW **)QueryResultSet); DPRINT("R_ResolverQuery() returned %lu\n", Status); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) { Status = RpcExceptionCode(); DPRINT("Exception returned %lu\n", Status); } RpcEndExcept;
return Status;}
WCHAR*xstrsave(const WCHAR *str){ WCHAR *p; size_t len = 0;
/* FIXME: how much instead of MAX_PATH? */ StringCbLengthW(str, MAX_PATH, &len); len+=sizeof(WCHAR);
p = RtlAllocateHeap(RtlGetProcessHeap(), 0, len);
if (p) StringCbCopyW(p, len, str);
return p;}
CHAR*xstrsaveA(const CHAR *str){ CHAR *p; size_t len = 0;
/* FIXME: how much instead of MAX_PATH? */ StringCbLengthA(str, MAX_PATH, &len); len++;
p = RtlAllocateHeap(RtlGetProcessHeap(), 0, len);
if (p) StringCbCopyA(p, len, str);
return p;}
/* This function is far from perfect but it works enough */IP4_ADDRESSCheckForCurrentHostname(CONST CHAR * Name, PFIXED_INFO network_info){ PCHAR TempName; DWORD AdapterAddressesSize, Status; IP4_ADDRESS ret = 0, Address; PIP_ADAPTER_ADDRESSES Addresses = NULL, pip; BOOL Found = FALSE;
if (network_info->DomainName[0]) { size_t StringLength; size_t TempSize = 2; StringCchLengthA(network_info->HostName, sizeof(network_info->HostName), &StringLength); TempSize += StringLength; StringCchLengthA(network_info->DomainName, sizeof(network_info->DomainName), &StringLength); TempSize += StringLength; TempName = RtlAllocateHeap(RtlGetProcessHeap(), 0, TempSize); StringCchCopyA(TempName, TempSize, network_info->HostName); StringCchCatA(TempName, TempSize, "."); StringCchCatA(TempName, TempSize, network_info->DomainName); } else { TempName = RtlAllocateHeap(RtlGetProcessHeap(), 0, 1); TempName[0] = 0; } Found = !_stricmp(Name, network_info->HostName) || !_stricmp(Name, TempName); RtlFreeHeap(RtlGetProcessHeap(), 0, TempName); if (!Found) { return 0; } /* get adapter info */ AdapterAddressesSize = 0; GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST, NULL, Addresses, &AdapterAddressesSize); if (!AdapterAddressesSize) { return 0; } Addresses = RtlAllocateHeap(RtlGetProcessHeap(), 0, AdapterAddressesSize); Status = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST, NULL, Addresses, &AdapterAddressesSize); if (Status) { RtlFreeHeap(RtlGetProcessHeap(), 0, Addresses); return 0; } for (pip = Addresses; pip != NULL; pip = pip->Next) { Address = ((LPSOCKADDR_IN)pip->FirstUnicastAddress->Address.lpSockaddr)->sin_addr.S_un.S_addr; if (Address != ntohl(INADDR_LOOPBACK)) break; } if (Address && Address != ntohl(INADDR_LOOPBACK)) { ret = Address; } RtlFreeHeap(RtlGetProcessHeap(), 0, Addresses); return ret;}
DNS_STATUSWINAPIQuery_Main(LPCWSTR Name, WORD Type, DWORD Options, PDNS_RECORD *QueryResultSet){ adns_state astate; int quflags = (Options & DNS_QUERY_NO_RECURSION) == 0 ? adns_qf_search : 0; int adns_error; adns_answer *answer; LPSTR CurrentName; unsigned CNameLoop; PFIXED_INFO network_info; ULONG network_info_blen = 0; DWORD network_info_result; PIP_ADDR_STRING pip; IP4_ADDRESS Address; struct in_addr addr; PCHAR HostWithDomainName; PCHAR AnsiName; size_t NameLen = 0;
if (Name == NULL) return ERROR_INVALID_PARAMETER; if (QueryResultSet == NULL) return ERROR_INVALID_PARAMETER;
*QueryResultSet = NULL;
switch (Type) { case DNS_TYPE_A: /* FIXME: how much instead of MAX_PATH? */ NameLen = WideCharToMultiByte(CP_ACP, 0, Name, -1, NULL, 0, NULL, 0); AnsiName = RtlAllocateHeap(RtlGetProcessHeap(), 0, NameLen); if (NULL == AnsiName) { return ERROR_OUTOFMEMORY; } WideCharToMultiByte(CP_ACP, 0, Name, -1, AnsiName, NameLen, NULL, 0); NameLen--;
network_info_result = GetNetworkParams(NULL, &network_info_blen); network_info = (PFIXED_INFO)RtlAllocateHeap(RtlGetProcessHeap(), 0, (size_t)network_info_blen); if (NULL == network_info) { return ERROR_OUTOFMEMORY; }
network_info_result = GetNetworkParams(network_info, &network_info_blen); if (network_info_result != ERROR_SUCCESS) { RtlFreeHeap(RtlGetProcessHeap(), 0, network_info); return network_info_result; }
if ((Address = CheckForCurrentHostname(NameLen != 0 ? AnsiName : network_info->HostName, network_info)) != 0) { size_t TempLen = 2, StringLength = 0; RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); StringCchLengthA(network_info->HostName, sizeof(network_info->HostName), &StringLength); TempLen += StringLength; StringCchLengthA(network_info->DomainName, sizeof(network_info->DomainName), &StringLength); TempLen += StringLength; HostWithDomainName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), 0, TempLen); StringCchCopyA(HostWithDomainName, TempLen, network_info->HostName); if (network_info->DomainName[0]) { StringCchCatA(HostWithDomainName, TempLen, "."); StringCchCatA(HostWithDomainName, TempLen, network_info->DomainName); } RtlFreeHeap(RtlGetProcessHeap(), 0, network_info); *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
if (NULL == *QueryResultSet) { RtlFreeHeap(RtlGetProcessHeap(), 0, HostWithDomainName); return ERROR_OUTOFMEMORY; }
(*QueryResultSet)->pNext = NULL; (*QueryResultSet)->wType = Type; (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA); (*QueryResultSet)->Flags.S.Section = DnsSectionAnswer; (*QueryResultSet)->Flags.S.CharSet = DnsCharSetUnicode; (*QueryResultSet)->Data.A.IpAddress = Address;
(*QueryResultSet)->pName = (LPSTR)DnsCToW(HostWithDomainName);
RtlFreeHeap(RtlGetProcessHeap(), 0, HostWithDomainName); return (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY; }
if ((Options & DNS_QUERY_NO_WIRE_QUERY) != 0) { RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); RtlFreeHeap(RtlGetProcessHeap(), 0, network_info); return ERROR_FILE_NOT_FOUND; }
adns_error = adns_init(&astate, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn, 0); if (adns_error != adns_s_ok) { RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); RtlFreeHeap(RtlGetProcessHeap(), 0, network_info); return DnsIntTranslateAdnsToDNS_STATUS(adns_error); } for (pip = &(network_info->DnsServerList); pip; pip = pip->Next) { addr.s_addr = inet_addr(pip->IpAddress.String); if ((addr.s_addr != INADDR_ANY) && (addr.s_addr != INADDR_NONE)) adns_addserver(astate, addr); } if (network_info->DomainName[0]) { adns_ccf_search(astate, "LOCALDOMAIN", -1, network_info->DomainName); } RtlFreeHeap(RtlGetProcessHeap(), 0, network_info);
if (!adns_numservers(astate)) { /* There are no servers to query so bail out */ adns_finish(astate); RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); return ERROR_FILE_NOT_FOUND; }
/* * adns doesn't resolve chained CNAME records (a CNAME which points to * another CNAME pointing to another... pointing to an A record), according * to a mailing list thread the authors believe that chained CNAME records * are invalid and the DNS entries should be fixed. That's a nice academic * standpoint, but there certainly are chained CNAME records out there, * even some fairly major ones (at the time of this writing * download.mozilla.org is a chained CNAME). Everyone else seems to resolve * these fine, so we should too. So we loop here to try to resolve CNAME * chains ourselves. Of course, there must be a limit to protect against * CNAME loops. */
#define CNAME_LOOP_MAX 16
CurrentName = AnsiName;
for (CNameLoop = 0; CNameLoop < CNAME_LOOP_MAX; CNameLoop++) { adns_error = adns_synchronous(astate, CurrentName, adns_r_addr, quflags, &answer);
if (adns_error != adns_s_ok) { adns_finish(astate);
if (CurrentName != AnsiName) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); return DnsIntTranslateAdnsToDNS_STATUS(adns_error); }
if (answer && answer->rrs.addr) { if (CurrentName != AnsiName) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
if (NULL == *QueryResultSet) { adns_finish(astate); return ERROR_OUTOFMEMORY; }
(*QueryResultSet)->pNext = NULL; (*QueryResultSet)->wType = Type; (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA); (*QueryResultSet)->Flags.S.Section = DnsSectionAnswer; (*QueryResultSet)->Flags.S.CharSet = DnsCharSetUnicode; (*QueryResultSet)->Data.A.IpAddress = answer->rrs.addr->addr.inet.sin_addr.s_addr;
adns_finish(astate);
(*QueryResultSet)->pName = (LPSTR)xstrsave(Name);
return (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY; }
if (NULL == answer || adns_s_prohibitedcname != answer->status || NULL == answer->cname) { adns_finish(astate);
if (CurrentName != AnsiName) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); return ERROR_FILE_NOT_FOUND; }
if (CurrentName != AnsiName) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
CurrentName = (LPSTR)xstrsaveA(answer->cname);
if (!CurrentName) { RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); adns_finish(astate); return ERROR_OUTOFMEMORY; } }
adns_finish(astate); RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); return ERROR_FILE_NOT_FOUND;
default: return ERROR_OUTOFMEMORY; /* XXX arty: find a better error code. */ }}
voidDnsIntFreeRecordList(PDNS_RECORD ToDelete){ UINT i; PDNS_RECORD 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_MX: RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->Data.MX.pNameExchange); break;
case DNS_TYPE_HINFO: 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; }
next = ToDelete->pNext; RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete); ToDelete = next; }}
BOOLWINAPIDnsFlushResolverCache(VOID){ DNS_STATUS Status = ERROR_SUCCESS;
DPRINT("DnsFlushResolverCache()\n");
RpcTryExcept { Status = R_ResolverFlushCache(NULL); DPRINT("R_ResolverFlushCache() returned %lu\n", Status); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) { Status = RpcExceptionCode(); DPRINT("Exception returned %lu\n", Status); } RpcEndExcept;
return (Status == ERROR_SUCCESS);}
BOOLWINAPIDnsFlushResolverCacheEntry_A( _In_ LPCSTR pszEntry){ DNS_STATUS Status = ERROR_SUCCESS; LPWSTR pszUnicodeEntry;
DPRINT1("DnsFlushResolverCacheEntry_A(%s)\n", pszEntry);
if (pszEntry == NULL) return FALSE;
pszUnicodeEntry = DnsCToW(pszEntry); if (pszUnicodeEntry == NULL) return FALSE;
RpcTryExcept { Status = R_ResolverFlushCacheEntry(NULL, pszUnicodeEntry, DNS_TYPE_ANY); DPRINT("R_ResolverFlushCacheEntry() returned %lu\n", Status); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) { Status = RpcExceptionCode(); DPRINT("Exception returned %lu\n", Status); } RpcEndExcept;
RtlFreeHeap(RtlGetProcessHeap(), 0, pszUnicodeEntry);
return (Status == ERROR_SUCCESS);}
BOOLWINAPIDnsFlushResolverCacheEntry_UTF8( _In_ LPCSTR pszEntry){ DNS_STATUS Status = ERROR_SUCCESS; LPWSTR pszUnicodeEntry;
DPRINT1("DnsFlushResolverCacheEntry_UTF8(%s)\n", pszEntry);
if (pszEntry == NULL) return FALSE;
pszUnicodeEntry = DnsCToW(pszEntry); if (pszUnicodeEntry == NULL) return FALSE;
RpcTryExcept { Status = R_ResolverFlushCacheEntry(NULL, pszUnicodeEntry, DNS_TYPE_ANY); DPRINT("R_ResolverFlushCacheEntry() returned %lu\n", Status); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) { Status = RpcExceptionCode(); DPRINT("Exception returned %lu\n", Status); } RpcEndExcept;
RtlFreeHeap(RtlGetProcessHeap(), 0, pszUnicodeEntry);
return (Status == ERROR_SUCCESS);}
BOOLWINAPIDnsFlushResolverCacheEntry_W( _In_ LPCWSTR pszEntry){ DNS_STATUS Status = ERROR_SUCCESS;
DPRINT1("DnsFlushResolverCacheEntry_W(%S)\n", pszEntry);
if (pszEntry == NULL) return FALSE;
RpcTryExcept { Status = R_ResolverFlushCacheEntry(NULL, pszEntry, DNS_TYPE_ANY); DPRINT("R_ResolverFlushCacheEntry() returned %lu\n", Status); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) { Status = RpcExceptionCode(); DPRINT("Exception returned %lu\n", Status); } RpcEndExcept;
return (Status == ERROR_SUCCESS);}
BOOLWINAPIDnsGetCacheDataTable( _Out_ PDNS_CACHE_ENTRY *DnsCache){ DNS_STATUS Status = ERROR_SUCCESS; PDNS_CACHE_ENTRY CacheEntries = NULL;
if (DnsCache == NULL) return FALSE;
RpcTryExcept { Status = CRrReadCache(NULL, &CacheEntries); DPRINT("CRrReadCache() returned %lu\n", Status); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) { Status = RpcExceptionCode(); DPRINT1("Exception returned %lu\n", Status); } RpcEndExcept;
if (Status != ERROR_SUCCESS) return FALSE;
if (CacheEntries == NULL) return FALSE;
*DnsCache = CacheEntries;
return TRUE;}
DWORDWINAPIGetCurrentTimeInSeconds(VOID){ FILETIME Time; FILETIME Adjustment; ULARGE_INTEGER lTime, lAdj; SYSTEMTIME st = {1970, 1, 0, 1, 0, 0, 0};
SystemTimeToFileTime(&st, &Adjustment); memcpy(&lAdj, &Adjustment, sizeof(lAdj)); GetSystemTimeAsFileTime(&Time); memcpy(&lTime, &Time, sizeof(lTime)); lTime.QuadPart -= lAdj.QuadPart; return (DWORD)(lTime.QuadPart/10000000ULL);}