2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/dnsapi/dnsapi/query.c
5 * PURPOSE: DNSAPI functions built on the ADNS library.
6 * PROGRAMER: Art Yerkes
22 _In_ PCWSTR AddressString
,
23 _Out_ PIN_ADDR pAddress
)
25 PCWSTR pTerminator
= NULL
;
28 Status
= RtlIpv4StringToAddressW(AddressString
,
32 if (NT_SUCCESS(Status
) && pTerminator
!= NULL
&& *pTerminator
== L
'\0')
42 _In_ PCWSTR AddressString
,
43 _Out_ PIN6_ADDR pAddress
)
45 PCWSTR pTerminator
= NULL
;
48 Status
= RtlIpv6StringToAddressW(AddressString
,
51 if (NT_SUCCESS(Status
) && pTerminator
!= NULL
&& *pTerminator
== L
'\0')
60 CreateRecordForIpAddress(
66 PDNS_RECORDW pRecord
= NULL
;
68 if (Type
== DNS_TYPE_A
)
70 if (ParseIpv4Address(Name
, &Ip4Address
))
72 pRecord
= RtlAllocateHeap(RtlGetProcessHeap(),
78 pRecord
->pName
= RtlAllocateHeap(RtlGetProcessHeap(),
80 (wcslen(Name
) + 1) * sizeof(WCHAR
));
83 RtlFreeHeap(RtlGetProcessHeap(), 0, pRecord
);
87 wcscpy(pRecord
->pName
, Name
);
88 pRecord
->wType
= DNS_TYPE_A
;
89 pRecord
->wDataLength
= sizeof(DNS_A_DATA
);
90 pRecord
->Flags
.S
.Section
= DnsSectionQuestion
;
91 pRecord
->Flags
.S
.CharSet
= DnsCharSetUnicode
;
92 pRecord
->dwTtl
= 7 * 24 * 60 * 60;
94 pRecord
->Data
.A
.IpAddress
= Ip4Address
.S_un
.S_addr
;
99 else if (Type
== DNS_TYPE_AAAA
)
101 if (ParseIpv6Address(Name
, &Ip6Address
))
103 pRecord
= RtlAllocateHeap(RtlGetProcessHeap(),
105 sizeof(DNS_RECORDW
));
109 pRecord
->pName
= RtlAllocateHeap(RtlGetProcessHeap(),
111 (wcslen(Name
) + 1) * sizeof(WCHAR
));
114 RtlFreeHeap(RtlGetProcessHeap(), 0, pRecord
);
118 wcscpy(pRecord
->pName
, Name
);
119 pRecord
->wType
= DNS_TYPE_AAAA
;
120 pRecord
->wDataLength
= sizeof(DNS_AAAA_DATA
);
121 pRecord
->Flags
.S
.Section
= DnsSectionQuestion
;
122 pRecord
->Flags
.S
.CharSet
= DnsCharSetUnicode
;
123 pRecord
->dwTtl
= 7 * 24 * 60 * 60;
125 CopyMemory(&pRecord
->Data
.AAAA
.Ip6Address
,
137 /* DnsQuery ****************************
138 * Begin a DNS query, and allow the result to be placed in the application
139 * supplied result pointer. The result can be manipulated with the record
142 * Name -- The DNS object to be queried.
143 * Type -- The type of records to be returned. These are
145 * Options -- Query options. DNS_QUERY_STANDARD is the base
146 * state, and every other option takes precedence.
147 * multiple options can be combined. Listed in
149 * Servers -- List of alternate servers (optional)
150 * QueryResultSet -- Pointer to the result pointer that will be filled
151 * when the response is available.
152 * Reserved -- Response as it appears on the wire. Optional.
156 DnsWToC(const WCHAR
*WideString
)
159 int AnsiLen
= WideCharToMultiByte(CP_ACP
,
169 AnsiString
= RtlAllocateHeap(RtlGetProcessHeap(), 0, AnsiLen
);
170 if (AnsiString
== NULL
)
174 WideCharToMultiByte(CP_ACP
,
187 DnsCToW(const CHAR
*NarrowString
)
190 int WideLen
= MultiByteToWideChar(CP_ACP
,
198 WideString
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WideLen
* sizeof(WCHAR
));
199 if (WideString
== NULL
)
203 MultiByteToWideChar(CP_ACP
,
214 DnsWToUTF8(const WCHAR
*WideString
)
217 int AnsiLen
= WideCharToMultiByte(CP_UTF8
,
227 AnsiString
= RtlAllocateHeap(RtlGetProcessHeap(), 0, AnsiLen
);
228 if (AnsiString
== NULL
)
232 WideCharToMultiByte(CP_UTF8
,
245 DnsUTF8ToW(const CHAR
*NarrowString
)
248 int WideLen
= MultiByteToWideChar(CP_UTF8
,
256 WideString
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WideLen
* sizeof(WCHAR
));
257 if (WideString
== NULL
)
261 MultiByteToWideChar(CP_UTF8
,
272 DnsQuery_CodePage(UINT CodePage
,
277 PDNS_RECORD
*QueryResultSet
,
283 PDNS_RECORD QueryResultWide
;
284 PDNS_RECORD ConvertedRecord
= 0, LastRecord
= 0;
287 return ERROR_INVALID_PARAMETER
;
288 if (QueryResultSet
== NULL
)
289 return ERROR_INVALID_PARAMETER
;
294 Buffer
= DnsCToW(Name
);
298 Buffer
= DnsUTF8ToW(Name
);
302 return ERROR_INVALID_PARAMETER
;
305 Status
= DnsQuery_W(Buffer
, Type
, Options
, Extra
, &QueryResultWide
, Reserved
);
307 while (Status
== ERROR_SUCCESS
&& QueryResultWide
)
309 switch (QueryResultWide
->wType
)
321 ConvertedRecord
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD
));
325 ConvertedRecord
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_TXT_DATA
) + QueryResultWide
->Data
.TXT
.dwStringCount
);
329 ConvertedRecord
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_NULL_DATA
) + QueryResultWide
->Data
.Null
.dwByteCount
);
332 if (ConvertedRecord
== NULL
)
335 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
337 DnsIntFreeRecordList(QueryResultWide
);
338 QueryResultSet
= NULL
;
339 return ERROR_OUTOFMEMORY
;
342 if (CodePage
== CP_ACP
)
344 ConvertedRecord
->pName
= DnsWToC((PWCHAR
)QueryResultWide
->pName
);
345 ConvertedRecord
->Flags
.S
.CharSet
= DnsCharSetAnsi
;
349 ConvertedRecord
->pName
= DnsWToUTF8((PWCHAR
)QueryResultWide
->pName
);
350 ConvertedRecord
->Flags
.S
.CharSet
= DnsCharSetUtf8
;
353 ConvertedRecord
->wType
= QueryResultWide
->wType
;
355 switch (QueryResultWide
->wType
)
359 ConvertedRecord
->wDataLength
= QueryResultWide
->wDataLength
;
360 memcpy(&ConvertedRecord
->Data
, &QueryResultWide
->Data
, QueryResultWide
->wDataLength
);
371 ConvertedRecord
->wDataLength
= sizeof(DNS_PTR_DATA
);
372 if (CodePage
== CP_ACP
)
373 ConvertedRecord
->Data
.PTR
.pNameHost
= DnsWToC((PWCHAR
)QueryResultWide
->Data
.PTR
.pNameHost
);
375 ConvertedRecord
->Data
.PTR
.pNameHost
= DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.PTR
.pNameHost
);
379 ConvertedRecord
->wDataLength
= sizeof(DNS_MINFO_DATA
);
380 if (CodePage
== CP_ACP
)
382 ConvertedRecord
->Data
.MINFO
.pNameMailbox
= DnsWToC((PWCHAR
)QueryResultWide
->Data
.MINFO
.pNameMailbox
);
383 ConvertedRecord
->Data
.MINFO
.pNameErrorsMailbox
= DnsWToC((PWCHAR
)QueryResultWide
->Data
.MINFO
.pNameErrorsMailbox
);
387 ConvertedRecord
->Data
.MINFO
.pNameMailbox
= DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.MINFO
.pNameMailbox
);
388 ConvertedRecord
->Data
.MINFO
.pNameErrorsMailbox
= DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.MINFO
.pNameErrorsMailbox
);
393 ConvertedRecord
->wDataLength
= sizeof(DNS_MX_DATA
);
394 if (CodePage
== CP_ACP
)
395 ConvertedRecord
->Data
.MX
.pNameExchange
= DnsWToC((PWCHAR
)QueryResultWide
->Data
.MX
.pNameExchange
);
397 ConvertedRecord
->Data
.MX
.pNameExchange
= DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.MX
.pNameExchange
);
398 ConvertedRecord
->Data
.MX
.wPreference
= QueryResultWide
->Data
.MX
.wPreference
;
402 ConvertedRecord
->wDataLength
= sizeof(DNS_TXT_DATA
) + (sizeof(PCHAR
) * QueryResultWide
->Data
.TXT
.dwStringCount
);
403 ConvertedRecord
->Data
.TXT
.dwStringCount
= QueryResultWide
->Data
.TXT
.dwStringCount
;
405 if (CodePage
== CP_ACP
)
406 for (i
= 0; i
< ConvertedRecord
->Data
.TXT
.dwStringCount
; i
++)
407 ConvertedRecord
->Data
.TXT
.pStringArray
[i
] = DnsWToC((PWCHAR
)QueryResultWide
->Data
.TXT
.pStringArray
[i
]);
409 for (i
= 0; i
< ConvertedRecord
->Data
.TXT
.dwStringCount
; i
++)
410 ConvertedRecord
->Data
.TXT
.pStringArray
[i
] = DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.TXT
.pStringArray
[i
]);
415 ConvertedRecord
->wDataLength
= sizeof(DNS_NULL_DATA
) + QueryResultWide
->Data
.Null
.dwByteCount
;
416 ConvertedRecord
->Data
.Null
.dwByteCount
= QueryResultWide
->Data
.Null
.dwByteCount
;
417 memcpy(&ConvertedRecord
->Data
.Null
.Data
, &QueryResultWide
->Data
.Null
.Data
, QueryResultWide
->Data
.Null
.dwByteCount
);
423 LastRecord
->pNext
= ConvertedRecord
;
424 LastRecord
= LastRecord
->pNext
;
428 LastRecord
= *QueryResultSet
= ConvertedRecord
;
431 QueryResultWide
= QueryResultWide
->pNext
;
435 LastRecord
->pNext
= 0;
438 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
440 if (QueryResultWide
) DnsIntFreeRecordList(QueryResultWide
);
446 DnsQuery_A(LPCSTR Name
,
450 PDNS_RECORD
*QueryResultSet
,
453 return DnsQuery_CodePage(CP_ACP
, Name
, Type
, Options
, Extra
, QueryResultSet
, Reserved
);
457 DnsQuery_UTF8(LPCSTR Name
,
461 PDNS_RECORD
*QueryResultSet
,
464 return DnsQuery_CodePage(CP_UTF8
, Name
, Type
, Options
, Extra
, QueryResultSet
, Reserved
);
469 DnsQuery_W(LPCWSTR Name
,
473 PDNS_RECORD
*QueryResultSet
,
477 PDNS_RECORDW pRecord
= NULL
;
478 DNS_STATUS Status
= ERROR_SUCCESS
;
480 DPRINT("DnsQuery_W()\n");
482 if ((Name
== NULL
) ||
483 (QueryResultSet
== NULL
))
484 return ERROR_INVALID_PARAMETER
;
486 *QueryResultSet
= NULL
;
488 /* Create an A or AAAA record for an IP4 or IP6 address */
489 pRecord
= CreateRecordForIpAddress(Name
,
493 *QueryResultSet
= (PDNS_RECORD
)pRecord
;
494 return ERROR_SUCCESS
;
499 Status
= R_ResolverQuery(NULL
,
504 (DNS_RECORDW
**)QueryResultSet
);
505 DPRINT("R_ResolverQuery() returned %lu\n", Status
);
507 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
509 Status
= RpcExceptionCode();
510 DPRINT("Exception returned %lu\n", Status
);
518 *xstrsave(const WCHAR
*str
)
523 /* FIXME: how much instead of MAX_PATH? */
524 StringCbLengthW(str
, MAX_PATH
, &len
);
527 p
= RtlAllocateHeap(RtlGetProcessHeap(), 0, len
);
530 StringCbCopyW(p
, len
, str
);
536 *xstrsaveA(const CHAR
*str
)
541 /* FIXME: how much instead of MAX_PATH? */
542 StringCbLengthA(str
, MAX_PATH
, &len
);
545 p
= RtlAllocateHeap(RtlGetProcessHeap(), 0, len
);
548 StringCbCopyA(p
, len
, str
);
554 /* This function is far from perfect but it works enough */
556 CheckForCurrentHostname(CONST CHAR
* Name
, PFIXED_INFO network_info
)
559 DWORD AdapterAddressesSize
, Status
;
560 IP4_ADDRESS ret
= 0, Address
;
561 PIP_ADAPTER_ADDRESSES Addresses
= NULL
, pip
;
564 if (network_info
->DomainName
[0])
568 StringCchLengthA(network_info
->HostName
, sizeof(network_info
->HostName
), &StringLength
);
569 TempSize
+= StringLength
;
570 StringCchLengthA(network_info
->DomainName
, sizeof(network_info
->DomainName
), &StringLength
);
571 TempSize
+= StringLength
;
572 TempName
= RtlAllocateHeap(RtlGetProcessHeap(), 0, TempSize
);
573 StringCchCopyA(TempName
, TempSize
, network_info
->HostName
);
574 StringCchCatA(TempName
, TempSize
, ".");
575 StringCchCatA(TempName
, TempSize
, network_info
->DomainName
);
579 TempName
= RtlAllocateHeap(RtlGetProcessHeap(), 0, 1);
582 Found
= !stricmp(Name
, network_info
->HostName
) || !stricmp(Name
, TempName
);
583 RtlFreeHeap(RtlGetProcessHeap(), 0, TempName
);
588 /* get adapter info */
589 AdapterAddressesSize
= 0;
590 GetAdaptersAddresses(AF_INET
,
591 GAA_FLAG_SKIP_FRIENDLY_NAME
| GAA_FLAG_SKIP_DNS_SERVER
|
592 GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
,
595 &AdapterAddressesSize
);
596 if (!AdapterAddressesSize
)
600 Addresses
= RtlAllocateHeap(RtlGetProcessHeap(), 0, AdapterAddressesSize
);
601 Status
= GetAdaptersAddresses(AF_INET
,
602 GAA_FLAG_SKIP_FRIENDLY_NAME
| GAA_FLAG_SKIP_DNS_SERVER
|
603 GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
,
606 &AdapterAddressesSize
);
609 RtlFreeHeap(RtlGetProcessHeap(), 0, Addresses
);
612 for (pip
= Addresses
; pip
!= NULL
; pip
= pip
->Next
) {
613 Address
= ((LPSOCKADDR_IN
)pip
->FirstUnicastAddress
->Address
.lpSockaddr
)->sin_addr
.S_un
.S_addr
;
614 if (Address
!= ntohl(INADDR_LOOPBACK
))
617 if (Address
&& Address
!= ntohl(INADDR_LOOPBACK
))
621 RtlFreeHeap(RtlGetProcessHeap(), 0, Addresses
);
628 Query_Main(LPCWSTR Name
,
631 PDNS_RECORD
*QueryResultSet
)
634 int quflags
= (Options
& DNS_QUERY_NO_RECURSION
) == 0 ? adns_qf_search
: 0;
638 unsigned i
, CNameLoop
;
639 PFIXED_INFO network_info
;
640 ULONG network_info_blen
= 0;
641 DWORD network_info_result
;
645 PCHAR HostWithDomainName
;
650 return ERROR_INVALID_PARAMETER
;
651 if (QueryResultSet
== NULL
)
652 return ERROR_INVALID_PARAMETER
;
654 *QueryResultSet
= NULL
;
659 /* FIXME: how much instead of MAX_PATH? */
660 NameLen
= WideCharToMultiByte(CP_ACP
,
668 AnsiName
= RtlAllocateHeap(RtlGetProcessHeap(), 0, NameLen
);
669 if (NULL
== AnsiName
)
671 return ERROR_OUTOFMEMORY
;
673 WideCharToMultiByte(CP_ACP
,
683 /* Check allowed characters
684 * According to RFC a-z,A-Z,0-9,-,_, but can't start or end with - or _
686 if (AnsiName
[0] == '-' || AnsiName
[0] == '_' || AnsiName
[NameLen
- 1] == '-' ||
687 AnsiName
[NameLen
- 1] == '_' || strstr(AnsiName
, "..") != NULL
)
689 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
690 return ERROR_INVALID_NAME
;
695 if (!((AnsiName
[i
] >= 'a' && AnsiName
[i
] <= 'z') ||
696 (AnsiName
[i
] >= 'A' && AnsiName
[i
] <= 'Z') ||
697 (AnsiName
[i
] >= '0' && AnsiName
[i
] <= '9') ||
698 AnsiName
[i
] == '-' || AnsiName
[i
] == '_' || AnsiName
[i
] == '.'))
700 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
701 return DNS_ERROR_INVALID_NAME_CHAR
;
706 network_info_result
= GetNetworkParams(NULL
, &network_info_blen
);
707 network_info
= (PFIXED_INFO
)RtlAllocateHeap(RtlGetProcessHeap(), 0, (size_t)network_info_blen
);
708 if (NULL
== network_info
)
710 return ERROR_OUTOFMEMORY
;
713 network_info_result
= GetNetworkParams(network_info
, &network_info_blen
);
714 if (network_info_result
!= ERROR_SUCCESS
)
716 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
717 return network_info_result
;
720 if ((Address
= CheckForCurrentHostname(NameLen
!= 0 ? AnsiName
: network_info
->HostName
, network_info
)) != 0)
722 size_t TempLen
= 2, StringLength
= 0;
723 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
724 StringCchLengthA(network_info
->HostName
, sizeof(network_info
->HostName
), &StringLength
);
725 TempLen
+= StringLength
;
726 StringCchLengthA(network_info
->DomainName
, sizeof(network_info
->DomainName
), &StringLength
);
727 TempLen
+= StringLength
;
728 HostWithDomainName
= (PCHAR
)RtlAllocateHeap(RtlGetProcessHeap(), 0, TempLen
);
729 StringCchCopyA(HostWithDomainName
, TempLen
, network_info
->HostName
);
730 if (network_info
->DomainName
[0])
732 StringCchCatA(HostWithDomainName
, TempLen
, ".");
733 StringCchCatA(HostWithDomainName
, TempLen
, network_info
->DomainName
);
735 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
736 *QueryResultSet
= (PDNS_RECORD
)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD
));
738 if (NULL
== *QueryResultSet
)
740 RtlFreeHeap(RtlGetProcessHeap(), 0, HostWithDomainName
);
741 return ERROR_OUTOFMEMORY
;
744 (*QueryResultSet
)->pNext
= NULL
;
745 (*QueryResultSet
)->wType
= Type
;
746 (*QueryResultSet
)->wDataLength
= sizeof(DNS_A_DATA
);
747 (*QueryResultSet
)->Flags
.S
.Section
= DnsSectionAnswer
;
748 (*QueryResultSet
)->Flags
.S
.CharSet
= DnsCharSetUnicode
;
749 (*QueryResultSet
)->Data
.A
.IpAddress
= Address
;
751 (*QueryResultSet
)->pName
= (LPSTR
)DnsCToW(HostWithDomainName
);
753 RtlFreeHeap(RtlGetProcessHeap(), 0, HostWithDomainName
);
754 return (*QueryResultSet
)->pName
? ERROR_SUCCESS
: ERROR_OUTOFMEMORY
;
757 if ((Options
& DNS_QUERY_NO_WIRE_QUERY
) != 0)
759 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
760 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
761 return ERROR_FILE_NOT_FOUND
;
764 adns_error
= adns_init(&astate
, adns_if_noenv
| adns_if_noerrprint
| adns_if_noserverwarn
, 0);
765 if (adns_error
!= adns_s_ok
)
767 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
768 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
769 return DnsIntTranslateAdnsToDNS_STATUS(adns_error
);
771 for (pip
= &(network_info
->DnsServerList
); pip
; pip
= pip
->Next
)
773 addr
.s_addr
= inet_addr(pip
->IpAddress
.String
);
774 if ((addr
.s_addr
!= INADDR_ANY
) && (addr
.s_addr
!= INADDR_NONE
))
775 adns_addserver(astate
, addr
);
777 if (network_info
->DomainName
[0])
779 adns_ccf_search(astate
, "LOCALDOMAIN", -1, network_info
->DomainName
);
781 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
783 if (!adns_numservers(astate
))
785 /* There are no servers to query so bail out */
787 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
788 return ERROR_FILE_NOT_FOUND
;
792 * adns doesn't resolve chained CNAME records (a CNAME which points to
793 * another CNAME pointing to another... pointing to an A record), according
794 * to a mailing list thread the authors believe that chained CNAME records
795 * are invalid and the DNS entries should be fixed. That's a nice academic
796 * standpoint, but there certainly are chained CNAME records out there,
797 * even some fairly major ones (at the time of this writing
798 * download.mozilla.org is a chained CNAME). Everyone else seems to resolve
799 * these fine, so we should too. So we loop here to try to resolve CNAME
800 * chains ourselves. Of course, there must be a limit to protect against
804 #define CNAME_LOOP_MAX 16
806 CurrentName
= AnsiName
;
808 for (CNameLoop
= 0; CNameLoop
< CNAME_LOOP_MAX
; CNameLoop
++)
810 adns_error
= adns_synchronous(astate
, CurrentName
, adns_r_addr
, quflags
, &answer
);
812 if (adns_error
!= adns_s_ok
)
816 if (CurrentName
!= AnsiName
)
817 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
819 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
820 return DnsIntTranslateAdnsToDNS_STATUS(adns_error
);
823 if (answer
&& answer
->rrs
.addr
)
825 if (CurrentName
!= AnsiName
)
826 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
828 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
829 *QueryResultSet
= (PDNS_RECORD
)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD
));
831 if (NULL
== *QueryResultSet
)
834 return ERROR_OUTOFMEMORY
;
837 (*QueryResultSet
)->pNext
= NULL
;
838 (*QueryResultSet
)->wType
= Type
;
839 (*QueryResultSet
)->wDataLength
= sizeof(DNS_A_DATA
);
840 (*QueryResultSet
)->Flags
.S
.Section
= DnsSectionAnswer
;
841 (*QueryResultSet
)->Flags
.S
.CharSet
= DnsCharSetUnicode
;
842 (*QueryResultSet
)->Data
.A
.IpAddress
= answer
->rrs
.addr
->addr
.inet
.sin_addr
.s_addr
;
846 (*QueryResultSet
)->pName
= (LPSTR
)xstrsave(Name
);
848 return (*QueryResultSet
)->pName
? ERROR_SUCCESS
: ERROR_OUTOFMEMORY
;
851 if (NULL
== answer
|| adns_s_prohibitedcname
!= answer
->status
|| NULL
== answer
->cname
)
855 if (CurrentName
!= AnsiName
)
856 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
858 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
859 return ERROR_FILE_NOT_FOUND
;
862 if (CurrentName
!= AnsiName
)
863 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
865 CurrentName
= (LPSTR
)xstrsaveA(answer
->cname
);
869 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
871 return ERROR_OUTOFMEMORY
;
876 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
877 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
878 return ERROR_FILE_NOT_FOUND
;
881 return ERROR_OUTOFMEMORY
; /* XXX arty: find a better error code. */
886 DnsIntFreeRecordList(PDNS_RECORD ToDelete
)
889 PDNS_RECORD next
= 0;
894 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->pName
);
896 switch(ToDelete
->wType
)
906 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->Data
.PTR
.pNameHost
);
911 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->Data
.MX
.pNameExchange
);
915 for(i
= 0; i
< ToDelete
->Data
.TXT
.dwStringCount
; i
++)
916 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->Data
.TXT
.pStringArray
[i
]);
918 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->Data
.TXT
.pStringArray
);
922 next
= ToDelete
->pNext
;
923 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
);
930 DnsFlushResolverCache(VOID
)
932 DNS_STATUS Status
= ERROR_SUCCESS
;
934 DPRINT("DnsFlushResolverCache()\n");
938 Status
= R_ResolverFlushCache(NULL
);
939 DPRINT("R_ResolverFlushCache() returned %lu\n", Status
);
941 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
943 Status
= RpcExceptionCode();
944 DPRINT("Exception returned %lu\n", Status
);
948 return (Status
== ERROR_SUCCESS
);
953 DnsGetCacheDataTable(
954 _Out_ PDNS_CACHE_ENTRY
*DnsCache
)
956 DNS_STATUS Status
= ERROR_SUCCESS
;
957 PDNS_CACHE_ENTRY CacheEntries
= NULL
;
959 if (DnsCache
== NULL
)
964 Status
= CRrReadCache(NULL
,
966 DPRINT("CRrReadCache() returned %lu\n", Status
);
968 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
970 Status
= RpcExceptionCode();
971 DPRINT1("Exception returned %lu\n", Status
);
975 if (Status
!= ERROR_SUCCESS
)
978 if (CacheEntries
== NULL
)
981 *DnsCache
= CacheEntries
;
988 GetCurrentTimeInSeconds(VOID
)
992 ULARGE_INTEGER lTime
, lAdj
;
993 SYSTEMTIME st
= {1970, 1, 0, 1, 0, 0, 0};
995 SystemTimeToFileTime(&st
, &Adjustment
);
996 memcpy(&lAdj
, &Adjustment
, sizeof(lAdj
));
997 GetSystemTimeAsFileTime(&Time
);
998 memcpy(&lTime
, &Time
, sizeof(lTime
));
999 lTime
.QuadPart
-= lAdj
.QuadPart
;
1000 return (DWORD
)(lTime
.QuadPart
/10000000ULL);