xref: /reactos/base/services/dnsrslvr/cache.c (revision 9393fc32)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS system libraries
4  * FILE:        base/services/dnsrslvr/cache.c
5  * PURPOSE:     DNS cache functions
6  * PROGRAMMER:  Peter Hater
7  */
8 
9 #include "precomp.h"
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 static RESOLVER_CACHE DnsCache;
15 static BOOL DnsCacheInitialized = FALSE;
16 
17 #define DnsCacheLock()          do { EnterCriticalSection(&DnsCache.Lock); } while (0)
18 #define DnsCacheUnlock()        do { LeaveCriticalSection(&DnsCache.Lock); } while (0)
19 
20 VOID
DnsIntCacheInitialize(VOID)21 DnsIntCacheInitialize(VOID)
22 {
23     DPRINT("DnsIntCacheInitialize()\n");
24 
25     /* Check if we're initialized */
26     if (DnsCacheInitialized)
27         return;
28 
29     /* Initialize the cache lock and namespace list */
30     InitializeCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock);
31     InitializeListHead(&DnsCache.RecordList);
32     DnsCacheInitialized = TRUE;
33 }
34 
35 VOID
DnsIntCacheFree(VOID)36 DnsIntCacheFree(VOID)
37 {
38     DPRINT("DnsIntCacheFree()\n");
39 
40     /* Check if we're initialized */
41     if (!DnsCacheInitialized)
42         return;
43 
44     if (!DnsCache.RecordList.Flink)
45         return;
46 
47     DnsIntCacheFlush(CACHE_FLUSH_ALL);
48 
49     DeleteCriticalSection(&DnsCache.Lock);
50     DnsCacheInitialized = FALSE;
51 }
52 
53 VOID
DnsIntCacheRemoveEntryItem(PRESOLVER_CACHE_ENTRY CacheEntry)54 DnsIntCacheRemoveEntryItem(PRESOLVER_CACHE_ENTRY CacheEntry)
55 {
56     DPRINT("DnsIntCacheRemoveEntryItem(%p)\n", CacheEntry);
57 
58     /* Remove the entry from the list */
59     RemoveEntryList(&CacheEntry->CacheLink);
60 
61     /* Free record */
62     DnsRecordListFree(CacheEntry->Record, DnsFreeRecordList);
63 
64     /* Delete us */
65     HeapFree(GetProcessHeap(), 0, CacheEntry);
66 }
67 
68 DNS_STATUS
DnsIntCacheFlush(_In_ ULONG ulFlags)69 DnsIntCacheFlush(
70     _In_ ULONG ulFlags)
71 {
72     PLIST_ENTRY Entry, NextEntry;
73     PRESOLVER_CACHE_ENTRY CacheEntry;
74 
75     DPRINT("DnsIntCacheFlush(%lu)\n", ulFlags);
76 
77     /* Lock the cache */
78     DnsCacheLock();
79 
80     /* Loop every entry */
81     Entry = DnsCache.RecordList.Flink;
82     while (Entry != &DnsCache.RecordList)
83     {
84         NextEntry = Entry->Flink;
85 
86         /* Get this entry */
87         CacheEntry = CONTAINING_RECORD(Entry, RESOLVER_CACHE_ENTRY, CacheLink);
88 
89         /* Remove it from list */
90         if (((ulFlags & CACHE_FLUSH_HOSTS_FILE_ENTRIES) && (CacheEntry->bHostsFileEntry != FALSE)) ||
91             ((ulFlags & CACHE_FLUSH_NON_HOSTS_FILE_ENTRIES) && (CacheEntry->bHostsFileEntry == FALSE)))
92             DnsIntCacheRemoveEntryItem(CacheEntry);
93 
94         /* Move to the next entry */
95         Entry = NextEntry;
96     }
97 
98     /* Unlock the cache */
99     DnsCacheUnlock();
100 
101     return ERROR_SUCCESS;
102 }
103 
104 
105 DNS_STATUS
DnsIntFlushCacheEntry(_In_ LPCWSTR pszName,_In_ WORD wType)106 DnsIntFlushCacheEntry(
107     _In_ LPCWSTR pszName,
108     _In_ WORD wType)
109 {
110     PLIST_ENTRY Entry, NextEntry;
111     PRESOLVER_CACHE_ENTRY CacheEntry;
112 
113     DPRINT("DnsIntFlushCacheEntry(%S %x)\n", pszName, wType);
114 
115     /* Lock the cache */
116     DnsCacheLock();
117 
118     /* Loop every entry */
119     Entry = DnsCache.RecordList.Flink;
120     while (Entry != &DnsCache.RecordList)
121     {
122         NextEntry = Entry->Flink;
123 
124         /* Get this entry */
125         CacheEntry = CONTAINING_RECORD(Entry, RESOLVER_CACHE_ENTRY, CacheLink);
126 
127         /* Remove it from the list */
128         if ((_wcsicmp(CacheEntry->Record->pName, pszName) == 0) &&
129             (CacheEntry->bHostsFileEntry == FALSE))
130         {
131             if ((wType == DNS_TYPE_ANY) ||
132                 (CacheEntry->Record->wType == wType))
133             {
134                 DnsIntCacheRemoveEntryItem(CacheEntry);
135             }
136         }
137 
138         /* Move to the next entry */
139         Entry = NextEntry;
140     }
141 
142     /* Unlock the cache */
143     DnsCacheUnlock();
144 
145     return ERROR_SUCCESS;
146 }
147 
148 
149 DNS_STATUS
DnsIntCacheGetEntryByName(LPCWSTR Name,WORD wType,DWORD dwFlags,PDNS_RECORDW * Record)150 DnsIntCacheGetEntryByName(
151     LPCWSTR Name,
152     WORD wType,
153     DWORD dwFlags,
154     PDNS_RECORDW *Record)
155 {
156     DNS_STATUS Status = DNS_INFO_NO_RECORDS;
157     PRESOLVER_CACHE_ENTRY CacheEntry;
158     PLIST_ENTRY NextEntry;
159 
160     DPRINT("DnsIntCacheGetEntryByName(%S %hu 0x%lx %p)\n",
161            Name, wType, dwFlags, Record);
162 
163     /* Assume failure */
164     *Record = NULL;
165 
166     /* Lock the cache */
167     DnsCacheLock();
168 
169     /* Match the Id with all the entries in the List */
170     NextEntry = DnsCache.RecordList.Flink;
171     while (NextEntry != &DnsCache.RecordList)
172     {
173         /* Get the Current Entry */
174         CacheEntry = CONTAINING_RECORD(NextEntry, RESOLVER_CACHE_ENTRY, CacheLink);
175 
176         /* Check if this is the Catalog Entry ID we want */
177         if (_wcsicmp(CacheEntry->Record->pName, Name) == 0)
178         {
179             /* Copy the entry and return it */
180             *Record = DnsRecordSetCopyEx(CacheEntry->Record, DnsCharSetUnicode, DnsCharSetUnicode);
181             Status = ERROR_SUCCESS;
182             break;
183         }
184 
185         NextEntry = NextEntry->Flink;
186     }
187 
188     /* Release the cache */
189     DnsCacheUnlock();
190 
191     return Status;
192 }
193 
194 BOOL
DnsIntCacheRemoveEntryByName(LPCWSTR Name)195 DnsIntCacheRemoveEntryByName(LPCWSTR Name)
196 {
197     BOOL Ret = FALSE;
198     PRESOLVER_CACHE_ENTRY CacheEntry;
199     PLIST_ENTRY NextEntry;
200 
201     DPRINT("DnsIntCacheRemoveEntryByName(%S)\n", Name);
202 
203     /* Lock the cache */
204     DnsCacheLock();
205 
206     /* Match the Id with all the entries in the List */
207     NextEntry = DnsCache.RecordList.Flink;
208     while (NextEntry != &DnsCache.RecordList)
209     {
210         /* Get the Current Entry */
211         CacheEntry = CONTAINING_RECORD(NextEntry, RESOLVER_CACHE_ENTRY, CacheLink);
212 
213         /* Check if this is the Catalog Entry ID we want */
214         if (_wcsicmp(CacheEntry->Record->pName, Name) == 0)
215         {
216             /* Remove the entry */
217             DnsIntCacheRemoveEntryItem(CacheEntry);
218             Ret = TRUE;
219             break;
220         }
221 
222         NextEntry = NextEntry->Flink;
223     }
224 
225     /* Release the cache */
226     DnsCacheUnlock();
227 
228     /* Return */
229     return Ret;
230 }
231 
232 VOID
DnsIntCacheAddEntry(_In_ PDNS_RECORDW Record,_In_ BOOL bHostsFileEntry)233 DnsIntCacheAddEntry(
234     _In_ PDNS_RECORDW Record,
235     _In_ BOOL bHostsFileEntry)
236 {
237     PRESOLVER_CACHE_ENTRY Entry;
238 
239     DPRINT("DnsIntCacheAddEntry(%p %u)\n",
240            Record, bHostsFileEntry);
241 
242     DPRINT("Name: %S\n", Record->pName);
243     DPRINT("TTL: %lu\n", Record->dwTtl);
244 
245     /* Lock the cache */
246     DnsCacheLock();
247 
248     /* Match the Id with all the entries in the List */
249     Entry = (PRESOLVER_CACHE_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(*Entry));
250     if (!Entry)
251         return;
252 
253     Entry->bHostsFileEntry = bHostsFileEntry;
254     Entry->Record = DnsRecordSetCopyEx(Record, DnsCharSetUnicode, DnsCharSetUnicode);
255 
256     /* Insert it to our List */
257     InsertTailList(&DnsCache.RecordList, &Entry->CacheLink);
258 
259     /* Release the cache */
260     DnsCacheUnlock();
261 }
262 
263 DNS_STATUS
DnsIntCacheGetEntries(_Out_ DNS_CACHE_ENTRY ** ppCacheEntries)264 DnsIntCacheGetEntries(
265     _Out_ DNS_CACHE_ENTRY **ppCacheEntries)
266 {
267     PRESOLVER_CACHE_ENTRY CacheEntry;
268     PLIST_ENTRY NextEntry;
269     PDNS_CACHE_ENTRY pLastEntry = NULL, pNewEntry;
270 
271     /* Lock the cache */
272     DnsCacheLock();
273 
274     *ppCacheEntries = NULL;
275 
276     NextEntry = DnsCache.RecordList.Flink;
277     while (NextEntry != &DnsCache.RecordList)
278     {
279         /* Get the Current Entry */
280         CacheEntry = CONTAINING_RECORD(NextEntry, RESOLVER_CACHE_ENTRY, CacheLink);
281 
282         DPRINT("1 %S %lu\n", CacheEntry->Record->pName, CacheEntry->Record->wType);
283         if (CacheEntry->Record->pNext)
284         {
285             DPRINT("2 %S %lu\n", CacheEntry->Record->pNext->pName, CacheEntry->Record->pNext->wType);
286         }
287 
288         pNewEntry = midl_user_allocate(sizeof(DNS_CACHE_ENTRY));
289         if (pNewEntry == NULL)
290         {
291             return ERROR_OUTOFMEMORY;
292         }
293 
294         pNewEntry->pszName = midl_user_allocate((wcslen(CacheEntry->Record->pName) + 1) * sizeof(WCHAR));
295         if (pNewEntry->pszName == NULL)
296         {
297             return ERROR_OUTOFMEMORY;
298         }
299 
300         wcscpy(pNewEntry->pszName, CacheEntry->Record->pName);
301         pNewEntry->wType1 = CacheEntry->Record->wType;
302         pNewEntry->wType2 = 0;
303         pNewEntry->wFlags = 0;
304 
305         if (pLastEntry == NULL)
306             *ppCacheEntries = pNewEntry;
307         else
308             pLastEntry->pNext = pNewEntry;
309         pLastEntry = pNewEntry;
310 
311         NextEntry = NextEntry->Flink;
312     }
313 
314     /* Release the cache */
315     DnsCacheUnlock();
316 
317     return ERROR_SUCCESS;
318 }
319