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