[ADNS][DNSAPI][MSWSOCK] Several fixes and improvements to DnsQuery and co, detailed in CORE-11394. This also fixes CORE-7441, many tests in dnsapi:DnsQuery, ws2_32:getaddrinfo and more. Brought to you by Peter Hater.

svn path=/trunk/; revision=72867
This commit is contained in:
Amine Khaldi 2016-09-30 15:19:29 +00:00
parent bc741955ed
commit 040de105cc
7 changed files with 941 additions and 555 deletions

View file

@ -24,6 +24,6 @@ add_library(dnsapi SHARED
set_module_type(dnsapi win32dll)
target_link_libraries(dnsapi adns)
add_importlibs(dnsapi user32 ws2_32 iphlpapi msvcrt kernel32 ntdll)
add_importlibs(dnsapi advapi32 user32 ws2_32 iphlpapi msvcrt kernel32 ntdll)
add_pch(dnsapi dnsapi/precomp.h SOURCE)
add_cd_file(TARGET dnsapi DESTINATION reactos/system32 FOR all)

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,7 @@ add_library(mswsock SHARED
mswsock.rc
${CMAKE_CURRENT_BINARY_DIR}/mswsock.def)
set_module_type(mswsock win32dll)
add_importlibs(mswsock ws2_32 dnsapi msvcrt kernel32)
set_module_type(mswsock win32dll UNICODE)
add_importlibs(mswsock ws2_32 advapi32 dnsapi msvcrt kernel32)
add_pch(mswsock precomp.h SOURCE)
add_cd_file(TARGET mswsock DESTINATION reactos/system32 FOR all)

View file

@ -263,8 +263,7 @@ mswBufferAppendBlob_Hostent(_Inout_ PMSW_BUFFER mswBuf,
/* addr_list */
RtlZeroMemory(lst, sizeof(lst));
if (ip4addr != 0)
lst[0] = (void*)&ip4addr;
lst[0] = (void*)&ip4addr;
phe->h_addr_list = (char**)(mswBufferEndPtr(mswBuf) - bytesOfs);

View file

@ -10,6 +10,7 @@
#include <svcguid.h>
#include <iptypes.h>
#include <strsafe.h>
#include <winreg.h>
#include "mswhelper.h"
@ -459,310 +460,71 @@ NSP_GetHostNameHeapAllocW(_Out_ WCHAR** hostname)
return ERROR_SUCCESS;
}
/* This function is far from perfect but it works enough */
IP4_ADDRESS
FindEntryInHosts(IN CONST WCHAR FAR* wname)
{
BOOL Found = FALSE;
HANDLE HostsFile;
CHAR HostsDBData[BUFSIZ] = {0};
PCHAR SystemDirectory = HostsDBData;
PCHAR HostsLocation = "\\drivers\\etc\\hosts";
PCHAR AddressStr, DnsName = NULL, AddrTerm, NameSt, NextLine, ThisLine, Comment;
UINT SystemDirSize = sizeof(HostsDBData) - 1, ValidData = 0;
DWORD ReadSize;
DWORD Address;
CHAR name[MAX_HOSTNAME_LEN + 1];
wcstombs(name, wname, MAX_HOSTNAME_LEN);
/* We assume that the parameters are valid */
if (!GetSystemDirectoryA(SystemDirectory, SystemDirSize))
{
WSASetLastError(WSANO_RECOVERY);
//WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
return 0; /* Can't get system directory */
}
strncat(SystemDirectory, HostsLocation, SystemDirSize);
HostsFile = CreateFileA(SystemDirectory,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (HostsFile == INVALID_HANDLE_VALUE)
{
WSASetLastError(WSANO_RECOVERY);
return 0;
}
while (!Found && ReadFile(HostsFile,
HostsDBData + ValidData,
sizeof(HostsDBData) - ValidData,
&ReadSize,
NULL))
{
ValidData += ReadSize;
ReadSize = 0;
NextLine = ThisLine = HostsDBData;
/* Find the beginning of the next line */
while ((NextLine < HostsDBData + ValidData) &&
(*NextLine != '\r') &&
(*NextLine != '\n'))
{
NextLine++;
}
/* Zero and skip, so we can treat what we have as a string */
if (NextLine > HostsDBData + ValidData)
break;
*NextLine = 0;
NextLine++;
Comment = strchr(ThisLine, '#');
if (Comment)
*Comment = 0; /* Terminate at comment start */
AddressStr = ThisLine;
/* Find the first space separating the IP address from the DNS name */
AddrTerm = strchr(ThisLine, ' ');
if (AddrTerm)
{
/* Terminate the address string */
*AddrTerm = 0;
/* Find the last space before the DNS name */
NameSt = strrchr(ThisLine, ' ');
/* If there is only one space (the one we removed above), then just use the address terminator */
if (!NameSt)
NameSt = AddrTerm;
/* Move from the space to the first character of the DNS name */
NameSt++;
DnsName = NameSt;
if (!strcmp(name, DnsName))
{
Found = TRUE;
break;
}
}
/* Get rid of everything we read so far */
while (NextLine <= HostsDBData + ValidData &&
isspace (*NextLine))
{
NextLine++;
}
if (HostsDBData + ValidData - NextLine <= 0)
break;
//WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
// HostsDBData + ValidData - NextLine));
memmove(HostsDBData, NextLine, HostsDBData + ValidData - NextLine);
ValidData -= NextLine - HostsDBData;
//WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
}
CloseHandle(HostsFile);
if (!Found)
{
//WS_DbgPrint(MAX_TRACE,("Not found\n"));
WSASetLastError(WSANO_DATA);
return 0;
}
if (strstr(AddressStr, ":"))
{
//DbgPrint("AF_INET6 NOT SUPPORTED!\n");
WSASetLastError(WSAEINVAL);
return 0;
}
Address = inet_addr(AddressStr);
if (Address == INADDR_NONE)
{
WSASetLastError(WSAEINVAL);
return 0;
}
return Address;
}
INT
NSP_GetHostByNameHeapAllocW(_In_ WCHAR* name,
_In_ GUID* lpProviderId,
_Out_ PWSHOSTINFOINTERN hostinfo)
{
HANDLE hHeap = GetProcessHeap();
enum addr_type
{
GH_INVALID,
GH_IPV6,
GH_IPV4,
GH_RFC1123_DNS
};
typedef enum addr_type addr_type;
addr_type addr;
INT ret = 0;
WCHAR* found = 0;
DNS_STATUS dns_status = {0};
/* include/WinDNS.h -- look up DNS_RECORD on MSDN */
PDNS_RECORD dp;
PDNS_RECORD curr;
WCHAR* tmpHostnameW;
CHAR* tmpHostnameA;
IP4_ADDRESS address;
INT result = ERROR_SUCCESS;
/* needed to be cleaned up if != NULL */
tmpHostnameW = NULL;
dp = NULL;
addr = GH_INVALID;
if (name == NULL)
{
result = ERROR_INVALID_PARAMETER;
goto cleanup;
}
/* Hostname "" / "localhost"
- convert to "computername" */
if ((wcscmp(L"", name) == 0) /*||
(wcsicmp(L"localhost", name) == 0)*/)
/* DNS_TYPE_A: include/WinDNS.h */
/* DnsQuery -- lib/dnsapi/dnsapi/query.c */
dns_status = DnsQuery(name,
DNS_TYPE_A,
DNS_QUERY_STANDARD,
/* extra dns servers */ 0,
&dp,
0);
if (dns_status == ERROR_INVALID_NAME)
{
ret = NSP_GetHostNameHeapAllocW(&tmpHostnameW);
if (ret != ERROR_SUCCESS)
{
result = ret;
goto cleanup;
}
name = tmpHostnameW;
}
/* Is it an IPv6 address? */
found = wcschr(name, L':');
if (found != NULL)
{
addr = GH_IPV6;
goto act;
}
/* Is it an IPv4 address? */
if (!iswalpha(name[0]))
{
addr = GH_IPV4;
goto act;
}
addr = GH_RFC1123_DNS;
/* Broken out in case we want to get fancy later */
act:
switch (addr)
{
case GH_IPV6:
WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED);
result = ERROR_CALL_NOT_IMPLEMENTED;
goto cleanup;
break;
case GH_INVALID:
WSASetLastError(WSAEFAULT);
result = ERROR_INVALID_PARAMETER;
goto cleanup;
break;
/* Note: If passed an IP address, MSDN says that gethostbyname()
treats it as an unknown host.
This is different from the unix implementation. Use inet_addr()
*/
case GH_IPV4:
case GH_RFC1123_DNS:
/* DNS_TYPE_A: include/WinDNS.h */
/* DnsQuery -- lib/dnsapi/dnsapi/query.c */
/* Look for the DNS name in the hosts file */
if ((address = FindEntryInHosts(name)) != 0)
{
hostinfo->hostnameW = StrCpyHeapAllocW(hHeap, name);
hostinfo->addr4 = address;
result = ERROR_SUCCESS;
goto cleanup;
}
tmpHostnameA = StrW2AHeapAlloc(hHeap, name);
dns_status = DnsQuery(tmpHostnameA,
DNS_TYPE_A,
DNS_QUERY_STANDARD,
/* extra dns servers */ 0,
&dp,
0);
HeapFree(hHeap, 0, tmpHostnameA);
if ((dns_status != 0) || (dp == NULL))
{
result = WSAHOST_NOT_FOUND;
goto cleanup;
}
//ASSERT(dp->wType == DNS_TYPE_A);
//ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
curr = dp;
while ((curr->pNext != NULL) || (curr->wType != DNS_TYPE_A))
{
curr = curr->pNext;
}
if (curr->wType != DNS_TYPE_A)
{
result = WSASERVICE_NOT_FOUND;
goto cleanup;
}
//WS_DbgPrint(MID_TRACE,("populating hostent\n"));
//WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName));
//populate_hostent(p->Hostent,
// (PCHAR)curr->pName,
// curr->Data.A.IpAddress);
hostinfo->hostnameW = StrA2WHeapAlloc(hHeap, curr->pName);
hostinfo->addr4 = curr->Data.A.IpAddress;
result = ERROR_SUCCESS;
WSASetLastError(WSAEFAULT);
result = ERROR_INVALID_PARAMETER;
goto cleanup;
//WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n",
// dns_status));
//WSASetLastError(WSAHOST_NOT_FOUND);
//return NULL;
break;
default:
result = WSANO_RECOVERY;
goto cleanup;
break;
}
result = WSANO_RECOVERY;
if ((dns_status != 0) || (dp == NULL))
{
result = WSAHOST_NOT_FOUND;
goto cleanup;
}
//ASSERT(dp->wType == DNS_TYPE_A);
//ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
curr = dp;
while ((curr->pNext != NULL) || (curr->wType != DNS_TYPE_A))
{
curr = curr->pNext;
}
if (curr->wType != DNS_TYPE_A)
{
result = WSASERVICE_NOT_FOUND;
goto cleanup;
}
hostinfo->hostnameW = StrCpyHeapAllocW(hHeap, curr->pName);
hostinfo->addr4 = curr->Data.A.IpAddress;
result = ERROR_SUCCESS;
cleanup:
if (dp != NULL)
DnsRecordListFree(dp, DnsFreeRecordList);
if (tmpHostnameW != NULL)
HeapFree(hHeap, 0, tmpHostnameW);
return result;
}
@ -825,6 +587,99 @@ DecodeServEntFromString(IN PCHAR ServiceString,
return TRUE;
}
HANDLE
WSAAPI
OpenNetworkDatabase(_In_ LPCWSTR Name)
{
PWSTR ExpandedPath;
PWSTR DatabasePath;
INT ErrorCode;
HKEY DatabaseKey;
DWORD RegType;
DWORD RegSize = 0;
size_t StringLength;
HANDLE ret;
ExpandedPath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(WCHAR));
if (!ExpandedPath)
return INVALID_HANDLE_VALUE;
/* Open the database path key */
ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
0,
KEY_READ,
&DatabaseKey);
if (ErrorCode == NO_ERROR)
{
/* Read the actual path */
ErrorCode = RegQueryValueEx(DatabaseKey,
L"DatabasePath",
NULL,
&RegType,
NULL,
&RegSize);
DatabasePath = HeapAlloc(GetProcessHeap(), 0, RegSize);
if (!DatabasePath)
{
HeapFree(GetProcessHeap(), 0, ExpandedPath);
return INVALID_HANDLE_VALUE;
}
/* Read the actual path */
ErrorCode = RegQueryValueEx(DatabaseKey,
L"DatabasePath",
NULL,
&RegType,
(LPBYTE)DatabasePath,
&RegSize);
/* Close the key */
RegCloseKey(DatabaseKey);
/* Expand the name */
ExpandEnvironmentStrings(DatabasePath, ExpandedPath, MAX_PATH);
HeapFree(GetProcessHeap(), 0, DatabasePath);
}
else
{
/* Use defalt path */
GetSystemDirectory(ExpandedPath, MAX_PATH);
StringCchLength(ExpandedPath, MAX_PATH, &StringLength);
if (ExpandedPath[StringLength - 1] != L'\\')
{
/* It isn't, so add it ourselves */
StringCchCat(ExpandedPath, MAX_PATH, L"\\");
}
StringCchCat(ExpandedPath, MAX_PATH, L"DRIVERS\\ETC\\");
}
/* Make sure that the path is backslash-terminated */
StringCchLength(ExpandedPath, MAX_PATH, &StringLength);
if (ExpandedPath[StringLength - 1] != L'\\')
{
/* It isn't, so add it ourselves */
StringCchCat(ExpandedPath, MAX_PATH, L"\\");
}
/* Add the database name */
StringCchCat(ExpandedPath, MAX_PATH, Name);
/* Return a handle to the file */
ret = CreateFile(ExpandedPath,
FILE_READ_DATA,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
HeapFree(GetProcessHeap(), 0, ExpandedPath);
return ret;
}
INT
NSP_GetServiceByNameHeapAllocW(_In_ WCHAR* nameW,
_In_ GUID* lpProviderId,
@ -833,14 +688,11 @@ NSP_GetServiceByNameHeapAllocW(_In_ WCHAR* nameW,
BOOL Found = FALSE;
HANDLE ServicesFile;
CHAR ServiceDBData[BUFSIZ * sizeof(WCHAR)] = {0};
PWCHAR SystemDirectory = (PWCHAR)ServiceDBData; /* Reuse this stack space */
PWCHAR ServicesFileLocation = L"\\drivers\\etc\\services";
PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
ProtocolStr = 0, Comment = 0, EndValid;
PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = {0};
PCHAR* AliasPtr;
UINT i = 0,
SystemDirSize = (sizeof(ServiceDBData) / sizeof(WCHAR)) - 1;
UINT i = 0;
DWORD ReadSize = 0;
HANDLE hHeap;
PCHAR nameA = NULL;
@ -872,23 +724,7 @@ NSP_GetServiceByNameHeapAllocW(_In_ WCHAR* nameW,
StringCbCopyA(nameServiceA, i + 1, nameA);
nameServiceA[i] = '\0';
if (!GetSystemDirectoryW(SystemDirectory, SystemDirSize))
{
/* Can't get system directory */
res = WSANO_RECOVERY;
goto End;
}
wcsncat(SystemDirectory, ServicesFileLocation, SystemDirSize);
ServicesFile = CreateFileW(SystemDirectory,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
ServicesFile = OpenNetworkDatabase(L"services");
if (ServicesFile == INVALID_HANDLE_VALUE)
{
return WSANO_RECOVERY;

View file

@ -368,6 +368,7 @@ ADNS_API int adns_init(adns_state *newstate_r, adns_initflags flags,
/* ReactOS addition */
ADNS_API void adns_addserver(adns_state state, struct in_addr server);
ADNS_API void adns_ccf_search(adns_state ads, const char *fn, int lno, const char *buf);
ADNS_API int adns_init_strcfg(adns_state *newstate_r, adns_initflags flags,
FILE *diagfile /*0=>discard*/, const char *configtext);

View file

@ -571,18 +571,6 @@ int adns_init(adns_state *ads_r, adns_initflags flags, FILE *diagfile) {
#ifdef ADNS_JGAA_WIN32
#define SECURE_PATH_LEN (MAX_PATH - 64)
char PathBuf[MAX_PATH];
struct in_addr addr;
#ifdef __REACTOS__
PFIXED_INFO network_info;
ULONG network_info_blen = 0;
#else
#define ADNS_PFIXED_INFO_BLEN (2048)
PFIXED_INFO network_info = (PFIXED_INFO)_alloca(ADNS_PFIXED_INFO_BLEN);
ULONG network_info_blen = ADNS_PFIXED_INFO_BLEN;
#endif /* __REACTOS__ */
DWORD network_info_result;
PIP_ADDR_STRING pip;
const char *network_err_str = "";
#endif
r= init_begin(&ads, flags, diagfile ? diagfile : stderr);
@ -606,36 +594,6 @@ int adns_init(adns_state *ads_r, adns_initflags flags, FILE *diagfile) {
GetWindowsDirectory(PathBuf, SECURE_PATH_LEN);
strcat(PathBuf,"\\System32\\Drivers\\etc\\resolv-adns.conf");
readconfig(ads,PathBuf,0);
#ifdef __REACTOS__
network_info_result = GetNetworkParams(NULL, &network_info_blen);
network_info = (PFIXED_INFO)malloc((size_t)network_info_blen);
#endif
network_info_result = GetNetworkParams(network_info, &network_info_blen);
if (network_info_result != ERROR_SUCCESS){
switch(network_info_result) {
case ERROR_BUFFER_OVERFLOW: network_err_str = "ERROR_BUFFER_OVERFLOW"; break;
case ERROR_INVALID_PARAMETER: network_err_str = "ERROR_INVALID_PARAMETER"; break;
case ERROR_NO_DATA: network_err_str = "ERROR_NO_DATA"; break;
case ERROR_NOT_SUPPORTED: network_err_str = "ERROR_NOT_SUPPORTED"; break;}
adns__diag(ads,-1,0,"GetNetworkParams() failed with error [%d] %s",
network_info_result,network_err_str);
}
else {
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))
addserver(ads, addr);
#ifdef __REACTOS__
if (network_info->DomainName)
ccf_search(ads, "LOCALDOMAIN", -1, network_info->DomainName);
else
ccf_search(ads, "LOCALDOMAIN", -1, "");
#endif
}
}
#ifdef __REACTOS__
if (network_info) free(network_info);
#endif
#else
readconfig(ads,"/etc/resolv.conf",1);
readconfig(ads,"/etc/resolv-adns.conf",0);
@ -753,3 +711,6 @@ adns_query adns_forallqueries_next(adns_state ads, void **context_r) {
void adns_addserver(adns_state ads, struct in_addr addr) {
addserver(ads, addr);
}
void adns_ccf_search(adns_state ads, const char *fn, int lno, const char *buf) {
ccf_search(ads, fn, lno, buf);
}