*/
#include "precomp.h"
+#include <winreg.h>
+#include <iphlpapi.h>
+#include <strsafe.h>
#define NDEBUG
#include <debug.h>
* Reserved -- Response as it appears on the wire. Optional.
*/
-char
-*xstrsave(const char *str)
+static PCHAR
+DnsWToC(const WCHAR *WideString)
{
- char *p;
-
- p = RtlAllocateHeap(RtlGetProcessHeap(), 0, strlen(str) + 1);
-
- if(p)
- strcpy(p, str);
+ 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;
+}
- return p;
+static PWCHAR
+DnsCToW(const CHAR *NarrowString)
+{
+ PWCHAR WideString;
+ int WideLen = MultiByteToWideChar(CP_ACP,
+ 0,
+ NarrowString,
+ -1,
+ NULL,
+ 0);
+ if (WideLen == 0)
+ return NULL;
+ WideLen *= sizeof(WCHAR);
+ WideString = RtlAllocateHeap(RtlGetProcessHeap(), 0, WideLen);
+ if (WideString == NULL)
+ {
+ return NULL;
+ }
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ NarrowString,
+ -1,
+ WideString,
+ WideLen);
+
+ return WideString;
}
DNS_STATUS WINAPI
PDNS_RECORD *QueryResultSet,
PVOID *Reserved)
{
- adns_state astate;
- int quflags = adns_qf_search;
- int adns_error;
- adns_answer *answer;
- LPSTR CurrentName;
- unsigned i, CNameLoop;
+ 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;
- *QueryResultSet = 0;
+ Buffer = DnsCToW(Name);
- switch(Type)
+ Status = DnsQuery_W(Buffer, Type, Options, Servers, &QueryResultWide, Reserved);
+
+ while (Status == ERROR_SUCCESS && QueryResultWide)
{
+ switch (QueryResultWide->wType)
+ {
case DNS_TYPE_A:
- adns_error = adns_init(&astate, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn, 0);
+ case DNS_TYPE_WKS:
+ ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
+ ConvertedRecord->pName = DnsWToC((PWCHAR)QueryResultWide->pName);
+ ConvertedRecord->wType = QueryResultWide->wType;
+ 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 = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
+ ConvertedRecord->pName = DnsWToC((PWCHAR)QueryResultWide->pName);
+ ConvertedRecord->wType = QueryResultWide->wType;
+ ConvertedRecord->wDataLength = sizeof(DNS_PTR_DATA);
+ ConvertedRecord->Data.PTR.pNameHost = DnsWToC((PWCHAR)QueryResultWide->Data.PTR.pNameHost);
+ break;
+
+ case DNS_TYPE_MINFO:
+ ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
+ ConvertedRecord->pName = DnsWToC((PWCHAR)QueryResultWide->pName);
+ ConvertedRecord->wType = QueryResultWide->wType;
+ ConvertedRecord->wDataLength = sizeof(DNS_MINFO_DATA);
+ ConvertedRecord->Data.MINFO.pNameMailbox = DnsWToC((PWCHAR)QueryResultWide->Data.MINFO.pNameMailbox);
+ ConvertedRecord->Data.MINFO.pNameErrorsMailbox = DnsWToC((PWCHAR)QueryResultWide->Data.MINFO.pNameErrorsMailbox);
+ break;
+
+ case DNS_TYPE_MX:
+ ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
+ ConvertedRecord->pName = DnsWToC((PWCHAR)QueryResultWide->pName);
+ ConvertedRecord->wType = QueryResultWide->wType;
+ ConvertedRecord->wDataLength = sizeof(DNS_MX_DATA);
+ ConvertedRecord->Data.MX.pNameExchange = DnsWToC((PWCHAR)QueryResultWide->Data.MX.pNameExchange);
+ ConvertedRecord->Data.MX.wPreference = QueryResultWide->Data.MX.wPreference;
+ break;
+
+ case DNS_TYPE_HINFO:
+ ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_TXT_DATA) + QueryResultWide->Data.TXT.dwStringCount);
+ ConvertedRecord->pName = DnsWToC((PWCHAR)QueryResultWide->pName);
+ ConvertedRecord->wType = QueryResultWide->wType;
+ ConvertedRecord->wDataLength = sizeof(DNS_TXT_DATA) + (sizeof(PCHAR) * QueryResultWide->Data.TXT.dwStringCount);
+ ConvertedRecord->Data.TXT.dwStringCount = QueryResultWide->Data.TXT.dwStringCount;
+
+ for (i = 0; i < ConvertedRecord->Data.TXT.dwStringCount; i++)
+ ConvertedRecord->Data.TXT.pStringArray[i] = DnsWToC((PWCHAR)QueryResultWide->Data.TXT.pStringArray[i]);
+
+ break;
+
+ case DNS_TYPE_NULL:
+ ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_NULL_DATA) + QueryResultWide->Data.Null.dwByteCount);
+ ConvertedRecord->pName = DnsWToC((PWCHAR)QueryResultWide->pName);
+ ConvertedRecord->wType = QueryResultWide->wType;
+ 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(adns_error != adns_s_ok)
- return DnsIntTranslateAdnsToDNS_STATUS(adns_error);
+ if (LastRecord)
+ {
+ LastRecord->pNext = ConvertedRecord;
+ LastRecord = LastRecord->pNext;
+ }
+ else
+ {
+ LastRecord = *QueryResultSet = ConvertedRecord;
+ }
- if (Servers)
- {
- for(i = 0; i < Servers->AddrCount; i++)
- {
- adns_addserver(astate, *((struct in_addr *)&Servers->AddrArray[i]));
- }
- }
+ QueryResultWide = QueryResultWide->pNext;
+ }
- /*
- * 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.
- */
+ if (LastRecord)
+ LastRecord->pNext = 0;
-#define CNAME_LOOP_MAX 16
+ /* The name */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+ /* The result*/
+ if (QueryResultWide) DnsIntFreeRecordList(QueryResultWide);
- CurrentName = (LPSTR) Name;
+ return Status;
+}
- for (CNameLoop = 0; CNameLoop < CNAME_LOOP_MAX; CNameLoop++)
- {
- adns_error = adns_synchronous(astate, CurrentName, adns_r_addr, quflags, &answer);
+WCHAR
+*xstrsave(const WCHAR *str)
+{
+ WCHAR *p;
+ size_t len = 0;
- if(adns_error != adns_s_ok)
- {
- adns_finish(astate);
+ /* FIXME: how much instead of MAX_PATH? */
+ StringCbLengthW(str, MAX_PATH, &len);
+ len+=sizeof(WCHAR);
- if (CurrentName != Name)
- RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
+ p = RtlAllocateHeap(RtlGetProcessHeap(), 0, len);
- return DnsIntTranslateAdnsToDNS_STATUS(adns_error);
- }
+ if (p)
+ StringCbCopyW(p, len, str);
- if(answer && answer->rrs.addr)
- {
- if (CurrentName != Name)
- RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
+ return p;
+}
- *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
+CHAR
+*xstrsaveA(const CHAR *str)
+{
+ CHAR *p;
+ size_t len = 0;
- if (NULL == *QueryResultSet)
- {
- adns_finish( astate );
- return ERROR_OUTOFMEMORY;
- }
+ /* FIXME: how much instead of MAX_PATH? */
+ StringCbLengthA(str, MAX_PATH, &len);
+ len++;
- (*QueryResultSet)->pNext = NULL;
- (*QueryResultSet)->wType = Type;
- (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA);
- (*QueryResultSet)->Data.A.IpAddress = answer->rrs.addr->addr.inet.sin_addr.s_addr;
+ p = RtlAllocateHeap(RtlGetProcessHeap(), 0, len);
- adns_finish(astate);
+ if (p)
+ StringCbCopyA(p, len, str);
- (*QueryResultSet)->pName = xstrsave( Name );
+ return p;
+}
- return NULL != (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
- }
+HANDLE
+OpenNetworkDatabase(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 = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+ 0,
+ KEY_READ,
+ &DatabaseKey);
+ if (ErrorCode == NO_ERROR)
+ {
+ /* Read the actual path */
+ ErrorCode = RegQueryValueExW(DatabaseKey,
+ L"DatabasePath",
+ NULL,
+ &RegType,
+ NULL,
+ &RegSize);
+
+ DatabasePath = HeapAlloc(GetProcessHeap(), 0, RegSize);
+ if (!DatabasePath)
+ {
+ HeapFree(GetProcessHeap(), 0, ExpandedPath);
+ return INVALID_HANDLE_VALUE;
+ }
- if (NULL == answer || adns_s_prohibitedcname != answer->status || NULL == answer->cname)
- {
- adns_finish(astate);
+ /* Read the actual path */
+ ErrorCode = RegQueryValueExW(DatabaseKey,
+ L"DatabasePath",
+ NULL,
+ &RegType,
+ (LPBYTE)DatabasePath,
+ &RegSize);
- if (CurrentName != Name)
- RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
+ /* Close the key */
+ RegCloseKey(DatabaseKey);
- return ERROR_FILE_NOT_FOUND;
- }
+ /* Expand the name */
+ ExpandEnvironmentStringsW(DatabasePath, ExpandedPath, MAX_PATH);
- if (CurrentName != Name)
- RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
+ HeapFree(GetProcessHeap(), 0, DatabasePath);
+ }
+ else
+ {
+ /* Use defalt path */
+ GetSystemDirectoryW(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\\");
+ }
- CurrentName = xstrsave(answer->cname);
+ /* 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"\\");
+ }
- if (!CurrentName)
- {
- adns_finish(astate);
- return ERROR_OUTOFMEMORY;
- }
- }
+ /* Add the database name */
+ StringCchCat(ExpandedPath, MAX_PATH, Name);
- adns_finish(astate);
- RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName);
- return ERROR_FILE_NOT_FOUND;
+ /* Return a handle to the file */
+ ret = CreateFileW(ExpandedPath,
+ FILE_READ_DATA,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
- default:
- return ERROR_OUTOFMEMORY; /* XXX arty: find a better error code. */
- }
+ HeapFree(GetProcessHeap(), 0, ExpandedPath);
+ return ret;
}
-static PCHAR
-DnsWToC(const WCHAR *WideString)
+/* This function is far from perfect but it works enough */
+IP4_ADDRESS
+CheckForCurrentHostname(CONST CHAR * Name, PFIXED_INFO network_info)
{
- int chars = wcstombs(NULL, WideString, 0);
- PCHAR out = RtlAllocateHeap(RtlGetProcessHeap(), 0, chars + 1);
+ PCHAR TempName;
+ DWORD AdapterAddressesSize, Status;
+ IP4_ADDRESS ret = 0, Address;
+ PIP_ADAPTER_ADDRESSES Addresses = NULL, pip;
+ BOOL Found = FALSE;
- wcstombs(out, WideString, chars + 1);
+ if (network_info->DomainName)
+ {
+ 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;
+}
- return out;
+BOOL
+ParseV4Address(LPCSTR AddressString,
+ OUT PDWORD pAddress)
+{
+ CHAR * cp = (CHAR *)AddressString;
+ DWORD val, base;
+ unsigned char c;
+ DWORD parts[4], *pp = parts;
+ if (!AddressString)
+ return FALSE;
+ if (!isdigit(*cp)) return FALSE;
+
+again:
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, other=decimal.
+ */
+ val = 0; base = 10;
+ if (*cp == '0') {
+ if (*++cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ else
+ base = 8;
+ }
+ while ((c = *cp)) {
+ if (isdigit(c)) {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isxdigit(c)) {
+ val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+ if (*cp == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ */
+ if (pp >= parts + 4) return FALSE;
+ *pp++ = val;
+ cp++;
+ goto again;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (*cp && *cp > ' ') return FALSE;
+
+ *pp++ = val;
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ if ((DWORD)(pp - parts) != 4) return FALSE;
+ if (parts[0] > 0xff || parts[1] > 0xff || parts[2] > 0xff || parts[3] > 0xff) return FALSE;
+ val = (parts[3] << 24) | (parts[2] << 16) | (parts[1] << 8) | parts[0];
+
+ if (pAddress)
+ *pAddress = val;
+
+ return TRUE;
}
-static PWCHAR
-DnsCToW(const CHAR *NarrowString)
+/* This function is far from perfect but it works enough */
+IP4_ADDRESS
+FindEntryInHosts(CONST CHAR * name)
{
- int chars = mbstowcs(NULL, NarrowString, 0);
- PWCHAR out = RtlAllocateHeap(RtlGetProcessHeap(), 0, (chars + 1) * sizeof(WCHAR));
+ BOOL Found = FALSE;
+ HANDLE HostsFile;
+ CHAR HostsDBData[BUFSIZ] = { 0 };
+ PCHAR AddressStr, DnsName = NULL, AddrTerm, NameSt, NextLine, ThisLine, Comment;
+ UINT ValidData = 0;
+ DWORD ReadSize;
+ DWORD Address;
+
+ /* Open the network database */
+ HostsFile = OpenNetworkDatabase(L"hosts");
+ 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 (!stricmp(name, DnsName) || !stricmp(name, AddressStr))
+ {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ /* Get rid of everything we read so far */
+ while (NextLine <= HostsDBData + ValidData &&
+ isspace(*NextLine))
+ {
+ NextLine++;
+ }
+
+ if (HostsDBData + ValidData - NextLine <= 0)
+ break;
+
+ memmove(HostsDBData, NextLine, HostsDBData + ValidData - NextLine);
+ ValidData -= NextLine - HostsDBData;
+ }
+
+ CloseHandle(HostsFile);
- mbstowcs(out, NarrowString, chars + 1);
+ if (!Found)
+ {
+ WSASetLastError(WSANO_DATA);
+ return 0;
+ }
+
+ if (strstr(AddressStr, ":"))
+ {
+ WSASetLastError(WSAEINVAL);
+ return 0;
+ }
- return out;
+ if (!ParseV4Address(AddressStr, &Address))
+ {
+ WSASetLastError(WSAEINVAL);
+ return 0;
+ }
+
+ return Address;
}
DNS_STATUS WINAPI
PDNS_RECORD *QueryResultSet,
PVOID *Reserved)
{
- UINT i;
- PCHAR Buffer;
- DNS_STATUS Status;
- PDNS_RECORD QueryResultWide;
- PDNS_RECORD ConvertedRecord = 0, LastRecord = 0;
+ adns_state astate;
+ int quflags = (Options & DNS_QUERY_NO_RECURSION) == 0 ? adns_qf_search : 0;
+ int adns_error;
+ adns_answer *answer;
+ LPSTR CurrentName;
+ unsigned i, 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;
+ if ((Options & DNS_QUERY_WIRE_ONLY) != 0 && (Options & DNS_QUERY_NO_WIRE_QUERY) != 0)
+ return ERROR_INVALID_PARAMETER;
- Buffer = DnsWToC(Name);
-
- Status = DnsQuery_A(Buffer, Type, Options, Servers, &QueryResultWide, Reserved);
+ *QueryResultSet = 0;
- while(Status == ERROR_SUCCESS && QueryResultWide)
+ switch (Type)
{
- switch(QueryResultWide->wType)
+ 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)
{
- case DNS_TYPE_A:
- case DNS_TYPE_WKS:
- ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
- ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
- ConvertedRecord->wType = QueryResultWide->wType;
- ConvertedRecord->wDataLength = QueryResultWide->wDataLength;
- memcpy(ConvertedRecord, QueryResultWide, QueryResultWide->wDataLength);
- break;
+ return ERROR_OUTOFMEMORY;
+ }
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ Name,
+ -1,
+ AnsiName,
+ NameLen,
+ NULL,
+ 0);
+ NameLen--;
+ /* Is it an IPv4 address? */
+ if (ParseV4Address(AnsiName, &Address))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName);
+ *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
- 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));
- ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
- ConvertedRecord->wType = QueryResultWide->wType;
- ConvertedRecord->wDataLength = sizeof(DNS_PTR_DATA);
- ConvertedRecord->Data.PTR.pNameHost = (PCHAR)DnsCToW(QueryResultWide->Data.PTR.pNameHost);
- break;
+ if (NULL == *QueryResultSet)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
- case DNS_TYPE_MINFO:
- ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
- ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
- ConvertedRecord->wType = QueryResultWide->wType;
- ConvertedRecord->wDataLength = sizeof(DNS_MINFO_DATA);
- ConvertedRecord->Data.MINFO.pNameMailbox = (PCHAR)DnsCToW(QueryResultWide->Data.MINFO.pNameMailbox);
- ConvertedRecord->Data.MINFO.pNameErrorsMailbox = (PCHAR)DnsCToW(QueryResultWide->Data.MINFO.pNameErrorsMailbox);
- break;
+ (*QueryResultSet)->pNext = NULL;
+ (*QueryResultSet)->wType = Type;
+ (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA);
+ (*QueryResultSet)->Data.A.IpAddress = Address;
- case DNS_TYPE_MX:
- ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
- ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
- ConvertedRecord->wType = QueryResultWide->wType;
- ConvertedRecord->wDataLength = sizeof(DNS_MX_DATA);
- ConvertedRecord->Data.MX.pNameExchange = (PCHAR)DnsCToW( QueryResultWide->Data.MX.pNameExchange);
- ConvertedRecord->Data.MX.wPreference = QueryResultWide->Data.MX.wPreference;
- break;
+ (*QueryResultSet)->pName = (LPSTR)xstrsave(Name);
- case DNS_TYPE_HINFO:
- ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_TXT_DATA) + QueryResultWide->Data.TXT.dwStringCount);
- ConvertedRecord->pName = (PCHAR)DnsCToW( QueryResultWide->pName );
- ConvertedRecord->wType = QueryResultWide->wType;
- ConvertedRecord->wDataLength = sizeof(DNS_TXT_DATA) + (sizeof(PWCHAR) * QueryResultWide->Data.TXT.dwStringCount);
- ConvertedRecord->Data.TXT.dwStringCount = QueryResultWide->Data.TXT.dwStringCount;
+ return (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
+ }
- for(i = 0; i < ConvertedRecord->Data.TXT.dwStringCount; i++)
- ConvertedRecord->Data.TXT.pStringArray[i] = (PCHAR)DnsCToW(QueryResultWide->Data.TXT.pStringArray[i]);
+ /* Check allowed characters
+ * According to RFC a-z,A-Z,0-9,-,_, but can't start or end with - or _
+ */
+ if (AnsiName[0] == '-' || AnsiName[0] == '_' || AnsiName[NameLen - 1] == '-' ||
+ AnsiName[NameLen - 1] == '_' || strstr(AnsiName, "..") != NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName);
+ return ERROR_INVALID_NAME;
+ }
+ i = 0;
+ while (i < NameLen)
+ {
+ if (!((AnsiName[i] >= 'a' && AnsiName[i] <= 'z') ||
+ (AnsiName[i] >= 'A' && AnsiName[i] <= 'Z') ||
+ (AnsiName[i] >= '0' && AnsiName[i] <= '9') ||
+ AnsiName[i] == '-' || AnsiName[i] == '_' || AnsiName[i] == '.'))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName);
+ return ERROR_INVALID_NAME;
+ }
+ i++;
+ }
- break;
+ if ((Options & DNS_QUERY_NO_HOSTS_FILE) == 0)
+ {
+ if ((Address = FindEntryInHosts(AnsiName)) != 0)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName);
+ *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
- case DNS_TYPE_NULL:
- ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_NULL_DATA) + QueryResultWide->Data.Null.dwByteCount);
- ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName);
- ConvertedRecord->wType = QueryResultWide->wType;
- 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 (NULL == *QueryResultSet)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ (*QueryResultSet)->pNext = NULL;
+ (*QueryResultSet)->wType = Type;
+ (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA);
+ (*QueryResultSet)->Data.A.IpAddress = Address;
+
+ (*QueryResultSet)->pName = (LPSTR)xstrsave(Name);
+
+ return (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
+ }
}
- if(LastRecord)
+ network_info_result = GetNetworkParams(NULL, &network_info_blen);
+ network_info = (PFIXED_INFO)RtlAllocateHeap(RtlGetProcessHeap(), 0, (size_t)network_info_blen);
+ if (NULL == network_info)
{
- LastRecord->pNext = ConvertedRecord;
- LastRecord = LastRecord->pNext;
+ return ERROR_OUTOFMEMORY;
}
- else
+
+ network_info_result = GetNetworkParams(network_info, &network_info_blen);
+ if (network_info_result != ERROR_SUCCESS)
{
- LastRecord = *QueryResultSet = ConvertedRecord;
+ RtlFreeHeap(RtlGetProcessHeap(), 0, network_info);
+ return network_info_result;
}
- QueryResultWide = QueryResultWide->pNext;
- }
+ 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)
+ {
+ StringCchCatA(HostWithDomainName, TempLen, ".");
+ StringCchCatA(HostWithDomainName, TempLen, network_info->DomainName);
+ }
+ RtlFreeHeap(RtlGetProcessHeap(), 0, network_info);
+ *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD));
- if (LastRecord)
- LastRecord->pNext = 0;
+ if (NULL == *QueryResultSet)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, HostWithDomainName);
+ return ERROR_OUTOFMEMORY;
+ }
- /* The name */
- RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+ (*QueryResultSet)->pNext = NULL;
+ (*QueryResultSet)->wType = Type;
+ (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA);
+ (*QueryResultSet)->Data.A.IpAddress = Address;
- return Status;
+ (*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);
+ 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)
+ {
+ adns_ccf_search(astate, "LOCALDOMAIN", -1, network_info->DomainName);
+ }
+ RtlFreeHeap(RtlGetProcessHeap(), 0, network_info);
+
+ if (adns_error != adns_s_ok)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName);
+ return DnsIntTranslateAdnsToDNS_STATUS(adns_error);
+ }
+
+ if (Servers)
+ {
+ for (i = 0; i < Servers->AddrCount; i++)
+ {
+ adns_addserver(astate, *((struct in_addr *)&Servers->AddrArray[i]));
+ }
+ }
+
+ /*
+ * 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)->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. */
+ }
}
DNS_STATUS WINAPI
#include <svcguid.h>
#include <iptypes.h>
#include <strsafe.h>
+#include <winreg.h>
#include "mswhelper.h"
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;
+ WSASetLastError(WSAEFAULT);
+ result = ERROR_INVALID_PARAMETER;
+ goto cleanup;
}
- /* Is it an IPv6 address? */
- found = wcschr(name, L':');
- if (found != NULL)
+ if ((dns_status != 0) || (dp == NULL))
{
- addr = GH_IPV6;
- goto act;
+ result = WSAHOST_NOT_FOUND;
+ goto cleanup;
}
- /* Is it an IPv4 address? */
- if (!iswalpha(name[0]))
+ //ASSERT(dp->wType == DNS_TYPE_A);
+ //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
+ curr = dp;
+ while ((curr->pNext != NULL) || (curr->wType != DNS_TYPE_A))
{
- addr = GH_IPV4;
- goto act;
+ curr = curr->pNext;
}
- addr = GH_RFC1123_DNS;
-
-/* Broken out in case we want to get fancy later */
-act:
- switch (addr)
+ if (curr->wType != DNS_TYPE_A)
{
- 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;
+ result = WSASERVICE_NOT_FOUND;
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;
+ 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;
}
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,
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;
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;