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
20 /* DnsQuery ****************************
21 * Begin a DNS query, and allow the result to be placed in the application
22 * supplied result pointer. The result can be manipulated with the record
25 * Name -- The DNS object to be queried.
26 * Type -- The type of records to be returned. These are
28 * Options -- Query options. DNS_QUERY_STANDARD is the base
29 * state, and every other option takes precedence.
30 * multiple options can be combined. Listed in
32 * Servers -- List of alternate servers (optional)
33 * QueryResultSet -- Pointer to the result pointer that will be filled
34 * when the response is available.
35 * Reserved -- Response as it appears on the wire. Optional.
39 DnsWToC(const WCHAR
*WideString
)
42 int AnsiLen
= WideCharToMultiByte(CP_ACP
,
52 AnsiString
= RtlAllocateHeap(RtlGetProcessHeap(), 0, AnsiLen
);
53 if (AnsiString
== NULL
)
57 WideCharToMultiByte(CP_ACP
,
70 DnsCToW(const CHAR
*NarrowString
)
73 int WideLen
= MultiByteToWideChar(CP_ACP
,
81 WideString
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WideLen
* sizeof(WCHAR
));
82 if (WideString
== NULL
)
86 MultiByteToWideChar(CP_ACP
,
97 DnsWToUTF8(const WCHAR
*WideString
)
100 int AnsiLen
= WideCharToMultiByte(CP_UTF8
,
110 AnsiString
= RtlAllocateHeap(RtlGetProcessHeap(), 0, AnsiLen
);
111 if (AnsiString
== NULL
)
115 WideCharToMultiByte(CP_UTF8
,
128 DnsUTF8ToW(const CHAR
*NarrowString
)
131 int WideLen
= MultiByteToWideChar(CP_UTF8
,
139 WideString
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WideLen
* sizeof(WCHAR
));
140 if (WideString
== NULL
)
144 MultiByteToWideChar(CP_UTF8
,
155 DnsQuery_CodePage(UINT CodePage
,
160 PDNS_RECORD
*QueryResultSet
,
166 PDNS_RECORD QueryResultWide
;
167 PDNS_RECORD ConvertedRecord
= 0, LastRecord
= 0;
170 return ERROR_INVALID_PARAMETER
;
171 if (QueryResultSet
== NULL
)
172 return ERROR_INVALID_PARAMETER
;
177 Buffer
= DnsCToW(Name
);
181 Buffer
= DnsUTF8ToW(Name
);
185 return ERROR_INVALID_PARAMETER
;
188 Status
= DnsQuery_W(Buffer
, Type
, Options
, Extra
, &QueryResultWide
, Reserved
);
190 while (Status
== ERROR_SUCCESS
&& QueryResultWide
)
192 switch (QueryResultWide
->wType
)
204 ConvertedRecord
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD
));
208 ConvertedRecord
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_TXT_DATA
) + QueryResultWide
->Data
.TXT
.dwStringCount
);
212 ConvertedRecord
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_NULL_DATA
) + QueryResultWide
->Data
.Null
.dwByteCount
);
215 if (ConvertedRecord
== NULL
)
218 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
220 DnsIntFreeRecordList(QueryResultWide
);
221 QueryResultSet
= NULL
;
222 return ERROR_OUTOFMEMORY
;
225 if (CodePage
== CP_ACP
)
227 ConvertedRecord
->pName
= DnsWToC((PWCHAR
)QueryResultWide
->pName
);
228 ConvertedRecord
->Flags
.S
.CharSet
= DnsCharSetAnsi
;
232 ConvertedRecord
->pName
= DnsWToUTF8((PWCHAR
)QueryResultWide
->pName
);
233 ConvertedRecord
->Flags
.S
.CharSet
= DnsCharSetUtf8
;
236 ConvertedRecord
->wType
= QueryResultWide
->wType
;
238 switch (QueryResultWide
->wType
)
242 ConvertedRecord
->wDataLength
= QueryResultWide
->wDataLength
;
243 memcpy(&ConvertedRecord
->Data
, &QueryResultWide
->Data
, QueryResultWide
->wDataLength
);
254 ConvertedRecord
->wDataLength
= sizeof(DNS_PTR_DATA
);
255 if (CodePage
== CP_ACP
)
256 ConvertedRecord
->Data
.PTR
.pNameHost
= DnsWToC((PWCHAR
)QueryResultWide
->Data
.PTR
.pNameHost
);
258 ConvertedRecord
->Data
.PTR
.pNameHost
= DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.PTR
.pNameHost
);
262 ConvertedRecord
->wDataLength
= sizeof(DNS_MINFO_DATA
);
263 if (CodePage
== CP_ACP
)
265 ConvertedRecord
->Data
.MINFO
.pNameMailbox
= DnsWToC((PWCHAR
)QueryResultWide
->Data
.MINFO
.pNameMailbox
);
266 ConvertedRecord
->Data
.MINFO
.pNameErrorsMailbox
= DnsWToC((PWCHAR
)QueryResultWide
->Data
.MINFO
.pNameErrorsMailbox
);
270 ConvertedRecord
->Data
.MINFO
.pNameMailbox
= DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.MINFO
.pNameMailbox
);
271 ConvertedRecord
->Data
.MINFO
.pNameErrorsMailbox
= DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.MINFO
.pNameErrorsMailbox
);
276 ConvertedRecord
->wDataLength
= sizeof(DNS_MX_DATA
);
277 if (CodePage
== CP_ACP
)
278 ConvertedRecord
->Data
.MX
.pNameExchange
= DnsWToC((PWCHAR
)QueryResultWide
->Data
.MX
.pNameExchange
);
280 ConvertedRecord
->Data
.MX
.pNameExchange
= DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.MX
.pNameExchange
);
281 ConvertedRecord
->Data
.MX
.wPreference
= QueryResultWide
->Data
.MX
.wPreference
;
285 ConvertedRecord
->wDataLength
= sizeof(DNS_TXT_DATA
) + (sizeof(PCHAR
) * QueryResultWide
->Data
.TXT
.dwStringCount
);
286 ConvertedRecord
->Data
.TXT
.dwStringCount
= QueryResultWide
->Data
.TXT
.dwStringCount
;
288 if (CodePage
== CP_ACP
)
289 for (i
= 0; i
< ConvertedRecord
->Data
.TXT
.dwStringCount
; i
++)
290 ConvertedRecord
->Data
.TXT
.pStringArray
[i
] = DnsWToC((PWCHAR
)QueryResultWide
->Data
.TXT
.pStringArray
[i
]);
292 for (i
= 0; i
< ConvertedRecord
->Data
.TXT
.dwStringCount
; i
++)
293 ConvertedRecord
->Data
.TXT
.pStringArray
[i
] = DnsWToUTF8((PWCHAR
)QueryResultWide
->Data
.TXT
.pStringArray
[i
]);
298 ConvertedRecord
->wDataLength
= sizeof(DNS_NULL_DATA
) + QueryResultWide
->Data
.Null
.dwByteCount
;
299 ConvertedRecord
->Data
.Null
.dwByteCount
= QueryResultWide
->Data
.Null
.dwByteCount
;
300 memcpy(&ConvertedRecord
->Data
.Null
.Data
, &QueryResultWide
->Data
.Null
.Data
, QueryResultWide
->Data
.Null
.dwByteCount
);
306 LastRecord
->pNext
= ConvertedRecord
;
307 LastRecord
= LastRecord
->pNext
;
311 LastRecord
= *QueryResultSet
= ConvertedRecord
;
314 QueryResultWide
= QueryResultWide
->pNext
;
318 LastRecord
->pNext
= 0;
321 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
323 if (QueryResultWide
) DnsIntFreeRecordList(QueryResultWide
);
329 DnsQuery_A(LPCSTR Name
,
333 PDNS_RECORD
*QueryResultSet
,
336 return DnsQuery_CodePage(CP_ACP
, Name
, Type
, Options
, Extra
, QueryResultSet
, Reserved
);
340 DnsQuery_UTF8(LPCSTR Name
,
344 PDNS_RECORD
*QueryResultSet
,
347 return DnsQuery_CodePage(CP_UTF8
, Name
, Type
, Options
, Extra
, QueryResultSet
, Reserved
);
351 *xstrsave(const WCHAR
*str
)
356 /* FIXME: how much instead of MAX_PATH? */
357 StringCbLengthW(str
, MAX_PATH
, &len
);
360 p
= RtlAllocateHeap(RtlGetProcessHeap(), 0, len
);
363 StringCbCopyW(p
, len
, str
);
369 *xstrsaveA(const CHAR
*str
)
374 /* FIXME: how much instead of MAX_PATH? */
375 StringCbLengthA(str
, MAX_PATH
, &len
);
378 p
= RtlAllocateHeap(RtlGetProcessHeap(), 0, len
);
381 StringCbCopyA(p
, len
, str
);
387 /* This function is far from perfect but it works enough */
389 CheckForCurrentHostname(CONST CHAR
* Name
, PFIXED_INFO network_info
)
392 DWORD AdapterAddressesSize
, Status
;
393 IP4_ADDRESS ret
= 0, Address
;
394 PIP_ADAPTER_ADDRESSES Addresses
= NULL
, pip
;
397 if (network_info
->DomainName
[0])
401 StringCchLengthA(network_info
->HostName
, sizeof(network_info
->HostName
), &StringLength
);
402 TempSize
+= StringLength
;
403 StringCchLengthA(network_info
->DomainName
, sizeof(network_info
->DomainName
), &StringLength
);
404 TempSize
+= StringLength
;
405 TempName
= RtlAllocateHeap(RtlGetProcessHeap(), 0, TempSize
);
406 StringCchCopyA(TempName
, TempSize
, network_info
->HostName
);
407 StringCchCatA(TempName
, TempSize
, ".");
408 StringCchCatA(TempName
, TempSize
, network_info
->DomainName
);
412 TempName
= RtlAllocateHeap(RtlGetProcessHeap(), 0, 1);
415 Found
= !stricmp(Name
, network_info
->HostName
) || !stricmp(Name
, TempName
);
416 RtlFreeHeap(RtlGetProcessHeap(), 0, TempName
);
421 /* get adapter info */
422 AdapterAddressesSize
= 0;
423 GetAdaptersAddresses(AF_INET
,
424 GAA_FLAG_SKIP_FRIENDLY_NAME
| GAA_FLAG_SKIP_DNS_SERVER
|
425 GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
,
428 &AdapterAddressesSize
);
429 if (!AdapterAddressesSize
)
433 Addresses
= RtlAllocateHeap(RtlGetProcessHeap(), 0, AdapterAddressesSize
);
434 Status
= GetAdaptersAddresses(AF_INET
,
435 GAA_FLAG_SKIP_FRIENDLY_NAME
| GAA_FLAG_SKIP_DNS_SERVER
|
436 GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_MULTICAST
,
439 &AdapterAddressesSize
);
442 RtlFreeHeap(RtlGetProcessHeap(), 0, Addresses
);
445 for (pip
= Addresses
; pip
!= NULL
; pip
= pip
->Next
) {
446 Address
= ((LPSOCKADDR_IN
)pip
->FirstUnicastAddress
->Address
.lpSockaddr
)->sin_addr
.S_un
.S_addr
;
447 if (Address
!= ntohl(INADDR_LOOPBACK
))
450 if (Address
&& Address
!= ntohl(INADDR_LOOPBACK
))
454 RtlFreeHeap(RtlGetProcessHeap(), 0, Addresses
);
459 ParseV4Address(LPCSTR AddressString
,
462 CHAR
* cp
= (CHAR
*)AddressString
;
465 DWORD parts
[4], *pp
= parts
;
468 if (!isdigit(*cp
)) return FALSE
;
472 * Collect number up to ``.''.
473 * Values are specified as for C:
474 * 0x=hex, 0=octal, other=decimal.
478 if (*++cp
== 'x' || *cp
== 'X')
485 val
= (val
* base
) + (c
- '0');
489 if (base
== 16 && isxdigit(c
)) {
490 val
= (val
<< 4) + (c
+ 10 - (islower(c
) ? 'a' : 'A'));
501 if (pp
>= parts
+ 4) return FALSE
;
507 * Check for trailing characters.
509 if (*cp
&& *cp
> ' ') return FALSE
;
511 if (pp
>= parts
+ 4) return FALSE
;
514 * Concoct the address according to
515 * the number of parts specified.
517 if ((DWORD
)(pp
- parts
) != 4) return FALSE
;
518 if (parts
[0] > 0xff || parts
[1] > 0xff || parts
[2] > 0xff || parts
[3] > 0xff) return FALSE
;
519 val
= (parts
[3] << 24) | (parts
[2] << 16) | (parts
[1] << 8) | parts
[0];
529 DnsQuery_W(LPCWSTR Name
,
533 PDNS_RECORD
*QueryResultSet
,
537 DNS_STATUS Status
= ERROR_SUCCESS
;
539 DPRINT("DnsQuery_W()\n");
541 *QueryResultSet
= NULL
;
545 Status
= R_ResolverQuery(NULL
,
550 (DNS_RECORDW
**)QueryResultSet
);
551 DPRINT("R_ResolverQuery() returned %lu\n", Status
);
553 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
555 Status
= RpcExceptionCode();
556 DPRINT("Exception returned %lu\n", Status
);
566 Query_Main(LPCWSTR Name
,
569 PDNS_RECORD
*QueryResultSet
)
572 int quflags
= (Options
& DNS_QUERY_NO_RECURSION
) == 0 ? adns_qf_search
: 0;
576 unsigned i
, CNameLoop
;
577 PFIXED_INFO network_info
;
578 ULONG network_info_blen
= 0;
579 DWORD network_info_result
;
583 PCHAR HostWithDomainName
;
588 return ERROR_INVALID_PARAMETER
;
589 if (QueryResultSet
== NULL
)
590 return ERROR_INVALID_PARAMETER
;
592 *QueryResultSet
= NULL
;
597 /* FIXME: how much instead of MAX_PATH? */
598 NameLen
= WideCharToMultiByte(CP_ACP
,
606 AnsiName
= RtlAllocateHeap(RtlGetProcessHeap(), 0, NameLen
);
607 if (NULL
== AnsiName
)
609 return ERROR_OUTOFMEMORY
;
611 WideCharToMultiByte(CP_ACP
,
620 /* Is it an IPv4 address? */
621 if (ParseV4Address(AnsiName
, &Address
))
623 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
624 *QueryResultSet
= (PDNS_RECORD
)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD
));
626 if (NULL
== *QueryResultSet
)
628 return ERROR_OUTOFMEMORY
;
631 (*QueryResultSet
)->pNext
= NULL
;
632 (*QueryResultSet
)->wType
= Type
;
633 (*QueryResultSet
)->wDataLength
= sizeof(DNS_A_DATA
);
634 (*QueryResultSet
)->Flags
.S
.Section
= DnsSectionAnswer
;
635 (*QueryResultSet
)->Flags
.S
.CharSet
= DnsCharSetUnicode
;
636 (*QueryResultSet
)->Data
.A
.IpAddress
= Address
;
638 (*QueryResultSet
)->pName
= (LPSTR
)xstrsave(Name
);
640 return (*QueryResultSet
)->pName
? ERROR_SUCCESS
: ERROR_OUTOFMEMORY
;
643 /* Check allowed characters
644 * According to RFC a-z,A-Z,0-9,-,_, but can't start or end with - or _
646 if (AnsiName
[0] == '-' || AnsiName
[0] == '_' || AnsiName
[NameLen
- 1] == '-' ||
647 AnsiName
[NameLen
- 1] == '_' || strstr(AnsiName
, "..") != NULL
)
649 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
650 return ERROR_INVALID_NAME
;
655 if (!((AnsiName
[i
] >= 'a' && AnsiName
[i
] <= 'z') ||
656 (AnsiName
[i
] >= 'A' && AnsiName
[i
] <= 'Z') ||
657 (AnsiName
[i
] >= '0' && AnsiName
[i
] <= '9') ||
658 AnsiName
[i
] == '-' || AnsiName
[i
] == '_' || AnsiName
[i
] == '.'))
660 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
661 return DNS_ERROR_INVALID_NAME_CHAR
;
666 network_info_result
= GetNetworkParams(NULL
, &network_info_blen
);
667 network_info
= (PFIXED_INFO
)RtlAllocateHeap(RtlGetProcessHeap(), 0, (size_t)network_info_blen
);
668 if (NULL
== network_info
)
670 return ERROR_OUTOFMEMORY
;
673 network_info_result
= GetNetworkParams(network_info
, &network_info_blen
);
674 if (network_info_result
!= ERROR_SUCCESS
)
676 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
677 return network_info_result
;
680 if ((Address
= CheckForCurrentHostname(NameLen
!= 0 ? AnsiName
: network_info
->HostName
, network_info
)) != 0)
682 size_t TempLen
= 2, StringLength
= 0;
683 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
684 StringCchLengthA(network_info
->HostName
, sizeof(network_info
->HostName
), &StringLength
);
685 TempLen
+= StringLength
;
686 StringCchLengthA(network_info
->DomainName
, sizeof(network_info
->DomainName
), &StringLength
);
687 TempLen
+= StringLength
;
688 HostWithDomainName
= (PCHAR
)RtlAllocateHeap(RtlGetProcessHeap(), 0, TempLen
);
689 StringCchCopyA(HostWithDomainName
, TempLen
, network_info
->HostName
);
690 if (network_info
->DomainName
[0])
692 StringCchCatA(HostWithDomainName
, TempLen
, ".");
693 StringCchCatA(HostWithDomainName
, TempLen
, network_info
->DomainName
);
695 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
696 *QueryResultSet
= (PDNS_RECORD
)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD
));
698 if (NULL
== *QueryResultSet
)
700 RtlFreeHeap(RtlGetProcessHeap(), 0, HostWithDomainName
);
701 return ERROR_OUTOFMEMORY
;
704 (*QueryResultSet
)->pNext
= NULL
;
705 (*QueryResultSet
)->wType
= Type
;
706 (*QueryResultSet
)->wDataLength
= sizeof(DNS_A_DATA
);
707 (*QueryResultSet
)->Flags
.S
.Section
= DnsSectionAnswer
;
708 (*QueryResultSet
)->Flags
.S
.CharSet
= DnsCharSetUnicode
;
709 (*QueryResultSet
)->Data
.A
.IpAddress
= Address
;
711 (*QueryResultSet
)->pName
= (LPSTR
)DnsCToW(HostWithDomainName
);
713 RtlFreeHeap(RtlGetProcessHeap(), 0, HostWithDomainName
);
714 return (*QueryResultSet
)->pName
? ERROR_SUCCESS
: ERROR_OUTOFMEMORY
;
717 if ((Options
& DNS_QUERY_NO_WIRE_QUERY
) != 0)
719 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
720 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
721 return ERROR_FILE_NOT_FOUND
;
724 adns_error
= adns_init(&astate
, adns_if_noenv
| adns_if_noerrprint
| adns_if_noserverwarn
, 0);
725 if (adns_error
!= adns_s_ok
)
727 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
728 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
729 return DnsIntTranslateAdnsToDNS_STATUS(adns_error
);
731 for (pip
= &(network_info
->DnsServerList
); pip
; pip
= pip
->Next
)
733 addr
.s_addr
= inet_addr(pip
->IpAddress
.String
);
734 if ((addr
.s_addr
!= INADDR_ANY
) && (addr
.s_addr
!= INADDR_NONE
))
735 adns_addserver(astate
, addr
);
737 if (network_info
->DomainName
[0])
739 adns_ccf_search(astate
, "LOCALDOMAIN", -1, network_info
->DomainName
);
741 RtlFreeHeap(RtlGetProcessHeap(), 0, network_info
);
743 if (!adns_numservers(astate
))
745 /* There are no servers to query so bail out */
747 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
748 return ERROR_FILE_NOT_FOUND
;
752 * adns doesn't resolve chained CNAME records (a CNAME which points to
753 * another CNAME pointing to another... pointing to an A record), according
754 * to a mailing list thread the authors believe that chained CNAME records
755 * are invalid and the DNS entries should be fixed. That's a nice academic
756 * standpoint, but there certainly are chained CNAME records out there,
757 * even some fairly major ones (at the time of this writing
758 * download.mozilla.org is a chained CNAME). Everyone else seems to resolve
759 * these fine, so we should too. So we loop here to try to resolve CNAME
760 * chains ourselves. Of course, there must be a limit to protect against
764 #define CNAME_LOOP_MAX 16
766 CurrentName
= AnsiName
;
768 for (CNameLoop
= 0; CNameLoop
< CNAME_LOOP_MAX
; CNameLoop
++)
770 adns_error
= adns_synchronous(astate
, CurrentName
, adns_r_addr
, quflags
, &answer
);
772 if (adns_error
!= adns_s_ok
)
776 if (CurrentName
!= AnsiName
)
777 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
779 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
780 return DnsIntTranslateAdnsToDNS_STATUS(adns_error
);
783 if (answer
&& answer
->rrs
.addr
)
785 if (CurrentName
!= AnsiName
)
786 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
788 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
789 *QueryResultSet
= (PDNS_RECORD
)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD
));
791 if (NULL
== *QueryResultSet
)
794 return ERROR_OUTOFMEMORY
;
797 (*QueryResultSet
)->pNext
= NULL
;
798 (*QueryResultSet
)->wType
= Type
;
799 (*QueryResultSet
)->wDataLength
= sizeof(DNS_A_DATA
);
800 (*QueryResultSet
)->Flags
.S
.Section
= DnsSectionAnswer
;
801 (*QueryResultSet
)->Flags
.S
.CharSet
= DnsCharSetUnicode
;
802 (*QueryResultSet
)->Data
.A
.IpAddress
= answer
->rrs
.addr
->addr
.inet
.sin_addr
.s_addr
;
806 (*QueryResultSet
)->pName
= (LPSTR
)xstrsave(Name
);
808 return (*QueryResultSet
)->pName
? ERROR_SUCCESS
: ERROR_OUTOFMEMORY
;
811 if (NULL
== answer
|| adns_s_prohibitedcname
!= answer
->status
|| NULL
== answer
->cname
)
815 if (CurrentName
!= AnsiName
)
816 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
818 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
819 return ERROR_FILE_NOT_FOUND
;
822 if (CurrentName
!= AnsiName
)
823 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
825 CurrentName
= (LPSTR
)xstrsaveA(answer
->cname
);
829 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
831 return ERROR_OUTOFMEMORY
;
836 RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName
);
837 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName
);
838 return ERROR_FILE_NOT_FOUND
;
841 return ERROR_OUTOFMEMORY
; /* XXX arty: find a better error code. */
846 DnsIntFreeRecordList(PDNS_RECORD ToDelete
)
849 PDNS_RECORD next
= 0;
854 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->pName
);
856 switch(ToDelete
->wType
)
866 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->Data
.PTR
.pNameHost
);
871 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->Data
.MX
.pNameExchange
);
875 for(i
= 0; i
< ToDelete
->Data
.TXT
.dwStringCount
; i
++)
876 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->Data
.TXT
.pStringArray
[i
]);
878 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
->Data
.TXT
.pStringArray
);
882 next
= ToDelete
->pNext
;
883 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete
);
890 DnsFlushResolverCache(VOID
)
892 DNS_STATUS Status
= ERROR_SUCCESS
;
894 DPRINT("DnsFlushResolverCache()\n");
898 Status
= R_ResolverFlushCache(NULL
);
899 DPRINT("R_ResolverFlushCache() returned %lu\n", Status
);
901 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
903 Status
= RpcExceptionCode();
904 DPRINT("Exception returned %lu\n", Status
);
908 return (Status
== ERROR_SUCCESS
);
913 DnsGetCacheDataTable(
914 _Out_ PDNS_CACHE_ENTRY
*DnsCache
)
916 DNS_STATUS Status
= ERROR_SUCCESS
;
917 PDNS_CACHE_ENTRY CacheEntries
= NULL
;
919 if (DnsCache
== NULL
)
924 Status
= CRrReadCache(NULL
,
926 DPRINT("CRrReadCache() returned %lu\n", Status
);
928 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
930 Status
= RpcExceptionCode();
931 DPRINT1("Exception returned %lu\n", Status
);
935 if (Status
!= ERROR_SUCCESS
)
938 if (CacheEntries
== NULL
)
941 *DnsCache
= CacheEntries
;
948 GetCurrentTimeInSeconds(VOID
)
952 ULARGE_INTEGER lTime
, lAdj
;
953 SYSTEMTIME st
= {1970, 1, 0, 1, 0, 0, 0};
955 SystemTimeToFileTime(&st
, &Adjustment
);
956 memcpy(&lAdj
, &Adjustment
, sizeof(lAdj
));
957 GetSystemTimeAsFileTime(&Time
);
958 memcpy(&lTime
, &Time
, sizeof(lTime
));
959 lTime
.QuadPart
-= lAdj
.QuadPart
;
960 return (DWORD
)(lTime
.QuadPart
/10000000ULL);