ReactOS  0.4.15-dev-499-g1f31905
hostsfile.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS system libraries
4  * FILE: base/services/dnsrslvr/hostsfile.c
5  * PURPOSE: HOSTS file routines
6  * PROGRAMERS: Art Yerkes
7  * Eric Kohl
8  */
9 
10 #include "precomp.h"
11 #include <inaddr.h>
12 #include <in6addr.h>
13 
14 
15 #define NDEBUG
16 #include <debug.h>
17 
18 static WCHAR szHexChar[] = L"0123456789abcdef";
19 
20 static
21 PWSTR
23  PSTR NarrowString)
24 {
25  PWSTR WideString;
26  int WideLen;
27 
28  WideLen = MultiByteToWideChar(CP_ACP,
29  0,
30  NarrowString,
31  -1,
32  NULL,
33  0);
34  if (WideLen == 0)
35  return NULL;
36 
37  WideString = HeapAlloc(GetProcessHeap(),
38  0,
39  WideLen * sizeof(WCHAR));
40  if (WideString == NULL)
41  return NULL;
42 
44  0,
45  NarrowString,
46  -1,
47  WideString,
48  WideLen);
49 
50  return WideString;
51 }
52 
53 
54 static
55 BOOL
57  _In_ PCSTR AddressString,
58  _Out_ PIN_ADDR pAddress)
59 {
60  PCSTR pTerminator = NULL;
62 
63  Status = RtlIpv4StringToAddressA(AddressString,
64  TRUE,
65  &pTerminator,
66  pAddress);
67  if (NT_SUCCESS(Status) && pTerminator != NULL && *pTerminator == '\0')
68  return TRUE;
69 
70  return FALSE;
71 }
72 
73 
74 static
75 BOOL
77  _In_ LPCSTR AddressString,
78  _Out_ PIN6_ADDR pAddress)
79 {
80  PCSTR pTerminator = NULL;
82 
83  Status = RtlIpv6StringToAddressA(AddressString,
84  &pTerminator,
85  pAddress);
86  if (NT_SUCCESS(Status) && pTerminator != NULL && *pTerminator == '\0')
87  return TRUE;
88 
89  return FALSE;
90 }
91 
92 
93 static
94 VOID
96  PWSTR pszHostName,
97  PIN_ADDR pAddress)
98 {
99  DNS_RECORDW ARecord, PtrRecord;
100  WCHAR szReverseName[32];
101 
102  /* Prepare the A record */
103  ZeroMemory(&ARecord, sizeof(DNS_RECORDW));
104 
105  ARecord.pName = pszHostName;
106  ARecord.wType = DNS_TYPE_A;
107  ARecord.wDataLength = sizeof(DNS_A_DATA);
108  ARecord.Flags.S.Section = DnsSectionAnswer;
109  ARecord.Flags.S.CharSet = DnsCharSetUnicode;
110  ARecord.dwTtl = 86400;
111 
112  ARecord.Data.A.IpAddress = pAddress->S_un.S_addr;
113 
114  /* Prepare the PTR record */
115  swprintf(szReverseName,
116  L"%u.%u.%u.%u.in-addr.arpa.",
117  pAddress->S_un.S_un_b.s_b4,
118  pAddress->S_un.S_un_b.s_b3,
119  pAddress->S_un.S_un_b.s_b2,
120  pAddress->S_un.S_un_b.s_b1);
121 
122  ZeroMemory(&PtrRecord, sizeof(DNS_RECORDW));
123 
124  PtrRecord.pName = szReverseName;
125  PtrRecord.wType = DNS_TYPE_PTR;
126  PtrRecord.wDataLength = sizeof(DNS_PTR_DATA);
127  PtrRecord.Flags.S.Section = DnsSectionAnswer;
128  PtrRecord.Flags.S.CharSet = DnsCharSetUnicode;
129  PtrRecord.dwTtl = 86400;
130 
131  PtrRecord.Data.PTR.pNameHost = pszHostName;
132 
133  DnsIntCacheAddEntry(&ARecord, TRUE);
134  DnsIntCacheAddEntry(&PtrRecord, TRUE);
135 }
136 
137 
138 static
139 VOID
141  PWSTR pszHostName,
142  PIN6_ADDR pAddress)
143 {
144  DNS_RECORDW AAAARecord, PtrRecord;
145  WCHAR szReverseName[80];
146  DWORD i, j, k;
147 
148  /* Prepare the AAAA record */
149  ZeroMemory(&AAAARecord, sizeof(DNS_RECORDW));
150 
151  AAAARecord.pName = pszHostName;
152  AAAARecord.wType = DNS_TYPE_AAAA;
153  AAAARecord.wDataLength = sizeof(DNS_AAAA_DATA);
154  AAAARecord.Flags.S.Section = DnsSectionAnswer;
155  AAAARecord.Flags.S.CharSet = DnsCharSetUnicode;
156  AAAARecord.dwTtl = 86400;
157 
158  CopyMemory(&AAAARecord.Data.AAAA.Ip6Address,
159  &pAddress->u.Byte,
160  sizeof(IN6_ADDR));
161 
162  /* Prepare the PTR record */
163  ZeroMemory(szReverseName, sizeof(szReverseName));
164 
165  for (i = 0; i < sizeof(IN6_ADDR); i++)
166  {
167  j = 4 * i;
168  k = sizeof(IN6_ADDR) - 1 - i;
169  szReverseName[j] = szHexChar[pAddress->u.Byte[k] & 0xF];
170  szReverseName[j + 1] = L'.';
171  szReverseName[j + 2] = szHexChar[(pAddress->u.Byte[k] >> 4) & 0xF];
172  szReverseName[j + 3] = L'.';
173  }
174  wcscat(szReverseName, L"ip6.arpa.");
175 
176  ZeroMemory(&PtrRecord, sizeof(DNS_RECORDW));
177 
178  PtrRecord.pName = szReverseName;
179  PtrRecord.wType = DNS_TYPE_PTR;
180  PtrRecord.wDataLength = sizeof(DNS_PTR_DATA);
181  PtrRecord.Flags.S.Section = DnsSectionAnswer;
182  PtrRecord.Flags.S.CharSet = DnsCharSetUnicode;
183  PtrRecord.dwTtl = 86400;
184 
185  PtrRecord.Data.PTR.pNameHost = pszHostName;
186 
187  DnsIntCacheAddEntry(&AAAARecord, TRUE);
188  DnsIntCacheAddEntry(&PtrRecord, TRUE);
189 }
190 
191 
192 static
193 FILE *
195 {
196  PWSTR ExpandedPath;
198  HKEY DatabaseKey;
199  DWORD RegSize = 0;
200  size_t StringLength;
201  FILE *pHostsFile;
202  DWORD dwError;
203 
204  ExpandedPath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
205  if (ExpandedPath == NULL)
206  return NULL;
207 
208  /* Open the database path key */
210  L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
211  0,
212  KEY_READ,
213  &DatabaseKey);
214  if (dwError == ERROR_SUCCESS)
215  {
216  /* Read the actual path */
217  RegQueryValueExW(DatabaseKey,
218  L"DatabasePath",
219  NULL,
220  NULL,
221  NULL,
222  &RegSize);
223 
224  DatabasePath = HeapAlloc(GetProcessHeap(), 0, RegSize);
225  if (DatabasePath == NULL)
226  {
227  HeapFree(GetProcessHeap(), 0, ExpandedPath);
228  RegCloseKey(DatabaseKey);
229  return NULL;
230  }
231 
232  /* Read the actual path */
233  dwError = RegQueryValueExW(DatabaseKey,
234  L"DatabasePath",
235  NULL,
236  NULL,
238  &RegSize);
239 
240  /* Close the key */
241  RegCloseKey(DatabaseKey);
242 
243  if (dwError != ERROR_SUCCESS)
244  {
246  HeapFree(GetProcessHeap(), 0, ExpandedPath);
247  return NULL;
248  }
249 
250  /* Expand the name */
252 
254  }
255  else
256  {
257  /* Use defalt path */
258  GetSystemDirectoryW(ExpandedPath, MAX_PATH);
259 
260  StringCchLengthW(ExpandedPath, MAX_PATH, &StringLength);
261  if (ExpandedPath[StringLength - 1] != L'\\')
262  {
263  /* It isn't, so add it ourselves */
264  StringCchCatW(ExpandedPath, MAX_PATH, L"\\");
265  }
266 
267  StringCchCatW(ExpandedPath, MAX_PATH, L"drivers\\etc\\");
268  }
269 
270  /* Make sure that the path is backslash-terminated */
271  StringCchLengthW(ExpandedPath, MAX_PATH, &StringLength);
272  if (ExpandedPath[StringLength - 1] != L'\\')
273  {
274  /* It isn't, so add it ourselves */
275  StringCchCatW(ExpandedPath, MAX_PATH, L"\\");
276  }
277 
278  /* Add the database name */
279  StringCchCatW(ExpandedPath, MAX_PATH, L"hosts");
280 
281  /* Open the hosts file */
282  pHostsFile = _wfopen(ExpandedPath, L"r");
283 
284  HeapFree(GetProcessHeap(), 0, ExpandedPath);
285 
286  return pHostsFile;
287 }
288 
289 
290 BOOL
292 {
293  CHAR szLineBuffer[512];
294  FILE *pHostFile = NULL;
295  CHAR *Ptr, *NameStart, *NameEnd, *AddressStart, *AddressEnd;
296  struct in_addr Ipv4Address;
297  struct in6_addr Ipv6Address;
298  PWSTR pszHostName;
299 
300  pHostFile = OpenHostsFile();
301  if (pHostFile == NULL)
302  return FALSE;
303 
304  for (;;)
305  {
306  /* Read a line */
307  if (fgets(szLineBuffer, sizeof(szLineBuffer), pHostFile) == NULL)
308  break;
309 
310  NameStart = NameEnd = NULL;
311  AddressStart = AddressEnd = NULL;
312 
313  /* Search for the start of the ip address */
314  Ptr = szLineBuffer;
315  for (;;)
316  {
317  if (*Ptr == 0 || *Ptr == '#')
318  break;
319 
320  if (!isspace(*Ptr))
321  {
322  AddressStart = Ptr;
323  Ptr = Ptr + 1;
324  break;
325  }
326 
327  Ptr = Ptr + 1;
328  }
329 
330  /* Search for the end of the ip address */
331  for (;;)
332  {
333  if (*Ptr == 0 || *Ptr == '#')
334  break;
335 
336  if (isspace(*Ptr))
337  {
338  AddressEnd = Ptr;
339  Ptr = Ptr + 1;
340  break;
341  }
342 
343  Ptr = Ptr + 1;
344  }
345 
346  /* Search for the start of the name */
347  for (;;)
348  {
349  if (*Ptr == 0 || *Ptr == '#')
350  break;
351 
352  if (!isspace(*Ptr))
353  {
354  NameStart = Ptr;
355  Ptr = Ptr + 1;
356  break;
357  }
358 
359  Ptr = Ptr + 1;
360  }
361 
362  /* Search for the end of the name */
363  for (;;)
364  {
365  if (*Ptr == 0 || *Ptr == '#')
366  break;
367 
368  if (isspace(*Ptr))
369  {
370  NameEnd = Ptr;
371  break;
372  }
373 
374  Ptr = Ptr + 1;
375  }
376 
377  if (AddressStart == NULL || AddressEnd == NULL ||
378  NameStart == NULL || NameEnd == NULL)
379  continue;
380 
381  *AddressEnd = 0;
382  *NameEnd = 0;
383 
384  DPRINT("%s ==> %s\n", NameStart, AddressStart);
385 
386  if (ParseIpv4Address(AddressStart, &Ipv4Address))
387  {
388  DPRINT("IPv4: %s\n", AddressStart);
389 
390  pszHostName = AnsiToUnicode(NameStart);
391  if (pszHostName != NULL)
392  {
393  AddIpv4HostEntries(pszHostName, &Ipv4Address);
394  HeapFree(GetProcessHeap(), 0, pszHostName);
395  }
396  }
397  else if (ParseIpv6Address(AddressStart, &Ipv6Address))
398  {
399  DPRINT("IPv6: %s\n", AddressStart);
400 
401  pszHostName = AnsiToUnicode(NameStart);
402  if (pszHostName != NULL)
403  {
404  AddIpv6HostEntries(pszHostName, &Ipv6Address);
405  HeapFree(GetProcessHeap(), 0, pszHostName);
406  }
407  }
408  }
409 
410  fclose(pHostFile);
411 
412  return TRUE;
413 }
414 
415 /* EOF */
DNS_A_DATA A
Definition: windns.h:609
DNS_PTR_DATAW PTR
Definition: windns.h:611
#define isspace(c)
Definition: acclib.h:69
NTSYSAPI NTSTATUS NTAPI RtlIpv4StringToAddressA(_In_ PCSTR String, _In_ BOOLEAN Strict, _Out_ PCSTR *Terminator, _Out_ struct in_addr *Addr)
Definition: network.c:338
struct in6_addr IN6_ADDR
#define TRUE
Definition: types.h:120
DWORD Section
Definition: windns.h:238
UCHAR Byte[16]
Definition: in6addr.h:5
#define ERROR_SUCCESS
Definition: deptool.c:10
_Check_return_ _CRTIMP FILE *__cdecl _wfopen(_In_z_ const wchar_t *_Filename, _In_z_ const wchar_t *_Mode)
#define KEY_READ
Definition: nt_native.h:1023
#define DNS_TYPE_AAAA
Definition: windns.h:68
#define DNS_TYPE_A
Definition: windns.h:41
uint16_t * PWSTR
Definition: typedefs.h:55
#define CP_ACP
Definition: compat.h:99
char CHAR
Definition: xmlstorage.h:175
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
static BOOL ParseIpv6Address(_In_ LPCSTR AddressString, _Out_ PIN6_ADDR pAddress)
Definition: hostsfile.c:76
LONG NTSTATUS
Definition: precomp.h:26
#define ZeroMemory
Definition: winbase.h:1648
struct in_addr::@1019::@1020 S_un_b
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
static FILE * OpenHostsFile(VOID)
Definition: hostsfile.c:194
WORD wDataLength
Definition: windns.h:601
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static BOOL ParseIpv4Address(_In_ PCSTR AddressString, _Out_ PIN_ADDR pAddress)
Definition: hostsfile.c:56
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
DNS_AAAA_DATA AAAA
Definition: windns.h:617
smooth NULL
Definition: ftsmooth.c:416
#define _Out_
Definition: no_sal2.h:323
void DPRINT(...)
Definition: polytest.cpp:61
LPWSTR pNameHost
Definition: windns.h:319
const char * LPCSTR
Definition: xmlstorage.h:183
IP4_ADDRESS IpAddress
Definition: windns.h:246
static WCHAR szHexChar[]
Definition: hostsfile.c:18
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
BOOL ReadHostsFile(VOID)
Definition: hostsfile.c:291
#define GetProcessHeap()
Definition: compat.h:404
static VOID AddIpv4HostEntries(PWSTR pszHostName, PIN_ADDR pAddress)
Definition: hostsfile.c:95
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define DNS_TYPE_PTR
Definition: windns.h:52
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Definition: tcpip.h:125
#define MAX_PATH
Definition: compat.h:26
#define swprintf(buf, format,...)
Definition: sprintf.c:56
union in6_addr::@2915 u
#define CopyMemory
Definition: winbase.h:1646
union _DnsRecordW::@3216 Flags
unsigned long DWORD
Definition: ntddk_ex.h:95
static const WCHAR L[]
Definition: oid.c:1250
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
union _DnsRecordW::@3217 Data
PWSTR DatabasePath
Definition: database.c:31
Status
Definition: gdiplustypes.h:24
WORD wType
Definition: windns.h:600
u_long S_addr
Definition: tcpip.h:131
#define _In_
Definition: no_sal2.h:204
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
static VOID AddIpv6HostEntries(PWSTR pszHostName, PIN6_ADDR pAddress)
Definition: hostsfile.c:140
static PWSTR AnsiToUnicode(PSTR NarrowString)
Definition: hostsfile.c:22
signed char * PSTR
Definition: retypes.h:7
#define DNS_PTR_DATA
Definition: windns.h:923
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2312
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
STRSAFEAPI StringCchLengthW(STRSAFE_LPCWSTR psz, size_t cchMax, size_t *pcchLength)
Definition: strsafe.h:842
#define MultiByteToWideChar
Definition: compat.h:100
DNS_IP6_ADDRESS Ip6Address
Definition: windns.h:250
DNS_RECORD_FLAGS S
Definition: windns.h:604
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
VOID DnsIntCacheAddEntry(_In_ PDNS_RECORDW Record, _In_ BOOL bHostsFileEntry)
Definition: cache.c:188
const char * PCSTR
Definition: typedefs.h:52
union in_addr::@1019 S_un
DWORD dwTtl
Definition: windns.h:606
NTSYSAPI NTSTATUS NTAPI RtlIpv6StringToAddressA(_In_ PCSTR String, _Out_ PCSTR *Terminator, _Out_ struct in6_addr *Addr)
Definition: network.c:745
int k
Definition: mpi.c:3369
#define HeapFree(x, y, z)
Definition: compat.h:403
DWORD CharSet
Definition: windns.h:240
LPWSTR pName
Definition: windns.h:599
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12