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 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 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 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 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 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 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 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 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 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