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 DNS_STATUS 105 DnsIntCacheGetEntryByName( 106 LPCWSTR Name, 107 WORD wType, 108 DWORD dwFlags, 109 PDNS_RECORDW *Record) 110 { 111 DNS_STATUS Status = DNS_INFO_NO_RECORDS; 112 PRESOLVER_CACHE_ENTRY CacheEntry; 113 PLIST_ENTRY NextEntry; 114 115 DPRINT("DnsIntCacheGetEntryByName(%S %hu 0x%lx %p)\n", 116 Name, wType, dwFlags, Record); 117 118 /* Assume failure */ 119 *Record = NULL; 120 121 /* Lock the cache */ 122 DnsCacheLock(); 123 124 /* Match the Id with all the entries in the List */ 125 NextEntry = DnsCache.RecordList.Flink; 126 while (NextEntry != &DnsCache.RecordList) 127 { 128 /* Get the Current Entry */ 129 CacheEntry = CONTAINING_RECORD(NextEntry, RESOLVER_CACHE_ENTRY, CacheLink); 130 131 /* Check if this is the Catalog Entry ID we want */ 132 if (_wcsicmp(CacheEntry->Record->pName, Name) == 0) 133 { 134 /* Copy the entry and return it */ 135 *Record = DnsRecordSetCopyEx(CacheEntry->Record, DnsCharSetUnicode, DnsCharSetUnicode); 136 Status = ERROR_SUCCESS; 137 break; 138 } 139 140 NextEntry = NextEntry->Flink; 141 } 142 143 /* Release the cache */ 144 DnsCacheUnlock(); 145 146 return Status; 147 } 148 149 BOOL 150 DnsIntCacheRemoveEntryByName(LPCWSTR Name) 151 { 152 BOOL Ret = FALSE; 153 PRESOLVER_CACHE_ENTRY CacheEntry; 154 PLIST_ENTRY NextEntry; 155 156 DPRINT("DnsIntCacheRemoveEntryByName(%S)\n", Name); 157 158 /* Lock the cache */ 159 DnsCacheLock(); 160 161 /* Match the Id with all the entries in the List */ 162 NextEntry = DnsCache.RecordList.Flink; 163 while (NextEntry != &DnsCache.RecordList) 164 { 165 /* Get the Current Entry */ 166 CacheEntry = CONTAINING_RECORD(NextEntry, RESOLVER_CACHE_ENTRY, CacheLink); 167 168 /* Check if this is the Catalog Entry ID we want */ 169 if (_wcsicmp(CacheEntry->Record->pName, Name) == 0) 170 { 171 /* Remove the entry */ 172 DnsIntCacheRemoveEntryItem(CacheEntry); 173 Ret = TRUE; 174 break; 175 } 176 177 NextEntry = NextEntry->Flink; 178 } 179 180 /* Release the cache */ 181 DnsCacheUnlock(); 182 183 /* Return */ 184 return Ret; 185 } 186 187 VOID 188 DnsIntCacheAddEntry( 189 _In_ PDNS_RECORDW Record, 190 _In_ BOOL bHostsFileEntry) 191 { 192 PRESOLVER_CACHE_ENTRY Entry; 193 194 DPRINT("DnsIntCacheAddEntry(%p %u)\n", 195 Record, bHostsFileEntry); 196 197 DPRINT("Name: %S\n", Record->pName); 198 DPRINT("TTL: %lu\n", Record->dwTtl); 199 200 /* Lock the cache */ 201 DnsCacheLock(); 202 203 /* Match the Id with all the entries in the List */ 204 Entry = (PRESOLVER_CACHE_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(*Entry)); 205 if (!Entry) 206 return; 207 208 Entry->bHostsFileEntry = bHostsFileEntry; 209 Entry->Record = DnsRecordSetCopyEx(Record, DnsCharSetUnicode, DnsCharSetUnicode); 210 211 /* Insert it to our List */ 212 InsertTailList(&DnsCache.RecordList, &Entry->CacheLink); 213 214 /* Release the cache */ 215 DnsCacheUnlock(); 216 } 217 218 DNS_STATUS 219 DnsIntCacheGetEntries( 220 _Out_ DNS_CACHE_ENTRY **ppCacheEntries) 221 { 222 PRESOLVER_CACHE_ENTRY CacheEntry; 223 PLIST_ENTRY NextEntry; 224 PDNS_CACHE_ENTRY pLastEntry = NULL, pNewEntry; 225 226 /* Lock the cache */ 227 DnsCacheLock(); 228 229 *ppCacheEntries = NULL; 230 231 NextEntry = DnsCache.RecordList.Flink; 232 while (NextEntry != &DnsCache.RecordList) 233 { 234 /* Get the Current Entry */ 235 CacheEntry = CONTAINING_RECORD(NextEntry, RESOLVER_CACHE_ENTRY, CacheLink); 236 237 DPRINT("1 %S %lu\n", CacheEntry->Record->pName, CacheEntry->Record->wType); 238 if (CacheEntry->Record->pNext) 239 { 240 DPRINT("2 %S %lu\n", CacheEntry->Record->pNext->pName, CacheEntry->Record->pNext->wType); 241 } 242 243 pNewEntry = midl_user_allocate(sizeof(DNS_CACHE_ENTRY)); 244 if (pNewEntry == NULL) 245 { 246 return ERROR_OUTOFMEMORY; 247 } 248 249 pNewEntry->pszName = midl_user_allocate((wcslen(CacheEntry->Record->pName) + 1) * sizeof(WCHAR)); 250 if (pNewEntry->pszName == NULL) 251 { 252 return ERROR_OUTOFMEMORY; 253 } 254 255 wcscpy(pNewEntry->pszName, CacheEntry->Record->pName); 256 pNewEntry->wType1 = CacheEntry->Record->wType; 257 pNewEntry->wType2 = 0; 258 pNewEntry->wFlags = 0; 259 260 if (pLastEntry == NULL) 261 *ppCacheEntries = pNewEntry; 262 else 263 pLastEntry->pNext = pNewEntry; 264 pLastEntry = pNewEntry; 265 266 NextEntry = NextEntry->Flink; 267 } 268 269 /* Release the cache */ 270 DnsCacheUnlock(); 271 272 return ERROR_SUCCESS; 273 } 274