From 98acf217f995a957ad319406780e5825fdcf20d9 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 25 Apr 2010 20:01:59 +0000 Subject: [PATCH] [WS2_32] - Add support for reading the hosts file - Fix an off-by-one error which prevented reading the last value in the services file - Fixes bug 4410 and bug 4880 svn path=/trunk/; revision=47020 --- reactos/dll/win32/ws2_32/misc/ns.c | 203 ++++++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 2 deletions(-) diff --git a/reactos/dll/win32/ws2_32/misc/ns.c b/reactos/dll/win32/ws2_32/misc/ns.c index bb89eadfb0d..fee4f032868 100644 --- a/reactos/dll/win32/ws2_32/misc/ns.c +++ b/reactos/dll/win32/ws2_32/misc/ns.c @@ -640,7 +640,199 @@ void free_servent(struct servent* s) HFREE(s); } +/* This function is far from perfect but it works enough */ +static +LPHOSTENT +FindEntryInHosts(IN CONST CHAR FAR* name) +{ + 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; + ULONG Address; + PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData; + /* 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 NULL; /* 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 NULL; + } + + 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 NULL; + } + + if( !p->Hostent ) + { + p->Hostent = HeapAlloc(GlobalHeap, 0, sizeof(*p->Hostent)); + if( !p->Hostent ) + { + WSASetLastError( WSATRY_AGAIN ); + return NULL; + } + } + + p->Hostent->h_name = HeapAlloc(GlobalHeap, 0, strlen(DnsName)); + if( !p->Hostent->h_name ) + { + WSASetLastError( WSATRY_AGAIN ); + return NULL; + } + + RtlCopyMemory(p->Hostent->h_name, + DnsName, + strlen(DnsName)); + + p->Hostent->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *)); + if( !p->Hostent->h_aliases ) + { + WSASetLastError( WSATRY_AGAIN ); + return NULL; + } + + p->Hostent->h_aliases[0] = 0; + + if (strstr(AddressStr, ":")) + { + DbgPrint("AF_INET6 NOT SUPPORTED!\n"); + WSASetLastError(WSAEINVAL); + return NULL; + } + else + p->Hostent->h_addrtype = AF_INET; + + p->Hostent->h_addr_list = HeapAlloc(GlobalHeap, 0, sizeof(char *)); + if( !p->Hostent->h_addr_list ) + { + WSASetLastError( WSATRY_AGAIN ); + return NULL; + } + + Address = inet_addr(AddressStr); + if (Address == INADDR_NONE) + { + WSASetLastError(WSAEINVAL); + return NULL; + } + + p->Hostent->h_addr_list[0] = HeapAlloc(GlobalHeap, 0, sizeof(Address)); + if( !p->Hostent->h_addr_list[0] ) + { + WSASetLastError( WSATRY_AGAIN ); + return NULL; + } + + RtlCopyMemory(p->Hostent->h_addr_list[0], + &Address, + sizeof(Address)); + + p->Hostent->h_length = sizeof(Address); + + return p->Hostent; +} LPHOSTENT EXPORT @@ -661,6 +853,7 @@ gethostbyname(IN CONST CHAR FAR* name) /* include/WinDNS.h -- look up DNS_RECORD on MSDN */ PDNS_RECORD dp = 0; PWINSOCK_THREAD_BLOCK p; + LPHOSTENT Hostent; addr = GH_INVALID; @@ -726,6 +919,12 @@ gethostbyname(IN CONST CHAR FAR* name) 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 */ + Hostent = FindEntryInHosts(name); + if (Hostent) + return Hostent; + dns_status = DnsQuery_A(name, DNS_TYPE_A, DNS_QUERY_STANDARD, @@ -993,7 +1192,7 @@ getservbyname(IN CONST CHAR FAR* name, } /* Zero and skip, so we can treat what we have as a string */ - if( NextLine >= ServiceDBData + ValidData ) + if( NextLine > ServiceDBData + ValidData ) break; *NextLine = 0; NextLine++; @@ -1174,7 +1373,7 @@ getservbyport(IN INT port, *NextLine != '\r' && *NextLine != '\n' ) NextLine++; /* Zero and skip, so we can treat what we have as a string */ - if( NextLine >= ServiceDBData + ValidData ) + if( NextLine > ServiceDBData + ValidData ) break; *NextLine = 0; NextLine++;